Newer
Older
#ifndef MANTID_DATAOBJECTS_WORKSPACECREATIONTEST_H_
#define MANTID_DATAOBJECTS_WORKSPACECREATIONTEST_H_
#include <cxxtest/TestSuite.h>
#include "MantidDataObjects/SpecialWorkspace2D.h"
#include "MantidDataObjects/WorkspaceCreation.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidIndexing/IndexInfo.h"
#include "MantidParallel/Communicator.h"
#include "MantidParallel/StorageMode.h"
#ifdef MPI_EXPERIMENTAL
#include "MantidParallel/ParallelRunner.h"
#endif
#include "MantidTypes/SpectrumDefinition.h"
#include "MantidTestHelpers/ComponentCreationHelper.h"
using namespace Mantid;
using namespace API;
using namespace DataObjects;
using namespace HistogramData;
using namespace Indexing;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
namespace {
void run_create_partitioned(const Parallel::Communicator &comm) {
IndexInfo indices(47, Parallel::StorageMode::Distributed, comm);
indices.setSpectrumDefinitions(
std::vector<SpectrumDefinition>(indices.size()));
const auto ws = create<Workspace2D>(indices, Histogram(BinEdges{1, 2, 4}));
const auto &i = ws->indexInfo();
TS_ASSERT_EQUALS(i.globalSize(), 47);
size_t expectedSize = 0;
for (size_t globalIndex = 0; globalIndex < i.globalSize(); ++globalIndex) {
// Current default is RoundRobinPartitioner
if (static_cast<int>(globalIndex) % comm.size() == comm.rank()) {
TS_ASSERT_EQUALS(i.spectrumNumber(expectedSize),
static_cast<int>(globalIndex) + 1);
++expectedSize;
}
}
TS_ASSERT_EQUALS(i.size(), expectedSize);
}
void run_create_partitioned_with_instrument(
const Parallel::Communicator &comm,
boost::shared_ptr<Geometry::Instrument> instrument) {
IndexInfo indices(4, Parallel::StorageMode::Distributed, comm);
// should a nullptr spectrum definitions vector indicate building default
// defs?
// - same length -> build
// - different length -> fail (cannot create default mapping)
// same for setIndexInfo?
const auto ws =
create<Workspace2D>(instrument, indices, Histogram(BinEdges{1, 2, 4}));
const auto &i = ws->indexInfo();
TS_ASSERT_EQUALS(i.globalSize(), 4);
size_t expectedSize = 0;
for (size_t globalIndex = 0; globalIndex < i.globalSize(); ++globalIndex) {
// Current default is RoundRobinPartitioner
if (static_cast<int>(globalIndex) % comm.size() == comm.rank()) {
TS_ASSERT_EQUALS(i.spectrumNumber(expectedSize),
static_cast<int>(globalIndex) + 1);
++expectedSize;
}
}
TS_ASSERT_EQUALS(i.size(), expectedSize);
}
void run_indexInfo_legacy_compatibility_partitioned_workspace_failure(
const Parallel::Communicator &comm) {
IndexInfo indices(3, Parallel::StorageMode::Distributed, comm);
indices.setSpectrumDefinitions(
std::vector<SpectrumDefinition>(indices.size()));
const auto ws = create<Workspace2D>(indices, Histogram(BinEdges{1, 2}));
ws->getSpectrum(0).setSpectrumNo(7);
if (comm.size() > 1) {
TS_ASSERT_THROWS(ws->indexInfo(), std::runtime_error);
} else {
TS_ASSERT_THROWS_NOTHING(ws->indexInfo());
}
}
}
class WorkspaceCreationTest : 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 WorkspaceCreationTest *createSuite() {
return new WorkspaceCreationTest();
}
static void destroySuite(WorkspaceCreationTest *suite) { delete suite; }
WorkspaceCreationTest() {
// 1 bank, 2x2 pixels, IDs 4,5,6,7
m_instrument =
ComponentCreationHelper::createTestInstrumentRectangular(1, 2);
}
IndexInfo make_indices() {
IndexInfo indices(2);
indices.setSpectrumNumbers({2, 4});
std::vector<SpectrumDefinition> specDefs(2);
specDefs[0].add(0);
specDefs[1].add(2);
specDefs[1].add(3);
indices.setSpectrumDefinitions(specDefs);
return indices;
}
IndexInfo make_indices_no_detectors() {
IndexInfo indices(2);
indices.setSpectrumNumbers({2, 4});
indices.setSpectrumDefinitions(std::vector<SpectrumDefinition>(2));
return indices;
}
Histogram make_data() {
BinEdges edges{1, 2, 4};
Counts counts{3.0, 5.0};
CountStandardDeviations deviations{2.0, 4.0};
return Histogram{edges, counts, deviations};
}
void check_size(const MatrixWorkspace &ws) {
TS_ASSERT_EQUALS(ws.getNumberHistograms(), 2);
}
void check_default_indices(const MatrixWorkspace &ws) {
check_size(ws);
TS_ASSERT_EQUALS(ws.getSpectrum(0).getSpectrumNo(), 1);
TS_ASSERT_EQUALS(ws.getSpectrum(1).getSpectrumNo(), 2);
TS_ASSERT_EQUALS(ws.getSpectrum(0).getDetectorIDs(),
(std::set<detid_t>{1}));
TS_ASSERT_EQUALS(ws.getSpectrum(1).getDetectorIDs(),
(std::set<detid_t>{2}));
}
void check_indices(const MatrixWorkspace &ws) {
check_size(ws);
TS_ASSERT_EQUALS(ws.getSpectrum(0).getSpectrumNo(), 2);
TS_ASSERT_EQUALS(ws.getSpectrum(1).getSpectrumNo(), 4);
TS_ASSERT_EQUALS(ws.getSpectrum(0).getDetectorIDs(),
(std::set<detid_t>{4}));
TS_ASSERT_EQUALS(ws.getSpectrum(1).getDetectorIDs(),
(std::set<detid_t>{6, 7}));
}
void check_indices_no_detectors(const MatrixWorkspace &ws) {
check_size(ws);
TS_ASSERT_EQUALS(ws.getSpectrum(0).getSpectrumNo(), 2);
TS_ASSERT_EQUALS(ws.getSpectrum(1).getSpectrumNo(), 4);
TS_ASSERT_EQUALS(ws.getSpectrum(0).getDetectorIDs(), (std::set<detid_t>{}));
TS_ASSERT_EQUALS(ws.getSpectrum(1).getDetectorIDs(), (std::set<detid_t>{}));
void check_zeroed_data(const MatrixWorkspace &ws) {
TS_ASSERT_EQUALS(ws.x(0).rawData(), std::vector<double>({1, 2, 4}));
TS_ASSERT_EQUALS(ws.x(1).rawData(), std::vector<double>({1, 2, 4}));
TS_ASSERT_EQUALS(ws.y(0).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws.y(1).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws.e(0).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws.e(1).rawData(), std::vector<double>({0, 0}));
}
void check_instrument(const MatrixWorkspace &ws) {
TS_ASSERT_EQUALS(ws.getInstrument()->baseInstrument(), m_instrument);
}
void check_data(const MatrixWorkspace &ws) {
TS_ASSERT_EQUALS(ws.x(0).rawData(), std::vector<double>({1, 2, 4}));
TS_ASSERT_EQUALS(ws.x(1).rawData(), std::vector<double>({1, 2, 4}));
TS_ASSERT_EQUALS(ws.y(0).rawData(), std::vector<double>({3, 5}));
TS_ASSERT_EQUALS(ws.y(1).rawData(), std::vector<double>({3, 5}));
TS_ASSERT_EQUALS(ws.e(0).rawData(), std::vector<double>({2, 4}));
TS_ASSERT_EQUALS(ws.e(1).rawData(), std::vector<double>({2, 4}));
}
void test_create_size_Histogram() {
const auto ws = create<Workspace2D>(2, Histogram(BinEdges{1, 2, 4}));
check_default_indices(*ws);
check_zeroed_data(*ws);
void test_create_size_fully_specified_Histogram() {
std::unique_ptr<Workspace2D> ws;
TS_ASSERT_THROWS_NOTHING(ws = create<Workspace2D>(2, make_data()))
check_data(*ws);
}
void test_create_parent_size_fully_specified_Histogram() {
const auto parent = create<Workspace2D>(make_indices_no_detectors(),
Histogram(BinEdges{-1, 0, 2}));
std::unique_ptr<Workspace2D> ws;
TS_ASSERT_THROWS_NOTHING(ws = create<Workspace2D>(*parent, 2, make_data()))
check_indices_no_detectors(*ws);
check_data(*ws);
}
void test_create_IndexInfo_Histogram() {
const auto ws = create<Workspace2D>(make_indices_no_detectors(),
Histogram(BinEdges{1, 2, 4}));
check_indices_no_detectors(*ws);
void test_create_bad_IndexInfo_Histogram_no_instrument() {
// No instrument, so spectrum definitions created by make_indices are bad.
TS_ASSERT_THROWS(
create<Workspace2D>(make_indices(), Histogram(BinEdges{1, 2, 4})),
void test_create_Instrument_size_Histogram() {
create<Workspace2D>(m_instrument, 2, Histogram(BinEdges{1, 2, 4}));
check_default_indices(*ws);
check_instrument(*ws);
}
void test_create_Instrument_IndexInfo_Histogram() {
const auto ws = create<Workspace2D>(m_instrument, make_indices(),
Histogram(BinEdges{1, 2, 4}));
check_indices(*ws);
check_zeroed_data(*ws);
check_instrument(*ws);
}
void test_create_parent() {
const auto parent = create<Workspace2D>(m_instrument, make_indices(),
Histogram(BinEdges{1, 2, 4}));
const auto ws = create<Workspace2D>(*parent);
check_indices(*ws);
check_zeroed_data(*ws);
check_instrument(*ws);
void test_create_parent_varying_bins() {
auto parent = create<Workspace2D>(make_indices_no_detectors(), make_data());
const double binShift = -0.54;
parent->mutableX(1) += binShift;
const auto ws = create<Workspace2D>(*parent);
check_indices_no_detectors(*ws);
TS_ASSERT_EQUALS(ws->x(0).rawData(), std::vector<double>({1, 2, 4}));
TS_ASSERT_EQUALS(
ws->x(1).rawData(),
std::vector<double>({1 + binShift, 2 + binShift, 4 + binShift}));
TS_ASSERT_EQUALS(ws->y(0).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws->y(1).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws->e(0).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws->e(1).rawData(), std::vector<double>({0, 0}));
}
void test_create_parent_varying_bins_from_event() {
auto parent =
create<EventWorkspace>(make_indices_no_detectors(), BinEdges{1, 2, 4});
const double binShift = -0.54;
parent->mutableX(1) += binShift;
const auto ws = create<EventWorkspace>(*parent);
check_indices_no_detectors(*ws);
TS_ASSERT_EQUALS(ws->x(0).rawData(), std::vector<double>({1, 2, 4}));
TS_ASSERT_EQUALS(
ws->x(1).rawData(),
std::vector<double>({1 + binShift, 2 + binShift, 4 + binShift}));
TS_ASSERT_EQUALS(ws->y(0).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws->y(1).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws->e(0).rawData(), std::vector<double>({0, 0}));
TS_ASSERT_EQUALS(ws->e(1).rawData(), std::vector<double>({0, 0}));
}
void test_create_parent_Histogram() {
const auto parent = create<Workspace2D>(m_instrument, make_indices(),
Histogram(BinEdges{0, 1}));
const auto ws = create<Workspace2D>(*parent, Histogram(BinEdges{1, 2, 4}));
check_indices(*ws);
check_zeroed_data(*ws);
check_instrument(*ws);
}
void test_create_parent_same_size() {
const auto parent = create<Workspace2D>(m_instrument, make_indices(),
Histogram(BinEdges{1, 2, 4}));
const auto ws = create<Workspace2D>(*parent, 2, parent->histogram(0));
// Same size -> Indices copied from parent
check_indices(*ws);
check_zeroed_data(*ws);
check_instrument(*ws);
}
void test_create_parent_size() {
const auto parent = create<Workspace2D>(3, Histogram(BinEdges{1, 2, 4}));
parent->getSpectrum(0).setSpectrumNo(7);
const auto ws = create<Workspace2D>(*parent, 2, parent->histogram(0));
check_default_indices(*ws);
check_zeroed_data(*ws);
}
void test_create_parent_IndexInfo_same_size() {
const auto parent = create<Workspace2D>(2, Histogram(BinEdges{1, 2, 4}));
const auto ws = create<Workspace2D>(*parent, make_indices_no_detectors(),
parent->histogram(0));
// If parent has same size, data in IndexInfo is ignored
check_default_indices(*ws);
check_zeroed_data(*ws);
void test_create_parent_bad_IndexInfo_no_instrument() {
const auto parent = create<Workspace2D>(3, Histogram(BinEdges{1, 2, 4}));
// parent has no instrument set, so spectrum definitions created by
// make_indices are bad.
TS_ASSERT_THROWS(
create<Workspace2D>(*parent, make_indices(), (BinEdges{1, 2, 4})),
std::invalid_argument);
void test_create_parent_IndexInfo() {
const auto parent =
create<Workspace2D>(m_instrument, 3, Histogram(BinEdges{1, 2, 4}));
const auto ws =
create<Workspace2D>(*parent, make_indices(), parent->histogram(0));
check_indices(*ws);
check_zeroed_data(*ws);
void test_create_parent_size_edges_from_event() {
const auto parent = create<EventWorkspace>(make_indices_no_detectors(),
Histogram(BinEdges{1, 2, 4}));
std::unique_ptr<EventWorkspace> ws;
ws = create<EventWorkspace>(*parent, 2, parent->binEdges(0)))
TS_ASSERT_EQUALS(ws->id(), "EventWorkspace");
check_indices_no_detectors(*ws);
check_zeroed_data(*ws);
void test_create_drop_events() {
auto eventWS = create<EventWorkspace>(1, Histogram(BinEdges(3)));
auto ws = create<HistoWorkspace>(*eventWS);
TS_ASSERT_EQUALS(ws->id(), "Workspace2D");
void test_EventWorkspace_MRU_is_empty() {
const auto ws1 = create<EventWorkspace>(1, Histogram(BinEdges(3)));
const auto ws2 = create<EventWorkspace>(*ws1, 1, Histogram(BinEdges(3)));
TS_ASSERT_EQUALS(ws2->MRUSize(), 0);
}
void test_create_from_more_derived() {
const auto parent = create<SpecialWorkspace2D>(2, Histogram(Points(1)));
const auto ws = create<Workspace2D>(*parent);
TS_ASSERT_EQUALS(ws->id(), "SpecialWorkspace2D");
}
void test_create_from_less_derived() {
const auto parent = create<Workspace2D>(2, Histogram(Points(1)));
const auto ws = create<SpecialWorkspace2D>(*parent);
TS_ASSERT_EQUALS(ws->id(), "SpecialWorkspace2D");
}
void test_create_event_from_histo() {
const auto parent = create<Workspace2D>(2, Histogram(BinEdges(2)));
const auto ws = create<EventWorkspace>(*parent);
TS_ASSERT_EQUALS(ws->id(), "EventWorkspace");
}
void test_create_event_from_event() {
const auto parent = create<Workspace2D>(2, Histogram(BinEdges{1, 2, 4}));
const auto ws = create<EventWorkspace>(*parent);
TS_ASSERT_EQUALS(ws->id(), "EventWorkspace");
check_zeroed_data(*ws);
}
void test_create_event_from_edges() {
std::unique_ptr<EventWorkspace> ws;
TS_ASSERT_THROWS_NOTHING(ws = create<EventWorkspace>(2, BinEdges{1, 2, 4}))
TS_ASSERT_EQUALS(ws->id(), "EventWorkspace");
check_zeroed_data(*ws);
void test_create_partitioned() {
run_create_partitioned(Parallel::Communicator{});
#ifdef MPI_EXPERIMENTAL
runParallel(run_create_partitioned);
#endif
void test_create_partitioned_with_instrument() {
run_create_partitioned_with_instrument(Parallel::Communicator{},
m_instrument);
#ifdef MPI_EXPERIMENTAL
runParallel(run_create_partitioned_with_instrument, m_instrument);
#endif
}
void test_indexInfo_legacy_compatibility_partitioned_workspace_failure() {
// Sibling of MatrixWorkspace::test_indexInfo_legacy_compatibility().
// Setting spectrum numbers via legacy interface should fail for partitioned
// workspace.
run_indexInfo_legacy_compatibility_partitioned_workspace_failure(
Parallel::Communicator{});
#ifdef MPI_EXPERIMENTAL
runParallel(
run_indexInfo_legacy_compatibility_partitioned_workspace_failure);
#endif
}
private:
boost::shared_ptr<Geometry::Instrument> m_instrument;
#endif /* MANTID_DATAOBJECTS_WORKSPACECREATIONTEST_H_ */