Newer
Older
Janik Zikovsky
committed
#ifndef MANTID_MDEVENTS_BOXCONTROLLERSETTINGSALGORITHMTEST_H_
#define MANTID_MDEVENTS_BOXCONTROLLERSETTINGSALGORITHMTEST_H_
#include "MantidAPI/FrameworkManager.h"
#include "MantidDataHandling/LoadParameterFile.h"
#include "MantidMDAlgorithms/BoxControllerSettingsAlgorithm.h"
#include "MantidTestHelpers/ComponentCreationHelper.h"
#include "MantidTestHelpers/ScopedFileHelper.h"
#include "MantidTestHelpers/WorkspaceCreationHelper.h"
Janik Zikovsky
committed
#include <cxxtest/TestSuite.h>
Janik Zikovsky
committed
using namespace Mantid;
using namespace Mantid::API;
using namespace Mantid::MDAlgorithms;
using ScopedFileHelper::ScopedFile;
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** Concrete declaration of BoxControllerSettingsAlgorithm for testing */
class BoxControllerSettingsAlgorithmImpl
: public BoxControllerSettingsAlgorithm {
Janik Zikovsky
committed
// Make all the members public so I can test them.
friend class BoxControllerSettingsAlgorithmTest;
Janik Zikovsky
committed
public:
const std::string name() const override {
return "BoxControllerSettingsAlgorithmImpl";
}
int version() const override { return 1; }
const std::string category() const override { return "Testing"; }
const std::string summary() const override { return "Summary of this test."; }
void init() override {}
void exec() override {}
Janik Zikovsky
committed
};
class BoxControllerSettingsAlgorithmTest : public CxxTest::TestSuite {
Helper function. Runs LoadParameterAlg, to get an instrument parameter
definition from a file onto a workspace.
void apply_instrument_parameter_file_to_workspace(MatrixWorkspace_sptr ws,
const ScopedFile &file) {
// Load the Instrument Parameter file over the existing test workspace +
// instrument.
using DataHandling::LoadParameterFile;
LoadParameterFile loadParameterAlg;
loadParameterAlg.setRethrows(true);
loadParameterAlg.initialize();
loadParameterAlg.setPropertyValue("Filename", file.getFileName());
loadParameterAlg.setProperty("Workspace", ws);
loadParameterAlg.execute();
}
MatrixWorkspace_sptr
create_workspace_with_splitting_params(int splitThreshold, int splitInto,
int maxRecursionDepth) {
auto ws = boost::make_shared<Mantid::DataObjects::Workspace2D>();
ws->initialize(1, 2, 1);
ws->setInstrument(
ComponentCreationHelper::createTestInstrumentRectangular(6, 1, 0.0));
const std::string instrumentName = ws->getInstrument()->getName();
// Create a parameter file, with a root equation that will apply to all
// detectors.
const std::string parameterFileContents = boost::str(
boost::format("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\
<parameter-file instrument = \"%1%\" date = \"2013-01-31T00:00:00\">\n\
<component-link name=\"%1%\">\n\
<parameter name=\"SplitThreshold\">\n\
<value val=\"%2%\"/>\n\
</parameter>\n\
<parameter name=\"SplitInto\">\n\
<value val=\"%3%\"/>\n\
</parameter>\n\
<parameter name=\"MaxRecursionDepth\">\n\
<value val=\"%4%\"/>\n\
</parameter>\n\
</component-link>\n\
</parameter-file>\n") %
instrumentName % splitThreshold % splitInto % maxRecursionDepth);
// Create a temporary Instrument Parameter file.
ScopedFile file(parameterFileContents, instrumentName + "_Parameters.xml");
// Apply parameter file to workspace.
apply_instrument_parameter_file_to_workspace(ws, file);
return ws;
}
Janik Zikovsky
committed
public:
Janik Zikovsky
committed
BoxControllerSettingsAlgorithmImpl alg;
alg.initBoxControllerProps();
BoxController_sptr bc(new BoxController(3));
alg.setBoxController(bc);
TS_ASSERT_EQUALS(bc->getSplitInto(0), 5);
TS_ASSERT_EQUALS(bc->getSplitThreshold(), 1000);
TS_ASSERT_EQUALS(bc->getMaxDepth(), 5);
Janik Zikovsky
committed
}
/** You can change the defaults given to the props */
void test_initProps_otherDefaults() {
Janik Zikovsky
committed
BoxControllerSettingsAlgorithmImpl alg;
alg.initBoxControllerProps("6", 1234, 34);
BoxController_sptr bc(new BoxController(3));
alg.setBoxController(bc);
TS_ASSERT_EQUALS(bc->getSplitInto(0), 6);
TS_ASSERT_EQUALS(bc->getSplitThreshold(), 1234);
TS_ASSERT_EQUALS(bc->getMaxDepth(), 34);
Janik Zikovsky
committed
}
void doTest(BoxController_sptr bc, std::string SplitInto = "",
std::string SplitThreshold = "",
std::string MaxRecursionDepth = "") {
Janik Zikovsky
committed
BoxControllerSettingsAlgorithmImpl alg;
Janik Zikovsky
committed
alg.initBoxControllerProps();
if (!SplitInto.empty())
alg.setPropertyValue("SplitInto", SplitInto);
if (!SplitThreshold.empty())
alg.setPropertyValue("SplitThreshold", SplitThreshold);
if (!MaxRecursionDepth.empty())
alg.setPropertyValue("MaxRecursionDepth", MaxRecursionDepth);
Janik Zikovsky
committed
alg.setBoxController(bc);
Janik Zikovsky
committed
}
Janik Zikovsky
committed
Janik Zikovsky
committed
BoxController_sptr bc(new BoxController(3));
TSM_ASSERT_THROWS_ANYTHING("Too few parameters", doTest(bc, "5,5"));
TSM_ASSERT_THROWS_ANYTHING("Too many parameters", doTest(bc, "1,2,3,4"));
doTest(bc, "4");
TS_ASSERT_EQUALS(bc->getSplitInto(2), 4);
doTest(bc, "7,6,5");
TS_ASSERT_EQUALS(bc->getSplitInto(0), 7);
TS_ASSERT_EQUALS(bc->getSplitInto(1), 6);
TS_ASSERT_EQUALS(bc->getSplitInto(2), 5);
Janik Zikovsky
committed
}
Janik Zikovsky
committed
BoxController_sptr bc(new BoxController(3));
TSM_ASSERT_THROWS_ANYTHING("Negative threshold", doTest(bc, "", "-3"));
doTest(bc, "", "1234");
TS_ASSERT_EQUALS(bc->getSplitThreshold(), 1234);
Janik Zikovsky
committed
}
Janik Zikovsky
committed
BoxController_sptr bc(new BoxController(3));
TSM_ASSERT_THROWS_ANYTHING("Negative MaxRecursionDepth",
doTest(bc, "", "", "-1"));
doTest(bc, "", "", "34");
TS_ASSERT_EQUALS(bc->getMaxDepth(), 34);
Janik Zikovsky
committed
}
void test_take_instrument_parameters() {
const int splitInto = 4;
const int splitThreshold = 16;
const int maxRecursionDepth = 5;
// Workspace has instrument has parameters for all box splitting parameters.
auto ws = create_workspace_with_splitting_params(splitThreshold, splitInto,
maxRecursionDepth);
BoxController_sptr bc(new BoxController(1));
BoxControllerSettingsAlgorithmImpl alg;
alg.initBoxControllerProps();
/* Note, not properties are set, so the algorithm will have defaults set.
and should therefore look to
pick-up any available in the instrument parameters.*/
alg.setBoxController(bc, ws->getInstrument());
int actualSplitThreshold = alg.getProperty("SplitThreshold");
TS_ASSERT_EQUALS(splitThreshold, actualSplitThreshold);
std::vector<int> actualSplitInto = alg.getProperty("SplitInto");
TS_ASSERT_EQUALS(bc->getNDims(), actualSplitInto.size());
std::vector<int> expectedSplitInto(bc->getNDims(), splitInto);
TS_ASSERT_EQUALS(expectedSplitInto, actualSplitInto);
int actualMaxRecursionDepth = alg.getProperty("MaxRecursionDepth");
TS_ASSERT_EQUALS(maxRecursionDepth, actualMaxRecursionDepth);
}
// Test that the user providied values for spliting have precedence.
void test_ignore_instrument_parameters() {
const int splitInto = 8;
const int splitThreshold = 16;
const int maxRecursionDepth = 5;
// Workspace has instrument has parameters for all box splitting parameters.
auto ws = create_workspace_with_splitting_params(splitThreshold, splitInto,
maxRecursionDepth);
BoxController_sptr bc(new BoxController(1));
// Create splitting parameters that are not default and not the same as
// those on the instrument parameters.
const std::vector<int> nonDefaultSplitInto =
std::vector<int>(bc->getNDims(), splitInto + 1);
const int nonDefaultSplitThreshold = splitThreshold + 1;
const int nonDefaultMaxRecursionDepth = maxRecursionDepth + 1;
BoxControllerSettingsAlgorithmImpl alg;
alg.initBoxControllerProps();
alg.setProperty("SplitInto", nonDefaultSplitInto);
alg.setProperty("SplitThreshold", nonDefaultSplitThreshold);
alg.setProperty("MaxRecursionDepth", nonDefaultMaxRecursionDepth);
alg.setBoxController(bc, ws->getInstrument());
int actualSplitThreshold = alg.getProperty("SplitThreshold");
TS_ASSERT_EQUALS(nonDefaultSplitThreshold, actualSplitThreshold);
std::vector<int> actualSplitInto = alg.getProperty("SplitInto");
TS_ASSERT_EQUALS(bc->getNDims(), actualSplitInto.size());
TS_ASSERT_EQUALS(nonDefaultSplitInto, actualSplitInto);
int actualMaxRecursionDepth = alg.getProperty("MaxRecursionDepth");
TS_ASSERT_EQUALS(nonDefaultMaxRecursionDepth, actualMaxRecursionDepth);
}
void test_with_no_instrument_parameters() {
// Create a workspace with an instrument, but no instrument parameters for
// box splitting.
auto ws = boost::make_shared<Mantid::DataObjects::Workspace2D>();
ws->initialize(1, 2, 1);
ws->setInstrument(
ComponentCreationHelper::createTestInstrumentRectangular(6, 1, 0));
BoxController_sptr bc(new BoxController(1));
BoxControllerSettingsAlgorithmImpl alg;
alg.initBoxControllerProps();
// Note that no properties are actually set. All properties should fall-back
// to their default values.
TSM_ASSERT_THROWS_NOTHING("Lack of specific instrument parameters should "
"not cause algorithm to fail.",
alg.setBoxController(bc, ws->getInstrument()));
// Check that the properties are unaffected. Should just reflect the
// defaults.
Mantid::Kernel::Property *p = alg.getProperty("SplitThreshold");
p = alg.getProperty("MaxRecursionDepth");
TS_ASSERT(p->isDefault());
}
Janik Zikovsky
committed
};
#endif /* MANTID_MDEVENTS_BOXCONTROLLERSETTINGSALGORITHMTEST_H_ */