Mantid
Loading...
Searching...
No Matches
CompareMDWorkspaces.cpp
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 +
14#include <sstream>
15#include <utility>
16
17using namespace Mantid::Kernel;
18using namespace Mantid::API;
19using namespace Mantid::DataObjects;
20using namespace Mantid::Geometry;
21
22//=============================================================================
26class CompareFailsException : public std::runtime_error {
27public:
28 explicit CompareFailsException(const std::string &msg) : std::runtime_error(msg) {}
29 std::string getMessage() const { return this->what(); }
30};
31
32namespace Mantid::MDAlgorithms {
33
35
36private:
37 std::vector<float> mCoordinates;
38 float mSignal;
39 float mError;
40
41public:
43 static float s_tolerance;
44 // static float s_tolerance {static_cast<float>(1E-7)};
45
46 SimpleMDEvent(std::vector<float> coordinates, const float &signal, const float &error)
47 : mCoordinates(std::move(coordinates)), mSignal(signal), mError(error) {}
48
49 SimpleMDEvent(const SimpleMDEvent &other) = default;
50
51 // pretty output
52 std::string str() const {
53 std::stringstream ss;
54 size_t numdirs = mCoordinates.size();
55 for (size_t i = 0; i < numdirs; ++i)
56 ss << mCoordinates[i] << ", ";
57 ss << "signal = " << mSignal << ", error = " << mError;
58
59 return ss.str();
60 }
61
62 float getCenter(size_t dim) const { return mCoordinates[dim]; }
63
64 float getSignal() const { return mSignal; }
65
66 float getError() const { return mError; }
67
68 bool operator()(const SimpleMDEvent &event1, const SimpleMDEvent &event2) const { return event1 < event2; }
69
78 bool operator<(const SimpleMDEvent &event2) const {
79
80 bool less(true);
81 bool equal(false);
82
83 // compare coordinates
84 size_t numdirs = mCoordinates.size();
85 for (size_t i = 0; i < numdirs; ++i) {
86 // equal is hard to tell
87 coord_t diff = mCoordinates[i] - event2.mCoordinates[i];
88
89 if (fabs(mCoordinates[i]) > s_tolerance && fabs(diff / mCoordinates[i]) < s_tolerance * 10.) {
90 // larger than epsilon and relative difference less than epsilon
91 equal = true;
92 less = false;
93 } else if (fabs(mCoordinates[i]) < s_tolerance && fabs(diff) < s_tolerance) {
94 // less than epsilon and absolute difference less than epsilon
95 equal = true;
96 less = false;
97 } else if (diff < 0) {
98 // less
99 less = true;
100 } else {
101 // larger
102 less = false;
103 }
104
105 // no need to continue
106 if (!equal)
107 break;
108 }
109
110 // signal
111 if (equal && mSignal < event2.mSignal) {
112 less = true;
113 equal = false;
114 } else if (equal && mSignal > event2.mSignal) {
115 less = false;
116 equal = false;
117 }
118
119 // error: no need to continue the comparison
120 if (equal && mError >= event2.mError) {
121 less = false;
122 }
123
124 return less;
125 }
126
128 // coordiate
129 size_t numdirs = mCoordinates.size();
130 for (size_t i = 0; i < numdirs; ++i)
131 mCoordinates[i] = event2.mCoordinates[i];
132 // signal and error
133 mSignal = event2.mSignal;
134 mError = event2.mError;
135
136 return *this;
137 }
138};
139
140float SimpleMDEvent::s_tolerance(static_cast<float>(1E-7));
141
142//----------------------------------------------------------------------------------------------
143bool compareSimpleEvents(const SimpleMDEvent &self, const SimpleMDEvent &other) { return self < other; }
144
145// Register the algorithm into the AlgorithmFactory
146DECLARE_ALGORITHM(CompareMDWorkspaces)
147
148//----------------------------------------------------------------------------------------------
150const std::string CompareMDWorkspaces::name() const { return "CompareMDWorkspaces"; }
151
153int CompareMDWorkspaces::version() const { return 1; }
154
156const std::string CompareMDWorkspaces::category() const { return "MDAlgorithms\\Utility\\Workspaces"; }
157
158//----------------------------------------------------------------------------------------------
162 declareProperty(std::make_unique<WorkspaceProperty<IMDWorkspace>>("Workspace1", "", Direction::Input),
163 "First MDWorkspace to compare.");
164 declareProperty(std::make_unique<WorkspaceProperty<IMDWorkspace>>("Workspace2", "", Direction::Input),
165 "Second MDWorkspace to compare.");
166
167 declareProperty("Tolerance", 0.0, "The maximum amount by which values may differ between the workspaces.");
168 declareProperty("MDEventTolerance", 1E-7,
169 "The maximum amount by which values may differ between 2 MDEvents to compare.");
170 declareProperty("CheckEvents", true,
171 "Whether to compare each MDEvent. If "
172 "False, will only look at the box "
173 "structure.");
174
175 declareProperty(std::make_unique<PropertyWithValue<bool>>("Equals", false, Direction::Output),
176 "Boolean set to true if the workspaces match.");
178 "String describing the difference found between the workspaces");
179 declareProperty("IgnoreBoxID", false,
180 "To ignore box ID-s when comparing MD "
181 "boxes as Multithreaded splitting "
182 "assigns box id-s randomly");
183}
184
185//----------------------------------------------------------------------------------------------
187template <typename T> std::string versus(T a, T b) {
188 return "(" + Strings::toString(a) + " vs " + Strings::toString(b) + ")";
189}
190
191//----------------------------------------------------------------------------------------------
199template <typename T> void CompareMDWorkspaces::compare(T a, T b, const std::string &message) {
200 if (a != b)
201 throw CompareFailsException(message + " " + versus(a, b));
202}
203
204//----------------------------------------------------------------------------------------------
212template <class T> void CompareMDWorkspaces::compareTol(T a, T b, const std::string &message) {
213 double diff = fabs(a - b);
214 if (diff > m_tolerance) {
215 double pa = fabs(a);
216 double pb = fabs(b);
217 if ((pa > 2 * m_tolerance) || (pb > 2 * m_tolerance)) {
218 diff = 0.5 * diff / (pa + pb);
219 if (diff > m_tolerance)
220 throw CompareFailsException(message + " " + versus(a, b));
221 } else
222 throw CompareFailsException(message + " " + versus(a, b));
223 }
224}
225
226//----------------------------------------------------------------------------------------------
231 compare(ws1->getNumDims(), ws2->getNumDims(), "Workspaces have a different number of dimensions");
232 for (size_t d = 0; d < ws1->getNumDims(); d++) {
233 IMDDimension_const_sptr dim1 = ws1->getDimension(d);
234 IMDDimension_const_sptr dim2 = ws2->getDimension(d);
235 compare(dim1->getName(), dim2->getName(), "Dimension #" + Strings::toString(d) + " has a different name");
236 compare(dim1->getUnits(), dim2->getUnits(), "Dimension #" + Strings::toString(d) + " has different units");
237 compare(dim1->getNBins(), dim2->getNBins(),
238 "Dimension #" + Strings::toString(d) + " has a different number of bins");
239 compareTol(dim1->getMinimum(), dim2->getMinimum(),
240 "Dimension #" + Strings::toString(d) + " has a different minimum");
241 compareTol(dim1->getMaximum(), dim2->getMaximum(),
242 "Dimension #" + Strings::toString(d) + " has a different maximum");
243 }
244}
245
246//----------------------------------------------------------------------------------------------
251 compare(ws1->getNumDims(), ws2->getNumDims(), "Workspaces have a different number of dimensions");
252 compare(ws1->getNPoints(), ws2->getNPoints(), "Workspaces have a different number of points");
253 for (size_t i = 0; i < ws1->getNPoints(); i++) {
254 double diff = fabs(ws1->getSignalAt(i) - ws2->getSignalAt(i));
255 if (diff > m_tolerance)
256 throw CompareFailsException("MDHistoWorkspaces have a different signal at index " + Strings::toString(i) + " " +
257 versus(ws1->getSignalAt(i), ws2->getSignalAt(i)));
258
259 double diffErr = fabs(ws1->getErrorAt(i) - ws2->getErrorAt(i));
260 if (diffErr > m_tolerance)
261 throw CompareFailsException("MDHistoWorkspaces have a different error at index " + Strings::toString(i) + " " +
262 versus(ws1->getErrorAt(i), ws2->getErrorAt(i)));
263 }
264}
265
266//----------------------------------------------------------------------------------------------
271template <typename MDE, size_t nd>
273 typename MDEventWorkspace<MDE, nd>::sptr ws2 = std::dynamic_pointer_cast<MDEventWorkspace<MDE, nd>>(inWS2);
274 if (!ws1 || !ws2)
275 throw std::runtime_error("Incompatible workspace types passed to PlusMD.");
276
277 std::vector<API::IMDNode *> boxes1;
278 std::vector<API::IMDNode *> boxes2;
279
280 ws1->getBox()->getBoxes(boxes1, 1000, false);
281 ws2->getBox()->getBoxes(boxes2, 1000, false);
282 std::stringstream ess;
283 ess << "Workspace1 has " << boxes1.size() << " boxes; Workspace2 has " << boxes2.size() << " boxes";
284 std::string boxinfo(ess.str());
285
286 this->compare(boxes1.size(), boxes2.size(), "Workspaces do not have the same number of boxes. " + boxinfo);
287 g_log.information(boxinfo);
288
289 bool boxes_same(true);
290 std::string errormessage("");
291 int num_boxes = static_cast<int>(boxes1.size());
292 // workspace with file backed cannot work with OpenMP
293 // segmentation fault is generated on Mac build
294 bool filebacked = ws1->isFileBacked() || ws2->isFileBacked();
295
296 PRAGMA_OMP( parallel for if (!filebacked))
297 for (int ibox = 0; ibox < num_boxes; ibox++) {
299 // No need to compare because the boxes are not same already
300 if (!boxes_same) {
301 continue;
302 }
303
304 bool local_fail(false);
305 std::string local_error("");
306
307 API::IMDNode *box1 = boxes1[ibox];
308 API::IMDNode *box2 = boxes2[ibox];
309 g_log.debug() << "Box " << ibox << "ws1 npoints = " << box1->getNPoints()
310 << "; ws2 npoints = " << box2->getNPoints() << "\n";
311
312 try {
313 CompareMDWorkspaces::compare2Boxes<MDE, nd>(box1, box2, static_cast<size_t>(ibox));
314 } catch (CompareFailsException &err) {
315 local_fail = true;
316 local_error += err.what();
317 }
318
319 PARALLEL_CRITICAL(FindPeaks_WriteOutput) {
320 if (local_fail) {
321 boxes_same = false;
322 errormessage += local_error;
323 }
324 }
325
327 } // for box
329
330 // throw altogether
331 if (!boxes_same) {
332 throw CompareFailsException(errormessage);
333 }
334}
335
336template <typename MDE, size_t nd>
338
339 if (m_CompareBoxID)
340 this->compare(box1->getID(), box2->getID(), "Boxes have different ID");
341 else {
342 if (box1->getID() != box2->getID())
343 g_log.debug() << " Boxes N: " << ibox << " have box ID: " << box1->getID() << " and " << box2->getID()
344 << " correspondingly\n";
345 }
346 this->compare(size_t(box1->getDepth()), size_t(box2->getDepth()), "Boxes are at a different depth");
347 this->compare(box1->getNumChildren(), box2->getNumChildren(), "Boxes do not have the same number of children");
348
349 for (size_t i = 0; i < box1->getNumChildren(); i++) {
350 if (m_CompareBoxID)
351 this->compare(box1->getChild(i)->getID(), box2->getChild(i)->getID(), "Child of boxes do not match IDs");
352 else {
353 if (box1->getID() != box2->getID())
354 g_log.debug() << " Boxes N: " << ibox << " children N: " << i << " have box ID: " << box1->getChild(i)->getID()
355 << " and " << box2->getChild(i)->getID() << " correspondingly\n";
356 }
357 }
358
359 for (size_t d = 0; d < nd; d++) {
360 this->compareTol(box1->getExtents(d).getMin(), box2->getExtents(d).getMin(), "Extents of box do not match");
361 this->compareTol(box1->getExtents(d).getMax(), box2->getExtents(d).getMax(), "Extents of box do not match");
362 }
363 this->compareTol(box1->getInverseVolume(), box2->getInverseVolume(), "Box inverse volume does not match");
364 this->compareTol(box1->getSignal(), box2->getSignal(), "Box signal does not match");
365 this->compareTol(box1->getErrorSquared(), box2->getErrorSquared(), "Box error squared does not match");
366 if (m_CheckEvents)
367 this->compare(box1->getNPoints(), box2->getNPoints(), "Number of points in box does not match");
368
369 // Are both MDGridBoxes ?
370 auto *gridbox1 = dynamic_cast<MDGridBox<MDE, nd> *>(box1);
371 auto *gridbox2 = dynamic_cast<MDGridBox<MDE, nd> *>(box2);
372 if (gridbox1 && gridbox2) {
373 // MDGridBox: compare box size on each dimension
374 for (size_t d = 0; d < nd; d++)
375 this->compareTol(gridbox1->getBoxSize(d), gridbox2->getBoxSize(d), "Box sizes do not match");
376 } else {
377 // Could be both MDBoxes (with events)
378 auto *mdbox1 = dynamic_cast<MDBox<MDE, nd> *>(box1);
379 auto *mdbox2 = dynamic_cast<MDBox<MDE, nd> *>(box2);
380 g_log.debug() << "Box " << ibox << "ws1 npoints = " << box1->getNPoints()
381 << "; ws2 npoints = " << box2->getNPoints() << "\n";
382
383 // Rule out the case if one and only one box is MDBox
384 if (mdbox1 && !mdbox2) {
385 // workspace 2's is MDBox but workspace 1 is not
386 throw CompareFailsException("Worksapce 2's Box " + std::to_string(ibox) + " is not MDBox");
387 } else if (!mdbox1 && mdbox2) {
388 // workspace 2's is MDBox but workspace 1 is not
389 throw CompareFailsException("Worksapce 1's Box " + std::to_string(ibox) + " is not MDBox");
390 }
391
392 // Both boxes are MDBoxes:
393 if (m_CheckEvents) {
394 const std::vector<MDE> &events1 = mdbox1->getConstEvents();
395 const std::vector<MDE> &events2 = mdbox2->getConstEvents();
396
397 try {
398 this->compare(events1.size(), events2.size(), "Box event vectors are not the same length");
399
400 if (events1.size() == events2.size() && events1.size() > 2) {
401
402 std::vector<SimpleMDEvent> events_vec1;
403 std::vector<SimpleMDEvent> events_vec2;
404
405 // convert MDEvents vectors to SimpleMDEvent vectors for comparison
406 for (size_t i = 0; i < events1.size(); i++) {
407 std::vector<float> centers1(nd);
408 std::vector<float> centers2(nd);
409 for (size_t d = 0; d < nd; d++) {
410 centers1[d] = events1[i].getCenter(d);
411 centers2[d] = events2[i].getCenter(d);
412 }
413 SimpleMDEvent se1(centers1, events1[i].getSignal(), events1[i].getErrorSquared());
414 SimpleMDEvent se2(centers2, events2[i].getSignal(), events2[i].getErrorSquared());
415 events_vec1.push_back(se1);
416 events_vec2.push_back(se2);
417 }
418
419 // sort events for comparing
420 std::sort(events_vec1.begin(), events_vec1.end());
421 std::sort(events_vec2.begin(), events_vec2.end());
422
423 // compare MEEvents
424 bool same = true;
425 size_t numdiff = 0;
426 for (size_t i = 0; i < events_vec1.size(); ++i) {
427 try {
428 // coordinate
429 for (size_t d = 0; d < nd; ++d) {
430 compareTol(events_vec1[i].getCenter(d), events_vec2[i].getCenter(d), "dim " + std::to_string(d) + " ");
431 }
432 // signal
433 compareTol(events_vec1[i].getSignal(), events_vec2[i].getSignal(), "");
434 // error
435 compareTol(events_vec1[i].getError(), events_vec2[i].getError(), "");
436 } catch (CompareFailsException &e) {
437 g_log.debug() << "Box " << ibox << " Event " << i << ": " << e.what()
438 << "\n [ws1] : " + events_vec1[i].str() << "\n [ws2] : " + events_vec2[i].str()
439 << "\n";
440 numdiff++;
441 same = false;
442 }
443 }
444
445 if (!same) {
446 std::string diffmessage("Box " + std::to_string(ibox) +
447 " Number of different MDEvents = " + std::to_string(numdiff));
448 throw CompareFailsException("MDEvents are not the same!\n" + diffmessage);
449 }
450 }
451 } catch (CompareFailsException &) {
452 // Boxes must release events if the check fails
453 mdbox1->releaseEvents();
454 mdbox2->releaseEvents();
455 // Rethrow with the same type of error message!
456 throw;
457 }
458 mdbox1->releaseEvents();
459 mdbox2->releaseEvents();
460 } // if check events
461 } // if-else for MDGridBox or MDBox
462}
463
464//----------------------------------------------------------------------------------------------
468 m_tolerance = getProperty("Tolerance");
469 m_CheckEvents = getProperty("CheckEvents");
470 if (m_CheckEvents) {
471 double x = getProperty("MDEventTolerance");
472 SimpleMDEvent::s_tolerance = static_cast<float>(x);
473 }
474
475 IMDWorkspace_sptr ws1 = getProperty("Workspace1");
476 IMDWorkspace_sptr ws2 = getProperty("Workspace2");
477 inWS2 = ws2;
478 if (!ws1 || !ws2)
479 throw std::invalid_argument("Invalid workspace given.");
480
481 MatrixWorkspace_sptr mws1 = std::dynamic_pointer_cast<MatrixWorkspace>(ws1);
482 MatrixWorkspace_sptr mws2 = std::dynamic_pointer_cast<MatrixWorkspace>(ws2);
483 if (mws1 || mws2)
484 throw std::invalid_argument("Cannot compare MatrixWorkspaces. Please use "
485 "CompareWorkspaces algorithm instead.");
486
487 MDHistoWorkspace_sptr histo1 = std::dynamic_pointer_cast<MDHistoWorkspace>(ws1);
488 MDHistoWorkspace_sptr histo2 = std::dynamic_pointer_cast<MDHistoWorkspace>(ws2);
489 IMDEventWorkspace_sptr event1 = std::dynamic_pointer_cast<IMDEventWorkspace>(ws1);
490 IMDEventWorkspace_sptr event2 = std::dynamic_pointer_cast<IMDEventWorkspace>(ws2);
491
492 try {
493 compare(ws1->id(), ws2->id(), "Workspaces are of different types");
494
495 this->compareMDGeometry(ws1, ws2);
496
497 if (histo1 && histo2) {
498 this->compareMDHistoWorkspaces(histo1, histo2);
499 } else if (event1 && event2) {
501 } else
502 m_result = "Workspaces are of different types.";
503 } catch (CompareFailsException &e) {
504 m_result = e.getMessage();
505 }
506}
507
508//----------------------------------------------------------------------------------------------
512 m_result.clear();
513 m_CompareBoxID = !getProperty("IgnoreBoxID");
514
515 this->doComparison();
516
517 if (!m_result.empty()) {
518 g_log.notice() << "The workspaces did not match: " << m_result << '\n';
519 this->setProperty("Equals", false);
520 } else {
521 m_result = "Success!";
522 g_log.notice("The workspaces did match");
523 this->setProperty("Equals", true);
524 }
525 setProperty("Result", m_result);
526}
527
528} // namespace Mantid::MDAlgorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
double error
#define CALL_MDEVENT_FUNCTION(funcname, workspace)
Macro that makes it possible to call a templated method for a MDEventWorkspace using a IMDEventWorksp...
#define fabs(x)
Definition Matrix.cpp:22
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_CRITICAL(name)
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PRAGMA_OMP(expression)
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
Custom exception class to signal a failure in the comparison.
CompareFailsException(const std::string &msg)
std::string getMessage() const
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
virtual size_t getNumChildren() const =0
Get the # of children MDBoxBase'es (non-recursive)
virtual coord_t getInverseVolume() const =0
virtual signal_t getErrorSquared() const =0
virtual size_t getID() const =0
virtual uint64_t getNPoints() const =0
Get total number of points both in memory and on file if present;.
virtual Mantid::Geometry::MDDimensionExtents< coord_t > & getExtents(size_t dim)=0
virtual uint32_t getDepth() const =0
virtual signal_t getSignal() const =0
virtual IMDNode * getChild(size_t index)=0
Return the indexth child MDBoxBase.
A property class for workspaces.
coord_t getBoxSize(size_t d)
For testing: return the internal-stored size of each box in each dimension.
Definition MDBoxBase.h:203
Templated class for a multi-dimensional event "box".
Definition MDBox.h:45
const std::vector< MDE > & getConstEvents() const
Get vector of constant events to use.
Definition MDBox.hxx:269
void releaseEvents()
For file-backed MDBoxes, this marks that the data vector is no longer "busy", and so it is safe for t...
Definition MDBox.hxx:294
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
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
The concrete, templated class for properties.
Compare two MDWorkspaces for equality.
void doComparison()
Perform comparison, set m_result if not matching.
int version() const override
Algorithm's version for identification.
void exec() override
Execute the algorithm.
void compareMDEventWorkspaces(typename Mantid::DataObjects::MDEventWorkspace< MDE, nd >::sptr ws)
Perform the comparison on MDEventWorkspaces.
void compareMDGeometry(const Mantid::API::IMDWorkspace_sptr &ws1, const Mantid::API::IMDWorkspace_sptr &ws2)
Compare the dimensions etc.
void compare2Boxes(API::IMDNode *box1, API::IMDNode *box2, size_t ibox)
const std::string category() const override
Algorithm's category for identification.
void compareTol(T a, T b, const std::string &message)
Compare a and b.
void init() override
Initialize the algorithm's properties.
void compareMDHistoWorkspaces(const Mantid::DataObjects::MDHistoWorkspace_sptr &ws1, const Mantid::DataObjects::MDHistoWorkspace_sptr &ws2)
Compare the dimensions etc.
void compare(T a, T b, const std::string &message)
Compare a and b.
bool operator()(const SimpleMDEvent &event1, const SimpleMDEvent &event2) const
SimpleMDEvent(const SimpleMDEvent &other)=default
bool operator<(const SimpleMDEvent &event2) const
override operator < order
static float s_tolerance
static tolerance
SimpleMDEvent(std::vector< float > coordinates, const float &signal, const float &error)
SimpleMDEvent & operator=(const SimpleMDEvent &event2)
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
std::shared_ptr< const IMDDimension > IMDDimension_const_sptr
Shared Pointer to const IMDDimension.
std::string toString(const T &value)
Convert a number to a string.
Definition Strings.cpp:734
std::string versus(T a, T b)
Return a string "(a vs b)".
bool compareSimpleEvents(const SimpleMDEvent &self, const SimpleMDEvent &other)
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54