Newer
Older
Russell Taylor
committed
#ifndef CONVERTUNITSTEST_H_
#define CONVERTUNITSTEST_H_
#include <cxxtest/TestSuite.h>
Gigg, Martyn Anthony
committed
#include "MantidTestHelpers/WorkspaceCreationHelper.h"
#include "MantidAlgorithms/ConvertUnits.h"
Russell Taylor
committed
#include "MantidKernel/PhysicalConstants.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataHandling/LoadInstrument.h"
#include "MantidDataHandling/LoadEventPreNexus.h"
Janik Zikovsky
committed
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidGeometry/Instrument.h"
using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace Mantid::Algorithms;
using namespace Mantid::Geometry;
class ConvertUnitsTest : public CxxTest::TestSuite {
// Set up a small workspace for testing
Workspace_sptr space =
WorkspaceFactory::Instance().create("Workspace2D", 256, 11, 10);
Workspace2D_sptr space2D = boost::dynamic_pointer_cast<Workspace2D>(space);
boost::shared_ptr<Mantid::MantidVec> x(new Mantid::MantidVec(11));
for (int i = 0; i < 11; ++i) {
(*x)[i] = i * 1000;
boost::shared_ptr<Mantid::MantidVec> a(new Mantid::MantidVec(10));
boost::shared_ptr<Mantid::MantidVec> e(new Mantid::MantidVec(10));
for (int i = 0; i < 10; ++i) {
(*a)[i] = i;
(*e)[i] = sqrt(double(i));
Russell Taylor
committed
for (int j = 0; j < 256; ++j) {
space2D->setX(j, x);
space2D->setData(j, a, e);
Russell Taylor
committed
// Just set the spectrum number to match the index
space2D->getSpectrum(j)->setSpectrumNo(j);
space2D->getSpectrum(j)->setDetectorID(j);
Gigg, Martyn Anthony
committed
space2D->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
Russell Taylor
committed
// Register the workspace in the data service
Michael Reuter
committed
this->inputSpace = "testWorkspace";
AnalysisDataService::Instance().addOrReplace(inputSpace, space);
// Load the instrument data
Mantid::DataHandling::LoadInstrument loader;
loader.initialize();
// Path to test input file assumes Test directory checked out from SVN
const std::string inputFile =
ConfigService::Instance().getInstrumentDirectory() +
"HET_Definition.xml";
loader.setPropertyValue("Filename", inputFile);
Michael Reuter
committed
loader.setPropertyValue("Workspace", this->inputSpace);
loader.setProperty("RewriteSpectraMap", false);
loader.execute();
}
Russell Taylor
committed
Russell Taylor
committed
TS_ASSERT_THROWS_NOTHING(alg.initialize());
Michael Reuter
committed
}
/* Test that when the units are the same between the input workspace and the
* target, AND the output workspace name IS the same as the input workspace
* name,
* that the input workspace and output workspace point to the same in-memory
* workspace.
void test_Exec_Input_Same_Output_And_Same_Units() {
this->setup_WS();
if (!alg.isInitialized())
alg.initialize();
auto inWS =
AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(inputSpace);
// Set the properties
alg.setRethrows(true);
alg.setPropertyValue("InputWorkspace", inputSpace);
alg.setPropertyValue("OutputWorkspace",
inputSpace); // OutputWorkspace == InputWorkspace
alg.setPropertyValue("Target", "TOF"); // Same as the input workspace.
alg.execute();
auto outWS =
AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(inputSpace);
TSM_ASSERT_EQUALS(
"Input and Output Workspaces should be pointer identical.", inWS.get(),
outWS.get());
AnalysisDataService::Instance().remove(inputSpace);
}
/* Test that when the units are the same between the input workspace and the
* target, AND the output workspace name IS NOT the same as the input
* workspace name,
* that the input workspace and output workspace do not point to the same
* in-memory workspace.
void test_Exec_Input_different_Output_But_Same_Units() {
this->setup_WS();
if (!alg.isInitialized())
alg.initialize();
auto inWS =
AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(inputSpace);
// Set the properties
alg.setRethrows(true);
alg.setPropertyValue("InputWorkspace", inputSpace);
const std::string outputWorkspaceName = "OutWSName";
alg.setPropertyValue(
"OutputWorkspace",
outputWorkspaceName); // OutputWorkspace == InputWorkspace
alg.setPropertyValue("Target", "TOF"); // Same as the input workspace.
alg.execute();
auto outWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
outputWorkspaceName);
TSM_ASSERT_DIFFERS(
"Input and Output Workspaces be completely different objects.",
inWS.get(), outWS.get());
AnalysisDataService::Instance().remove(outputWorkspaceName);
AnalysisDataService::Instance().remove(inputSpace);
}
Michael Reuter
committed
this->setup_WS();
if (!alg.isInitialized())
alg.initialize();
Russell Taylor
committed
// Set the properties
alg.setRethrows(true);
alg.setPropertyValue("InputWorkspace", inputSpace);
outputSpace = "outWorkspace";
alg.setPropertyValue("OutputWorkspace", outputSpace);
alg.setPropertyValue("Target", "Wavelength");
alg.setPropertyValue("AlignBins", "1");
Russell Taylor
committed
TS_ASSERT_THROWS_NOTHING(alg.execute());
alg.isExecuted();
// Get back the saved workspace
TS_ASSERT_THROWS_NOTHING(
output = AnalysisDataService::Instance().retrieve(outputSpace));
TS_ASSERT_THROWS_NOTHING(
input = AnalysisDataService::Instance().retrieve(inputSpace));
Russell Taylor
committed
Workspace2D_sptr output2D =
boost::dynamic_pointer_cast<Workspace2D>(output);
Workspace2D_sptr input2D = boost::dynamic_pointer_cast<Workspace2D>(input);
Russell Taylor
committed
// Check that the output unit is correct
TS_ASSERT_EQUALS(output2D->getAxis(0)->unit()->unitID(), "Wavelength");
// Test that y & e data is unchanged
Russell Taylor
committed
Mantid::MantidVec y = output2D->dataY(101);
Mantid::MantidVec e = output2D->dataE(101);
unsigned int ten = 10;
TS_ASSERT_EQUALS(y.size(), ten);
TS_ASSERT_EQUALS(e.size(), ten);
Russell Taylor
committed
Mantid::MantidVec yIn = input2D->dataY(101);
Mantid::MantidVec eIn = input2D->dataE(101);
TS_ASSERT_DELTA(y[0], yIn[0], 1e-6);
TS_ASSERT_DELTA(y[4], yIn[4], 1e-6);
TS_ASSERT_DELTA(e[1], eIn[1], 1e-6);
// Test that spectra that should have been zeroed have been
Russell Taylor
committed
Mantid::MantidVec x = output2D->dataX(0);
Russell Taylor
committed
y = output2D->dataY(0);
e = output2D->dataE(0);
TS_ASSERT_EQUALS(y[1], 0);
TS_ASSERT_EQUALS(e[9], 0);
// Check that the data has truly been copied (i.e. isn't a reference to the
// same
// vector in both workspaces)
double test[10] = {11, 22, 33, 44, 55, 66, 77, 88, 99, 1010};
boost::shared_ptr<Mantid::MantidVec> tester(
new Mantid::MantidVec(test, test + 10));
output2D->setData(111, tester, tester);
Russell Taylor
committed
y = output2D->dataY(111);
Russell Taylor
committed
yIn = input2D->dataY(111);
Russell Taylor
committed
// Check that a couple of x bin boundaries have been correctly converted
Russell Taylor
committed
x = output2D->dataX(103);
TS_ASSERT_DELTA(x[5], 1.5808, 0.0001);
TS_ASSERT_DELTA(x[10], 3.1617, 0.0001);
// Just check that an input bin boundary is unchanged
Russell Taylor
committed
Mantid::MantidVec xIn = input2D->dataX(66);
TS_ASSERT_EQUALS(xIn[4], 4000.0);
AnalysisDataService::Instance().remove("outputSpace");
Russell Taylor
committed
Russell Taylor
committed
ConvertUnits quickly;
quickly.initialize();
TS_ASSERT(quickly.isInitialized());
quickly.setPropertyValue("InputWorkspace", outputSpace);
quickly.setPropertyValue("OutputWorkspace", "quickOut2");
quickly.setPropertyValue("Target", "Energy");
TS_ASSERT_THROWS_NOTHING(quickly.execute());
TS_ASSERT(quickly.isExecuted());
Russell Taylor
committed
Roman Tolchenov
committed
MatrixWorkspace_const_sptr output;
TS_ASSERT_THROWS_NOTHING(
output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
"quickOut2"));
TS_ASSERT_EQUALS(output->getAxis(0)->unit()->unitID(), "Energy");
TS_ASSERT_DELTA(output->dataX(1)[1], 10.10, 0.01);
AnalysisDataService::Instance().remove("quickOut2");
Russell Taylor
committed
}
void testConvertQuicklyCommonBins() {
Workspace2D_sptr input =
WorkspaceCreationHelper::Create2DWorkspace123(3, 10, 1);
input->getAxis(0)->unit() =
UnitFactory::Instance().create("MomentumTransfer");
Russell Taylor
committed
AnalysisDataService::Instance().add("quickIn", input);
ConvertUnits quickly;
quickly.initialize();
TS_ASSERT(quickly.isInitialized());
quickly.setPropertyValue("InputWorkspace", "quickIn");
quickly.setPropertyValue("OutputWorkspace", "quickOut");
quickly.setPropertyValue("Target", "dSpacing");
TS_ASSERT_THROWS_NOTHING(quickly.execute());
TS_ASSERT(quickly.isExecuted());
Russell Taylor
committed
Roman Tolchenov
committed
MatrixWorkspace_const_sptr output;
TS_ASSERT_THROWS_NOTHING(
output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
"quickOut"));
TS_ASSERT_EQUALS(output->getAxis(0)->unit()->unitID(), "dSpacing");
TS_ASSERT_EQUALS(&(output->dataX(0)[0]), &(output->dataX(0)[0]));
const size_t xsize = output->blocksize();
for (size_t i = 0; i < output->getNumberHistograms(); ++i) {
const auto &outX = output->readX(i);
for (size_t j = 0; j <= xsize; ++j) {
TS_ASSERT_EQUALS(outX[j], 2.0 * M_PI);
Russell Taylor
committed
}
AnalysisDataService::Instance().remove("quickIn");
AnalysisDataService::Instance().remove("quickOut");
}
void testDeltaE() {
MatrixWorkspace_sptr ws =
WorkspaceCreationHelper::Create2DWorkspaceBinned(1, 2663, 5, 7.5);
ws->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
Instrument_sptr testInst(new Instrument);
ws->setInstrument(testInst);
// Make it look like MARI (though not bin boundaries are different to the
// real MARI file used before)
// Define a source and sample position
// Define a source component
ObjComponent *source =
new ObjComponent("moderator", Object_sptr(), testInst.get());
source->setPos(V3D(0, 0.0, -11.739));
testInst->add(source);
testInst->markAsSource(source);
// Define a sample as a simple sphere
ObjComponent *sample =
new ObjComponent("samplePos", Object_sptr(), testInst.get());
testInst->setPos(0.0, 0.0, 0.0);
testInst->add(sample);
testInst->markAsSamplePos(sample);
Detector *physicalPixel = new Detector("pixel", 1, testInst.get());
physicalPixel->setPos(-0.34732, -3.28797, -2.29022);
testInst->add(physicalPixel);
testInst->markAsDetector(physicalPixel);
ws->getSpectrum(0)->addDetectorID(physicalPixel->getID());
Janik Zikovsky
committed
ConvertUnits conv;
conv.initialize();
conv.setProperty("InputWorkspace", ws);
std::string outputSpace = "outWorkspace";
conv.setPropertyValue("OutputWorkspace", outputSpace);
conv.setPropertyValue("Target", "DeltaE");
conv.setPropertyValue("Emode", "Direct");
conv.setPropertyValue("Efixed", "12.95");
conv.execute();
MatrixWorkspace_const_sptr output;
TS_ASSERT_THROWS_NOTHING(
output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
outputSpace));
TS_ASSERT_EQUALS(output->getAxis(0)->unit()->unitID(), "DeltaE");
TS_ASSERT_EQUALS(output->blocksize(), 1669);
ConvertUnits conv2;
conv2.initialize();
conv2.setProperty("InputWorkspace", ws);
conv2.setPropertyValue("OutputWorkspace", outputSpace);
conv2.setPropertyValue("Target", "DeltaE_inWavenumber");
conv2.setPropertyValue("Emode", "Indirect");
conv2.setPropertyValue("Efixed", "10");
Gigg, Martyn Anthony
committed
conv2.execute();
TS_ASSERT_THROWS_NOTHING(
output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
outputSpace));
TS_ASSERT_EQUALS(output->getAxis(0)->unit()->unitID(),
"DeltaE_inWavenumber");
TS_ASSERT_EQUALS(output->blocksize(), 2275);
AnalysisDataService::Instance().remove(outputSpace);
Russell Taylor
committed
}
Russell Taylor
committed
this->inputSpace = "eventWS";
EventWorkspace_sptr ws =
WorkspaceCreationHelper::createEventWorkspaceWithFullInstrument(1, 10,
false);
AnalysisDataService::Instance().addOrReplace(inputSpace, ws);
void testExecEvent_sameOutputWS() {
std::size_t wkspIndex = 0;
this->setup_Event();
// Retrieve Workspace
EventWorkspace_sptr WS =
AnalysisDataService::Instance().retrieveWS<EventWorkspace>(inputSpace);
TS_ASSERT(WS); // workspace is loaded
size_t start_blocksize = WS->blocksize();
size_t num_events = WS->getNumberEvents();
EventList el = WS->getEventList(wkspIndex);
double a_tof = el.getEvents()[0].tof();
double a_x = el.dataX()[1];
if (!alg.isInitialized())
alg.initialize();
TS_ASSERT(alg.isInitialized());
alg.setPropertyValue("InputWorkspace", inputSpace);
alg.setPropertyValue("Target", "DeltaE");
alg.setPropertyValue("EMode", "Direct");
alg.setPropertyValue("Efixed", "15.0");
this->outputSpace = inputSpace;
alg.setPropertyValue("OutputWorkspace", outputSpace);
TS_ASSERT_THROWS_NOTHING(alg.execute());
TS_ASSERT(alg.isExecuted());
// Things that haven't changed
TS_ASSERT_EQUALS(start_blocksize, WS->blocksize());
TS_ASSERT_EQUALS(num_events, WS->getNumberEvents());
// But a TOF changed.
TS_ASSERT_DIFFERS(a_tof, WS->getEventList(wkspIndex).getEvents()[0].tof());
TS_ASSERT_DIFFERS(a_x, WS->getEventList(wkspIndex).dataX()[1]);
void testExecEvent_TwoStepConversionWithDeltaE() {
Michael Reuter
committed
// Test to make sure the TOF->DeltaE->Other Quantity works for
// EventWorkspaces
this->setup_Event();
ConvertUnits conv;
conv.initialize();
conv.setPropertyValue("InputWorkspace", this->inputSpace);
conv.setPropertyValue("OutputWorkspace", this->inputSpace);
conv.setPropertyValue("Target", "DeltaE");
conv.setPropertyValue("Emode", "Direct");
conv.setPropertyValue("Efixed", "15.0");
Michael Reuter
committed
conv.execute();
ConvertUnits conv2;
conv2.initialize();
conv2.setPropertyValue("InputWorkspace", this->inputSpace);
conv2.setPropertyValue("OutputWorkspace", this->inputSpace);
conv2.setPropertyValue("Target", "Wavelength");
conv2.setPropertyValue("Emode", "Direct");
conv2.setPropertyValue("Efixed", "15.0");
TS_ASSERT_THROWS_NOTHING(conv2.execute());
TS_ASSERT(conv2.isExecuted());
Michael Reuter
committed
}
/** Ticket #3934: If the workspace is sorted by TOF, it should remain so even
* if
Janik Zikovsky
committed
* sorting flips the direction
*/
void do_testExecEvent_RemainsSorted(EventSortType sortType,
std::string targetUnit) {
EventWorkspace_sptr ws =
WorkspaceCreationHelper::createEventWorkspaceWithFullInstrument(1, 10,
false);
Janik Zikovsky
committed
ws->getAxis(0)->setUnit("TOF");
ws->sortAll(sortType, NULL);
Janik Zikovsky
committed
// Only threadsafe if all the event lists are sorted
Janik Zikovsky
committed
}
TS_ASSERT_EQUALS(ws->getNumberEvents(), 100 * 200);
Janik Zikovsky
committed
ConvertUnits conv;
conv.initialize();
conv.setProperty("InputWorkspace",
boost::dynamic_pointer_cast<MatrixWorkspace>(ws));
Janik Zikovsky
committed
conv.setPropertyValue("OutputWorkspace", "out");
conv.setPropertyValue("Target", targetUnit);
Janik Zikovsky
committed
conv.execute();
Janik Zikovsky
committed
EventWorkspace_sptr out =
AnalysisDataService::Instance().retrieveWS<EventWorkspace>("out");
Janik Zikovsky
committed
TS_ASSERT(out);
if (!out)
return;
TS_ASSERT_EQUALS(out->getNumberEvents(), 100 * 200);
Janik Zikovsky
committed
EventList &el = out->getEventList(0);
TS_ASSERT(el.getSortType() == sortType);
Janik Zikovsky
committed
Janik Zikovsky
committed
// Only threadsafe if all the event lists are sorted by TOF
Janik Zikovsky
committed
// Check directly that it is indeed increasing
double last_x = -1e10;
for (size_t i = 0; i < el.getNumberEvents(); i++) {
Janik Zikovsky
committed
double x = el.getEvent(i).tof();
Janik Zikovsky
committed
last_x = x;
}
} else if (sortType == PULSETIME_SORT) {
Janik Zikovsky
committed
// Check directly that it is indeed increasing
Mantid::Kernel::DateAndTime last_x;
for (size_t i = 0; i < el.getNumberEvents(); i++) {
Janik Zikovsky
committed
Mantid::Kernel::DateAndTime x = el.getEvent(i).pulseTime();
Janik Zikovsky
committed
last_x = x;
}
}
Janik Zikovsky
committed
}
void testExecEvent_RemainsSorted_TOF() {
Janik Zikovsky
committed
do_testExecEvent_RemainsSorted(TOF_SORT, "dSpacing");
Janik Zikovsky
committed
}
void testExecEvent_RemainsSorted_Pulsetime() {
Janik Zikovsky
committed
do_testExecEvent_RemainsSorted(PULSETIME_SORT, "dSpacing");
}
void testExecEvent_RemainsSorted_TOF_to_Energy() {
Janik Zikovsky
committed
do_testExecEvent_RemainsSorted(TOF_SORT, "Energy");
}
void testExecEvent_RemainsSorted_Pulsetime_to_Energy() {
Janik Zikovsky
committed
do_testExecEvent_RemainsSorted(PULSETIME_SORT, "Energy");
Janik Zikovsky
committed
}
ConvertUnits alg;
std::string inputSpace;
std::string outputSpace;
};
class ConvertUnitsTestPerformance : public CxxTest::TestSuite {
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static ConvertUnitsTestPerformance *createSuite() {
return new ConvertUnitsTestPerformance();
}
static void destroySuite(ConvertUnitsTestPerformance *suite) { delete suite; }
ConvertUnitsTestPerformance() {
FrameworkManager::Instance().exec(
"Load", "Filename=HET15869;OutputWorkspace=hist_tof");
FrameworkManager::Instance().exec(
"Load", "Filename=CNCS_7860_event;OutputWorkspace=event_tof");
void test_histogram_workspace() {
IAlgorithm *alg;
alg = FrameworkManager::Instance().exec(
"ConvertUnits",
"InputWorkspace=hist_tof;OutputWorkspace=hist_wave;Target=Wavelength");
TS_ASSERT(alg->isExecuted());
alg = FrameworkManager::Instance().exec(
"ConvertUnits", "InputWorkspace=hist_wave;OutputWorkspace=hist_"
"dSpacing;Target=dSpacing");
TS_ASSERT(alg->isExecuted());
void test_event_workspace() {
IAlgorithm *alg;
alg = FrameworkManager::Instance().exec(
"ConvertUnits", "InputWorkspace=event_tof;OutputWorkspace=event_wave;"
"Target=Wavelength");
TS_ASSERT(alg->isExecuted());
alg = FrameworkManager::Instance().exec(
"ConvertUnits", "InputWorkspace=event_wave;OutputWorkspace=event_"
"dSpacing;Target=dSpacing");
TS_ASSERT(alg->isExecuted());
}
private:
MatrixWorkspace_sptr histWS;
MatrixWorkspace_sptr eventWS;
};
Russell Taylor
committed
#endif /*CONVERTUNITSTEST_H_*/