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 +
13#include "MantidKernel/System.h"
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:
29
32 // Stop watching once object is deleted
33 API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
34 }
35 }
36
38 if (!m_observingDelete) {
39 API::AnalysisDataService::Instance().notificationCenter.addObserver(m_delete_observer);
40 m_observingDelete = true;
41 }
42 }
43
45 m_parent.deleteNotificationReceived(notice->object());
46 }
47
48private:
50
53
55 bool m_observingDelete{false};
56};
57
58//----------------------------------------------------------------------------------------------
62 : m_dimensions(), m_originalWorkspaces(), m_origin(), m_transforms_FromOriginal(), m_transforms_ToOriginal(),
63 m_notificationHelper(std::make_unique<MDGeometryNotificationHelper>(*this)), m_Wtransf(3, 3, true),
64 m_basisVectors() {}
65
66//----------------------------------------------------------------------------------------------
69MDGeometry::MDGeometry(const MDGeometry &other) { *this = other; }
70
72 m_dimensions = std::vector<std::shared_ptr<IMDDimension>>{};
73 m_originalWorkspaces = std::vector<std::shared_ptr<Workspace>>{};
74 m_origin = other.m_origin;
75 m_transforms_FromOriginal = std::vector<std::shared_ptr<const CoordTransform>>{};
76 m_transforms_ToOriginal = std::vector<std::shared_ptr<const CoordTransform>>{};
77 m_notificationHelper = std::make_unique<MDGeometryNotificationHelper>(*this);
78 m_Wtransf = other.m_Wtransf;
79 m_basisVectors = other.m_basisVectors;
80
81 // Perform a deep copy of the dimensions
82 std::vector<Mantid::Geometry::IMDDimension_sptr> dimensions;
83 for (size_t d = 0; d < other.getNumDims(); d++) {
84 // Copy the dimension
85 auto dim = std::make_shared<MDHistoDimension>(other.getDimension(d).get());
86 dimensions.emplace_back(dim);
87 }
88 this->initGeometry(dimensions);
89
90 // Perform a deep copy of the coordinate transformations
91 std::vector<CoordTransform_const_sptr>::const_iterator it;
92 for (it = other.m_transforms_FromOriginal.begin(); it != other.m_transforms_FromOriginal.end(); ++it) {
93 if (*it)
94 m_transforms_FromOriginal.emplace_back(CoordTransform_const_sptr((*it)->clone()));
95 else
97 }
98
99 for (it = other.m_transforms_ToOriginal.begin(); it != other.m_transforms_ToOriginal.end(); ++it) {
100 if (*it)
101 m_transforms_ToOriginal.emplace_back(CoordTransform_const_sptr((*it)->clone()));
102 else
104 }
105
106 // Copy the references to the original workspaces
107 // This will also set up the delete observer to listen to those workspaces
108 // being deleted.
109 for (size_t i = 0; i < other.m_originalWorkspaces.size(); i++)
111
112 return *this;
113}
114
121}
122
127
128//----------------------------------------------------------------------------------------------
132
133//----------------------------------------------------------------------------------------------
139void MDGeometry::initGeometry(const std::vector<Mantid::Geometry::IMDDimension_sptr> &dimensions) {
140 // Copy the dimensions array
141 m_dimensions = dimensions;
142 // Make sure the basis vectors are big enough
144}
145
146// --------------------------------------------------------------------------------------------
148size_t MDGeometry::getNumDims() const { return m_dimensions.size(); }
149
152 return std::count_if(m_dimensions.cbegin(), m_dimensions.cend(),
153 [](const auto &dimension) { return !dimension->getIsIntegrated(); });
154}
155
156// --------------------------------------------------------------------------------------------
161std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getDimension(size_t index) const {
162 if (index >= m_dimensions.size())
163 throw std::runtime_error("Workspace does not have a dimension at that index.");
164 return m_dimensions[index];
165}
166
167// --------------------------------------------------------------------------------------------
172std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getDimensionWithId(std::string id) const {
173 auto dimension = std::find_if(
174 m_dimensions.begin(), m_dimensions.end(),
175 [&id](const std::shared_ptr<const Mantid::Geometry::IMDDimension> &dim) { return dim->getDimensionId() == id; });
176 if (dimension != m_dimensions.end())
177 return *dimension;
178 else
179 throw std::invalid_argument("Dimension tagged " + id + " was not found in the Workspace");
180}
181
182// --------------------------------------------------------------------------------------------
187 using namespace Mantid::Geometry;
188 VecIMDDimension_const_sptr vecCollapsedDimensions;
189 std::copy_if(m_dimensions.cbegin(), m_dimensions.cend(), std::back_inserter(vecCollapsedDimensions),
190 [](const auto &dimension) { return !dimension->getIsIntegrated(); });
191 return vecCollapsedDimensions;
192}
193
194//-----------------------------------------------------------------------------------------------
196std::vector<coord_t> MDGeometry::estimateResolution() const {
197 std::vector<coord_t> out;
198 for (size_t d = 0; d < this->getNumDims(); d++)
199 out.emplace_back(this->getDimension(d)->getBinWidth());
200 return out;
201}
202
203//-----------------------------------------------------------------------------------------------
210size_t MDGeometry::getDimensionIndexByName(const std::string &name) const {
211 for (size_t d = 0; d < m_dimensions.size(); d++)
212 if (m_dimensions[d]->getName() == name)
213 return d;
214 throw std::runtime_error("Dimension named '" + name + "' was not found in the IMDWorkspace.");
215}
216
217//-----------------------------------------------------------------------------------------------
224size_t MDGeometry::getDimensionIndexById(const std::string &id) const {
225 for (size_t d = 0; d < m_dimensions.size(); d++)
226 if (m_dimensions[d]->getDimensionId() == id)
227 return d;
228 throw std::runtime_error("Dimension with id '" + id + "' was not found in the IMDWorkspace.");
229}
230
231// --------------------------------------------------------------------------------------------
234void MDGeometry::addDimension(const std::shared_ptr<Mantid::Geometry::IMDDimension> &dim) {
235 m_dimensions.emplace_back(dim);
236}
237
238// --------------------------------------------------------------------------------------------
242 m_dimensions.emplace_back(std::shared_ptr<Mantid::Geometry::IMDDimension>(dim));
243}
244
245// --------------------------------------------------------------------------------------------
247std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getXDimension() const {
248 if (this->getNumDims() < 1)
249 throw std::runtime_error("Workspace does not have any dimensions!");
250 return this->getDimension(0);
251}
252
254std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getYDimension() const {
255 if (this->getNumDims() < 2)
256 throw std::runtime_error("Workspace does not have a Y dimension.");
257 return this->getDimension(1);
258}
259
261std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getZDimension() const {
262 if (this->getNumDims() < 3)
263 throw std::runtime_error("Workspace does not have a Z dimension.");
264 return this->getDimension(2);
265}
266
268std::shared_ptr<const Mantid::Geometry::IMDDimension> MDGeometry::getTDimension() const {
269 if (this->getNumDims() < 4)
270 throw std::runtime_error("Workspace does not have a T dimension.");
271 return this->getDimension(3);
272}
273
274// --------------------------------------------------------------------------------------------
281 if (index >= m_basisVectors.size())
282 throw std::invalid_argument("getBasisVector(): invalid index");
283 return m_basisVectors[index];
284}
285
292 if (index >= m_basisVectors.size())
293 throw std::invalid_argument("getBasisVector(): invalid index");
294 return m_basisVectors[index];
295}
296
303 if (index >= m_basisVectors.size())
304 throw std::invalid_argument("getBasisVector(): invalid index");
305 m_basisVectors[index] = vec;
306}
307
312 auto normalized = std::find_if(m_basisVectors.begin(), m_basisVectors.end(),
313 [](const Mantid::Kernel::VMD &basisVector) { return basisVector.length() != 1.0; });
314 return normalized == m_basisVectors.end();
315}
316
317//---------------------------------------------------------------------------------------------------
321 if (index >= m_originalWorkspaces.size())
322 return false;
323 return bool(m_originalWorkspaces[index]);
324}
325
328
329//---------------------------------------------------------------------------------------------------
340std::shared_ptr<Workspace> MDGeometry::getOriginalWorkspace(size_t index) const {
341 if (index >= m_originalWorkspaces.size())
342 throw std::runtime_error("MDGeometry::getOriginalWorkspace() invalid index.");
344}
345
346//---------------------------------------------------------------------------------------------------
357void MDGeometry::setOriginalWorkspace(std::shared_ptr<Workspace> ws, size_t index) {
358 if (index >= m_originalWorkspaces.size())
359 m_originalWorkspaces.resize(index + 1);
360 m_originalWorkspaces[index] = std::move(ws);
361 m_notificationHelper->watchForWorkspaceDeletions();
362}
363
364//---------------------------------------------------------------------------------------------------
377void MDGeometry::transformDimensions(std::vector<double> &scaling, std::vector<double> &offset) {
378 if (scaling.size() != m_dimensions.size())
379 throw std::invalid_argument("MDGeometry::transformDimensions(): "
380 "scaling.size() must be equal to number of "
381 "dimensions.");
382 if (offset.size() != m_dimensions.size())
383 throw std::invalid_argument("MDGeometry::transformDimensions(): "
384 "offset.size() must be equal to number of "
385 "dimensions.");
386 for (size_t d = 0; d < m_dimensions.size(); d++) {
388 coord_t min = (dim->getMinimum() * static_cast<coord_t>(scaling[d])) + static_cast<coord_t>(offset[d]);
389 coord_t max = (dim->getMaximum() * static_cast<coord_t>(scaling[d])) + static_cast<coord_t>(offset[d]);
390 if (min < max)
391 dim->setRange(dim->getNBins(), min, max);
392 else
393 dim->setRange(dim->getNBins(), max, min);
394 }
395 // Clear the original workspace
396 setOriginalWorkspace(std::shared_ptr<Workspace>());
398 setTransformToOriginal(nullptr);
399}
400
401//---------------------------------------------------------------------------------------------------
410void MDGeometry::deleteNotificationReceived(const std::shared_ptr<const Workspace> &deleted) {
411 for (auto &original : m_originalWorkspaces) {
412 if (original) {
413 // Compare the pointer being deleted to the one stored as the original.
414 if (original == deleted) {
415 // Clear the reference
416 original.reset();
417 }
418 }
419 }
420}
421
422//---------------------------------------------------------------------------------------------------
434 if (index >= m_transforms_FromOriginal.size())
435 throw std::runtime_error("MDGeometry::getTransformFromOriginal(): invalid index.");
436 return m_transforms_FromOriginal[index].get();
437}
438
439//---------------------------------------------------------------------------------------------------
451 if (index >= m_transforms_FromOriginal.size()) {
453 }
455}
456
457//---------------------------------------------------------------------------------------------------
470 if (index >= m_transforms_ToOriginal.size())
471 throw std::runtime_error("MDGeometry::getTransformFromOriginal(): invalid index.");
472 return m_transforms_ToOriginal[index].get();
473}
474
475//---------------------------------------------------------------------------------------------------
488 if (index >= m_transforms_ToOriginal.size()) {
489 m_transforms_ToOriginal.resize(index + 1);
490 }
492}
493
494//---------------------------------------------------------------------------------------------------
496std::string MDGeometry::getGeometryXML() const {
500 // Add all dimensions.
501 const size_t nDimensions = this->getNumDims();
502 for (size_t i = 0; i < nDimensions; i++) {
503 xmlBuilder.addOrdinaryDimension(this->getDimension(i));
504 }
505 // Add mapping dimensions
506 if (nDimensions > 0) {
507 xmlBuilder.addXDimension(this->getXDimension());
508 }
509 if (nDimensions > 1) {
510 xmlBuilder.addYDimension(this->getYDimension());
511 }
512 if (nDimensions > 2) {
513 xmlBuilder.addZDimension(this->getZDimension());
514 }
515 if (nDimensions > 3) {
516 xmlBuilder.addTDimension(this->getTDimension());
517 }
518 // Create the xml.
519 return xmlBuilder.create();
520}
521
527
533
534} // namespace Mantid::API
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
std::string getName(const IMDDimension &self)
Unique SingleValueParameter Declaration for InputNDimensions.
MDGeometryNotificationHelper(MDGeometry &parent)
Definition: MDGeometry.cpp:27
Poco::NObserver< MDGeometryNotificationHelper, WorkspacePreDeleteNotification > m_delete_observer
Poco delete notification observer object.
Definition: MDGeometry.cpp:52
void deleteNotificationReceived(Mantid::API::WorkspacePreDeleteNotification_ptr notice)
Definition: MDGeometry.cpp:44
bool m_observingDelete
Set to True when the m_delete_observer is observing workspace deletions.
Definition: MDGeometry.cpp:55
Describes the geometry (i.e.
Definition: MDGeometry.h:37
Kernel::DblMatrix m_Wtransf
the matrix which transforms momentums from orthogonal Q-system to Orthogonal HKL or non-orthogonal HK...
Definition: MDGeometry.h:150
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...
Definition: MDGeometry.cpp:433
void initGeometry(const std::vector< std::shared_ptr< Geometry::IMDDimension > > &dimensions)
Initialize the geometry.
Definition: MDGeometry.cpp:139
std::shared_ptr< const Mantid::Geometry::IMDDimension > getTDimension() const
Get the t-dimension mapping.
Definition: MDGeometry.cpp:268
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:155
virtual ~MDGeometry()
Destructor.
Definition: MDGeometry.cpp:131
size_t getNumberTransformsToOriginal() const
Get the number of transforms defined to the original coordinate system.
Definition: MDGeometry.cpp:526
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:135
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:131
bool allBasisNormalized() const
Definition: MDGeometry.cpp:311
virtual std::shared_ptr< const Mantid::Geometry::IMDDimension > getDimension(size_t index) const
Get a dimension.
Definition: MDGeometry.cpp:161
void addDimension(const std::shared_ptr< Mantid::Geometry::IMDDimension > &dim)
Add a dimension.
Definition: MDGeometry.cpp:234
void transformDimensions(std::vector< double > &scaling, std::vector< double > &offset)
Transform the dimensions contained in this geometry x' = x*scaling + offset.
Definition: MDGeometry.cpp:377
std::vector< std::shared_ptr< const Geometry::IMDDimension > > getNonIntegratedDimensions() const
Get non-collapsed dimensions.
Definition: MDGeometry.cpp:186
void clearTransforms()
Clear transforms.
Definition: MDGeometry.cpp:118
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).
Definition: MDGeometry.cpp:357
size_t getDimensionIndexById(const std::string &id) const
Get the index of the dimension that matches the ID given.
Definition: MDGeometry.cpp:224
virtual std::shared_ptr< const Mantid::Geometry::IMDDimension > getDimensionWithId(std::string id) const
Get a dimension.
Definition: MDGeometry.cpp:172
size_t numOriginalWorkspaces() const
Definition: MDGeometry.cpp:327
void setBasisVector(size_t index, const Mantid::Kernel::VMD &vec)
Set the basis vector (in the original workspace) for a dimension of this workspace.
Definition: MDGeometry.cpp:302
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:123
virtual size_t getNumDims() const
Definition: MDGeometry.cpp:148
void clearOriginalWorkspaces()
Clear original workspaces.
Definition: MDGeometry.cpp:126
virtual size_t getNumNonIntegratedDims() const
Definition: MDGeometry.cpp:151
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:139
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...
Definition: MDGeometry.cpp:469
bool hasOriginalWorkspace(size_t index=0) const
Definition: MDGeometry.cpp:320
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...
Definition: MDGeometry.cpp:450
virtual std::vector< coord_t > estimateResolution() const
Definition: MDGeometry.cpp:196
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...
Definition: MDGeometry.cpp:487
std::string getGeometryXML() const
Definition: MDGeometry.cpp:496
std::shared_ptr< Workspace > getOriginalWorkspace(size_t index=0) const
Get the "original" workspace (the workspace that was the source for a binned MDWorkspace).
Definition: MDGeometry.cpp:340
void deleteNotificationReceived(const std::shared_ptr< const Workspace > &deleted)
Function called when observer objects recieves a notification.
Definition: MDGeometry.cpp:410
Mantid::Kernel::VMD & getBasisVector(size_t index)
Get the basis vector (in the original workspace) for a dimension of this workspace.
Definition: MDGeometry.cpp:280
MDGeometry & operator=(const MDGeometry &other)
Definition: MDGeometry.cpp:71
size_t getDimensionIndexByName(const std::string &name) const
Get the index of the dimension that matches the name given.
Definition: MDGeometry.cpp:210
std::shared_ptr< const Mantid::Geometry::IMDDimension > getXDimension() const
Get the x-dimension mapping.
Definition: MDGeometry.cpp:247
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:127
MDGeometry()
Constructor.
Definition: MDGeometry.cpp:61
size_t getNumberTransformsFromOriginal() const
Get the number of transforms defined from the original coordinate system.
Definition: MDGeometry.cpp:532
std::shared_ptr< const Mantid::Geometry::IMDDimension > getYDimension() const
Get the y-dimension mapping.
Definition: MDGeometry.cpp:254
std::shared_ptr< const Mantid::Geometry::IMDDimension > getZDimension() const
Get the z-dimension mapping.
Definition: MDGeometry.cpp:261
std::unique_ptr< MDGeometryNotificationHelper > m_notificationHelper
Helper that deals with notifications and observing the ADS.
Definition: MDGeometry.h:142
The class describes one dimension of multidimensional dataset representing an orthogonal dimension an...
Definition: IMDDimension.h:39
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.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
const Poco::AutoPtr< Mantid::Kernel::DataService< Mantid::API::Workspace >::PreDeleteNotification > & WorkspacePreDeleteNotification_ptr
std::shared_ptr< const CoordTransform > CoordTransform_const_sptr
std::shared_ptr< IMDDimension > IMDDimension_sptr
Shared Pointer for IMDDimension. Frequently used type in framework.
Definition: IMDDimension.h:98
std::vector< IMDDimension_const_sptr > VecIMDDimension_const_sptr
Vector of constant shared pointers to IMDDimensions.
Definition: IMDDimension.h:103
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.