Mantid
Loading...
Searching...
No Matches
TimeSplitter.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
9namespace Mantid {
10
11using namespace Types::Core;
12namespace Kernel {
13
15SplittingInterval::SplittingInterval() : m_start(), m_stop(), m_index(-1) {}
16
18SplittingInterval::SplittingInterval(const Types::Core::DateAndTime &start, const Types::Core::DateAndTime &stop,
19 const int index)
20 : m_start(start), m_stop(stop), m_index(index) {}
21
23DateAndTime SplittingInterval::start() const { return m_start; }
24
26DateAndTime SplittingInterval::stop() const { return m_stop; }
27
29double SplittingInterval::duration() const { return DateAndTime::secondsFromDuration(m_stop - m_start); }
30
32int SplittingInterval::index() const { return m_index; }
33
36 return ((b.m_start < this->m_stop) && (b.m_start >= this->m_start)) ||
37 ((b.m_stop < this->m_stop) && (b.m_stop >= this->m_start)) ||
38 ((this->m_start < b.m_stop) && (this->m_start >= b.m_start)) ||
39 ((this->m_stop < b.m_stop) && (this->m_stop >= b.m_start));
40}
41
45SplittingInterval SplittingInterval::operator&(const SplittingInterval &b) const {
46 SplittingInterval out(*this);
47 if (b.m_start > this->m_start)
48 out.m_start = b.m_start;
49 if (b.m_stop < this->m_stop)
50 out.m_stop = b.m_stop;
51 return out;
52}
54
57 SplittingInterval out(*this);
58 if (!this->overlaps(b))
59 throw std::invalid_argument("SplittingInterval: cannot apply the OR (|) "
60 "operator to non-overlapping "
61 "SplittingInterval's.");
62
63 if (b.m_start < this->m_start)
64 out.m_start = b.m_start;
65 if (b.m_stop > this->m_stop)
66 out.m_stop = b.m_stop;
67 return out;
68}
69
71bool SplittingInterval::operator<(const SplittingInterval &b) const { return (this->m_start < b.m_start); }
72
74bool SplittingInterval::operator>(const SplittingInterval &b) const { return (this->m_start > b.m_start); }
75
78 return (si1.start() < si2.start());
79}
80
81//------------------------------------------------------------------------------------------------
85bool isFilter(const TimeSplitterType &a) {
86 int max = -1;
87 TimeSplitterType::const_iterator it;
88 for (it = a.begin(); it != a.end(); ++it)
89 if (it->index() > max)
90 max = it->index();
91 return (max <= 0);
92}
93
94//------------------------------------------------------------------------------------------------
105 bool a_filter, b_filter;
106 a_filter = isFilter(a);
107 b_filter = isFilter(b);
108
109 if (a_filter && b_filter) {
110 return a & b;
111 } else if (a_filter && !b_filter) {
112 return b & a;
113 } else if (!a_filter && b_filter) {
114 return a & b;
115 } else // (!a_filter && !b_filter)
116 {
117 // Both are splitters.
118 throw std::invalid_argument("Cannot combine two splitters together, as the "
119 "output is undefined. Try splitting each "
120 "output workspace by b after the a split has "
121 "been done.");
122 }
123}
124
125//------------------------------------------------------------------------------------------------
138 // If either is empty, then no entries in the filter (aka everything is
139 // removed)
140 if ((a.empty()) || (b.empty()))
141 return out;
142
143 TimeSplitterType::const_iterator ait;
144 TimeSplitterType::const_iterator bit;
145
146 // For now, a simple double iteration. Can be made smarter if a and b are
147 // sorted.
148 for (ait = a.begin(); ait != a.end(); ++ait) {
149 for (bit = b.begin(); bit != b.end(); ++bit) {
150 if (ait->overlaps(*bit)) {
151 // The & operator for SplittingInterval keeps the index of the
152 // left-hand-side (ait in this case)
153 // meaning that a has to be the splitter because the b index is
154 // ignored.
155 out.emplace_back(*ait & *bit);
156 }
157 }
158 }
159 return out;
160}
161
162//------------------------------------------------------------------------------------------------
169 out.reserve(a.size());
170
171 // Now we have to merge duplicate/overlapping intervals together
172 auto it = a.cbegin();
173 while (it != a.cend()) {
174 // All following intervals will start at or after this one
175 DateAndTime start = it->start();
176 DateAndTime stop = it->stop();
177
178 // Keep looking for the next interval where there is a gap (start > old
179 // stop);
180 while ((it != a.cend()) && (it->start() <= stop)) {
181 // Extend the stop point (the start cannot be extended since the list is
182 // sorted)
183 if (it->stop() > stop)
184 stop = it->stop();
185 ++it;
186 }
187 // We've reached a gap point. Output this merged interval and move on.
188 out.emplace_back(start, stop, 0);
189 }
190
191 return out;
192}
193
194//------------------------------------------------------------------------------------------------
205
206 // Concatenate the two lists
207 TimeSplitterType temp;
208 // temp.insert(temp.end(), b.begin(), b.end());
209
210 // Add the intervals, but don't add any invalid (empty) ranges
211 TimeSplitterType::const_iterator it;
212 ;
213 for (it = a.begin(); it != a.end(); ++it)
214 if (it->stop() > it->start())
215 temp.emplace_back(*it);
216 for (it = b.begin(); it != b.end(); ++it)
217 if (it->stop() > it->start())
218 temp.emplace_back(*it);
219
220 // Sort by start time
221 std::sort(temp.begin(), temp.end(), compareSplittingInterval);
222
223 out = removeFilterOverlap(temp);
224
225 return out;
226}
227
228//------------------------------------------------------------------------------------------------
236 TimeSplitterType out, temp;
237 // First, you must remove any overlapping intervals, otherwise the output is
238 // stupid.
239 temp = removeFilterOverlap(a);
240
241 // No entries: then make a "filter" that keeps everything
242 if ((temp.empty())) {
243 out.emplace_back(DateAndTime::minimum(), DateAndTime::maximum(), 0);
244 return out;
245 }
246
247 TimeSplitterType::const_iterator ait;
248 ait = temp.begin();
249 if (ait != temp.end()) {
250 // First entry; start at -infinite time
251 out.emplace_back(DateAndTime::minimum(), ait->start(), 0);
252 // Now start at the second entry
253 while (ait != temp.end()) {
254 DateAndTime start, stop;
255 start = ait->stop();
256 ++ait;
257 if (ait == temp.end()) { // Reached the end - go to inf
258 stop = DateAndTime::maximum();
259 } else { // Stop at the start of the next entry
260 stop = ait->start();
261 }
262 out.emplace_back(start, stop, 0);
263 }
264 }
265 return out;
266}
267} // namespace Kernel
268} // namespace Mantid
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
Class holding a start/end time and a destination for splitting event lists and logs.
Definition: TimeSplitter.h:23
bool operator<(const SplittingInterval &b) const
Compare two splitter by the begin time.
Types::Core::DateAndTime m_stop
end
Definition: TimeSplitter.h:50
bool operator>(const SplittingInterval &b) const
Compare two splitter by the begin time.
Types::Core::DateAndTime stop() const
Return the stop time.
SplittingInterval()
Default constructor.
int index() const
Return the index (destination of this split time block)
bool overlaps(const SplittingInterval &b) const
Return true if the b SplittingInterval overlaps with this one.
int m_index
Index of the destination.
Definition: TimeSplitter.h:52
Types::Core::DateAndTime start() const
Return the start time.
Types::Core::DateAndTime m_start
begin
Definition: TimeSplitter.h:48
SplittingInterval operator|(const SplittingInterval &b) const
Or operator. Return the largest time interval.
double duration() const
Returns the duration in seconds.
MANTID_KERNEL_DLL TimeSplitterType operator&(const TimeSplitterType &a, const TimeSplitterType &b)
AND operator for TimeSplitterType Works on Filters - combines them to only keep times where both Filt...
TimeSplitterType removeFilterOverlap(const TimeSplitterType &a)
Remove any overlap in a filter (will not work properly on a splitter)
std::vector< SplittingInterval > TimeSplitterType
A typedef for splitting events according their pulse time.
Definition: LogManager.h:31
bool compareSplittingInterval(const SplittingInterval &si1, const SplittingInterval &si2)
Comparator for sorting lists of SplittingInterval.
MANTID_KERNEL_DLL TimeSplitterType operator~(const TimeSplitterType &a)
NOT operator for TimeSplitterType Only works on Filters.
bool isFilter(const TimeSplitterType &a)
Return true if the TimeSplitterType provided is a filter, meaning that it only has an output index of...
MANTID_KERNEL_DLL TimeSplitterType operator|(const TimeSplitterType &a, const TimeSplitterType &b)
OR operator for TimeSplitterType Only works on Filters, not splitters.
MANTID_KERNEL_DLL TimeSplitterType operator+(const TimeSplitterType &a, const TimeSplitterType &b)
Plus operator for TimeSplitterType.
Helper class which provides the Collimation Length for SANS instruments.