Newer
Older
#ifndef WORKSPACETEST_H_
#define WORKSPACETEST_H_
#include "MantidAPI/ISpectrum.h"
Roman Tolchenov
committed
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/NumericAxis.h"
#include "MantidAPI/SpectraAxis.h"
#include "MantidAPI/SpectrumDetectorMapping.h"
#include "MantidAPI/WorkspaceFactory.h"
Russell Taylor
committed
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/Detector.h"
#include "MantidKernel/make_cow.h"
#include "MantidKernel/TimeSeriesProperty.h"
#include "MantidKernel/VMD.h"
#include "MantidIndexing/IndexInfo.h"
#include "MantidTestHelpers/FakeGmockObjects.h"
#include "MantidTestHelpers/FakeObjects.h"
#include "MantidTestHelpers/InstrumentCreationHelper.h"
#include "MantidTestHelpers/NexusTestHelper.h"
#include <cxxtest/TestSuite.h>
#include <boost/make_shared.hpp>
using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace Mantid::Geometry;
using Mantid::Indexing::IndexInfo;
Janik Zikovsky
committed
// Declare into the factory.
Janik Zikovsky
committed
/** Create a workspace with numSpectra, with
* each spectrum having one detector, at id = workspace index.
* @param numSpectra
* @return
*/
boost::shared_ptr<MatrixWorkspace> makeWorkspaceWithDetectors(size_t numSpectra,
size_t numBins) {
boost::shared_ptr<MatrixWorkspace> ws2 =
boost::make_shared<WorkspaceTester>();
ws2->initialize(numSpectra, numBins, numBins);
Gigg, Martyn Anthony
committed
auto inst = boost::make_shared<Instrument>("TestInstrument");
Russell Taylor
committed
ws2->setInstrument(inst);
// We get a 1:1 map by default so the detector ID should match the spectrum
// number
for (size_t i = 0; i < ws2->getNumberHistograms(); ++i) {
Janik Zikovsky
committed
// Create a detector for each spectra
Detector *det = new Detector("pixel", static_cast<detid_t>(i), inst.get());
Janik Zikovsky
committed
inst->add(det);
inst->markAsDetector(det);
ws2->getSpectrum(i).addDetectorID(static_cast<detid_t>(i));
Gigg, Martyn Anthony
committed
}
Janik Zikovsky
committed
return ws2;
Gigg, Martyn Anthony
committed
}
Janik Zikovsky
committed
class MatrixWorkspaceTest : public CxxTest::TestSuite {
Russell Taylor
committed
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static MatrixWorkspaceTest *createSuite() {
return new MatrixWorkspaceTest();
Russell Taylor
committed
}
static void destroySuite(MatrixWorkspaceTest *suite) { delete suite; }
MatrixWorkspaceTest() : ws(boost::make_shared<WorkspaceTester>()) {
ws->initialize(1, 1, 1);
}
void test_setIndexInfo() {
WorkspaceTester ws;
ws.initialize(3, 1, 1);
IndexInfo bad_indices(2);
TS_ASSERT_THROWS(ws.setIndexInfo(std::move(bad_indices)),
std::runtime_error);
IndexInfo indices(3);
indices.setSpectrumNumbers({2, 4, 6});
indices.setDetectorIDs({{0}, {1}, {2, 3}});
TS_ASSERT_THROWS_NOTHING(ws.setIndexInfo(std::move(indices)));
TS_ASSERT_EQUALS(ws.getSpectrum(0).getSpectrumNo(), 2);
TS_ASSERT_EQUALS(ws.getSpectrum(1).getSpectrumNo(), 4);
TS_ASSERT_EQUALS(ws.getSpectrum(2).getSpectrumNo(), 6);
TS_ASSERT_EQUALS(ws.getSpectrum(0).getDetectorIDs(),
(std::set<detid_t>{0}));
TS_ASSERT_EQUALS(ws.getSpectrum(1).getDetectorIDs(),
(std::set<detid_t>{1}));
TS_ASSERT_EQUALS(ws.getSpectrum(2).getDetectorIDs(),
(std::set<detid_t>{2, 3}));
}
void test_toString_Produces_Expected_Contents() {
auto testWS = boost::make_shared<WorkspaceTester>();
testWS->setTitle("A test run");
testWS->getAxis(0)->setUnit("TOF");
testWS->setYUnitLabel("Counts");
std::string expected = "WorkspaceTester\n"
"Title: A test run\n"
"Histograms: 1\n"
"Bins: 1\n"
"Histogram\n"
"X axis: Time-of-flight / microsecond\n"
"Y axis: Counts\n"
"Distribution: False\n"
"Instrument: None\n"
"Run start: not available\n"
"Run end: not available\n";
TS_ASSERT_EQUALS(expected, testWS->toString());
}
void testGetSetTitle() {
TS_ASSERT_EQUALS(ws->getTitle(), "");
Russell Taylor
committed
ws->setTitle("something");
TS_ASSERT_EQUALS(ws->getTitle(), "something");
Russell Taylor
committed
ws->setTitle("");
void testGetSetComment() {
TS_ASSERT_EQUALS(ws->getComment(), "");
Russell Taylor
committed
ws->setComment("commenting");
TS_ASSERT_EQUALS(ws->getComment(), "commenting");
Russell Taylor
committed
ws->setComment("");
void test_getIndicesFromDetectorIDs() {
WorkspaceTester ws;
ws.initialize(10, 1, 1);
for (size_t i = 0; i < 10; i++)
ws.getSpectrum(i).setDetectorID(detid_t(i * 10));
std::vector<detid_t> dets;
dets.push_back(60);
dets.push_back(20);
dets.push_back(90);
std::vector<size_t> indices = ws.getIndicesFromDetectorIDs(dets);
TS_ASSERT_EQUALS(indices.size(), 3);
TS_ASSERT_EQUALS(indices[0], 6);
TS_ASSERT_EQUALS(indices[1], 2);
TS_ASSERT_EQUALS(indices[2], 9);
}
void
test_That_A_Workspace_Gets_SpectraMap_When_Initialized_With_NVector_Elements() {
WorkspaceTester testWS;
Gigg, Martyn Anthony
committed
const size_t nhist(10);
testWS.initialize(nhist, 1, 1);
for (size_t i = 0; i < testWS.getNumberHistograms(); i++) {
TS_ASSERT_EQUALS(testWS.getSpectrum(i).getSpectrumNo(), specnum_t(i + 1));
TS_ASSERT(testWS.getSpectrum(i).hasDetectorID(detid_t(i)));
Gigg, Martyn Anthony
committed
}
void test_updateSpectraUsing() {
WorkspaceTester testWS;
specnum_t specs[] = {1, 2, 2, 3};
detid_t detids[] = {10, 99, 20, 30};
TS_ASSERT_THROWS_NOTHING(
testWS.updateSpectraUsing(SpectrumDetectorMapping(specs, detids, 4)));
TS_ASSERT(testWS.getSpectrum(0).hasDetectorID(10));
TS_ASSERT(testWS.getSpectrum(1).hasDetectorID(20));
TS_ASSERT(testWS.getSpectrum(1).hasDetectorID(99));
TS_ASSERT(testWS.getSpectrum(2).hasDetectorID(30));
}
void testDetectorMappingCopiedWhenAWorkspaceIsCopied() {
boost::shared_ptr<MatrixWorkspace> parent =
boost::make_shared<WorkspaceTester>();
parent->getSpectrum(0).setSpectrumNo(99);
parent->getSpectrum(0).setDetectorID(999);
MatrixWorkspace_sptr copied = WorkspaceFactory::Instance().create(parent);
// Has it been copied?
TS_ASSERT_EQUALS(copied->getSpectrum(0).getSpectrumNo(), 99);
TS_ASSERT(copied->getSpectrum(0).hasDetectorID(999));
Russell Taylor
committed
}
Russell Taylor
committed
void testGetMemorySize() { TS_ASSERT_THROWS_NOTHING(ws->getMemorySize()); }
void testHistory() { TS_ASSERT_THROWS_NOTHING(ws->history()); }
void testAxes() { TS_ASSERT_EQUALS(ws->axes(), 2); }
Russell Taylor
committed
void testGetAxis() {
TS_ASSERT_THROWS(ws->getAxis(-1), Exception::IndexError);
TS_ASSERT_THROWS_NOTHING(ws->getAxis(0));
TS_ASSERT(ws->getAxis(0));
TS_ASSERT(ws->getAxis(0)->isNumeric());
TS_ASSERT_THROWS(ws->getAxis(2), Exception::IndexError);
Russell Taylor
committed
void testReplaceAxis() {
Axis *ax = new SpectraAxis(ws.get());
TS_ASSERT_THROWS(ws->replaceAxis(2, ax), Exception::IndexError);
TS_ASSERT_THROWS_NOTHING(ws->replaceAxis(0, ax));
TS_ASSERT(ws->getAxis(0)->isSpectra());
Russell Taylor
committed
}
void testIsDistribution() {
TS_ASSERT(!ws->isDistribution());
ws->setDistribution(true);
TS_ASSERT(ws->isDistribution());
void testGetSetYUnit() {
TS_ASSERT_EQUALS(ws->YUnit(), "");
TS_ASSERT_THROWS_NOTHING(ws->setYUnit("something"));
TS_ASSERT_EQUALS(ws->YUnit(), "something");
Russell Taylor
committed
}
WorkspaceTester ws;
TS_ASSERT_THROWS_NOTHING(ws.getSpectrum(0));
TS_ASSERT_THROWS_NOTHING(ws.getSpectrum(3));
Janik Zikovsky
committed
}
/** Get a detector sptr for each spectrum */
Janik Zikovsky
committed
// Workspace has 3 spectra, each 1 in length
const int numHist(3);
boost::shared_ptr<MatrixWorkspace> workspace(
makeWorkspaceWithDetectors(3, 1));
Janik Zikovsky
committed
// Initially un masked
for (int i = 0; i < numHist; ++i) {
Russell Taylor
committed
IDetector_const_sptr det;
Janik Zikovsky
committed
TS_ASSERT_THROWS_NOTHING(det = workspace->getDetector(i));
Janik Zikovsky
committed
TS_ASSERT_EQUALS(det->getID(), i);
Janik Zikovsky
committed
TS_FAIL("No detector defined");
}
}
// Now a detector group
auto &spec = workspace->getSpectrum(0);
spec.addDetectorID(1);
spec.addDetectorID(2);
Russell Taylor
committed
IDetector_const_sptr det;
Janik Zikovsky
committed
TS_ASSERT_THROWS_NOTHING(det = workspace->getDetector(0));
TS_ASSERT(det);
// Now an empty (no detector) pixel
auto &spec2 = workspace->getSpectrum(1);
spec2.clearDetectorIDs();
Russell Taylor
committed
IDetector_const_sptr det2;
Janik Zikovsky
committed
TS_ASSERT_THROWS_ANYTHING(det2 = workspace->getDetector(1));
TS_ASSERT(!det2);
}
void testWholeSpectraMasking() {
Gigg, Martyn Anthony
committed
// Workspace has 3 spectra, each 1 in length
const int numHist(3);
boost::shared_ptr<MatrixWorkspace> workspace(
makeWorkspaceWithDetectors(3, 1));
Gigg, Martyn Anthony
committed
// Initially un masked
for (int i = 0; i < numHist; ++i) {
Gigg, Martyn Anthony
committed
TS_ASSERT_EQUALS(workspace->readY(i)[0], 1.0);
TS_ASSERT_EQUALS(workspace->readE(i)[0], 1.0);
Russell Taylor
committed
IDetector_const_sptr det;
Gigg, Martyn Anthony
committed
TS_ASSERT_THROWS_NOTHING(det = workspace->getDetector(i));
Gigg, Martyn Anthony
committed
TS_ASSERT_EQUALS(det->isMasked(), false);
Gigg, Martyn Anthony
committed
TS_FAIL("No detector defined");
Gigg, Martyn Anthony
committed
}
}
// Mask a spectra
Russell Taylor
committed
workspace->maskWorkspaceIndex(1);
workspace->maskWorkspaceIndex(2);
Gigg, Martyn Anthony
committed
for (int i = 0; i < numHist; ++i) {
Gigg, Martyn Anthony
committed
double expectedValue(0.0);
bool expectedMasked(false);
Gigg, Martyn Anthony
committed
expectedValue = 1.0;
expectedMasked = false;
Gigg, Martyn Anthony
committed
expectedMasked = true;
Gigg, Martyn Anthony
committed
}
TS_ASSERT_EQUALS(workspace->readY(i)[0], expectedValue);
TS_ASSERT_EQUALS(workspace->readE(i)[0], expectedValue);
Russell Taylor
committed
IDetector_const_sptr det;
Gigg, Martyn Anthony
committed
TS_ASSERT_THROWS_NOTHING(det = workspace->getDetector(i));
Gigg, Martyn Anthony
committed
TS_ASSERT_EQUALS(det->isMasked(), expectedMasked);
Gigg, Martyn Anthony
committed
TS_FAIL("No detector defined");
Gigg, Martyn Anthony
committed
}
}
}
void testFlagMasked() {
auto ws = makeWorkspaceWithDetectors(2, 2);
// Now do a valid masking
TS_ASSERT_THROWS_NOTHING(ws->flagMasked(0, 1, 0.75));
TS_ASSERT(ws->hasMaskedBins(0));
TS_ASSERT_EQUALS(ws->maskedBins(0).size(), 1);
TS_ASSERT_EQUALS(ws->maskedBins(0).begin()->first, 1);
TS_ASSERT_EQUALS(ws->maskedBins(0).begin()->second, 0.75);
// flagMasked() shouldn't change the y-value maskBins() tested below does
// that
TS_ASSERT_EQUALS(ws->dataY(0)[1], 1.0);
// Now mask a bin earlier than above and check it's sorting properly
TS_ASSERT_THROWS_NOTHING(ws->flagMasked(1, 1))
TS_ASSERT_EQUALS(ws->maskedBins(1).size(), 1)
TS_ASSERT_EQUALS(ws->maskedBins(1).begin()->first, 1)
TS_ASSERT_EQUALS(ws->maskedBins(1).begin()->second, 1.0)
// Check the previous masking is still OK
TS_ASSERT_EQUALS(ws->maskedBins(0).rbegin()->first, 1)
TS_ASSERT_EQUALS(ws->maskedBins(0).rbegin()->second, 0.75)
Janik Zikovsky
committed
void testMasking() {
auto ws2 = makeWorkspaceWithDetectors(1, 2);
Janik Zikovsky
committed
TS_ASSERT(!ws2->hasMaskedBins(0));
// Doesn't throw on invalid spectrum number, just returns false
TS_ASSERT(!ws2->hasMaskedBins(1));
TS_ASSERT(!ws2->hasMaskedBins(-1));
// Will throw if nothing masked for spectrum
TS_ASSERT_THROWS(ws2->maskedBins(0), Mantid::Kernel::Exception::IndexError);
// Will throw if attempting to mask invalid spectrum
TS_ASSERT_THROWS(ws2->maskBin(-1, 1),
Mantid::Kernel::Exception::IndexError);
TS_ASSERT_THROWS(ws2->maskBin(1, 1), Mantid::Kernel::Exception::IndexError);
TS_ASSERT_THROWS(ws2->maskBin(0, -1),
Mantid::Kernel::Exception::IndexError);
TS_ASSERT_THROWS(ws2->maskBin(0, 2), Mantid::Kernel::Exception::IndexError);
TS_ASSERT_THROWS_NOTHING(ws2->maskBin(0, 1, 0.5));
TS_ASSERT(ws2->hasMaskedBins(0));
TS_ASSERT_EQUALS(ws2->maskedBins(0).size(), 1);
TS_ASSERT_EQUALS(ws2->maskedBins(0).begin()->first, 1);
TS_ASSERT_EQUALS(ws2->maskedBins(0).begin()->second, 0.5);
TS_ASSERT_EQUALS(ws2->dataY(0)[1], 0.5);
// Now mask a bin earlier than above and check it's sorting properly
TS_ASSERT_THROWS_NOTHING(ws2->maskBin(0, 0));
TS_ASSERT_EQUALS(ws2->maskedBins(0).begin()->first, 0);
TS_ASSERT_EQUALS(ws2->maskedBins(0).begin()->second, 1.0);
TS_ASSERT_EQUALS(ws2->dataY(0)[0], 0.0);
// Check the previous masking is still OK
TS_ASSERT_EQUALS(ws2->maskedBins(0).rbegin()->first, 1);
TS_ASSERT_EQUALS(ws2->maskedBins(0).rbegin()->second, 0.5);
TS_ASSERT_EQUALS(ws2->dataY(0)[1], 0.5);
void testMaskingNaNInf() {
const size_t s = 4;
const double y[s] = {NAN, INFINITY, -INFINITY, 2.};
WorkspaceTester ws;
ws.initialize(1, s + 1, s);
// initialize and mask first with 0 weights
// masking with 0 weight should be equiavalent to flagMasked
// i.e. values should not change, even Inf and NaN
for (size_t i = 0; i < s; ++i) {
ws.mutableY(0)[i] = y[i];
ws.maskBin(0, i, 0);
}
TS_ASSERT(std::isnan(ws.y(0)[0]));
TS_ASSERT(std::isinf(ws.y(0)[1]));
TS_ASSERT(std::isinf(ws.y(0)[2]));
TS_ASSERT_EQUALS(ws.y(0)[3], 2.);
// now mask w/o specifying weight (e.g. 1 by default)
// in this case everything should be 0, even NaN and Inf
for (size_t i = 0; i < s; ++i) {
ws.maskBin(0, i);
TS_ASSERT_EQUALS(ws.y(0)[i], 0.);
}
}
WorkspaceTester wkspace;
TS_ASSERT_EQUALS(wkspace.blocksize(), 3);
TS_ASSERT_EQUALS(wkspace.size(), 3);
Gigg, Martyn Anthony
committed
}
WorkspaceTester wkspace;
wkspace.initialize(1, 4, 3);
wkspace.dataX(0)[1] = 2.0;
wkspace.dataX(0)[2] = 3.0;
wkspace.dataX(0)[3] = 4.0;
TS_ASSERT_EQUALS(wkspace.getNumberHistograms(), 1);
Gigg, Martyn Anthony
committed
TS_ASSERT_EQUALS(wkspace.binIndexOf(1.3), 0);
Gigg, Martyn Anthony
committed
// Bin boundary
TS_ASSERT_EQUALS(wkspace.binIndexOf(2.0), 0);
Gigg, Martyn Anthony
committed
// Mid range
TS_ASSERT_EQUALS(wkspace.binIndexOf(2.5), 1);
Gigg, Martyn Anthony
committed
// Still second bin
TS_ASSERT_EQUALS(wkspace.binIndexOf(2.001), 1);
Gigg, Martyn Anthony
committed
// Last bin
TS_ASSERT_EQUALS(wkspace.binIndexOf(3.1), 2);
Gigg, Martyn Anthony
committed
// Last value
TS_ASSERT_EQUALS(wkspace.binIndexOf(4.0), 2);
Gigg, Martyn Anthony
committed
// Error handling
// Bad index value
TS_ASSERT_THROWS(wkspace.binIndexOf(2.5, 1), std::out_of_range);
TS_ASSERT_THROWS(wkspace.binIndexOf(2.5, -1), std::out_of_range);
Gigg, Martyn Anthony
committed
// Bad X values
TS_ASSERT_THROWS(wkspace.binIndexOf(5.), std::out_of_range);
TS_ASSERT_THROWS(wkspace.binIndexOf(0.), std::out_of_range);
Gigg, Martyn Anthony
committed
}
th.createFile("MatrixWorkspaceTest.nxs");
auto ws = makeWorkspaceWithDetectors(100, 50);
std::vector<int> spec;
// Give some funny numbers, so it is not the default
ws->getSpectrum(size_t(i)).setSpectrumNo(i * 11);
ws->getSpectrum(size_t(i)).setDetectorID(99 - i);
spec.push_back(i);
}
// Save that to the NXS file
TS_ASSERT_THROWS_NOTHING(ws->saveSpectraMapNexus(th.file, spec););
}
void test_get_neighbours_exact() {
// Create a nearest neighbours product, which can be returned.
MockNearestNeighbours *product = new MockNearestNeighbours;
EXPECT_CALL(*product, neighbours(_)).WillRepeatedly(Return(map));
EXPECT_CALL(*product, die()).Times(1); // Created once and destroyed once!
// Create a factory, for generating the nearest neighbour products
MockNearestNeighboursFactory *factory = new MockNearestNeighboursFactory;
EXPECT_CALL(*factory, create(_, _, _, _))
.Times(1)
.WillOnce(Return(product));
WorkspaceTester wkspace(factory);
wkspace.initialize(1, 4, 3);
wkspace.getNeighboursExact(0, 1); // First call should construct nearest
// neighbours before calling ::neighbours
wkspace.getNeighboursExact(0, 1); // Second call should not construct
// nearest neighbours before calling
// ::neighbours
void test_get_neighbours_radius() {
// Create a nearest neighbours product, which can be returned.
MockNearestNeighbours *product = new MockNearestNeighbours;
EXPECT_CALL(*product, neighboursInRadius(_, _)).WillRepeatedly(Return(map));
EXPECT_CALL(*product, die()).Times(1); // Created once and destroyed once!
// Create a factory, for generating the nearest neighbour products
MockNearestNeighboursFactory *factory = new MockNearestNeighboursFactory;
EXPECT_CALL(*factory, create(_, _, _)).Times(1).WillOnce(Return(product));
WorkspaceTester wkspace(factory);
wkspace.initialize(1, 4, 3);
wkspace.getNeighbours(0, 1); // First call should construct nearest
// neighbours before calling ::neighbours
wkspace.getNeighbours(0, 1); // Second call should not construct nearest
// neighbours before calling ::neighbours
void test_reset_neighbours() {
// Create a nearest neighbours product, which can be returned.
MockNearestNeighbours *product = new MockNearestNeighbours;
EXPECT_CALL(*product, neighboursInRadius(_, _)).WillRepeatedly(Return(map));
EXPECT_CALL(*product, die())
.Times(1); // Should be explicitly called upon reset.
// Create a factory, for generating the nearest neighbour products
MockNearestNeighboursFactory *factory = new MockNearestNeighboursFactory;
EXPECT_CALL(*factory, create(_, _, _)).Times(1).WillOnce(Return(product));
WorkspaceTester wkspace(factory);
wkspace.initialize(1, 4, 3);
wkspace.getNeighbours(0, 1); // First call should construct nearest
// neighbours before calling ::neighbours
wkspace.rebuildNearestNeighbours(); // should cause die.
TSM_ASSERT("Nearest neigbhbours Factory has not been used as expected",
Mock::VerifyAndClearExpectations(factory));
TSM_ASSERT("Nearest neigbhbours Product has not been used as expected",
Mock::VerifyAndClearExpectations(product));
void test_rebuild_after_reset_neighbours() {
SpectrumDistanceMap mapA, mapB, mapC;
MockNearestNeighbours *productA = new MockNearestNeighbours;
EXPECT_CALL(*productA, neighboursInRadius(_, _))
.WillRepeatedly(Return(mapA));
EXPECT_CALL(*productA, die()).Times(1);
MockNearestNeighbours *productB = new MockNearestNeighbours;
EXPECT_CALL(*productB, neighboursInRadius(_, _))
.WillRepeatedly(Return(mapB));
EXPECT_CALL(*productB, die()).Times(1);
MockNearestNeighbours *productC = new MockNearestNeighbours;
EXPECT_CALL(*productC, neighboursInRadius(_, _))
.WillRepeatedly(Return(mapC));
EXPECT_CALL(*productC, die()).Times(1);
// Create a factory, for generating the nearest neighbour products
MockNearestNeighboursFactory *factory = new MockNearestNeighboursFactory;
EXPECT_CALL(*factory, create(_, _, _))
.Times(3)
.WillOnce(Return(productA))
.WillOnce(Return(productB))
.WillOnce(Return(productC));
WorkspaceTester wkspace(factory);
wkspace.initialize(1, 4, 3);
wkspace.getNeighbours(0, 1); // First call should construct nearest
// neighbours before calling ::neighbours
wkspace.rebuildNearestNeighbours(); // should cause die.
wkspace.getNeighbours(0, 1); // should cause creation for radius type call
wkspace.rebuildNearestNeighbours(); // should cause die.
wkspace.getNeighbours(
0, 1); // should cause creation for number of neighbours type call
wkspace.rebuildNearestNeighbours(); // should cause die. allows expectations
// to be checked, otherwise die called
// on nn destruction!
TSM_ASSERT("Nearest neigbhbours Factory has not been used as expected",
Mock::VerifyAndClearExpectations(factory));
TSM_ASSERT("Nearest neigbhbours ProductA has not been used as expected",
Mock::VerifyAndClearExpectations(productA));
TSM_ASSERT("Nearest neigbhbours ProductB has not been used as expected",
Mock::VerifyAndClearExpectations(productB));
TSM_ASSERT("Nearest neigbhbours ProductC has not been used as expected",
Mock::VerifyAndClearExpectations(productC));
/** Properly, this tests a method on Instrument, not MatrixWorkspace, but they
* are related.
*/
auto ws = makeWorkspaceWithDetectors(100, 10);
Instrument_const_sptr inst = ws->getInstrument();
// Make sure the instrument is parametrized so that the test is thorough
TS_ASSERT(inst->isParametrized());
TS_ASSERT(!inst->isDetectorMasked(1));
TS_ASSERT(!inst->isDetectorMasked(19));
// Mask then check that it returns as masked
TS_ASSERT(ws->getSpectrum(19).hasDetectorID(19));
ws->maskWorkspaceIndex(19);
TS_ASSERT(inst->isDetectorMasked(19));
}
/** Check if any of a list of detectors are masked */
void test_isDetectorMasked_onASet() {
auto ws = makeWorkspaceWithDetectors(100, 10);
Instrument_const_sptr inst = ws->getInstrument();
// Make sure the instrument is parametrized so that the test is thorough
TS_ASSERT(inst->isParametrized());
// Mask detector IDs 8 and 9
ws->maskWorkspaceIndex(8);
ws->maskWorkspaceIndex(9);
std::set<detid_t> dets;
TSM_ASSERT("No detector IDs = not masked", !inst->isDetectorMasked(dets));
TSM_ASSERT("Detector is not masked", !inst->isDetectorMasked(dets));
TSM_ASSERT("Detectors are not masked", !inst->isDetectorMasked(dets));
TSM_ASSERT("If any detector is not masked, return false",
!inst->isDetectorMasked(dets));
// Start again
dets.clear();
dets.insert(8);
TSM_ASSERT("If all detectors are not masked, return true",
inst->isDetectorMasked(dets));
TSM_ASSERT("If all detectors are not masked, return true",
inst->isDetectorMasked(dets));
TSM_ASSERT("If any detector is not masked, return false",
!inst->isDetectorMasked(dets));
void test_hasGroupedDetectors() {
auto ws = makeWorkspaceWithDetectors(5, 1);
TS_ASSERT_EQUALS(ws->hasGroupedDetectors(), false);
ws->getSpectrum(0).addDetectorID(3);
TS_ASSERT_EQUALS(ws->hasGroupedDetectors(), true);
void test_getSpectrumToWorkspaceIndexMap() {
const auto map = ws.getSpectrumToWorkspaceIndexMap();
TS_ASSERT_EQUALS(map.size(), 2);
TS_ASSERT_EQUALS(map.begin()->first, 1);
TS_ASSERT_EQUALS(map.begin()->second, 0);
TS_ASSERT_EQUALS(map.rbegin()->first, 2);
TS_ASSERT_EQUALS(map.rbegin()->second, 1);
// Check it throws for non-spectra axis
ws.replaceAxis(1, new NumericAxis(1));
TS_ASSERT_THROWS(ws.getSpectrumToWorkspaceIndexMap(), std::runtime_error);
void test_getDetectorIDToWorkspaceIndexMap() {
auto ws = makeWorkspaceWithDetectors(5, 1);
detid2index_map idmap = ws->getDetectorIDToWorkspaceIndexMap(true);
TS_ASSERT_EQUALS(idmap.size(), 5);
int i = 0;
for (auto it = idmap.begin(); it != idmap.end(); ++it, ++i) {
TS_ASSERT_EQUALS(idmap.count(i), 1);
TS_ASSERT_EQUALS(idmap[i], i);
}
ws->getSpectrum(2).addDetectorID(99); // Set a second ID on one spectrum
TS_ASSERT_THROWS(ws->getDetectorIDToWorkspaceIndexMap(true),
std::runtime_error);
detid2index_map idmap2 = ws->getDetectorIDToWorkspaceIndexMap();
TS_ASSERT_EQUALS(idmap2.size(), 6);
}
void test_getDetectorIDToWorkspaceIndexVector() {
auto ws = makeWorkspaceWithDetectors(100, 10);
std::vector<size_t> out;
detid_t offset = -1234;
out = ws->getDetectorIDToWorkspaceIndexVector(offset));
TS_ASSERT_EQUALS(offset, 0);
TS_ASSERT_EQUALS(out.size(), 100);
TS_ASSERT_EQUALS(out[0], 0);
TS_ASSERT_EQUALS(out[1], 1);
TS_ASSERT_EQUALS(out[99], 99);
// Create some discontinuities and check that the default value is there
// Have to create a whole new instrument to keep things consistent, since
// the detector ID
// is stored in at least 3 places
auto inst = boost::make_shared<Instrument>("TestInstrument");
ws->setInstrument(inst);
// We get a 1:1 map by default so the detector ID should match the spectrum
// number
for (size_t i = 0; i < ws->getNumberHistograms(); ++i) {
detid_t detid = static_cast<detid_t>(i);
// Create a detector for each spectra
if (i == 0)
detid = -1;
if (i == 99)
detid = 110;
Detector *det = new Detector("pixel", detid, inst.get());
inst->add(det);
inst->markAsDetector(det);
ws->getSpectrum(i).addDetectorID(detid);
}
ws->getSpectrum(66).clearDetectorIDs();
out = ws->getDetectorIDToWorkspaceIndexVector(offset));
TS_ASSERT_EQUALS(offset, 1);
TS_ASSERT_EQUALS(out.size(), 112);
TS_ASSERT_EQUALS(out[66 + offset], std::numeric_limits<size_t>::max());
TS_ASSERT_EQUALS(out[99 + offset], 99);
TS_ASSERT_EQUALS(out[105 + offset], std::numeric_limits<size_t>::max());
TS_ASSERT_EQUALS(out[110 + offset], 99);
void test_getSpectrumToWorkspaceIndexVector() {
auto ws = makeWorkspaceWithDetectors(100, 10);
std::vector<size_t> out;
detid_t offset = -1234;
TS_ASSERT_THROWS_NOTHING(out =
ws->getSpectrumToWorkspaceIndexVector(offset));
TS_ASSERT_EQUALS(offset, -1);
TS_ASSERT_EQUALS(out.size(), 100);
TS_ASSERT_EQUALS(out[0], 0);
TS_ASSERT_EQUALS(out[1], 1);
TS_ASSERT_EQUALS(out[99], 99);
void test_getSignalAtCoord_histoData() {
// Create a test workspace
const auto ws = createTestWorkspace(4, 6, 5);
// Get signal at coordinates
std::vector<coord_t> coords = {0.5, 1.0};
TS_ASSERT_DELTA(
ws.getSignalAtCoord(coords.data(), Mantid::API::NoNormalization), 0.0,
1e-5);
coords[0] = 1.5;
TS_ASSERT_DELTA(
ws.getSignalAtCoord(coords.data(), Mantid::API::NoNormalization), 1.0,
1e-5);
}
void test_getSignalAtCoord_pointData() {
// Create a test workspace
const auto ws = createTestWorkspace(4, 5, 5);
// Get signal at coordinates
std::vector<coord_t> coords = {0.0, 1.0};
TS_ASSERT_DELTA(
ws.getSignalAtCoord(coords.data(), Mantid::API::NoNormalization), 0.0,
1e-5);
coords[0] = 1.0;
TS_ASSERT_DELTA(
ws.getSignalAtCoord(coords.data(), Mantid::API::NoNormalization), 1.0,
1e-5);
}
void test_getCoordAtSignal_regression() {
Having more spectrum numbers (acutally vertical axis increments) than x bins
in VolumeNormalisation mode
should not cause any issues.
*/
WorkspaceTester ws;
const int nVertical = 4;
const int nBins = 2;
const int nYValues = 1;
ws.initialize(nVertical, nBins, nYValues);
NumericAxis *verticalAxis = new NumericAxis(nVertical);
for (int i = 0; i < nVertical; ++i) {
for (int j = 0; j < nBins; ++j) {
if (j < nYValues) {
ws.dataY(i)[j] = 1.0; // All y values are 1.
ws.dataE(i)[j] = j;
}
ws.dataX(i)[j] = j; // x increments by 1
}
verticalAxis->setValue(i, double(i)); // Vertical axis increments by 1.
}
ws.replaceAxis(1, verticalAxis);
// Signal is always 1 and volume of each box is 1. Therefore normalized
// signal values by volume should always be 1.
coord_t coord_top_right[2] = {static_cast<float>(ws.readX(0).back()),
float(0)};
TS_ASSERT_THROWS_NOTHING(
value = ws.getSignalAtCoord(coord_top_right, VolumeNormalization));
// Test at another location just to be sure.
coord_t coord_bottom_left[2] = {
static_cast<float>(ws.readX(nVertical - 1)[1]), float(nVertical - 1)};
TS_ASSERT_THROWS_NOTHING(
value = ws.getSignalAtCoord(coord_bottom_left, VolumeNormalization));
WorkspaceTester ws;
TSM_ASSERT_THROWS("Characterisation test. This is not implemented.",
ws.setMDMasking(NULL), std::runtime_error);
WorkspaceTester ws;
TSM_ASSERT_THROWS("Characterisation test. This is not implemented.",
ws.clearMDMasking(), std::runtime_error);
void test_getSpecialCoordinateSystem_default() {
WorkspaceTester ws;
TSM_ASSERT_EQUALS("Should default to no special coordinate system.",
Mantid::Kernel::None, ws.getSpecialCoordinateSystem());
void test_getFirstPulseTime_getLastPulseTime() {
WorkspaceTester ws;
auto proton_charge = new TimeSeriesProperty<double>("proton_charge");
DateAndTime startTime("2013-04-21T10:40:00");
proton_charge->addValue(startTime, 1.0E-7);
proton_charge->addValue(startTime + 1.0, 2.0E-7);
proton_charge->addValue(startTime + 2.0, 3.0E-7);
proton_charge->addValue(startTime + 3.0, 4.0E-7);
ws.mutableRun().addLogData(proton_charge);
TS_ASSERT_EQUALS(ws.getFirstPulseTime(), startTime);
TS_ASSERT_EQUALS(ws.getLastPulseTime(), startTime + 3.0);
void test_getFirstPulseTime_getLastPulseTime_SNS1990bug() {
WorkspaceTester ws;
auto proton_charge = new TimeSeriesProperty<double>("proton_charge");
DateAndTime startTime("1990-12-31T23:59:00");
proton_charge->addValue(startTime, 1.0E-7);
proton_charge->addValue(startTime + 1.0, 2.0E-7);
ws.mutableRun().addLogData(proton_charge);
// If fewer than 100 entries (unlikely to happen in reality), you just get
// back the last one
TS_ASSERT_EQUALS(ws.getFirstPulseTime(), startTime + 1.0);
for (int i = 2; i < 62; ++i) {
proton_charge->addValue(startTime + static_cast<double>(i), 1.0E-7);
TS_ASSERT_EQUALS(ws.getFirstPulseTime(),
DateAndTime("1991-01-01T00:00:00"));
void
test_getFirstPulseTime_getLastPulseTime_throws_if_protoncharge_missing_or_empty() {
TS_ASSERT_THROWS(ws.getFirstPulseTime(), std::runtime_error);
TS_ASSERT_THROWS(ws.getLastPulseTime(), std::runtime_error);
ws.mutableRun().addLogData(new TimeSeriesProperty<double>("proton_charge"));
TS_ASSERT_THROWS(ws.getFirstPulseTime(), std::runtime_error);
TS_ASSERT_THROWS(ws.getLastPulseTime(), std::runtime_error);
void
test_getFirstPulseTime_getLastPulseTime_throws_if_protoncharge_wrong_type() {
WorkspaceTester ws;
auto proton_charge = new TimeSeriesProperty<int>("proton_charge");
proton_charge->addValue("2013-04-21T10:19:10", 1);
proton_charge->addValue("2013-04-21T10:19:12", 2);
ws.mutableRun().addLogData(proton_charge);
TS_ASSERT_THROWS(ws.getFirstPulseTime(), std::invalid_argument);
TS_ASSERT_THROWS(ws.getLastPulseTime(), std::invalid_argument);
ws.mutableRun().addProperty(
new PropertyWithValue<double>("proton_charge", 99.0), true);
TS_ASSERT_THROWS(ws.getFirstPulseTime(), std::invalid_argument);
TS_ASSERT_THROWS(ws.getLastPulseTime(), std::invalid_argument);
TS_ASSERT_EQUALS(xmin, 1.0);
TS_ASSERT_EQUALS(xmax, 1.0);
TS_ASSERT_EQUALS(ws->getXMin(), 1.0);
TS_ASSERT_EQUALS(ws->getXMax(), 1.0);
}
auto ws = boost::make_shared<WorkspaceTester>();
TSM_ASSERT("There should be no monitor workspace by default",
!ws->monitorWorkspace())
auto ws2 = boost::make_shared<WorkspaceTester>();
ws->setMonitorWorkspace(ws2);
TSM_ASSERT_EQUALS("Monitor workspace not successfully set",
ws->monitorWorkspace(), ws2)
ws->setMonitorWorkspace(boost::shared_ptr<MatrixWorkspace>());
TSM_ASSERT("Monitor workspace not successfully reset",
!ws->monitorWorkspace())
auto &X = ws.dataX(0);
X[0] = 1.0;
X[1] = 2.0;
X[2] = 3.0;
X[3] = 4.0;
auto ip = ws.getXIndex(0, 0.0, true);
TS_ASSERT_EQUALS(ip.first, 0);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 0.0, false);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 1.0, true);
TS_ASSERT_EQUALS(ip.first, 0);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 1.0, false);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 5.0, true);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 5.0, false);
TS_ASSERT_EQUALS(ip.first, 3);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, true);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, false);
TS_ASSERT_EQUALS(ip.first, 3);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 5.0, true, 5);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 5.0, false, 5);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 3.0, true, 5);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 3.0, false, 5);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, true, 5);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, false, 5);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, true, 4);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, false, 4);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, true, 3);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, false, 3);
TS_ASSERT_EQUALS(ip.first, 3);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, true);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 4.0, false);
TS_ASSERT_EQUALS(ip.first, 3);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 2.0, true, 3);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 2.0, false, 3);
TS_ASSERT_EQUALS(ip.first, 3);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 1.0, true, 3);
TS_ASSERT_EQUALS(ip.first, 4);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 1.0, false, 3);
TS_ASSERT_EQUALS(ip.first, 3);
TS_ASSERT_DELTA(ip.second, 0.0, 1e-15);
ip = ws.getXIndex(0, 2.1, true);
TS_ASSERT_EQUALS(ip.first, 1);
TS_ASSERT_DELTA(ip.second, 0.1, 1e-15);
ip = ws.getXIndex(0, 2.1, false);
TS_ASSERT_EQUALS(ip.first, 2);
TS_ASSERT_DELTA(ip.second, 0.9, 1e-15);