Mantid
Loading...
Searching...
No Matches
UnwrapSNS.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 +
20
21#include <limits>
22
23namespace Mantid::Algorithms {
24
25DECLARE_ALGORITHM(UnwrapSNS)
26
27using namespace Kernel;
28using namespace API;
29using DataObjects::EventWorkspace;
30using std::size_t;
31
34 : m_conversionConstant(0.), m_inputWS(), m_inputEvWS(), m_LRef(0.), m_Tmin(0.), m_Tmax(0.), m_frameWidth(0.),
35 m_numberOfSpectra(0), m_XSize(0) {}
36
39 auto wsValidator = std::make_shared<CompositeValidator>();
40 wsValidator->add<WorkspaceUnitValidator>("TOF");
41 wsValidator->add<HistogramValidator>();
42 wsValidator->add<RawCountValidator>();
43 wsValidator->add<InstrumentValidator>();
45 std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input, wsValidator),
46 "Contains numbers counts against time of flight (TOF).");
47 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
48 "This workspace will be in the units of time of flight. (See "
49 "http://www.mantidproject.org/Units)");
50
51 auto validator = std::make_shared<BoundedValidator<double>>();
52 validator->setLower(0.01);
53 declareProperty("LRef", 0.0, validator,
54 "A distance at which it is possible to deduce if a particle "
55 "is from the current or a past frame based on its arrival "
56 "time. This time criterion can be set with the property "
57 "below e.g. correct when arrival time < Tmin.");
58 validator->setLower(0.01);
59 declareProperty("Tmin", Mantid::EMPTY_DBL(), validator,
60 "With LRef this defines the maximum speed expected for "
61 "particles. For each count or time bin the mean particle "
62 "speed is calculated and if this is greater than LRef/Tmin "
63 "its TOF is corrected.");
64 validator->setLower(0.01);
65 declareProperty("Tmax", Mantid::EMPTY_DBL(), validator,
66 "The maximum time of flight of the data used for the width "
67 "of the frame. If not set the maximum time of flight of the "
68 "data is used.");
69
70 // Calculate and set the constant factor for the conversion to wavelength
71 const double TOFisinMicroseconds = 1e6;
72 const double toAngstroms = 1e10;
73 m_conversionConstant = (PhysicalConstants::h * toAngstroms) / (PhysicalConstants::NeutronMass * TOFisinMicroseconds);
74}
75
84 // Get the input workspace
85 m_inputWS = getProperty("InputWorkspace");
86
87 // Get the "reference" flightpath (currently passed in as a property)
88 m_LRef = getProperty("LRef");
89
90 m_XSize = static_cast<int>(m_inputWS->x(0).size());
91 m_numberOfSpectra = static_cast<int>(m_inputWS->getNumberHistograms());
92 g_log.debug() << "Number of spectra in input workspace: " << m_numberOfSpectra << "\n";
93
94 // go off and do the event version if appropriate
95 m_inputEvWS = std::dynamic_pointer_cast<const EventWorkspace>(m_inputWS);
96 if ((m_inputEvWS != nullptr)) // && ! this->getProperty("ForceHist")) // TODO
97 // remove ForceHist option
98 {
99 this->execEvent();
100 return;
101 }
102
103 this->getTofRangeData(false);
104
105 // set up the progress bar
106 m_progress = std::make_unique<Progress>(this, 0.0, 1.0, m_numberOfSpectra);
107
108 MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
109 if (outputWS != m_inputWS) {
111 setProperty("OutputWorkspace", outputWS);
112 }
113
114 // without the primary flight path the algorithm cannot work
115 const auto &spectrumInfo = m_inputWS->spectrumInfo();
116 const double L1 = spectrumInfo.l1();
117
119 for (int workspaceIndex = 0; workspaceIndex < m_numberOfSpectra; workspaceIndex++) {
121 if (!spectrumInfo.hasDetectors(workspaceIndex)) {
122 // If the detector flightpath is missing, zero the data
123 g_log.debug() << "Detector information for workspace index " << workspaceIndex << " is not available.\n";
124 outputWS->setSharedX(workspaceIndex, m_inputWS->sharedX(workspaceIndex));
125 outputWS->mutableY(workspaceIndex) = 0.0;
126 outputWS->mutableE(workspaceIndex) = 0.0;
127 } else {
128 const double Ld = L1 + spectrumInfo.l2(workspaceIndex);
129 // fix the x-axis
130 std::vector<double> timeBins;
131 size_t pivot = this->unwrapX(m_inputWS->x(workspaceIndex), timeBins, Ld);
132 outputWS->setBinEdges(workspaceIndex, std::move(timeBins));
133
134 pivot++; // one-off difference between x and y
135
136 // fix the counts using the pivot point
137 auto &yIn = m_inputWS->y(workspaceIndex);
138 auto &yOut = outputWS->mutableY(workspaceIndex);
139
140 auto lengthFirstPartY = std::distance(yIn.begin() + pivot, yIn.end());
141 std::copy(yIn.begin() + pivot, yIn.end(), yOut.begin());
142 std::copy(yIn.begin(), yIn.begin() + pivot, yOut.begin() + lengthFirstPartY);
143
144 // fix the uncertainties using the pivot point
145 auto &eIn = m_inputWS->e(workspaceIndex);
146 auto &eOut = outputWS->mutableE(workspaceIndex);
147
148 auto lengthFirstPartE = std::distance(eIn.begin() + pivot, eIn.end());
149 std::copy(eIn.begin() + pivot, eIn.end(), eOut.begin());
150 std::copy(eIn.begin(), eIn.begin() + pivot, eOut.begin() + lengthFirstPartE);
151 }
152 m_progress->report();
154 }
156
157 m_inputWS.reset();
158 this->runMaskDetectors();
159}
160
162 // set up the output workspace
163 MatrixWorkspace_sptr matrixOutW = this->getProperty("OutputWorkspace");
164 if (matrixOutW != m_inputWS) {
165 matrixOutW = m_inputWS->clone();
166 setProperty("OutputWorkspace", matrixOutW);
167 }
168 auto outW = std::dynamic_pointer_cast<EventWorkspace>(matrixOutW);
169
170 // set up the progress bar
171 m_progress = std::make_unique<Progress>(this, 0.0, 1.0, m_numberOfSpectra * 2);
172
173 // algorithm assumes the data is sorted so it can jump out early
174 outW->sortAll(Mantid::DataObjects::TOF_SORT, m_progress.get());
175
176 this->getTofRangeData(true);
177
178 // without the primary flight path the algorithm cannot work
179 const auto &spectrumInfo = m_inputWS->spectrumInfo();
180 const double L1 = spectrumInfo.l1();
181
182 // do the actual work
183 for (int workspaceIndex = 0; workspaceIndex < m_numberOfSpectra; workspaceIndex++) {
184 std::size_t numEvents = outW->getSpectrum(workspaceIndex).getNumberEvents();
185 double Ld = -1.0;
186 if (spectrumInfo.hasDetectors(workspaceIndex))
187 Ld = L1 + spectrumInfo.l2(workspaceIndex);
188
189 std::vector<double> time_bins;
190 if (outW->x(0).size() > 2) {
191 this->unwrapX(m_inputWS->x(workspaceIndex), time_bins, Ld);
192 outW->setBinEdges(workspaceIndex, std::move(time_bins));
193 } else {
194 outW->setSharedX(workspaceIndex, m_inputWS->sharedX(workspaceIndex));
195 }
196 if (numEvents > 0) {
197 std::vector<double> times(numEvents);
198 outW->getSpectrum(workspaceIndex).getTofs(times);
199 double filterVal = m_Tmin * Ld / m_LRef;
200 for (size_t j = 0; j < numEvents; j++) {
201 if (times[j] < filterVal)
202 times[j] += m_frameWidth;
203 else
204 break; // stop filtering
205 }
206 outW->getSpectrum(workspaceIndex).setTofs(times);
207 }
208 m_progress->report();
209 }
210
211 outW->clearMRU();
212 this->runMaskDetectors();
213}
214
215int UnwrapSNS::unwrapX(const Mantid::HistogramData::HistogramX &datain, std::vector<double> &dataout,
216 const double &Ld) {
217 std::vector<double> tempX_L; // lower half - to be frame wrapped
218 tempX_L.reserve(m_XSize);
219 tempX_L.clear();
220 std::vector<double> tempX_U; // upper half - to not be frame wrapped
221 tempX_U.reserve(m_XSize);
222 tempX_U.clear();
223
224 double filterVal = m_Tmin * Ld / m_LRef;
225 dataout.clear();
226 int specialBin = 0;
227 for (int bin = 0; bin < m_XSize; ++bin) {
228 // This is the time-of-flight value under consideration in the current
229 // iteration of the loop
230 const double tof = datain[bin];
231 if (tof < filterVal) {
232 tempX_L.emplace_back(tof + m_frameWidth);
233 // Record the bins that fall in this range for copying over the data &
234 // errors
235 if (specialBin < bin)
236 specialBin = bin;
237 } else {
238 tempX_U.emplace_back(tof);
239 }
240 } // loop over X values
241
242 // now put it back into the vector supplied
243 dataout.clear();
244 dataout.insert(dataout.begin(), tempX_U.begin(), tempX_U.end());
245 dataout.insert(dataout.end(), tempX_L.begin(), tempX_L.end());
246 assert(datain.size() == dataout.size());
247
248 return specialBin;
249}
250
251void UnwrapSNS::getTofRangeData(const bool isEvent) {
252 // get the Tmin/Tmax properties
253 m_Tmin = this->getProperty("Tmin");
254 m_Tmax = this->getProperty("Tmax");
255
256 // if either the values are not specified by properties, find them from the
257 // data
258 double empty = Mantid::EMPTY_DBL();
259 if ((m_Tmin == empty) || (m_Tmax == empty)) {
260 // get data min/max values
261 double dataTmin;
262 double dataTmax;
263 if (isEvent) {
264 m_inputEvWS->sortAll(DataObjects::TOF_SORT, nullptr);
265 m_inputEvWS->getEventXMinMax(dataTmin, dataTmax);
266 } else {
267 m_inputWS->getXMinMax(dataTmin, dataTmax);
268 }
269
270 // fix the unspecified values
271 if (m_Tmin == empty) {
272 m_Tmin = dataTmin;
273 }
274 if (m_Tmax == empty) {
275 m_Tmax = dataTmax;
276 }
277 }
278
279 // check the frame width
281
282 g_log.information() << "Frame range in microseconds is: " << m_Tmin << " - " << m_Tmax << "\n";
283 if (m_Tmin < 0.)
284 throw std::runtime_error("Cannot have Tmin less than zero");
285 if (m_Tmin > m_Tmax)
286 throw std::runtime_error("Have case of Tmin > Tmax");
287
288 g_log.information() << "Wavelength cuttoff is : " << (m_conversionConstant * m_Tmin / m_LRef)
289 << "Angstrom, Frame width is: " << m_frameWidth << "microseconds\n";
290}
291
293 auto alg = createChildAlgorithm("MaskDetectors");
294 alg->setProperty<MatrixWorkspace_sptr>("Workspace", this->getProperty("OutputWorkspace"));
295 alg->setProperty<MatrixWorkspace_sptr>("MaskedWorkspace", this->getProperty("InputWorkspace"));
296 if (!alg->execute())
297 throw std::runtime_error("MaskDetectors Child Algorithm has not executed successfully");
298}
299
300} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
#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.
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
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
A validator which checks that a workspace contains histogram data (the default) or point data as requ...
A validator which checks that a workspace has a valid instrument.
A validator which checks that a workspace contains raw counts in its bins.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
double m_conversionConstant
The constant used in the conversion from TOF.
Definition: UnwrapSNS.h:59
double m_Tmin
The start of the time-of-flight frame.
Definition: UnwrapSNS.h:64
double m_Tmax
The end of the time-of-flight frame.
Definition: UnwrapSNS.h:65
double m_frameWidth
The width of the frame cached to speed up things.
Definition: UnwrapSNS.h:66
void init() override
Initialisation method.
Definition: UnwrapSNS.cpp:38
UnwrapSNS()
Default constructor.
Definition: UnwrapSNS.cpp:33
double m_LRef
The 'reference' flightpath.
Definition: UnwrapSNS.h:63
DataObjects::EventWorkspace_const_sptr m_inputEvWS
Pointer to the input event workspace.
Definition: UnwrapSNS.h:62
int unwrapX(const Mantid::HistogramData::HistogramX &, std::vector< double > &dataout, const double &Ld)
Definition: UnwrapSNS.cpp:215
API::MatrixWorkspace_const_sptr m_inputWS
to wavelength
Definition: UnwrapSNS.h:61
int m_XSize
The size of the X vectors in the input workspace.
Definition: UnwrapSNS.h:68
std::unique_ptr< API::Progress > m_progress
Progress reporting.
Definition: UnwrapSNS.h:70
void exec() override
Executes the algorithm.
Definition: UnwrapSNS.cpp:83
int m_numberOfSpectra
The number of spectra in the workspace.
Definition: UnwrapSNS.h:67
void getTofRangeData(const bool)
Definition: UnwrapSNS.cpp:251
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 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< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::size_t numEvents(::NeXus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const NexusHDF5Descriptor &descriptor)
Get the number of events in the currently opened group.
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
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54