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
21#include <boost/algorithm/string/join.hpp>
22#include <filesystem>
23
24namespace Mantid::Algorithms {
25// Register the algorithm into the algorithm factory
26DECLARE_ALGORITHM(PolarizerEfficiency)
27
28using namespace Kernel;
29using namespace API;
30using namespace FlipperConfigurations;
31
32namespace PropertyNames {
33static const std::string INPUT_WORKSPACE = "InputWorkspace";
34static const std::string ANALYSER_EFFICIENCY = "AnalyserEfficiency";
35static const std::string SPIN_STATES = "SpinStates";
36static const std::string OUTPUT_WORKSPACE = "OutputWorkspace";
37static const std::string OUTPUT_FILE_PATH = "OutputFilePath";
38} // namespace PropertyNames
39
40namespace {
41static const std::string FILE_EXTENSION = ".nxs";
42
50bool validateInputWorkspace(MatrixWorkspace_sptr const &ws, std::string const &propertyName,
51 std::map<std::string, std::string> &errorList) {
52 if (ws == nullptr) {
53 errorList[propertyName] = "All input workspaces must be of type MatrixWorkspace.";
54 return false;
55 }
56 if (ws->getNumberHistograms() != 1) {
57 errorList[propertyName] = "All input workspaces must contain a single histogram.";
58 return true;
59 }
60 if (ws->getAxis(0)->unit()->unitID() != "Wavelength") {
61 errorList[propertyName] = "All input workspaces must be in units of Wavelength.";
62 return true;
63 }
64 if (!ws->isHistogramData() && ws->isDistribution()) {
65 errorList[propertyName] = "All input workspaces must be using distributed histogram data.";
66 return true;
67 }
68 return true;
69}
70
71} // unnamed namespace
72
75 std::make_unique<WorkspaceProperty<WorkspaceGroup>>(
77 std::make_shared<Mantid::API::PolSANSWorkspaceValidator>(true, false, std::unordered_set<int>{2, 3, 4})),
78 "Input group workspace to use for polarization calculation");
79 const auto &wavelengthValidator = std::make_shared<WorkspaceUnitValidator>("Wavelength");
81 Direction::Input, wavelengthValidator),
82 "Analyser efficiency as a function of wavelength");
85 "Polarizer efficiency as a function of wavelength");
86
87 const auto &spinValidator = std::make_shared<SpinStateValidator>(std::unordered_set<int>{2, 3, 4});
88 declareProperty(PropertyNames::SPIN_STATES, "11,10,01,00", spinValidator,
89 "Order of individual spin states in the input group workspace, e.g. \"01,11,00,10\"");
90
92 "File name or path for the output to be saved to.");
93}
94
100std::map<std::string, std::string> PolarizerEfficiency::validateInputs() {
101 std::map<std::string, std::string> errorList;
102 // Check input workspaces.
105 if (!validateInputWorkspace(analyserWs, PropertyNames::ANALYSER_EFFICIENCY, errorList)) {
106 return errorList;
107 }
108
109 auto const &inputWsCount = inputWorkspace->size();
111 if (spinStates.size() != inputWsCount) {
112 errorList[PropertyNames::SPIN_STATES] =
113 "The number of workspaces in the input WorkspaceGroup (" + std::to_string(inputWsCount) +
114 ") does not match the number of spin states provided (" + std::to_string(spinStates.size()) + ").";
115 return errorList;
116 }
119 if (!t01WsIndex.has_value() || !t00WsIndex.has_value()) {
120 errorList[PropertyNames::SPIN_STATES] =
121 "The required spin configurations (00, 01) could not be found in the given SpinStates.";
122 } else {
123 const MatrixWorkspace_sptr t00Ws =
124 std::dynamic_pointer_cast<MatrixWorkspace>(inputWorkspace->getItem(t00WsIndex.value()));
125 if (!WorkspaceHelpers::matchingBins(t00Ws, analyserWs, true)) {
126 errorList[PropertyNames::ANALYSER_EFFICIENCY] = "The bins in the " + std::string(PropertyNames::INPUT_WORKSPACE) +
128 "workspace do not match.";
129 }
130 }
131
132 // Check outputs.
134 auto const &outputFile = getPropertyValue(PropertyNames::OUTPUT_FILE_PATH);
135 if (outputWs.empty() && outputFile.empty()) {
136 errorList[PropertyNames::OUTPUT_FILE_PATH] = "Either an output workspace or output file must be provided.";
137 errorList[PropertyNames::OUTPUT_WORKSPACE] = "Either an output workspace or output file must be provided.";
138 }
139
140 return errorList;
141}
142
144
146 // First we extract the individual workspaces corresponding to each spin configuration from the group workspace
148 const auto spinConfigurationInput = getPropertyValue(PropertyNames::SPIN_STATES);
149
150 const auto &t01Ws = PolarizationCorrectionsHelpers::workspaceForSpinState(groupWorkspace, spinConfigurationInput,
152 const auto &t00Ws = PolarizationCorrectionsHelpers::workspaceForSpinState(groupWorkspace, spinConfigurationInput,
154
156
157 auto &&effPolarizer = (t00Ws - t01Ws) / (2 * (2 * effCell - 1) * (t00Ws + t01Ws)) + 0.5;
158
159 calculateErrors(t00Ws, t01Ws, effCell, effPolarizer);
160
162 if (!filename.empty()) {
163 saveToFile(effPolarizer, filename);
164 }
165
166 auto const &outputWsName = getPropertyValue(PropertyNames::OUTPUT_WORKSPACE);
167 if (!outputWsName.empty()) {
169 }
170}
171
173 const MatrixWorkspace_sptr &effCellWs,
174 const MatrixWorkspace_sptr &effPolarizerWs) {
175
176 auto &effPolarizerE = effPolarizerWs->mutableE(0);
177 const auto &t00E = t00Ws->e(0);
178 const auto &t01E = t01Ws->e(0);
179 const auto &effCellE = effCellWs->e(0);
180 const auto &t00Y = t00Ws->y(0);
181 const auto &t01Y = t01Ws->y(0);
182 const auto &effCellY = effCellWs->y(0);
183
184 for (size_t i = 0; i < effPolarizerE.size(); ++i) {
185 const auto &twoCellEffMinusOne = 2 * effCellY[i] - 1;
186 const auto &t00PlusT01 = t00Y[i] + t01Y[i];
187
188 const auto &delta00 = (t01Y[i]) / ((twoCellEffMinusOne)*pow(t00PlusT01, 2));
189 const auto &delta01 = (-1 * t00Y[i]) / ((twoCellEffMinusOne)*pow(t00PlusT01, 2));
190 const auto &deltaEffCell = (t01Y[i] - t00Y[i]) / (pow(twoCellEffMinusOne, 2) * (t00PlusT01));
191 effPolarizerE[i] = sqrt(pow(delta00 * t00E[i], 2) + pow(delta01 * t01E[i], 2) + pow(deltaEffCell * effCellE[i], 2));
192 }
193}
194
195void PolarizerEfficiency::saveToFile(MatrixWorkspace_sptr const &workspace, std::string const &filePathStr) {
196 std::filesystem::path filePath = filePathStr;
197 // Add the nexus extension if it's not been applied already.
198 if (filePath.extension() != FILE_EXTENSION) {
199 filePath.replace_extension(FILE_EXTENSION);
200 }
201 auto saveAlg = createChildAlgorithm("SaveNexus");
202 saveAlg->initialize();
203 saveAlg->setProperty("Filename", filePath.string());
204 saveAlg->setProperty("InputWorkspace", workspace);
205 saveAlg->execute();
206}
207
208} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
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:53
@ Output
An output workspace.
Definition Property.h:54