32#include <boost/algorithm/string/case_conv.hpp>
33#include <boost/algorithm/string/predicate.hpp>
37using API::ExperimentInfo;
39using Geometry::Container;
40using Geometry::Goniometer;
41using Geometry::ReferenceFrame;
42using Geometry::SampleEnvironment;
43using Geometry::ShapeFactory;
45using Kernel::MaterialBuilder;
46using Kernel::PropertyManager;
48using Kernel::PropertyWithValue;
52constexpr double CUBIC_METRE_TO_CM = 100. * 100. * 100.;
53constexpr double degToRad(
const double x) {
return x * M_PI / 180.; }
58const std::string INPUT_WORKSPACE(
"InputWorkspace");
60const std::string GEOMETRY(
"Geometry");
62const std::string MATERIAL(
"Material");
64const std::string ENVIRONMENT(
"Environment");
66const std::string CONTAINER_GEOMETRY(
"ContainerGeometry");
68const std::string CONTAINER_MATERIAL(
"ContainerMaterial");
73const std::string NAME(
"Name");
75const std::string CONTAINER(
"Container");
77const std::string PATH(
"Path");
80namespace GeometryArgs {
82const std::string SHAPE(
"Shape");
84const std::string VALUE(
"Value");
90const std::string FLAT_PLATE(
"FlatPlate");
92const std::string CYLINDER(
"Cylinder");
94const std::string HOLLOW_CYLINDER(
"HollowCylinder");
96const std::string SPHERE(
"Sphere");
98const std::string FLAT_PLATE_HOLDER(
"FlatPlateHolder");
100const std::string HOLLOW_CYLINDER_HOLDER(
"HollowCylinderHolder");
102const std::string CSG(
"CSG");
104const std::string WIDTH(
"Width");
106const std::string HEIGHT(
"Height");
108const std::string THICK(
"Thick");
110const std::string FRONT_THICK(
"FrontThick");
112const std::string BACK_THICK(
"BackThick");
114const std::string AXIS(
"Axis");
116const std::string ANGLE(
"Angle");
118const std::string CENTER(
"Center");
120const std::string RADIUS(
"Radius");
122const std::string INNER_RADIUS(
"InnerRadius");
124const std::string OUTER_RADIUS(
"OuterRadius");
126const std::string INNER_OUTER_RADIUS(
"InnerOuterRadius");
128const std::string OUTER_INNER_RADIUS(
"OuterInnerRadius");
138V3D cylBaseCentre(
const std::vector<double> &cylCentre,
double height,
unsigned axisIdx) {
139 const V3D halfHeight = [&]() {
151 return V3D(cylCentre[0], cylCentre[1], cylCentre[2]) - halfHeight;
161V3D cylBaseCentre(
const std::vector<double> &cylCentre,
double height,
const std::vector<double> &axis) {
163 V3D axisVector = V3D{axis[0], axis[1], axis[2]};
165 return V3D(cylCentre[0], cylCentre[1], cylCentre[2]) - axisVector *
height * 0.5;
173std::string axisXML(
unsigned axisIdx) {
176 return R
"(<axis x="1" y="0" z="0" />)";
178 return R
"(<axis x="0" y="1" z="0" />)";
180 return R
"(<axis x="0" y="0" z="1" />)";
191std::string axisXML(
const std::vector<double> &axis) {
192 std::ostringstream str;
193 str <<
"<axis x=\"" << axis[0] <<
"\" y=\"" << axis[1] <<
"\" z=\"" << axis[2] <<
"\" /> ";
205double getPropertyAsDouble(
const Kernel::PropertyManager &args,
const std::string &name) {
206 return std::stod(args.getPropertyValue(name));
217std::vector<double> getPropertyAsVectorDouble(
const Kernel::PropertyManager &args,
const std::string &name) {
218 std::string vectorAsString = args.getPropertyValue(name);
219 std::vector<double> vectorOfDoubles;
220 std::stringstream ss(vectorAsString);
221 std::string elementAsString;
222 while (std::getline(ss, elementAsString,
',')) {
223 vectorOfDoubles.push_back(std::stod(elementAsString));
225 return vectorOfDoubles;
234bool existsAndNotEmptyString(
const PropertyManager &pm,
const std::string &name) {
235 if (pm.existsProperty(name)) {
236 const auto value = pm.getPropertyValue(name);
237 return !
value.empty();
248bool existsAndNegative(
const PropertyManager &pm,
const std::string &name) {
249 if (pm.existsProperty(name)) {
250 const auto value = pm.getPropertyValue(name);
251 if (boost::lexical_cast<double>(
value) < 0.0) {
274 return "Set properties of the sample and its environment for a workspace";
284 const std::string &flavour) {
287 if (existsAndNotEmptyString(geomArgs, GeometryArgs::SHAPE)) {
289 if (shape == ShapeArgs::CSG) {
290 if (!existsAndNotEmptyString(geomArgs, GeometryArgs::VALUE)) {
291 errors[flavour] =
"For " + shape +
" shape " + GeometryArgs::VALUE +
" is required";
296 if (!shapeFromValue || !shapeFromValue->hasValidShape()) {
297 errors[flavour] =
"Invalid XML for CSG shape value";
301 if (shape == ShapeArgs::FLAT_PLATE || shape == ShapeArgs::FLAT_PLATE_HOLDER) {
302 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::WIDTH)) {
303 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::WIDTH +
" is required";
305 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::THICK)) {
306 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::THICK +
" is required";
308 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
309 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::HEIGHT +
" is required";
312 if (shape == ShapeArgs::CYLINDER) {
313 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::RADIUS)) {
314 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::RADIUS +
" is required";
316 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
317 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::HEIGHT +
" is required";
320 if (shape == ShapeArgs::HOLLOW_CYLINDER || shape == ShapeArgs::HOLLOW_CYLINDER_HOLDER) {
321 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::INNER_RADIUS)) {
322 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::INNER_RADIUS +
" is required";
324 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::OUTER_RADIUS)) {
325 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::OUTER_RADIUS +
" is required";
327 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
328 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::HEIGHT +
" is required";
331 if (shape == ShapeArgs::FLAT_PLATE_HOLDER) {
332 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::WIDTH)) {
333 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::WIDTH +
" is required";
335 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::FRONT_THICK)) {
336 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::FRONT_THICK +
" is required";
338 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::BACK_THICK)) {
339 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::BACK_THICK +
" is required";
341 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
342 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::HEIGHT +
" is required";
345 if (shape == ShapeArgs::HOLLOW_CYLINDER_HOLDER) {
346 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::INNER_OUTER_RADIUS)) {
347 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::INNER_OUTER_RADIUS +
" is required";
349 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::OUTER_INNER_RADIUS)) {
350 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::OUTER_INNER_RADIUS +
" is required";
352 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
353 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::HEIGHT +
" is required";
356 if (shape == ShapeArgs::SPHERE) {
357 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::RADIUS)) {
358 errors[flavour] =
"For " + shape +
" shape " + ShapeArgs::RADIUS +
" is required";
363 errors[flavour] = GeometryArgs::SHAPE +
" is required";
374 const std::string &flavour) {
379 if (!materialErrors.empty()) {
380 std::stringstream ss;
381 for (
const auto &
error : materialErrors) {
382 ss <<
error.first <<
":" <<
error.second <<
"\n";
384 errors[flavour] = ss.str();
396 const std::string &flavour,
const std::vector<const std::string *> &keys) {
397 if (existsAndNotEmptyString(geomArgs, GeometryArgs::SHAPE)) {
398 for (
const auto &arg : keys) {
399 if (existsAndNegative(geomArgs, *arg)) {
400 errors[flavour] = *arg +
" argument < 0.0";
411 bool isPopulated =
false;
413 if (dict->propertyCount() > 0)
420 std::map<std::string, std::string> errors;
425 if (!std::dynamic_pointer_cast<ExperimentInfo>(inputWS)) {
426 errors[PropertyNames::INPUT_WORKSPACE] =
"InputWorkspace type invalid. "
427 "Expected MatrixWorkspace, "
441 const std::vector<const std::string *> positiveValues = {{&ShapeArgs::HEIGHT, &ShapeArgs::WIDTH, &ShapeArgs::THICK,
442 &ShapeArgs::RADIUS, &ShapeArgs::INNER_RADIUS,
443 &ShapeArgs::OUTER_RADIUS}};
447 errors[
"Geometry"] =
"At least one of the input parameters must be populated";
451 if (!existsAndNotEmptyString(*environArgs, SEArgs::NAME)) {
452 errors[PropertyNames::ENVIRONMENT] =
"Environment flags require a non-empty 'Name' entry.";
474 assertNonNegative(errors, *canGeomArgs, PropertyNames::CONTAINER_GEOMETRY, positiveValues);
479 validateMaterial(errors, *canMaterialArgs, PropertyNames::CONTAINER_MATERIAL);
495 "A workspace whose sample properties will be updated");
497 "A dictionary of geometry parameters for the sample.");
499 "A dictionary of material parameters for the sample. See "
500 "SetSampleMaterial for all accepted parameters");
502 "A dictionary of parameters to configure the sample environment");
504 "A dictionary of geometry parameters for the container.");
506 "A dictionary of material parameters for the container.");
524 auto experimentInfo = std::dynamic_pointer_cast<ExperimentInfo>(
workspace);
535 double sampleVolume = 0.;
538 if (experimentInfo->sample().getShape().hasValidShape()) {
540 sampleVolume = CUBIC_METRE_TO_CM * experimentInfo->sample().getShape().volume();
548 if (sampleVolume > 0.) {
556 setMaterial(materialParams, materialArgsCompatible);
561 std::shared_ptr<Geometry::IObject>(experimentInfo->sample().getShape().cloneWithMaterial(*sampleMaterial));
562 experimentInfo->mutableSample().setShape(shapeObject);
577 const std::string envName = args->getPropertyValue(SEArgs::NAME);
578 std::string canName =
"";
579 if (args->existsProperty(SEArgs::CONTAINER)) {
580 canName = args->getPropertyValue(SEArgs::CONTAINER);
586 const auto &instOnWS = instrument->getName();
588 std::string facilityName, instrumentName;
590 const auto &instInfo = config.getInstrument(instOnWS);
591 instrumentName = instInfo.name();
592 facilityName = instInfo.facility().name();
593 }
catch (std::runtime_error &) {
595 facilityName = config.getFacility().name();
596 instrumentName = config.getInstrument().name();
599 const auto &instDirs = config.getInstrumentDirectories();
600 std::vector<std::string> environDirs(instDirs);
601 for (
auto &direc : environDirs) {
602 direc = Poco::Path(direc).append(
"sampleenvironments").toString();
604 auto finder = std::make_unique<SampleEnvironmentSpecFileFinder>(environDirs);
607 if (args->existsProperty(SEArgs::PATH)) {
608 auto sampleEnvironSpec = factory.
parseSpec(envName, args->getPropertyValue(SEArgs::PATH));
609 sampleEnviron = sampleEnvironSpec->buildEnvironment(canName);
611 sampleEnviron = factory.
create(facilityName, instrumentName, envName, canName);
628 const auto refFrame = exptInfo.
getInstrument()->getReferenceFrame();
634 if (shape->hasValidShape()) {
635 if (canMaterialArgs) {
638 setMaterial(materialParams, canMaterialCompatible);
639 if (materialParams.
volume <= 0.) {
640 materialParams.
volume = shape->volume() * CUBIC_METRE_TO_CM;
645 shape->setMaterial(*canMaterial);
684 const std::string numberDensityUnit = materialArgs.
getProperty(
"NumberDensityUnit");
685 if (numberDensityUnit ==
"Atoms") {
735 const auto refFrame = experiment.
getInstrument()->getReferenceFrame();
755 const auto &props = args->getProperties();
756 for (
const auto &prop : props) {
758 const double val = getPropertyAsDouble(*args, prop->name());
759 shapeArgs.emplace(boost::algorithm::to_lower_copy(prop->name()), val * 0.01);
762 auto shapeObject = can.createSampleShape(shapeArgs);
767 if (
auto csgObj = std::dynamic_pointer_cast<Geometry::CSGObject>(shapeObject)) {
768 csgObj->setMaterial(mat);
773 throw std::runtime_error(
"The can has a fixed sample shape that cannot "
774 "be adjusted using the Geometry parameter.");
776 auto shapeObject = can.getSampleShape();
780 if (
typeid(shapeObject) ==
typeid(std::shared_ptr<Geometry::MeshObject>)) {
782 std::dynamic_pointer_cast<Geometry::MeshObject>(shapeObject)->
rotate(rotationMatrix);
786 shapeObject->setMaterial(mat);
791 throw std::runtime_error(
"Cannot override the sample shape because the "
792 "environment definition does not define a "
793 "default sample shape. Please either provide "
794 "a 'Shape' argument in the dictionary for the "
795 "Geometry parameter or update the environment "
796 "definition with this information.");
800 throw std::runtime_error(
"No sample environment defined, please provide "
801 "a 'Shape' argument to define the sample "
820 if (shape == ShapeArgs::CSG) {
822 }
else if (shape == ShapeArgs::FLAT_PLATE) {
824 }
else if (boost::algorithm::ends_with(shape, ShapeArgs::CYLINDER)) {
825 result =
createCylinderLikeXML(args, refFrame, boost::algorithm::equals(shape, ShapeArgs::HOLLOW_CYLINDER));
826 }
else if (boost::algorithm::ends_with(shape, ShapeArgs::FLAT_PLATE_HOLDER)) {
828 }
else if (boost::algorithm::ends_with(shape, ShapeArgs::HOLLOW_CYLINDER_HOLDER)) {
830 }
else if (boost::algorithm::ends_with(shape, ShapeArgs::SPHERE)) {
833 std::stringstream msg;
834 msg <<
"Unknown 'Shape' argument '" << shape <<
"' provided in 'Geometry' property. Allowed values are "
835 << ShapeArgs::CSG <<
", " << ShapeArgs::FLAT_PLATE <<
", " << ShapeArgs::CYLINDER <<
", "
836 << ShapeArgs::HOLLOW_CYLINDER <<
", " << ShapeArgs::FLAT_PLATE_HOLDER <<
", "
837 << ShapeArgs::HOLLOW_CYLINDER_HOLDER <<
", " << ShapeArgs::SPHERE;
838 throw std::invalid_argument(msg.str());
840 if (
g_log.
is(Logger::Priority::PRIO_DEBUG)) {
841 g_log.
debug(
"XML shape definition:\n" + result +
'\n');
854 const std::string &
id)
const {
857 auto makeV3D = [&refFrame](
double x,
double y,
double z) {
864 const double widthInCM = getPropertyAsDouble(args, ShapeArgs::WIDTH);
865 const double heightInCM = getPropertyAsDouble(args, ShapeArgs::HEIGHT);
866 const double thickInCM = getPropertyAsDouble(args, ShapeArgs::THICK);
869 const double szX = (widthInCM * 5e-3);
870 const double szY = (heightInCM * 5e-3);
871 const double szZ = (thickInCM * 5e-3);
874 auto lfb = makeV3D(szX, -szY, -szZ);
875 auto lft = makeV3D(szX, szY, -szZ);
876 auto lbb = makeV3D(szX, -szY, szZ);
877 auto rfb = makeV3D(-szX, -szY, -szZ);
879 const double angleInDegrees = getPropertyAsDouble(args, ShapeArgs::ANGLE);
881 const auto upAxis = makeV3D(0, 1, 0);
889 std::vector<double> center = {0., 0., 0.};
891 center = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
892 const V3D centrePos(center[0] * 0.01, center[1] * 0.01, center[2] * 0.01);
899 std::ostringstream xmlShapeStream;
900 xmlShapeStream <<
" <cuboid id=\"" <<
id <<
"\"> "
901 <<
"<left-front-bottom-point x=\"" << lfb.
X() <<
"\" y=\"" << lfb.Y() <<
"\" z=\"" << lfb.Z()
903 <<
"<left-front-top-point x=\"" << lft.X() <<
"\" y=\"" << lft.Y() <<
"\" z=\"" << lft.Z()
905 <<
"<left-back-bottom-point x=\"" << lbb.X() <<
"\" y=\"" << lbb.Y() <<
"\" z=\"" << lbb.Z()
907 <<
"<right-front-bottom-point x=\"" << rfb.X() <<
"\" y =\"" << rfb.Y() <<
"\" z=\"" << rfb.Z()
910 return xmlShapeStream.str();
927 std::vector<double> centre = {0., 0., 0.};
929 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
932 const double sampleThickness = getPropertyAsDouble(args, ShapeArgs::THICK);
933 const double frontPlateThickness = getPropertyAsDouble(args, ShapeArgs::FRONT_THICK);
934 const double backPlateThickness = getPropertyAsDouble(args, ShapeArgs::BACK_THICK);
937 angle = degToRad(getPropertyAsDouble(args, ShapeArgs::ANGLE));
944 auto frontPlate = args;
945 frontPlate.
setProperty(ShapeArgs::THICK, frontPlateThickness);
946 auto frontCentre = centre;
947 const double frontCentreOffset = (frontPlateThickness + sampleThickness) * 0.5;
948 frontCentre[pointingAlongBeam] -= frontCentreOffset * std::cos(angle);
949 frontCentre[pointingHorizontal] -= signHorizontal * frontCentreOffset * std::sin(angle);
950 if (!frontPlate.existsProperty(ShapeArgs::CENTER)) {
951 frontPlate.declareProperty(ShapeArgs::CENTER, frontCentre);
953 frontPlate.setProperty(ShapeArgs::CENTER, frontCentre);
956 auto backPlate = args;
957 backPlate.
setProperty(ShapeArgs::THICK, backPlateThickness);
958 auto backCentre = centre;
959 const double backCentreOffset = (backPlateThickness + sampleThickness) * 0.5;
960 backCentre[pointingAlongBeam] += backCentreOffset * std::cos(angle);
961 backCentre[pointingHorizontal] += signHorizontal * backCentreOffset * std::sin(angle);
962 if (!backPlate.existsProperty(ShapeArgs::CENTER)) {
963 backPlate.declareProperty(ShapeArgs::CENTER, backCentre);
965 backPlate.setProperty(ShapeArgs::CENTER, backCentre);
968 return frontPlateXML + backPlateXML +
"<algebra val=\"back:front\"/>";
983 auto innerCylinder = args;
984 const double innerOuterRadius = getPropertyAsDouble(args, ShapeArgs::INNER_OUTER_RADIUS);
985 innerCylinder.setProperty(ShapeArgs::OUTER_RADIUS, innerOuterRadius);
987 auto outerCylinder = args;
988 const double outerInnerRadius = getPropertyAsDouble(args, ShapeArgs::OUTER_INNER_RADIUS);
989 outerCylinder.setProperty(ShapeArgs::INNER_RADIUS, outerInnerRadius);
991 return innerCylinderXML + outerCylinderXML +
"<algebra val=\"inner:outer\"/>";
1004 const std::string &
id)
const {
1005 const std::string tag = hollow ?
"hollow-cylinder" :
"cylinder";
1006 double height = getPropertyAsDouble(args, ShapeArgs::HEIGHT);
1007 double innerRadius = hollow ? getPropertyAsDouble(args, ShapeArgs::INNER_RADIUS) : 0.0;
1008 double outerRadius =
1009 hollow ? getPropertyAsDouble(args, ShapeArgs::OUTER_RADIUS) : getPropertyAsDouble(args,
"Radius");
1010 std::vector<double> centre = {0., 0., 0.};
1012 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
1013 std::transform(centre.begin(), centre.end(), centre.begin(), [](
double val) { return val *= 0.01; });
1018 outerRadius *= 0.01;
1022 std::ostringstream XMLString;
1025 if (axis.length() == 1) {
1026 const auto axisId =
static_cast<unsigned>(std::stoi(axis));
1027 XMLString << axisXML(axisId);
1028 baseCentre = cylBaseCentre(centre,
height, axisId);
1030 const std::vector<double> axisVector = getPropertyAsVectorDouble(args, ShapeArgs::AXIS);
1031 XMLString << axisXML(axisVector);
1032 baseCentre = cylBaseCentre(centre,
height, axisVector);
1035 const auto axisId =
static_cast<unsigned>(refFrame.
pointingUp());
1036 XMLString << axisXML(axisId);
1037 baseCentre = cylBaseCentre(centre,
height, axisId);
1040 std::ostringstream xmlShapeStream;
1041 xmlShapeStream <<
"<" << tag <<
" id=\"" <<
id <<
"\"> "
1042 <<
"<centre-of-bottom-base x=\"" << baseCentre.
X() <<
"\" y=\"" << baseCentre.
Y() <<
"\" z=\""
1043 << baseCentre.
Z() <<
"\" /> " << XMLString.str() <<
"<height val=\"" <<
height <<
"\" /> ";
1045 xmlShapeStream <<
"<inner-radius val=\"" <<
innerRadius <<
"\"/>"
1046 <<
"<outer-radius val=\"" << outerRadius <<
"\"/>";
1048 xmlShapeStream <<
"<radius val=\"" << outerRadius <<
"\"/>";
1050 xmlShapeStream <<
"</" << tag <<
">";
1051 return xmlShapeStream.str();
1060 const double radius =
static_cast<double>(args.
getProperty(ShapeArgs::RADIUS)) * 0.01;
1061 std::vector<double> center = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
1062 std::transform(center.begin(), center.end(), center.begin(), [](
double val) { return val *= 0.01; });
1064 std::ostringstream xmlShapeStream;
1065 const std::string tag{
"sphere"};
1066 const auto id =
"sphere";
1067 xmlShapeStream <<
"<" << tag <<
" id=\"" <<
id <<
"\"> "
1068 <<
"<center x=\"" << center[0] <<
"\" y=\"" << center[1] <<
"\" z=\"" << center[2] <<
"\" /> "
1069 <<
"<radius val=\"" <<
radius <<
"\" /> ";
1070 xmlShapeStream <<
"</" << tag <<
">";
1071 return xmlShapeStream.str();
1088 const double numberDensity = materialArgs.
getProperty(
"SampleNumberDensity");
1092 compatible.
setProperty(
"NumberDensity", numberDensity);
1095 if (materialArgs.
existsProperty(
"SampleEffectiveNumberDensity")) {
1096 const double numberDensityEff = materialArgs.
getProperty(
"SampleEffectiveNumberDensity");
1098 compatible.
declareProperty(
"EffectiveNumberDensity", numberDensityEff);
1100 compatible.
setProperty(
"EffectiveNumberDesnity", numberDensityEff);
1104 const double packingFraction = materialArgs.
getProperty(
"SamplePackingFraction");
1108 compatible.
setProperty(
"PackingFraction", packingFraction);
1112 const double massDensity = materialArgs.
getProperty(
"SampleMassDensity");
1116 compatible.
setProperty(
"MassDensity", massDensity);
1120 const double mass = materialArgs.
getProperty(
"SampleMass");
1128 const double volume = materialArgs.
getProperty(
"SampleVolume");
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
IPeaksWorkspace_sptr workspace
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
This class is shared by a few Workspace types and holds information related to a particular experimen...
const Run & run() const
Run details object access.
Geometry::Instrument_const_sptr getInstrument() const
Returns the parameterized instrument.
const Sample & sample() const
Sample accessors.
Sample & mutableSample()
Writable version of the sample object.
const Geometry::Goniometer & getGoniometer() const
Return reference to the first const Goniometer object for this run.
void setShape(const Geometry::IObject_sptr &shape)
Update the shape of the object.
const Kernel::Material & getMaterial() const
Return the material (convenience method)
void setEnvironment(std::shared_ptr< Geometry::SampleEnvironment > env)
Set the environment used to contain the sample.
const Geometry::SampleEnvironment & getEnvironment() const
Get a reference to the sample's environment.
A property class for workspaces.
Base Workspace Abstract Class.
static void setSampleShape(API::ExperimentInfo &expt, const std::string &shapeXML)
Set the shape via an XML string on the given experiment.
This class contains code for interpreting a material input for SetSampleMaterial, validating the para...
std::unique_ptr< Kernel::Material > buildMaterial()
Construct the material,.
void setMaterialParameters(const MaterialParameters ¶ms)
Set the parameters to build the material to the builder, taking into account which values were and we...
static ValidationErrors validateInputs(const MaterialParameters ¶ms)
Validate the parameters to build the material from, this returns any errors in the inputs.
Create a single instance of a SampleEnvironment.
SampleEnvironmentSpec_uptr parseSpec(const std::string &filename, const std::string &filepath) const
Calls SampleEnvironmentSpecFileFinder::parseSpec.
Geometry::SampleEnvironment_uptr create(const std::string &facility, const std::string &instrument, const std::string &specName, const std::string &canName)
Create a new SampleEnvironment instance from the given specification and can.
High-level interface for setting sample metadata on a workspace.
std::string createHollowCylinderHolderXML(const Kernel::PropertyManager &args, const Geometry::ReferenceFrame &refFrame) const
Create the XML required to define a hollow cylinder holder from the given args Hollow cylinder holder...
std::string createSphereXML(const Kernel::PropertyManager &args) const
Create the XML required to define a sphere from the given args.
int version() const override final
Algorithm's version for identification.
bool isDictionaryPopulated(const Kernel::PropertyManager_const_sptr &dict) const
Checks if a json dictionary parameter is populated or not.
void init() override final
Initialize the algorithm's properties.
void validateMaterial(std::map< std::string, std::string > &errors, const Kernel::PropertyManager &inputArgs, const std::string &flavour)
Validates the material.
const std::string summary() const override final
Algorithm's summary for use in the GUI and help.
std::string createFlatPlateHolderXML(const Kernel::PropertyManager &args, const Geometry::ReferenceFrame &refFrame) const
Create the XML required to define a flat plate holder from the given args Flate plate holder is a CSG...
const Geometry::SampleEnvironment * setSampleEnvironmentFromFile(API::ExperimentInfo &experiment, const Kernel::PropertyManager_const_sptr &args)
Set the requested sample environment on the workspace from the environment file.
const std::string category() const override final
Algorithm's category for identification.
void setMaterial(ReadMaterial::MaterialParameters &materialParams, const Kernel::PropertyManager &materialArgs)
SetSample::setMaterial Configures a material from the parameters.
Kernel::PropertyManager materialSettingsEnsureLegacyCompatibility(const Kernel::PropertyManager &materialArgs)
Ensures the backwards compatibility of material arguments.
const Geometry::SampleEnvironment * setSampleEnvironmentFromXML(API::ExperimentInfo &experiment, const Kernel::PropertyManager_const_sptr &canGeometryArgs, const Kernel::PropertyManager_const_sptr &canMaterialArgs)
Set the requested sample environment from shape XML string.
void validateGeometry(std::map< std::string, std::string > &errors, const Kernel::PropertyManager &args, const std::string &flavour)
Validates the geometry.
void setSampleShape(API::ExperimentInfo &experiment, const Kernel::PropertyManager_const_sptr &args, const Geometry::SampleEnvironment *sampleEnv)
void assertNonNegative(std::map< std::string, std::string > &errors, const Kernel::PropertyManager &args, const std::string &flavour, const std::vector< const std::string * > &keys)
Ensures there is no specified property with negative value.
std::string tryCreateXMLFromArgsOnly(const Kernel::PropertyManager &args, const Geometry::ReferenceFrame &refFrame)
Create the required XML for a given shape type plus its arguments.
std::map< std::string, std::string > validateInputs() override final
Validate the inputs against each other.
void exec() override final
Execute the algorithm.
std::string createCylinderLikeXML(const Kernel::PropertyManager &args, const Geometry::ReferenceFrame &refFrame, bool hollow, const std::string &id="sample-shape") const
Create the XML required to define a cylinder from the given args.
std::string createFlatPlateXML(const Kernel::PropertyManager &args, const Geometry::ReferenceFrame &refFrame, const std::string &id="sample-shape") const
Create the XML required to define a flat plate from the given args.
Models a Container is used to hold a sample in the beam.
bool hasFixedSampleShape() const
std::unordered_map< std::string, double > ShapeArgs
bool hasCustomizableSampleShape() const
Class to represent a particular goniometer setting, which is described by the rotation matrix.
void pushAxis(const std::string &name, double axisx, double axisy, double axisz, double angle=0., int sense=CCW, int angUnit=angDegrees)
Add an additional axis to the goniometer, closer to the sample.
const Kernel::DblMatrix & getR() const
Return global rotation matrix.
ReferenceFrame : Holds reference frame information from the geometry description file.
PointingAlong pointingUp() const
Gets the pointing up direction.
PointingAlong pointingHorizontal() const
Gets the pointing horizontal direction, i.e perpendicular to up & along beam.
Handedness getHandedness() const
Gets the handedness.
PointingAlong pointingAlongBeam() const
Gets the beam pointing along direction.
Defines a single instance of a SampleEnvironment.
const Container & getContainer() const
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...
std::string addGoniometerTag(const Kernel::Matrix< double > &rotateMatrix, std::string xml)
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
bool is(int level) const
Returns true if at least the given log level is set.
void rotate(double const, double const, int const, int const, int const, int const)
Applies a rotation to a particular point of tan(theta)=tau.
Property manager helper class.
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void declareProperty(std::unique_ptr< Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
The concrete, templated class for properties.
Manage the lifetime of a class intended to be a singleton.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
constexpr double X() const noexcept
Get x.
double normalize()
Make a normalized vector (return norm value)
constexpr double Y() const noexcept
Get y.
constexpr double Z() const noexcept
Get z.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::unique_ptr< SampleEnvironment > SampleEnvironment_uptr
std::shared_ptr< const PropertyManager > PropertyManager_const_sptr
shared pointer to Mantid::Kernel::PropertyManager(const version)
std::shared_ptr< PropertyManager > PropertyManager_sptr
Typedef for a shared pointer to a PropertyManager.
This struct contains the parameters for constructing a material, and gives them a default value for e...
double numberDensity
The sample number density to set, defaults to EMPTY_DBL()
double coherentXSection
The coherent scattering cross section to set, defaults to EMPTY_DBL()
int massNumber
The mass number to set, defaults to 0.
double mass
The sample mass to set, defaults to EMPTY_DBL()
double packingFraction
The sample packing fraction.
double attenuationXSection
The absorption cross section to set, defaults to EMPTY_DBL()
Kernel::MaterialBuilder::NumberDensityUnit numberDensityUnit
A flag indicating the unit of sampleNumberDensity.
double volume
The sample volume to set, defaults to EMPTY_DBL()
double massDensity
The sample mass density to set, defaults to EMPTY_DBL()
double scatteringXSection
The total scattering cross section to set, defaults to EMPTY_DBL()
double incoherentXSection
The incoherent scattering cross section to set, defaults to EMPTY_DBL()
double zParameter
The zParameter to set, defaults to EMPTY_DBL()
std::string chemicalSymbol
The chemical formula to set, defaults to the empty string.
double numberDensityEffective
The sample effective number density.
double unitCellVolume
The unit cell volume to set, defaults to EMPTY_DBL()
int atomicNumber
The atomic number to set, defaults to 0.
Describes the direction (within an algorithm) of a Property.
@ InOut
Both an input & output workspace.
@ Input
An input workspace.