Mantid
Loading...
Searching...
No Matches
EQSANSQ2D.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 +
8#include "MantidAPI/Run.h"
12#include "Poco/NumberFormatter.h"
13
15
16// Register the algorithm into the AlgorithmFactory
17DECLARE_ALGORITHM(EQSANSQ2D)
18
19using namespace Kernel;
20using namespace API;
21using namespace Geometry;
22
24 auto wsValidator = std::make_shared<WorkspaceUnitValidator>("Wavelength");
25 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, wsValidator),
26 "Workspace to calculate I(qx,qy) from");
27 declareProperty("OutputWorkspace", "", Direction::Input);
28 declareProperty("NumberOfBins", 100, "Number of bins in each dimension of the 2D output", Kernel::Direction::Input);
29 declareProperty("IQxQyLogBinning", false, "I(qx,qy) log binning when binning is not specified.",
31 declareProperty("OutputMessage", "", Direction::Output);
32}
33
37double getRunProperty(const MatrixWorkspace_sptr &inputWS, const std::string &pname) {
38 return inputWS->run().getPropertyValueAsType<double>(pname);
39}
40
43 Progress progress(this, 0.0, 1.0, 3);
44 progress.report("Setting up I(qx,Qy) calculation");
45
46 MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
47 const int nbins = getProperty("NumberOfBins");
48
49 // If the OutputWorkspace property was not given, use the
50 // name of the input workspace as the base name for the output
51 std::string outputWSName = getPropertyValue("OutputWorkspace");
52 if (outputWSName.empty()) {
53 outputWSName = inputWS->getName();
54 }
55
56 // Determine whether we need frame skipping or not by checking the chopper
57 // speed
58 bool frame_skipping = false;
59 const auto &run = inputWS->run();
60 if (run.hasProperty("is_frame_skipping")) {
61 auto prop = run.getProperty("is_frame_skipping");
62 const auto &typeInfo = *(prop->type_info());
63 if (typeInfo == typeid(int64_t)) {
64 frame_skipping = (run.getPropertyValueAsType<int64_t>("is_frame_skipping") == 1);
65 } else if (typeInfo == typeid(int32_t)) {
66 frame_skipping = (run.getPropertyValueAsType<int32_t>("is_frame_skipping") == 1);
67 } else
68 g_log.warning() << "Unknown property type for is_frame_skipping\n";
69 }
70
71 // Get run properties necessary to calculate the input parameters to Qxy
72 // Wavelength bandwidths
73 double wavelength_min = 0.0;
74 if (inputWS->run().hasProperty("wavelength_min"))
75 wavelength_min = getRunProperty(inputWS, "wavelength_min");
76 else if (inputWS->dataX(0).size() > 1)
77 wavelength_min = (inputWS->dataX(1)[0] + inputWS->dataX(1)[1]) / 2.0;
78 else if (inputWS->dataX(0).size() == 1)
79 wavelength_min = inputWS->dataX(1)[0];
80 else {
81 g_log.error("Can't determine the minimum wavelength for the input workspace.");
82 throw std::invalid_argument("Can't determine the minimum wavelength for the input workspace.");
83 }
84
85 double qmax = 0;
86 if (inputWS->run().hasProperty("qmax")) {
87 qmax = getRunProperty(inputWS, "qmax");
88 g_log.debug() << "Using Qmax from run properties = " << qmax << std::endl;
89 } else {
90 // This is pointing to the correct parameter in the workspace,
91 // which has been changed to the right distance in EQSANSLoad.cpp
92 const double sample_detector_distance = getRunProperty(inputWS, "sample_detector_distance");
93
94 const double nx_pixels = inputWS->getInstrument()->getNumberParameter("number-of-x-pixels")[0];
95 const double ny_pixels = inputWS->getInstrument()->getNumberParameter("number-of-y-pixels")[0];
96 const double pixel_size_x = inputWS->getInstrument()->getNumberParameter("x-pixel-size")[0];
97 const double pixel_size_y = inputWS->getInstrument()->getNumberParameter("y-pixel-size")[0];
98
99 const double beam_ctr_x = getRunProperty(inputWS, "beam_center_x");
100 const double beam_ctr_y = getRunProperty(inputWS, "beam_center_y");
101
102 double dxmax = pixel_size_x * std::max(beam_ctr_x, nx_pixels - beam_ctr_x);
103 double dymax = pixel_size_y * std::max(beam_ctr_y, ny_pixels - beam_ctr_y);
104 double maxdist = std::max(dxmax, dymax);
105
106 // This uses the correct parameter in the workspace, which has been
107 // changed to the right distance in EQSANSLoad.cpp
108 qmax = 4 * M_PI / wavelength_min * std::sin(0.5 * std::atan(maxdist / sample_detector_distance));
109 g_log.debug() << "Using calculated Qmax = " << qmax << std::endl;
110 };
111
112 if (frame_skipping) {
113 // In frame skipping mode, treat each frame separately
114 const double wavelength_max = getRunProperty(inputWS, "wavelength_max");
115 const double wavelength_min_f2 = getRunProperty(inputWS, "wavelength_min_frame2");
116 const double wavelength_max_f2 = getRunProperty(inputWS, "wavelength_max_frame2");
117
118 // Frame 1
119 std::string params =
120 Poco::NumberFormatter::format(wavelength_min, 2) + ",0.1," + Poco::NumberFormatter::format(wavelength_max, 2);
121 auto rebinAlg = createChildAlgorithm("Rebin", 0.4, 0.5);
122 rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS);
123 rebinAlg->setPropertyValue("Params", params);
124 rebinAlg->setProperty("PreserveEvents", false);
125 rebinAlg->executeAsChildAlg();
126
127 const bool log_binning = getProperty("IQxQyLogBinning");
128 auto qxyAlg = createChildAlgorithm("Qxy", .5, .65);
129 qxyAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", rebinAlg->getProperty("OutputWorkspace"));
130 qxyAlg->setProperty<double>("MaxQxy", qmax);
131 qxyAlg->setProperty<double>("DeltaQ", qmax / nbins);
132 qxyAlg->setProperty<bool>("SolidAngleWeighting", false);
133 qxyAlg->setProperty<bool>("IQxQyLogBinning", log_binning);
134 qxyAlg->executeAsChildAlg();
135
136 MatrixWorkspace_sptr qxy_output = qxyAlg->getProperty("OutputWorkspace");
137 auto replaceAlg = createChildAlgorithm("ReplaceSpecialValues", .65, 0.7);
138 replaceAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", qxy_output);
139 replaceAlg->setProperty<double>("NaNValue", 0.0);
140 replaceAlg->setProperty<double>("NaNError", 0.0);
141 replaceAlg->executeAsChildAlg();
142
143 std::string outputWSName_frame = outputWSName + "_frame1_Iqxy";
145 std::make_unique<WorkspaceProperty<>>("OutputWorkspaceFrame1", outputWSName_frame, Direction::Output));
146 MatrixWorkspace_sptr result = replaceAlg->getProperty("OutputWorkspace");
147 setProperty("OutputWorkspaceFrame1", result);
148
149 // Frame 2
150 params = Poco::NumberFormatter::format(wavelength_min_f2, 2) + ",0.1," +
151 Poco::NumberFormatter::format(wavelength_max_f2, 2);
152 rebinAlg = createChildAlgorithm("Rebin", 0.7, 0.8);
153 rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS);
154 rebinAlg->setPropertyValue("Params", params);
155 rebinAlg->setProperty("PreserveEvents", false);
156 rebinAlg->executeAsChildAlg();
157
158 qxyAlg = createChildAlgorithm("Qxy", .8, 0.95);
159 qxyAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", rebinAlg->getProperty("OutputWorkspace"));
160 qxyAlg->setProperty<double>("MaxQxy", qmax);
161 qxyAlg->setProperty<double>("DeltaQ", qmax / nbins);
162 qxyAlg->setProperty<bool>("SolidAngleWeighting", false);
163 qxyAlg->setProperty<bool>("IQxQyLogBinning", log_binning);
164 qxyAlg->executeAsChildAlg();
165
166 qxy_output = qxyAlg->getProperty("OutputWorkspace");
167 replaceAlg = createChildAlgorithm("ReplaceSpecialValues", .95, 1.0);
168 replaceAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", qxy_output);
169 replaceAlg->setProperty<double>("NaNValue", 0.0);
170 replaceAlg->setProperty<double>("NaNError", 0.0);
171 replaceAlg->executeAsChildAlg();
172
173 outputWSName_frame = outputWSName + "_frame2_Iqxy";
175 std::make_unique<WorkspaceProperty<>>("OutputWorkspaceFrame2", outputWSName_frame, Direction::Output));
176 result = replaceAlg->getProperty("OutputWorkspace");
177 setProperty("OutputWorkspaceFrame2", result);
178 setProperty("OutputMessage", "I(Qx,Qy) computed for each frame");
179 } else {
180 // When not in frame skipping mode, simply run Qxy
181 const bool log_binning = getProperty("IQxQyLogBinning");
182 auto qxyAlg = createChildAlgorithm("Qxy", .3, 0.9);
183 qxyAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS);
184 qxyAlg->setProperty<double>("MaxQxy", qmax);
185 qxyAlg->setProperty<double>("DeltaQ", qmax / nbins);
186 qxyAlg->setProperty<bool>("SolidAngleWeighting", false);
187 qxyAlg->setProperty<bool>("IQxQyLogBinning", log_binning);
188 qxyAlg->executeAsChildAlg();
189
190 MatrixWorkspace_sptr qxy_output = qxyAlg->getProperty("OutputWorkspace");
191 auto replaceAlg = createChildAlgorithm("ReplaceSpecialValues", .9, 1.0);
192 replaceAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", qxy_output);
193 replaceAlg->setProperty<double>("NaNValue", 0.0);
194 replaceAlg->setProperty<double>("NaNError", 0.0);
195 replaceAlg->executeAsChildAlg();
196
197 outputWSName += "_Iqxy";
198 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspaceFrame1", outputWSName, Direction::Output));
199 MatrixWorkspace_sptr result = replaceAlg->getProperty("OutputWorkspace");
200 setProperty("OutputWorkspaceFrame1", result);
201 setProperty("OutputMessage", "I(Qx,Qy) computed for each frame");
202 }
203}
204
205} // namespace Mantid::WorkflowAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void init() override
Initialisation code.
Definition: EQSANSQ2D.cpp:23
void exec() override
Execution code.
Definition: EQSANSQ2D.cpp:42
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
double getRunProperty(const MatrixWorkspace_sptr &inputWS, const std::string &pname)
Returns the value of a run property from a given workspace.
Definition: EQSANSQ2D.cpp:37
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54