Skip to content
Snippets Groups Projects
BinaryOperationTest.h 11.3 KiB
Newer Older
Nick Draper's avatar
Nick Draper committed
#ifndef BINARYOPERATIONTEST_H_
#define BINARYOPERATIONTEST_H_
Nick Draper's avatar
Nick Draper committed

#include <cxxtest/TestSuite.h>
#include <cmath>

#include "MantidTestHelpers/WorkspaceCreationHelper.h"
Nick Draper's avatar
Nick Draper committed
#include "MantidAlgorithms/BinaryOperation.h"
Nick Draper's avatar
Nick Draper committed
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/WorkspaceFactory.h"
Nick Draper's avatar
Nick Draper committed
#include "MantidDataObjects/Workspace2D.h"
Nick Draper's avatar
Nick Draper committed

using namespace Mantid::API;
using namespace Mantid::Algorithms;
using namespace Mantid::DataObjects;
using Mantid::DataObjects::Workspace2D_sptr;
using Mantid::Geometry::IDetector_const_sptr;
Nick Draper's avatar
Nick Draper committed

class BinaryOpHelper : public Mantid::Algorithms::BinaryOperation {
  BinaryOpHelper() : BinaryOperation(){};
  virtual ~BinaryOpHelper(){};
  /// function to return a name of the algorithm, must be overridden in all
  /// algorithms
  virtual const std::string name() const { return "BinaryOpHelper"; }
  /// function to return a version of the algorithm, must be overridden in all
  /// algorithms
  virtual int version() const { return 1; }
  /// function to return a category of the algorithm. A default implementation
  /// is provided
  virtual const std::string category() const { return "Helper"; }
  /// function to return the summary of the algorithm. A default implementation
  /// is provided.
  virtual const std::string summary() const { return "Summary of this test."; }
  std::string checkSizeCompatibility(const MatrixWorkspace_const_sptr ws1,
                                     const MatrixWorkspace_const_sptr ws2) {
    m_lhs = ws1;
    m_rhs = ws2;
    BinaryOperation::checkRequirements();
    return BinaryOperation::checkSizeCompatibility(ws1, ws2);
  // Unhide base class method to avoid Intel compiler warning
  using BinaryOperation::checkSizeCompatibility;
  void performBinaryOperation(const Mantid::MantidVec &,
                              const Mantid::MantidVec &,
                              const Mantid::MantidVec &,
                              const Mantid::MantidVec &,
                              const Mantid::MantidVec &, Mantid::MantidVec &,
                              Mantid::MantidVec &) {}
  void performBinaryOperation(const Mantid::MantidVec &,
                              const Mantid::MantidVec &,
                              const Mantid::MantidVec &, const double,
                              const double, Mantid::MantidVec &,
                              Mantid::MantidVec &) {}
Nick Draper's avatar
Nick Draper committed

class BinaryOperationTest : public CxxTest::TestSuite {
Nick Draper's avatar
Nick Draper committed
public:
  void testcheckSizeCompatibility1D1D() {
Nick Draper's avatar
Nick Draper committed
    // Register the workspace in the data service
    Workspace2D_sptr work_in1 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(10);
    Workspace2D_sptr work_in2 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(20);
    Workspace2D_sptr work_in3 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(10);
    Workspace2D_sptr work_in4 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(5);
    Workspace2D_sptr work_in5 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(3);
    Workspace2D_sptr work_in6 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(1);
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in2).empty());
    TS_ASSERT(helper.checkSizeCompatibility(work_in1, work_in3).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in4).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in5).empty());
    TS_ASSERT(helper.checkSizeCompatibility(work_in1, work_in6).empty());
Nick Draper's avatar
Nick Draper committed
  }

  void testcheckSizeCompatibility2D1D() {
Nick Draper's avatar
Nick Draper committed
    // Register the workspace in the data service
    Workspace2D_sptr work_in1 =
        WorkspaceCreationHelper::Create2DWorkspace123(10, 10);
    Workspace2D_sptr work_in2 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(20);
    Workspace2D_sptr work_in3 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(10);
    Workspace2D_sptr work_in4 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(5);
    Workspace2D_sptr work_in5 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(3);
    Workspace2D_sptr work_in6 =
        WorkspaceCreationHelper::Create1DWorkspaceFib(1);
    MatrixWorkspace_sptr work_inEvent1 =
        WorkspaceCreationHelper::CreateEventWorkspace(10, 1);
    // will not pass x array does not match
    MatrixWorkspace_sptr work_inEvent2 =
        WorkspaceCreationHelper::CreateEventWorkspace(1, 10);
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in2).empty());
    TS_ASSERT(helper.checkSizeCompatibility(work_in1, work_in3).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in4).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in5).empty());
    TS_ASSERT(helper.checkSizeCompatibility(work_in1, work_in6).empty());
    TS_ASSERT(helper.checkSizeCompatibility(work_in1, work_inEvent1).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_inEvent2).empty());
Nick Draper's avatar
Nick Draper committed
  }

  void testcheckSizeCompatibility2D2D() {
Nick Draper's avatar
Nick Draper committed
    // Register the workspace in the data service
    Workspace2D_sptr work_in1 =
        WorkspaceCreationHelper::Create2DWorkspace(10, 10);
    Workspace2D_sptr work_in2 =
        WorkspaceCreationHelper::Create2DWorkspace(10, 20);
    Workspace2D_sptr work_in3 =
        WorkspaceCreationHelper::Create2DWorkspace(10, 10);
    Workspace2D_sptr work_in4 =
        WorkspaceCreationHelper::Create2DWorkspace(5, 5);
    Workspace2D_sptr work_in5 =
        WorkspaceCreationHelper::Create2DWorkspace(3, 3);
    Workspace2D_sptr work_in6 =
        WorkspaceCreationHelper::Create2DWorkspace(100, 1);
    MatrixWorkspace_sptr work_inEvent1 =
        WorkspaceCreationHelper::CreateEventWorkspace(5, 5);
    MatrixWorkspace_sptr work_inEvent2 =
        WorkspaceCreationHelper::CreateEventWorkspace(10, 10);
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in2).empty());
    TS_ASSERT(helper.checkSizeCompatibility(work_in1, work_in3).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in4).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in5).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_in6).empty());
    TS_ASSERT(!helper.checkSizeCompatibility(work_in1, work_inEvent1).empty());
    TS_ASSERT(helper.checkSizeCompatibility(work_in1, work_inEvent2).empty());
Nick Draper's avatar
Nick Draper committed
  }

  void testMaskedSpectraPropagation() {
    const int nHist = 5, nBins = 10;
    std::set<int64_t> masking;
    masking.insert(0);
    masking.insert(2);
    masking.insert(4);
    MatrixWorkspace_sptr work_in1 =
        WorkspaceCreationHelper::Create2DWorkspace123(nHist, nBins, 0, masking);
    MatrixWorkspace_sptr work_in2 =
        WorkspaceCreationHelper::Create2DWorkspace154(nHist, nBins);

    BinaryOpHelper helper;
    helper.initialize();
    helper.setProperty("LHSWorkspace", work_in1);
    helper.setProperty("RHSWorkspace", work_in2);
    const std::string outputSpace("test");
    helper.setPropertyValue("OutputWorkspace", outputSpace);
    helper.setRethrows(true);
    helper.execute();

    TS_ASSERT(helper.isExecuted());

    MatrixWorkspace_sptr output =
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
            outputSpace);
    for (int i = 0; i < nHist; ++i) {
      } catch (Mantid::Kernel::Exception::NotFoundError &) {
      if (det) {
        if (masking.count(i) == 0) {
          TS_ASSERT_EQUALS(det->isMasked(), false);
  BinaryOperation::BinaryOperationTable_sptr
  do_test_buildBinaryOperationTable(std::vector<std::vector<int>> lhs,
                                    std::vector<std::vector<int>> rhs,
                                    bool expect_throw = false) {
    EventWorkspace_sptr lhsWS =
        WorkspaceCreationHelper::CreateGroupedEventWorkspace(lhs, 50, 1.0);
    EventWorkspace_sptr rhsWS =
        WorkspaceCreationHelper::CreateGroupedEventWorkspace(rhs, 50, 1.0);
    BinaryOperation::BinaryOperationTable_sptr table;
    if (expect_throw) {
      TS_ASSERT_THROWS(
          table = BinaryOperation::buildBinaryOperationTable(lhsWS, rhsWS),
          std::runtime_error);
    } else {
      TS_ASSERT_THROWS_NOTHING(
          table = BinaryOperation::buildBinaryOperationTable(lhsWS, rhsWS));
      // std::cout << timer1.elapsed() << " sec to run
      // buildBinaryOperationTable\n";
      TS_ASSERT(table);
      TS_ASSERT_EQUALS(table->size(), lhsWS->getNumberHistograms());
  void test_buildBinaryOperationTable_simpleLHS_by_groupedRHS() {
    std::vector<std::vector<int>> lhs(6), rhs(2);
    for (int i = 0; i < 6; i++) {
      // one detector per pixel in lhs
      lhs[i].push_back(i);
      // 3 detectors in each on the rhs
      rhs[i / 3].push_back(i);
    auto table = do_test_buildBinaryOperationTable(lhs, rhs);
    for (int i = 0; i < 6; i++) {
      TS_ASSERT_EQUALS((*table)[i], i / 3);
  void
  test_buildBinaryOperationTable_simpleLHS_by_groupedRHS_mismatched_throws() {
    std::vector<std::vector<int>> lhs(6), rhs(2);
    for (int i = 0; i < 6; i++) {
      // one detector per pixel in lhs, but they start at 3
      lhs[i].push_back(i + 3);
      rhs[i / 3].push_back(i);
    auto table = do_test_buildBinaryOperationTable(lhs, rhs, false);
    TS_ASSERT_EQUALS((*table)[0], 1);
    TS_ASSERT_EQUALS((*table)[1], 1);
    TS_ASSERT_EQUALS((*table)[2], 1);
    TS_ASSERT_EQUALS((*table)[3], -1);
    TS_ASSERT_EQUALS((*table)[4], -1);
    TS_ASSERT_EQUALS((*table)[5], -1);
  void test_buildBinaryOperationTable_groupedLHS_by_groupedRHS() {
    std::vector<std::vector<int>> lhs(8), rhs(4);
    for (int i = 0; i < 16; i++) {
      lhs[i / 2].push_back(i);
      rhs[i / 4].push_back(i);
    auto table = do_test_buildBinaryOperationTable(lhs, rhs);
    for (int i = 0; i < 8; i++) {
      TS_ASSERT_EQUALS((*table)[i], i / 2);
  void
  test_buildBinaryOperationTable_groupedLHS_by_groupedRHS_bad_overlap_throws() {
    std::vector<std::vector<int>> lhs(6), rhs(4);
    for (int i = 0; i < 24; i++) {
      lhs[i / 4].push_back(i);
      rhs[i / 6].push_back(i);
    auto table = do_test_buildBinaryOperationTable(lhs, rhs, false);
    TS_ASSERT_EQUALS((*table)[0], 0);  // 0-3 go into 0-5
    TS_ASSERT_EQUALS((*table)[1], -1); // 4-7 fails to go anywhere
    TS_ASSERT_EQUALS((*table)[2], 1);  // 8-11 goes into 6-11
  void test_buildBinaryOperationTable_simpleLHS_by_groupedRHS_large() {
    std::vector<std::vector<int>> lhs(2000, std::vector<int>(1)),
        rhs(20, std::vector<int>(100));
    for (int i = 0; i < 2000; i++) {
      lhs[i][0] = i;
      // 1000 detectors in each on the rhs
      rhs[i / 100][i % 100] = i;
    auto table = do_test_buildBinaryOperationTable(lhs, rhs);
    for (int i = 0; i < 2000; i++) {
      TS_ASSERT_EQUALS((*table)[i], i / 100);
Nick Draper's avatar
Nick Draper committed
};

Nick Draper's avatar
Nick Draper committed
#endif /*BINARYOPERATIONTEST_H_*/