Mantid
Loading...
Searching...
No Matches
PolarizerEfficiency.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2024 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 +
7
9#include "MantidAPI/Axis.h"
20#include "MantidKernel/Unit.h"
21
22#include <boost/algorithm/string/join.hpp>
23#include <filesystem>
24
25namespace Mantid::Algorithms {
26// Register the algorithm into the algorithm factory
27DECLARE_ALGORITHM(PolarizerEfficiency)
28
29using namespace Kernel;
30using namespace API;
31using namespace FlipperConfigurations;
32
33namespace PropertyNames {
34static const std::string INPUT_WORKSPACE = "InputWorkspace";
35static const std::string ANALYSER_EFFICIENCY = "AnalyserEfficiency";
36static const std::string SPIN_STATES = "SpinStates";
37static const std::string OUTPUT_WORKSPACE = "OutputWorkspace";
38static const std::string OUTPUT_FILE_PATH = "OutputFilePath";
39} // namespace PropertyNames
40
41namespace {
42static const std::string FILE_EXTENSION = ".nxs";
43
51bool validateInputWorkspace(MatrixWorkspace_sptr const &ws, std::string const &propertyName,
52 std::map<std::string, std::string> &errorList) {
53 if (ws == nullptr) {
54 errorList[propertyName] = "All input workspaces must be of type MatrixWorkspace.";
55 return false;
56 }
57 if (ws->getNumberHistograms() != 1) {
58 errorList[propertyName] = "All input workspaces must contain a single histogram.";
59 return true;
60 }
61 if (ws->getAxis(0)->unit()->unitID() != "Wavelength") {
62 errorList[propertyName] = "All input workspaces must be in units of Wavelength.";
63 return true;
64 }
65 if (!ws->isHistogramData() && ws->isDistribution()) {
66 errorList[propertyName] = "All input workspaces must be using distributed histogram data.";
67 return true;
68 }
69 return true;
70}
71
72} // unnamed namespace
73
76 std::make_unique<WorkspaceProperty<WorkspaceGroup>>(
78 std::make_shared<Mantid::API::PolSANSWorkspaceValidator>(true, false, std::unordered_set<int>{2, 3, 4})),
79 "Input group workspace to use for polarization calculation");
80 const auto &wavelengthValidator = std::make_shared<WorkspaceUnitValidator>("Wavelength");
82 Direction::Input, wavelengthValidator),
83 "Analyser efficiency as a function of wavelength");
86 "Polarizer efficiency as a function of wavelength");
87
88 const auto &spinValidator = std::make_shared<SpinStateValidator>(std::unordered_set<int>{2, 3, 4});
89 declareProperty(PropertyNames::SPIN_STATES, "11,10,01,00", spinValidator,
90 "Order of individual spin states in the input group workspace, e.g. \"01,11,00,10\"");
91
93 "File name or path for the output to be saved to.");
94}
95
101std::map<std::string, std::string> PolarizerEfficiency::validateInputs() {
102 std::map<std::string, std::string> errorList;
103 // Check input workspaces.
106 if (!validateInputWorkspace(analyserWs, PropertyNames::ANALYSER_EFFICIENCY, errorList)) {
107 return errorList;
108 }
109
110 auto const &inputWsCount = inputWorkspace->size();
112 if (spinStates.size() != inputWsCount) {
113 errorList[PropertyNames::SPIN_STATES] =
114 "The number of workspaces in the input WorkspaceGroup (" + std::to_string(inputWsCount) +
115 ") does not match the number of spin states provided (" + std::to_string(spinStates.size()) + ").";
116 return errorList;
117 }
120 if (!t01WsIndex.has_value() || !t00WsIndex.has_value()) {
121 errorList[PropertyNames::SPIN_STATES] =
122 "The required spin configurations (00, 01) could not be found in the given SpinStates.";
123 } else {
124 const MatrixWorkspace_sptr t00Ws =
125 std::dynamic_pointer_cast<MatrixWorkspace>(inputWorkspace->getItem(t00WsIndex.value()));
126 if (!WorkspaceHelpers::matchingBins(t00Ws, analyserWs, true)) {
127 errorList[PropertyNames::ANALYSER_EFFICIENCY] = "The bins in the " + std::string(PropertyNames::INPUT_WORKSPACE) +
129 "workspace do not match.";
130 }
131 }
132
133 // Check outputs.
135 auto const &outputFile = getPropertyValue(PropertyNames::OUTPUT_FILE_PATH);
136 if (outputWs.empty() && outputFile.empty()) {
137 errorList[PropertyNames::OUTPUT_FILE_PATH] = "Either an output workspace or output file must be provided.";
138 errorList[PropertyNames::OUTPUT_WORKSPACE] = "Either an output workspace or output file must be provided.";
139 }
140
141 return errorList;
142}
143
145
147 // First we extract the individual workspaces corresponding to each spin configuration from the group workspace
149 const auto spinConfigurationInput = getPropertyValue(PropertyNames::SPIN_STATES);
150
151 const auto &t01Ws = PolarizationCorrectionsHelpers::workspaceForSpinState(groupWorkspace, spinConfigurationInput,
153 const auto &t00Ws = PolarizationCorrectionsHelpers::workspaceForSpinState(groupWorkspace, spinConfigurationInput,
155
157
158 auto &&effPolarizer = (t00Ws - t01Ws) / (2 * (2 * effCell - 1) * (t00Ws + t01Ws)) + 0.5;
159
160 calculateErrors(t00Ws, t01Ws, effCell, effPolarizer);
161
163 if (!filename.empty()) {
164 saveToFile(effPolarizer, filename);
165 }
166
167 auto const &outputWsName = getPropertyValue(PropertyNames::OUTPUT_WORKSPACE);
168 if (!outputWsName.empty()) {
170 }
171}
172
174 const MatrixWorkspace_sptr &effCellWs,
175 const MatrixWorkspace_sptr &effPolarizerWs) {
176
177 auto &effPolarizerE = effPolarizerWs->mutableE(0);
178 const auto &t00E = t00Ws->e(0);
179 const auto &t01E = t01Ws->e(0);
180 const auto &effCellE = effCellWs->e(0);
181 const auto &t00Y = t00Ws->y(0);
182 const auto &t01Y = t01Ws->y(0);
183 const auto &effCellY = effCellWs->y(0);
184
185 for (size_t i = 0; i < effPolarizerE.size(); ++i) {
186 const auto &twoCellEffMinusOne = 2 * effCellY[i] - 1;
187 const auto &t00PlusT01 = t00Y[i] + t01Y[i];
188
189 const auto &delta00 = (t01Y[i]) / ((twoCellEffMinusOne)*pow(t00PlusT01, 2));
190 const auto &delta01 = (-1 * t00Y[i]) / ((twoCellEffMinusOne)*pow(t00PlusT01, 2));
191 const auto &deltaEffCell = (t01Y[i] - t00Y[i]) / (pow(twoCellEffMinusOne, 2) * (t00PlusT01));
192 effPolarizerE[i] = sqrt(pow(delta00 * t00E[i], 2) + pow(delta01 * t01E[i], 2) + pow(deltaEffCell * effCellE[i], 2));
193 }
194}
195
196void PolarizerEfficiency::saveToFile(MatrixWorkspace_sptr const &workspace, std::string const &filePathStr) {
197 std::filesystem::path filePath = filePathStr;
198 // Add the nexus extension if it's not been applied already.
199 if (filePath.extension() != FILE_EXTENSION) {
200 filePath.replace_extension(FILE_EXTENSION);
201 }
202 auto saveAlg = createChildAlgorithm("SaveNexus");
203 saveAlg->initialize();
204 saveAlg->setProperty("Filename", filePath.string());
205 saveAlg->setProperty("InputWorkspace", workspace);
206 saveAlg->execute();
207}
208
209} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
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.
@ OptionalSave
to specify a file to write to but an empty string is
A property class for workspaces.
std::map< std::string, std::string > validateInputs() override
Check that input params are valid.
void saveToFile(MatrixWorkspace_sptr const &workspace, std::string const &filePathStr)
void init() override
Virtual method - must be overridden by concrete algorithm.
void exec() override
Virtual method - must be overridden by concrete algorithm.
void calculateErrors(const MatrixWorkspace_sptr &t00Ws, const MatrixWorkspace_sptr &t01Ws, const MatrixWorkspace_sptr &effCellWs, const MatrixWorkspace_sptr &effPolarizerWs)
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
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
MANTID_ALGORITHMS_DLL API::MatrixWorkspace_sptr workspaceForSpinState(const API::WorkspaceGroup_sptr &group, const std::string &spinStateOrder, const std::string &targetSpinState)
Returns the workspace in the group associated with the given targetSpinState according to the order d...
static const std::string OUTPUT_WORKSPACE
static const std::string ANALYSER_EFFICIENCY
static const std::string OUTPUT_FILE_PATH
MANTID_KERNEL_DLL std::vector< std::string > splitSpinStateString(const std::string &spinStates)
MANTID_KERNEL_DLL std::optional< size_t > indexOfWorkspaceForSpinState(const std::vector< std::string > &spinStateOrder, std::string targetSpinState)
std::string to_string(const wide_integer< Bits, Signed > &n)
static bool matchingBins(const std::shared_ptr< const MatrixWorkspace > &ws1, const std::shared_ptr< const MatrixWorkspace > &ws2, const bool firstOnly=false)
Checks whether the bins (X values) of two workspace are the same.
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55