Skip to content
Snippets Groups Projects
CalculateCarpenterSampleCorrectionTest.h 11.8 KiB
Newer Older
#ifndef MULTIPLE_SCATTERING_ABSORPTION_TEST_H_
#define MULTIPLE_SCATTERING_ABSORPTION_TEST_H_

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

#include "MantidAlgorithms/CalculateCarpenterSampleCorrection.h"
#include "MantidDataObjects/WorkspaceCreation.h"
#include "MantidAPI/Axis.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidIndexing/IndexInfo.h"
#include "MantidHistogramData/LinearGenerator.h"
#include "MantidTestHelpers/WorkspaceCreationHelper.h"
#include "MantidTestHelpers/ComponentCreationHelper.h"

using namespace Mantid;
using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace Mantid::DataObjects;

class CalculateCarpenterSampleCorrectionTest : public CxxTest::TestSuite {
public:
  void testName() {
    TS_ASSERT_EQUALS(algorithm.name(), "CalculateCarpenterSampleCorrection");
  }

  void testVersion() { TS_ASSERT_EQUALS(algorithm.version(), 1); }

  void testInit() {
    Mantid::Algorithms::CalculateCarpenterSampleCorrection algorithm_b;
    TS_ASSERT_THROWS_NOTHING(algorithm_b.initialize());
    TS_ASSERT(algorithm_b.isInitialized());

    const std::vector<Property *> props = algorithm_b.getProperties();
    TS_ASSERT_EQUALS(props.size(), 8);

    TS_ASSERT_EQUALS(props[0]->name(), "InputWorkspace");
    TS_ASSERT(props[0]->isDefault());
    TS_ASSERT(dynamic_cast<WorkspaceProperty<MatrixWorkspace> *>(props[0]));

    TS_ASSERT_EQUALS(props[1]->name(), "OutputWorkspaceBaseName");
    TS_ASSERT(props[1]->isDefault());
    TS_ASSERT(dynamic_cast<WorkspaceProperty<API::WorkspaceGroup> *>(props[1]));

    TS_ASSERT_EQUALS(props[2]->name(), "AttenuationXSection");
    TS_ASSERT(props[2]->isDefault());
    TS_ASSERT(dynamic_cast<PropertyWithValue<double> *>(props[2]));

    TS_ASSERT_EQUALS(props[3]->name(), "ScatteringXSection");
    TS_ASSERT(props[3]->isDefault());
    TS_ASSERT(dynamic_cast<PropertyWithValue<double> *>(props[3]));

    TS_ASSERT_EQUALS(props[4]->name(), "SampleNumberDensity");
    TS_ASSERT(props[4]->isDefault());
    TS_ASSERT(dynamic_cast<PropertyWithValue<double> *>(props[4]));

    TS_ASSERT_EQUALS(props[5]->name(), "CylinderSampleRadius");
    TS_ASSERT(props[5]->isDefault());
    TS_ASSERT(dynamic_cast<PropertyWithValue<double> *>(props[5]));

    TS_ASSERT_EQUALS(props[6]->name(), "Absorption");
    TS_ASSERT(props[6]->isDefault());
    TS_ASSERT(dynamic_cast<PropertyWithValue<bool> *>(props[6]));

    TS_ASSERT_EQUALS(props[7]->name(), "MultipleScattering");
    TS_ASSERT(props[7]->isDefault());
    TS_ASSERT(dynamic_cast<PropertyWithValue<bool> *>(props[7]));
  }

  void testCalculationHist() {
    using namespace Mantid::HistogramData;
    auto wksp = DataObjects::create<DataObjects::Workspace2D>(
        ComponentCreationHelper::createTestInstrumentCylindrical(1),
        Indexing::IndexInfo(9),
        Histogram(BinEdges(17, LinearGenerator(1000.0, 1000.0)),
                  Counts(16, 2.0)));
    wksp->getAxis(0)->setUnit("TOF");
    AnalysisDataService::Instance().add("TestInputWS", std::move(wksp));

    // convert to wavelength
    auto convertUnitsAlg =
        Mantid::API::FrameworkManager::Instance().createAlgorithm(
            "ConvertUnits");
    convertUnitsAlg->setPropertyValue("InputWorkspace", "TestInputWS");
    convertUnitsAlg->setPropertyValue("OutputWorkspace", "TestInputWS");
    convertUnitsAlg->setProperty("Target", "Wavelength");
    convertUnitsAlg->execute();

    // create and execute the algorithm
    Mantid::Algorithms::CalculateCarpenterSampleCorrection algorithm_c;
    TS_ASSERT_THROWS_NOTHING(algorithm_c.initialize());
    TS_ASSERT(algorithm_c.isInitialized());

    TS_ASSERT_THROWS_NOTHING(
        algorithm_c.setPropertyValue("InputWorkspace", "TestInputWS"));
    TS_ASSERT_THROWS_NOTHING(algorithm_c.setPropertyValue(
        "OutputWorkspaceBaseName", "TestOutputWS"));
    TS_ASSERT_THROWS_NOTHING(
        algorithm_c.setPropertyValue("CylinderSampleRadius", "0.3175"));
    TS_ASSERT_THROWS_NOTHING(
        algorithm_c.setPropertyValue("AttenuationXSection", "2.8"));
    TS_ASSERT_THROWS_NOTHING(
        algorithm_c.setPropertyValue("SampleNumberDensity", "0.0721"));
    TS_ASSERT_THROWS_NOTHING(
        algorithm_c.setPropertyValue("ScatteringXSection", "5.1"));

    TS_ASSERT_THROWS_NOTHING(algorithm_c.execute());
    TS_ASSERT(algorithm_c.isExecuted());

    WorkspaceGroup_sptr test_output_WS;

    TS_ASSERT_THROWS_NOTHING(
        test_output_WS =
            AnalysisDataService::Instance().retrieveWS<API::WorkspaceGroup>(
                "TestOutputWS"));
    TS_ASSERT(test_output_WS);

    // Check the correction workspaces in the group
    Workspace_sptr absPtr = test_output_WS->getItem(0);
    Workspace_sptr msPtr = test_output_WS->getItem(1);
    auto absWksp = boost::dynamic_pointer_cast<MatrixWorkspace>(absPtr);
    auto msWksp = boost::dynamic_pointer_cast<MatrixWorkspace>(msPtr);
    TS_ASSERT(absWksp);
    TS_ASSERT(msWksp);

    // Check absorption correction
    const size_t size = 16;
    std::array<double, size> abs_corr_expected = {
McDonnell, Marshall's avatar
McDonnell, Marshall committed
        {0.786608, 0.764593, 0.743221, 0.722473, 0.702329, 0.682772, 0.663783,
         0.645345, 0.627442, 0.610057, 0.593173, 0.576775, 0.560848, 0.545376,
         0.530345, 0.515739}};

    auto &abs_corr_actual = absWksp->y(0);
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_DELTA(abs_corr_actual[i], abs_corr_expected[i], 0.00001);

    // Check applying absorption correction
    auto divide =
        Mantid::API::FrameworkManager::Instance().createAlgorithm("Divide");
    divide->initialize();
    divide->setPropertyValue("LHSWorkspace", "TestInputWS");
    divide->setPropertyValue("RHSWorkspace", absWksp->getName());
    divide->setPropertyValue("OutputWorkspace", "TestAbsWS");
    divide->execute();
    MatrixWorkspace_sptr absCorrectedWksp =
        AnalysisDataService::Instance().retrieveWS<API::MatrixWorkspace>(
            "TestAbsWS");
    std::array<double, size> abs_ws_expected = {
McDonnell, Marshall's avatar
McDonnell, Marshall committed
        {2.54256, 2.61577, 2.69099, 2.76827, 2.84767, 2.92924, 3.01303, 3.09912,
         3.18754, 3.27838, 3.37170, 3.46756, 3.56603, 3.66720, 3.77113,
         3.87793}};
    auto &abs_ws_actual = absCorrectedWksp->y(0);
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_DELTA(abs_ws_actual[i], abs_ws_expected[i], 0.00001);

    // Check multiple scattering correction
    std::array<double, size> ms_corr_expected = {
McDonnell, Marshall's avatar
McDonnell, Marshall committed
        {0.159334, 0.161684, 0.164032, 0.166376, 0.168712, 0.171039, 0.173355,
         0.175658, 0.177944, 0.180211, 0.182457, 0.184678, 0.186873, 0.189038,
         0.191171, 0.193268}};
    auto &ms_corr_actual = msWksp->y(0);
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_DELTA(ms_corr_actual[i], ms_corr_expected[i], 0.00001);

    // Check applying multiple scattering correction
    auto multiply =
        Mantid::API::FrameworkManager::Instance().createAlgorithm("Multiply");
    multiply->initialize();
    multiply->setPropertyValue("LHSWorkspace", "TestInputWS");
    multiply->setPropertyValue("RHSWorkspace", msWksp->getName());
    multiply->setPropertyValue("OutputWorkspace", "TestMultScatWS");
    multiply->execute();
    MatrixWorkspace_sptr msCorrectedWksp =
        AnalysisDataService::Instance().retrieveWS<API::MatrixWorkspace>(
            "TestMultScatWS");
    std::array<double, size> ms_ws_expected = {
McDonnell, Marshall's avatar
McDonnell, Marshall committed
        {0.318668, 0.323369, 0.328065, 0.332751, 0.337424, 0.342079, 0.346711,
         0.351315, 0.355887, 0.360422, 0.364913, 0.369356, 0.373746, 0.378076,
         0.382341, 0.386535}};

    auto &ms_ws_actual = msCorrectedWksp->y(0);
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_DELTA(ms_ws_actual[i], ms_ws_expected[i], 0.00001);

    // Check full correction comparison
    auto minus =
        Mantid::API::FrameworkManager::Instance().createAlgorithm("Minus");
    minus->initialize();
    minus->setPropertyValue("LHSWorkspace", "TestAbsWS");
    minus->setPropertyValue("RHSWorkspace", "TestMultScatWS");
    minus->setPropertyValue("OutputWorkspace", "TestOutputWS");
    minus->execute();
    MatrixWorkspace_sptr outputWksp =
        AnalysisDataService::Instance().retrieveWS<API::MatrixWorkspace>(
            "TestOutputWS");
    std::array<double, size> test_ws_expected = {
McDonnell, Marshall's avatar
McDonnell, Marshall committed
        {2.22389, 2.2924, 2.36292, 2.43552, 2.51024, 2.58716, 2.66632, 2.7478,
         2.83166, 2.91796, 3.00678, 3.09820, 3.19228, 3.28912, 3.38879,
         3.49139}};

    auto &test_ws_actual = outputWksp->y(0);
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_DELTA(test_ws_actual[i], test_ws_expected[i], 0.00001);

    // cleanup
    AnalysisDataService::Instance().remove("TestInputWS");
    AnalysisDataService::Instance().remove("TestAbsWS");
    AnalysisDataService::Instance().remove("TestMultScatWS");
    AnalysisDataService::Instance().remove("TestOutputWS");
  }

  void testCalculationEvent() {
    const std::string outName("CalculateCarpenterSampleCorrectionEventOutput");

    // setup the test workspace
    auto wksp = WorkspaceCreationHelper::createEventWorkspaceWithFullInstrument(
        1, 1, false);
    wksp->getAxis(0)
        ->setUnit("Wavelength"); // cheat and set the units to Wavelength
    wksp->getSpectrum(0)
        .convertTof(.09, 1.); // convert to be from 1->10 (about)

    AnalysisDataService::Instance().add(outName, wksp);

    // create the algorithm
    Mantid::Algorithms::CalculateCarpenterSampleCorrection algorithm;
    TS_ASSERT_THROWS_NOTHING(algorithm.initialize());
    TS_ASSERT(algorithm.isInitialized());

    // execute the algorithm
    TS_ASSERT_THROWS_NOTHING(algorithm.setProperty("InputWorkspace", wksp));
    TS_ASSERT_THROWS_NOTHING(
        algorithm.setPropertyValue("OutputWorkspaceBaseName", outName));
    TS_ASSERT_THROWS_NOTHING(algorithm.execute());
    TS_ASSERT(algorithm.isExecuted());

    // quick checks on the output workspace
    WorkspaceGroup_sptr outputWS;
    TS_ASSERT_THROWS_NOTHING(
        outputWS = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(
            outName));
    // Check the correction workspaces in the group
    auto absWksp =
        boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS->getItem(0));
    auto msWksp =
        boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS->getItem(1));
    TS_ASSERT(absWksp);
    TS_ASSERT(msWksp);

    auto group = boost::dynamic_pointer_cast<WorkspaceGroup>(outputWS);
    TS_ASSERT_EQUALS(group->getNumberOfEntries(), 2);

    // Check absorption correction
    const size_t size = 16;
    std::array<double, size> abs_corr_expected = {
McDonnell, Marshall's avatar
McDonnell, Marshall committed
        {0.733553, 0.726500, 0.719519, 0.712607, 0.705765, 0.698992, 0.692286,
         0.685648, 0.679076, 0.672570, 0.666129, 0.659753, 0.65344, 0.647191,
         0.641004, 0.634878}};
    const auto &abs_corr_actual = absWksp->histogram(0).y();
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_DELTA(abs_corr_actual[i], abs_corr_expected[i], 0.00001);

    const auto &abs_corr_actual_err = absWksp->histogram(0).e();
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_EQUALS(abs_corr_actual_err[i], 0.00);

    // Check multiple scattering correction
    std::array<double, size> ms_corr_expected = {
McDonnell, Marshall's avatar
McDonnell, Marshall committed
        {0.165116, 0.165916, 0.166714, 0.167512, 0.168309, 0.169105, 0.169900,
         0.170693, 0.171486, 0.172277, 0.173066, 0.173854, 0.17464, 0.175425,
         0.176207, 0.176988}};
    auto &ms_corr_actual = msWksp->y(0);
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_DELTA(ms_corr_actual[i], ms_corr_expected[i], 0.00001);

    const auto &ms_corr_actual_err = msWksp->histogram(0).e();
    for (size_t i = 0; i < size; i++)
      TS_ASSERT_EQUALS(ms_corr_actual_err[i], 0.00);

    // cleanup
    AnalysisDataService::Instance().remove(wksp->getName());
    AnalysisDataService::Instance().remove(outName + "_abs");
    AnalysisDataService::Instance().remove(outName + "_ms");
    AnalysisDataService::Instance().remove(outName);
  }

private:
  Mantid::Algorithms::CalculateCarpenterSampleCorrection algorithm;
};

#endif /*MULTIPLE_SCATTERING_ABSORPTION_TEST_H_*/