Mantid
Loading...
Searching...
No Matches
CompressEvents.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 +
8#include "MantidAPI/Run.h"
18
19#include "tbb/parallel_for.h"
20
21#include <numeric>
22#include <set>
23
24namespace Mantid::DataHandling {
25// Register the algorithm into the algorithm factory
26DECLARE_ALGORITHM(CompressEvents)
27
28using namespace Kernel;
29using namespace API;
30using namespace DataObjects;
31
32namespace {
33const std::vector<std::string> binningModeNames{"Default", "Linear", "Logarithmic"};
34enum class BinningMode { DEFAULT, LINEAR, LOGARITHMIC, enum_count };
36} // namespace
37
39 declareProperty(std::make_unique<WorkspaceProperty<EventWorkspace>>("InputWorkspace", "", Direction::Input),
40 "The name of the EventWorkspace on which to perform the algorithm");
41
42 declareProperty(std::make_unique<WorkspaceProperty<EventWorkspace>>("OutputWorkspace", "", Direction::Output),
43 "The name of the output EventWorkspace.");
44
45 // Tolerance must be >= 0.0
46 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
47 mustBePositive->setLower(0.0);
48 declareProperty(std::make_unique<PropertyWithValue<double>>("Tolerance", 1e-5, Direction::Input),
49 "The tolerance on each event's X value (normally TOF, but may be a "
50 "different unit if you have used ConvertUnits).\n"
51 "Any events within Tolerance will be summed into a single event. When compressing where positive is "
52 "linear tolerance, negative is logorithmic tolerance, and zero indicates that time-of-flight must be "
53 "identical to compress.");
54
56 std::make_unique<PropertyWithValue<double>>("WallClockTolerance", EMPTY_DBL(), mustBePositive, Direction::Input),
57 "The tolerance (in seconds) on the wall-clock time for comparison. Unset "
58 "means compressing all wall-clock times together disabling pulsetime "
59 "resolution.");
60
61 auto dateValidator = std::make_shared<DateTimeValidator>();
62 dateValidator->allowEmpty(true);
63 declareProperty("StartTime", "", dateValidator,
64 "An ISO formatted date/time string specifying the timestamp for "
65 "starting filtering. Ignored if WallClockTolerance is not specified. "
66 "Default is start of run",
68
69 declareProperty("BinningMode", binningModeNames[size_t(BinningMode::DEFAULT)],
70 std::make_shared<Mantid::Kernel::StringListValidator>(binningModeNames),
71 "Binning behavior can be specified in the usual way through sign of tolerance and other properties "
72 "('Default'); or can be set to one of the allowed binning modes. This will override all other "
73 "specification or default behavior.");
74 declareProperty("SortFirst", true,
75 "If false a different method, that will not sort events first, will be used to compress events which "
76 "is faster when you have a large number of events per compress tolerance");
77}
78
80 // Get the input workspace
81 EventWorkspace_sptr inputWS = getProperty("InputWorkspace");
82 EventWorkspace_sptr outputWS = getProperty("OutputWorkspace");
83 double toleranceTof = getProperty("Tolerance");
84 const double toleranceWallClock = getProperty("WallClockTolerance");
85 const bool compressFat = !isEmpty(toleranceWallClock);
86 const bool sortFirst = getProperty("SortFirst");
87
88 BINMODE mode = getPropertyValue("BinningMode");
89 if (mode == BinningMode::LINEAR)
90 toleranceTof = std::fabs(toleranceTof);
91 else if (mode == BinningMode::LOGARITHMIC)
92 toleranceTof = -1. * std::fabs(toleranceTof);
93
94 Types::Core::DateAndTime startTime;
95
96 if (compressFat) {
97 std::string startTimeProp = getProperty("StartTime");
98 if (startTimeProp.empty()) {
99 startTime = inputWS->run().startTime();
100 } else {
101 // the property returns ISO8601
102 startTime = DateAndTimeHelpers::createFromSanitizedISO8601(startTimeProp);
103 }
104 }
105
106 // Some starting things
107 bool inplace = (inputWS == outputWS);
108 const size_t noSpectra = inputWS->getNumberHistograms();
109 Progress prog(this, 0.0, 1.0, noSpectra * 2);
110
111 // Sort the input workspace in-place by TOF. This can be faster if there are
112 // few event lists. Compressing with wall clock does the sorting internally
113 if (!compressFat && sortFirst) {
114 const auto timerStart = std::chrono::high_resolution_clock::now();
115 inputWS->sortAll(TOF_SORT, &prog);
116 addTimer("sortByTOF", timerStart, std::chrono::high_resolution_clock::now());
117 }
118
119 // created required variables if using unsorted methdo
120 auto histogram_bin_edges = std::make_shared<std::vector<double>>();
121 size_t num_edges{0};
122 if (!compressFat && !sortFirst && !(inputWS->getSortType() == TOF_SORT)) {
123 // only initialize if needed
124 double tof_min_fixed;
125 double tof_max_fixed;
126 inputWS->getEventXMinMax(tof_min_fixed, tof_max_fixed);
128 {tof_min_fixed, toleranceTof, (tof_max_fixed + std::abs(toleranceTof))}, *histogram_bin_edges, true, true);
129 num_edges = histogram_bin_edges->size();
130 }
131
132 // Are we making a copy of the input workspace?
133 if (!inplace) {
134 outputWS = create<EventWorkspace>(*inputWS, HistogramData::BinEdges(2));
135 // We DONT copy the data though
136 // Loop over the histograms (detector spectra)
137 tbb::parallel_for(tbb::blocked_range<size_t>(0, noSpectra),
138 [compressFat, sortFirst, toleranceTof, startTime, toleranceWallClock, num_edges,
139 &histogram_bin_edges, &inputWS, &outputWS, &prog](const tbb::blocked_range<size_t> &range) {
140 for (size_t index = range.begin(); index < range.end(); ++index) {
141 // The input event list
142 EventList &input_el = inputWS->getSpectrum(index);
143 // And on the output side
144 EventList &output_el = outputWS->getSpectrum(index);
145 // Copy other settings into output
146 output_el.setX(input_el.ptrX());
147 // The EventList method does the work.
148 if (compressFat)
149 input_el.compressFatEvents(toleranceTof, startTime, toleranceWallClock, &output_el);
150 else if (sortFirst || input_el.isSortedByTof() || input_el.getNumberEvents() <= num_edges)
151 input_el.compressEvents(toleranceTof, &output_el);
152 else
153 input_el.compressEvents(toleranceTof, &output_el, histogram_bin_edges);
154 prog.report("Compressing");
155 }
156 });
157 } else { // inplace
158 tbb::parallel_for(tbb::blocked_range<size_t>(0, noSpectra),
159 [compressFat, sortFirst, toleranceTof, startTime, toleranceWallClock, num_edges,
160 &histogram_bin_edges, &outputWS, &prog](const tbb::blocked_range<size_t> &range) {
161 for (size_t index = range.begin(); index < range.end(); ++index) {
162 // The input (also output) event list
163 auto &output_el = outputWS->getSpectrum(index);
164 // The EventList method does the work.
165 if (compressFat)
166 output_el.compressFatEvents(toleranceTof, startTime, toleranceWallClock, &output_el);
167 else if (sortFirst || output_el.isSortedByTof() || output_el.getNumberEvents() <= num_edges)
168 output_el.compressEvents(toleranceTof, &output_el);
169 else
170 output_el.compressEvents(toleranceTof, &output_el, histogram_bin_edges);
171 prog.report("Compressing");
172 }
173 });
174 }
175
176 // Cast to the matrixOutputWS and save it
177 this->setProperty("OutputWorkspace", outputWS);
178}
179
180} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
std::map< DeltaEMode::Type, std::string > index
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.
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)
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
void init() override
Virtual method - must be overridden by concrete algorithm.
void exec() override
Virtual method - must be overridden by concrete algorithm.
A class for holding :
Definition EventList.h:57
void compressFatEvents(const double tolerance, const Types::Core::DateAndTime &timeStart, const double seconds, EventList *destination)
void compressEvents(double tolerance, EventList *destination)
Compress the event list by grouping events with the same TOF (within a given tolerance).
std::size_t getNumberEvents() const override
Return the number of events in the list.
Kernel::cow_ptr< HistogramData::HistogramX > ptrX() const override
Deprecated, use sharedX() instead. Returns a pointer to the x data.
void setX(const Kernel::cow_ptr< HistogramData::HistogramX > &X) override
Deprecated, use setSharedX() instead.
bool isSortedByTof() const override
Return true if the event list is sorted by TOF.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
The concrete, templated class for properties.
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
MANTID_KERNEL_DLL Types::Core::DateAndTime createFromSanitizedISO8601(const std::string &date)
Creates a DateAndTime object from a date string even if the string does not exactly conform to ISO860...
int MANTID_KERNEL_DLL createAxisFromRebinParams(const std::vector< double > &params, std::vector< double > &xnew, const bool resize_xnew=true, const bool full_bins_only=false, const double xMinHint=std::nan(""), const double xMaxHint=std::nan(""), const bool useReverseLogarithmic=false, const double power=-1)
Creates a new output X array given a 'standard' set of rebinning parameters.
const std::string BINMODE("BinningMode")
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:53
@ Output
An output workspace.
Definition Property.h:54