Mantid
Loading...
Searching...
No Matches
DetectorEfficiencyCorUser.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 +
10#include "MantidAPI/Run.h"
21
22namespace Mantid::Algorithms {
23
24using namespace Kernel;
25using namespace API;
26using namespace Geometry;
27
28// Register the algorithm into the AlgorithmFactory
29DECLARE_ALGORITHM(DetectorEfficiencyCorUser)
30
31
32const std::string DetectorEfficiencyCorUser::name() const { return "DetectorEfficiencyCorUser"; }
33
35int DetectorEfficiencyCorUser::version() const { return 1; }
36
38const std::string DetectorEfficiencyCorUser::category() const {
39 return "CorrectionFunctions\\EfficiencyCorrections;Inelastic\\Corrections";
40}
41
45 auto val = std::make_shared<CompositeValidator>();
46 // val->add<WorkspaceUnitValidator>("Energy");
47 val->add<WorkspaceUnitValidator>("DeltaE");
48 val->add<HistogramValidator>();
49 val->add<InstrumentValidator>();
50 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, val),
51 "The workspace to correct for detector efficiency");
52 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
53 "The name of the workspace in which to store the result.");
54 auto checkEi = std::make_shared<BoundedValidator<double>>();
55 checkEi->setLower(0.0);
56 declareProperty("IncidentEnergy", EMPTY_DBL(), checkEi, "The energy of neutrons leaving the source.");
57}
58
62 // get input properties (WSs, Ei)
64
65 const size_t numberOfChannels = this->m_inputWS->blocksize();
66 // Calculate the number of spectra in this workspace
67 const auto numberOfSpectra = static_cast<int>(this->m_inputWS->size() / numberOfChannels);
68 API::Progress prog(this, 0.0, 1.0, numberOfSpectra);
69 auto numberOfSpectra_i = static_cast<int64_t>(numberOfSpectra); // cast to make openmp happy
70
71 // Loop over the histograms (detector spectra)
73 for (int64_t i = 0; i < numberOfSpectra_i; ++i) {
75 const auto effFormula = retrieveFormula(i);
76 // Calculate Efficiency for E = Ei
77 double e;
78 auto parser = generateParser(effFormula, &e);
79 e = m_Ei;
80 const double eff0 = evaluate(parser);
81 correctHistogram(i, eff0, e, parser);
82
83 prog.report("Detector Efficiency correction...");
84
86 } // end for i
88
89 this->setProperty("OutputWorkspace", this->m_outputWS);
90}
91
100void DetectorEfficiencyCorUser::correctHistogram(const size_t index, const double eff0, double &e,
101 const mu::Parser &parser) {
102 const auto &xIn = m_inputWS->points(index);
103 const auto &yIn = m_inputWS->y(index);
104 const auto &eIn = m_inputWS->e(index);
105 auto &yOut = m_outputWS->mutableY(index);
106 auto &eOut = m_outputWS->mutableE(index);
107 for (size_t i = 0; i < xIn.size(); ++i) {
108 e = m_Ei - xIn[i];
109 const double eff = evaluate(parser);
110 const double corr = eff / eff0;
111 yOut[i] = yIn[i] / corr;
112 eOut[i] = eIn[i] / corr;
113 }
114}
115
122double DetectorEfficiencyCorUser::evaluate(const mu::Parser &parser) const {
123 try {
124 return parser.Eval();
125 } catch (mu::Parser::exception_type &e) {
127 "Error calculating formula from string. Muparser error message is: " + e.GetMsg());
128 }
129}
130
131mu::Parser DetectorEfficiencyCorUser::generateParser(const std::string &formula, double *e) const {
132 mu::Parser p;
133 p.DefineVar("e", e);
134 p.SetExpr(formula);
135 return p;
136}
137
143std::string DetectorEfficiencyCorUser::retrieveFormula(const size_t workspaceIndex) {
144 const std::string formulaParamName("formula_eff");
145 const auto &spectrumInfo = m_inputWS->spectrumInfo();
146 if (!spectrumInfo.hasDetectors(workspaceIndex)) {
147 throw Kernel::Exception::NotFoundError("MatrixWorkspace::getDetector(): No detectors for this workspace index.",
148 std::to_string(workspaceIndex));
149 }
150 const auto &componentInfo = m_inputWS->componentInfo();
151 const auto detIndex = spectrumInfo.firstDetectorIndex(workspaceIndex);
152 // A spectrum of several detectors has no parameters of its own
153 const auto param = spectrumInfo.hasUniqueDetector(workspaceIndex)
154 ? componentInfo.parameter(detIndex, formulaParamName, "string")
155 : nullptr;
156 if (!param) {
157 throw Kernel::Exception::InstrumentDefinitionError("No <" + formulaParamName + "> parameter found for component '" +
158 componentInfo.fullName(detIndex) +
159 "' in the instrument definition.");
160 }
161 const auto ret = param->asString();
162 g_log.debug() << "Found formula for workspace index " << workspaceIndex << ": " << ret << "\n";
163 return ret;
164}
165
172 // Get the workspaces
173 m_inputWS = this->getProperty("InputWorkspace");
174
175 m_outputWS = this->getProperty("OutputWorkspace");
176
177 // If input and output workspaces are not the same, create a new workspace for
178 // the output
179 if (m_outputWS != this->m_inputWS) {
180 m_outputWS.reset(Mantid::DataObjects::create<DataObjects::Workspace2D>(*m_inputWS).release());
181 }
182
183 // these first three properties are fully checked by validators
184 m_Ei = this->getProperty("IncidentEnergy");
185 // If we're not given an Ei, see if one has been set.
186 if (m_Ei == EMPTY_DBL()) {
187 Mantid::Kernel::Property const *prop = m_inputWS->run().getProperty("Ei");
188 double val;
189 if (!prop || !Strings::convert(prop->value(), val)) {
190 throw std::invalid_argument("No Ei value has been set or stored within the run information.");
191 }
192 m_Ei = val;
193 g_log.debug() << "Using stored Ei value " << m_Ei << "\n";
194 } else {
195 g_log.debug() << "Using user input Ei value: " << m_Ei << "\n";
196 }
197}
198} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
std::map< DeltaEMode::Type, std::string > index
#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:426
A validator which checks that a workspace contains histogram data (the default) or point data as requ...
A validator which checks that a workspace has a valid instrument.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
double m_Ei
stores the user selected value for incidient energy of the neutrons
mu::Parser generateParser(const std::string &formula, double *e) const
const std::string category() const override
Algorithm's category for identification.
API::MatrixWorkspace_sptr m_outputWS
The output workspace, maybe the same as the input one.
void retrieveProperties()
Loads and checks the values passed to the algorithm.
double evaluate(const mu::Parser &parser) const
Calculate the value of a formula parsed by muParser.
API::MatrixWorkspace_const_sptr m_inputWS
The user selected (input) workspace.
void init() override
Initialize the algorithm's properties.
int version() const override
Algorithm's version for identification.
void correctHistogram(const size_t index, const double eff0, double &e, const mu::Parser &parser)
Apply efficiency corrections to a histogram in the output workspace.
std::string retrieveFormula(const size_t workspaceIndex)
Returns the efficiency correction formula associated to a detector.
Exception for errors associated with the instrument definition.
Definition Exception.h:220
Exception for when an item is not found in a collection.
Definition Exception.h:145
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
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Base class for properties.
Definition Property.h:95
virtual std::string value() const =0
Returns the value of the property as a string.
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition Strings.cpp:697
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.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55