Mantid
Loading...
Searching...
No Matches
Sample.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 +
7#include "MantidAPI/Sample.h"
17#include <utility>
18
19namespace Mantid::API {
20using namespace Mantid::Kernel;
26
31 : m_name(), m_shape(ShapeFactory().createShape("")), m_environment(), m_lattice(nullptr), m_crystalStructure(),
32 m_samples(), m_geom_id(0), m_thick(0.0), m_height(0.0), m_width(0.0) {}
33
39 : m_name(copy.m_name), m_shape(copy.m_shape), m_environment(copy.m_environment), m_lattice(nullptr),
40 m_crystalStructure(), m_samples(copy.m_samples), m_geom_id(copy.m_geom_id), m_thick(copy.m_thick),
41 m_height(copy.m_height), m_width(copy.m_width) {
42 if (copy.m_lattice)
43 m_lattice = std::make_unique<OrientedLattice>(copy.getOrientedLattice());
44
45 if (copy.hasCrystalStructure()) {
46 m_crystalStructure = std::make_unique<Geometry::CrystalStructure>(copy.getCrystalStructure());
47 }
48}
49
51Sample::~Sample() = default;
52
59 if (this == &rhs)
60 return *this;
62 m_shape = rhs.m_shape;
63 m_environment = rhs.m_environment;
64 m_geom_id = rhs.m_geom_id;
65 m_samples = std::vector<std::shared_ptr<Sample>>(rhs.m_samples);
66 m_thick = rhs.m_thick;
67 m_height = rhs.m_height;
68 m_width = rhs.m_width;
69 if (rhs.m_lattice)
70 m_lattice = std::make_unique<OrientedLattice>(rhs.getOrientedLattice());
71 else
72 m_lattice.reset(nullptr);
73
74 m_crystalStructure.reset();
75 if (rhs.hasCrystalStructure()) {
76 m_crystalStructure.reset(new Geometry::CrystalStructure(rhs.getCrystalStructure()));
77 }
78
79 return *this;
80}
81
86const std::string &Sample::getName() const { return m_name; }
87
92void Sample::setName(const std::string &name) { m_name = name; }
93
94bool Sample::hasShape() const { return (m_shape != nullptr); }
95
102const IObject &Sample::getShape() const { return *m_shape; }
103
110const IObject_sptr Sample::getShapePtr() const { return m_shape; }
111
116void Sample::setShape(const IObject_sptr &shape) {
117 if (!shape) {
119 } else if (shape != m_shape) {
120 m_shape = shape; // share ownership safely
121 }
122}
123
127const Material &Sample::getMaterial() const { return m_shape->material(); }
128
129bool Sample::hasEnvironment() const { return (m_environment != nullptr); }
130
137 if (!m_environment) {
138 throw std::runtime_error("Sample::getEnvironment - No sample enviroment has been defined.");
139 }
140 return *m_environment;
141}
142
148void Sample::setEnvironment(std::shared_ptr<SampleEnvironment> env) { m_environment = std::move(env); }
149
155 if (!m_lattice) {
156 throw std::runtime_error("Sample::getOrientedLattice - No OrientedLattice has been defined.");
157 }
158 return *m_lattice;
159}
160
166 if (!m_lattice) {
167 throw std::runtime_error("Sample::getOrientedLattice - No OrientedLattice has been defined.");
168 }
169 return *m_lattice;
170}
171
176void Sample::setOrientedLattice(std::unique_ptr<Geometry::OrientedLattice> lattice) { m_lattice = std::move(lattice); }
177
179bool Sample::hasOrientedLattice() const { return (m_lattice != nullptr); }
180
182 if (!hasCrystalStructure()) {
183 throw std::runtime_error("Sample::getCrystalStructure - No CrystalStructure has been defined.");
184 }
185
186 return *m_crystalStructure;
187}
188
191 m_crystalStructure.reset(new Geometry::CrystalStructure(newCrystalStructure));
192}
193
196 // Conversion to bool seems to be a problem in VS2012, so this is a bit more
197 // verbose than it should be.
198 return static_cast<bool>(m_crystalStructure);
199}
200
203
209void Sample::setGeometryFlag(int geom_id) { m_geom_id = geom_id; }
210
216int Sample::getGeometryFlag() const { return m_geom_id; }
217
222void Sample::setThickness(double thick) { m_thick = thick; }
223
228double Sample::getThickness() const { return m_thick; }
229
235
240double Sample::getHeight() const { return m_height; }
241
246void Sample::setWidth(double width) { m_width = width; }
247
252double Sample::getWidth() const { return m_width; }
253
260 if (index == 0) {
261 return *this;
262 } else if ((static_cast<std::size_t>(index) > m_samples.size()) || (index < 0)) {
263 throw std::out_of_range("The index value provided was out of range");
264 } else {
265 return *m_samples[index - 1];
266 }
267}
268
273std::size_t Sample::size() const { return m_samples.size() + 1; }
274
279void Sample::addSample(const std::shared_ptr<Sample> &childSample) { m_samples.emplace_back(childSample); }
280
281//--------------------------------------------------------------------------------------------
286void Sample::saveNexus(Nexus::File *file, const std::string &group) const {
287 file->makeGroup(group, "NXsample", true);
288 file->putAttr("name", m_name);
289 if (m_name.empty()) {
290 file->putAttr("name_empty", 1);
291 }
292 file->putAttr("version", 1);
293 std::string shapeXML("");
294 if (auto csgObject = std::dynamic_pointer_cast<Mantid::Geometry::CSGObject>(m_shape)) {
295 shapeXML = csgObject->getShapeXML();
296 }
297 file->putAttr("shape_xml", shapeXML);
298
299 if (auto meshObject = std::dynamic_pointer_cast<Mantid::Geometry::MeshObject>(m_shape)) {
300 meshObject->saveNexus(file, "shape_mesh");
301 }
302
303 m_shape->material().saveNexus(file, "material");
304 // Write out the other (indexes 1+) samples
305 file->writeData("num_other_samples", int(m_samples.size()));
306 for (size_t i = 0; i < m_samples.size(); i++)
307 m_samples[i]->saveNexus(file, "sample" + Strings::toString(i + 1));
308 // TODO: SampleEnvironment
309 // OrientedLattice
310 if (hasOrientedLattice()) {
311 file->writeData("num_oriented_lattice", 1);
312 m_lattice->saveNexus(file, "oriented_lattice");
313 } else
314 file->writeData("num_oriented_lattice", 0);
315
316 // Legacy info from RAW file (I think)
317 file->writeData("geom_id", m_geom_id);
318 file->writeData("geom_thickness", m_thick);
319 file->writeData("geom_height", m_height);
320 file->writeData("geom_width", m_width);
321
322 file->closeGroup();
323}
324
325//--------------------------------------------------------------------------------------------
331int Sample::loadNexus(Nexus::File *file, const std::string &group) {
332 file->openGroup(group, "NXsample");
333
334 // Version 0 = saveNexusProcessed before Sep 8, 2011
335 int version = 0;
336 if (file->hasAttr("version")) {
337 file->getAttr("version", version);
338 } else {
339 version = 0;
340 }
341
342 if (version == 0) {
343 // Sample NAME field may/may not be present
344 if (file->hasData("name")) {
345 file->readData("name", m_name);
346 } else {
347 m_name = "";
348 }
349 }
350
351 if (version > 0) {
352 // Name is an attribute
353 file->getAttr("name", m_name);
354 if (file->hasAttr("name_empty")) {
355 int isEmpty;
356 file->getAttr("name_empty", isEmpty);
357 if (isEmpty) {
358 m_name.clear();
359 }
360 }
361 // exctract the material if there is one
362 Kernel::Material material;
363 material.loadNexus(file, "material");
364 // Shape (from XML)
365 std::string shape_xml;
366 file->getAttr("shape_xml", shape_xml);
367 shape_xml = Strings::strip(shape_xml);
368 if (!shape_xml.empty()) {
369 ShapeFactory shapeMaker;
370 m_shape = shapeMaker.createShape(std::move(shape_xml), false /*Don't wrap with <type> tag*/);
371 } else if (file->hasGroup("shape_mesh", "NXoff_geometry")) {
372 m_shape = Mantid::Geometry::MeshObject::loadNexus(file, "shape_mesh", material);
373 }
374 // CSGObject expected, if so, set its material
375 if (auto csgObj = std::dynamic_pointer_cast<Geometry::CSGObject>(m_shape)) {
376 csgObj->setMaterial(material);
377 }
378
379 // Load other samples
380 int num_other_samples;
381 file->readData("num_other_samples", num_other_samples);
382 for (int i = 0; i < num_other_samples; i++) {
383 auto extra = std::make_shared<Sample>();
384 extra->loadNexus(file, "sample" + Strings::toString(i + 1));
385 this->addSample(extra);
386 }
387
388 // OrientedLattice
389 int num_oriented_lattice;
390 file->readData("num_oriented_lattice", num_oriented_lattice);
391 if (num_oriented_lattice > 0) {
392 m_lattice = std::make_unique<OrientedLattice>();
393 m_lattice->loadNexus(file, "oriented_lattice");
394 }
395 }
396
397 try {
398 // Legacy info from RAW file (I think)
399 file->readData("geom_id", m_geom_id);
400 file->readData("geom_thickness", m_thick);
401 file->readData("geom_height", m_height);
402 file->readData("geom_width", m_width);
403 } catch (...) { /* Very old files don't have them. Ignore. */
404 }
405
406 file->closeGroup();
407
408 return version;
409}
410
415 if (m_lattice) {
416 m_lattice.reset(nullptr);
417 }
418}
419
420bool Sample::operator==(const Sample &other) const {
421 if (m_samples.size() != other.m_samples.size())
422 return false;
423 for (size_t i = 0; i < m_samples.size(); ++i) {
424 if (*m_samples[i] != *other.m_samples[i])
425 return false;
426 }
427 auto compare = [](const auto &a, const auto &b, auto call_on) {
428 // both null or both not null
429 if (bool(a) ^ bool(b))
430 return false;
431 if (a)
432 return call_on(a) == call_on(b);
433 else
434 return true;
435 };
436 return *m_lattice == *other.m_lattice && this->m_name == other.m_name && this->m_height == other.m_height &&
437 this->m_width == other.m_width && this->m_thick == other.m_thick && m_geom_id == other.m_geom_id &&
438 compare(m_environment, other.m_environment, [](const auto &x) { return x->name(); }) &&
439 compare(m_shape, other.m_shape, [](const auto &x) { return x->shape(); }) &&
440 compare(m_crystalStructure, other.m_crystalStructure, [](const auto &x) { return *(x->spaceGroup()); });
441}
442
443bool Sample::operator!=(const Sample &other) const { return !this->operator==(other); }
444} // namespace Mantid::API
std::string name
Definition Run.cpp:60
const std::vector< double > & rhs
double height
Definition GetAllEi.cpp:155
std::map< DeltaEMode::Type, std::string > index
This class stores information about the sample used in particular run.
Definition Sample.h:33
void setShape(const Geometry::IObject_sptr &shape)
Update the shape of the object.
Definition Sample.cpp:116
double m_width
The sample width from the SPB_STRUCT in the raw file.
Definition Sample.h:148
double m_thick
The sample thickness from the SPB_STRUCT in the raw file.
Definition Sample.h:144
void clearOrientedLattice()
Delete the oriented lattice.
Definition Sample.cpp:414
const Kernel::Material & getMaterial() const
Return the material (convenience method)
Definition Sample.cpp:127
std::string m_name
The sample name.
Definition Sample.h:127
bool hasEnvironment() const
Definition Sample.cpp:129
int loadNexus(Nexus::File *file, const std::string &group)
Load the object from an open NeXus file.
Definition Sample.cpp:331
void saveNexus(Nexus::File *file, const std::string &group) const
Save the object to an open NeXus file.
Definition Sample.cpp:286
const std::string & getName() const
Returns the name of the sample.
Definition Sample.cpp:86
const Geometry::IObject & getShape() const
Return the sample shape.
Definition Sample.cpp:102
bool operator!=(const Sample &other) const
Definition Sample.cpp:443
void setEnvironment(std::shared_ptr< Geometry::SampleEnvironment > env)
Set the environment used to contain the sample.
Definition Sample.cpp:148
int getGeometryFlag() const
Returns the geometry flag.
Definition Sample.cpp:216
void setOrientedLattice(std::unique_ptr< Geometry::OrientedLattice > lattice)
Set the pointer to OrientedLattice defining the sample's lattice and orientation.
Definition Sample.cpp:176
Sample & operator[](const int index)
index operator for accessing multiple samples
Definition Sample.cpp:259
std::unique_ptr< Geometry::OrientedLattice > m_lattice
Pointer to the OrientedLattice of the sample, NULL if not set.
Definition Sample.h:133
const Geometry::OrientedLattice & getOrientedLattice() const
Get a reference to the sample's OrientedLattice.
Definition Sample.cpp:154
void addSample(const std::shared_ptr< Sample > &childSample)
Adds a sample to the list.
Definition Sample.cpp:279
std::shared_ptr< Geometry::SampleEnvironment > m_environment
An owned pointer to the SampleEnvironment object.
Definition Sample.h:131
void setCrystalStructure(const Geometry::CrystalStructure &newCrystalStructure)
Resets the internal pointer to the new CrystalStructure (it's copied).
Definition Sample.cpp:190
bool hasOrientedLattice() const
Definition Sample.cpp:179
~Sample()
Destructor.
std::unique_ptr< Geometry::CrystalStructure > m_crystalStructure
CrystalStructure of the sample.
Definition Sample.h:136
void setGeometryFlag(int geom_id)
Sets the geometry flag.
Definition Sample.cpp:209
void setName(const std::string &name)
Set the name of the sample.
Definition Sample.cpp:92
Sample()
Default constructor.
Definition Sample.cpp:30
std::size_t size() const
the number of samples
Definition Sample.cpp:273
std::vector< std::shared_ptr< Sample > > m_samples
Vector of child samples.
Definition Sample.h:139
void setWidth(double width)
Sets the width.
Definition Sample.cpp:246
double getWidth() const
Returns the width.
Definition Sample.cpp:252
bool hasCrystalStructure() const
Returns true if the sample actually holds a CrystalStructure.
Definition Sample.cpp:195
void setHeight(double height)
Sets the height.
Definition Sample.cpp:234
int m_geom_id
The sample geometry flag.
Definition Sample.h:142
double getHeight() const
Returns the height.
Definition Sample.cpp:240
void clearCrystalStructure()
Destroys the internally stored CrystalStructure-object.
Definition Sample.cpp:202
double m_height
The sample height from the SPB_STRUCT in the raw file.
Definition Sample.h:146
Geometry::IObject_sptr m_shape
The sample shape object.
Definition Sample.h:129
const Geometry::SampleEnvironment & getEnvironment() const
Get a reference to the sample's environment.
Definition Sample.cpp:136
Sample & operator=(const Sample &rhs)
Assignment operator.
Definition Sample.cpp:58
void setThickness(double thick)
Sets the thickness.
Definition Sample.cpp:222
const Geometry::CrystalStructure & getCrystalStructure() const
Definition Sample.cpp:181
double getThickness() const
Returns the thickness.
Definition Sample.cpp:228
bool operator==(const Sample &other) const
Definition Sample.cpp:420
const Geometry::IObject_sptr getShapePtr() const
Return a pointer to the sample shape.
Definition Sample.cpp:110
bool hasShape() const
Check if sample has a valid shape.
Definition Sample.cpp:94
Three components are required to describe a crystal structure:
IObject : Interface for geometry objects.
Definition IObject.h:42
static std::shared_ptr< MeshObject > loadNexus(Nexus::File *file, const std::string &group, const Kernel::Material &material)
Load mesh from an NXoff_geometry group in a NeXus file.
Class to implement UB matrix.
Defines a single instance of a SampleEnvironment.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Definition Material.h:50
void loadNexus(Nexus::File *file, const std::string &group)
Load the object from an open NeXus file.
Definition Material.cpp:544
bool compare(const mypair &left, const mypair &right)
std::shared_ptr< IObject > IObject_sptr
Typdef for a shared pointer.
Definition IObject.h:93
MANTID_KERNEL_DLL std::string strip(const std::string &A)
strip pre/post spaces
Definition Strings.cpp:419
std::string toString(const T &value)
Convert a number to a string.
Definition Strings.cpp:734