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 &instOnWS = instrument->getName();
587 const auto &config = ConfigService::Instance();
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 = (std::filesystem::path(direc) /
"sampleenvironments").
string();
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") {
733 const auto refFrame = experiment.
getInstrument()->getReferenceFrame();
753 const auto &props = args->getProperties();
754 for (
const auto &prop : props) {
756 const double val = getPropertyAsDouble(*args, prop->name());
757 shapeArgs.emplace(boost::algorithm::to_lower_copy(prop->name()), val * 0.01);
760 auto shapeObject = can.createSampleShape(shapeArgs);
765 if (
auto csgObj = std::dynamic_pointer_cast<Geometry::CSGObject>(shapeObject)) {
766 csgObj->setMaterial(mat);
771 throw std::runtime_error(
"The can has a fixed sample shape that cannot "
772 "be adjusted using the Geometry parameter.");
774 auto shapeObject = can.getSampleShape();
778 if (
typeid(shapeObject) ==
typeid(std::shared_ptr<Geometry::MeshObject>)) {
780 std::dynamic_pointer_cast<Geometry::MeshObject>(shapeObject)->
rotate(rotationMatrix);
784 shapeObject->setMaterial(mat);
789 throw std::runtime_error(
"Cannot override the sample shape because the "
790 "environment definition does not define a "
791 "default sample shape. Please either provide "
792 "a 'Shape' argument in the dictionary for the "
793 "Geometry parameter or update the environment "
794 "definition with this information.");
798 throw std::runtime_error(
"No sample environment defined, please provide "
799 "a 'Shape' argument to define the sample "
818 if (shape == ShapeArgs::CSG) {
820 }
else if (shape == ShapeArgs::FLAT_PLATE) {
822 }
else if (shape.ends_with(ShapeArgs::CYLINDER)) {
823 result =
createCylinderLikeXML(args, refFrame, boost::algorithm::equals(shape, ShapeArgs::HOLLOW_CYLINDER));
824 }
else if (shape.ends_with(ShapeArgs::FLAT_PLATE_HOLDER)) {
826 }
else if (shape.ends_with(ShapeArgs::HOLLOW_CYLINDER_HOLDER)) {
828 }
else if (shape.ends_with(ShapeArgs::SPHERE)) {
831 std::stringstream msg;
832 msg <<
"Unknown 'Shape' argument '" << shape <<
"' provided in 'Geometry' property. Allowed values are "
833 << ShapeArgs::CSG <<
", " << ShapeArgs::FLAT_PLATE <<
", " << ShapeArgs::CYLINDER <<
", "
834 << ShapeArgs::HOLLOW_CYLINDER <<
", " << ShapeArgs::FLAT_PLATE_HOLDER <<
", "
835 << ShapeArgs::HOLLOW_CYLINDER_HOLDER <<
", " << ShapeArgs::SPHERE;
836 throw std::invalid_argument(msg.str());
838 if (
g_log.
is(Logger::Priority::PRIO_DEBUG)) {
839 g_log.
debug(
"XML shape definition:\n" + result +
'\n');
852 const std::string &
id)
const {
855 auto makeV3D = [&refFrame](
double x,
double y,
double z) {
862 const double widthInCM = getPropertyAsDouble(args, ShapeArgs::WIDTH);
863 const double heightInCM = getPropertyAsDouble(args, ShapeArgs::HEIGHT);
864 const double thickInCM = getPropertyAsDouble(args, ShapeArgs::THICK);
867 const double szX = (widthInCM * 5e-3);
868 const double szY = (heightInCM * 5e-3);
869 const double szZ = (thickInCM * 5e-3);
872 auto lfb = makeV3D(szX, -szY, -szZ);
873 auto lft = makeV3D(szX, szY, -szZ);
874 auto lbb = makeV3D(szX, -szY, szZ);
875 auto rfb = makeV3D(-szX, -szY, -szZ);
877 const double angleInDegrees = getPropertyAsDouble(args, ShapeArgs::ANGLE);
879 const auto upAxis = makeV3D(0, 1, 0);
887 std::vector<double> center = {0., 0., 0.};
889 center = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
890 const V3D centrePos(center[0] * 0.01, center[1] * 0.01, center[2] * 0.01);
897 std::ostringstream xmlShapeStream;
898 xmlShapeStream <<
" <cuboid id=\"" <<
id <<
"\"> "
899 <<
"<left-front-bottom-point x=\"" << lfb.
X() <<
"\" y=\"" << lfb.Y() <<
"\" z=\"" << lfb.Z()
901 <<
"<left-front-top-point x=\"" << lft.X() <<
"\" y=\"" << lft.Y() <<
"\" z=\"" << lft.Z()
903 <<
"<left-back-bottom-point x=\"" << lbb.X() <<
"\" y=\"" << lbb.Y() <<
"\" z=\"" << lbb.Z()
905 <<
"<right-front-bottom-point x=\"" << rfb.X() <<
"\" y =\"" << rfb.Y() <<
"\" z=\"" << rfb.Z()
908 return xmlShapeStream.str();
925 std::vector<double> centre = {0., 0., 0.};
927 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
930 const double sampleThickness = getPropertyAsDouble(args, ShapeArgs::THICK);
931 const double frontPlateThickness = getPropertyAsDouble(args, ShapeArgs::FRONT_THICK);
932 const double backPlateThickness = getPropertyAsDouble(args, ShapeArgs::BACK_THICK);
935 angle = degToRad(getPropertyAsDouble(args, ShapeArgs::ANGLE));
942 auto frontPlate = args;
943 frontPlate.
setProperty(ShapeArgs::THICK, frontPlateThickness);
944 auto frontCentre = centre;
945 const double frontCentreOffset = (frontPlateThickness + sampleThickness) * 0.5;
946 frontCentre[pointingAlongBeam] -= frontCentreOffset * std::cos(angle);
947 frontCentre[pointingHorizontal] -= signHorizontal * frontCentreOffset * std::sin(angle);
948 if (!frontPlate.existsProperty(ShapeArgs::CENTER)) {
949 frontPlate.declareProperty(ShapeArgs::CENTER, frontCentre);
951 frontPlate.setProperty(ShapeArgs::CENTER, frontCentre);
954 auto backPlate = args;
955 backPlate.
setProperty(ShapeArgs::THICK, backPlateThickness);
956 auto backCentre = centre;
957 const double backCentreOffset = (backPlateThickness + sampleThickness) * 0.5;
958 backCentre[pointingAlongBeam] += backCentreOffset * std::cos(angle);
959 backCentre[pointingHorizontal] += signHorizontal * backCentreOffset * std::sin(angle);
960 if (!backPlate.existsProperty(ShapeArgs::CENTER)) {
961 backPlate.declareProperty(ShapeArgs::CENTER, backCentre);
963 backPlate.setProperty(ShapeArgs::CENTER, backCentre);
966 return frontPlateXML + backPlateXML +
"<algebra val=\"back:front\"/>";
981 auto innerCylinder = args;
982 const double innerOuterRadius = getPropertyAsDouble(args, ShapeArgs::INNER_OUTER_RADIUS);
983 innerCylinder.setProperty(ShapeArgs::OUTER_RADIUS, innerOuterRadius);
985 auto outerCylinder = args;
986 const double outerInnerRadius = getPropertyAsDouble(args, ShapeArgs::OUTER_INNER_RADIUS);
987 outerCylinder.setProperty(ShapeArgs::INNER_RADIUS, outerInnerRadius);
989 return innerCylinderXML + outerCylinderXML +
"<algebra val=\"inner:outer\"/>";
1002 const std::string &
id)
const {
1003 const std::string tag = hollow ?
"hollow-cylinder" :
"cylinder";
1004 double height = getPropertyAsDouble(args, ShapeArgs::HEIGHT);
1005 double innerRadius = hollow ? getPropertyAsDouble(args, ShapeArgs::INNER_RADIUS) : 0.0;
1006 double outerRadius =
1007 hollow ? getPropertyAsDouble(args, ShapeArgs::OUTER_RADIUS) : getPropertyAsDouble(args,
"Radius");
1008 std::vector<double> centre = {0., 0., 0.};
1010 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
1011 std::transform(centre.begin(), centre.end(), centre.begin(), [](
double val) { return val *= 0.01; });
1015 innerRadius *= 0.01;
1016 outerRadius *= 0.01;
1020 std::ostringstream XMLString;
1023 if (axis.length() == 1) {
1024 const auto axisId =
static_cast<unsigned>(std::stoi(axis));
1025 XMLString << axisXML(axisId);
1026 baseCentre = cylBaseCentre(centre,
height, axisId);
1028 const std::vector<double> axisVector = getPropertyAsVectorDouble(args, ShapeArgs::AXIS);
1029 XMLString << axisXML(axisVector);
1030 baseCentre = cylBaseCentre(centre,
height, axisVector);
1033 const auto axisId =
static_cast<unsigned>(refFrame.
pointingUp());
1034 XMLString << axisXML(axisId);
1035 baseCentre = cylBaseCentre(centre,
height, axisId);
1038 std::ostringstream xmlShapeStream;
1039 xmlShapeStream <<
"<" << tag <<
" id=\"" <<
id <<
"\"> "
1040 <<
"<centre-of-bottom-base x=\"" << baseCentre.
X() <<
"\" y=\"" << baseCentre.
Y() <<
"\" z=\""
1041 << baseCentre.
Z() <<
"\" /> " << XMLString.str() <<
"<height val=\"" <<
height <<
"\" /> ";
1043 xmlShapeStream <<
"<inner-radius val=\"" << innerRadius <<
"\"/>"
1044 <<
"<outer-radius val=\"" << outerRadius <<
"\"/>";
1046 xmlShapeStream <<
"<radius val=\"" << outerRadius <<
"\"/>";
1048 xmlShapeStream <<
"</" << tag <<
">";
1049 return xmlShapeStream.str();
1058 const double radius =
static_cast<double>(args.
getProperty(ShapeArgs::RADIUS)) * 0.01;
1059 std::vector<double> center = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
1060 std::transform(center.begin(), center.end(), center.begin(), [](
double val) { return val *= 0.01; });
1062 std::ostringstream xmlShapeStream;
1063 const std::string tag{
"sphere"};
1064 const auto id =
"sphere";
1065 xmlShapeStream <<
"<" << tag <<
" id=\"" <<
id <<
"\"> "
1066 <<
"<center x=\"" << center[0] <<
"\" y=\"" << center[1] <<
"\" z=\"" << center[2] <<
"\" /> "
1067 <<
"<radius val=\"" << radius <<
"\" /> ";
1068 xmlShapeStream <<
"</" << tag <<
">";
1069 return xmlShapeStream.str();
1086 const double numberDensity = materialArgs.
getProperty(
"SampleNumberDensity");
1090 compatible.
setProperty(
"NumberDensity", numberDensity);
1093 if (materialArgs.
existsProperty(
"SampleEffectiveNumberDensity")) {
1094 const double numberDensityEff = materialArgs.
getProperty(
"SampleEffectiveNumberDensity");
1096 compatible.
declareProperty(
"EffectiveNumberDensity", numberDensityEff);
1098 compatible.
setProperty(
"EffectiveNumberDesnity", numberDensityEff);
1102 const double packingFraction = materialArgs.
getProperty(
"SamplePackingFraction");
1106 compatible.
setProperty(
"PackingFraction", packingFraction);
1110 const double massDensity = materialArgs.
getProperty(
"SampleMassDensity");
1114 compatible.
setProperty(
"MassDensity", massDensity);
1118 const double mass = materialArgs.
getProperty(
"SampleMass");
1126 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, 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)
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.