Mantid
Loading...
Searching...
No Matches
MDEventsTestHelper.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7/*********************************************************************************
8 * PLEASE READ THIS!!!!!!!
9 *
10 * This header MAY NOT be included in any test from a package below the level
11 *of
12 * DataObjects (e.g. Kernel, Geometry, API).
13 *********************************************************************************/
14#pragma once
15
24#include "MantidKernel/Utils.h"
26
27namespace {
28template <typename MDE, size_t nd>
29std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>> createOutputWorkspace(size_t splitInto) {
30 std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>> out(
32 Mantid::API::BoxController_sptr bc = out->getBoxController();
33 bc->setSplitThreshold(100);
34 bc->setSplitInto(splitInto);
35 return out;
36}
37
38template <typename MDE, size_t nd>
39void addMDDimensions(std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>> out, Mantid::coord_t min,
40 Mantid::coord_t max, const std::string &axisNameFormat, const std::string &axisIdFormat) {
41
42 // Create MDFrame of General Frame type
44
45 // Create dimensions
46 for (size_t d = 0; d < nd; d++) {
47 char name[200];
48 sprintf(name, axisNameFormat.c_str(), d);
49 char id[200];
50 sprintf(id, axisIdFormat.c_str(), d);
51
53 new Mantid::Geometry::MDHistoDimension(std::string(name), std::string(id), frame, min, max, 10));
54 out->addDimension(dim);
55 }
56 out->initialize();
57}
58
59template <typename MDE, size_t nd>
60void addMDDimensionsWithFrames(std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>> out, Mantid::coord_t min,
62 const std::string &axisNameFormat, const std::string &axisIdFormat) {
63 for (size_t d = 0; d < nd; d++) {
64 char name[200];
65 sprintf(name, axisNameFormat.c_str(), d);
66 char id[200];
67 sprintf(id, axisIdFormat.c_str(), d);
68
69 // Use the same frame for all dimensions
70 auto dim =
71 std::make_shared<Mantid::Geometry::MDHistoDimension>(std::string(name), std::string(id), frame, min, max, 10);
72 out->addDimension(dim);
73 }
74 out->initialize();
75}
76
77template <typename MDE, size_t nd>
78void addMDDimensionsWithIndividualFrames(std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>> out,
80 const std::vector<Mantid::Geometry::MDFrame_sptr> &frame,
81 const std::string &axisNameFormat, const std::string &axisIdFormat) {
82 for (size_t d = 0; d < nd; d++) {
83 char name[200];
84 sprintf(name, axisNameFormat.c_str(), d);
85 char id[200];
86 sprintf(id, axisIdFormat.c_str(), d);
87
88 // Use the same frame for all dimensions
89 auto dim = std::make_shared<Mantid::Geometry::MDHistoDimension>(std::string(name), std::string(id), *frame[d], min,
90 max, 10);
91 out->addDimension(dim);
92 }
93 out->initialize();
94}
95
96template <typename MDE, size_t nd>
97void addData(std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>> out, size_t splitInto, Mantid::coord_t min,
98 Mantid::coord_t max, size_t numEventsPerBox) {
99 if (numEventsPerBox > 0) {
100 out->splitBox();
101 size_t index[nd];
103 size_t index_max[nd];
104 Mantid::Kernel::Utils::NestedForLoop::SetUp(nd, index_max, splitInto);
105 bool allDone = false;
106 while (!allDone) {
107 for (size_t i = 0; i < numEventsPerBox; i++) {
108 // Put an event in the middle of each box
109 Mantid::coord_t centers[nd];
110 for (size_t d = 0; d < nd; d++)
111 centers[d] = min + (static_cast<Mantid::coord_t>(index[d]) + 0.5f) * (max - min) /
112 static_cast<Mantid::coord_t>(splitInto);
113 out->addEvent(MDE(1.0, 1.0, centers));
114 }
115
117 }
118 out->refreshCache();
119 }
121 out->addExperimentInfo(ei);
122}
123} // namespace
124
125namespace Mantid {
126namespace DataObjects {
127
133namespace MDEventsTestHelper {
134
142 int numBins = 160);
143
145MDEventWorkspace3Lean::sptr makeFakeMDEventWorkspace(const std::string &wsName, long numEvents = 10000,
147
149MDHistoWorkspace_sptr makeFakeMDHistoWorkspace(double signal, size_t numDims, size_t numBins = 10, coord_t max = 10.0,
150 double errorSquared = 1.0, const std::string &name = "",
151 double numEvents = 1.0);
152
154makeFakeMDHistoWorkspaceWithMDFrame(double signal, size_t numDims, const Mantid::Geometry::MDFrame &frame,
155 size_t numBins = 10, coord_t max = 10.0, double errorSquared = 1.0,
156 const std::string &name = "", double numEvents = 1.0);
157
160 double errorSquared, size_t *numBins,
161 coord_t *min, coord_t *max,
162 const std::string &name = "");
165makeFakeMDHistoWorkspaceGeneral(size_t numDims, double signal, double errorSquared, size_t *numBins, coord_t *min,
166 coord_t *max, std::vector<std::string> names, const std::string &name = "");
167
168//-------------------------------------------------------------------------------------
183template <typename MDE, size_t nd>
184std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>>
185makeAnyMDEW(size_t splitInto, coord_t min, coord_t max, size_t numEventsPerBox = 0, const std::string &wsName = "",
186 const std::string &axisNameFormat = "Axis%d", const std::string &axisIdFormat = "Axis%d") {
187 // Create bare workspace
188 auto out = createOutputWorkspace<MDE, nd>(splitInto);
189
190 // Add standard dimensions
191 addMDDimensions<MDE, nd>(out, min, max, axisNameFormat, axisIdFormat);
192
193 // Add data
194 addData<MDE, nd>(out, splitInto, min, max, numEventsPerBox);
195
196 // Add to ADS on option
197 if (!wsName.empty())
198 Mantid::API::AnalysisDataService::Instance().addOrReplace(wsName, out);
199
200 return out;
201}
202
219template <typename MDE, size_t nd>
220std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>>
222 std::vector<Mantid::Geometry::MDFrame_sptr> frames, size_t numEventsPerBox = 0,
223 const std::string &wsName = "", std::string axisNameFormat = "Axis%d",
224 std::string axisIdFormat = "Axis%d") {
225 // Create bare workspace
226 auto out = createOutputWorkspace<MDE, nd>(splitInto);
227
228 // Add standard dimensions
229 addMDDimensionsWithIndividualFrames<MDE, nd>(out, min, max, frames, axisNameFormat, axisIdFormat);
230
231 // Add data
232 addData<MDE, nd>(out, splitInto, min, max, numEventsPerBox);
233
234 // Add to ADS on option
235 if (!wsName.empty())
236 Mantid::API::AnalysisDataService::Instance().addOrReplace(wsName, out);
237
238 return out;
239}
240
258template <typename MDE, size_t nd>
259std::shared_ptr<Mantid::DataObjects::MDEventWorkspace<MDE, nd>>
260makeAnyMDEWWithFrames(size_t splitInto, coord_t min, coord_t max, const Mantid::Geometry::MDFrame &frame,
261 size_t numEventsPerBox = 0, const std::string &wsName = "",
262 const std::string &axisNameFormat = "Axis%d", const std::string &axisIdFormat = "Axis%d") {
263 // Create bare workspace
264 auto out = createOutputWorkspace<MDE, nd>(splitInto);
265
266 // Add standard dimensions
267 addMDDimensionsWithFrames<MDE, nd>(out, min, max, frame, axisNameFormat, axisIdFormat);
268
269 // Add data
270 addData<MDE, nd>(out, splitInto, min, max, numEventsPerBox);
271
272 // Add to ADS on option
273 if (!wsName.empty())
274 Mantid::API::AnalysisDataService::Instance().addOrReplace(wsName, out);
275
276 return out;
277}
278
280template <size_t nd>
281std::shared_ptr<MDEventWorkspace<MDLeanEvent<nd>, nd>> makeMDEW(size_t splitInto, coord_t min, coord_t max,
282 size_t numEventsPerBox = 0) {
283 return makeAnyMDEW<MDLeanEvent<nd>, nd>(splitInto, min, max, numEventsPerBox);
284}
285
287template <size_t nd>
288std::shared_ptr<MDEventWorkspace<MDLeanEvent<nd>, nd>> makeMDEWWithFrames(size_t splitInto, coord_t min, coord_t max,
289 const Mantid::Geometry::MDFrame &frame,
290 size_t numEventsPerBox = 0) {
291 return makeAnyMDEWWithFrames<MDLeanEvent<nd>, nd>(splitInto, min, max, frame, numEventsPerBox);
292}
293
295template <size_t nd>
296std::shared_ptr<MDEventWorkspace<MDLeanEvent<nd>, nd>>
298 const std::vector<Mantid::Geometry::MDFrame_sptr> &frame, size_t numEventsPerBox = 0) {
299 return makeAnyMDEWWithIndividualFrames<MDLeanEvent<nd>, nd>(splitInto, min, max, frame, numEventsPerBox);
300}
301
304template <size_t nd>
305std::shared_ptr<MDEventWorkspace<MDEvent<nd>, nd>> makeMDEWFull(size_t splitInto, coord_t min, coord_t max,
306 size_t numEventsPerBox = 0) {
307 return makeAnyMDEW<MDEvent<nd>, nd>(splitInto, min, max, numEventsPerBox);
308}
309
310//=====================================================================================
311//=============================== MDGRIDBOX HELPER METHODS
312//============================
313//=====================================================================================
314
316MDBox<MDLeanEvent<1>, 1> *makeMDBox1(size_t splitInto = 10, API::BoxController *splitter = nullptr);
317
320
323std::vector<MDLeanEvent<1>> makeMDEvents1(size_t num);
324
325// The makeMDGridBox method makes a unique_ptr to an MDBox, passes the raw pointer to
326// another MBBox, then as the unique_ptr goes out of scope the first MDBox will be
327// deleted, potentially leaving a dangling pointer. However it seems to work, and it's
328// only used in tests. Would be good to fix this though.
329GNU_DIAG_OFF("array-bounds")
330
331//-------------------------------------------------------------------------------------
341template <size_t nd>
342static MDGridBox<MDLeanEvent<nd>, nd> *makeMDGridBox(size_t split0 = 10, size_t split1 = 10, coord_t dimensionMin = 0.0,
343 coord_t dimensionMax = 10.0) {
344 // Split at 5 events
345 auto splitter = new Mantid::API::BoxController(nd);
346 splitter->setSplitThreshold(5);
347 // Splits into 10x10x.. boxes
348 splitter->setSplitInto(split0);
349 splitter->setSplitInto(0, split0);
350 if (nd > 1)
351 splitter->setSplitInto(1, split1);
352 // Set the size to 10.0 in all directions
353 auto box = std::make_unique<MDBox<MDLeanEvent<nd>, nd>>(splitter);
354 for (size_t d = 0; d < nd; d++)
355 // carefull! function with the side effects!
356 box->setExtents(d, dimensionMin, dimensionMax);
357 // calc volume necessary
358 box->calcVolume();
359
360 // Split
361 auto out = new MDGridBox<MDLeanEvent<nd>, nd>(box.get());
362 return out;
363}
364
365GNU_DIAG_ON("array-bounds")
366
367//-------------------------------------------------------------------------------------
377template <size_t nd>
378static void feedMDBox(MDBoxBase<MDLeanEvent<nd>, nd> *box, size_t repeat = 1, size_t numPerSide = 10,
379 coord_t start = 0.5, coord_t step = 1.0) {
380 size_t counters[nd];
382 size_t index_max[nd];
383 Mantid::Kernel::Utils::NestedForLoop::SetUp(nd, index_max, numPerSide);
384 // Recursive for loop
385 bool allDone = false;
386 while (!allDone) {
387 // Generate the position from the counter
388 coord_t centers[nd];
389 for (size_t d = 0; d < nd; d++)
390 centers[d] = static_cast<coord_t>(counters[d]) * step + start;
391
392 // Add that event 'repeat' times
393 for (size_t i = 0; i < repeat; ++i)
394 box->addEvent(MDLeanEvent<nd>(1.0, 1.0, centers));
395
396 // Increment the nested for loop
397 allDone = Mantid::Kernel::Utils::NestedForLoop::Increment(nd, counters, index_max);
398 }
399 box->refreshCache(nullptr);
400}
401
402//-------------------------------------------------------------------------------------
409template <size_t nd>
410static void recurseSplit(MDGridBox<MDLeanEvent<nd>, nd> *box, size_t atRecurseLevel, size_t recurseLimit) {
411 using boxVector = std::vector<MDBoxBase<MDLeanEvent<nd>, nd> *>;
412 if (atRecurseLevel >= recurseLimit)
413 return;
414
415 // Split all the contents
416 boxVector boxes;
417 boxes = box->getBoxes();
418 for (size_t i = 0; i < boxes.size(); i++)
419 box->splitContents(i);
420
421 // Retrieve the contained MDGridBoxes
422 boxes = box->getBoxes();
423
424 // Go through them and split them
425 for (size_t i = 0; i < boxes.size(); i++) {
426 MDGridBox<MDLeanEvent<nd>, nd> *containedbox = dynamic_cast<MDGridBox<MDLeanEvent<nd>, nd> *>(boxes[i]);
427 if (containedbox)
428 recurseSplit(containedbox, atRecurseLevel + 1, recurseLimit);
429 }
430}
431
432//-------------------------------------------------------------------------------------
440template <size_t nd> static MDGridBox<MDLeanEvent<nd>, nd> *makeRecursiveMDGridBox(size_t splitInto, size_t levels) {
441 // Split at 5 events
442 auto splitter(new Mantid::API::BoxController(nd));
443 splitter->setSplitThreshold(5);
444 splitter->resetNumBoxes();
445 splitter->setMaxDepth(levels + 1);
446 // Splits into splitInto x splitInto x ... boxes
447 splitter->setSplitInto(splitInto);
448 // Set the size to splitInto*1.0 in all directions
449 auto box = std::make_unique<MDBox<MDLeanEvent<nd>, nd>>(splitter);
450 for (size_t d = 0; d < nd; d++)
451 box->setExtents(d, 0.0, static_cast<coord_t>(splitInto));
452 // Split into the gridbox.
453 auto gridbox = new MDGridBox<MDLeanEvent<nd>, nd>(box.get());
454 // Now recursively split more
455 recurseSplit(gridbox, 0, levels);
456
457 return gridbox;
458}
459
460//-------------------------------------------------------------------------------------
462template <typename MDBOX> static void extents_match(MDBOX box, size_t dim, double min, double max) {
463 TSM_ASSERT_DELTA(dim, box->getExtents(dim).getMin(), min, 1e-6);
464 TSM_ASSERT_DELTA(dim, box->getExtents(dim).getMax(), max, 1e-6);
465}
466
467void checkAndDeleteFile(const std::string &filename);
468
469//=====================================================================================
470//===================================== TEST METHODS
471//==================================
472//=====================================================================================
473
474} // namespace MDEventsTestHelper
475} // namespace DataObjects
476} // namespace Mantid
std::string name
Definition Run.cpp:60
std::map< DeltaEMode::Type, std::string > index
#define GNU_DIAG_ON(x)
#define GNU_DIAG_OFF(x)
This is a collection of macros for turning compiler warnings off in a controlled manner.
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
This class is shared by a few Workspace types and holds information related to a particular experimen...
Templated super-class of a multi-dimensional event "box".
Definition MDBoxBase.h:50
Templated class for a multi-dimensional event "box".
Definition MDBox.h:45
Templated class for the multi-dimensional event workspace.
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
Templated class for a GRIDDED multi-dimensional event "box".
Definition MDGridBox.h:42
Templated class holding data about a neutron detection event in N-dimensions (for example,...
Definition MDLeanEvent.h:60
GeneralFrame : Any MDFrame that isn't related to momemtum transfer.
static const std::string GeneralFrameDistance
MDFrame : The coordinate frame for a dimension, or set of dimensions in a multidimensional workspace.
Definition MDFrame.h:22
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
std::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const Nexus::NexusDescriptor &descriptor)
Get the number of events in the currently opened group.
MDBox< MDLeanEvent< 1 >, 1 > * makeMDBox1(size_t splitInto=10, API::BoxController *splitter=nullptr)
Generate an empty MDBox.
std::shared_ptr< MDEventWorkspace< MDEvent< nd >, nd > > makeMDEWFull(size_t splitInto, coord_t min, coord_t max, size_t numEventsPerBox=0)
Make a MDEventWorkspace with MDEvents - updated to split dims by splitInto, not 10.
static void feedMDBox(MDBoxBase< MDLeanEvent< nd >, nd > *box, size_t repeat=1, size_t numPerSide=10, coord_t start=0.5, coord_t step=1.0)
Feed a MDGridBox with evenly-spaced events.
Mantid::DataObjects::EventWorkspace_sptr createDiffractionEventWorkspace(int numEvents, int numPixels=400, int numBins=160)
Create an EventWorkspace containing fake data of single-crystal diffraction.
MDHistoWorkspace_sptr makeFakeMDHistoWorkspace(double signal, size_t numDims, size_t numBins=10, coord_t max=10.0, double errorSquared=1.0, const std::string &name="", double numEvents=1.0)
Make a fake n-dimensional MDHistoWorkspace.
std::vector< MDLeanEvent< 1 > > makeMDEvents1(size_t num)
Return a vector with this many MDEvents, spaced evenly from 0.5, 1.5, etc.
Mantid::DataObjects::MDHistoWorkspace_sptr makeFakeMDHistoWorkspaceGeneral(size_t numDims, double signal, double errorSquared, size_t *numBins, coord_t *min, coord_t *max, const std::string &name="")
More general fake n-dimensionsal MDHistoWorkspace.
std::shared_ptr< MDEventWorkspace< MDLeanEvent< nd >, nd > > makeMDEW(size_t splitInto, coord_t min, coord_t max, size_t numEventsPerBox=0)
Make a MDEventWorkspace with MDLeanEvents.
std::shared_ptr< Mantid::DataObjects::MDEventWorkspace< MDE, nd > > makeAnyMDEWWithIndividualFrames(size_t splitInto, coord_t min, coord_t max, std::vector< Mantid::Geometry::MDFrame_sptr > frames, size_t numEventsPerBox=0, const std::string &wsName="", std::string axisNameFormat="Axis%d", std::string axisIdFormat="Axis%d")
Create a test MDEventWorkspace<nd> .
std::shared_ptr< MDEventWorkspace< MDLeanEvent< nd >, nd > > makeMDEWWithFrames(size_t splitInto, coord_t min, coord_t max, const Mantid::Geometry::MDFrame &frame, size_t numEventsPerBox=0)
Make a MDEventWorkspace with MDLeanEvents nad MDFrames.
MDBox< MDLeanEvent< 3 >, 3 > * makeMDBox3()
Generate an empty MDBox with 3 dimensions, split 10x5x2.
std::shared_ptr< Mantid::DataObjects::MDEventWorkspace< MDE, nd > > makeAnyMDEW(size_t splitInto, coord_t min, coord_t max, size_t numEventsPerBox=0, const std::string &wsName="", const std::string &axisNameFormat="Axis%d", const std::string &axisIdFormat="Axis%d")
Create a test MDEventWorkspace<nd> .
static MDGridBox< MDLeanEvent< nd >, nd > * makeRecursiveMDGridBox(size_t splitInto, size_t levels)
Generate a recursively gridded MDGridBox.
void checkAndDeleteFile(const std::string &filename)
Delete a file from disk.
std::shared_ptr< MDEventWorkspace< MDLeanEvent< nd >, nd > > makeMDEWWithIndividualFrames(size_t splitInto, coord_t min, coord_t max, const std::vector< Mantid::Geometry::MDFrame_sptr > &frame, size_t numEventsPerBox=0)
Make a MDEventWorkspace with MDLeanEvents and individual MDFrames.
std::shared_ptr< Mantid::DataObjects::MDEventWorkspace< MDE, nd > > makeAnyMDEWWithFrames(size_t splitInto, coord_t min, coord_t max, const Mantid::Geometry::MDFrame &frame, size_t numEventsPerBox=0, const std::string &wsName="", const std::string &axisNameFormat="Axis%d", const std::string &axisIdFormat="Axis%d")
Create a test MDEventWorkspace<nd> .
static void recurseSplit(MDGridBox< MDLeanEvent< nd >, nd > *box, size_t atRecurseLevel, size_t recurseLimit)
Recursively split an existing MDGridBox.
MDEventWorkspace3Lean::sptr makeFakeMDEventWorkspace(const std::string &wsName, long numEvents=10000, Kernel::SpecialCoordinateSystem coord=Kernel::None)
Make a (optionally) file backed MDEventWorkspace with 10000 fake random data points.
static MDGridBox< MDLeanEvent< nd >, nd > * makeMDGridBox(size_t split0=10, size_t split1=10, coord_t dimensionMin=0.0, coord_t dimensionMax=10.0)
Generate an empty MDBox with 2 dimensions, splitting in (default) 10x10 boxes.
static void extents_match(MDBOX box, size_t dim, double min, double max)
Helper function compares the extents of the given box.
Mantid::DataObjects::MDHistoWorkspace_sptr makeFakeMDHistoWorkspaceWithMDFrame(double signal, size_t numDims, const Mantid::Geometry::MDFrame &frame, size_t numBins=10, coord_t max=10.0, double errorSquared=1.0, const std::string &name="", double numEvents=1.0)
Creates a fake MDHistoWorkspace with MDFrame selection.
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::shared_ptr< MDHistoDimension > MDHistoDimension_sptr
Shared pointer to a MDHistoDimension.
bool Increment(const size_t numDims, size_t *index, const size_t *index_max, const size_t *index_min)
Utility function for performing arbitrarily nested for loops in a serial way.
Definition Utils.h:165
void SetUp(const size_t numDims, size_t *out, const size_t value=0)
Set up a nested for loop by setting an array of counters.
Definition Utils.h:82
SpecialCoordinateSystem
Special coordinate systems for Q3D.
DataObjects::MDLeanEvent< 3 > MDE
Our MDLeanEvent dimension.
Helper class which provides the Collimation Length for SANS instruments.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27