Mantid
Loading...
Searching...
No Matches
RemoveLowResTOF.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 +
18#include "MantidKernel/Unit.h"
20#include <cmath>
21#include <limits>
22#include <map>
23
24namespace Mantid::Algorithms {
25
26using namespace Kernel;
27using namespace API;
28using namespace Geometry;
29using DataObjects::EventWorkspace;
30using std::size_t;
31using std::string;
32
33DECLARE_ALGORITHM(RemoveLowResTOF)
34
35
37 : m_inputWS(), m_inputEvWS(), m_DIFCref(0.), m_K(0.), m_Tmin(0.), m_wavelengthMin(0.), m_numberOfSpectra(0),
38 m_outputLowResTOF(false) {}
39
41const string RemoveLowResTOF::name() const { return "RemoveLowResTOF"; }
42
44int RemoveLowResTOF::version() const { return 1; }
45
47const string RemoveLowResTOF::category() const { return "Diffraction\\Corrections"; }
48
50 auto wsValidator = std::make_shared<CompositeValidator>();
51 wsValidator->add<WorkspaceUnitValidator>("TOF");
52 wsValidator->add<HistogramValidator>();
53 wsValidator->add<RawCountValidator>();
54 wsValidator->add<InstrumentValidator>();
56 std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input, wsValidator),
57 "A workspace with x values in units of TOF and y values in counts");
58 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
59 "The name of the workspace to be created as the output of the algorithm");
60 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("LowResTOFWorkspace", "", Direction::Output,
62 "The name of the optional output workspace that contains low resolution "
63 "TOF which are removed "
64 "from input workspace.");
65
66 auto validator = std::make_shared<BoundedValidator<double>>();
67 validator->setLower(0.01);
68 declareProperty("ReferenceDIFC", Mantid::EMPTY_DBL(), validator, "The DIFC value for the reference");
69
70 declareProperty("K", 3.22, validator,
71 "Some arbitrary number whose default "
72 "is 3.22 for reasons that I don't "
73 "understand");
74
75 declareProperty("Tmin", Mantid::EMPTY_DBL(), validator,
76 "The minimum time-of-flight of the frame (in microseconds). "
77 "If not set the data range will be used.");
78 declareProperty("MinWavelength", Mantid::EMPTY_DBL(), validator,
79 "The minimum wavelength for measurement. This overides all "
80 "other parameters if specified.");
81
82 // hide things when people cjoose the minimum wavelength
83 setPropertySettings("ReferenceDIFC", std::make_unique<EnabledWhenProperty>("MinWavelength", IS_DEFAULT));
84 setPropertySettings("K", std::make_unique<EnabledWhenProperty>("MinWavelength", IS_DEFAULT));
85 setPropertySettings("Tmin", std::make_unique<EnabledWhenProperty>("MinWavelength", IS_DEFAULT));
86}
87
89 // Get the input workspace
90 m_inputWS = this->getProperty("InputWorkspace");
91 const auto &spectrumInfo = m_inputWS->spectrumInfo();
92
93 m_DIFCref = this->getProperty("ReferenceDIFC");
94 m_K = this->getProperty("K");
95 m_wavelengthMin = this->getProperty("MinWavelength");
96
97 m_numberOfSpectra = m_inputWS->getNumberHistograms();
98
99 std::string lowreswsname = getPropertyValue("LowResTOFWorkspace");
100 if (!lowreswsname.empty())
101 m_outputLowResTOF = true;
102 else
103 m_outputLowResTOF = false;
104
105 // Only create the output workspace if it's different to the input one
106 MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
107 if (outputWS != m_inputWS) {
108 outputWS = m_inputWS->clone();
109 setProperty("OutputWorkspace", outputWS);
110 }
111
112 // go off and do the event version if appropriate
113 m_inputEvWS = std::dynamic_pointer_cast<const EventWorkspace>(m_inputWS);
114 if (m_inputEvWS != nullptr) {
115 this->execEvent(spectrumInfo);
116 return;
117 }
118
119 // set up the progress bar
120 m_progress = std::make_unique<Progress>(this, 0.0, 1.0, m_numberOfSpectra);
121
122 this->getTminData(false);
123
124 for (size_t workspaceIndex = 0; workspaceIndex < m_numberOfSpectra; workspaceIndex++) {
125 // calculate where to zero out to
126 const double tofMin = this->calcTofMin(workspaceIndex, spectrumInfo);
127 const auto &X = m_inputWS->x(0);
128 auto last = std::lower_bound(X.cbegin(), X.cend(), tofMin);
129 if (last == X.end())
130 --last;
131 const size_t endBin = last - X.begin();
132
133 // flatten out the data
134 for (size_t i = 0; i < endBin; i++) {
135 outputWS->maskBin(workspaceIndex, i);
136 }
137 m_progress->report();
138 }
139}
140
143void RemoveLowResTOF::execEvent(const SpectrumInfo &spectrumInfo) {
144 // set up the output workspace
145 MatrixWorkspace_sptr matrixOutW = getProperty("OutputWorkspace");
146 auto outW = std::dynamic_pointer_cast<EventWorkspace>(matrixOutW);
147
148 MatrixWorkspace_sptr matrixLowResW = getProperty("LowResTOFWorkspace");
149 if (m_outputLowResTOF) {
150 matrixLowResW = m_inputWS->clone();
151 setProperty("LowResTOFWorkspace", matrixLowResW);
152 }
153 auto lowW = std::dynamic_pointer_cast<EventWorkspace>(matrixLowResW);
154
155 g_log.debug() << "TOF range was " << m_inputEvWS->getTofMin() << " to " << m_inputEvWS->getTofMax()
156 << " microseconds\n";
157
158 std::size_t numEventsOrig = outW->getNumberEvents();
159 // set up the progress bar
160 m_progress = std::make_unique<Progress>(this, 0.0, 1.0, m_numberOfSpectra * 2);
161
162 // algorithm assumes the data is sorted so it can jump out early
163 outW->sortAll(Mantid::DataObjects::TOF_SORT, m_progress.get());
164
165 this->getTminData(true);
166 size_t numClearedEventLists = 0;
167 size_t numClearedEvents = 0;
168
169 // do the actual work
170 for (size_t workspaceIndex = 0; workspaceIndex < m_numberOfSpectra; workspaceIndex++) {
171 if (outW->getSpectrum(workspaceIndex).getNumberEvents() > 0) {
172 double tmin = this->calcTofMin(workspaceIndex, spectrumInfo);
173 if (tmin != tmin) {
174 // Problematic
175 g_log.warning() << "tmin for workspaceIndex " << workspaceIndex << " is nan. Clearing out data. "
176 << "There are " << outW->getSpectrum(workspaceIndex).getNumberEvents() << " of it. \n";
177 numClearedEventLists += 1;
178 numClearedEvents += outW->getSpectrum(workspaceIndex).getNumberEvents();
179 outW->getSpectrum(workspaceIndex).clear(false);
180
182 lowW->getSpectrum(workspaceIndex).clear(false);
183 } else if (tmin > 0.) {
184 // there might be events between 0 and tmin (i.e., low resolution)
185 outW->getSpectrum(workspaceIndex).maskTof(0., tmin);
186 if (outW->getSpectrum(workspaceIndex).getNumberEvents() == 0)
187 numClearedEventLists += 1;
188
189 if (m_outputLowResTOF) {
190 double tmax = lowW->getSpectrum(workspaceIndex).getTofMax();
191 if (tmax != tmax) {
192 g_log.warning() << "tmax for workspaceIndex " << workspaceIndex << " is nan. Clearing out data. \n";
193 lowW->getSpectrum(workspaceIndex).clear(false);
194 } else {
195 // There is possibility that tmin calculated is larger than TOF-MAX
196 // of the spectrum
197 if (tmax + DBL_MIN > tmin)
198 lowW->getSpectrum(workspaceIndex).maskTof(tmin, tmax + DBL_MIN);
199 }
200 }
201 } else {
202 // do nothing if tmin <= 0. for outW
203 if (m_outputLowResTOF) {
204 // tmin = 0. no event will be in low resolution
205 lowW->getSpectrum(workspaceIndex).clear(false);
206 }
207 } //
208 }
209 }
210 g_log.information() << "Went from " << numEventsOrig << " events to " << outW->getNumberEvents() << " events ("
211 << (static_cast<double>(numEventsOrig - outW->getNumberEvents()) * 100. /
212 static_cast<double>(numEventsOrig))
213 << "% removed)\n";
214 if (numClearedEventLists > 0)
215 g_log.warning() << numClearedEventLists << " spectra of " << m_numberOfSpectra
216 << " had all data removed. The number of removed events is " << numClearedEvents << ".\n";
217 g_log.debug() << "TOF range is now " << outW->getTofMin() << " to " << outW->getTofMax() << " microseconds\n";
218 outW->clearMRU();
219}
220
221double RemoveLowResTOF::calcTofMin(const std::size_t workspaceIndex, const SpectrumInfo &spectrumInfo) {
222
223 const double l1 = spectrumInfo.l1();
224
225 double tmin = 0.;
227 double dspmap = 1. / spectrumInfo.difcUncalibrated(workspaceIndex);
228
229 // this is related to the reference tof
230 double sqrtdmin = sqrt(m_Tmin / m_DIFCref) + m_K * log10(dspmap * m_DIFCref);
231 if (sqrtdmin <= 0.)
232 return 0.;
233 tmin = sqrtdmin * sqrtdmin / dspmap;
234 if (tmin != tmin) {
235 g_log.warning() << "tmin is nan because dspmap = " << dspmap << ".\n";
236 }
237 } else {
238 const double l2 = spectrumInfo.l2(workspaceIndex);
239
240 Kernel::Unit_sptr wavelength = UnitFactory::Instance().create("Wavelength");
241 // unfortunately there isn't a good way to convert a single value
242 std::vector<double> X(1), temp(1);
243 X[0] = m_wavelengthMin;
244 wavelength->toTOF(X, temp, l1, 0, {{UnitParams::l2, l2}});
245 tmin = X[0];
246 }
247
248 g_log.debug() << "tmin[" << workspaceIndex << "] " << tmin << "\n";
249
250 return tmin;
251}
252
253void RemoveLowResTOF::getTminData(const bool isEvent) {
254 // get it from the properties
255 double empty = Mantid::EMPTY_DBL();
256 double temp = this->getProperty("Tmin");
257 if (temp != empty) {
258 m_Tmin = temp;
259 return;
260 }
261
262 if (isEvent) {
263 m_Tmin = m_inputEvWS->getEventXMin();
264 } else {
265 m_Tmin = m_inputWS->getXMin();
266 }
267 g_log.information() << "Tmin = " << m_Tmin << " microseconds\n";
268 if (m_Tmin < 0.)
269 throw std::runtime_error("Cannot have minimum time less than zero");
270}
271
272} // namespace Mantid::Algorithms
#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
Kernel::Logger & g_log
Definition: Algorithm.h:451
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
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.
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
Definition: SpectrumInfo.h:53
double difcUncalibrated(const size_t index) const
Calculate average uncalibrated DIFC value of detectors associated with this spectrum.
double l2(const size_t index) const
Returns L2 (distance from sample to spectrum).
double l1() const
Returns L1 (distance from source to sample).
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
API::MatrixWorkspace_const_sptr m_inputWS
Pointer to the input workspace.
std::unique_ptr< API::Progress > m_progress
Progress reporting.
const std::string category() const override
Algorithm's category for identification overriding a virtual method.
double calcTofMin(const std::size_t, const API::SpectrumInfo &spectrumInfo)
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
double m_wavelengthMin
The minimum wavelength accessible in the frame.
double m_DIFCref
The reference value for DIFC to filter with.
std::size_t m_numberOfSpectra
The number of spectra in the workspace.
double m_Tmin
The start of the time-of-flight frame.
DataObjects::EventWorkspace_const_sptr m_inputEvWS
Pointer to the input event workspace.
void execEvent(const API::SpectrumInfo &spectrumInfo)
Remove low resolution TOF from an EventWorkspace.
void exec() override
Virtual method - must be overridden by concrete algorithm.
int version() const override
Algorithm's version for identification overriding a virtual method.
void init() override
Virtual method - must be overridden by concrete algorithm.
double m_K
Mystery variable that I'm not sure what it is for.
bool m_outputLowResTOF
Flag to generate low resolution TOF workspace.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
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::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
Definition: Unit.h:229
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