Mantid
Loading...
Searching...
No Matches
RemovePromptPulse.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 +
12
13#include <tuple>
14
15using std::string;
16namespace Mantid::Algorithms {
17
18// Register the algorithm into the AlgorithmFactory
19DECLARE_ALGORITHM(RemovePromptPulse)
20
21using namespace Mantid::Kernel;
22using namespace Mantid::API;
23
24//----------------------------------------------------------------------------------------------
25
26const string RemovePromptPulse::name() const { return "RemovePromptPulse"; }
27
28int RemovePromptPulse::version() const { return 1; }
29
30const string RemovePromptPulse::category() const { return "CorrectionFunctions\\BackgroundCorrections"; }
31
32//----------------------------------------------------------------------------------------------
36 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input,
37 std::make_shared<WorkspaceUnitValidator>("TOF")),
38 "An input workspace.");
39 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
40 "An output workspace.");
41
42 auto validator = std::make_shared<BoundedValidator<double>>();
43 validator->setLower(0.0);
44 declareProperty("Width", Mantid::EMPTY_DBL(), validator,
45 "The width of the time of flight (in microseconds) to remove from the data.");
46 declareProperty("Frequency", Mantid::EMPTY_DBL(), validator,
47 "The frequency of the source (in Hz) used to calculate the minimum time of flight to filter.");
49 "TMin", Mantid::EMPTY_DBL(),
50 "Minimum time of flight. "
51 "Execution will be faster if this is specified, but the value will be determined from the workspace if not.");
53 "TMax", Mantid::EMPTY_DBL(),
54 "Minimum time of flight. "
55 "Execution will be faster if this is specified, but the value will be determined from the workspace if not.");
56}
57
58//----------------------------------------------------------------------------------------------
59namespace { // anonymous namespace begin
60double getMedian(const API::Run &run, const std::string &name) {
61
62 if (!run.hasProperty(name)) {
63 return Mantid::EMPTY_DBL();
64 }
65 try {
67 } catch (const std::invalid_argument &) {
68 return Mantid::EMPTY_DBL(); // maybe one of the other names will work
69 }
70}
71} // namespace
72
73void RemovePromptPulse::getTofRange(const MatrixWorkspace_const_sptr &wksp, double &tmin, double &tmax) {
74 const auto timerStart = std::chrono::high_resolution_clock::now();
75
76 // first get the values from the properties
77 tmin = getProperty("TMin");
78 tmax = getProperty("TMax");
79
80 // only get the values that are not specified
81 const bool findTmin = isEmpty(tmin);
82 const bool findTmax = isEmpty(tmax);
83
84 if (findTmin && findTmax) {
85 if (const auto eventWksp = std::dynamic_pointer_cast<const DataObjects::EventWorkspace>(wksp)) {
86 eventWksp->getEventXMinMax(tmin, tmax);
87 } else {
88 std::tie(tmin, tmax) = wksp->getXMinMax();
89 }
90 } else if (findTmin) {
91 if (const auto eventWksp = std::dynamic_pointer_cast<const DataObjects::EventWorkspace>(wksp)) {
92 tmin = eventWksp->getEventXMin();
93 } else {
94 tmin = wksp->getXMin();
95 }
96 } else if (findTmax) {
97 if (const auto eventWksp = std::dynamic_pointer_cast<const DataObjects::EventWorkspace>(wksp)) {
98 tmax = eventWksp->getEventXMax();
99 } else {
100 tmax = wksp->getXMax();
101 }
102 }
103 // the fall-through case is to use the properties for both which was set at the top of the function
104
105 addTimer("getTofRange", timerStart, std::chrono::high_resolution_clock::now());
106}
107
111 // verify there is a width parameter specified
112 double width = this->getProperty("Width");
113 if (this->isEmpty(width)) {
114 throw std::runtime_error("Failed to specify \'Width\' parameter");
115 }
116
117 // need the input workspace in general
118 API::MatrixWorkspace_const_sptr inputWS = this->getProperty("InputWorkspace");
119
120 // get the frequency
121 double frequency = this->getProperty("Frequency");
122 if (this->isEmpty(frequency)) { // it wasn't specified so try divination
123 frequency = this->getFrequency(inputWS->run());
124 if (this->isEmpty(frequency)) {
125 throw std::runtime_error("Failed to determine the frequency");
126 }
127 }
128 g_log.information() << "Using frequency of " << frequency << "Hz\n";
129 double period = 1000000. / frequency; // period in microseconds
130
131 // determine the overall tof window for the data
132 double tmin;
133 double tmax;
134 getTofRange(inputWS, tmin, tmax);
135 g_log.information() << "Data tmin=" << tmin << ", tmax=" << tmax << ", period=" << period << " microseconds\n";
136
137 // calculate the times for the prompt pulse
138 std::vector<double> pulseTimes = this->calculatePulseTimes(tmin, tmax, period, width);
139 if (pulseTimes.empty()) {
140 g_log.notice() << "Not applying filter since prompt pulse is not in data "
141 "range (period = "
142 << period << ")\n";
143 setProperty("OutputWorkspace", std::const_pointer_cast<MatrixWorkspace>(inputWS));
144 return;
145 }
146 g_log.information() << "Calculated prompt pulses at ";
147 for (double pulseTime : pulseTimes)
148 g_log.information() << pulseTime << " ";
149 g_log.information() << " microseconds\n";
150
151 // loop through each prompt pulse
152 MatrixWorkspace_sptr outputWS;
153 auto algo = createChildAlgorithm("MaskBins");
154 for (const double &pulseTime : pulseTimes) {
155 const double right = pulseTime + width;
156
157 g_log.notice() << "Filtering tmin=" << pulseTime << ", tmax=" << right << " microseconds\n";
158
159 // run maskbins to do the work on the first prompt pulse
160 if (outputWS) {
161 algo->setProperty<MatrixWorkspace_sptr>("InputWorkspace", std::const_pointer_cast<MatrixWorkspace>(outputWS));
162 } else { // should only be first time
163 algo->setProperty<MatrixWorkspace_sptr>("InputWorkspace", std::const_pointer_cast<MatrixWorkspace>(inputWS));
164 outputWS = this->getProperty("OutputWorkspace");
165 }
166 // always write to correct output workspace
167 algo->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS);
168 algo->setProperty<double>("XMin", pulseTime);
169 algo->setProperty<double>("XMax", right);
170 algo->executeAsChildAlg();
171
172 // copy over the output workspace
173 outputWS = algo->getProperty("OutputWorkspace");
174 }
175
176 setProperty("OutputWorkspace", outputWS);
177}
178
180 double candidate;
181
182 candidate = getMedian(run, "Frequency");
183 if (!(this->isEmpty(candidate)))
184 return candidate;
185
186 candidate = getMedian(run, "frequency");
187 if (!(this->isEmpty(candidate)))
188 return candidate;
189
190 candidate = getMedian(run, "FREQUENCY");
191 if (!(this->isEmpty(candidate)))
192 return candidate;
193
194 // give up
195 return Mantid::EMPTY_DBL();
196}
197
207std::vector<double> RemovePromptPulse::calculatePulseTimes(const double tmin, const double tmax, const double period,
208 const double width) {
209 std::vector<double> times;
210 double time = 0.;
211 // zero pulse should be taken into account
212 if (tmin > 0 && tmin < width)
213 times.emplace_back(time);
214 // find when the first prompt pulse would be
215 while (time < tmin)
216 time += period;
217
218 // calculate all times possible
219 while (time < tmax) {
220 times.emplace_back(time);
221 time += period;
222 }
223
224 return times;
225}
226} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
double right
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
Kernel::Logger & g_log
Definition Algorithm.h:426
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
void addTimer(const std::string &name, const Kernel::time_point_ns &begin, const Kernel::time_point_ns &end)
bool hasProperty(const std::string &name) const
Does the property exist on the object.
double getPropertyAsSingleValue(const std::string &name, Kernel::Math::StatisticType statistic=Kernel::Math::Mean) const
Returns a property as a single double value from its name.
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:36
A property class for workspaces.
const std::string name() const override
Algorithm's name for identification.
int version() const override
Algorithm's version for identification.
const std::string category() const override
Algorithm's category for identification.
double getFrequency(const API::Run &run)
Try to get the frequency from a given name.
std::vector< double > calculatePulseTimes(const double tmin, const double tmax, const double period, const double width)
Calculate when all prompt pulses might be between the supplied times.
void getTofRange(const API::MatrixWorkspace_const_sptr &wksp, double &tmin, double &tmax)
void exec() override
Run the algorithm.
void init() override
Sets documentation strings for this algorithm.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
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
double getMedian(Range const &data)
There are enough special cases in determining the median where it useful to put it in a single functi...
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55