Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/Sample.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/SampleEnvironment.h"
#include "MantidGeometry/IComponent.h"
Janik Zikovsky
committed
#include "MantidGeometry/Crystal/OrientedLattice.h"
#include "MantidGeometry/Objects/ShapeFactory.h"
#include "MantidNexusCPP/NeXusException.hpp"
Janik Zikovsky
committed
using namespace Mantid::Kernel;
using Mantid::Geometry::ShapeFactory;
Russell Taylor
committed
Gigg, Martyn Anthony
committed
namespace API
{
using Geometry::Object;
using Geometry::Material;
Gigg, Martyn Anthony
committed
using Kernel::V3D;
Gigg, Martyn Anthony
committed
/**
* Default constructor
*/
Sample::Sample() :
m_name(), m_shape(), m_material(), m_environment(),
Gigg, Martyn Anthony
committed
m_geom_id(0), m_thick(0.0), m_height(0.0), m_width(0.0)
{
}
/**
* Copy constructor
Janik Zikovsky
committed
* @param copy :: const reference to the sample object
Gigg, Martyn Anthony
committed
*/
Sample::Sample(const Sample& copy) :
m_name(copy.m_name), m_shape(copy.m_shape), m_material(copy.m_material),
Janik Zikovsky
committed
m_environment(copy.m_environment),
Janik Zikovsky
committed
m_geom_id(copy.m_geom_id), m_thick(copy.m_thick),
m_height(copy.m_height), m_width(copy.m_width)
Gigg, Martyn Anthony
committed
{
Janik Zikovsky
committed
if (copy.m_lattice)
m_lattice = new OrientedLattice(copy.getOrientedLattice());
Gigg, Martyn Anthony
committed
}
/** Assignment operator
Janik Zikovsky
committed
* @param rhs :: const reference to the sample object
Gigg, Martyn Anthony
committed
* @return A reference to this object, which will have the same
* state as the argument
*/
Gigg, Martyn Anthony
committed
{
if (this == &rhs) return *this;
m_name = rhs.m_name;
m_shape = rhs.m_shape;
m_material = rhs.m_material;
m_environment = rhs.m_environment;
m_geom_id = rhs.m_geom_id;
m_samples = std::vector<boost::shared_ptr<Sample> >(rhs.m_samples);
Gigg, Martyn Anthony
committed
m_thick = rhs.m_thick;
m_height = rhs.m_height;
m_width = rhs.m_width;
Janik Zikovsky
committed
if (rhs.m_lattice)
m_lattice = new OrientedLattice(rhs.getOrientedLattice());
else
m_lattice = NULL;
Gigg, Martyn Anthony
committed
return *this;
}
Russell Taylor
committed
Gigg, Martyn Anthony
committed
/**
* Returns the name of the sample
* @returns The name of this sample
*/
const std::string & Sample::getName() const
{
return m_name;
}
/**
* Update the name of the sample
Janik Zikovsky
committed
* @param name :: The name of the sample
Gigg, Martyn Anthony
committed
*/
void Sample::setName(const std::string & name)
{
m_name = name;
}
/**
* Get a pointer to the sample shape object. It is assumed that this is defined within
* its own coordinate system with its centre at [0,0,0]
* @return A reference to the object describing the shape
Gigg, Martyn Anthony
committed
*/
const Object& Sample::getShape() const
{
return m_shape;
}
/** Set the object that describes the sample shape. It is assumed that this is defined such
* that its centre is at [0,0,0]
Janik Zikovsky
committed
* @param object :: The object describing the shape
* @throw An std::invalid_argument error if the object does
Gigg, Martyn Anthony
committed
* not have a valid shape
*/
void Sample::setShape(const Object & object)
{
if( object.hasValidShape() )
{
Gigg, Martyn Anthony
committed
}
else
{
throw std::invalid_argument("Sample::setShape - Object has an invalid shape.");
Gigg, Martyn Anthony
committed
}
}
/** Return the material.
* @return A reference to the material the sample is composed of
*/
const Material & Sample::getMaterial() const
{
return m_material;
}
/**
* Set the type of material that this sample is composed from
Janik Zikovsky
committed
* @param material :: A reference to the material object. It is copied into the sample.
*/
void Sample::setMaterial(const Geometry::Material& material)
{
m_material = material;
}
Gigg, Martyn Anthony
committed
/**
* Return a reference to the sample environment that this sample is attached to
* @return A const reference to a SampleEnvironment object
Janik Zikovsky
committed
* @throw std::runtime_error If the environment has not been defined
Gigg, Martyn Anthony
committed
*/
const SampleEnvironment & Sample::getEnvironment() const
{
if( !m_environment )
{
Janik Zikovsky
committed
throw std::runtime_error("Sample::getEnvironment - No sample enviroment has been defined.");
Gigg, Martyn Anthony
committed
}
return *m_environment;
}
/**
Janik Zikovsky
committed
* Attach an environment onto this sample
Janik Zikovsky
committed
* @param env :: A pointer to a created sample environment. This takes
Gigg, Martyn Anthony
committed
* ownership of the object.
*/
void Sample::setEnvironment(SampleEnvironment * env)
{
m_environment = boost::shared_ptr<SampleEnvironment>(env);
}
/** Return a const reference to the OrientedLattice of this sample
Janik Zikovsky
committed
* @return A const reference to a OrientedLattice object
* @throw std::runtime_error If the OrientedLattice has not been defined
*/
const OrientedLattice & Sample::getOrientedLattice() const
{
if( !m_lattice )
{
throw std::runtime_error("Sample::getOrientedLattice - No OrientedLattice has been defined.");
}
return *m_lattice;
}
/** Return a reference to the OrientedLattice of this sample
* @return A reference to a OrientedLattice object
* @throw std::runtime_error If the OrientedLattice has not been defined
*/
OrientedLattice & Sample::getOrientedLattice()
{
if( !m_lattice )
{
throw std::runtime_error("Sample::getOrientedLattice - No OrientedLattice has been defined.");
Janik Zikovsky
committed
}
return *m_lattice;
}
/** Attach an OrientedLattice onto this sample
*
Janik Zikovsky
committed
* @param env :: A pointer to a OrientedLattice.
Janik Zikovsky
committed
*/
void Sample::setOrientedLattice(OrientedLattice * latt)
{
Janik Zikovsky
committed
m_lattice = latt;
Janik Zikovsky
committed
}
Janik Zikovsky
committed
/** @return true if the sample has an OrientedLattice */
bool Sample::hasOrientedLattice() const
{ return (m_lattice != NULL); }
Gigg, Martyn Anthony
committed
/**
* Set the geometry flag that is specfied in the raw file within the SPB_STRUCT
* 1 = cylinder, 2 = flat plate, 3 = disc, 4 = single crystal
Janik Zikovsky
committed
* @param geom_id :: The flag for the geometry
Gigg, Martyn Anthony
committed
*/
void Sample::setGeometryFlag(int geom_id)
{
m_geom_id = geom_id;
}
/**
* Get the geometry flag that is specified in the raw file within the SPB_STRUCT
* 1 = cylinder, 2 = flat plate, 3 = disc, 4 = single crystal
* @returns The flag for the sample geometry
*/
int Sample::getGeometryFlag() const
{
return m_geom_id;
}
/**
* Set the thickness value
Janik Zikovsky
committed
* @param thick :: The parameter e_thick in the SPB_STRUCT
Gigg, Martyn Anthony
committed
*/
void Sample::setThickness(double thick)
{
m_thick = thick;
}
/**
* Get the thickness value
* @returns The parameter thickness parameter
*/
double Sample::getThickness() const
{
return m_thick;
}
/**
* Set the height value
Janik Zikovsky
committed
* @param height :: The parameter e_height in the SPB_STRUCT
Gigg, Martyn Anthony
committed
*/
void Sample::setHeight(double height)
{
m_height = height;
}
/**
* Get the height value
* @returns The parameter height parameter
*/
double Sample::getHeight() const
{
return m_height;
}
/**
* Set the width value
Janik Zikovsky
committed
* @param width :: The parameter e_width in the SPB_STRUCT
Gigg, Martyn Anthony
committed
*/
void Sample::setWidth(double width)
{
m_width = width;
}
/**
* Get the height value
* @returns The parameter height parameter
*/
double Sample::getWidth() const
{
return m_width;
}
/**
* Gets the desired sample, 0 is the current sample
* @param index The index of the desired sample
* @returns The desired sample
*/
Sample& Sample::operator[] (const int index)
{
if (index == 0)
{
return *this;
}
else if ((static_cast<std::size_t>(index) > m_samples.size()) || ( index < 0))
{
throw std::out_of_range("The index value provided was out of range");
}
else
{
return *m_samples[index-1];
}
}
/**
* Gets the number of samples in this collection
* @returns The count of samples
*/
{
return m_samples.size()+1;
}
/**
* Adds a sample to the sample collection
* @param childSample The child sample to be added
*/
void Sample::addSample(boost::shared_ptr<Sample> childSample)
{
m_samples.push_back(childSample);
}
Janik Zikovsky
committed
//--------------------------------------------------------------------------------------------
/** Save the object to an open NeXus file.
* @param file :: open NeXus file
* @param group :: name of the group to create
*/
void Sample::saveNexus(::NeXus::File * file, const std::string & group) const
{
file->makeGroup(group, "NXsample", 1);
file->putAttr("name", m_name);
file->putAttr("version", 1);
Janik Zikovsky
committed
file->putAttr("shape_xml", m_shape.getShapeXML());
m_material.saveNexus(file, "material");
// Write out the other (indexes 1+) samples
file->writeData("num_other_samples", int(m_samples.size()) );
for (size_t i=0; i<m_samples.size(); i++)
Janik Zikovsky
committed
m_samples[i]->saveNexus(file, "sample" + Strings::toString(i+1));
//TODO: SampleEnvironment
// OrientedLattice
if (hasOrientedLattice())
{
file->writeData("num_oriented_lattice", 1 );
m_lattice->saveNexus(file, "oriented_lattice");
}
else
file->writeData("num_oriented_lattice", 0 );
// Legacy info from RAW file (I think)
file->writeData("geom_id", m_geom_id);
file->writeData("geom_thickness", m_thick);
file->writeData("geom_height", m_height);
file->writeData("geom_width", m_width);
Janik Zikovsky
committed
//--------------------------------------------------------------------------------------------
/** Load the object from an open NeXus file.
* @param file :: open NeXus file
* @param group :: name of the group to open
Janik Zikovsky
committed
* @return the version tag of the sample group
Janik Zikovsky
committed
int Sample::loadNexus(::NeXus::File * file, const std::string & group)
{
file->openGroup(group, "NXsample");
Janik Zikovsky
committed
// Version 0 = saveNexusProcessed before Sep 8, 2011
int version = 0;
try { file->getAttr("version", version); }
catch (::NeXus::Exception &) { version=0; }
Janik Zikovsky
committed
if (version == 0)
Janik Zikovsky
committed
{
// Sample NAME field may/may not be present
try { file->readData("name", m_name); }
catch (::NeXus::Exception &) { m_name = ""; }
Janik Zikovsky
committed
}
if (version > 0)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
// Name is an attribute
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
file->getAttr("name", m_name);
// Shape (from XML)
std::string shape_xml;
file->getAttr("shape_xml", shape_xml);
shape_xml = Strings::strip(shape_xml);
if (!shape_xml.empty())
{
ShapeFactory shapeMaker;
m_shape = *shapeMaker.createShape(shape_xml, false /*Don't wrap with <type> tag*/);
}
m_material.loadNexus(file, "material");
// Load other samples
int num_other_samples;
file->readData("num_other_samples", num_other_samples);
for (int i=0; i < num_other_samples; i++)
{
boost::shared_ptr<Sample> extra(new Sample);
extra->loadNexus(file, "sample" + Strings::toString(i+1));
this->addSample(extra);
}
// OrientedLattice
int num_oriented_lattice;
file->readData("num_oriented_lattice", num_oriented_lattice );
if (num_oriented_lattice > 0)
{
m_lattice = new OrientedLattice;
m_lattice->loadNexus(file, "oriented_lattice");
}
Janik Zikovsky
committed
}
Janik Zikovsky
committed
try
{
// Legacy info from RAW file (I think)
file->readData("geom_id", m_geom_id);
file->readData("geom_thickness", m_thick);
file->readData("geom_height", m_height);
file->readData("geom_width", m_width);
}
catch (...)
{ /* Very old files don't have them. Ignore. */ }
Janik Zikovsky
committed
return version;
Gigg, Martyn Anthony
committed
}