Mantid
Loading...
Searching...
No Matches
ScaleX.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 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
11#include "MantidAPI/Axis.h"
19#include "MantidTypes/SpectrumDefinition.h"
20
21namespace Mantid::Algorithms {
22
23using namespace Kernel;
24using namespace API;
25using namespace DataObjects;
26
27// Register the class into the algorithm factory
29
30
34 : API::Algorithm(), m_progress(nullptr), m_algFactor(1.0), m_parname(), m_combine(false), m_binOp(), m_wi_min(-1),
35 m_wi_max(-1) {}
36
41 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input),
42 "Name of the input workspace");
43 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
44 "Name of the output workspace");
45 auto isDouble = std::make_shared<BoundedValidator<double>>();
46 declareProperty("Factor", m_algFactor, isDouble,
47 "The value by which to scale the X-axis of the input "
48 "workspace. Default is 1.0");
49 std::vector<std::string> op(2);
50 op[0] = "Multiply";
51 op[1] = "Add";
52 declareProperty("Operation", "Multiply", std::make_shared<StringListValidator>(op),
53 "Whether to multiply by, or add factor");
54 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
55 mustBePositive->setLower(0);
56 declareProperty("IndexMin", 0, mustBePositive,
57 "The workspace index of the first spectrum to scale. Only "
58 "used if IndexMax is set.");
59 declareProperty("IndexMax", Mantid::EMPTY_INT(), mustBePositive,
60 "The workspace index of the last spectrum to scale. Only "
61 "used if explicitly set.");
62 // Add InstrumentParameter property here so as not to mess with the parameter
63 // order for current scripts
64 declareProperty("InstrumentParameter", m_parname,
65 "The name of an instrument parameter whose value is used to "
66 "scale as the input factor");
67 declareProperty("Combine", m_combine,
68 "If true, combine the value given in the Factor property with the value "
69 "obtained from the instrument parameter. The factors are combined using "
70 "the operation specified "
71 "in the Operation parameter");
72}
73
78 // Get input workspace and offset
79 const MatrixWorkspace_sptr inputW = getProperty("InputWorkspace");
80 m_algFactor = getProperty("Factor");
81 m_parname = getPropertyValue("InstrumentParameter");
82 m_combine = getProperty("Combine");
83 if (m_combine && m_parname.empty()) {
84 throw std::invalid_argument("Combine behaviour requested but the "
85 "InstrumentParameter argument is blank.");
86 }
87
88 const std::string op = getPropertyValue("Operation");
90 // Get number of histograms
91 auto histnumber = static_cast<int>(inputW->getNumberHistograms());
92 m_progress = std::make_unique<API::Progress>(this, 0.0, 1.0, histnumber + 1);
93 m_progress->report("Scaling X");
94 m_wi_min = 0;
95 m_wi_max = histnumber - 1;
96 // check if workspace indexes have been set
97 int tempwi_min = getProperty("IndexMin");
98 int tempwi_max = getProperty("IndexMax");
99 if (tempwi_max != Mantid::EMPTY_INT()) {
100 if ((m_wi_min <= tempwi_min) && (tempwi_min <= tempwi_max) && (tempwi_max <= m_wi_max)) {
101 m_wi_min = tempwi_min;
102 m_wi_max = tempwi_max;
103 } else {
104 g_log.error("Invalid Workspace Index min/max properties");
105 throw std::invalid_argument("Inconsistent properties defined");
106 }
107 }
108 // Setup appropriate binary function
109 const bool multiply = (op == "Multiply");
110 if (multiply)
111 m_binOp = std::multiplies<double>();
112 else
113 m_binOp = std::plus<double>();
114
115 // Check if its an event workspace
116 EventWorkspace_const_sptr eventWS = std::dynamic_pointer_cast<const EventWorkspace>(inputW);
117 if (eventWS != nullptr) {
118 this->execEvent();
119 return;
120 }
121
122 // do the shift in X
123 PARALLEL_FOR_IF(Kernel::threadSafe(*inputW, *outputW))
124 for (int i = 0; i < histnumber; ++i) {
126
127 // Copy y and e data
128 outputW->setHistogram(i, inputW->histogram(i));
129
130 auto &outX = outputW->mutableX(i);
131 auto &outY = outputW->mutableY(i);
132 auto &outE = outputW->mutableE(i);
133
134 const auto &inX = inputW->x(i);
135 // Change bin value by offset
136 if ((i >= m_wi_min) && (i <= m_wi_max)) {
137 double factor = getScaleFactor(inputW, i);
138 // Do the offsetting
139 using std::placeholders::_1;
140 std::transform(inX.begin(), inX.end(), outX.begin(), std::bind(m_binOp, _1, factor));
141 // reverse the vector if multiplicative factor was negative
142 if (multiply && factor < 0.0) {
143 std::reverse(outX.begin(), outX.end());
144 std::reverse(outY.begin(), outY.end());
145 std::reverse(outE.begin(), outE.end());
146 }
147 }
148
149 m_progress->report("Scaling X");
150
152 }
154
155 // Copy units
156 if (outputW->getAxis(0)->unit().get())
157 outputW->getAxis(0)->unit() = inputW->getAxis(0)->unit();
158 try {
159 if (inputW->getAxis(1)->unit().get())
160 outputW->getAxis(1)->unit() = inputW->getAxis(1)->unit();
161 } catch (Exception::IndexError &) {
162 // OK, so this isn't a Workspace2D
163 }
164 // Assign it to the output workspace property
165 setProperty("OutputWorkspace", outputW);
166}
167
169 g_log.information("Processing event workspace");
170 const MatrixWorkspace_const_sptr matrixInputWS = this->getProperty("InputWorkspace");
171 // generate the output workspace pointer
172 API::MatrixWorkspace_sptr matrixOutputWS = getProperty("OutputWorkspace");
173 if (matrixOutputWS != matrixInputWS) {
174 matrixOutputWS = matrixInputWS->clone();
175 setProperty("OutputWorkspace", matrixOutputWS);
176 }
177 auto outputWS = std::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS);
178
179 const std::string op = getPropertyValue("Operation");
180 auto numHistograms = static_cast<int>(outputWS->getNumberHistograms());
182 for (int i = 0; i < numHistograms; ++i) {
184 // Do the offsetting
185 if ((i >= m_wi_min) && (i <= m_wi_max)) {
186 auto factor = getScaleFactor(outputWS, i);
187 if (op == "Multiply") {
188 outputWS->getSpectrum(i).scaleTof(factor);
189 if (factor < 0) {
190 outputWS->getSpectrum(i).reverse();
191 }
192 } else if (op == "Add") {
193 outputWS->getSpectrum(i).addTof(factor);
194 }
195 }
196 m_progress->report("Scaling X");
198 }
200 outputWS->clearMRU();
201}
202
204 // Check whether input = output to see whether a new workspace is required.
205 MatrixWorkspace_sptr output = getProperty("OutputWorkspace");
206 if (input != output) {
207 // Create new workspace for output from old
208 output = API::WorkspaceFactory::Instance().create(input);
209 }
210 return output;
211}
212
222 if (m_parname.empty())
223 return m_algFactor;
224
225 // Try and get factor from component. If we see a DetectorGroup this will
226 // use the first component
227 const auto &spectrumInfo = inputWS->spectrumInfo();
228 if (!spectrumInfo.hasDetectors(index)) {
229 return 0.0;
230 }
231
232 const auto &detectorInfo = inputWS->detectorInfo();
233 const auto detIndex = spectrumInfo.spectrumDefinition(index)[0].first;
234 const auto &det = detectorInfo.detector(detIndex);
235 const auto &pmap = inputWS->constInstrumentParameters();
236 auto par = pmap.getRecursive(det.getComponentID(), m_parname);
237 if (par) {
238 if (!m_combine)
239 return par->value<double>();
240 else
241 return m_binOp(m_algFactor, par->value<double>());
242 } else {
243 std::ostringstream os;
244 os << "Spectrum at index '" << index << "' has no parameter named '" << m_parname << "'\n";
245 throw std::runtime_error(os.str());
246 }
247}
248
249} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
Definition: MultiThreaded.h:94
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
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
Kernel::Logger & g_log
Definition: Algorithm.h:451
A property class for workspaces.
Takes a workspace and adjusts all the time bin values by the same multiplicative factor.
Definition: ScaleX.h:34
boost::function< double(double, double)> m_binOp
Function defining request operation.
Definition: ScaleX.h:75
double m_algFactor
Scaling factor.
Definition: ScaleX.h:69
int m_wi_min
Start workspace index.
Definition: ScaleX.h:77
int m_wi_max
Stop workspace index.
Definition: ScaleX.h:79
void exec() override
Executes the algorithm.
Definition: ScaleX.cpp:77
API::MatrixWorkspace_sptr createOutputWS(const API::MatrixWorkspace_sptr &input)
Create output workspace.
Definition: ScaleX.cpp:203
void execEvent()
Execute algorithm for EventWorkspaces.
Definition: ScaleX.cpp:168
void init() override
Initialisation method.
Definition: ScaleX.cpp:40
double getScaleFactor(const API::MatrixWorkspace_const_sptr &inputWS, const size_t index)
Get the scale factor for the given spectrum.
Definition: ScaleX.cpp:221
std::string m_parname
instrument parameter name
Definition: ScaleX.h:71
bool m_combine
Flag whether we are combining input parameters.
Definition: ScaleX.h:73
std::unique_ptr< API::Progress > m_progress
The progress reporting object.
Definition: ScaleX.h:66
Exception for index errors.
Definition: Exception.h:284
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.
Definition: Logger.cpp:77
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
Definition: MultiThreaded.h:22
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
Generate a tableworkspace to store the calibration results.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54