Mantid
Loading...
Searching...
No Matches
AnnularRingAbsorption.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
11
18
19#include "MantidKernel/Atom.h"
25#include "MantidKernel/V3D.h"
26
27#include <boost/format.hpp>
28#include <memory>
29
30namespace Mantid::Algorithms {
31using namespace Mantid::API;
32using namespace Mantid::Kernel;
33
34// Register the algorithm into the AlgorithmFactory
35DECLARE_ALGORITHM(AnnularRingAbsorption)
36
37//----------------------------------------------------------------------------------------------
38
39
40const std::string AnnularRingAbsorption::name() const { return "AnnularRingAbsorption"; }
41
43int AnnularRingAbsorption::version() const { return 1; }
44
46const std::string AnnularRingAbsorption::category() const { return "CorrectionFunctions\\AbsorptionCorrections"; }
47
49const std::string AnnularRingAbsorption::summary() const {
50 return "Calculates bin-by-bin correction factors for attenuation due to "
51 "absorption "
52 "in a cylindrical sample in the wall of a hollow can";
53}
54
55//----------------------------------------------------------------------------------------------
60 // The input workspace must have an instrument and units of wavelength
61 auto wsValidator = std::make_shared<CompositeValidator>();
62 wsValidator->add<WorkspaceUnitValidator>("Wavelength");
63 wsValidator->add<InstrumentValidator>();
64 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, wsValidator),
65 "The input workspace in units of wavelength.");
66
67 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
68 "The name to use for the output workspace.");
69
70 // -- can properties --
71 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
72 mustBePositive->setLower(0.0);
73 declareProperty("CanOuterRadius", -1.0, mustBePositive, "The outer radius of the can in centimetres");
74 declareProperty("CanInnerRadius", -1.0, mustBePositive, "The inner radius of the can in centimetres");
75
76 // -- sample properties --
77 declareProperty("SampleHeight", -1.0, mustBePositive, "The height of the sample in centimetres");
78 declareProperty("SampleThickness", -1.0, mustBePositive, "The thickness of the sample in centimetres");
79 auto nonEmptyString = std::make_shared<MandatoryValidator<std::string>>();
80 declareProperty("SampleChemicalFormula", "", "Chemical composition of the sample material", nonEmptyString);
81 declareProperty("SampleNumberDensity", -1.0, mustBePositive,
82 "The number density of the sample in number of formulas per "
83 "cubic angstrom");
84
85 // -- Monte Carlo properties --
86 auto positiveInt = std::make_shared<Kernel::BoundedValidator<int>>();
87 positiveInt->setLower(1);
88 declareProperty("NumberOfWavelengthPoints", EMPTY_INT(), positiveInt,
89 "The number of wavelength points for which a simulation is "
90 "atttempted (default: all points)");
91 declareProperty("EventsPerPoint", 300, positiveInt,
92 "The number of \"neutron\" events to generate per simulated point");
93 declareProperty("SeedValue", 123456789, positiveInt, "Seed the random number generator with this value");
94}
95
96//----------------------------------------------------------------------------------------------
101 MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
102 // We neglect any absorption in the can so the actual shape defined is a
103 // hollow cylinder
104 // where the sample is in the centre of the can wall
105 attachSample(inputWS);
106
108 setProperty("OutputWorkspace", factors);
109}
110
111//---------------------------------------------------------------------------------------------
112// Private members
113//---------------------------------------------------------------------------------------------
114
121}
122
127 auto inst = workspace->getInstrument();
128 auto refFrame = inst->getReferenceFrame();
129
130 bool childLog = g_log.is(Logger::Priority::PRIO_DEBUG);
131 auto alg = this->createChildAlgorithm("CreateSampleShape", -1, -1, childLog);
132 alg->setProperty("InputWorkspace", workspace);
133 alg->setPropertyValue("ShapeXML", createSampleShapeXML(refFrame->vecPointingUp()));
134 try {
135 alg->executeAsChildAlg();
136 } catch (const std::exception &exc) {
137 throw std::invalid_argument(std::string("Unable to create sample shape: '") + exc.what() + "'");
138 }
139}
140
154std::string AnnularRingAbsorption::createSampleShapeXML(const V3D &upAxis) const {
155 // User input
156 const double canLowRadiusCM = getProperty("CanInnerRadius");
157 const double canUppRadiusCM = getProperty("CanOuterRadius");
158 const double sampleHeightCM = getProperty("SampleHeight");
159 const double sampleThickCM = getProperty("SampleThickness");
160 // Sample dimensions for approximation (converted to metres)
161 const double wallMidPtCM = canLowRadiusCM + 0.5 * (canUppRadiusCM - canLowRadiusCM);
162 const double lowRadiusMtr = (wallMidPtCM - 0.5 * sampleThickCM) / 100.;
163 const double uppRadiusMtr = (wallMidPtCM + 0.5 * sampleThickCM) / 100.;
164
165 // Cylinders oriented along Y, with origin at the centre as expected by
166 // the MonteCarloAbsorption algorithm.
167 const V3D bottomCentre{0.0, -sampleHeightCM / 2.0 / 100.0, 0.0}; // in metres.
168 const std::string innerCylID = std::string("inner-cyl");
169 const std::string innerCyl = cylinderXML(innerCylID, bottomCentre, lowRadiusMtr, upAxis, sampleHeightCM / 100.0);
170 const std::string outerCylID = std::string("outer-cyl");
171 const std::string outerCyl = cylinderXML(outerCylID, bottomCentre, uppRadiusMtr, upAxis, sampleHeightCM / 100.0);
172
173 // Combine shapes
174 boost::format algebra("<algebra val=\"(%1% (# %2%))\" />");
175 algebra % outerCylID % innerCylID;
176 auto xml = outerCyl + "\n" + innerCyl + "\n" + algebra.str();
177 g_log.debug() << "Sample shape XML:\n" << xml << "\n";
178 return xml;
179}
180
189const std::string AnnularRingAbsorption::cylinderXML(const std::string &id, const V3D &bottomCentre,
190 const double radius, const V3D &axis, const double height) const {
191 // The newline characters are not necessary for the XML but they make it
192 // easier to read for debugging
193 static const char *CYL_TEMPLATE = "<cylinder id=\"%1%\">\n"
194 "<centre-of-bottom-base x=\"%2%\" y=\"%3%\" z=\"%4%\" />\n"
195 " <axis x=\"%5%\" y=\"%6%\" z=\"%7%\" />\n"
196 " <radius val=\"%8%\" />\n"
197 " <height val=\"%9%\" />\n"
198 "</cylinder>";
199
200 boost::format xml(CYL_TEMPLATE);
201 xml % id % bottomCentre.X() % bottomCentre.Y() % bottomCentre.Z() % axis.X() % axis.Y() % axis.Z() % radius % height;
202 return xml.str();
203}
204
209 bool childLog = g_log.is(Logger::Priority::PRIO_DEBUG);
210 auto alg = this->createChildAlgorithm("SetSampleMaterial", -1, -1, childLog);
211 alg->setProperty("InputWorkspace", workspace);
212 alg->setProperty("ChemicalFormula", getPropertyValue("SampleChemicalFormula"));
213 alg->setProperty<double>("SampleNumberDensity", getProperty("SampleNumberDensity"));
214 try {
215 alg->executeAsChildAlg();
216 } catch (std::exception &exc) {
217 throw std::invalid_argument(std::string("Unable to set sample material: '") + exc.what() + "'");
218 }
219}
220
228 bool childLog = g_log.is(Logger::Priority::PRIO_DEBUG);
229 auto alg = this->createChildAlgorithm("MonteCarloAbsorption", 0.1, 1.0, childLog);
230 alg->setProperty("InputWorkspace", workspace);
231 alg->setProperty<int>("NumberOfWavelengthPoints", getProperty("NumberOfWavelengthPoints"));
232 alg->setProperty<int>("EventsPerPoint", getProperty("EventsPerPoint"));
233 alg->setProperty<int>("SeedValue", getProperty("SeedValue"));
234 try {
235 alg->executeAsChildAlg();
236 } catch (std::exception &exc) {
237 throw std::invalid_argument(std::string("Error running absorption correction: '") + exc.what() + "'");
238 }
239
240 return alg->getProperty("OutputWorkspace");
241}
242
243} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double height
Definition: GetAllEi.cpp:155
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
double radius
Definition: Rasterize.cpp:31
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
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
A validator which checks that a workspace has a valid instrument.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
Constructs a hollow sample shape, defines material for the sample and runs the MonteCarloAbsorption a...
const std::string cylinderXML(const std::string &id, const Kernel::V3D &bottomCentre, const double radius, const Kernel::V3D &axis, const double height) const
void init() override
Initialize the algorithm's properties.
const std::string category() const override
Algorithm's category for identification.
void runSetSampleMaterial(API::MatrixWorkspace_sptr &workspace)
API::MatrixWorkspace_sptr runMonteCarloAbsorptionCorrection(const API::MatrixWorkspace_sptr &workspace)
Run the MonteCarloAbsorption algorithm on the given workspace and return the calculated factors.
void attachSample(API::MatrixWorkspace_sptr &workspace)
void runCreateSampleShape(API::MatrixWorkspace_sptr &workspace)
void exec() override
Execute the algorithm.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
std::string createSampleShapeXML(const Kernel::V3D &upAxis) const
Create the XML that defines a hollow cylinder with dimensions provided by the user The shape is a hol...
int version() const override
Algorithm's version for identification.
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
Class for 3D vectors.
Definition: V3D.h:34
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
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< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54