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
13using std::string;
14namespace Mantid::Algorithms {
15
16// Register the algorithm into the AlgorithmFactory
17DECLARE_ALGORITHM(RemovePromptPulse)
18
19using namespace Mantid::Kernel;
20using namespace Mantid::API;
21
22//----------------------------------------------------------------------------------------------
23
24const string RemovePromptPulse::name() const { return "RemovePromptPulse"; }
25
26int RemovePromptPulse::version() const { return 1; }
27
28const string RemovePromptPulse::category() const { return "CorrectionFunctions\\BackgroundCorrections"; }
29
30//----------------------------------------------------------------------------------------------
34 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input,
35 std::make_shared<WorkspaceUnitValidator>("TOF")),
36 "An input workspace.");
37 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
38 "An output workspace.");
39
40 auto validator = std::make_shared<BoundedValidator<double>>();
41 validator->setLower(0.0);
42 declareProperty("Width", Mantid::EMPTY_DBL(), validator,
43 "The width of the time of flight (in microseconds) to remove "
44 "from the data.");
45 declareProperty("Frequency", Mantid::EMPTY_DBL(), validator,
46 "The frequency of the source (in Hz) used to calculate the "
47 "minimum time of flight to filter.");
48}
49
50//----------------------------------------------------------------------------------------------
51namespace { // anonymous namespace begin
52double getMedian(const API::Run &run, const std::string &name) {
53
54 if (!run.hasProperty(name)) {
55 return Mantid::EMPTY_DBL();
56 }
57 auto *log = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(run.getLogData(name));
58 if (!log)
59 return Mantid::EMPTY_DBL();
60
61 Kernel::TimeSeriesPropertyStatistics stats = log->getStatistics();
62 return stats.median;
63}
64
65void getTofRange(const MatrixWorkspace_const_sptr &wksp, double &tmin, double &tmax) {
66 DataObjects::EventWorkspace_const_sptr eventWksp = std::dynamic_pointer_cast<const DataObjects::EventWorkspace>(wksp);
67 if (eventWksp == nullptr) {
68 wksp->getXMinMax(tmin, tmax);
69 } else {
70 eventWksp->getEventXMinMax(tmin, tmax);
71 }
72}
73} // namespace
74
78 // verify there is a width parameter specified
79 double width = this->getProperty("Width");
80 if (this->isEmpty(width)) {
81 throw std::runtime_error("Failed to specify \'Width\' parameter");
82 }
83
84 // need the input workspace in general
85 API::MatrixWorkspace_const_sptr inputWS = this->getProperty("InputWorkspace");
86
87 // get the frequency
88 double frequency = this->getProperty("Frequency");
89 if (this->isEmpty(frequency)) // it wasn't specified so try divination
90 {
91 frequency = this->getFrequency(inputWS->run());
92 if (this->isEmpty(frequency)) {
93 throw std::runtime_error("Failed to determine the frequency");
94 }
95 }
96 g_log.information() << "Using frequency of " << frequency << "Hz\n";
97 double period = 1000000. / frequency; // period in microseconds
98
99 // determine the overall tof window for the data
100 double tmin;
101 double tmax;
102 getTofRange(inputWS, tmin, tmax);
103 g_log.information() << "Data tmin=" << tmin << ", tmax=" << tmax << ", period=" << period << " microseconds\n";
104
105 // calculate the times for the prompt pulse
106 std::vector<double> pulseTimes = this->calculatePulseTimes(tmin, tmax, period);
107 if (pulseTimes.empty()) {
108 g_log.notice() << "Not applying filter since prompt pulse is not in data "
109 "range (period = "
110 << period << ")\n";
111 setProperty("OutputWorkspace", std::const_pointer_cast<MatrixWorkspace>(inputWS));
112 return;
113 }
114 g_log.information() << "Calculated prompt pulses at ";
115 for (double pulseTime : pulseTimes)
116 g_log.information() << pulseTime << " ";
117 g_log.information() << " microseconds\n";
118
119 MatrixWorkspace_sptr outputWS;
120 for (double &pulseTime : pulseTimes) {
121 double right = pulseTime + width;
122
123 g_log.notice() << "Filtering tmin=" << pulseTime << ", tmax=" << right << " microseconds\n";
124
125 // run maskbins to do the work on the first prompt pulse
126 auto algo = createChildAlgorithm("MaskBins");
127 if (outputWS) {
128 algo->setProperty<MatrixWorkspace_sptr>("InputWorkspace", std::const_pointer_cast<MatrixWorkspace>(outputWS));
129 } else { // should only be first time
130 algo->setProperty<MatrixWorkspace_sptr>("InputWorkspace", std::const_pointer_cast<MatrixWorkspace>(inputWS));
131 outputWS = this->getProperty("OutputWorkspace");
132 }
133 // always write to correct output workspace
134 algo->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS);
135 algo->setProperty<double>("XMin", pulseTime);
136 algo->setProperty<double>("XMax", right);
137 algo->executeAsChildAlg();
138
139 // copy over the output workspace
140 outputWS = algo->getProperty("OutputWorkspace");
141 }
142
143 setProperty("OutputWorkspace", outputWS);
144}
145
147 double candidate;
148
149 candidate = getMedian(run, "Frequency");
150 if (!(this->isEmpty(candidate)))
151 return candidate;
152
153 candidate = getMedian(run, "frequency");
154 if (!(this->isEmpty(candidate)))
155 return candidate;
156
157 candidate = getMedian(run, "FREQUENCY");
158 if (!(this->isEmpty(candidate)))
159 return candidate;
160
161 // give up
162 return Mantid::EMPTY_DBL();
163}
164
173std::vector<double> RemovePromptPulse::calculatePulseTimes(const double tmin, const double tmax, const double period) {
174 std::vector<double> times;
175 double time = 0.;
176
177 // find when the first prompt pulse would be
178 while (time < tmin)
179 time += period;
180
181 // calculate all times possible
182 while (time < tmax) {
183 times.emplace_back(time);
184 time += period;
185 }
186
187 return times;
188}
189} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double right
Definition: LineProfile.cpp:81
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
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
bool hasProperty(const std::string &name) const
Does the property exist on the object.
Definition: LogManager.cpp:265
Kernel::Property * getLogData(const std::string &name) const
Access a single log entry.
Definition: LogManager.h:129
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
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.
std::vector< double > calculatePulseTimes(const double tmin, const double tmax, const double period)
Calculate when all prompt pulses might be between the supplied times.
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.
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:95
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
A specialised Property class for holding a series of time-value pairs.
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
double getMedian(const vector< TYPE > &data)
There are enough special cases in determining the median where it useful to put it in a single functi...
Definition: Statistics.cpp:51
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
Struct holding some useful statistics for a TimeSeriesProperty.