32#include <boost/algorithm/string.hpp>
38double DegreesToRadians(
double angle) {
return angle * M_PI / 180; }
44using namespace Kernel;
46using namespace Geometry;
49 auto wsValidator = std::make_shared<InstrumentValidator>();
52 "The name of the workspace containing the instrument to add "
56 const std::vector<std::string> extensions{
".stl",
".3mf"};
58 "The path name of the file containing the Environment");
65 "The name of the workspace that will contain the loaded "
66 "Environment of the sample");
75 declareProperty(
"XDegrees", 0.0,
"The degrees to rotate on the x axis by");
76 declareProperty(
"YDegrees", 0.0,
"The degrees to rotate on the y axis by");
77 declareProperty(
"ZDegrees", 0.0,
"The degrees to rotate on the z axis by");
81 "Vector by which to translate the loaded environment");
87 declareProperty(
"ChemicalFormula",
"",
"The chemical formula, see examples in documentation");
90 declareProperty(
"MassNumber", 0,
"Mass number if ion (use 0 for default mass sensity)");
91 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
92 mustBePositive->setLower(0.0);
94 "This number density of the sample in number of "
95 "atoms per cubic angstrom will be used instead of "
99 "Unit cell volume in Angstoms^3. Will be calculated from the "
100 "OrientedLattice if not supplied.");
102 "Optional: This coherent cross-section for the sample "
103 "material in barns will be used instead of tabulated");
105 "Optional: This incoherent cross-section for the sample "
106 "material in barns will be used instead of tabulated");
108 "Optional: This absorption cross-section for the sample "
109 "material in barns will be used instead of tabulated");
111 "Optional: This total scattering cross-section (coherent + "
112 "incoherent) for the sample material in barns will be used "
113 "instead of tabulated");
114 const std::vector<std::string> attExtensions{
".DAT"};
116 "The path name of the file containing the attenuation profile");
118 "Measured mass density in g/cubic cm of the sample "
119 "to be used to calculate the number density.");
120 const std::vector<std::string> units({
"Atoms",
"Formula Units"});
121 declareProperty(
"NumberDensityUnit", units.front(), std::make_shared<StringListValidator>(units),
122 "Choose which units SampleNumberDensity referes to.");
125 std::string formulaGrp(
"By Formula or Atomic Number");
133 std::string densityGrp(
"Sample Density");
144 std::make_unique<EnabledWhenProperty>(
"SampleNumberDensity",
IS_NOT_DEFAULT));
146 std::string specificValuesGrp(
"Override Cross Section Values");
160 std::map<std::string, std::string> result;
185 std::string debugString) {
186 std::unique_ptr<SampleEnvironment> environment =
nullptr;
187 std::shared_ptr<MeshObject> environmentMesh =
nullptr;
189 std::unique_ptr<LoadAsciiStl> asciiStlReader =
nullptr;
190 std::unique_ptr<LoadBinaryStl> binaryStlReader =
nullptr;
202 std::unique_ptr<LoadStl> reader =
nullptr;
218 const std::string numberDensityUnit =
getProperty(
"NumberDensityUnit");
219 if (numberDensityUnit ==
"Atoms") {
225 reader = std::make_unique<LoadBinaryStl>(filename, scaleType, params);
227 reader = std::make_unique<LoadAsciiStl>(filename, scaleType, params);
231 reader = std::make_unique<LoadBinaryStl>(filename, scaleType);
233 reader = std::make_unique<LoadAsciiStl>(filename, scaleType);
237 environmentMesh = reader->readShape();
239 const double xRotation = DegreesToRadians(
getProperty(
"xDegrees"));
240 const double yRotation = DegreesToRadians(
getProperty(
"yDegrees"));
241 const double zRotation = DegreesToRadians(
getProperty(
"zDegrees"));
242 environmentMesh = reader->rotate(environmentMesh, xRotation, yRotation, zRotation);
243 const std::vector<double> translationVector =
getProperty(
"TranslationVector");
244 environmentMesh = reader->translate(environmentMesh, translationVector);
248 environment = std::make_unique<SampleEnvironment>(sample.
getEnvironment());
249 environment->add(environmentMesh);
251 auto can = std::make_shared<Container>(environmentMesh);
252 environment = std::make_unique<SampleEnvironment>(
name, can);
255 debugString +=
"Environment has: " +
std::to_string(environment->nelements()) +
" elements.";
261 auto translatedVertices = environmentMesh->getVertices();
262 if (
g_log.
is(Logger::Priority::PRIO_DEBUG)) {
264 for (
double vertex : translatedVertices) {
285 [[maybe_unused]]
const std::string &filename,
286 [[maybe_unused]]
Sample &sample, [[maybe_unused]]
const bool add,
287 [[maybe_unused]] std::string &debugString) {
289 std::unique_ptr<Geometry::SampleEnvironment> environment =
nullptr;
292 boost::shared_ptr<MeshObject> environmentMesh =
nullptr;
294 std::vector<std::shared_ptr<Geometry::MeshObject>> environmentMeshes;
295 std::shared_ptr<Geometry::MeshObject> sampleMesh;
300 sampleMesh->rotate(inputWS->run().getGoniometer().getR());
301 sample.setShape(sampleMesh);
304 for (
auto environmentMesh : environmentMeshes) {
307 environment = std::make_unique<SampleEnvironment>(sample.getEnvironment());
308 environment->add(environmentMesh);
310 auto can = std::make_shared<Container>(environmentMesh);
311 environment = std::make_unique<SampleEnvironment>(
name, can);
314 environment->add(environmentMesh);
317 debugString +=
"Environment has: " +
std::to_string(environment->nelements()) +
" elements.";
321 sample.setEnvironment(std::move(environment));
323 throw std::runtime_error(
"3MF format not supported on this platform");
332 if (inputWS != outputWS) {
333 outputWS = inputWS->clone();
336 const std::string filename =
getProperty(
"Filename");
337 const std::ifstream file(filename.c_str());
339 g_log.
error(
"Unable to open file: " + filename);
344 std::string debugString;
345 Sample &sample = outputWS->mutableSample();
347 std::string fileExt = Poco::Path(filename).getExtension();
349 std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(), toupper);
351 if (fileExt ==
"STL") {
353 }
else if (fileExt ==
"3MF") {
356 throw "Invalid file extension";
360 const auto outMaterial = outputWS->sample().getEnvironment().getContainer().material();
362 "Environment Material: " +
365 "Environment Material Number Density: " +
#define DECLARE_ALGORITHM(classname)
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
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.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
@ Load
allowed here which will be passed to the algorithm
This class stores information about the sample used in particular run.
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.
static bool isAsciiSTL(const std::string &filename)
static bool isBinarySTL(const std::string &filename)
void exec() override
Virtual method - must be overridden by concrete algorithm.
void loadEnvironmentFrom3MF(const API::MatrixWorkspace_const_sptr &inputWS, const std::string &filename, API::Sample &sample, const bool add, std::string &debugString)
Load a sample environment definition from a .3mf file.
void init() override
Virtual method - must be overridden by concrete algorithm.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
void loadEnvironmentFromSTL(const std::string &filename, API::Sample &sample, const bool add, std::string debugString)
Load a sample environment definition from a .stl file.
Class to load and save .3mf files .3mf format is a 3D manufacturing format for storing mesh descripti...
void readMeshObjects(std::vector< MeshObject_sptr > &meshObjects, MeshObject_sptr &sample)
Read a set of mesh objects from the in memory lib3mf model object.
void LoadFile(std::string filename)
Load 3MF format file.
static ValidationErrors validateInputs(const MaterialParameters ¶ms)
Validate the parameters to build the material from, this returns any errors in the inputs.
Support for a property that holds an array of values.
Records the filename and the description of failure.
Records the filename, the description of failure and the line on which it happened.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
bool is(int level) const
Returns true if at least the given log level is set.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
ScaleUnits getScaleTypeFromStr(const std::string &scaleProperty)
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
std::string to_string(const wide_integer< Bits, Signed > &n)
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 attenuationXSection
The absorption cross section to set, defaults to EMPTY_DBL()
Kernel::MaterialBuilder::NumberDensityUnit numberDensityUnit
A flag indicating the unit of sampleNumberDensity.
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 unitCellVolume
The unit cell volume to set, defaults to EMPTY_DBL()
int atomicNumber
The atomic number to set, defaults to 0.
std::string attenuationProfileFileName
The name or path of a file containing an attenuation profile.
@ Input
An input workspace.
@ Output
An output workspace.