Mantid
Loading...
Searching...
No Matches
SetSample.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
10#include "MantidAPI/Run.h"
11#include "MantidAPI/Sample.h"
24#include "MantidKernel/Logger.h"
27#include "MantidKernel/Matrix.h"
30
31#include <Poco/Path.h>
32#include <boost/algorithm/string/case_conv.hpp>
33#include <boost/algorithm/string/predicate.hpp>
34
35namespace Mantid::DataHandling {
36
37using API::ExperimentInfo;
39using Geometry::Container;
40using Geometry::Goniometer;
41using Geometry::ReferenceFrame;
42using Geometry::SampleEnvironment;
43using Geometry::ShapeFactory;
44using Kernel::Logger;
45using Kernel::MaterialBuilder;
46using Kernel::PropertyManager;
48using Kernel::PropertyWithValue;
49using Kernel::V3D;
50
51namespace {
52constexpr double CUBIC_METRE_TO_CM = 100. * 100. * 100.;
53constexpr double degToRad(const double x) { return x * M_PI / 180.; }
54
56namespace PropertyNames {
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");
69} // namespace PropertyNames
71namespace SEArgs {
73const std::string NAME("Name");
75const std::string CONTAINER("Container");
77const std::string PATH("Path");
78} // namespace SEArgs
80namespace GeometryArgs {
82const std::string SHAPE("Shape");
84const std::string VALUE("Value");
85} // namespace GeometryArgs
86
88namespace ShapeArgs {
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");
129} // namespace ShapeArgs
130
138V3D cylBaseCentre(const std::vector<double> &cylCentre, double height, unsigned axisIdx) {
139 const V3D halfHeight = [&]() {
140 switch (axisIdx) {
141 case 0:
142 return V3D(0.5 * height, 0, 0);
143 case 1:
144 return V3D(0, 0.5 * height, 0);
145 case 2:
146 return V3D(0, 0, 0.5 * height);
147 default:
148 return V3D();
149 }
150 }();
151 return V3D(cylCentre[0], cylCentre[1], cylCentre[2]) - halfHeight;
152}
153
161V3D cylBaseCentre(const std::vector<double> &cylCentre, double height, const std::vector<double> &axis) {
162 using Kernel::V3D;
163 V3D axisVector = V3D{axis[0], axis[1], axis[2]};
164 axisVector.normalize();
165 return V3D(cylCentre[0], cylCentre[1], cylCentre[2]) - axisVector * height * 0.5;
166}
167
173std::string axisXML(unsigned axisIdx) {
174 switch (axisIdx) {
175 case 0:
176 return R"(<axis x="1" y="0" z="0" />)";
177 case 1:
178 return R"(<axis x="0" y="1" z="0" />)";
179 case 2:
180 return R"(<axis x="0" y="0" z="1" />)";
181 default:
182 return "";
183 }
184}
185
191std::string axisXML(const std::vector<double> &axis) {
192 std::ostringstream str;
193 str << "<axis x=\"" << axis[0] << "\" y=\"" << axis[1] << "\" z=\"" << axis[2] << "\" /> ";
194 return str.str();
195}
196
205double getPropertyAsDouble(const Kernel::PropertyManager &args, const std::string &name) {
206 return std::stod(args.getPropertyValue(name));
207}
208
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));
224 }
225 return vectorOfDoubles;
226}
227
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();
238 }
239 return false;
240}
241
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) {
252 return true;
253 }
254 }
255 return false;
256}
257
258} // namespace
259
260// Register the algorithm into the AlgorithmFactory
261DECLARE_ALGORITHM(SetSample)
262
263
264const std::string SetSample::name() const { return "SetSample"; }
265
267int SetSample::version() const { return 1; }
268
270const std::string SetSample::category() const { return "Sample"; }
271
273const std::string SetSample::summary() const {
274 return "Set properties of the sample and its environment for a workspace";
275}
276
283void SetSample::validateGeometry(std::map<std::string, std::string> &errors, const Kernel::PropertyManager &geomArgs,
284 const std::string &flavour) {
285
286 // Validate as much of the shape information as possible
287 if (existsAndNotEmptyString(geomArgs, GeometryArgs::SHAPE)) {
288 auto shape = geomArgs.getPropertyValue(GeometryArgs::SHAPE);
289 if (shape == ShapeArgs::CSG) {
290 if (!existsAndNotEmptyString(geomArgs, GeometryArgs::VALUE)) {
291 errors[flavour] = "For " + shape + " shape " + GeometryArgs::VALUE + " is required";
292 } else {
293 // check if the value is a valid shape XML
294 ShapeFactory shapeFactory;
295 auto shapeFromValue = shapeFactory.createShape(geomArgs.getPropertyValue(GeometryArgs::VALUE));
296 if (!shapeFromValue || !shapeFromValue->hasValidShape()) {
297 errors[flavour] = "Invalid XML for CSG shape value";
298 }
299 }
300 } else {
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";
304 }
305 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::THICK)) {
306 errors[flavour] = "For " + shape + " shape " + ShapeArgs::THICK + " is required";
307 }
308 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
309 errors[flavour] = "For " + shape + " shape " + ShapeArgs::HEIGHT + " is required";
310 }
311 }
312 if (shape == ShapeArgs::CYLINDER) {
313 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::RADIUS)) {
314 errors[flavour] = "For " + shape + " shape " + ShapeArgs::RADIUS + " is required";
315 }
316 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
317 errors[flavour] = "For " + shape + " shape " + ShapeArgs::HEIGHT + " is required";
318 }
319 }
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";
323 }
324 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::OUTER_RADIUS)) {
325 errors[flavour] = "For " + shape + " shape " + ShapeArgs::OUTER_RADIUS + " is required";
326 }
327 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
328 errors[flavour] = "For " + shape + " shape " + ShapeArgs::HEIGHT + " is required";
329 }
330 }
331 if (shape == ShapeArgs::FLAT_PLATE_HOLDER) {
332 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::WIDTH)) {
333 errors[flavour] = "For " + shape + " shape " + ShapeArgs::WIDTH + " is required";
334 }
335 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::FRONT_THICK)) {
336 errors[flavour] = "For " + shape + " shape " + ShapeArgs::FRONT_THICK + " is required";
337 }
338 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::BACK_THICK)) {
339 errors[flavour] = "For " + shape + " shape " + ShapeArgs::BACK_THICK + " is required";
340 }
341 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
342 errors[flavour] = "For " + shape + " shape " + ShapeArgs::HEIGHT + " is required";
343 }
344 }
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";
348 }
349 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::OUTER_INNER_RADIUS)) {
350 errors[flavour] = "For " + shape + " shape " + ShapeArgs::OUTER_INNER_RADIUS + " is required";
351 }
352 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::HEIGHT)) {
353 errors[flavour] = "For " + shape + " shape " + ShapeArgs::HEIGHT + " is required";
354 }
355 }
356 if (shape == ShapeArgs::SPHERE) {
357 if (!existsAndNotEmptyString(geomArgs, ShapeArgs::RADIUS)) {
358 errors[flavour] = "For " + shape + " shape " + ShapeArgs::RADIUS + " is required";
359 }
360 }
361 }
362 } else {
363 errors[flavour] = GeometryArgs::SHAPE + " is required";
364 }
365}
366
373void SetSample::validateMaterial(std::map<std::string, std::string> &errors, const Kernel::PropertyManager &inputArgs,
374 const std::string &flavour) {
377 setMaterial(materialParams, args);
378 auto materialErrors = ReadMaterial::validateInputs(materialParams);
379 if (!materialErrors.empty()) {
380 std::stringstream ss;
381 for (const auto &error : materialErrors) {
382 ss << error.first << ":" << error.second << "\n";
383 }
384 errors[flavour] = ss.str();
385 }
386}
387
395void SetSample::assertNonNegative(std::map<std::string, std::string> &errors, const Kernel::PropertyManager &geomArgs,
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";
401 }
402 }
403 }
404}
405
411 bool isPopulated = false;
412 if (dict)
413 if (dict->propertyCount() > 0)
414 isPopulated = true;
415 return isPopulated;
416}
417
419std::map<std::string, std::string> SetSample::validateInputs() {
420 std::map<std::string, std::string> errors;
421 // Check workspace type has ExperimentInfo fields
424 Workspace_sptr inputWS = getProperty(PropertyNames::INPUT_WORKSPACE);
425 if (!std::dynamic_pointer_cast<ExperimentInfo>(inputWS)) {
426 errors[PropertyNames::INPUT_WORKSPACE] = "InputWorkspace type invalid. "
427 "Expected MatrixWorkspace, "
428 "PeaksWorkspace.";
429 }
430
431 const PropertyManager_const_sptr geomArgs = getProperty(PropertyNames::GEOMETRY);
432
433 const PropertyManager_const_sptr materialArgs = getProperty(PropertyNames::MATERIAL);
434
435 const PropertyManager_const_sptr environArgs = getProperty(PropertyNames::ENVIRONMENT);
436
437 const PropertyManager_const_sptr canGeomArgs = getProperty(PropertyNames::CONTAINER_GEOMETRY);
438
439 const PropertyManager_const_sptr canMaterialArgs = getProperty(PropertyNames::CONTAINER_MATERIAL);
440
441 const std::vector<const std::string *> positiveValues = {{&ShapeArgs::HEIGHT, &ShapeArgs::WIDTH, &ShapeArgs::THICK,
442 &ShapeArgs::RADIUS, &ShapeArgs::INNER_RADIUS,
443 &ShapeArgs::OUTER_RADIUS}};
444
445 if (!isDictionaryPopulated(geomArgs) && !isDictionaryPopulated(materialArgs) && !isDictionaryPopulated(environArgs) &&
446 !isDictionaryPopulated(canGeomArgs) && !isDictionaryPopulated(canMaterialArgs)) {
447 errors["Geometry"] = "At least one of the input parameters must be populated";
448 }
449
450 if (isDictionaryPopulated(environArgs)) {
451 if (!existsAndNotEmptyString(*environArgs, SEArgs::NAME)) {
452 errors[PropertyNames::ENVIRONMENT] = "Environment flags require a non-empty 'Name' entry.";
453 } else {
454 // If specifying the environment through XML file, we can not strictly
455 // validate the sample settings, since only the overriding properties
456 // are specified. Hence we just make sure that whatever is specified is
457 // at least positive
458 if (isDictionaryPopulated(geomArgs)) {
459 assertNonNegative(errors, *geomArgs, PropertyNames::GEOMETRY, positiveValues);
460 }
461 }
462 } else {
463 // We cannot strictly require geometry and material to be defined
464 // simultaneously; it can be that one is defined at a later time
465 if (isDictionaryPopulated(geomArgs)) {
466 assertNonNegative(errors, *geomArgs, PropertyNames::GEOMETRY, positiveValues);
467 validateGeometry(errors, *geomArgs, PropertyNames::GEOMETRY);
468 }
469 if (isDictionaryPopulated(materialArgs)) {
470 validateMaterial(errors, *materialArgs, PropertyNames::MATERIAL);
471 }
472 }
473 if (isDictionaryPopulated(canGeomArgs)) {
474 assertNonNegative(errors, *canGeomArgs, PropertyNames::CONTAINER_GEOMETRY, positiveValues);
475 validateGeometry(errors, *canGeomArgs, PropertyNames::CONTAINER_GEOMETRY);
476 }
477
478 if (isDictionaryPopulated(canMaterialArgs)) {
479 validateMaterial(errors, *canMaterialArgs, PropertyNames::CONTAINER_MATERIAL);
480 }
481 return errors;
482}
483
488 using API::Workspace;
490 using Kernel::Direction;
492
493 // Inputs
494 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>(PropertyNames::INPUT_WORKSPACE, "", Direction::InOut),
495 "A workspace whose sample properties will be updated");
496 declareProperty(std::make_unique<PropertyManagerProperty>(PropertyNames::GEOMETRY, Direction::Input),
497 "A dictionary of geometry parameters for the sample.");
498 declareProperty(std::make_unique<PropertyManagerProperty>(PropertyNames::MATERIAL, Direction::Input),
499 "A dictionary of material parameters for the sample. See "
500 "SetSampleMaterial for all accepted parameters");
501 declareProperty(std::make_unique<PropertyManagerProperty>(PropertyNames::ENVIRONMENT, Direction::Input),
502 "A dictionary of parameters to configure the sample environment");
503 declareProperty(std::make_unique<PropertyManagerProperty>(PropertyNames::CONTAINER_GEOMETRY, Direction::Input),
504 "A dictionary of geometry parameters for the container.");
505 declareProperty(std::make_unique<PropertyManagerProperty>(PropertyNames::CONTAINER_MATERIAL, Direction::Input),
506 "A dictionary of material parameters for the container.");
507}
508
515
516 Workspace_sptr workspace = getProperty(PropertyNames::INPUT_WORKSPACE);
517 PropertyManager_sptr environArgs = getProperty(PropertyNames::ENVIRONMENT);
518 PropertyManager_sptr geometryArgs = getProperty(PropertyNames::GEOMETRY);
519 PropertyManager_sptr materialArgs = getProperty(PropertyNames::MATERIAL);
520 PropertyManager_sptr canGeometryArgs = getProperty(PropertyNames::CONTAINER_GEOMETRY);
521 PropertyManager_sptr canMaterialArgs = getProperty(PropertyNames::CONTAINER_MATERIAL);
522
523 // validateInputs guarantees this will be an ExperimentInfo object
524 auto experimentInfo = std::dynamic_pointer_cast<ExperimentInfo>(workspace);
525 // The order here is important. Set the environment first. If this
526 // defines a sample geometry then we can process the Geometry flags
527 // combined with this
528 const SampleEnvironment *sampleEnviron(nullptr);
529 if (isDictionaryPopulated(environArgs)) {
530 sampleEnviron = setSampleEnvironmentFromFile(*experimentInfo, environArgs);
531 } else if (isDictionaryPopulated(canGeometryArgs)) {
532 setSampleEnvironmentFromXML(*experimentInfo, canGeometryArgs, canMaterialArgs);
533 }
534
535 double sampleVolume = 0.;
536 if (isDictionaryPopulated(geometryArgs) || sampleEnviron) {
537 setSampleShape(*experimentInfo, geometryArgs, sampleEnviron);
538 if (experimentInfo->sample().getShape().hasValidShape()) {
539 // get the volume back out to use in setting the material
540 sampleVolume = CUBIC_METRE_TO_CM * experimentInfo->sample().getShape().volume();
541 }
542 }
543
544 // Finally the material arguments
545 if (isDictionaryPopulated(materialArgs)) {
546 PropertyManager materialArgsCompatible = materialSettingsEnsureLegacyCompatibility(*materialArgs);
547 // add the sample volume if it was defined/determined
548 if (sampleVolume > 0.) {
549 // only add the volume if it isn't already specfied
550 if (!materialArgsCompatible.existsProperty("Volume")) {
551 materialArgsCompatible.declareProperty(std::make_unique<PropertyWithValue<double>>("Volume", sampleVolume));
552 }
553 }
554 // this does what SetSampleMaterial would do, but without calling it
556 setMaterial(materialParams, materialArgsCompatible);
557 ReadMaterial reader;
558 reader.setMaterialParameters(materialParams);
559 const auto sampleMaterial = reader.buildMaterial();
560 auto shapeObject =
561 std::shared_ptr<Geometry::IObject>(experimentInfo->sample().getShape().cloneWithMaterial(*sampleMaterial));
562 experimentInfo->mutableSample().setShape(shapeObject);
563 }
564}
565
576
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);
581 }
582 // The specifications need to be qualified by the facility and instrument.
583 // Check instrument for name and then lookup facility if facility
584 // is unknown then set to default facility & instrument.
585 auto instrument = exptInfo.getInstrument();
586 const auto &instOnWS = instrument->getName();
587 const auto &config = ConfigService::Instance();
588 std::string facilityName, instrumentName;
589 try {
590 const auto &instInfo = config.getInstrument(instOnWS);
591 instrumentName = instInfo.name();
592 facilityName = instInfo.facility().name();
593 } catch (std::runtime_error &) {
594 // use default facility/instrument
595 facilityName = config.getFacility().name();
596 instrumentName = config.getInstrument().name();
597 }
598
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();
603 }
604 auto finder = std::make_unique<SampleEnvironmentSpecFileFinder>(environDirs);
605 SampleEnvironmentFactory factory(std::move(finder));
607 if (args->existsProperty(SEArgs::PATH)) {
608 auto sampleEnvironSpec = factory.parseSpec(envName, args->getPropertyValue(SEArgs::PATH));
609 sampleEnviron = sampleEnvironSpec->buildEnvironment(canName);
610 } else {
611 sampleEnviron = factory.create(facilityName, instrumentName, envName, canName);
612 }
613 exptInfo.mutableSample().setEnvironment(std::move(sampleEnviron));
614 return &(exptInfo.sample().getEnvironment());
615}
616
626 const Kernel::PropertyManager_const_sptr &canGeomArgs,
627 const Kernel::PropertyManager_const_sptr &canMaterialArgs) {
628 const auto refFrame = exptInfo.getInstrument()->getReferenceFrame();
629 const auto xml = tryCreateXMLFromArgsOnly(*canGeomArgs, *refFrame);
630 if (!xml.empty()) {
631 ShapeFactory sFactory;
632 // Create the object
633 auto shape = sFactory.createShape(xml);
634 if (shape->hasValidShape()) {
635 if (canMaterialArgs) {
636 PropertyManager canMaterialCompatible = materialSettingsEnsureLegacyCompatibility(*canMaterialArgs);
638 setMaterial(materialParams, canMaterialCompatible);
639 if (materialParams.volume <= 0.) {
640 materialParams.volume = shape->volume() * CUBIC_METRE_TO_CM;
641 }
642 ReadMaterial reader;
643 reader.setMaterialParameters(materialParams);
644 auto canMaterial = reader.buildMaterial();
645 shape->setMaterial(*canMaterial);
646 }
647 const SampleEnvironment se("unnamed", std::make_shared<Container>(shape));
648 exptInfo.mutableSample().setEnvironment(std::make_unique<SampleEnvironment>(se));
649 }
650 }
651 return &(exptInfo.sample().getEnvironment());
652}
653
661 const Kernel::PropertyManager &materialArgs) {
662 if (materialArgs.existsProperty("ChemicalFormula")) {
663 materialParams.chemicalSymbol = materialArgs.getPropertyValue("ChemicalFormula");
664 }
665 if (materialArgs.existsProperty("AtomicNumber")) {
666 materialParams.atomicNumber = materialArgs.getProperty("AtomicNumber");
667 }
668 if (materialArgs.existsProperty("MassNumber")) {
669 materialParams.massNumber = materialArgs.getProperty("MassNumber");
670 }
671 if (materialArgs.existsProperty("CoherentXSection")) {
672 materialParams.coherentXSection = materialArgs.getProperty("CoherentXSection");
673 }
674 if (materialArgs.existsProperty("IncoherentXSection")) {
675 materialParams.incoherentXSection = materialArgs.getProperty("IncoherentXSection");
676 }
677 if (materialArgs.existsProperty("AttenuationXSection")) {
678 materialParams.attenuationXSection = materialArgs.getProperty("AttenuationXSection");
679 }
680 if (materialArgs.existsProperty("ScatteringXSection")) {
681 materialParams.scatteringXSection = materialArgs.getProperty("ScatteringXSection");
682 }
683 if (materialArgs.existsProperty("NumberDensityUnit")) {
684 const std::string numberDensityUnit = materialArgs.getProperty("NumberDensityUnit");
685 if (numberDensityUnit == "Atoms") {
687 } else {
689 }
690 }
691 if (materialArgs.existsProperty("ZParameter")) {
692 materialParams.zParameter = materialArgs.getProperty("ZParameter");
693 }
694 if (materialArgs.existsProperty("UnitCellVolume")) {
695 materialParams.unitCellVolume = materialArgs.getProperty("UnitCellVolume");
696 }
697 if (materialArgs.existsProperty("NumberDensity")) {
698 materialParams.numberDensity = materialArgs.getProperty("NumberDensity");
699 }
700 if (materialArgs.existsProperty("MassDensity")) {
701 materialParams.massDensity = materialArgs.getProperty("MassDensity");
702 }
703 if (materialArgs.existsProperty("EffectiveNumberDensity")) {
704 materialParams.numberDensityEffective = materialArgs.getProperty("EffectiveNumberDensity");
705 }
706 if (materialArgs.existsProperty("PackingFraction")) {
707 materialParams.packingFraction = materialArgs.getProperty("packingFraction");
708 }
709 if (materialArgs.existsProperty("Mass")) {
710 materialParams.mass = materialArgs.getProperty("Mass");
711 }
712 if (materialArgs.existsProperty("Volume")) {
713 materialParams.volume = materialArgs.getProperty("Volume");
714 }
715}
716
725 const Geometry::SampleEnvironment *sampleEnv) {
727 /* The sample geometry can be specified in two ways:
728 - a known set of primitive shapes with values or CSG string
729 - or a <samplegeometry> field sample environment can, with values possible
730 overridden by the Geometry flags
731 */
732
733 // Try known shapes or CSG first if supplied
734 if (isDictionaryPopulated(args)) {
735 const auto refFrame = experiment.getInstrument()->getReferenceFrame();
736 auto xml = tryCreateXMLFromArgsOnly(*args, *refFrame);
737 if (!xml.empty()) {
738 Kernel::Matrix<double> rotationMatrix = experiment.run().getGoniometer().getR();
739 if (rotationMatrix != Kernel::Matrix<double>(3, 3, true) && !sampleEnv) {
740 // Only add goniometer tag if rotationMatrix is not the Identity,
741 // and this shape is not defined within a sample environment
742 xml = Geometry::ShapeFactory().addGoniometerTag(rotationMatrix, xml);
743 }
744 CreateSampleShape::setSampleShape(experiment, xml);
745 return;
746 }
747 }
748 // Any arguments in the args dict are assumed to be values that should
749 // override the default set by the sampleEnv samplegeometry if it exists
750 if (sampleEnv) {
751 const auto &can = sampleEnv->getContainer();
752 if (sampleEnv->getContainer().hasCustomizableSampleShape()) {
753 Container::ShapeArgs shapeArgs;
754 if (isDictionaryPopulated(args)) {
755 const auto &props = args->getProperties();
756 for (const auto &prop : props) {
757 // assume in cm
758 const double val = getPropertyAsDouble(*args, prop->name());
759 shapeArgs.emplace(boost::algorithm::to_lower_copy(prop->name()), val * 0.01);
760 }
761 }
762 auto shapeObject = can.createSampleShape(shapeArgs);
763 // Given that the object is a CSG object, set the object
764 // directly on the sample ensuring we preserve the
765 // material.
766 const auto mat = experiment.sample().getMaterial();
767 if (auto csgObj = std::dynamic_pointer_cast<Geometry::CSGObject>(shapeObject)) {
768 csgObj->setMaterial(mat);
769 }
770 experiment.mutableSample().setShape(shapeObject);
771 } else if (sampleEnv->getContainer().hasFixedSampleShape()) {
772 if (isDictionaryPopulated(args)) {
773 throw std::runtime_error("The can has a fixed sample shape that cannot "
774 "be adjusted using the Geometry parameter.");
775 }
776 auto shapeObject = can.getSampleShape();
777
778 // apply Goniometer rotation
779 // Rotate only implemented on mesh objects so far
780 if (typeid(shapeObject) == typeid(std::shared_ptr<Geometry::MeshObject>)) {
781 const std::vector<double> rotationMatrix = experiment.run().getGoniometer().getR();
782 std::dynamic_pointer_cast<Geometry::MeshObject>(shapeObject)->rotate(rotationMatrix);
783 }
784
785 const auto mat = experiment.sample().getMaterial();
786 shapeObject->setMaterial(mat);
787
788 experiment.mutableSample().setShape(shapeObject);
789 } else {
790 if (isDictionaryPopulated(args)) {
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.");
797 }
798 }
799 } else {
800 throw std::runtime_error("No sample environment defined, please provide "
801 "a 'Shape' argument to define the sample "
802 "shape.");
803 }
804}
805
813 const Geometry::ReferenceFrame &refFrame) {
814 std::string result;
815 if (!args.existsProperty(GeometryArgs::SHAPE)) {
816 return result;
817 }
818
819 const auto shape = args.getPropertyValue(GeometryArgs::SHAPE);
820 if (shape == ShapeArgs::CSG) {
821 result = args.getPropertyValue("Value");
822 } else if (shape == ShapeArgs::FLAT_PLATE) {
823 result = createFlatPlateXML(args, refFrame);
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)) {
827 result = createFlatPlateHolderXML(args, refFrame);
828 } else if (boost::algorithm::ends_with(shape, ShapeArgs::HOLLOW_CYLINDER_HOLDER)) {
829 result = createHollowCylinderHolderXML(args, refFrame);
830 } else if (boost::algorithm::ends_with(shape, ShapeArgs::SPHERE)) {
831 result = createSphereXML(args);
832 } else {
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());
839 }
840 if (g_log.is(Logger::Priority::PRIO_DEBUG)) {
841 g_log.debug("XML shape definition:\n" + result + '\n');
842 }
843 return result;
844}
845
854 const std::string &id) const {
855 // Helper to take 3 coordinates and turn them to a V3D respecting the
856 // current reference frame
857 auto makeV3D = [&refFrame](double x, double y, double z) {
858 V3D v;
859 v[refFrame.pointingHorizontal()] = x;
860 v[refFrame.pointingUp()] = y;
861 v[refFrame.pointingAlongBeam()] = z;
862 return v;
863 };
864 const double widthInCM = getPropertyAsDouble(args, ShapeArgs::WIDTH);
865 const double heightInCM = getPropertyAsDouble(args, ShapeArgs::HEIGHT);
866 const double thickInCM = getPropertyAsDouble(args, ShapeArgs::THICK);
867
868 // Convert to half-"width" in metres
869 const double szX = (widthInCM * 5e-3);
870 const double szY = (heightInCM * 5e-3);
871 const double szZ = (thickInCM * 5e-3);
872 // Contruct cuboid corners. Define points about origin, rotate and then
873 // translate to final center position
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);
878 if (args.existsProperty(ShapeArgs::ANGLE)) {
879 const double angleInDegrees = getPropertyAsDouble(args, ShapeArgs::ANGLE);
880 Goniometer gr;
881 const auto upAxis = makeV3D(0, 1, 0);
882 gr.pushAxis("up", upAxis.X(), upAxis.Y(), upAxis.Z(), angleInDegrees, Geometry::CCW, Geometry::angDegrees);
883 auto &rotation = gr.getR();
884 lfb.rotate(rotation);
885 lft.rotate(rotation);
886 lbb.rotate(rotation);
887 rfb.rotate(rotation);
888 }
889 std::vector<double> center = {0., 0., 0.};
890 if (args.existsProperty(ShapeArgs::CENTER)) {
891 center = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
892 const V3D centrePos(center[0] * 0.01, center[1] * 0.01, center[2] * 0.01);
893 // translate to true center after rotation
894 lfb += centrePos;
895 lft += centrePos;
896 lbb += centrePos;
897 rfb += centrePos;
898 }
899 std::ostringstream xmlShapeStream;
900 xmlShapeStream << " <cuboid id=\"" << id << "\"> "
901 << "<left-front-bottom-point x=\"" << lfb.X() << "\" y=\"" << lfb.Y() << "\" z=\"" << lfb.Z()
902 << "\" /> "
903 << "<left-front-top-point x=\"" << lft.X() << "\" y=\"" << lft.Y() << "\" z=\"" << lft.Z()
904 << "\" /> "
905 << "<left-back-bottom-point x=\"" << lbb.X() << "\" y=\"" << lbb.Y() << "\" z=\"" << lbb.Z()
906 << "\" /> "
907 << "<right-front-bottom-point x=\"" << rfb.X() << "\" y =\"" << rfb.Y() << "\" z=\"" << rfb.Z()
908 << "\" /> "
909 << "</cuboid>";
910 return xmlShapeStream.str();
911}
912
925 const Geometry::ReferenceFrame &refFrame) const {
926
927 std::vector<double> centre = {0., 0., 0.};
928 if (args.existsProperty(ShapeArgs::CENTER)) {
929 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
930 }
931
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);
935 double angle = 0.;
936 if (args.existsProperty(ShapeArgs::ANGLE)) {
937 angle = degToRad(getPropertyAsDouble(args, ShapeArgs::ANGLE));
938 }
939 const auto pointingAlongBeam = refFrame.pointingAlongBeam();
940 const auto pointingHorizontal = refFrame.pointingHorizontal();
941 const auto handedness = refFrame.getHandedness();
942 const int signHorizontal = (handedness == Mantid::Geometry::Handedness::Right) ? 1 : -1;
943
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);
952 }
953 frontPlate.setProperty(ShapeArgs::CENTER, frontCentre);
954 const std::string frontPlateXML = createFlatPlateXML(frontPlate, refFrame, "front");
955
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);
964 }
965 backPlate.setProperty(ShapeArgs::CENTER, backCentre);
966 const std::string backPlateXML = createFlatPlateXML(backPlate, refFrame, "back");
967
968 return frontPlateXML + backPlateXML + "<algebra val=\"back:front\"/>";
969}
970
982 const Geometry::ReferenceFrame &refFrame) const {
983 auto innerCylinder = args;
984 const double innerOuterRadius = getPropertyAsDouble(args, ShapeArgs::INNER_OUTER_RADIUS);
985 innerCylinder.setProperty(ShapeArgs::OUTER_RADIUS, innerOuterRadius);
986 const std::string innerCylinderXML = createCylinderLikeXML(innerCylinder, refFrame, true, "inner");
987 auto outerCylinder = args;
988 const double outerInnerRadius = getPropertyAsDouble(args, ShapeArgs::OUTER_INNER_RADIUS);
989 outerCylinder.setProperty(ShapeArgs::INNER_RADIUS, outerInnerRadius);
990 const std::string outerCylinderXML = createCylinderLikeXML(outerCylinder, refFrame, true, "outer");
991 return innerCylinderXML + outerCylinderXML + "<algebra val=\"inner:outer\"/>";
992}
993
1003 const Geometry::ReferenceFrame &refFrame, bool hollow,
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.};
1011 if (args.existsProperty(ShapeArgs::CENTER)) {
1012 centre = getPropertyAsVectorDouble(args, ShapeArgs::CENTER);
1013 std::transform(centre.begin(), centre.end(), centre.begin(), [](double val) { return val *= 0.01; });
1014 }
1015 // convert to metres
1016 height *= 0.01;
1017 innerRadius *= 0.01;
1018 outerRadius *= 0.01;
1019 // XML needs center position of bottom base but user specifies center of
1020 // cylinder
1021 V3D baseCentre;
1022 std::ostringstream XMLString;
1023 if (args.existsProperty(ShapeArgs::AXIS)) {
1024 const std::string axis = args.getPropertyValue(ShapeArgs::AXIS);
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);
1029 } else {
1030 const std::vector<double> axisVector = getPropertyAsVectorDouble(args, ShapeArgs::AXIS);
1031 XMLString << axisXML(axisVector);
1032 baseCentre = cylBaseCentre(centre, height, axisVector);
1033 }
1034 } else {
1035 const auto axisId = static_cast<unsigned>(refFrame.pointingUp());
1036 XMLString << axisXML(axisId);
1037 baseCentre = cylBaseCentre(centre, height, axisId);
1038 }
1039
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 << "\" /> ";
1044 if (hollow) {
1045 xmlShapeStream << "<inner-radius val=\"" << innerRadius << "\"/>"
1046 << "<outer-radius val=\"" << outerRadius << "\"/>";
1047 } else {
1048 xmlShapeStream << "<radius val=\"" << outerRadius << "\"/>";
1049 }
1050 xmlShapeStream << "</" << tag << ">";
1051 return xmlShapeStream.str();
1052}
1053
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; });
1063
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();
1072}
1073
1080 PropertyManager compatible(materialArgs);
1081
1082 // The material should be agnostic whether it's sample's material or
1083 // container's so in the properties below there should be no sample prefix,
1084 // i.e. NumberDensity instead of SampleNumberDensity.
1085 // However, for legacy compatibility, those prefixed with Sample are still
1086 // considered through aliases
1087 if (materialArgs.existsProperty("SampleNumberDensity")) {
1088 const double numberDensity = materialArgs.getProperty("SampleNumberDensity");
1089 if (!compatible.existsProperty("NumberDensity")) {
1090 compatible.declareProperty("NumberDensity", numberDensity);
1091 } else {
1092 compatible.setProperty("NumberDensity", numberDensity);
1093 }
1094 }
1095 if (materialArgs.existsProperty("SampleEffectiveNumberDensity")) {
1096 const double numberDensityEff = materialArgs.getProperty("SampleEffectiveNumberDensity");
1097 if (!compatible.existsProperty("EffectiveNumberDensity")) {
1098 compatible.declareProperty("EffectiveNumberDensity", numberDensityEff);
1099 } else {
1100 compatible.setProperty("EffectiveNumberDesnity", numberDensityEff);
1101 }
1102 }
1103 if (materialArgs.existsProperty("SamplePackingFraction")) {
1104 const double packingFraction = materialArgs.getProperty("SamplePackingFraction");
1105 if (!compatible.existsProperty("PackingFraction")) {
1106 compatible.declareProperty("PackingFraction", packingFraction);
1107 } else {
1108 compatible.setProperty("PackingFraction", packingFraction);
1109 }
1110 }
1111 if (materialArgs.existsProperty("SampleMassDensity")) {
1112 const double massDensity = materialArgs.getProperty("SampleMassDensity");
1113 if (!compatible.existsProperty("MassDensity")) {
1114 compatible.declareProperty("MassDensity", massDensity);
1115 } else {
1116 compatible.setProperty("MassDensity", massDensity);
1117 }
1118 }
1119 if (materialArgs.existsProperty("SampleMass")) {
1120 const double mass = materialArgs.getProperty("SampleMass");
1121 if (!compatible.existsProperty("Mass")) {
1122 compatible.declareProperty("Mass", mass);
1123 } else {
1124 compatible.setProperty("Mass", mass);
1125 }
1126 }
1127 if (materialArgs.existsProperty("SampleVolume")) {
1128 const double volume = materialArgs.getProperty("SampleVolume");
1129 if (!compatible.existsProperty("Volume")) {
1130 compatible.declareProperty("Volume", volume);
1131 } else {
1132 compatible.setProperty("Volume", volume);
1133 }
1134 }
1135 return compatible;
1136}
1137} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double value
The value of the point.
Definition: FitMW.cpp:51
double height
Definition: GetAllEi.cpp:155
double error
Definition: IndexPeaks.cpp:133
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
double radius
Definition: Rasterize.cpp:31
double innerRadius
Definition: Rasterize.cpp:39
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
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.
Definition: Run.cpp:324
void setShape(const Geometry::IObject_sptr &shape)
Update the shape of the object.
Definition: Sample.cpp:116
const Kernel::Material & getMaterial() const
Return the material (convenience method)
Definition: Sample.cpp:127
void setEnvironment(std::shared_ptr< Geometry::SampleEnvironment > env)
Set the environment used to contain the sample.
Definition: Sample.cpp:148
const Geometry::SampleEnvironment & getEnvironment() const
Get a reference to the sample's environment.
Definition: Sample.cpp:136
A property class for workspaces.
Base Workspace Abstract Class.
Definition: Workspace.h:30
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...
Definition: ReadMaterial.h:26
std::unique_ptr< Kernel::Material > buildMaterial()
Construct the material,.
void setMaterialParameters(const MaterialParameters &params)
Set the parameters to build the material to the builder, taking into account which values were and we...
static ValidationErrors validateInputs(const MaterialParameters &params)
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.
Definition: SetSample.h:27
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...
Definition: SetSample.cpp:981
std::string createSphereXML(const Kernel::PropertyManager &args) const
Create the XML required to define a sphere from the given args.
Definition: SetSample.cpp:1059
int version() const override final
Algorithm's version for identification.
Definition: SetSample.cpp:267
bool isDictionaryPopulated(const Kernel::PropertyManager_const_sptr &dict) const
Checks if a json dictionary parameter is populated or not.
Definition: SetSample.cpp:410
void init() override final
Initialize the algorithm's properties.
Definition: SetSample.cpp:487
void validateMaterial(std::map< std::string, std::string > &errors, const Kernel::PropertyManager &inputArgs, const std::string &flavour)
Validates the material.
Definition: SetSample.cpp:373
const std::string summary() const override final
Algorithm's summary for use in the GUI and help.
Definition: SetSample.cpp:273
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...
Definition: SetSample.cpp:924
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.
Definition: SetSample.cpp:574
const std::string category() const override final
Algorithm's category for identification.
Definition: SetSample.cpp:270
void setMaterial(ReadMaterial::MaterialParameters &materialParams, const Kernel::PropertyManager &materialArgs)
SetSample::setMaterial Configures a material from the parameters.
Definition: SetSample.cpp:660
Kernel::PropertyManager materialSettingsEnsureLegacyCompatibility(const Kernel::PropertyManager &materialArgs)
Ensures the backwards compatibility of material arguments.
Definition: SetSample.cpp:1079
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.
Definition: SetSample.cpp:625
void validateGeometry(std::map< std::string, std::string > &errors, const Kernel::PropertyManager &args, const std::string &flavour)
Validates the geometry.
Definition: SetSample.cpp:283
void setSampleShape(API::ExperimentInfo &experiment, const Kernel::PropertyManager_const_sptr &args, const Geometry::SampleEnvironment *sampleEnv)
Definition: SetSample.cpp:724
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.
Definition: SetSample.cpp:395
std::string tryCreateXMLFromArgsOnly(const Kernel::PropertyManager &args, const Geometry::ReferenceFrame &refFrame)
Create the required XML for a given shape type plus its arguments.
Definition: SetSample.cpp:812
std::map< std::string, std::string > validateInputs() override final
Validate the inputs against each other.
Definition: SetSample.cpp:419
void exec() override final
Execute the algorithm.
Definition: SetSample.cpp:512
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.
Definition: SetSample.cpp:1002
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.
Definition: SetSample.cpp:853
Models a Container is used to hold a sample in the beam.
Definition: Container.h:24
bool hasFixedSampleShape() const
Definition: Container.cpp:84
std::unordered_map< std::string, double > ShapeArgs
Definition: Container.h:26
bool hasCustomizableSampleShape() const
Definition: Container.cpp:78
Class to represent a particular goniometer setting, which is described by the rotation matrix.
Definition: Goniometer.h:55
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.
Definition: Goniometer.cpp:133
const Kernel::DblMatrix & getR() const
Return global rotation matrix.
Definition: Goniometer.cpp:80
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.
Definition: ShapeFactory.h:89
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
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.
Definition: Logger.cpp:114
bool is(int level) const
Returns true if at least the given log level is set.
Definition: Logger.cpp:146
Numerical Matrix class.
Definition: Matrix.h:42
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.
Definition: Matrix.cpp:699
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...
Class for 3D vectors.
Definition: V3D.h:34
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
double normalize()
Make a normalized vector (return norm value)
Definition: V3D.cpp:130
constexpr double Y() const noexcept
Get y.
Definition: V3D.h:233
constexpr double Z() const noexcept
Get z.
Definition: V3D.h:234
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
@ CCW
Clockwise rotation.
Definition: Goniometer.h:34
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.
STL namespace.
This struct contains the parameters for constructing a material, and gives them a default value for e...
Definition: ReadMaterial.h:32
double numberDensity
The sample number density to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:40
double coherentXSection
The coherent scattering cross section to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:56
int massNumber
The mass number to set, defaults to 0.
Definition: ReadMaterial.h:38
double mass
The sample mass to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:52
double packingFraction
The sample packing fraction.
Definition: ReadMaterial.h:44
double attenuationXSection
The absorption cross section to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:60
Kernel::MaterialBuilder::NumberDensityUnit numberDensityUnit
A flag indicating the unit of sampleNumberDensity.
Definition: ReadMaterial.h:68
double volume
The sample volume to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:54
double massDensity
The sample mass density to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:50
double scatteringXSection
The total scattering cross section to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:62
double incoherentXSection
The incoherent scattering cross section to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:58
double zParameter
The zParameter to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:46
std::string chemicalSymbol
The chemical formula to set, defaults to the empty string.
Definition: ReadMaterial.h:34
double numberDensityEffective
The sample effective number density.
Definition: ReadMaterial.h:42
double unitCellVolume
The unit cell volume to set, defaults to EMPTY_DBL()
Definition: ReadMaterial.h:48
int atomicNumber
The atomic number to set, defaults to 0.
Definition: ReadMaterial.h:36
Describes the direction (within an algorithm) of a Property.
Definition: Property.h:50
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53