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"
15
16#include <nexus/NeXusException.hpp>
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;
61 m_name = rhs.m_name;
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) {
118 m_shape = shape;
119 } else {
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 m_shape->material().saveNexus(file, "material");
300 // Write out the other (indexes 1+) samples
301 file->writeData("num_other_samples", int(m_samples.size()));
302 for (size_t i = 0; i < m_samples.size(); i++)
303 m_samples[i]->saveNexus(file, "sample" + Strings::toString(i + 1));
304 // TODO: SampleEnvironment
305 // OrientedLattice
306 if (hasOrientedLattice()) {
307 file->writeData("num_oriented_lattice", 1);
308 m_lattice->saveNexus(file, "oriented_lattice");
309 } else
310 file->writeData("num_oriented_lattice", 0);
311
312 // Legacy info from RAW file (I think)
313 file->writeData("geom_id", m_geom_id);
314 file->writeData("geom_thickness", m_thick);
315 file->writeData("geom_height", m_height);
316 file->writeData("geom_width", m_width);
317
318 file->closeGroup();
319}
320
321//--------------------------------------------------------------------------------------------
327int Sample::loadNexus(::NeXus::File *file, const std::string &group) {
328 file->openGroup(group, "NXsample");
329
330 // Version 0 = saveNexusProcessed before Sep 8, 2011
331 int version = 0;
332 try {
333 file->getAttr("version", version);
334 } catch (::NeXus::Exception &) {
335 version = 0;
336 }
337
338 if (version == 0) {
339 // Sample NAME field may/may not be present
340 try {
341 file->readData("name", m_name);
342 } catch (::NeXus::Exception &) {
343 m_name = "";
344 }
345 }
346
347 if (version > 0) {
348 // Name is an attribute
349 file->getAttr("name", m_name);
350 if (file->hasAttr("name_empty")) {
351 int isEmpty;
352 file->getAttr("name_empty", isEmpty);
353 if (isEmpty) {
354 m_name.clear();
355 }
356 }
357
358 // Shape (from XML)
359 std::string shape_xml;
360 file->getAttr("shape_xml", shape_xml);
361 shape_xml = Strings::strip(shape_xml);
362 if (!shape_xml.empty()) {
363 ShapeFactory shapeMaker;
364 m_shape = shapeMaker.createShape(shape_xml, false /*Don't wrap with <type> tag*/);
365 }
366 Kernel::Material material;
367 material.loadNexus(file, "material");
368 // CSGObject expected, if so, set its material
369 if (auto csgObj = std::dynamic_pointer_cast<Geometry::CSGObject>(m_shape)) {
370 csgObj->setMaterial(material);
371 }
372
373 // Load other samples
374 int num_other_samples;
375 file->readData("num_other_samples", num_other_samples);
376 for (int i = 0; i < num_other_samples; i++) {
377 auto extra = std::make_shared<Sample>();
378 extra->loadNexus(file, "sample" + Strings::toString(i + 1));
379 this->addSample(extra);
380 }
381
382 // OrientedLattice
383 int num_oriented_lattice;
384 file->readData("num_oriented_lattice", num_oriented_lattice);
385 if (num_oriented_lattice > 0) {
386 m_lattice = std::make_unique<OrientedLattice>();
387 m_lattice->loadNexus(file, "oriented_lattice");
388 }
389 }
390
391 try {
392 // Legacy info from RAW file (I think)
393 file->readData("geom_id", m_geom_id);
394 file->readData("geom_thickness", m_thick);
395 file->readData("geom_height", m_height);
396 file->readData("geom_width", m_width);
397 } catch (...) { /* Very old files don't have them. Ignore. */
398 }
399
400 file->closeGroup();
401
402 return version;
403}
404
409 if (m_lattice) {
410 m_lattice.reset(nullptr);
411 }
412}
413
414bool Sample::operator==(const Sample &other) const {
415 if (m_samples.size() != other.m_samples.size())
416 return false;
417 for (size_t i = 0; i < m_samples.size(); ++i) {
418 if (*m_samples[i] != *other.m_samples[i])
419 return false;
420 }
421 auto compare = [](const auto &a, const auto &b, auto call_on) {
422 // both null or both not null
423 if (bool(a) ^ bool(b))
424 return false;
425 if (a)
426 return call_on(a) == call_on(b);
427 else
428 return true;
429 };
430 return *m_lattice == *other.m_lattice && this->m_name == other.m_name && this->m_height == other.m_height &&
431 this->m_width == other.m_width && this->m_thick == other.m_thick && m_geom_id == other.m_geom_id &&
432 compare(m_environment, other.m_environment, [](const auto &x) { return x->name(); }) &&
433 compare(m_shape, other.m_shape, [](const auto &x) { return x->shape(); }) &&
434 compare(m_crystalStructure, other.m_crystalStructure, [](const auto &x) { return *(x->spaceGroup()); });
435}
436
437bool Sample::operator!=(const Sample &other) const { return !this->operator==(other); }
438} // namespace Mantid::API
const std::vector< double > & rhs
double height
Definition: GetAllEi.cpp:155
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
This class stores information about the sample used in particular run.
Definition: Sample.h:33
void saveNexus(::NeXus::File *file, const std::string &group) const
Save the object to an open NeXus file.
Definition: Sample.cpp:286
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:408
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
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:437
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
int loadNexus(::NeXus::File *file, const std::string &group)
Load the object from an open NeXus file.
Definition: Sample.cpp:327
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:414
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:41
Class to implement UB matrix.
Defines a single instance of a SampleEnvironment.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
Definition: ShapeFactory.h:89
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)
Definition: LoadSassena.cpp:91
std::shared_ptr< IObject > IObject_sptr
Typdef for a shared pointer.
Definition: IObject.h:92
MANTID_KERNEL_DLL std::string strip(const std::string &A)
strip pre/post spaces
Definition: Strings.cpp:397
std::string toString(const T &value)
Convert a number to a string.
Definition: Strings.cpp:703