Mantid
Loading...
Searching...
No Matches
AddAbsorptionWeightedPathLengths.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2020 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 +
9#include "MantidAPI/Sample.h"
24
25using namespace Mantid::API;
26using namespace Mantid::DataObjects;
27using namespace Mantid::Geometry;
28using namespace Mantid::Kernel;
29
30namespace Mantid::Algorithms {
31
32// Register the algorithm into the AlgorithmFactory
33DECLARE_ALGORITHM(AddAbsorptionWeightedPathLengths)
34
35//----------------------------------------------------------------------------------------------
36
37namespace {
38
39constexpr int DEFAULT_NEVENTS = 1000;
40constexpr int DEFAULT_SEED = 123456789;
41constexpr int NLAMBDA = 1;
42
43} // namespace
44
45//----------------------------------------------------------------------------------------------
49 declareProperty(std::make_unique<WorkspaceProperty<IPeaksWorkspace>>("InputWorkspace", "", Direction::InOut),
50 "An input/output peaks workspace that the path distances will be added "
51 "to.");
52 declareProperty("UseSinglePath", false, "Use a single path with a scatter point at the sample position.");
53 auto positiveInt = std::make_shared<Kernel::BoundedValidator<int>>();
54 positiveInt->setLower(1);
55 declareProperty("EventsPerPoint", DEFAULT_NEVENTS, positiveInt,
56 "The number of \"neutron\" events to generate per peak");
57 declareProperty("SeedValue", DEFAULT_SEED, positiveInt, "Seed the random number generator with this value");
58 declareProperty("MaxScatterPtAttempts", 5000, positiveInt,
59 "Maximum number of tries made to generate a scattering point "
60 "within the sample. Objects with "
61 "holes in them, e.g. a thin annulus can cause problems "
62 "if this number is too low.\n"
63 "If a scattering point cannot be generated by increasing "
64 "this value then there is most likely a problem with "
65 "the sample geometry.");
66 setPropertySettings("SeedValue",
67 std::make_unique<EnabledWhenProperty>("UseSinglePath", ePropertyCriterion::IS_DEFAULT));
68 setPropertySettings("EventsPerPoint",
69 std::make_unique<EnabledWhenProperty>("UseSinglePath", ePropertyCriterion::IS_DEFAULT));
70 setPropertySettings("MaxScatterPtAttempts",
71 std::make_unique<EnabledWhenProperty>("UseSinglePath", ePropertyCriterion::IS_DEFAULT));
72 declareProperty("ApplyCorrection", false,
73 "Calculate the attenuation/transmission and apply it to the integrated intensity and uncertainty.");
74}
75
76std::map<std::string, std::string> AddAbsorptionWeightedPathLengths::validateInputs() {
77 IPeaksWorkspace_sptr inputWS = getProperty("InputWorkspace");
78 std::map<std::string, std::string> issues;
79 auto sample = inputWS->sample();
80 if (!sample.hasShape()) {
81 issues["InputWorkspace"] = "Input workspace does not have a sample shape";
82 } else {
83 if (inputWS->sample().hasEnvironment()) {
84 issues["InputWorkspace"] = "Sample must not have a sample environment";
85 }
86
87 if (inputWS->sample().getMaterial().numberDensity() == 0) {
88 issues["InputWorkspace"] = "Sample must have a material set up with a non-zero number density";
89 }
90 }
91 return issues;
92}
93
94//----------------------------------------------------------------------------------------------
98
99 const API::IPeaksWorkspace_sptr inputWS = getProperty("InputWorkspace");
100 const int nevents = getProperty("EventsPerPoint");
101 const int maxScatterPtAttempts = getProperty("MaxScatterPtAttempts");
102 const int seed = getProperty("SeedValue");
103
104 if (!inputWS->getInstrument()->hasSource()) {
106 Detector *detector = new Detector("det1", -1, nullptr);
107 detector->setPos(0.0, 0.0, 0.0);
108 inst->add(detector); // This takes care of deletion
109 inst->markAsDetector(detector);
111 source->setPos(0.0, 0.0, -1.0);
112 inst->add(source); // This takes care of deletion
113 inst->markAsSource(source);
114 inputWS->setInstrument(inst);
115 }
116
117 auto instrument = inputWS->getInstrument();
118
119 auto beamProfile = BeamProfileFactory::createBeamProfile(*instrument, inputWS->sample());
120 // Configure strategy
121 std::shared_ptr<IMCInteractionVolume> interactionVol =
122 MCInteractionVolume::create(inputWS->sample(), maxScatterPtAttempts);
123 MCAbsorptionStrategy strategy(interactionVol, *beamProfile, DeltaEMode::Elastic, nevents, maxScatterPtAttempts, true);
124
125 bool useSinglePath = getProperty("UseSinglePath");
126 bool applyCorrection = getProperty("ApplyCorrection");
127 const auto npeaks = inputWS->getNumberPeaks();
128
129 // Configure progress
130 Progress prog(this, 0.0, 1.0, npeaks);
131 prog.setNotifyStep(0.01);
132 const std::string reportMsg = "Computing path lengths";
133
135 for (int i = 0; i < npeaks; ++i) {
137 IPeak &peak = inputWS->getPeak(i);
138 auto peakWavelength = peak.getWavelength();
139
140 std::vector<double> lambdas{peakWavelength}, absFactors(NLAMBDA);
141
142 const auto R = peak.getGoniometerMatrix();
143 const auto sourcePos = R * peak.getSourceDirectionSampleFrame();
144 const auto detectorPos = R * peak.getDetectorDirectionSampleFrame();
145 const auto samplePos = peak.getSamplePos();
146
147 if (useSinglePath) {
148 const auto reverseBeamDir = normalize(samplePos - sourcePos);
149 const IObject *sampleShape = &(inputWS->sample().getShape());
150
151 Track beforeScatter(samplePos, reverseBeamDir);
152 sampleShape->interceptSurface(beforeScatter);
153 const auto detDir = normalize(detectorPos - samplePos);
154 Track afterScatter(samplePos, detDir);
155 sampleShape->interceptSurface(afterScatter);
156
157 absFactors[0] = beforeScatter.calculateAttenuation(lambdas[0]) * afterScatter.calculateAttenuation(lambdas[0]);
158
159 } else {
160 MersenneTwister rng(seed + int(i));
161 int detID;
162 try {
163 detID = peak.getDetectorID();
164 } catch (const Exception::NotImplementedError &) {
165 detID = -1; // no detector ID in lean peaks
166 }
167 MCInteractionStatistics detStatistics(detID, inputWS->sample());
168 std::vector<double> absFactorErrors(NLAMBDA);
169 strategy.calculate(rng, detectorPos, lambdas, peakWavelength, absFactors, absFactorErrors, detStatistics);
170
171 if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) {
172 g_log.debug(detStatistics.generateScatterPointStats());
173 }
174 }
175
176 double mu = inputWS->sample().getMaterial().attenuationCoefficient(peakWavelength); // m-1
177 double absWeightedPathLength = -log(absFactors[0]) / mu; // metres
178 peak.setAbsorptionWeightedPathLength(absWeightedPathLength * 100); // cm
179 if (applyCorrection) {
180 peak.setIntensity(peak.getIntensity() / absFactors[0]);
181 peak.setSigmaIntensity(peak.getSigmaIntensity() / absFactors[0]);
182 }
183
184 prog.report(reportMsg);
186 }
188}
189
190} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
std::map< std::string, std::string > validateInputs() override
Method checking errors on ALL the inputs, before execution.
static std::unique_ptr< IBeamProfile > createBeamProfile(const Geometry::Instrument &instrument, const API::Sample &sample)
Implements the algorithm for calculating the correction factor for self-attenuation and single wavele...
virtual void calculate(Kernel::PseudoRandomNumberGenerator &rng, const Kernel::V3D &finalPos, const std::vector< double > &lambdas, const double lambdaFixed, std::vector< double > &attenuationFactors, std::vector< double > &attFactorErrors, MCInteractionStatistics &stats) override
Compute the correction for a final position of the neutron and wavelengths before and after scatterin...
Stores statistics relating to the tracks generated in MCInteractionVolume for a specific detector.
std::string generateScatterPointStats()
Log a debug string summarising which parts of the environment the simulated scatter points occurred i...
static std::shared_ptr< IMCInteractionVolume > create(const API::Sample &sample, const size_t maxScatterAttempts=5000, const ScatteringPointVicinity pointsIn=ScatteringPointVicinity::SAMPLEANDENVIRONMENT, Geometry::IObject_sptr gaugeVolume=nullptr)
Factory Method for constructing the volume encompassing the sample + any environment kit.
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
This class represents a detector - i.e.
Definition Detector.h:30
IObject : Interface for geometry objects.
Definition IObject.h:42
virtual int interceptSurface(Geometry::Track &) const =0
Structure describing a single-crystal peak.
Definition IPeak.h:26
virtual double getWavelength() const =0
Base Instrument Class.
Definition Instrument.h:47
Object Component class, this class brings together the physical attributes of the component to the po...
Defines a track as a start point and a direction.
Definition Track.h:165
virtual double calculateAttenuation(double lambda) const
Calculate attenuation across all links.
Definition Track.cpp:276
Marks code as not implemented yet.
Definition Exception.h:138
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
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
This implements the Mersenne Twister 19937 pseudo-random number generator algorithm as a specialzatio...
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
void setNotifyStep(double notifyStepPct)
Override the frequency at which notifications are sent out.
std::shared_ptr< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition V3D.h:352
@ InOut
Both an input & output workspace.
Definition Property.h:55