51static const std::string CRHO_LABEL(
"Rho");
53static const std::string CPP_LABEL(
"Pp");
55static const std::string CALPHA_LABEL(
"Alpha");
57static const std::string CAP_LABEL(
"Ap");
59static const std::string PNR_LABEL(
"PNR");
61static const std::string PA_LABEL(
"PA");
63std::vector<std::string> modes() {
64 std::vector<std::string> modes;
65 modes.emplace_back(PA_LABEL);
66 modes.emplace_back(PNR_LABEL);
71 if (groupWS->
size() == 0) {
72 throw std::invalid_argument(
"Input group workspace has no children.");
77 return matrixWS->getInstrument();
81bool isValidSpinState(
const std::vector<std::string> &spinStates,
const std::string &analysisMode) {
82 if (analysisMode == PNR_LABEL) {
84 return (spinStates.size() == 2 &&
90 }
else if (analysisMode == PA_LABEL) {
92 return (spinStates.size() == 4 || spinStates.empty());
99 const std::string &outputStatesStr,
const std::string &analysisMode) {
101 for (
size_t i = 0; i < ws->size(); ++i) {
108 auto wsUnit = ws2d->getAxis(0)->unit();
110 if (wsUnit->unitID() != expectedUnit.unitID()) {
111 throw std::invalid_argument(
"Input workspaces must have units of Wavelength");
116 if (lastWS->getNumberHistograms() != ws2d->getNumberHistograms()) {
117 throw std::invalid_argument(
"Not all workspaces in the "
118 "InputWorkspace WorkspaceGroup have the "
119 "same number of spectrum");
121 if (lastWS->blocksize() != ws2d->blocksize()) {
122 throw std::invalid_argument(
"Number of bins do not match between all "
123 "workspaces in the InputWorkspace "
127 auto ¤tX = ws2d->x(0);
128 auto &lastX = lastWS->x(0);
129 auto xMatches = std::equal(lastX.cbegin(), lastX.cend(), currentX.cbegin());
131 throw std::invalid_argument(
"X-arrays do not match between all "
132 "workspaces in the InputWorkspace "
139 if (!isValidSpinState(inputStates, analysisMode)) {
140 throw std::invalid_argument(
"Invalid input spin state: " + inputStatesStr +
" for " + analysisMode +
141 " The possible values are 'pp,pa,ap,aa' for PA, or 'p,a' for PNR, in any order");
144 if (!isValidSpinState(outputStates, analysisMode)) {
145 throw std::invalid_argument(
"Invalid output spin state: " + outputStatesStr +
" for " + analysisMode +
146 " The possible values are 'pp,pa,ap,aa' for PA, or 'p,a' for PNR, in any order");
154 std::stringstream messageBuffer;
155 messageBuffer <<
"Item with index: " << i <<
"in the InputWorkspace is not a MatrixWorkspace";
156 throw std::invalid_argument(messageBuffer.str());
167std::map<std::string, MatrixWorkspace_sptr> mapSpinStatesToWorkspaces(
const WorkspaceGroup_sptr &inWS,
168 const std::vector<std::string> &spinStates) {
169 std::map<std::string, MatrixWorkspace_sptr> workspaceMap;
171 for (
size_t i = 0; i < spinStates.size(); ++i) {
172 workspaceMap[spinStates[i]] = std::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(i));
193WorkspaceGroup_sptr mapWorkspacesToSpinStates(
const std::map<std::string, MatrixWorkspace_sptr> &workspaces,
194 const std::vector<std::string> &spinStates,
const bool addSpinStateLog) {
196 auto dataOut = std::make_shared<WorkspaceGroup>();
198 std::for_each(spinStates.begin(), spinStates.end(), [&](
const auto &spinState) {
200 auto workspace = workspaces.at(spinState);
202 dataOut->addWorkspace(workspace);
204 if (addSpinStateLog) {
206 addSpinStateLogToWs(workspace, spinState);
236 return "Makes corrections for polarization efficiencies of the polarizer and "
237 "analyzer in a reflectometry neutron spectrometer.";
248 auto rhsWS = std::make_shared<DataObjects::WorkspaceSingleValue>(
rhs);
250 multiply->setProperty(
"LHSWorkspace", lhsWS);
251 multiply->setProperty(
"RHSWorkspace", rhsWS);
265 auto rhsWS = std::make_shared<DataObjects::WorkspaceSingleValue>(
rhs);
267 plus->setProperty(
"LHSWorkspace", lhsWS);
268 plus->setProperty(
"RHSWorkspace", rhsWS);
280 "An input workspace to process.");
282 auto propOptions = modes();
283 declareProperty(
"PolarizationAnalysis",
"PA", std::make_shared<StringListValidator>(propOptions),
284 "What Polarization mode will be used?\n"
285 "PNR: Polarized Neutron Reflectivity mode\n"
286 "PA: Full Polarization Analysis PNR-PA");
290 "A workspace containing the efficiency factors Pp, Ap, Rho and Alpha "
295 "An output workspace.");
297 const auto spinStateValidator =
298 std::make_shared<SpinStateValidator>(std::unordered_set<int>{2, 4},
true,
"p",
"a",
true);
301 "The order of spin states in the input workspace group. The possible values are 'pp,pa,ap,aa' or "
302 "'p,a', in any order.");
305 "The order of spin states in the output workspace group. The possible values are 'pp,pa,ap,aa' or "
306 "'p,a', in any order.");
310 "Whether to add the final spin state into the sample log of each child workspace in the output group.");
314 const std::vector<std::string> &inputSpinStates,
315 const std::vector<std::string> &outputSpinStates,
316 const bool addSpinStateLog) {
321 auto inputMap = mapSpinStatesToWorkspaces(inWS, effectiveInputSpinStates);
328 Ipp->setTitle(
"Ipp");
329 Iaa->setTitle(
"Iaa");
330 Ipa->setTitle(
"Ipa");
331 Iap->setTitle(
"Iap");
338 const auto A0 = (Iaa * pp * ap) + (Ipa * ap *
rho * pp) + (Iap * ap * alpha * pp) + (Ipp * ap * alpha *
rho * pp);
339 const auto A1 = Iaa * pp;
340 const auto A2 = Iap * pp;
341 const auto A3 = Iaa * ap;
342 const auto A4 = Ipa * ap;
343 const auto A5 = Ipp * ap * alpha;
344 const auto A6 = Iap * ap * alpha;
345 const auto A7 = Ipp * pp *
rho;
346 const auto A8 = Ipa * pp *
rho;
348 const auto D = pp * ap * (
rho + alpha + 1.0 + (
rho * alpha));
350 const auto nIpp = (A0 - A1 + A2 - A3 + A4 + A5 - A6 + A7 - A8 + Ipp + Iaa - Ipa - Iap) / D;
351 const auto nIaa = (A0 + A1 - A2 + A3 - A4 - A5 + A6 - A7 + A8 + Ipp + Iaa - Ipa - Iap) / D;
352 const auto nIap = (A0 - A1 + A2 + A3 - A4 - A5 + A6 + A7 - A8 - Ipp - Iaa + Ipa + Iap) / D;
353 const auto nIpa = (A0 + A1 - A2 - A3 + A4 + A5 - A6 - A7 + A8 - Ipp - Iaa + Ipa + Iap) / D;
356 std::map<std::string, MatrixWorkspace_sptr> outputMap;
364 auto dataOut = mapWorkspacesToSpinStates(outputMap, effectiveOutputSpinStates, addSpinStateLog);
366 size_t totalGroupEntries(dataOut->getNumberOfEntries());
367 for (
size_t i = 1; i < totalGroupEntries; i++) {
371 alg->setProperty(
"NaNValue", 0.0);
372 alg->setProperty(
"NaNError", 0.0);
373 alg->setProperty(
"InfinityValue", 0.0);
374 alg->setProperty(
"InfinityError", 0.0);
378 nIpp->history().addHistory(Ipp->getHistory());
379 nIaa->history().addHistory(Iaa->getHistory());
380 nIpa->history().addHistory(Ipa->getHistory());
381 nIap->history().addHistory(Iap->getHistory());
387 const std::vector<std::string> &inputSpinStates,
388 const std::vector<std::string> &outputSpinStates,
389 const bool addSpinStateLog) {
394 auto inputMap = mapSpinStatesToWorkspaces(inWS, effectiveInputOrder);
402 const auto D = pp * (
rho + 1);
404 const auto nIp = (Ip * (
rho * pp + 1.0) + Ia * (pp - 1.0)) / D;
405 const auto nIa = (Ip * (
rho * pp - 1.0) + Ia * (pp + 1.0)) / D;
408 nIp->history().addHistory(Ip->getHistory());
409 nIa->history().addHistory(Ia->getHistory());
411 std::map<std::string, MatrixWorkspace_sptr> outputMap;
417 auto dataOut = mapWorkspacesToSpinStates(outputMap, effectiveOutputSpinStates, addSpinStateLog);
426std::shared_ptr<Mantid::API::MatrixWorkspace>
429 const auto &axis =
dynamic_cast<TextAxis &
>(*efficiencies->getAxis(1));
431 for (
size_t i = 0; i < axis.length(); ++i) {
432 if (axis.label(i) == label) {
438 if (
index == axis.length()) {
441 static std::map<std::string, std::string> loadableProperties{
442 {CRHO_LABEL,
"crho"}, {CPP_LABEL,
"cPp"}, {CAP_LABEL,
"cAp"}, {CALPHA_LABEL,
"calpha"}};
445 auto vals = instrument->getStringParameter(loadableProperties[label]);
447 throw std::invalid_argument(
"Efficiency property not found: " + label);
450 extract->initialize();
452 extract->setProperty(label, vals.front());
458 extract->initialize();
460 extract->setProperty(
"WorkspaceIndex",
static_cast<int>(
index));
472 const std::string analysisMode =
getProperty(
"PolarizationAnalysis");
473 const size_t nWorkspaces = inWS->size();
482 validateInputWorkspace(inWS, inputStatesStr, outputStatesStr, analysisMode);
485 if (analysisMode == PA_LABEL) {
486 if (nWorkspaces != 4) {
487 throw std::invalid_argument(
"For PA analysis, input group must have 4 periods.");
490 outWS =
execPA(inWS, inputStates, outputStates, addSpinStateLog);
491 }
else if (analysisMode == PNR_LABEL) {
492 if (nWorkspaces != 2) {
493 throw std::invalid_argument(
"For PNR analysis, input group must have 2 periods.");
495 outWS =
execPNR(inWS, inputStates, outputStates, addSpinStateLog);
#define DECLARE_ALGORITHM(classname)
const std::vector< double > & rhs
std::map< DeltaEMode::Type, std::string > index
std::vector< double > VecDouble
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.
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.
Class to represent a text axis of a workspace.
std::size_t length() const override
Get the length of the axis.
Class to hold a set of workspaces.
Workspace_sptr getItem(const size_t index) const
Return the ith workspace.
size_t size() const
Return the size of the group, so it is more like a container.
A property class for workspaces.
PolarizationCorrectionFredrikze : Algorithm to perform polarisation corrections on multi-period group...
std::shared_ptr< Mantid::API::WorkspaceGroup > execPA(const std::shared_ptr< Mantid::API::WorkspaceGroup > &inWS, const std::vector< std::string > &inputSpinStates, const std::vector< std::string > &outputSpinStates, const bool addSpinStateLog)
std::shared_ptr< Mantid::API::MatrixWorkspace > add(const std::shared_ptr< Mantid::API::MatrixWorkspace > &lhsWS, const double &rhs)
Add a constant value to a workspace.
void init() override
Initialize the algorithm's properties.
std::shared_ptr< Mantid::API::WorkspaceGroup > execPNR(const std::shared_ptr< Mantid::API::WorkspaceGroup > &inWS, const std::vector< std::string > &inputSpinStates, const std::vector< std::string > &outputSpinStates, const bool addSpinStateLog)
std::shared_ptr< Mantid::API::MatrixWorkspace > getEfficiencyWorkspace(const std::string &label)
Extract a spectrum from the Efficiencies workspace as a 1D workspace.
int version() const override
Algorithm's version for identification.
const std::string summary() const override
std::shared_ptr< Mantid::API::MatrixWorkspace > multiply(const std::shared_ptr< Mantid::API::MatrixWorkspace > &lhsWS, const double &rhs)
Multiply a workspace by a constant value.
const std::string category() const override
Algorithm's category for identification.
void exec() override
Execute the algorithm.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static const std::string PARA_PARA
static const std::string ANTI
static const std::string PARA_ANTI
static const std::string ANTI_ANTI
static const std::string PARA
static const std::string ANTI_PARA
MANTID_ALGORITHMS_DLL void addORSOLogForSpinState(const Mantid::API::MatrixWorkspace_sptr &ws, const std::string &spinState)
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
MANTID_KERNEL_DLL std::vector< std::string > splitSpinStateString(const std::string &spinStates)
String constants for algorithm's properties.
static const std::string ADD_SPIN_STATE_LOG
static const std::string INPUT_WORKSPACE
static const std::string OUTPUT_WORKSPACE
static const std::string EFFICIENCIES
static const std::string OUTPUT_SPIN_STATES("OutputSpinStates")
static const std::vector< std::string > defaultSpinStatesForPNR
static const std::vector< std::string > defaultSpinStatesForPA
static const std::string INPUT_SPIN_STATES("InputSpinStates")
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.