void addFullInstrumentToWorkspace(MatrixWorkspace &workspace,
                                  bool includeMonitors, bool startYNegative,
                                  const std::string &instrumentName) {
  auto instrument = boost::make_shared<Instrument>(instrumentName);
  instrument->setReferenceFrame(
      boost::make_shared<ReferenceFrame>(Y, Z, Right, ""));
  workspace.setInstrument(instrument);

  const double pixelRadius(0.05);
  Object_sptr pixelShape = ComponentCreationHelper::createCappedCylinder(
      pixelRadius, 0.02, V3D(0.0, 0.0, 0.0), V3D(0., 1.0, 0.), "tube");

  const double detZPos(5.0);
  // Careful! Do not use size_t or auto, the unisgned will break the -=2 below.
  int ndets = static_cast<int>(workspace.getNumberHistograms());
  if (includeMonitors)
    ndets -= 2;
  for (int i = 0; i < ndets; ++i) {
    std::ostringstream lexer;
    lexer << "pixel-" << i << ")";
    Detector *physicalPixel =
        new Detector(lexer.str(), workspace.getAxis(1)->spectraNo(i),
                     pixelShape, instrument.get());
    int ycount(i);
    if (startYNegative)
      ycount -= 1;
    const double ypos = ycount * 2.0 * pixelRadius;
    physicalPixel->setPos(0.0, ypos, detZPos);
    instrument->add(physicalPixel);
    instrument->markAsDetector(physicalPixel);
    workspace.getSpectrum(i).setDetectorID(physicalPixel->getID());
  }

  // Monitors last
  if (includeMonitors) // These occupy the last 2 spectra
  {
    Detector *monitor1 =
        new Detector("mon1", workspace.getAxis(1)->spectraNo(ndets),
                     Object_sptr(), instrument.get());
    monitor1->setPos(0.0, 0.0, -9.0);
    instrument->add(monitor1);
    instrument->markAsMonitor(monitor1);
    workspace.getSpectrum(ndets).setDetectorID(ndets + 1);

    Detector *monitor2 =
        new Detector("mon2", workspace.getAxis(1)->spectraNo(ndets) + 1,
                     Object_sptr(), instrument.get());
    monitor2->setPos(0.0, 0.0, -2.0);
    instrument->add(monitor2);
    instrument->markAsMonitor(monitor2);
    workspace.getSpectrum(ndets + 1).setDetectorID(ndets + 2);
  }

  // Define a source and sample position
  // Define a source component
  ObjComponent *source = new ObjComponent(
      "moderator",
      ComponentCreationHelper::createSphere(0.1, V3D(0, 0, 0), "1"),
      instrument.get());
  source->setPos(V3D(0.0, 0.0, -20.0));
  instrument->add(source);
  instrument->markAsSource(source);

  // Define a sample as a simple sphere
  ObjComponent *sample = new ObjComponent(
      "samplePos",
      ComponentCreationHelper::createSphere(0.1, V3D(0, 0, 0), "1"),
      instrument.get());
  instrument->setPos(0.0, 0.0, 0.0);
  instrument->add(sample);
  instrument->markAsSamplePos(sample);
  // chopper position
  Component *chop_pos = new Component("chopper-position",
                                      Kernel::V3D(0, 0, -10), instrument.get());
  instrument->add(chop_pos);
}
/**
 * Create an test instrument with n panels of rectangular detectors,
 *pixels*pixels in size,
 * a source and spherical sample shape.
 *
 * Banks' lower-left corner is at position (0,0,5*banknum) and they go up to
 *(pixels*0.008, pixels*0.008, Z)
 * Pixels are 4 mm wide.
 *
 * @param progress :: progress indicator
 * @param num_banks :: number of rectangular banks to create
 * @param pixels :: number of pixels in each direction.
 * @param pixelSpacing :: padding between pixels
 * @param bankDistanceFromSample :: Distance of first bank from sample (defaults
 *to 5.0m)
 * @param sourceSampleDistance :: The distance from the source to the sample
 * @returns A shared pointer to the generated instrument
 */
Instrument_sptr CreateSampleWorkspace::createTestInstrumentRectangular(
    API::Progress &progress, int num_banks, int pixels, double pixelSpacing,
    const double bankDistanceFromSample, const double sourceSampleDistance) {
  boost::shared_ptr<Instrument> testInst(new Instrument("basic_rect"));
  // The instrument is going to be set up with z as the beam axis and y as the
  // vertical axis.
  testInst->setReferenceFrame(
      boost::shared_ptr<ReferenceFrame>(new ReferenceFrame(Y, Z, Left, "")));

  const double cylRadius(pixelSpacing / 2);
  const double cylHeight(0.0002);
  // One object
  Object_sptr pixelShape = createCappedCylinder(
      cylRadius, cylHeight, V3D(0.0, -cylHeight / 2.0, 0.0), V3D(0., 1.0, 0.),
      "pixel-shape");

  for (int banknum = 1; banknum <= num_banks; banknum++) {
    // Make a new bank
    std::ostringstream bankname;
    bankname << "bank" << banknum;

    RectangularDetector *bank = new RectangularDetector(bankname.str());
    bank->initialize(pixelShape, pixels, 0.0, pixelSpacing, pixels, 0.0,
                     pixelSpacing, banknum * pixels * pixels, true, pixels);

    // Mark them all as detectors
    for (int x = 0; x < pixels; x++)
      for (int y = 0; y < pixels; y++) {
        boost::shared_ptr<Detector> detector = bank->getAtXY(x, y);
        if (detector)
          // Mark it as a detector (add to the instrument cache)
          testInst->markAsDetector(detector.get());
      }

    testInst->add(bank);
    // Set the bank along the z-axis of the instrument. (beam direction).
    bank->setPos(V3D(0.0, 0.0, bankDistanceFromSample * banknum));

    progress.report();
  }

  // Define a source component
  ObjComponent *source =
      new ObjComponent("moderator", Object_sptr(new Object), testInst.get());
  source->setPos(V3D(0.0, 0.0, -sourceSampleDistance));
  testInst->add(source);
  testInst->markAsSource(source);

  // Add chopper
  ObjComponent *chopper = new ObjComponent(
      "chopper-position", Object_sptr(new Object), testInst.get());
  chopper->setPos(V3D(0.0, 0.0, -0.25 * sourceSampleDistance));
  testInst->add(chopper);

  // Define a sample as a simple sphere
  Object_sptr sampleSphere =
      createSphere(0.001, V3D(0.0, 0.0, 0.0), "sample-shape");
  ObjComponent *sample =
      new ObjComponent("sample", sampleSphere, testInst.get());
  testInst->setPos(0.0, 0.0, 0.0);
  testInst->add(sample);
  testInst->markAsSamplePos(sample);

  return testInst;
}