Skip to content
Snippets Groups Projects
MatrixWorkspaceTest.h 53.1 KiB
Newer Older
    size_t stop = 8;
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width), std::runtime_error);
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width), std::runtime_error);
    TS_ASSERT_THROWS_NOTHING(ws.getImageY(start, stop, width));
  void test_getImage_wrong_stop() {
    ws.init(9, 2, 1);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    size_t stop = 18;
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width), std::runtime_error);
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width), std::runtime_error);
    TS_ASSERT_THROWS_NOTHING(ws.getImageY(start, stop, width));
  void test_getImage_empty_set() {
    ws.init(9, 2, 1);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    size_t stop = 0;
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width), std::runtime_error);
    TS_ASSERT_THROWS_NOTHING(ws.getImageY(start, stop, width));
  void test_getImage_non_rectangular() {
    ws.init(9, 2, 1);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    size_t stop = 7;
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width), std::runtime_error);
  void test_getImage_wrong_indexStart() {
    ws.init(9, 2, 1);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    const size_t start = 0;
    const size_t stop = 8;
    const size_t width = 3;
    double startX = 3;
    double endX = 4;
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width, startX, endX),
                     std::runtime_error);
    wsh.init(9, 1, 1);
    TS_ASSERT_THROWS(wsh.getImageY(start, stop, width, startX, endX),
                     std::runtime_error);
  void test_getImage_wrong_indexEnd() {
    ws.init(9, 2, 1);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    const size_t start = 0;
    const size_t stop = 8;
    const size_t width = 3;
    double startX = 1.0;
    double endX = 0.0;
    TS_ASSERT_THROWS(ws.getImageY(start, stop, width, startX, endX),
                     std::runtime_error);
    wsh.init(9, 2, 2);
    auto &X1 = ws.dataX(0);
    X1[0] = 1.0;
    X1[1] = 2.0;
    startX = 1.0;
    endX = 0.0;
    TS_ASSERT_THROWS(wsh.getImageY(start, stop, width, startX, endX),
                     std::runtime_error);
  void test_getImage_single_bin_histo() {
    ws.init(9, 2, 1);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    for (size_t i = 0; i < ws.getNumberHistograms(); ++i) {
      ws.dataY(i)[0] = static_cast<double>(i + 1);
    const size_t stop = 8;
    const size_t width = 3;
    double startX = 0;
    double endX = 3;
    Mantid::API::MantidImage_sptr image;
    TS_ASSERT_THROWS_NOTHING(
        image = ws.getImageY(start, stop, width, startX, endX));
    if (!image)
      return;
    TS_ASSERT_EQUALS(image->size(), 3);
    TS_ASSERT_EQUALS((*image)[0].size(), 3);
    TS_ASSERT_EQUALS((*image)[1].size(), 3);
    TS_ASSERT_EQUALS((*image)[2].size(), 3);

    TS_ASSERT_EQUALS((*image)[0][0], 1);
    TS_ASSERT_EQUALS((*image)[0][1], 2);
    TS_ASSERT_EQUALS((*image)[0][2], 3);
    TS_ASSERT_EQUALS((*image)[1][0], 4);
    TS_ASSERT_EQUALS((*image)[1][1], 5);
    TS_ASSERT_EQUALS((*image)[1][2], 6);
    TS_ASSERT_EQUALS((*image)[2][0], 7);
    TS_ASSERT_EQUALS((*image)[2][1], 8);
    TS_ASSERT_EQUALS((*image)[2][2], 9);
  }

  void test_getImage_single_bin_points() {
    ws.init(9, 1, 1);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    for (size_t i = 0; i < ws.getNumberHistograms(); ++i) {
      ws.dataY(i)[0] = static_cast<double>(i + 1);
    const size_t stop = 8;
    const size_t width = 3;
    double startX = 1;
    double endX = 1;
    Mantid::API::MantidImage_sptr image;
    TS_ASSERT_THROWS_NOTHING(
        image = ws.getImageY(start, stop, width, startX, endX));
    if (!image)
      return;
    TS_ASSERT_EQUALS(image->size(), 3);
    TS_ASSERT_EQUALS((*image)[0].size(), 3);
    TS_ASSERT_EQUALS((*image)[1].size(), 3);
    TS_ASSERT_EQUALS((*image)[2].size(), 3);

    TS_ASSERT_EQUALS((*image)[0][0], 1);
    TS_ASSERT_EQUALS((*image)[0][1], 2);
    TS_ASSERT_EQUALS((*image)[0][2], 3);
    TS_ASSERT_EQUALS((*image)[1][0], 4);
    TS_ASSERT_EQUALS((*image)[1][1], 5);
    TS_ASSERT_EQUALS((*image)[1][2], 6);
    TS_ASSERT_EQUALS((*image)[2][0], 7);
    TS_ASSERT_EQUALS((*image)[2][1], 8);
    TS_ASSERT_EQUALS((*image)[2][2], 9);
  }

  void test_getImage_multi_bin_histo() {
    ws.init(9, 4, 3);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    X[2] = 3.0;
    X[3] = 4.0;
    for (size_t i = 0; i < ws.getNumberHistograms(); ++i) {
      ws.dataY(i)[0] = static_cast<double>(i + 1);
      ws.dataY(i)[1] = static_cast<double>(i + 2);
      ws.dataY(i)[2] = static_cast<double>(i + 3);
    const size_t stop = 8;
    const size_t width = 3;
    Mantid::API::MantidImage_sptr image;
    TS_ASSERT_THROWS_NOTHING(image = ws.getImageY(start, stop, width));
    if (!image)
      return;
    TS_ASSERT_EQUALS(image->size(), 3);
    TS_ASSERT_EQUALS((*image)[0].size(), 3);
    TS_ASSERT_EQUALS((*image)[1].size(), 3);
    TS_ASSERT_EQUALS((*image)[2].size(), 3);

    TS_ASSERT_EQUALS((*image)[0][0], 6);
    TS_ASSERT_EQUALS((*image)[0][1], 9);
    TS_ASSERT_EQUALS((*image)[0][2], 12);
    TS_ASSERT_EQUALS((*image)[1][0], 15);
    TS_ASSERT_EQUALS((*image)[1][1], 18);
    TS_ASSERT_EQUALS((*image)[1][2], 21);
    TS_ASSERT_EQUALS((*image)[2][0], 24);
    TS_ASSERT_EQUALS((*image)[2][1], 27);
    TS_ASSERT_EQUALS((*image)[2][2], 30);
  }

  void test_getImage_multi_bin_points() {
    ws.init(9, 3, 3);
    auto &X = ws.dataX(0);
    X[0] = 1.0;
    X[1] = 2.0;
    X[2] = 3.0;
    for (size_t i = 0; i < ws.getNumberHistograms(); ++i) {
      ws.dataY(i)[0] = static_cast<double>(i + 1);
      ws.dataY(i)[1] = static_cast<double>(i + 2);
      ws.dataY(i)[2] = static_cast<double>(i + 3);
    const size_t stop = 8;
    const size_t width = 3;
    Mantid::API::MantidImage_sptr image;
    TS_ASSERT_THROWS_NOTHING(image = ws.getImageY(start, stop, width));
    if (!image)
      return;
    TS_ASSERT_EQUALS(image->size(), 3);
    TS_ASSERT_EQUALS((*image)[0].size(), 3);
    TS_ASSERT_EQUALS((*image)[1].size(), 3);
    TS_ASSERT_EQUALS((*image)[2].size(), 3);

    TS_ASSERT_EQUALS((*image)[0][0], 6);
    TS_ASSERT_EQUALS((*image)[0][1], 9);
    TS_ASSERT_EQUALS((*image)[0][2], 12);
    TS_ASSERT_EQUALS((*image)[1][0], 15);
    TS_ASSERT_EQUALS((*image)[1][1], 18);
    TS_ASSERT_EQUALS((*image)[1][2], 21);
    TS_ASSERT_EQUALS((*image)[2][0], 24);
    TS_ASSERT_EQUALS((*image)[2][1], 27);
    TS_ASSERT_EQUALS((*image)[2][2], 30);
  }

  void test_setImage_too_large() {
    auto image = createImage(2, 3);
    WorkspaceTester ws;
    ws.init(2, 2, 1);
    TS_ASSERT_THROWS(ws.setImageY(*image), std::runtime_error);
  void test_setImage_not_single_bin() {
    auto image = createImage(2, 3);
    WorkspaceTester ws;
    ws.init(20, 3, 2);
    TS_ASSERT_THROWS(ws.setImageY(*image), std::runtime_error);
  void test_setImageY() {
    auto image = createImage(2, 3);
    WorkspaceTester ws;
    ws.init(6, 2, 1);
    TS_ASSERT_THROWS_NOTHING(ws.setImageY(*image));
    TS_ASSERT_EQUALS(ws.readY(0)[0], 1);
    TS_ASSERT_EQUALS(ws.readY(1)[0], 2);
    TS_ASSERT_EQUALS(ws.readY(2)[0], 3);
    TS_ASSERT_EQUALS(ws.readY(3)[0], 4);
    TS_ASSERT_EQUALS(ws.readY(4)[0], 5);
    TS_ASSERT_EQUALS(ws.readY(5)[0], 6);
  }

  void test_setImageE() {
    auto image = createImage(2, 3);
    WorkspaceTester ws;
    ws.init(6, 2, 1);
    TS_ASSERT_THROWS_NOTHING(ws.setImageE(*image));
    TS_ASSERT_EQUALS(ws.readE(0)[0], 1);
    TS_ASSERT_EQUALS(ws.readE(1)[0], 2);
    TS_ASSERT_EQUALS(ws.readE(2)[0], 3);
    TS_ASSERT_EQUALS(ws.readE(3)[0], 4);
    TS_ASSERT_EQUALS(ws.readE(4)[0], 5);
    TS_ASSERT_EQUALS(ws.readE(5)[0], 6);
  }

  void test_setImageY_start() {
    auto image = createImage(2, 3);
    WorkspaceTester ws;
    ws.init(9, 2, 1);
    TS_ASSERT_THROWS_NOTHING(ws.setImageY(*image, 3));
    TS_ASSERT_EQUALS(ws.readY(3)[0], 1);
    TS_ASSERT_EQUALS(ws.readY(4)[0], 2);
    TS_ASSERT_EQUALS(ws.readY(5)[0], 3);
    TS_ASSERT_EQUALS(ws.readY(6)[0], 4);
    TS_ASSERT_EQUALS(ws.readY(7)[0], 5);
    TS_ASSERT_EQUALS(ws.readY(8)[0], 6);
  }

  void test_setImageE_start() {
    auto image = createImage(2, 3);
    WorkspaceTester ws;
    ws.init(9, 2, 1);
    TS_ASSERT_THROWS_NOTHING(ws.setImageE(*image, 2));
    TS_ASSERT_EQUALS(ws.readE(2)[0], 1);
    TS_ASSERT_EQUALS(ws.readE(3)[0], 2);
    TS_ASSERT_EQUALS(ws.readE(4)[0], 3);
    TS_ASSERT_EQUALS(ws.readE(5)[0], 4);
    TS_ASSERT_EQUALS(ws.readE(6)[0], 5);
    TS_ASSERT_EQUALS(ws.readE(7)[0], 6);
  /**
  * Test declaring an input workspace and retrieving as const_sptr or sptr
  */
  void testGetProperty_const_sptr() {
    const std::string wsName = "InputWorkspace";
Hahn, Steven's avatar
Hahn, Steven committed
    MatrixWorkspace_sptr wsInput = boost::make_shared<WorkspaceTester>();
    PropertyManagerHelper manager;
    manager.declareProperty(wsName, wsInput, Direction::Input);

    // Check property can be obtained as const_sptr or sptr
    MatrixWorkspace_const_sptr wsConst;
    MatrixWorkspace_sptr wsNonConst;
    TS_ASSERT_THROWS_NOTHING(
        wsConst = manager.getValue<MatrixWorkspace_const_sptr>(wsName));
    TS_ASSERT(wsConst != NULL);
    TS_ASSERT_THROWS_NOTHING(
        wsNonConst = manager.getValue<MatrixWorkspace_sptr>(wsName));
    TS_ASSERT(wsNonConst != NULL);
    TS_ASSERT_EQUALS(wsConst, wsNonConst);

    // Check TypedValue can be cast to const_sptr or to sptr
    PropertyManagerHelper::TypedValue val(manager, wsName);
    MatrixWorkspace_const_sptr wsCastConst;
    MatrixWorkspace_sptr wsCastNonConst;
    TS_ASSERT_THROWS_NOTHING(wsCastConst = (MatrixWorkspace_const_sptr)val);
    TS_ASSERT(wsCastConst != NULL);
    TS_ASSERT_THROWS_NOTHING(wsCastNonConst = (MatrixWorkspace_sptr)val);
    TS_ASSERT(wsCastNonConst != NULL);
    TS_ASSERT_EQUALS(wsCastConst, wsCastNonConst);
  }

  void test_x_uncertainty_can_be_set() {
    // Arrange
    WorkspaceTester ws;
    const size_t numspec = 4;
    const size_t j = 3;
    const size_t k = j;
    ws.init(numspec, j, k);

    double values[3] = {10, 11, 17};
    size_t workspaceIndexWithDx[3] = {0, 1, 2};
    Mantid::MantidVec dxSpec0(j, values[0]);
    auto dxSpec1 =
        Kernel::make_cow<Mantid::HistogramData::HistogramDx>(j, values[1]);
    auto dxSpec2 = boost::make_shared<Mantid::HistogramData::HistogramDx>(
        Mantid::MantidVec(j, values[2]));
    // Act
    for (size_t spec = 0; spec < numspec; ++spec) {
      TSM_ASSERT("Should not have any x resolution values", !ws.hasDx(spec));
    }
    ws.dataDx(workspaceIndexWithDx[0]) = dxSpec0;
    ws.setSharedDx(workspaceIndexWithDx[1], dxSpec1);
    ws.setSharedDx(workspaceIndexWithDx[2], dxSpec2);
    auto compareValue =
        [&values](double data, size_t index) { return data == values[index]; };
    for (auto &index : workspaceIndexWithDx) {
      TSM_ASSERT("Should have x resolution values", ws.hasDx(index));
      TSM_ASSERT_EQUALS("Should have a length of 3", ws.dataDx(index).size(),
      auto compareValueForSpecificWorkspaceIndex =
          std::bind(compareValue, std::placeholders::_1, index);
      auto &dataDx = ws.dataDx(index);
      TSM_ASSERT("dataDx should allow access to the spectrum",
                 std::all_of(std::begin(dataDx), std::end(dataDx),
                             compareValueForSpecificWorkspaceIndex));
      auto &readDx = ws.readDx(index);
      TSM_ASSERT("readDx should allow access to the spectrum",
                 std::all_of(std::begin(readDx), std::end(readDx),
                             compareValueForSpecificWorkspaceIndex));
      auto refDx = ws.sharedDx(index);
      TSM_ASSERT("readDx should allow access to the spectrum",
                 std::all_of(std::begin(*refDx), std::end(*refDx),
                             compareValueForSpecificWorkspaceIndex));

    TSM_ASSERT("Should not have any x resolution values", !ws.hasDx(3));
  Mantid::API::MantidImage_sptr createImage(const size_t width,
                                            const size_t height) {
    auto image =
        boost::make_shared<Mantid::API::MantidImage>(height, MantidVec(width));
    double startingValue = 1.0;
    for (auto &row : *image) {
      std::iota(row.begin(), row.end(), startingValue);
      startingValue += static_cast<double>(width);
  /**
   * Create a test workspace. Can be histo or points depending on x/yLength.
   * @param nVectors :: [input] Number of vectors
   * @param xLength :: [input] Length of X vector
   * @param yLength :: [input] Length of Y, E vectors
   * @returns :: workspace
   */
  WorkspaceTester createTestWorkspace(size_t nVectors, size_t xLength,
                                      size_t yLength) {
    WorkspaceTester ws;
    ws.initialize(nVectors, xLength, yLength);
    // X data
    std::vector<double> xData(xLength);
    std::iota(xData.begin(), xData.end(), 0.0);

    // Y data
    const auto yCounts = [&yLength](size_t wi) {
      std::vector<double> v(yLength);
      std::iota(v.begin(), v.end(), static_cast<double>(wi) * 10.0);
      return v;
    };

    // E data
    const auto errors = [&yLength](size_t wi) {
      std::vector<double> v(yLength);
      std::generate(v.begin(), v.end(), [&wi]() {
        return std::sqrt(static_cast<double>(wi) * 10.0);
      });
      return v;
    };

    for (size_t wi = 0; wi < nVectors; ++wi) {
      if (xLength == yLength) {
        ws.setPoints(wi, xData);
      } else if (xLength == yLength + 1) {
        ws.setBinEdges(wi, xData);
      } else {
        throw std::invalid_argument(
            "yLength must either be equal to xLength or xLength - 1");
      }
      ws.setCounts(wi, yCounts(wi));
      ws.setCountStandardDeviations(wi, errors(wi));
    }
    return ws;
  }

class MatrixWorkspaceTestPerformance : public CxxTest::TestSuite {
public:
  static MatrixWorkspaceTestPerformance *createSuite() {
    return new MatrixWorkspaceTestPerformance();
  }
  static void destroySuite(MatrixWorkspaceTestPerformance *suite) {
    delete suite;
  }

  MatrixWorkspaceTestPerformance() : m_workspace(nullptr) {
    using namespace Mantid::Geometry;

    size_t numberOfHistograms = 10000;
    size_t numberOfBins = 1;
    m_workspace.init(numberOfHistograms, numberOfBins, numberOfBins - 1);
    bool includeMonitors = false;
    bool startYNegative = true;
    const std::string instrumentName("SimpleFakeInstrument");
    InstrumentCreationHelper::addFullInstrumentToWorkspace(
        m_workspace, includeMonitors, startYNegative, instrumentName);

    Mantid::Kernel::V3D sourcePos(0, 0, 0);
    Mantid::Kernel::V3D samplePos(0, 0, 1);
    Mantid::Kernel::V3D trolley1Pos(0, 0, 3);
    Mantid::Kernel::V3D trolley2Pos(0, 0, 6);
    m_paramMap = boost::make_shared<Mantid::Geometry::ParameterMap>();

    auto baseInstrument = ComponentCreationHelper::sansInstrument(
        sourcePos, samplePos, trolley1Pos, trolley2Pos);

    auto sansInstrument =
        boost::make_shared<Instrument>(baseInstrument, m_paramMap);

    // See component creation helper for instrument definition
    m_sansBank = sansInstrument->getComponentByName("Bank1");

Owen Arnold's avatar
Owen Arnold committed
    numberOfHistograms = sansInstrument->getNumberDetectors();
    m_workspaceSans.init(numberOfHistograms, numberOfBins, numberOfBins - 1);
    m_workspaceSans.setInstrument(sansInstrument);
    m_zRotation =
        Mantid::Kernel::Quat(180, V3D(0, 0, 1)); // rotate 180 degrees around z

    m_pos = Mantid::Kernel::V3D(1, 1, 1);
  }

  /// This test is equivalent to GeometryInfoFactoryTestPerformance, see there.
  void test_typical() {
    auto instrument = m_workspace.getInstrument();
    auto source = instrument->getSource();
    auto sample = instrument->getSample();
    auto L1 = source->getDistance(*sample);
    double result = 0.0;
    for (size_t i = 0; i < 10000; ++i) {
      auto detector = m_workspace.getDetector(i);
      result += L1;
      result += detector->getDistance(*sample);
      result += m_workspace.detectorTwoTheta(*detector);
    }
    // We are computing an using the result to fool the optimizer.
    TS_ASSERT_DELTA(result, 5214709.740869, 1e-6);
  }

Owen Arnold's avatar
Owen Arnold committed
   * Rotate a bank in the workspace and read the positions out again. Very
   * typical.
  void test_rotate_bank_and_read_positions_x10() {

    using namespace Mantid::Geometry;
    using namespace Mantid::Kernel;

    int count = 0;
    // Repeated execution to improve statistics and for comparison purposes with
    // future updates
    while (count < 10) {
Owen Arnold's avatar
Owen Arnold committed
      // Rotate the bank
      ComponentHelper::rotateComponent(
          *m_sansBank, *m_paramMap, m_zRotation,
          Mantid::Geometry::ComponentHelper::Relative);

      V3D pos;
      for (size_t i = 1; i < m_workspaceSans.getNumberHistograms(); ++i) {
        pos += m_workspaceSans.getDetector(i)->getPos();
      }
      ++count;
Owen Arnold's avatar
Owen Arnold committed
   * Move a bank in the workspace and read the positions out again. Very
   * typical.
  void test_move_bank_and_read_positions_x10() {

    using namespace Mantid::Geometry;
    using namespace Mantid::Kernel;

    int count = 0;
    // Repeated execution to improve statistics and for comparison purposes with
    // future updates
    while (count < 10) {
Owen Arnold's avatar
Owen Arnold committed
      // move the bank
      ComponentHelper::moveComponent(
          *m_sansBank, *m_paramMap, m_pos,
          Mantid::Geometry::ComponentHelper::Relative);

      V3D pos;
      for (size_t i = 1; i < m_workspaceSans.getNumberHistograms(); ++i) {
        pos += m_workspaceSans.getDetector(i)->getPos();
      }
      ++count;
private:
  WorkspaceTester m_workspace;
  WorkspaceTester m_workspaceSans;
  Mantid::Kernel::Quat m_zRotation;
  Mantid::Kernel::V3D m_pos;
  Mantid::Geometry::IComponent_const_sptr m_sansBank;
  boost::shared_ptr<Mantid::Geometry::ParameterMap> m_paramMap;
#endif /*WORKSPACETEST_H_*/