Newer
Older
#ifndef WORKSPACETEST_H_
#define WORKSPACETEST_H_
#include "MantidAPI/DetectorInfo.h"
#include "MantidAPI/ISpectrum.h"
Roman Tolchenov
committed
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/NumericAxis.h"
#include "MantidAPI/Run.h"
#include "MantidAPI/SpectraAxis.h"
#include "MantidAPI/SpectrumDetectorMapping.h"
#include "MantidAPI/SpectrumInfo.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidGeometry/Instrument/ComponentHelper.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 "MantidTypes/SpectrumDefinition.h"
#include "MantidIndexing/IndexInfo.h"
#include "MantidTestHelpers/FakeObjects.h"
#include "MantidTestHelpers/InstrumentCreationHelper.h"
#include "MantidTestHelpers/ComponentCreationHelper.h"
#include "MantidTestHelpers/NexusTestHelper.h"
#include <cxxtest/TestSuite.h>
#include <boost/make_shared.hpp>
#include <atomic>
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");
// 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
}
ws2->setInstrument(inst);
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_set_bad_IndexInfo() {
WorkspaceTester ws;
ws.initialize(3, 1, 1);
IndexInfo bad(2);
TS_ASSERT_THROWS(ws.setIndexInfo(std::move(bad)), std::runtime_error);
}
void test_IndexInfo() {
WorkspaceTester ws;
ws.initialize(3, 1, 1);
const auto &indexInfo = ws.indexInfo();
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(indexInfo.spectrumNumber(0), 2);
TS_ASSERT_EQUALS(indexInfo.spectrumNumber(1), 4);
TS_ASSERT_EQUALS(indexInfo.spectrumNumber(2), 6);
TS_ASSERT_EQUALS(indexInfo.detectorIDs(0), (std::vector<detid_t>{0}));
TS_ASSERT_EQUALS(indexInfo.detectorIDs(1), (std::vector<detid_t>{1}));
TS_ASSERT_EQUALS(indexInfo.detectorIDs(2), (std::vector<detid_t>{2, 3}));
}
void test_setIndexInfo() {
// NOTE: This test checks if the IndexInfo set via
// MatrixWorkspace::setIndexInfo() affects data stored in ISpectrum and
// obtained via the legacy interface. THIS TEST SHOULD BE REMOVED ONCE THAT
// INTERFACE IS BEING REMOVED.
WorkspaceTester ws;
ws.initialize(3, 1, 1);
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_indexInfo_legacy_compatibility() {
// NOTE: This test checks if the IndexInfo reference returned by
// MatrixWorkspace::indexInfo() reflects changes done via the legacy
// interface of ISpectrum. THIS TEST SHOULD BE REMOVED ONCE THAT INTERFACE
// IS BEING REMOVED.
WorkspaceTester ws;
ws.initialize(1, 1, 1);
const auto &indexInfo = ws.indexInfo();
TS_ASSERT_EQUALS(indexInfo.spectrumNumber(0), 1);
TS_ASSERT_EQUALS(indexInfo.detectorIDs(0), std::vector<detid_t>({0}));
ws.getSpectrum(0).setSpectrumNo(7);
ws.getSpectrum(0).addDetectorID(7);
TS_ASSERT_EQUALS(indexInfo.spectrumNumber(0), 7);
TS_ASSERT_EQUALS(indexInfo.detectorIDs(0), std::vector<detid_t>({0, 7}));
}
void test_IndexInfo_copy() {
WorkspaceTester ws;
ws.initialize(3, 1, 1);
IndexInfo indices(3);
indices.setSpectrumNumbers({2, 4, 6});
indices.setDetectorIDs({{0}, {1}, {2, 3}});
ws.setIndexInfo(std::move(indices));
// Internally this references data in ISpectrum
const auto &indexInfo = ws.indexInfo();
// This should create a copy, dropping any links to MatrixWorkspace or
// ISpectrum
const auto copy(indexInfo);
TS_ASSERT_EQUALS(copy.spectrumNumber(0), 2);
TS_ASSERT_EQUALS(copy.spectrumNumber(1), 4);
TS_ASSERT_EQUALS(copy.spectrumNumber(2), 6);
TS_ASSERT_EQUALS(copy.detectorIDs(0), (std::vector<detid_t>{0}));
TS_ASSERT_EQUALS(copy.detectorIDs(1), (std::vector<detid_t>{1}));
TS_ASSERT_EQUALS(copy.detectorIDs(2), (std::vector<detid_t>{2, 3}));
// Changing data in workspace affects indexInfo, but not copy
ws.getSpectrum(0).setSpectrumNo(7);
ws.getSpectrum(0).addDetectorID(7);
TS_ASSERT_EQUALS(indexInfo.spectrumNumber(0), 7);
TS_ASSERT_EQUALS(indexInfo.detectorIDs(0), (std::vector<detid_t>{0, 7}));
TS_ASSERT_EQUALS(copy.spectrumNumber(0), 2);
TS_ASSERT_EQUALS(copy.detectorIDs(0), (std::vector<detid_t>{0}));
}
void test_setIndexInfo_shares_spectrumDefinition() {
WorkspaceTester ws;
ws.initialize(3, 1, 1);
IndexInfo indices(3);
indices.setSpectrumNumbers({2, 4, 6});
indices.setDetectorIDs({{0}, {1}, {2, 3}});
auto defs = Kernel::make_cow<std::vector<SpectrumDefinition>>(3);
TS_ASSERT_THROWS_NOTHING(indices.setSpectrumDefinitions(defs));
TS_ASSERT_THROWS_NOTHING(ws.setIndexInfo(std::move(indices)));
TS_ASSERT_EQUALS(ws.indexInfo().spectrumDefinitions().get(), defs.get());
}
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
const auto &spectrumInfo = workspace->spectrumInfo();
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);
TS_ASSERT(spectrumInfo.hasDetectors(i));
TS_ASSERT_EQUALS(spectrumInfo.isMasked(i), false);
Gigg, Martyn Anthony
committed
}
// Mask a spectra
workspace->getSpectrum(1).clearData();
workspace->getSpectrum(2).clearData();
workspace->mutableSpectrumInfo().setMasked(1, true);
workspace->mutableSpectrumInfo().setMasked(2, true);
Gigg, Martyn Anthony
committed
const auto &spectrumInfo2 = workspace->spectrumInfo();
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);
TS_ASSERT(spectrumInfo2.hasDetectors(i));
TS_ASSERT_EQUALS(spectrumInfo2.isMasked(i), expectedMasked);
Gigg, Martyn Anthony
committed
}
}
void testWholeSpectraMasking_SpectrumInfo() {
// Workspace has 3 spectra, each 1 in length
const int numHist(3);
auto workspace = makeWorkspaceWithDetectors(numHist, 1);
workspace->getSpectrum(1).clearData();
workspace->getSpectrum(2).clearData();
workspace->mutableSpectrumInfo().setMasked(1, true);
workspace->mutableSpectrumInfo().setMasked(2, true);
const auto &spectrumInfo = workspace->spectrumInfo();
for (int i = 0; i < numHist; ++i) {
bool expectedMasked(false);
if (i == 0) {
expectedMasked = false;
} else {
expectedMasked = true;
}
TS_ASSERT_EQUALS(spectrumInfo.isMasked(i), expectedMasked);
}
}
void test_spectrumInfo_works_unthreaded() {
const int numHist(3);
auto workspace = makeWorkspaceWithDetectors(numHist, 1);
std::atomic<bool> parallelException{false};
for (int i = 0; i < numHist; ++i) {
try {
static_cast<void>(workspace->spectrumInfo());
} catch (...) {
parallelException = true;
}
}
TS_ASSERT(!parallelException);
}
void test_spectrumInfo_works_threaded() {
const int numHist(3);
auto workspace = makeWorkspaceWithDetectors(numHist, 1);
std::vector<const SpectrumInfo *> spectrumInfos(numHist);
std::atomic<bool> parallelException{false};
PARALLEL_FOR_IF(Kernel::threadSafe(*workspace))
for (int i = 0; i < numHist; ++i) {
try {
spectrumInfos[i] = &(workspace->spectrumInfo());
} catch (...) {
parallelException = true;
}
}
TS_ASSERT(!parallelException);
for (int i = 0; i < numHist; ++i)
TS_ASSERT_EQUALS(spectrumInfos[0], spectrumInfos[i]);
}
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
}
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
void testBinIndexOfDescendingBinning() {
WorkspaceTester wkspace;
wkspace.initialize(1, 4, 3);
wkspace.dataX(0)[0] = 5.3;
wkspace.dataX(0)[1] = 4.3;
wkspace.dataX(0)[2] = 3.3;
wkspace.dataX(0)[3] = 2.3;
TS_ASSERT_EQUALS(wkspace.getNumberHistograms(), 1);
// First boundary
TS_ASSERT_EQUALS(wkspace.binIndexOf(5.3), 0)
// First bin
TS_ASSERT_EQUALS(wkspace.binIndexOf(5.2), 0);
// Bin boundary
TS_ASSERT_EQUALS(wkspace.binIndexOf(4.3), 0);
// Mid range
TS_ASSERT_EQUALS(wkspace.binIndexOf(3.8), 1);
// Still second bin
TS_ASSERT_EQUALS(wkspace.binIndexOf(std::nextafter(3.3, 10.0)), 1);
// Last bin
TS_ASSERT_EQUALS(wkspace.binIndexOf(3.1), 2);
// Last value
TS_ASSERT_EQUALS(wkspace.binIndexOf(2.3), 2);
// 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);
// Bad X values
TS_ASSERT_THROWS(wkspace.binIndexOf(std::nextafter(5.3, 10.0)),
std::out_of_range);
TS_ASSERT_THROWS(wkspace.binIndexOf(5.4), std::out_of_range);
TS_ASSERT_THROWS(wkspace.binIndexOf(std::nextafter(2.3, 0.0)),
std::out_of_range);
TS_ASSERT_THROWS(wkspace.binIndexOf(0.), std::out_of_range);
}
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_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() {
auto map = ws.getSpectrumToWorkspaceIndexMap();
TS_ASSERT_EQUALS(0, map[1]);
TS_ASSERT_EQUALS(1, map[2]);
TS_ASSERT_EQUALS(map.size(), 2);
// 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");
// 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->setInstrument(inst);
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())
ws.initialize(1, 4, 3);
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);