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
122
124 auto inst = workspace->getInstrument();
125 auto refFrame = inst->getReferenceFrame();
126
127 bool childLog = g_log.is(Logger::Priority::PRIO_DEBUG);
128 auto alg = this->createChildAlgorithm("CreateSampleShape", -1, -1, childLog);
129 alg->setProperty("InputWorkspace", workspace);
130 alg->setPropertyValue("ShapeXML", createSampleShapeXML(refFrame->vecPointingUp()));
131 try {
132 alg->executeAsChildAlg();
133 } catch (const std::exception &exc) {
134 throw std::invalid_argument(std::string("Unable to create sample shape: '") + exc.what() + "'");
135 }
136}
137
151std::string AnnularRingAbsorption::createSampleShapeXML(const V3D &upAxis) const {
152 // User input
153 const double canLowRadiusCM = getProperty("CanInnerRadius");
154 const double canUppRadiusCM = getProperty("CanOuterRadius");
155 const double sampleHeightCM = getProperty("SampleHeight");
156 const double sampleThickCM = getProperty("SampleThickness");
157 // Sample dimensions for approximation (converted to metres)
158 const double wallMidPtCM = canLowRadiusCM + 0.5 * (canUppRadiusCM - canLowRadiusCM);
159 const double lowRadiusMtr = (wallMidPtCM - 0.5 * sampleThickCM) / 100.;
160 const double uppRadiusMtr = (wallMidPtCM + 0.5 * sampleThickCM) / 100.;
161
162 // Cylinders oriented along Y, with origin at the centre as expected by
163 // the MonteCarloAbsorption algorithm.
164 const V3D bottomCentre{0.0, -sampleHeightCM / 2.0 / 100.0, 0.0}; // in metres.
165 const std::string innerCylID = std::string("inner-cyl");
166 const std::string innerCyl = cylinderXML(innerCylID, bottomCentre, lowRadiusMtr, upAxis, sampleHeightCM / 100.0);
167 const std::string outerCylID = std::string("outer-cyl");
168 const std::string outerCyl = cylinderXML(outerCylID, bottomCentre, uppRadiusMtr, upAxis, sampleHeightCM / 100.0);
169
170 // Combine shapes
171 boost::format algebra("<algebra val=\"(%1% (# %2%))\" />");
172 algebra % outerCylID % innerCylID;
173 auto xml = outerCyl + "\n" + innerCyl + "\n" + algebra.str();
174 g_log.debug() << "Sample shape XML:\n" << xml << "\n";
175 return xml;
176}
177
186const std::string AnnularRingAbsorption::cylinderXML(const std::string &id, const V3D &bottomCentre,
187 const double radius, const V3D &axis, const double height) const {
188 // The newline characters are not necessary for the XML but they make it
189 // easier to read for debugging
190 static const char *CYL_TEMPLATE = "<cylinder id=\"%1%\">\n"
191 "<centre-of-bottom-base x=\"%2%\" y=\"%3%\" z=\"%4%\" />\n"
192 " <axis x=\"%5%\" y=\"%6%\" z=\"%7%\" />\n"
193 " <radius val=\"%8%\" />\n"
194 " <height val=\"%9%\" />\n"
195 "</cylinder>";
196
197 boost::format xml(CYL_TEMPLATE);
198 xml % id % bottomCentre.X() % bottomCentre.Y() % bottomCentre.Z() % axis.X() % axis.Y() % axis.Z() % radius % height;
199 return xml.str();
200}
201
207 bool childLog = g_log.is(Logger::Priority::PRIO_DEBUG);
208 auto alg = this->createChildAlgorithm("SetSampleMaterial", -1, -1, childLog);
209 alg->setProperty("InputWorkspace", workspace);
210 alg->setProperty("ChemicalFormula", getPropertyValue("SampleChemicalFormula"));
211 alg->setProperty<double>("SampleNumberDensity", getProperty("SampleNumberDensity"));
212 try {
213 alg->executeAsChildAlg();
214 } catch (std::exception &exc) {
215 throw std::invalid_argument(std::string("Unable to set sample material: '") + exc.what() + "'");
216 }
217}
218
226 bool childLog = g_log.is(Logger::Priority::PRIO_DEBUG);
227 auto alg = this->createChildAlgorithm("MonteCarloAbsorption", 0.1, 1.0, childLog);
228 alg->setProperty("InputWorkspace", workspace);
229 alg->setProperty<int>("NumberOfWavelengthPoints", getProperty("NumberOfWavelengthPoints"));
230 alg->setProperty<int>("EventsPerPoint", getProperty("EventsPerPoint"));
231 alg->setProperty<int>("SeedValue", getProperty("SeedValue"));
232 try {
233 alg->executeAsChildAlg();
234 } catch (std::exception &exc) {
235 throw std::invalid_argument(std::string("Error running absorption correction: '") + exc.what() + "'");
236 }
237
238 return alg->getProperty("OutputWorkspace");
239}
240
241} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
double height
Definition GetAllEi.cpp:155
IPeaksWorkspace_sptr workspace
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.
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
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 runSetSampleMaterial(const API::MatrixWorkspace_sptr &workspace)
Attaches a new Material object to the sample.
void init() override
Initialize the algorithm's properties.
const std::string category() const override
Algorithm's category for identification.
void attachSample(const 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 exec() override
Execute the algorithm.
void runCreateSampleShape(const API::MatrixWorkspace_sptr &workspace)
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:145
bool is(int level) const
Returns true if at least the given log level is set.
Definition Logger.cpp:177
Class for 3D vectors.
Definition V3D.h:34
constexpr double X() const noexcept
Get x.
Definition V3D.h:238
constexpr double Y() const noexcept
Get y.
Definition V3D.h:239
constexpr double Z() const noexcept
Get z.
Definition V3D.h:240
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:24
STL namespace.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54