Mantid
Loading...
Searching...
No Matches
TimeROI.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2022 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 +
7
8#include <iostream>
9#include <limits>
10#include <sstream>
11
12#include "MantidKernel/Logger.h"
14
15namespace Mantid {
16namespace Kernel {
17
18using Mantid::Types::Core::DateAndTime;
19// alias for iterators
20using DateAndTimeIter = std::vector<DateAndTime>::iterator;
21
22namespace {
24Logger g_log("TimeROI");
25
26const bool ROI_USE{true};
27const bool ROI_IGNORE{false};
28
30void assert_increasing(const DateAndTime &startTime, const DateAndTime &stopTime) {
31 if (!bool(startTime < stopTime)) {
32 std::stringstream msg;
33 msg << startTime << " and " << stopTime << " are not in increasing order";
34 throw std::runtime_error(msg.str());
35 }
36}
37
38/*
39 * This method assumes that there is an overlap between the two intervals
40 */
41TimeInterval calculate_union(const TimeInterval &left, const TimeInterval &right) {
42 return TimeInterval(std::min(left.start(), right.start()), std::max(left.stop(), right.stop()));
43}
44
45/*
46 * This is slightly different than overlaps in TimeInterval because
47 * two timeROI that touch on the boundary are considered overlapping
48 */
49bool overlaps(const TimeInterval &left, const TimeInterval &right) {
50 if (left.overlaps(right))
51 return true;
52 else if (left.start() == right.stop())
53 return true;
54 else if (left.stop() == right.start())
55 return true;
56 else
57 return false; // they don't overlap
58}
59
60} // namespace
61
62const std::string TimeROI::NAME = "Kernel_TimeROI";
64const TimeROI TimeROI::USE_NONE{DateAndTime::GPS_EPOCH - DateAndTime::ONE_SECOND, DateAndTime::GPS_EPOCH};
66const TimeROI TimeROI::USE_ALL{};
67
69
70TimeROI::TimeROI(const Types::Core::DateAndTime &startTime, const Types::Core::DateAndTime &stopTime) {
71 this->addROI(startTime, stopTime);
72}
73
75
76void TimeROI::addROI(const std::string &startTime, const std::string &stopTime) {
77 this->addROI(DateAndTime(startTime), DateAndTime(stopTime));
78}
79
83void TimeROI::addROI(const Types::Core::DateAndTime &startTime, const Types::Core::DateAndTime &stopTime) {
84 assert_increasing(startTime, stopTime);
85
86 if ((this->empty()) || (startTime > m_roi.back())) {
87 // add in the new region
88 m_roi.push_back(startTime);
89 m_roi.push_back(stopTime);
90 } else if (this->isCompletelyInROI(startTime, stopTime)) {
91 g_log.debug("TimeROI::addROI to use region");
92 } else if ((startTime <= m_roi.front()) && stopTime >= m_roi.back()) {
93 // overwrite everything
94 m_roi.clear();
95 m_roi.push_back(startTime);
96 m_roi.push_back(stopTime);
97 } else if (stopTime < m_roi.front() || startTime > m_roi.back()) {
98 m_roi.insert(m_roi.begin(), stopTime);
99 m_roi.insert(m_roi.begin(), startTime);
100 } else {
101 TimeInterval roi_to_add(startTime, stopTime);
102 std::vector<TimeInterval> output;
103 bool union_added = false;
104 for (const auto &interval : this->toTimeIntervals()) {
105 if (overlaps(roi_to_add, interval)) {
106 // the roi absorbs this interval
107 // this check must be first
108 roi_to_add = calculate_union(roi_to_add, interval);
109 } else if (interval < roi_to_add) {
110 output.push_back(interval);
111 } else if (interval > roi_to_add) {
112 if (!union_added) {
113 output.push_back(roi_to_add);
114 union_added = true;
115 }
116 output.push_back(interval);
117 } else {
118 throw std::runtime_error("encountered supposedly imposible place in TimeROI::addROI");
119 }
120 }
121 if (!union_added)
122 output.push_back(roi_to_add);
123 this->clear();
124 for (const auto interval : output) {
125 m_roi.push_back(interval.start());
126 m_roi.push_back(interval.stop());
127 }
128 }
129
130 // verify "this" is in a good state
131 this->validateValues("TimeROI::addROI");
132}
133
134void TimeROI::addROI(const std::time_t &startTime, const std::time_t &stopTime) {
135 this->addROI(DateAndTime(startTime), DateAndTime(stopTime));
136}
137
142void TimeROI::appendROIFast(const Types::Core::DateAndTime &startTime, const Types::Core::DateAndTime &stopTime) {
143 if (!m_roi.empty() && m_roi.back() == startTime)
144 m_roi.back() = stopTime; // grow existent region
145 else { // add new region
146 m_roi.push_back(startTime);
147 m_roi.push_back(stopTime);
148 }
149}
150
151void TimeROI::addMask(const std::string &startTime, const std::string &stopTime) {
152 this->addMask(DateAndTime(startTime), DateAndTime(stopTime));
153}
154
161void TimeROI::addMask(const Types::Core::DateAndTime &startTime, const Types::Core::DateAndTime &stopTime) {
162 assert_increasing(startTime, stopTime);
163
164 if (this->useAll()) {
165 g_log.debug("TimeROI::addMask to an empty object is ignored");
166 } else if (this->isCompletelyInMask(startTime, stopTime)) {
167 g_log.debug("TimeROI::addMask to ignored region");
168 } else if ((startTime <= m_roi.front()) && (stopTime >= m_roi.back())) {
169 // the mask includes everything so remove all current values
170 this->m_roi.clear();
171 } else if ((startTime <= m_roi.front()) && (stopTime < m_roi.back())) {
172 // trimming the front off
173 auto iter = std::upper_bound(m_roi.begin(), m_roi.end(), stopTime);
174 const auto newValue = std::max(m_roi.front(), stopTime);
175 m_roi.erase(m_roi.begin(), iter);
176 // decide how to put in the new start time based on whether this has an even number of values
177 if (m_roi.size() % 2 == 0) {
178 if (newValue > m_roi.front())
179 *(m_roi.begin()) = newValue;
180 } else {
181 m_roi.insert(m_roi.begin(), newValue);
182 }
183 } else if ((startTime > m_roi.front()) && (stopTime >= m_roi.back())) {
184 // trim the end off
185 auto iter = std::upper_bound(m_roi.begin(), m_roi.end(), startTime);
186 const auto newValue = std::min(*iter, startTime);
187 iter = m_roi.erase(iter, m_roi.end());
188 // decide how to put in the new start time based on whether this has an even number of values
189 if (m_roi.size() % 2 == 0) {
190 *iter = newValue;
191 } else {
192 if (newValue == m_roi.back()) {
193 // currently ends in use and needs to be removed
194 m_roi.pop_back();
195 } else {
196 // need to close the end
197 m_roi.push_back(newValue);
198 }
199 }
200 } else {
201 g_log.debug("TimeROI::addMask cutting notch in existing ROI");
202 // create rois for before and after the mask
203 const TimeInterval use_before(m_roi.front(), startTime);
204 const TimeInterval use_after(stopTime, m_roi.back());
205
206 // loop through all current splitters and get new intersections
207 std::vector<TimeInterval> output;
209 const std::size_t roiSize = this->numBoundaries();
210 for (std::size_t i = 0; i < roiSize; i += 2) {
211 const TimeInterval interval(this->m_roi[i], this->m_roi[i + 1]);
212 intersection = use_before.intersection(interval);
213 if (intersection.isValid()) {
214 output.push_back(intersection);
215 }
216 intersection = use_after.intersection(interval);
217 if (intersection.isValid()) {
218 output.push_back(intersection);
219 }
220 }
221 this->clear();
222 for (const auto &interval : output) {
223 m_roi.push_back(interval.start());
224 m_roi.push_back(interval.stop());
225 }
226 }
227
228 // verify "this" is in a good state
229 this->validateValues("TimeROI::addMask");
230}
231
232void TimeROI::addMask(const std::time_t &startTime, const std::time_t &stopTime) {
233 this->addMask(DateAndTime(startTime), DateAndTime(stopTime));
234}
235
240bool TimeROI::isCompletelyInROI(const Types::Core::DateAndTime &startTime,
241 const Types::Core::DateAndTime &stopTime) const {
242 // check if the region is in the overall window at all
243 if ((startTime > m_roi.back()) || (stopTime <= m_roi.front()))
244 return false;
245
246 // since the ROI should be alternating "use" and "ignore", see if the start and stop are within a single region
247 const auto iterStart = std::lower_bound(m_roi.cbegin(), m_roi.cend(), startTime);
248 const auto iterStop = std::lower_bound(iterStart, m_roi.cend(), stopTime);
249 // too far apart
250 if (std::distance(iterStart, iterStop) > 0)
251 return false;
252
253 // the value at the start time should be "use"
254 return this->valueAtTime(startTime) == ROI_USE;
255}
256
261bool TimeROI::isCompletelyInMask(const Types::Core::DateAndTime &startTime,
262 const Types::Core::DateAndTime &stopTime) const {
263 if (this->useAll())
264 return true;
265 if (startTime >= m_roi.back())
266 return true;
267 if (stopTime < m_roi.front())
268 return true;
269
270 const auto iterStart = std::lower_bound(m_roi.cbegin(), m_roi.cend(), startTime);
271 const auto iterStop = std::lower_bound(iterStart, m_roi.cend(), stopTime);
272 // too far apart
273 if (std::distance(iterStart, iterStop) > 0)
274 return false;
275
276 // give the answer
277 return this->valueAtTime(startTime) == ROI_IGNORE;
278}
279
286bool TimeROI::valueAtTime(const Types::Core::DateAndTime &time) const {
287 if (useNone() || empty())
288 return ROI_IGNORE;
289
290 // ignore a time if it's outside ROI
291 if (time < m_roi.front() || time >= m_roi.back())
292 return ROI_IGNORE;
293
294 // get the first ROI time boundary greater than the input time. Note that an ROI is a series of alternating ROI_USE
295 // and ROI_IGNORE values.
296 const auto iterUpper = std::upper_bound(m_roi.cbegin(), m_roi.cend(), time);
297 if (std::distance(m_roi.cbegin(), iterUpper) % 2 == 0)
298 return ROI_IGNORE;
299 else
300 return ROI_USE;
301}
302
309Types::Core::DateAndTime TimeROI::getEffectiveTime(const Types::Core::DateAndTime &time) const {
310 if (m_roi.empty()) {
311 return time;
312 } else if (time > m_roi.back()) {
313 throw std::runtime_error("Requesting effective time after the end of the TimeROI");
314 } else if (valueAtTime(time) == ROI_USE) {
315 return time;
316 } else {
317 // need to find the start time the first USE region after the time
318 auto iter = std::lower_bound(m_roi.begin(), m_roi.end(), time);
319 if (valueAtTime(*iter) == ROI_IGNORE) {
320 // move to the next value
321 iter++;
322 }
323 return *iter;
324 }
325}
326
327// returns the first time in the TimeROI
328Types::Core::DateAndTime TimeROI::firstTime() const {
329 if (m_roi.empty())
330 throw std::runtime_error("cannot return time from empty TimeROI");
331 return m_roi.front();
332}
333
334// returns the last time in the TimeROI
335Types::Core::DateAndTime TimeROI::lastTime() const {
336 if (m_roi.empty())
337 throw std::runtime_error("cannot return time from empty TimeROI");
338 return m_roi.back();
339}
340
341Types::Core::DateAndTime TimeROI::timeAtIndex(unsigned long index) const {
342 return (index < m_roi.size()) ? m_roi[index] : DateAndTime::GPS_EPOCH;
343}
344
345// return the indices of the TimeROI would fall in the supplied vector of times
346std::vector<std::pair<size_t, size_t>> TimeROI::calculate_indices(const std::vector<DateAndTime> &times) const {
347 // this will create a vector of pairs, where each pair is the start and stop index of the time intervals
348 std::vector<std::pair<size_t, size_t>> indices;
349 if (this->useAll()) {
350 // if the ROI is set to use all, then we just return the whole range
351 indices.emplace_back(0, std::numeric_limits<size_t>::max());
352 return indices;
353 }
354 indices.reserve(m_roi.size() / 2);
355
356 // Iterate through the m_roi vector in pairs to find the start and stop indices for each ROI.
357 // Don't add anything if the start is out of range. Set stop to max if the stop is out of range.
358 for (size_t i = 0; i < m_roi.size(); i += 2) {
359 const auto start = std::lower_bound(times.cbegin(), times.cend(), m_roi[i]);
360 if (start != times.cend()) {
361 const auto stop = std::lower_bound(times.cbegin(), times.cend(), m_roi[i + 1]);
362 if (stop != times.cend())
363 indices.emplace_back(std::distance(times.cbegin(), start), std::distance(times.cbegin(), stop));
364 else
365 indices.emplace_back(std::distance(times.cbegin(), start), std::numeric_limits<size_t>::max());
366 }
367 }
368
369 return indices;
370}
371
373std::vector<DateAndTime> TimeROI::getAllTimes(const TimeROI &other) {
374
375 std::set<DateAndTime> times_set;
376 times_set.insert(this->m_roi.cbegin(), this->m_roi.cend());
377 times_set.insert(other.m_roi.cbegin(), other.m_roi.cend());
378
379 // copy into the vector
380 std::vector<DateAndTime> times_all;
381 times_all.assign(times_set.begin(), times_set.end());
382
383 return times_all;
384}
385
387 // this is used by LogManager::loadNexus
388 m_roi.clear();
389
390 if (roi != nullptr && roi->size() > 0) {
391 // make a copy with unique values
392 TimeSeriesProperty<bool> roi_copy(*roi);
393 roi_copy.eliminateDuplicates(); // takes last value
394
395 // TSP will always give the times sorted in increasing order and the values parallel to that
396 const auto values = roi_copy.valuesAsVector();
397
398 // find the first USE value and start there
399 const auto iter = std::find(values.cbegin(), values.cend(), ROI_USE);
400 if (iter == values.cend())
401 throw std::runtime_error("TimeROI cannot be created. All values are ignore.");
402 std::size_t start = std::size_t(std::distance(values.cbegin(), iter));
403
404 const auto times = roi_copy.timesAsVector();
405
406 // add the first start time
407 m_roi.push_back(times[start]);
408 start++; // advance past that
409
410 // add values
411 const auto NUM_VALUES = values.size();
412 for (std::size_t i = start; i < NUM_VALUES; ++i) {
413 if (values[i - 1] == values[i])
414 continue; // skip if the value is the same as the predicessor
415 // add the value to the end
416 m_roi.push_back(times[i]);
417 }
418
419 // if last value was use, add a new value at the end that is the full duration of the log out
420 if (roi->lastValue() == ROI_USE) {
421 if (roi->firstTime() == roi->lastTime()) {
422 throw std::runtime_error(
423 "Cannot guess ending value from a TimeSeriesProperty that contains only a single time");
424 } else {
425 const auto duration = roi->lastTime() - roi->firstTime();
426 m_roi.push_back(roi->lastTime() + duration);
427 }
428 }
429 }
430
431 this->validateValues("TimeROI::replaceROI");
432}
433
434void TimeROI::replaceROI(const TimeROI &other) {
435 m_roi.clear();
436 if (!other.useAll())
437 m_roi.assign(other.m_roi.cbegin(), other.m_roi.cend());
438}
439
441void TimeROI::replaceROI(const std::vector<Types::Core::DateAndTime> &roi) {
442 m_roi.clear();
443 if (!roi.empty())
444 m_roi.assign(roi.cbegin(), roi.cend());
445}
446
447namespace ROI {
448template <typename TYPE>
449std::vector<TYPE> calculate_intersection(const std::vector<TYPE> &left, const std::vector<TYPE> &right) {
450 // empty is interpreted to mean use everything
451 // these checks skip putting together temporary variables for the loops
452 if (left == right || right.empty())
453 return left;
454 else if (left.empty())
455 return right;
456
457 // verify that the dimensionality is reasonable
458 if (left.size() % 2 != 0)
459 throw std::runtime_error("Cannot calculate_intersection with odd left dimension");
460 if (right.size() % 2 != 0)
461 throw std::runtime_error("Cannot calculate_intersection with odd right dimension");
462
463 // create vector to hold the intersection results
464 std::vector<TYPE> result;
465
466 // iterators are faster access than random access via operator[]
467 auto it1 = left.cbegin();
468 auto it2 = right.cbegin();
469
470 while (it1 != left.cend() && it2 != right.cend()) {
471 // Left bound for intersecting segment
472 const TYPE &leftBound = std::max(*it1, *it2);
473
474 // Right bound for intersecting segment
475 const auto it1_next = std::next(it1);
476 const auto it2_next = std::next(it2);
477 const TYPE &rightBound = std::min(*it1_next, *it2_next);
478
479 // If segment is valid, include it
480 if (leftBound < rightBound) {
481 result.emplace_back(leftBound);
482 result.emplace_back(rightBound);
483 }
484
485 // If it1 right bound is smaller, increment it1; else increment it2
486 if (*it1_next < *it2_next)
487 std::advance(it1, 2);
488 else
489 std::advance(it2, 2);
490 }
491
492 return result;
493}
494} // namespace ROI
495
504 // exit early if the two TimeROI are identical
505 if (*this == other)
506 return;
507
508 if (other.useAll() || this->useAll()) {
509 // empty out this environment
510 // this behavior is required by existing calling code due to not universal use of TimeROI
511 m_roi.clear();
512 return;
513 }
514
515 auto output = ROI::calculate_intersection(m_roi, other.m_roi);
516
517 if (output.empty())
518 this->replaceROI(USE_NONE);
519 else
520 m_roi = std::move(output);
521}
522
529void TimeROI::update_union(const TimeROI &other) {
530 // exit early if the two TimeROI are identical
531 if (*this == other)
532 return;
533
534 // add all the intervals from the other
535 for (const auto &interval : other.toTimeIntervals()) {
536 this->addROI(interval.start(), interval.stop());
537 }
538}
539
549 if (this->useAll()) {
550 this->replaceROI(other);
551 } else if (!other.useAll()) {
552 this->update_intersection(other);
553 }
554}
555
557const std::vector<Kernel::TimeInterval> TimeROI::toTimeIntervals() const {
558 const auto NUM_VAL = m_roi.size();
559 std::vector<TimeInterval> output;
560 // every other value is a start/stop
561 for (std::size_t i = 0; i < NUM_VAL; i += 2) {
562 output.emplace_back(m_roi[i], m_roi[i + 1]);
563 }
564
565 return output;
566}
567
574const std::vector<Kernel::TimeInterval> TimeROI::toTimeIntervals(const Types::Core::DateAndTime &after) const {
575 const auto NUM_VAL = m_roi.size();
576 std::vector<TimeInterval> output;
577 // every other value is a start/stop
578 for (std::size_t i = 0; i < NUM_VAL; i += 2) {
579 if (m_roi[i + 1] > after) { // make sure end is after the first time requested
580 if (m_roi[i] > after) { // full region should be used
581 output.emplace_back(m_roi[i], m_roi[i + 1]);
582 } else {
583 output.emplace_back(after, m_roi[i + 1]);
584 }
585 }
586 }
587
588 return output;
589}
590
591bool TimeROI::operator==(const TimeROI &other) const { return this->m_roi == other.m_roi; }
592bool TimeROI::operator!=(const TimeROI &other) const { return this->m_roi != other.m_roi; }
593
602std::string TimeROI::debugStrPrint(const std::size_t type) const {
603 std::stringstream ss;
604 if (type == 0) {
605 const auto NUM_VALUES{m_roi.size()};
606 for (std::size_t i = 0; i < NUM_VALUES; i += 2) {
607 ss << (i / 2) << ": " << m_roi[i] << " to " << m_roi[i + 1] << "\n";
608 }
609 } else if (type == 1) {
610 for (const auto &val : m_roi)
611 ss << val << " ";
612 ss << "\n";
613 } else {
614 throw std::runtime_error("Invalid type parameter");
615 }
616 return ss.str();
617}
618
619size_t TimeROI::getMemorySize() const { return this->numBoundaries() * sizeof(DateAndTime); }
620
625 const auto ROI_SIZE = this->numBoundaries();
626 if (ROI_SIZE == 0) {
627 return 0.;
628 } else if (this->useNone()) {
629 return -1.;
630 } else {
631 double total{0.};
632 for (std::size_t i = 0; i < ROI_SIZE - 1; i += 2) {
633 total += DateAndTime::secondsFromDuration(m_roi[i + 1] - m_roi[i]);
634 }
635
636 return total;
637 }
638}
639
643double TimeROI::durationInSeconds(const Types::Core::DateAndTime &startTime,
644 const Types::Core::DateAndTime &stopTime) const {
645 assert_increasing(startTime, stopTime);
646
647 // just return the difference between the supplied other times if this has no regions
648 if (this->useAll()) {
649 return DateAndTime::secondsFromDuration(stopTime - startTime);
650 }
651
652 if (stopTime <= m_roi.front()) { // asking before ROI
653 return 0.;
654 } else if (startTime >= m_roi.back()) { // asking after ROI
655 return 0.;
656 } else if ((startTime <= m_roi.front()) && (stopTime >= m_roi.back())) { // full range of ROI
657 return this->durationInSeconds();
658 } else { // do the calculation
659 // the time requested is an intersection of start/stop time and this object
660 TimeROI temp{startTime, stopTime};
661 temp.update_intersection(*this);
662 return temp.durationInSeconds();
663 }
664}
665
666void TimeROI::validateValues(const std::string &label) {
667 // verify there is an even number of values
668 if (m_roi.size() % 2 != 0) {
669 std::stringstream msg;
670 msg << "Something went wrong in " << label << " and the object is now invalid. "
671 << "There are " << m_roi.size() << " regions and it must be an even number";
672 throw std::runtime_error(msg.str());
673 }
674 // verify the values are in increasing order
675 if (!std::is_sorted(m_roi.cbegin(), m_roi.cend())) {
676 throw std::runtime_error("Values are not in increasing order");
677 }
678 // verify the values are unique
679 const std::size_t NUM_UNIQUE = std::size_t(std::distance(m_roi.begin(), std::unique(m_roi.begin(), m_roi.end())));
680 if (NUM_UNIQUE != m_roi.size()) {
681 std::stringstream msg;
682 msg << "In " << label << ": Values are not unique";
683 throw std::runtime_error(msg.str());
684 }
685}
686
687std::size_t TimeROI::numBoundaries() const { return static_cast<std::size_t>(m_roi.size()); }
688
689std::size_t TimeROI::numberOfRegions() const { return this->numBoundaries() / 2; }
690
691bool TimeROI::empty() const { return bool(this->numBoundaries() == 0); }
692
693bool TimeROI::useAll() const { return this->empty(); }
694
695bool TimeROI::useNone() const { return *this == USE_NONE; }
696
699
700// serialization / deserialization items
701void TimeROI::saveNexus(Nexus::File *file) const {
702 // create a local TimeSeriesProperty which will do the actual work
704 for (const auto &interval : this->toTimeIntervals()) {
705 tsp.addValue(interval.start(), ROI_USE);
706 tsp.addValue(interval.stop(), ROI_IGNORE);
707 }
708
709 // save things to to disk
710 tsp.saveProperty(file);
711}
712
713namespace ROI {
714// concrete instantiations need to be exported
715template MANTID_KERNEL_DLL std::vector<std::size_t> calculate_intersection(const std::vector<std::size_t> &left,
716 const std::vector<std::size_t> &right);
717template MANTID_KERNEL_DLL std::vector<Types::Core::DateAndTime>
718calculate_intersection(const std::vector<Types::Core::DateAndTime> &left,
719 const std::vector<Types::Core::DateAndTime> &right);
720} // namespace ROI
721
722} // namespace Kernel
723} // namespace Mantid
std::map< DeltaEMode::Type, std::string > index
double left
double right
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
Represents a time interval.
Definition DateAndTime.h:25
TimeInterval intersection(const TimeInterval &ti) const
Returns an intersection of two intervals.
TimeROI : Object that holds information about when the time measurement was active.
Definition TimeROI.h:18
void replaceROI(const TimeSeriesProperty< bool > *roi)
Definition TimeROI.cpp:386
double durationInSeconds() const
Duration of the whole TimeROI.
Definition TimeROI.cpp:624
Types::Core::DateAndTime getEffectiveTime(const Types::Core::DateAndTime &time) const
Returns the time supplied if it is in a "use" region, or the minimum of the next higher use region.
Definition TimeROI.cpp:309
void addMask(const std::string &startTime, const std::string &stopTime)
Definition TimeROI.cpp:151
const std::vector< Kernel::TimeInterval > toTimeIntervals() const
This method is to lend itself to helping with transition.
Definition TimeROI.cpp:557
const std::vector< Types::Core::DateAndTime > & getAllTimes() const
Definition TimeROI.h:49
std::vector< std::pair< size_t, size_t > > calculate_indices(const std::vector< Types::Core::DateAndTime > &times) const
Definition TimeROI.cpp:346
bool operator==(const TimeROI &other) const
Definition TimeROI.cpp:591
std::size_t numBoundaries() const
Definition TimeROI.cpp:687
Types::Core::DateAndTime firstTime() const
Definition TimeROI.cpp:328
std::vector< Types::Core::DateAndTime > m_roi
Definition TimeROI.h:77
void clear()
Removes all ROI's, leaving an empty object.
Definition TimeROI.cpp:698
bool isCompletelyInROI(const Types::Core::DateAndTime &startTime, const Types::Core::DateAndTime &stopTime) const
This method returns true if the entire region between startTime and stopTime is inside an existing us...
Definition TimeROI.cpp:240
std::size_t numberOfRegions() const
Definition TimeROI.cpp:689
void update_union(const TimeROI &other)
Updates the TimeROI values with the union with another TimeROI.
Definition TimeROI.cpp:529
void saveNexus(Nexus::File *file) const
Definition TimeROI.cpp:701
bool operator!=(const TimeROI &other) const
Definition TimeROI.cpp:592
size_t getMemorySize() const
Definition TimeROI.cpp:619
void addROI(const std::string &startTime, const std::string &stopTime)
Definition TimeROI.cpp:76
bool isCompletelyInMask(const Types::Core::DateAndTime &startTime, const Types::Core::DateAndTime &stopTime) const
This method returns true if the entire region between startTime and stopTime is inside an existing ig...
Definition TimeROI.cpp:261
bool useNone() const
TimeROI selects no time to be used as all is invalid.
Definition TimeROI.cpp:695
static const std::string NAME
the underlying property needs a name
Definition TimeROI.h:21
std::string debugStrPrint(const std::size_t type=0) const
print the ROI boundaries to a string
Definition TimeROI.cpp:602
bool useAll() const
TimeROI selects all time to be used.
Definition TimeROI.cpp:693
Types::Core::DateAndTime timeAtIndex(unsigned long index) const
Definition TimeROI.cpp:341
void update_or_replace_intersection(const TimeROI &other)
If this is empty, replace it with the supplied TimeROI, otherwise calculate the intersection.
Definition TimeROI.cpp:548
void update_intersection(const TimeROI &other)
Updates the TimeROI values with the intersection with another TimeROI.
Definition TimeROI.cpp:503
void appendROIFast(const Types::Core::DateAndTime &startTime, const Types::Core::DateAndTime &stopTime)
Append a new region to TimeROI fast.
Definition TimeROI.cpp:142
Types::Core::DateAndTime lastTime() const
Definition TimeROI.cpp:335
bool valueAtTime(const Types::Core::DateAndTime &time) const
This returns whether the time should be "used" (rather than ignored).
Definition TimeROI.cpp:286
static const TimeROI USE_ALL
Constant for TimeROI where any time is used.
Definition TimeROI.h:23
static const TimeROI USE_NONE
Constant for TimeROI where no time is used.
Definition TimeROI.h:22
void validateValues(const std::string &label)
Definition TimeROI.cpp:666
A specialised Property class for holding a series of time-value pairs.
int size() const override
Returns the number of values at UNIQUE time intervals in the time series.
std::vector< TYPE > valuesAsVector() const
Return the time series's values (unfiltered) as a vector<TYPE>
Types::Core::DateAndTime firstTime() const
Returns the first time regardless of filter.
void eliminateDuplicates()
Detects whether there are duplicated entries (of time) in property & eliminates them.
void addValue(const Types::Core::DateAndTime &time, const TYPE &value)
Add a value to the map using a DateAndTime object.
Types::Core::DateAndTime lastTime() const
Returns the last time.
TYPE lastValue() const
Returns the last value.
std::vector< Types::Core::DateAndTime > timesAsVector() const override
Return the time series's times as a vector<DateAndTime>
void saveProperty(Nexus::File *file) override
bool MANTID_GEOMETRY_DLL intersection(const ConvexPolygon &P, const ConvexPolygon &Q, ConvexPolygon &out)
Compute the instersection of two convex polygons.
std::vector< TYPE > calculate_intersection(const std::vector< TYPE > &left, const std::vector< TYPE > &right)
This calculates the intersection of two sorted vectors that represent regions of interest (ROI).
Definition TimeROI.cpp:449
std::vector< DateAndTime >::iterator DateAndTimeIter
Definition TimeROI.cpp:20
Helper class which provides the Collimation Length for SANS instruments.