Mantid
Loading...
Searching...
No Matches
MDGeometry.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 +
10
14
15#include <Poco/NObserver.h>
16#include <memory>
17#include <utility>
18
19using namespace Mantid::Kernel;
20using namespace Mantid::API;
21using namespace Mantid::Geometry;
22
23namespace Mantid::API {
24
26public:
30
33 // Stop watching once object is deleted
34 API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
35 }
37 API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_replace_observer);
38 }
39 }
40
41 // delete copy operations - Poco::NObserver contains std::atomic which is not copyable
44
46 if (!m_observingDelete) {
47 API::AnalysisDataService::Instance().notificationCenter.addObserver(m_delete_observer);
48 m_observingDelete = true;
49 }
50 }
51
53 if (!m_observingReplace) {
54 API::AnalysisDataService::Instance().notificationCenter.addObserver(m_replace_observer);
55 m_observingReplace = true;
56 }
57 }
58
62
66
67private:
69
73
75 bool m_observingDelete{false};
76 bool m_observingReplace{false};
77};
78
79//----------------------------------------------------------------------------------------------
83 : m_dimensions(), m_originalWorkspaces(), m_origin(), m_transforms_FromOriginal(), m_transforms_ToOriginal(),
84 m_notificationHelper(std::make_unique<MDGeometryNotificationHelper>(*this)), m_Wtransf(3, 3, true),
85 m_basisVectors() {}
86
87//----------------------------------------------------------------------------------------------
90MDGeometry::MDGeometry(const MDGeometry &other) { *this = other; }
91
93 m_dimensions = std::vector<std::shared_ptr<IMDDimension>>{};
94 m_originalWorkspaces = std::vector<std::shared_ptr<Workspace>>{};
95 m_origin = other.m_origin;
96 m_transforms_FromOriginal = std::vector<std::shared_ptr<const CoordTransform>>{};
97 m_transforms_ToOriginal = std::vector<std::shared_ptr<const CoordTransform>>{};
98 m_notificationHelper = std::make_unique<MDGeometryNotificationHelper>(*this);
99 m_Wtransf = other.m_Wtransf;
100 m_basisVectors = other.m_basisVectors;
101
102 // Perform a deep copy of the dimensions
103 std::vector<Mantid::Geometry::IMDDimension_sptr> dimensions;
104 for (size_t d = 0; d < other.getNumDims(); d++) {
105 // Copy the dimension
106 auto dim = std::make_shared<MDHistoDimension>(other.getDimension(d).get());
107 dimensions.emplace_back(dim);
108 }
109 this->initGeometry(dimensions);
110
111 // Perform a deep copy of the coordinate transformations
112 std::vector<CoordTransform_const_sptr>::const_iterator it;
113 for (it = other.m_transforms_FromOriginal.begin(); it != other.m_transforms_FromOriginal.end(); ++it) {
114 if (*it)
115 m_transforms_FromOriginal.emplace_back(CoordTransform_const_sptr((*it)->clone()));
116 else
118 }
119
120 for (it = other.m_transforms_ToOriginal.begin(); it != other.m_transforms_ToOriginal.end(); ++it) {
121 if (*it)
122 m_transforms_ToOriginal.emplace_back(CoordTransform_const_sptr((*it)->clone()));
123 else
125 }
126
127 // Copy the references to the original workspaces
128 // This will also set up the delete observer to listen to those workspaces
129 // being deleted.
130 for (size_t i = 0; i < other.m_originalWorkspaces.size(); i++)
132
133 return *this;
134}
135
143
148
149//----------------------------------------------------------------------------------------------
153
154//----------------------------------------------------------------------------------------------
160void MDGeometry::initGeometry(const std::vector<Mantid::Geometry::IMDDimension_sptr> &dimensions) {
161 // Copy the dimensions array
162 m_dimensions = dimensions;
163 // Make sure the basis vectors are big enough
165}
166
167// --------------------------------------------------------------------------------------------
169size_t MDGeometry::getNumDims() const { return m_dimensions.size(); }
170
173 return std::count_if(m_dimensions.cbegin(), m_dimensions.cend(),
174 [](const auto &dimension) { return !dimension->getIsIntegrated(); });
175}
176
177// --------------------------------------------------------------------------------------------
182std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getDimension(size_t index) const {
183 if (index >= m_dimensions.size())
184 throw std::runtime_error("Workspace does not have a dimension at that index.");
185 return m_dimensions[index];
186}
187
188// --------------------------------------------------------------------------------------------
193std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getDimensionWithId(std::string id) const {
194 auto dimension = std::find_if(
195 m_dimensions.begin(), m_dimensions.end(),
196 [&id](const std::shared_ptr<const Mantid::Geometry::IMDDimension> &dim) { return dim->getDimensionId() == id; });
197 if (dimension != m_dimensions.end())
198 return *dimension;
199 else
200 throw std::invalid_argument("Dimension tagged " + id + " was not found in the Workspace");
201}
202
203// --------------------------------------------------------------------------------------------
208 using namespace Mantid::Geometry;
209 VecIMDDimension_const_sptr vecCollapsedDimensions;
210 std::copy_if(m_dimensions.cbegin(), m_dimensions.cend(), std::back_inserter(vecCollapsedDimensions),
211 [](const auto &dimension) { return !dimension->getIsIntegrated(); });
212 return vecCollapsedDimensions;
213}
214
215//-----------------------------------------------------------------------------------------------
217std::vector<coord_t> MDGeometry::estimateResolution() const {
218 std::vector<coord_t> out;
219 for (size_t d = 0; d < this->getNumDims(); d++)
220 out.emplace_back(this->getDimension(d)->getBinWidth());
221 return out;
222}
223
224//-----------------------------------------------------------------------------------------------
231size_t MDGeometry::getDimensionIndexByName(const std::string &name) const {
232 const auto it = std::find_if(m_dimensions.cbegin(), m_dimensions.cend(),
233 [&name](const auto &dimension) { return dimension->getName() == name; });
234 if (it != m_dimensions.cend()) {
235 return std::distance(m_dimensions.cbegin(), it);
236 }
237 throw std::runtime_error("Dimension named '" + name + "' was not found in the IMDWorkspace.");
238}
239
240//-----------------------------------------------------------------------------------------------
247size_t MDGeometry::getDimensionIndexById(const std::string &id) const {
248 const auto it = std::find_if(m_dimensions.cbegin(), m_dimensions.cend(),
249 [&id](const auto &dimension) { return dimension->getDimensionId() == id; });
250 if (it != m_dimensions.cend()) {
251 return std::distance(m_dimensions.cbegin(), it);
252 }
253 throw std::runtime_error("Dimension with id '" + id + "' was not found in the IMDWorkspace.");
254}
255
256// --------------------------------------------------------------------------------------------
259void MDGeometry::addDimension(const std::shared_ptr<Mantid::Geometry::IMDDimension> &dim) {
260 m_dimensions.emplace_back(dim);
261}
262
263// --------------------------------------------------------------------------------------------
267 m_dimensions.emplace_back(std::shared_ptr<Mantid::Geometry::IMDDimension>(dim));
268}
269
270// --------------------------------------------------------------------------------------------
272std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getXDimension() const {
273 if (this->getNumDims() < 1)
274 throw std::runtime_error("Workspace does not have any dimensions!");
275 return this->getDimension(0);
276}
277
279std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getYDimension() const {
280 if (this->getNumDims() < 2)
281 throw std::runtime_error("Workspace does not have a Y dimension.");
282 return this->getDimension(1);
283}
284
286std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getZDimension() const {
287 if (this->getNumDims() < 3)
288 throw std::runtime_error("Workspace does not have a Z dimension.");
289 return this->getDimension(2);
290}
291
293std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getTDimension() const {
294 if (this->getNumDims() < 4)
295 throw std::runtime_error("Workspace does not have a T dimension.");
296 return this->getDimension(3);
297}
298
299// --------------------------------------------------------------------------------------------
306 if (index >= m_basisVectors.size())
307 throw std::invalid_argument("getBasisVector(): invalid index");
308 return m_basisVectors[index];
309}
310
317 if (index >= m_basisVectors.size())
318 throw std::invalid_argument("getBasisVector(): invalid index");
319 return m_basisVectors[index];
320}
321
328 if (index >= m_basisVectors.size())
329 throw std::invalid_argument("getBasisVector(): invalid index");
331}
332
337 auto normalized = std::find_if(m_basisVectors.begin(), m_basisVectors.end(),
338 [](const Mantid::Kernel::VMD &basisVector) { return basisVector.length() != 1.0; });
339 return normalized == m_basisVectors.end();
340}
341
342//---------------------------------------------------------------------------------------------------
346 if (index >= m_originalWorkspaces.size())
347 return false;
348 return bool(m_originalWorkspaces[index]);
349}
350
353
354//---------------------------------------------------------------------------------------------------
365std::shared_ptr<Workspace> MDGeometry::getOriginalWorkspace(size_t index) const {
366 if (index >= m_originalWorkspaces.size())
367 throw std::runtime_error("MDGeometry::getOriginalWorkspace() invalid index.");
369}
370
371//---------------------------------------------------------------------------------------------------
382void MDGeometry::setOriginalWorkspace(std::shared_ptr<Workspace> ws, size_t index) {
383 if (index >= m_originalWorkspaces.size())
384 m_originalWorkspaces.resize(index + 1);
385 m_originalWorkspaces[index] = std::move(ws);
386 m_notificationHelper->watchForWorkspaceDeletions();
387 m_notificationHelper->watchForWorkspaceReplace();
388}
389
390//---------------------------------------------------------------------------------------------------
403void MDGeometry::transformDimensions(std::vector<double> const &scaling, std::vector<double> const &offset) {
404 if (scaling.size() != m_dimensions.size())
405 throw std::invalid_argument("MDGeometry::transformDimensions(): "
406 "scaling.size() must be equal to number of "
407 "dimensions.");
408 if (offset.size() != m_dimensions.size())
409 throw std::invalid_argument("MDGeometry::transformDimensions(): "
410 "offset.size() must be equal to number of "
411 "dimensions.");
412 for (size_t d = 0; d < m_dimensions.size(); d++) {
414 coord_t min = (dim->getMinimum() * static_cast<coord_t>(scaling[d])) + static_cast<coord_t>(offset[d]);
415 coord_t max = (dim->getMaximum() * static_cast<coord_t>(scaling[d])) + static_cast<coord_t>(offset[d]);
416 if (min < max)
417 dim->setRange(dim->getNBins(), min, max);
418 else
419 dim->setRange(dim->getNBins(), max, min);
420 }
421 // Clear the original workspace
422 setOriginalWorkspace(std::shared_ptr<Workspace>());
424 setTransformToOriginal(nullptr);
425}
426
427//---------------------------------------------------------------------------------------------------
436void MDGeometry::deleteNotificationReceived(const std::shared_ptr<const Workspace> &deleted) {
437 for (auto &original : m_originalWorkspaces) {
438 if (original) {
439 // Compare the pointer being deleted to the one stored as the original.
440 if (original == deleted) {
441 // Clear the reference
442 original.reset();
443 }
444 }
445 }
446}
447
448//---------------------------------------------------------------------------------------------------
457void MDGeometry::replaceNotificationReceived(const std::shared_ptr<const Workspace> &replaced) {
458 for (auto &original : m_originalWorkspaces) {
459 if (original) {
460 // Compare the pointer being replaced to the one stored as the original.
461 if (original == replaced) {
462 // Clear the reference
463 original.reset();
464 }
465 }
466 }
467}
468
469//---------------------------------------------------------------------------------------------------
481 if (index >= m_transforms_FromOriginal.size())
482 throw std::runtime_error("MDGeometry::getTransformFromOriginal(): invalid index.");
483 return m_transforms_FromOriginal[index].get();
484}
485
486//---------------------------------------------------------------------------------------------------
503
504//---------------------------------------------------------------------------------------------------
517 if (index >= m_transforms_ToOriginal.size())
518 throw std::runtime_error("MDGeometry::getTransformFromOriginal(): invalid index.");
519 return m_transforms_ToOriginal[index].get();
520}
521
522//---------------------------------------------------------------------------------------------------
540
541//---------------------------------------------------------------------------------------------------
543std::string MDGeometry::getGeometryXML() const {
547 // Add all dimensions.
548 const size_t nDimensions = this->getNumDims();
549 for (size_t i = 0; i < nDimensions; i++) {
550 xmlBuilder.addOrdinaryDimension(this->getDimension(i));
551 }
552 // Add mapping dimensions
553 if (nDimensions > 0) {
554 xmlBuilder.addXDimension(this->getXDimension());
555 }
556 if (nDimensions > 1) {
557 xmlBuilder.addYDimension(this->getYDimension());
558 }
559 if (nDimensions > 2) {
560 xmlBuilder.addZDimension(this->getZDimension());
561 }
562 if (nDimensions > 3) {
563 xmlBuilder.addTDimension(this->getTDimension());
564 }
565 // Create the xml.
566 return xmlBuilder.create();
567}
568
574
580
581} // namespace Mantid::API
std::string name
Definition Run.cpp:60
std::map< DeltaEMode::Type, std::string > index
std::vector< T > const * vec
Unique SingleValueParameter Declaration for InputNDimensions.
MDGeometryNotificationHelper(MDGeometry &parent)
MDGeometryNotificationHelper & operator=(const MDGeometryNotificationHelper &)=delete
Poco::NObserver< MDGeometryNotificationHelper, WorkspacePreDeleteNotification > m_delete_observer
Poco delete notification observer object.
void deleteNotificationReceived(Mantid::API::WorkspacePreDeleteNotification_ptr notice)
bool m_observingDelete
Set to True when the m_delete_observer is observing workspace deletions.
Poco::NObserver< MDGeometryNotificationHelper, WorkspaceBeforeReplaceNotification > m_replace_observer
MDGeometryNotificationHelper(const MDGeometryNotificationHelper &)=delete
void replaceNotificationReceived(Mantid::API::WorkspaceBeforeReplaceNotification_ptr notice)
Describes the geometry (i.e.
Definition MDGeometry.h:36
Kernel::DblMatrix m_Wtransf
the matrix which transforms momentums from orthogonal Q-system to Orthogonal HKL or non-orthogonal HK...
Definition MDGeometry.h:152
Mantid::API::CoordTransform const * getTransformFromOriginal(size_t index=0) const
Get the Coordinate Transformation that goes from the original workspace to this workspace's coordinat...
void initGeometry(const std::vector< std::shared_ptr< Geometry::IMDDimension > > &dimensions)
Initialize the geometry.
std::shared_ptr< const Mantid::Geometry::IMDDimension > getTDimension() const
Get the t-dimension mapping.
std::vector< Mantid::Kernel::VMD > m_basisVectors
Vector of the basis vector (in the original workspace) for each dimension of this workspace.
Definition MDGeometry.h:157
virtual ~MDGeometry()
Destructor.
size_t getNumberTransformsToOriginal() const
Get the number of transforms defined to the original coordinate system.
std::vector< std::shared_ptr< const Mantid::API::CoordTransform > > m_transforms_FromOriginal
Coordinate Transformation that goes from the original workspace to this workspace's coordinates.
Definition MDGeometry.h:137
Mantid::Kernel::VMD m_origin
Vector of the origin (in the original workspace) that corresponds to 0,0,0... in this workspace.
Definition MDGeometry.h:133
bool allBasisNormalized() const
virtual std::shared_ptr< const Mantid::Geometry::IMDDimension > getDimension(size_t index) const
Get a dimension.
void addDimension(const std::shared_ptr< Mantid::Geometry::IMDDimension > &dim)
Add a dimension.
void replaceNotificationReceived(const std::shared_ptr< const Workspace > &deleted)
Function called when observer detects a workspace is replaced.
std::vector< std::shared_ptr< const Geometry::IMDDimension > > getNonIntegratedDimensions() const
Get non-collapsed dimensions.
void clearTransforms()
Clear transforms.
void setOriginalWorkspace(std::shared_ptr< Workspace > ws, size_t index=0)
Set the "original" workspace (the workspace that was the source for a binned MDWorkspace).
size_t getDimensionIndexById(const std::string &id) const
Get the index of the dimension that matches the ID given.
virtual std::shared_ptr< const Mantid::Geometry::IMDDimension > getDimensionWithId(std::string id) const
Get a dimension.
size_t numOriginalWorkspaces() const
void setBasisVector(size_t index, const Mantid::Kernel::VMD &vec)
Set the basis vector (in the original workspace) for a dimension of this workspace.
std::vector< std::shared_ptr< Geometry::IMDDimension > > m_dimensions
Vector of the dimensions used, in the order X Y Z t, etc.
Definition MDGeometry.h:125
virtual size_t getNumDims() const
void transformDimensions(std::vector< double > const &scaling, std::vector< double > const &offset)
Transform the dimensions contained in this geometry x' = x*scaling + offset.
void clearOriginalWorkspaces()
Clear original workspaces.
virtual size_t getNumNonIntegratedDims() const
std::vector< std::shared_ptr< const Mantid::API::CoordTransform > > m_transforms_ToOriginal
Coordinate Transformation that goes from this workspace's coordinates to the original workspace coord...
Definition MDGeometry.h:141
Mantid::API::CoordTransform const * getTransformToOriginal(size_t index=0) const
Get the Coordinate Transformation that goes from THIS workspace's coordinates to the ORIGINAL workspa...
bool hasOriginalWorkspace(size_t index=0) const
void setTransformFromOriginal(Mantid::API::CoordTransform *transform, size_t index=0)
Sets the Coordinate Transformation that goes from the original workspace to this workspace's coordina...
virtual std::vector< coord_t > estimateResolution() const
void setTransformToOriginal(Mantid::API::CoordTransform *transform, size_t index=0)
Sets the Coordinate Transformation that goes from THIS workspace's coordinates to the ORIGINAL worksp...
std::string getGeometryXML() const
std::shared_ptr< Workspace > getOriginalWorkspace(size_t index=0) const
Get the "original" workspace (the workspace that was the source for a binned MDWorkspace).
Mantid::Kernel::VMD & getBasisVector(size_t index)
Get the basis vector (in the original workspace) for a dimension of this workspace.
MDGeometry & operator=(const MDGeometry &other)
size_t getDimensionIndexByName(const std::string &name) const
Get the index of the dimension that matches the name given.
std::shared_ptr< const Mantid::Geometry::IMDDimension > getXDimension() const
Get the x-dimension mapping.
std::vector< std::shared_ptr< Workspace > > m_originalWorkspaces
Pointer to the original workspace(s), if this workspace is a coordinate transformation from an origin...
Definition MDGeometry.h:129
MDGeometry()
Constructor.
size_t getNumberTransformsFromOriginal() const
Get the number of transforms defined from the original coordinate system.
void deleteNotificationReceived(const std::shared_ptr< const Workspace > &replaced)
Function called when observer objects recieves a notification.
std::shared_ptr< const Mantid::Geometry::IMDDimension > getYDimension() const
Get the y-dimension mapping.
std::shared_ptr< const Mantid::Geometry::IMDDimension > getZDimension() const
Get the z-dimension mapping.
std::unique_ptr< MDGeometryNotificationHelper > m_notificationHelper
Helper that deals with notifications and observing the ADS.
Definition MDGeometry.h:144
The class describes one dimension of multidimensional dataset representing an orthogonal dimension an...
bool addXDimension(const IMDDimension_const_sptr &dimension) const
Add x dimension.
bool addZDimension(const IMDDimension_const_sptr &dimension) const
Add z dimension.
bool addYDimension(const IMDDimension_const_sptr &dimension) const
Add y dimension.
bool addTDimension(const IMDDimension_const_sptr &dimension) const
Add t dimension.
const std::string & create() const
Create the xml.
bool addOrdinaryDimension(IMDDimension_const_sptr dimensionToAdd) const
Add a dimension that is neither considered x, y, z or t.
const Poco::AutoPtr< Mantid::Kernel::DataService< Mantid::API::Workspace >::PreDeleteNotification > & WorkspacePreDeleteNotification_ptr
std::shared_ptr< const CoordTransform > CoordTransform_const_sptr
const Poco::AutoPtr< Mantid::Kernel::DataService< Mantid::API::Workspace >::BeforeReplaceNotification > & WorkspaceBeforeReplaceNotification_ptr
std::shared_ptr< IMDDimension > IMDDimension_sptr
Shared Pointer for IMDDimension. Frequently used type in framework.
std::vector< IMDDimension_const_sptr > VecIMDDimension_const_sptr
Vector of constant shared pointers to IMDDimensions.
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.