31#include <boost/algorithm/string/case_conv.hpp>
32#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.; }
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 &config = ConfigService::Instance();
587 std::string facilityName, instrumentName;
589 const auto &instInfo = config.getInstrument(instOnWS);
590 instrumentName = instInfo.name();
591 facilityName = instInfo.facility().name();
592 }
catch (std::runtime_error &) {
594 facilityName = config.getFacility().name();
595 instrumentName = config.getInstrument().name();
598 const auto &instDirs = config.getInstrumentDirectories();
599 std::vector<std::string> environDirs(instDirs);
600 for (
auto &direc : environDirs) {
601 direc = (std::filesystem::path(direc) /
"sampleenvironments").
string();
603 auto finder = std::make_unique<SampleEnvironmentSpecFileFinder>(environDirs);
606 if (args->existsProperty(SEArgs::PATH)) {
607 auto sampleEnvironSpec = factory.
parseSpec(envName, args->getPropertyValue(SEArgs::PATH));
608 sampleEnviron = sampleEnvironSpec->buildEnvironment(canName);
610 sampleEnviron = factory.
create(facilityName, instrumentName, envName, canName);
627 const auto refFrame = exptInfo.
getInstrument()->getReferenceFrame();
633 if (shape->hasValidShape()) {
634 if (canMaterialArgs) {
637 setMaterial(materialParams, canMaterialCompatible);
638 if (materialParams.
volume <= 0.) {
639 materialParams.
volume = shape->volume() * CUBIC_METRE_TO_CM;
644 shape->setMaterial(*canMaterial);
683 const std::string numberDensityUnit = materialArgs.
getProperty(
"NumberDensityUnit");
684 if (numberDensityUnit ==
"Atoms") {
732 const auto refFrame = experiment.
getInstrument()->getReferenceFrame();
752 const auto &props = args->getProperties();
753 for (
const auto &prop : props) {
755 const double val = getPropertyAsDouble(*args, prop->name());
756 shapeArgs.emplace(boost::algorithm::to_lower_copy(prop->name()), val * 0.01);
759 auto shapeObject = can.createSampleShape(shapeArgs);
764 if (
auto csgObj = std::dynamic_pointer_cast<Geometry::CSGObject>(shapeObject)) {
765 csgObj->setMaterial(mat);
770 throw std::runtime_error(
"The can has a fixed sample shape that cannot "
771 "be adjusted using the Geometry parameter.");
773 auto shapeObject = can.getSampleShape();
777 if (
typeid(shapeObject) ==
typeid(std::shared_ptr<Geometry::MeshObject>)) {
779 std::dynamic_pointer_cast<Geometry::MeshObject>(shapeObject)->
rotate(rotationMatrix);
783 shapeObject->setMaterial(mat);
788 throw std::runtime_error(
"Cannot override the sample shape because the "
789 "environment definition does not define a "
790 "default sample shape. Please either provide "
791 "a 'Shape' argument in the dictionary for the "
792 "Geometry parameter or update the environment "
793 "definition with this information.");
797 throw std::runtime_error(
"No sample environment defined, please provide "
798 "a 'Shape' argument to define the sample "
817 if (shape == ShapeArgs::CSG) {
819 }
else if (shape == ShapeArgs::FLAT_PLATE) {
821 }
else if (shape.ends_with(ShapeArgs::CYLINDER)) {
822 result =
createCylinderLikeXML(args, refFrame, boost::algorithm::equals(shape, ShapeArgs::HOLLOW_CYLINDER));
823 }
else if (shape.ends_with(ShapeArgs::FLAT_PLATE_HOLDER)) {
825 }
else if (shape.ends_with(ShapeArgs::HOLLOW_CYLINDER_HOLDER)) {
827 }
else if (shape.ends_with(ShapeArgs::SPHERE)) {
830 std::stringstream msg;
831 msg <<
"Unknown 'Shape' argument '" << shape <<
"' provided in 'Geometry' property. Allowed values are "
832 << ShapeArgs::CSG <<
", " << ShapeArgs::FLAT_PLATE <<
", " << ShapeArgs::CYLINDER <<
", "
833 << ShapeArgs::HOLLOW_CYLINDER <<
", " << ShapeArgs::FLAT_PLATE_HOLDER <<
", "
834 << ShapeArgs::HOLLOW_CYLINDER_HOLDER <<
", " << ShapeArgs::SPHERE;
835 throw std::invalid_argument(msg.str());
837 if (
g_log.
is(Logger::Priority::PRIO_DEBUG)) {
838 g_log.
debug(
"XML shape definition:\n" + result +
'\n');
851 const std::string &
id)
const {
854 auto makeV3D = [&refFrame](
double x,
double y,
double z) {
861 const double widthInCM = getPropertyAsDouble(args, ShapeArgs::WIDTH);
862 const double heightInCM = getPropertyAsDouble(args, ShapeArgs::HEIGHT);
863 const double thickInCM = getPropertyAsDouble(args, ShapeArgs::THICK);
866 const double szX = (widthInCM * 5e-3);
867 const double szY = (heightInCM * 5e-3);
868 const double szZ = (thickInCM * 5e-3);
871 auto lfb = makeV3D(szX, -szY, -szZ);
872 auto lft = makeV3D(szX, szY, -szZ);
873 auto lbb = makeV3D(szX, -szY, szZ);
874 auto rfb = makeV3D(-szX, -szY, -szZ);
876 const double angleInDegrees = getPropertyAsDouble(args, ShapeArgs::ANGLE);
878 const auto upAxis = makeV3D(0, 1, 0);
886 std::vector<double> center = {0., 0., 0.};
888 center = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
889 const V3D centrePos(center[0] * 0.01, center[1] * 0.01, center[2] * 0.01);
896 std::ostringstream xmlShapeStream;
897 xmlShapeStream <<
" <cuboid id=\"" <<
id <<
"\"> "
898 <<
"<left-front-bottom-point x=\"" << lfb.
X() <<
"\" y=\"" << lfb.Y() <<
"\" z=\"" << lfb.Z()
900 <<
"<left-front-top-point x=\"" << lft.X() <<
"\" y=\"" << lft.Y() <<
"\" z=\"" << lft.Z()
902 <<
"<left-back-bottom-point x=\"" << lbb.X() <<
"\" y=\"" << lbb.Y() <<
"\" z=\"" << lbb.Z()
904 <<
"<right-front-bottom-point x=\"" << rfb.X() <<
"\" y =\"" << rfb.Y() <<
"\" z=\"" << rfb.Z()
907 return xmlShapeStream.str();
924 std::vector<double>
centre = {0., 0., 0.};
926 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
929 const double sampleThickness = getPropertyAsDouble(args, ShapeArgs::THICK);
930 const double frontPlateThickness = getPropertyAsDouble(args, ShapeArgs::FRONT_THICK);
931 const double backPlateThickness = getPropertyAsDouble(args, ShapeArgs::BACK_THICK);
934 angle = degToRad(getPropertyAsDouble(args, ShapeArgs::ANGLE));
941 auto frontPlate = args;
942 frontPlate.
setProperty(ShapeArgs::THICK, frontPlateThickness);
943 auto frontCentre =
centre;
944 const double frontCentreOffset = (frontPlateThickness + sampleThickness) * 0.5;
945 frontCentre[pointingAlongBeam] -= frontCentreOffset * std::cos(angle);
946 frontCentre[pointingHorizontal] -= signHorizontal * frontCentreOffset * std::sin(angle);
947 if (!frontPlate.existsProperty(ShapeArgs::CENTER)) {
948 frontPlate.declareProperty(ShapeArgs::CENTER, frontCentre);
950 frontPlate.setProperty(ShapeArgs::CENTER, frontCentre);
953 auto backPlate = args;
954 backPlate.
setProperty(ShapeArgs::THICK, backPlateThickness);
956 const double backCentreOffset = (backPlateThickness + sampleThickness) * 0.5;
957 backCentre[pointingAlongBeam] += backCentreOffset * std::cos(angle);
958 backCentre[pointingHorizontal] += signHorizontal * backCentreOffset * std::sin(angle);
959 if (!backPlate.existsProperty(ShapeArgs::CENTER)) {
960 backPlate.declareProperty(ShapeArgs::CENTER, backCentre);
962 backPlate.setProperty(ShapeArgs::CENTER, backCentre);
965 return frontPlateXML + backPlateXML +
"<algebra val=\"back:front\"/>";
980 auto innerCylinder = args;
981 const double innerOuterRadius = getPropertyAsDouble(args, ShapeArgs::INNER_OUTER_RADIUS);
982 innerCylinder.setProperty(ShapeArgs::OUTER_RADIUS, innerOuterRadius);
984 auto outerCylinder = args;
985 const double outerInnerRadius = getPropertyAsDouble(args, ShapeArgs::OUTER_INNER_RADIUS);
986 outerCylinder.setProperty(ShapeArgs::INNER_RADIUS, outerInnerRadius);
988 return innerCylinderXML + outerCylinderXML +
"<algebra val=\"inner:outer\"/>";
1001 const std::string &
id)
const {
1002 const std::string tag = hollow ?
"hollow-cylinder" :
"cylinder";
1003 double height = getPropertyAsDouble(args, ShapeArgs::HEIGHT);
1004 double innerRadius = hollow ? getPropertyAsDouble(args, ShapeArgs::INNER_RADIUS) : 0.0;
1005 double outerRadius =
1006 hollow ? getPropertyAsDouble(args, ShapeArgs::OUTER_RADIUS) : getPropertyAsDouble(args,
"Radius");
1007 std::vector<double>
centre = {0., 0., 0.};
1009 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
1010 std::transform(
centre.begin(),
centre.end(),
centre.begin(), [](
double val) { return val *= 0.01; });
1014 innerRadius *= 0.01;
1015 outerRadius *= 0.01;
1019 std::ostringstream XMLString;
1022 if (axis.length() == 1) {
1023 const auto axisId =
static_cast<unsigned>(std::stoi(axis));
1024 XMLString << axisXML(axisId);
1027 const std::vector<double> axisVector = getPropertyAsVectorDouble(args, ShapeArgs::AXIS);
1028 XMLString << axisXML(axisVector);
1029 baseCentre = cylBaseCentre(
centre,
height, axisVector);
1032 const auto axisId =
static_cast<unsigned>(refFrame.
pointingUp());
1033 XMLString << axisXML(axisId);
1037 std::ostringstream xmlShapeStream;
1038 xmlShapeStream <<
"<" << tag <<
" id=\"" <<
id <<
"\"> "
1039 <<
"<centre-of-bottom-base x=\"" << baseCentre.
X() <<
"\" y=\"" << baseCentre.
Y() <<
"\" z=\""
1040 << baseCentre.
Z() <<
"\" /> " << XMLString.str() <<
"<height val=\"" <<
height <<
"\" /> ";
1042 xmlShapeStream <<
"<inner-radius val=\"" << innerRadius <<
"\"/>"
1043 <<
"<outer-radius val=\"" << outerRadius <<
"\"/>";
1045 xmlShapeStream <<
"<radius val=\"" << outerRadius <<
"\"/>";
1047 xmlShapeStream <<
"</" << tag <<
">";
1048 return xmlShapeStream.str();
1057 const double radius =
static_cast<double>(args.
getProperty(ShapeArgs::RADIUS)) * 0.01;
1058 std::vector<double> center = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
1059 std::transform(center.begin(), center.end(), center.begin(), [](
double val) { return val *= 0.01; });
1061 std::ostringstream xmlShapeStream;
1062 const std::string tag{
"sphere"};
1063 const auto id =
"sphere";
1064 xmlShapeStream <<
"<" << tag <<
" id=\"" <<
id <<
"\"> "
1065 <<
"<center x=\"" << center[0] <<
"\" y=\"" << center[1] <<
"\" z=\"" << center[2] <<
"\" /> "
1066 <<
"<radius val=\"" << radius <<
"\" /> ";
1067 xmlShapeStream <<
"</" << tag <<
">";
1068 return xmlShapeStream.str();
1085 const double numberDensity = materialArgs.
getProperty(
"SampleNumberDensity");
1089 compatible.
setProperty(
"NumberDensity", numberDensity);
1092 if (materialArgs.
existsProperty(
"SampleEffectiveNumberDensity")) {
1093 const double numberDensityEff = materialArgs.
getProperty(
"SampleEffectiveNumberDensity");
1095 compatible.
declareProperty(
"EffectiveNumberDensity", numberDensityEff);
1097 compatible.
setProperty(
"EffectiveNumberDesnity", numberDensityEff);
1101 const double packingFraction = materialArgs.
getProperty(
"SamplePackingFraction");
1105 compatible.
setProperty(
"PackingFraction", packingFraction);
1109 const double massDensity = materialArgs.
getProperty(
"SampleMassDensity");
1113 compatible.
setProperty(
"MassDensity", massDensity);
1117 const double mass = materialArgs.
getProperty(
"SampleMass");
1125 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.
std::string getInstrumentName() const
Return the name of the instrument from the ComponentInfo object.
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, bool addTypeTag=true)
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)
Replace or insert the <goniometer> tag, the TOTAL rotation applied to the shape's surfaces.
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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
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.
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.
constexpr auto INPUT_WORKSPACE
std::unique_ptr< SampleEnvironment > SampleEnvironment_uptr
Mantid::Kernel::SingletonHolder< ConfigServiceImpl > ConfigService
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.