15#include "MantidHistogramData/HistogramMath.h"
24static const std::string PARALLAX_PARAMETER =
"parallax";
25static const std::string DIRECTION_PARAMETER =
"direction";
33std::string validateFormula(
const std::string ¶llax,
const std::string &direction) {
34 if (direction !=
"x" && direction !=
"y") {
35 return "Direction must be x or y";
39 muParser.DefineVar(
"t", &t);
40 muParser.SetExpr(parallax);
43 }
catch (mu::Parser::exception_type &e) {
68 return "Performs parallax correction for tube based SANS instruments.";
73 std::map<std::string, std::string> results;
74 const std::vector<double> angleOffsets =
getProperty(
"AngleOffsets");
75 const std::vector<std::string> componentNames =
getProperty(
"ComponentNames");
76 if (angleOffsets.size() != componentNames.size() && angleOffsets.size() != 1) {
77 results[
"AngleOffsets"] =
"Angle offsets should have one value or as many "
78 "as there are components";
87 auto validator = std::make_shared<Kernel::CompositeValidator>();
88 validator->add(std::make_unique<API::InstrumentValidator>());
89 auto lengthValidator = std::make_shared<Kernel::ArrayLengthValidator<std::string>>();
90 lengthValidator->setLengthMin(1);
93 "An input workspace.");
95 "List of instrument components to perform the corrections for.");
98 "An output workspace.");
101 "The values of offset angles [degrees] to be subtracted from "
102 "the scattering angle (per component).");
115 const std::string ¶llax,
const std::string &direction,
116 const double angleOffset) {
119 muParser.DefineVar(
"t", &t);
120 muParser.SetExpr(parallax);
121 const auto &detectorInfo = outWS->detectorInfo();
123 for (
const auto wsIndex : indices) {
124 const Kernel::V3D pos = detectorInfo.position(wsIndex);
125 if (direction ==
"y") {
126 t = std::fabs(std::atan2(pos.
X(), pos.
Z()));
128 t = std::fabs(std::atan2(pos.
Y(), pos.
Z()));
130 t -= angleOffset * M_PI / 180.;
131 const double correction = muParser.Eval();
132 if (correction > 0.) {
133 auto &spectrum = outWS->mutableY(wsIndex);
134 auto &errors = outWS->mutableE(wsIndex);
135 spectrum /= correction;
136 errors /= correction;
138 g_log.
warning() <<
"Correction is <=0 for workspace index " << wsIndex <<
". Skipping the correction.\n";
149 if (inputWorkspace != outputWorkspace) {
150 outputWorkspace = inputWorkspace->clone();
152 const std::vector<double> angleOffsets =
getProperty(
"AngleOffsets");
153 const std::vector<std::string> componentNames =
getProperty(
"ComponentNames");
154 const auto &instrument = inputWorkspace->getInstrument();
155 const auto &detectorInfo = outputWorkspace->detectorInfo();
156 const auto &allDetIDs = detectorInfo.detectorIDs();
157 const auto &componentInfo = outputWorkspace->componentInfo();
158 auto progress = std::make_unique<API::Progress>(
this, 0., 1., componentNames.size());
159 size_t componentIndex = 0;
160 for (
const auto &componentName : componentNames) {
161 const double angleOffset = angleOffsets[(angleOffsets.size() == 1) ? 0 : componentIndex];
163 progress->report(
"Performing parallax correction for component " + componentName);
164 const auto component = instrument->getComponentByName(componentName);
166 g_log.
error() <<
"No component defined with name " << componentName <<
"\n";
169 if (!component->hasParameter(PARALLAX_PARAMETER) || !component->hasParameter(DIRECTION_PARAMETER)) {
170 g_log.
error() <<
"No parallax correction defined in IPF for component " << componentName <<
"\n";
173 const std::string parallax = component->getStringParameter(PARALLAX_PARAMETER)[0];
174 const std::string direction = component->getStringParameter(DIRECTION_PARAMETER)[0];
175 const auto valid = validateFormula(parallax, direction);
176 if (!valid.empty()) {
177 g_log.
error() <<
"Unable to parse the parallax formula and direction "
179 << componentName <<
". Reason: " << valid <<
"\n";
182 const auto &detectorIndices = componentInfo.detectorsInSubtree(componentInfo.indexOfAny(componentName));
183 if (detectorIndices.empty()) {
184 g_log.
error() <<
"No detectors found in component " << componentName <<
"\n";
187 std::vector<detid_t> detIDs;
188 detIDs.reserve(detectorIndices.size());
189 std::transform(detectorIndices.cbegin(), detectorIndices.cend(), std::back_inserter(detIDs),
190 [&allDetIDs](
size_t i) { return allDetIDs[i]; });
191 const auto indices = outputWorkspace->getIndicesFromDetectorIDs(detIDs);
#define DECLARE_ALGORITHM(classname)
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
A property class for workspaces.
ParallaxCorrection : Performs geometrical correction for parallax effect in tube based SANS instrumen...
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::string category() const override
Algorithm's category for identification.
std::map< std::string, std::string > validateInputs() override
Validate inputs.
int version() const override
Algorithm's version for identification.
void performCorrection(const API::MatrixWorkspace_sptr &, const std::vector< size_t > &, const std::string &, const std::string &, const double)
ParallaxCorrection::performCorrection for the given bank.
void exec() override
Execute the algorithm.
void init() override
Initialize the algorithm's properties.
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 error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
constexpr double X() const noexcept
Get x.
constexpr double Y() const noexcept
Get y.
constexpr double Z() const noexcept
Get z.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
@ Input
An input workspace.
@ Output
An output workspace.