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 const auto &spectrumInfo = inputW->spectrumInfo();
122
123 // do the shift in X
124 PARALLEL_FOR_IF(Kernel::threadSafe(*inputW, *outputW))
125 for (int i = 0; i < histnumber; ++i) {
127
128 // Copy y and e data
129 outputW->setHistogram(i, inputW->histogram(i));
130
131 auto &outX = outputW->mutableX(i);
132 auto &outY = outputW->mutableY(i);
133 auto &outE = outputW->mutableE(i);
134
135 const auto &inX = inputW->x(i);
136 // Change bin value by offset
137 if ((i >= m_wi_min) && (i <= m_wi_max)) {
138 double factor = getScaleFactor(inputW, spectrumInfo, i);
139 // Do the offsetting
140 using std::placeholders::_1;
141 std::transform(inX.begin(), inX.end(), outX.begin(), std::bind(m_binOp, _1, factor));
142 // reverse the vector if multiplicative factor was negative
143 if (multiply && factor < 0.0) {
144 std::reverse(outX.begin(), outX.end());
145 std::reverse(outY.begin(), outY.end());
146 std::reverse(outE.begin(), outE.end());
147 }
148 }
149
150 m_progress->report("Scaling X");
151
153 }
155
156 // Copy units
157 if (outputW->getAxis(0)->unit().get())
158 outputW->getAxis(0)->unit() = inputW->getAxis(0)->unit();
159 try {
160 if (inputW->getAxis(1)->unit().get())
161 outputW->getAxis(1)->unit() = inputW->getAxis(1)->unit();
162 } catch (Exception::IndexError &) {
163 // OK, so this isn't a Workspace2D
164 }
165 // Assign it to the output workspace property
166 setProperty("OutputWorkspace", outputW);
167}
168
170 g_log.information("Processing event workspace");
171 const MatrixWorkspace_const_sptr matrixInputWS = this->getProperty("InputWorkspace");
172 // generate the output workspace pointer
173 API::MatrixWorkspace_sptr matrixOutputWS = getProperty("OutputWorkspace");
174 if (matrixOutputWS != matrixInputWS) {
175 matrixOutputWS = matrixInputWS->clone();
176 setProperty("OutputWorkspace", matrixOutputWS);
177 }
178 auto outputWS = std::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS);
179 const auto &spectrumInfo = matrixInputWS->spectrumInfo();
180
181 const std::string op = getPropertyValue("Operation");
182 auto numHistograms = static_cast<int>(outputWS->getNumberHistograms());
184 for (int i = 0; i < numHistograms; ++i) {
186 // Do the offsetting
187 if ((i >= m_wi_min) && (i <= m_wi_max)) {
188 auto factor = getScaleFactor(outputWS, spectrumInfo, i);
189 if (op == "Multiply") {
190 outputWS->getSpectrum(i).scaleTof(factor);
191 if (factor < 0) {
192 outputWS->getSpectrum(i).reverse();
193 }
194 } else if (op == "Add") {
195 outputWS->getSpectrum(i).addTof(factor);
196 }
197 }
198 m_progress->report("Scaling X");
200 }
202 outputWS->clearMRU();
203}
204
206 // Check whether input = output to see whether a new workspace is required.
207 MatrixWorkspace_sptr output = getProperty("OutputWorkspace");
208 if (input != output) {
209 // Create new workspace for output from old
210 output = API::WorkspaceFactory::Instance().create(input);
211 }
212 return output;
213}
214
225 const Mantid::API::SpectrumInfo &spectrumInfo, const size_t index) {
226 if (m_parname.empty())
227 return m_algFactor;
228
229 // Try and get factor from component. If we see a DetectorGroup this will
230 // use the first component
231 if (!spectrumInfo.hasDetectors(index)) {
232 return 0.0;
233 }
234
235 const auto &detectorInfo = inputWS->detectorInfo();
236 const auto detIndex = spectrumInfo.spectrumDefinition(index)[0].first;
237 const auto &det = detectorInfo.detector(detIndex);
238 const auto &pmap = inputWS->constInstrumentParameters();
239 auto par = pmap.getRecursive(det.getComponentID(), m_parname);
240 if (par) {
241 if (!m_combine)
242 return par->value<double>();
243 else
244 return m_binOp(m_algFactor, par->value<double>());
245 } else {
246 std::ostringstream os;
247 os << "Spectrum at index '" << index << "' has no parameter named '" << m_parname << "'\n";
248 throw std::runtime_error(os.str());
249 }
250}
251
252} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
std::map< DeltaEMode::Type, std::string > index
#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...
#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:76
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
bool hasDetectors(const size_t index) const
Returns true if the spectrum is associated with detectors in the instrument.
const SpectrumDefinition & spectrumDefinition(const size_t index) const
Returns a const reference to the SpectrumDefinition of the spectrum.
A property class for workspaces.
Takes a workspace and adjusts all the time bin values by the same multiplicative factor.
Definition ScaleX.h:35
boost::function< double(double, double)> m_binOp
Function defining request operation.
Definition ScaleX.h:77
double m_algFactor
Scaling factor.
Definition ScaleX.h:71
int m_wi_min
Start workspace index.
Definition ScaleX.h:79
int m_wi_max
Stop workspace index.
Definition ScaleX.h:81
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:205
void execEvent()
Execute algorithm for EventWorkspaces.
Definition ScaleX.cpp:169
void init() override
Initialisation method.
Definition ScaleX.cpp:40
std::string m_parname
instrument parameter name
Definition ScaleX.h:73
bool m_combine
Flag whether we are combining input parameters.
Definition ScaleX.h:75
double getScaleFactor(const API::MatrixWorkspace_const_sptr &inputWS, const Mantid::API::SpectrumInfo &spectrumInfo, const size_t index)
Get the scale factor for the given spectrum.
Definition ScaleX.cpp:224
std::unique_ptr< API::Progress > m_progress
The progress reporting object.
Definition ScaleX.h:68
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:108
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
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.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition EmptyValues.h:24
Generate a tableworkspace to store the calibration results.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54