Mantid
Loading...
Searching...
No Matches
PolarizationEfficiencyCor.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 +
9
11#include "MantidAPI/Axis.h"
21
22#include <Eigen/Dense>
23#include <boost/math/special_functions/pow.hpp>
24
25namespace {
26
28namespace Prop {
29static const std::string FLIPPERS{"Flippers"};
30static const std::string OUTPUT_WILDES_SPIN_STATES{"SpinStatesOutWildes"};
31static const std::string POLARIZATION_ANALYSIS{"PolarizationAnalysis"};
32static const std::string EFFICIENCIES{"Efficiencies"};
33static const std::string INPUT_WORKSPACES{"InputWorkspaces"};
34static const std::string INPUT_WORKSPACE_GROUP{"InputWorkspaceGroup"};
35static const std::string OUTPUT_WORKSPACES{"OutputWorkspace"};
36static const std::string CORRECTION_METHOD{"CorrectionMethod"};
37static const std::string INPUT_FRED_SPIN_STATES{"SpinStatesInFredrikze"};
38static const std::string OUTPUT_FRED_SPIN_STATES{"SpinStatesOutFredrikze"};
39static const std::string ADD_SPIN_STATE_LOG{"AddSpinStateToLog"};
40} // namespace Prop
41
43static const std::string WILDES{"Wildes"};
44static const std::string FREDRIKZE{"Fredrikze"};
45} // namespace CorrectionMethod
46
47} // namespace
48
49namespace Mantid::Algorithms {
50
51using namespace API;
52using namespace Kernel;
53
54// Register the algorithm into the AlgorithmFactory
55DECLARE_ALGORITHM(PolarizationEfficiencyCor)
56
57//----------------------------------------------------------------------------------------------
58
59
60const std::string PolarizationEfficiencyCor::name() const { return "PolarizationEfficiencyCor"; }
61
63int PolarizationEfficiencyCor::version() const { return 1; }
64
66const std::string PolarizationEfficiencyCor::category() const { return "Reflectometry"; }
67
69const std::string PolarizationEfficiencyCor::summary() const {
70 return "Corrects a group of polarization analysis workspaces for polarizer "
71 "and analyzer efficiencies.";
72}
73
74//----------------------------------------------------------------------------------------------
78 bool const allowMultiSelection = true;
79 bool const isOptional = true;
81 Prop::INPUT_WORKSPACES, "", std::make_shared<ADSValidator>(allowMultiSelection, isOptional),
83 "A list of names of workspaces to be corrected.");
84
85 declareProperty(std::make_unique<WorkspaceProperty<WorkspaceGroup>>(Prop::INPUT_WORKSPACE_GROUP, "",
87 "A group of workspaces to be corrected.");
88
89 const std::vector<std::string> methods{CorrectionMethod::WILDES, CorrectionMethod::FREDRIKZE};
90 declareProperty(Prop::CORRECTION_METHOD, CorrectionMethod::WILDES,
91 std::make_shared<Kernel::ListValidator<std::string>>(methods), "Correction method.");
92
95 "A workspace containing the efficiency factors as "
96 "histograms: P1, P2, F1 and F2 in the Wildes method and Pp, "
97 "Ap, Rho and Alpha for Fredrikze.");
98
99 const auto wildesFlipperValidator =
100 std::make_shared<SpinStateValidator>(std::unordered_set<int>{1, 2, 3, 4}, true, "0", "1", true);
101 declareProperty(Prop::FLIPPERS, "", wildesFlipperValidator,
102 "Flipper configurations of the input workspaces (Wildes method only)");
103
104 const auto spinStateValidator =
105 std::make_shared<SpinStateValidator>(std::unordered_set<int>{0, 2, 4}, true, "+", "-", true);
106 declareProperty(Prop::OUTPUT_WILDES_SPIN_STATES, "", spinStateValidator,
107 "The order of the spin states in the output workspace. (Wildes method only).");
108
109 std::vector<std::string> propOptions{"", "PA", "PNR"};
110 declareProperty("PolarizationAnalysis", "", std::make_shared<StringListValidator>(propOptions),
111 "What Polarization mode will be used?\n"
112 "PNR: Polarized Neutron Reflectivity mode\n"
113 "PA: Full Polarization Analysis PNR-PA "
114 "(Fredrikze method only)");
115
116 const auto fredrikzeSpinStateValidator =
117 std::make_shared<SpinStateValidator>(std::unordered_set<int>{2, 4}, true, "p", "a", true);
118
119 declareProperty(Prop::INPUT_FRED_SPIN_STATES, "", fredrikzeSpinStateValidator,
120 "The order of spin states in the input workspace group. The possible values are 'pp,pa,ap,aa' or "
121 "'p,a'. (Fredrikze method only).");
122
123 declareProperty(Prop::OUTPUT_FRED_SPIN_STATES, "", fredrikzeSpinStateValidator,
124 "The order of spin states in the output workspace group. The possible values are 'pp,pa,ap,aa' or "
125 "'p,a'. (Fredrikze method only).");
126
128 std::make_unique<WorkspaceProperty<WorkspaceGroup>>(Prop::OUTPUT_WORKSPACES, "", Kernel::Direction::Output),
129 "A group of polarization efficiency corrected workspaces.");
130
132 "Whether to add the final spin state into the sample log of each child workspace in the output "
133 "group.");
134
136 Prop::OUTPUT_WILDES_SPIN_STATES,
137 std::make_unique<EnabledWhenProperty>(Prop::CORRECTION_METHOD, Kernel::IS_EQUAL_TO, CorrectionMethod::WILDES));
138
139 setPropertySettings(Prop::FLIPPERS, std::make_unique<EnabledWhenProperty>(
140 Prop::CORRECTION_METHOD, Kernel::IS_EQUAL_TO, CorrectionMethod::WILDES));
141
143 Prop::INPUT_FRED_SPIN_STATES,
144 std::make_unique<EnabledWhenProperty>(Prop::CORRECTION_METHOD, Kernel::IS_EQUAL_TO, CorrectionMethod::FREDRIKZE));
145
147 Prop::OUTPUT_FRED_SPIN_STATES,
148 std::make_unique<EnabledWhenProperty>(Prop::CORRECTION_METHOD, Kernel::IS_EQUAL_TO, CorrectionMethod::FREDRIKZE));
149
151 "PolarizationAnalysis",
152 std::make_unique<EnabledWhenProperty>(Prop::CORRECTION_METHOD, Kernel::IS_EQUAL_TO, CorrectionMethod::FREDRIKZE));
153}
154
155//----------------------------------------------------------------------------------------------
159 std::string const method = getProperty(Prop::CORRECTION_METHOD);
160 if (method == CorrectionMethod::WILDES) {
161 execWildes();
162 } else {
164 }
165}
166
167//----------------------------------------------------------------------------------------------
170 std::vector<std::string> workspaces = getWorkspaceNameList();
171
172 MatrixWorkspace_sptr efficiencies = getEfficiencies();
173 auto alg = createChildAlgorithm("PolarizationCorrectionWildes");
174 alg->initialize();
175 alg->setProperty("InputWorkspaces", workspaces);
176 alg->setProperty("Efficiencies", efficiencies);
177 if (!isDefault(Prop::FLIPPERS)) {
178 alg->setPropertyValue("Flippers", getPropertyValue(Prop::FLIPPERS));
179 }
181 alg->setPropertyValue("AddSpinStateToLog", getPropertyValue(Prop::ADD_SPIN_STATE_LOG));
182 }
183 if (!isDefault(Prop::OUTPUT_WILDES_SPIN_STATES)) {
184 alg->setPropertyValue("SpinStates", getPropertyValue(Prop::OUTPUT_WILDES_SPIN_STATES));
185 }
186 auto out = getPropertyValue(Prop::OUTPUT_WORKSPACES);
187 alg->setPropertyValue("OutputWorkspace", out);
188 alg->execute();
189 API::WorkspaceGroup_sptr outWS = alg->getProperty("OutputWorkspace");
190 setProperty(Prop::OUTPUT_WORKSPACES, outWS);
191}
192
193//----------------------------------------------------------------------------------------------
197 MatrixWorkspace_sptr efficiencies = getEfficiencies();
198 auto alg = createChildAlgorithm("PolarizationCorrectionFredrikze");
199 alg->initialize();
200 alg->setProperty("InputWorkspace", group);
201 alg->setProperty("Efficiencies", efficiencies);
202 if (!isDefault(Prop::POLARIZATION_ANALYSIS)) {
203 alg->setPropertyValue("PolarizationAnalysis", getPropertyValue(Prop::POLARIZATION_ANALYSIS));
204 }
205 if (!isDefault(Prop::INPUT_FRED_SPIN_STATES)) {
206 alg->setPropertyValue("InputSpinStates", getPropertyValue(Prop::INPUT_FRED_SPIN_STATES));
207 }
208 if (!isDefault(Prop::OUTPUT_FRED_SPIN_STATES)) {
209 alg->setPropertyValue("OutputSpinStates", getPropertyValue(Prop::OUTPUT_FRED_SPIN_STATES));
210 }
211 alg->setPropertyValue("OutputWorkspace", getPropertyValue(Prop::OUTPUT_WORKSPACES));
212 alg->execute();
213 API::WorkspaceGroup_sptr outWS = alg->getProperty("OutputWorkspace");
214 setProperty(Prop::OUTPUT_WORKSPACES, outWS);
215}
216
217//----------------------------------------------------------------------------------------------
221 if (isDefault(Prop::INPUT_WORKSPACES) && isDefault(Prop::INPUT_WORKSPACE_GROUP)) {
222 throw std::invalid_argument("Input workspaces are missing. Either a "
223 "workspace group or a list of workspace names "
224 "must be given.");
225 }
226 if (!isDefault(Prop::INPUT_WORKSPACES) && !isDefault(Prop::INPUT_WORKSPACE_GROUP)) {
227 throw std::invalid_argument("Input workspaces must be given either as a "
228 "workspace group or a list of names.");
229 }
230}
231
232//----------------------------------------------------------------------------------------------
237
238 if (!isDefault(Prop::POLARIZATION_ANALYSIS)) {
239 throw std::invalid_argument("Property PolarizationAnalysis cannot be used with the Wildes method.");
240 }
241
242 if (!isDefault(Prop::INPUT_FRED_SPIN_STATES)) {
243 throw std::invalid_argument("Property SpinStatesInFredrikze cannot be used with the Wildes method.");
244 }
245
246 if (!isDefault(Prop::OUTPUT_FRED_SPIN_STATES)) {
247 throw std::invalid_argument("Property SpinStatesOutFredrikze cannot be used with the Wildes method.");
248 }
249}
250
251//----------------------------------------------------------------------------------------------
256
257 if (!isDefault(Prop::FLIPPERS)) {
258 throw std::invalid_argument("Property Flippers cannot be used with the Fredrikze method.");
259 }
260 if (!isDefault(Prop::OUTPUT_WILDES_SPIN_STATES)) {
261 throw std::invalid_argument("Property SpinStatesOutWildes cannot be used with the Fredrikze method.");
262 }
263}
264
265//----------------------------------------------------------------------------------------------
268std::vector<std::string> PolarizationEfficiencyCor::getWorkspaceNameList() const {
269 std::vector<std::string> wsNames;
270 if (!isDefault(Prop::INPUT_WORKSPACES)) {
271 wsNames = getProperty(Prop::INPUT_WORKSPACES);
272 if (std::any_of(wsNames.cbegin(), wsNames.cend(), [](const auto &wsName) {
273 return AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(wsName) == nullptr;
274 })) {
275 throw std::invalid_argument(
276 "Only Matrix Workspaces can be added in InputWorkspace property list. If the input is a group, "
277 "use the InputWorkspaceGroup property");
278 }
279 } else {
280 WorkspaceGroup_sptr group = getProperty(Prop::INPUT_WORKSPACE_GROUP);
281 auto const n = group->size();
282 for (size_t i = 0; i < n; ++i) {
283 auto ws = group->getItem(i);
284 auto const wsName = ws->getName();
285 if (wsName.empty()) {
286 throw std::invalid_argument("Workspace from the input workspace group is not stored in the "
287 "Analysis Data Service which is required by the Wildes method.");
288 }
289 wsNames.emplace_back(wsName);
290 }
291 }
292 return wsNames;
293}
294
295//----------------------------------------------------------------------------------------------
300 if (!isDefault(Prop::INPUT_WORKSPACE_GROUP)) {
301 group = getProperty(Prop::INPUT_WORKSPACE_GROUP);
302 } else {
303 throw std::invalid_argument("Input workspaces are required to be in a workspace group.");
304 }
305 return group;
306}
307
308//----------------------------------------------------------------------------------------------
312 MatrixWorkspace const &inWS) const {
313
314 if (!efficiencies.isHistogramData())
315 return true;
316 if (efficiencies.blocksize() != inWS.blocksize())
317 return true;
318
319 auto const &x = inWS.x(0);
320 for (size_t i = 0; i < efficiencies.getNumberHistograms(); ++i) {
321 if (efficiencies.x(i).rawData() != x.rawData())
322 return true;
323 }
324 return false;
325}
326
327//----------------------------------------------------------------------------------------------
330 if (efficiencies->isHistogramData()) {
331 return efficiencies;
332 }
333 auto alg = createChildAlgorithm("ConvertToHistogram");
334 alg->initialize();
335 alg->setProperty("InputWorkspace", efficiencies);
336 alg->setProperty("OutputWorkspace", "dummy");
337 alg->execute();
338 MatrixWorkspace_sptr result = alg->getProperty("OutputWorkspace");
339 return result;
340}
341
342//----------------------------------------------------------------------------------------------
345 const MatrixWorkspace_sptr &inWS) {
346
347 efficiencies->setDistribution(true);
348 auto alg = createChildAlgorithm("RebinToWorkspace");
349 alg->initialize();
350 alg->setProperty("WorkspaceToRebin", efficiencies);
351 alg->setProperty("WorkspaceToMatch", inWS);
352 alg->setProperty("OutputWorkspace", "dummy");
353 alg->execute();
354 MatrixWorkspace_sptr result = alg->getProperty("OutputWorkspace");
355 return result;
356}
357
358//----------------------------------------------------------------------------------------------
363 if (!isDefault(Prop::INPUT_WORKSPACES)) {
364 std::vector<std::string> const names = getProperty(Prop::INPUT_WORKSPACES);
365 inWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(names.front());
366 } else {
367 WorkspaceGroup_sptr group = getProperty(Prop::INPUT_WORKSPACE_GROUP);
368 inWS = std::dynamic_pointer_cast<MatrixWorkspace>(group->getItem(0));
369 }
371
372 if (!needInterpolation(*efficiencies, *inWS)) {
373 return efficiencies;
374 }
375
376 efficiencies = convertToHistogram(efficiencies);
377 efficiencies = interpolate(efficiencies, inWS);
378
379 return efficiencies;
380}
381
382} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
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.
bool isDefault(const std::string &name) const
Base MatrixWorkspace Abstract Class.
virtual std::size_t blocksize() const =0
Returns the size of each block of data returned by the dataY accessors.
virtual std::size_t getNumberHistograms() const =0
Returns the number of histograms in the workspace.
const HistogramData::HistogramX & x(const size_t index) const
virtual bool isHistogramData() const
Returns true if the workspace contains data in histogram form (as opposed to point-like)
A property class for workspaces.
PolarizationEfficiencyCor: a generalised polarization correction algorithm.
API::MatrixWorkspace_sptr getEfficiencies()
Prepare and return the efficiencies.
const std::string category() const override
Algorithm's category for identification.
void checkWildesProperties() const
Check that the inputs for the Wildes are correct and consistent.
std::vector< std::string > getWorkspaceNameList() const
Get the input workspaces as a list of names.
API::MatrixWorkspace_sptr convertToHistogram(API::MatrixWorkspace_sptr efficiencies)
Convert the efficiencies to histogram.
API::MatrixWorkspace_sptr interpolate(const API::MatrixWorkspace_sptr &efficiencies, const API::MatrixWorkspace_sptr &inWS)
Convert the efficiencies to histogram.
void checkWorkspaces() const
Check that the inputs workspaces are set.
void init() override
Initialize the algorithm's properties.
API::WorkspaceGroup_sptr getWorkspaceGroup() const
Get the input workspaces as a workspace group.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
void checkFredrikzeProperties() const
Check that the inputs for the Fredrikze method are correct and consistent.
int version() const override
Algorithm's version for identification.
bool needInterpolation(API::MatrixWorkspace const &efficiencies, API::MatrixWorkspace const &inWS) const
Check if efficiencies workspace needs interpolation.
Support for a property that holds an array of values.
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)
ListValidator is a validator that requires the value of a property to be one of a defined list of pos...
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
String constants for algorithm's properties.
static const std::string ADD_SPIN_STATE_LOG
static const std::string EFFICIENCIES
STL namespace.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54