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 +
7
10#include "MantidKernel/Logger.h"
13
14namespace Mantid {
15using API::EventType;
16using Kernel::SplittingInterval;
18using Kernel::TimeROI;
19using Types::Core::DateAndTime;
20
21namespace DataObjects {
22
23namespace {
24
25void assertIncreasing(const DateAndTime &start, const DateAndTime &stop) {
26 if (start > stop)
27 throw std::runtime_error("start time found at a later time than stop time");
28}
29
31Kernel::Logger g_log("TimeSplitter");
32
33} // namespace
34
36 m_roi_map = other.m_roi_map;
37 m_name_index_map = other.m_name_index_map;
38 m_index_name_map = other.m_index_name_map;
39}
40
42 m_roi_map = other.m_roi_map;
43 m_name_index_map = other.m_name_index_map;
44 m_index_name_map = other.m_index_name_map;
45
46 resetCache();
47
48 return *this;
49}
50
51TimeSplitter::TimeSplitter(const DateAndTime &start, const DateAndTime &stop, const int value) {
52 clearAndReplace(start, stop, value);
53}
54
60 if (ws->getNumberHistograms() != 1) {
61 throw std::runtime_error("MatrixWorkspace can only have 1 histogram when constructing TimeSplitter.");
62 }
63
64 const auto X = ws->binEdges(0);
65 const auto &Y = ws->y(0);
66 if (std::any_of(X.begin(), X.end(), [](double i) { return static_cast<int>(i) < 0; })) {
67 throw std::runtime_error("All X values in MatrixWorkspace must be >= 0 to construct TimeSplitter.");
68 }
69 if (X.size() != Y.size() + 1) {
70 throw std::runtime_error(
71 "Size of x values must be one more than size of y values to construct TimeSplitter from MatrixWorkspace.");
72 }
73
74 int64_t offset_ns{offset.totalNanoseconds()};
75 for (size_t i = 1; i < X.size(); i++) {
76 auto timeStart = Types::Core::DateAndTime(X[i - 1], 0.0) + offset_ns;
77 auto timeEnd = Types::Core::DateAndTime(X[i], 0.0) + offset_ns;
78 auto target_index = static_cast<int>(Y[i - 1]);
79 if ((target_index != NO_TARGET) && (valueAtTime(timeStart) != NO_TARGET || valueAtTime(timeEnd) != NO_TARGET)) {
80 g_log.warning() << "Values between " << timeStart.second() << "(s) and " << timeEnd.second()
81 << "(s) may be overwritten in conversion to TimeSplitter" << '\n';
82 }
83 this->addROI(timeStart, timeEnd, target_index);
84 std::string target_name = std::to_string(target_index);
85 m_name_index_map[target_name] = target_index;
86 m_index_name_map[target_index] = target_name;
87 }
88}
89
90TimeSplitter::TimeSplitter(const TableWorkspace_sptr &tws, const DateAndTime &offset) {
91 if (tws->columnCount() != 3) {
92 throw std::runtime_error("Table workspace used for event filtering must have 3 columns.");
93 }
94
95 // by design, there should be 3 columns, e.g. "start", "stop", "target", although the exact names are not enforced
96 const std::size_t COL_START{0};
97 const std::size_t COL_STOP{1};
98 const std::size_t COL_TARGET{2};
99 API::Column_sptr col_target = tws->getColumn(COL_TARGET);
100
101 int target_index{NO_TARGET};
102 int max_target_index{0};
103
104 g_log.information() << "Creating a time splitter from a table workspace. Total number of rows: " << tws->rowCount()
105 << "\n";
106
107 // can't mix label types except for NO_TARGET
108 bool has_target_name_numeric = false;
109 bool has_target_name_nonnumeric = false;
110
111 for (size_t row = 0; row < tws->rowCount(); row++) {
112 // by design, the times in the table must be in seconds
113 const double timeStart_s{tws->cell_cast<double>(row, COL_START)};
114 const double timeStop_s{tws->cell_cast<double>(row, COL_STOP)};
115
116 if (timeStart_s < 0 || timeStop_s < 0) {
117 throw std::runtime_error("All times in TableWorkspace must be >= 0 to construct TimeSplitter.");
118 }
119
120 // create start/stop based from the supplied offset time
121 const Types::Core::DateAndTime timeStart = offset + timeStart_s;
122 const Types::Core::DateAndTime timeStop = offset + timeStop_s;
123
124 // get the target name; it may or may not represent an integer
125 std::string target_name = col_target->cell<std::string>(row);
126
127 const auto targetIter = m_name_index_map.find(target_name);
128 if (targetIter == m_name_index_map.end()) {
129 // Try converting to integer or create an index
130 // If target name represents an integer, that integer automatically becomes the
131 // workspace index. If target name is a non-numeric string, we will assign a unique index to it.
132 try {
133 target_index = std::stoi(target_name);
134 m_name_index_map[target_name] = target_index;
135 m_index_name_map[target_index] = target_name;
136 if (target_index != NO_TARGET)
137 has_target_name_numeric = true;
138 } catch (std::invalid_argument &) { // a non-integer string
139 has_target_name_nonnumeric = true;
140
141 if (m_name_index_map.count(target_name) == 0) {
142 target_index = max_target_index;
143 m_name_index_map[target_name] = target_index;
144 m_index_name_map[target_index] = target_name;
145 max_target_index++;
146 } else {
147 target_index = m_name_index_map[target_name];
148 assert(m_index_name_map[target_index] == target_name);
149 }
150 }
151 } else {
152 target_index = targetIter->second;
153 }
154
155 // if this row's time interval intersects an interval already in the splitter, no separate ROI will be created
156 if ((target_index != NO_TARGET) && (valueAtTime(timeStart) != NO_TARGET || valueAtTime(timeStop) != NO_TARGET)) {
157 g_log.warning() << "Workspace row " << row << " may be overwritten in conversion to TimeSplitter" << '\n';
158 }
159
160 addROI(timeStart, timeStop, target_index);
161 }
162
163 // Verify that the input target names are either all numeric or all non-numeric. The exception is a name "-1", i.e. no
164 // target specified. That name is ok to mix with non-numeric names.
165 if (has_target_name_numeric && has_target_name_nonnumeric)
166 throw std::runtime_error("Valid splitter targets cannot be a mix of numeric and non-numeric names.");
167}
168
170 for (size_t ii = 0; ii < sws->rowCount(); ii++) {
171 Kernel::SplittingInterval interval = sws->getSplitter(ii);
172
173 // if this row's time interval intersects an interval already in the splitter, no separate ROI will be created
174 if (interval.index() != NO_TARGET &&
175 (valueAtTime(interval.start()) != NO_TARGET || valueAtTime(interval.stop()) != NO_TARGET)) {
176 g_log.warning() << "Workspace row " << ii << " may be overwritten in conversion to TimeSplitter" << '\n';
177 }
178
179 int target_index = interval.index();
180 addROI(interval.start(), interval.stop(), target_index);
181 std::string target_name = std::to_string(target_index);
182 m_name_index_map[target_name] = target_index;
183 m_index_name_map[target_index] = target_name;
184 }
185}
186
188std::string TimeSplitter::debugPrint() const {
189 std::stringstream msg;
190 for (const auto &iter : m_roi_map)
191 msg << iter.second << "|" << iter.first << "\n";
192 return msg.str();
193}
194
195const std::map<DateAndTime, int> &TimeSplitter::getSplittersMap() const { return m_roi_map; }
196
197// Get the target name from the target index.
198std::string TimeSplitter::getWorkspaceIndexName(const int workspaceIndex, const int numericalShift) const {
199 if (m_index_name_map.count(workspaceIndex) == 0) {
200 std::stringstream msg;
201 msg << "Invalid target index " << workspaceIndex << " when calling TimeSplitter::getWorkspaceIndexName";
202 throw std::runtime_error(msg.str());
203 }
204
205 std::string target_name = m_index_name_map.at(workspaceIndex);
206
207 // If numericalShift is not zero, the "_index" suffix of the name will be shifted.
208 // This is needed to support FilterEvents property OutputWorkspaceIndexedFrom1.
209 if (numericalShift != 0) {
210 // If this TimeSplitter was built from a TableWorkspace, targets could be non-numeric, in which case a numeric
211 // shift wouldn't make sense.
212 int target_index;
213 try {
214 target_index = std::stoi(target_name);
215 } catch (std::invalid_argument &) // a non-integer string
216 {
217 throw std::runtime_error(
218 "FilterEvents property \"OutputWorkspaceIndexedFrom1\" is not compatible with non-numeric targets.");
219 }
220
221 assert(target_index == m_name_index_map.at(target_name));
222 std::stringstream s;
223 s << target_index + numericalShift;
224 return s.str();
225 }
226
227 return target_name;
228}
229
230void TimeSplitter::addROI(const DateAndTime &start, const DateAndTime &stop, const int value) {
231 resetCache();
232
233 // If start time == stop time, the map will be corrupted.
234 if (start == stop)
235 return;
236 assertIncreasing(start, stop);
237 if (m_roi_map.empty()) {
238 // set the values without checks
239 clearAndReplace(start, stop, value);
240 return;
241 }
242 const DateAndTime &firstTime = m_roi_map.begin()->first;
243 const DateAndTime &lastTime = m_roi_map.rbegin()->first;
244 if ((start <= firstTime) && (stop >= lastTime)) {
245 // the new ROI covers the whole of the existing TimeSplitter, thus replace it
246 clearAndReplace(start, stop, value);
247 } else if ((stop < firstTime) || (start > lastTime)) {
248 // the new ROI lies outside the whole of the existing TimeSplitter, thus just add it
249 if (value > NO_TARGET) { // only add non-ignore values
250 m_roi_map.emplace(start, value);
251 m_roi_map.emplace(stop, NO_TARGET);
252 }
253 } else if (start == lastTime) { // the new ROI starts at the end of the existing TimeSplitter
254 if (value > NO_TARGET) { // only add non-ignore values
255 m_roi_map.rbegin()->second = value;
256 m_roi_map.emplace(stop, NO_TARGET);
257 }
258 } else if (stop == firstTime) { // the new ROI ends at the start of the existing TimeSplitter
259 if (value > NO_TARGET) { // only add non-ignore values
260 m_roi_map.emplace(start, value);
261 }
262 } else { // the new ROI either overlaps or is inside the existing TimeSplitter
263 // do the interesting version
264 g_log.debug() << "addROI(" << start << ", " << stop << ", " << value << ")\n";
265
266 // cache what the final value will be
267 const int stopValue = this->valueAtTime(stop);
268
269 // find if there are values to erase
270
271 // the starting point is greater than or equal to the "start" supplied
272 auto startIterator = m_roi_map.lower_bound(start);
273 if ((startIterator->first != start) && (startIterator != m_roi_map.begin()))
274 startIterator--; // move to the one before
275
276 // the end is one past the "stop"
277 auto stopIterator = m_roi_map.upper_bound(stop);
278 if ((stopIterator != m_roi_map.end()) && (stopValue == NO_TARGET))
279 stopIterator++; // move to the one after
280
281 const bool atStart = (startIterator == m_roi_map.begin());
282
283 // remove the elements that are being replaced [inclusive, exclusive)
284 m_roi_map.erase(startIterator, stopIterator);
285
286 // put in the new elements
287 if ((value > NO_TARGET) || (!atStart)) {
288 if (value != this->valueAtTime(start)) {
289 m_roi_map.emplace(start, value);
290 }
291 }
292
293 // find the new iterator for where this goes to see if it's the same value
294 stopIterator = m_roi_map.lower_bound(stop);
295 if ((stopIterator != m_roi_map.end()) && (value == stopIterator->second)) {
296 m_roi_map.erase(stopIterator);
297 }
298 if (value != stopValue) {
299 m_roi_map.emplace(stop, stopValue);
300 }
301
302 // verify this ends with NO_TARGET
303 if (m_roi_map.rbegin()->second != NO_TARGET) {
304 throw std::runtime_error("Something went wrong in TimeSplitter::addROI");
305 }
306 }
307}
308
310bool TimeSplitter::empty() const { return m_roi_map.empty(); }
311
312void TimeSplitter::clearAndReplace(const DateAndTime &start, const DateAndTime &stop, const int value) {
313 m_roi_map.clear();
314 if (value >= 0) {
315 m_roi_map.insert({start, value});
316 m_roi_map.insert({stop, NO_TARGET});
317 }
318 resetCache();
319}
320
321// Invalidate all cached "views" on the class implementation, i.e. m_roi_map.
322// Every time m_roi_map changes, the cached "views" need to be invalidated.
327
328// Invalidate cached partial TimeROIs, so that the next call to getTimeROI() would trigger their rebuild.
335
336// Invalidate cached splitting intervals, so that the next call to getSplittingIntervals() would trigger their rebuild
344
345// Rebuild and mark as valid a cached map of partial TimeROIs. The getTimeROI() method will then use that map to quickly
346// look up and return a TimeROI.
349
350 if (empty())
351 return;
352
353 // Loop over m_roi_map and build all partial TimeROIs
354 auto it = m_roi_map.cbegin();
355 for (; it != std::prev(m_roi_map.cend()); it++) {
356 DateAndTime intervalStart = it->first;
357 DateAndTime intervalStop = std::next(it)->first;
358 int target = it->second;
359
360 if (m_cachedPartialTimeROIs.count(target) > 0) {
361 m_cachedPartialTimeROIs[target].appendROIFast(intervalStart, intervalStop);
362 } else {
364 m_cachedPartialTimeROIs[target].appendROIFast(intervalStart, intervalStop);
365 }
366 }
367
368 if (it->second != NO_TARGET) {
369 std::ostringstream err;
370 err << "Open-ended time interval is invalid in event filtering: " << it->first << " - ?,"
371 << " target index: " << it->second << std::endl;
372 throw std::runtime_error(err.str());
373 }
374
376}
377
378// Rebuild and mark as valid a cached vector of splitting intervals. The getSplittingIntervals() method will then return
379// that cached vector without building it.
380void TimeSplitter::rebuildCachedSplittingIntervals(const bool includeNoTarget) const {
382
383 if (empty())
384 return;
385
386 auto it = m_roi_map.cbegin();
387 const auto itEnd = m_roi_map.cend();
388 while (std::next(it) != itEnd) {
389 // invoke constructor SplittingInterval(DateAndTime &start, DateAndTime &stop, int index)
390 if (includeNoTarget || it->second != NO_TARGET)
391 m_cachedSplittingIntervals.emplace_back(it->first, std::next(it)->first, it->second);
392 std::advance(it, 1);
393 }
394
395 if (it->second != NO_TARGET) {
396 std::ostringstream err;
397 err << "Open-ended time interval is invalid in event filtering: " << it->first << " - ?,"
398 << " target index: " << it->second << std::endl;
399 throw std::runtime_error(err.str());
400 }
401
402 m_validCachedSplittingIntervals_All = includeNoTarget;
404}
405
411int TimeSplitter::valueAtTime(const DateAndTime &time) const {
412 // empty means exclude everything
413 if (m_roi_map.empty())
414 return NO_TARGET;
415
416 // before the beginning is excluded
417 if (time < m_roi_map.cbegin()->first)
418 return NO_TARGET;
419
420 // this method can be used when the object is in an unusual state and doesn't
421 // end with NO_TARGET
422 if (time >= m_roi_map.crbegin()->first)
423 return m_roi_map.crbegin()->second;
424
425 // find location that is greater than or equal to the requested time and give
426 // back previous value
427 auto location = m_roi_map.lower_bound(time);
428 if (location->first == time) {
429 // found the time in the map
430 return location->second;
431 } else if (location == m_roi_map.begin()) {
432 // iterator is greater than the first value in the map b/c equal is already
433 // handled asked for a time outside of the map
434 return NO_TARGET;
435 } else {
436 // go to the value before
437 location--;
438 return location->second;
439 }
440}
441
446 // sets have unique values and are sorted
447 std::set<int> outputSet;
448
449 // copy all the non-negative output destination indices
450 for (const auto &iter : m_roi_map) {
451 if (iter.second > NO_TARGET)
452 outputSet.insert(iter.second);
453 }
454
455 return outputSet;
456}
457
468const TimeROI &TimeSplitter::getTimeROI(const int workspaceIndex) const {
469 std::lock_guard<std::mutex> lock(m_mutex);
470
473 }
474 // convert indexes less than NO_TARGET to NO_TARGET
475 const int effectiveIndex = std::max<int>(workspaceIndex, NO_TARGET);
476
477 if (m_cachedPartialTimeROIs.count(effectiveIndex) == 0)
478 return TimeROI::USE_ALL;
479
480 return m_cachedPartialTimeROIs[effectiveIndex];
481}
482
491 std::lock_guard<std::mutex> lock(m_mutex);
492
493 if ((includeNoTarget && !m_validCachedSplittingIntervals_All) ||
495 rebuildCachedSplittingIntervals(includeNoTarget);
496 }
497
499}
500
501std::size_t TimeSplitter::numRawValues() const { return m_roi_map.size(); }
502const std::map<std::string, int> &TimeSplitter::getNameTargetMap() const { return m_name_index_map; }
503const std::map<int, std::string> &TimeSplitter::getTargetNameMap() const { return m_index_name_map; }
504
505// ------------------------------------------------------------------------
506// SPLITTING EVENTS METHODS
507// ------------------------------------------------------------------------
508
522void TimeSplitter::splitEventList(const EventList &events, std::map<int, EventList *> &partials, const bool pulseTof,
523 const bool tofCorrect, const double factor, const double shift) const {
524
525 if (events.getEventType() == EventType::WEIGHTED_NOTIME)
526 throw std::invalid_argument("EventList::splitEventList() called on an EventList "
527 "that no longer has time information.");
528
529 if (this->empty())
530 return;
531
532 // sort the input EventList in-place
533 const EventSortType sortOrder = pulseTof ? EventSortType::PULSETIMETOF_SORT
534 : EventSortType::PULSETIME_SORT; // this will be used to set order on outputs
535 if (pulseTof) {
536 // this sorting is preserved under linear transformation tof --> factor*tof+shift with factor>0
537 events.sortPulseTimeTOF();
538 } else {
539 events.sortPulseTime();
540 }
541
542 // split the events
543 switch (events.getEventType()) {
544 case EventType::TOF:
545 this->splitEventVec(events.getEvents(), partials, pulseTof, tofCorrect, factor, shift);
546 break;
547 case EventType::WEIGHTED:
548 this->splitEventVec(events.getWeightedEvents(), partials, pulseTof, tofCorrect, factor, shift);
549 break;
550 default:
551 throw std::runtime_error("Unhandled event type");
552 }
553
554 // set the sort order on the EventLists since we know the sorting already
555 for (auto &partial : partials) {
556 if (!partial.second->empty())
557 partial.second->setSortOrder(sortOrder);
558 }
559}
560
577template <typename EventType>
578
579void TimeSplitter::splitEventVec(const std::vector<EventType> &events, std::map<int, EventList *> &partials,
580 const bool pulseTof, const bool tofCorrect, const double factor,
581 const double shift) const {
582 // determine the right function for getting the "pulse time" for the event
583 std::function<const DateAndTime(const EventType &)> timeCalc;
584 if (pulseTof) {
585 if (tofCorrect) {
586 timeCalc = [factor, shift](const EventType &event) { return event.pulseTOFTimeAtSample(factor, shift); };
587 } else {
588 timeCalc = [](const EventType &event) { return event.pulseTOFTime(); };
589 }
590 } else {
591 timeCalc = [](const EventType &event) { return event.pulseTime(); };
592 }
593
594 // do the actual event splitting
595 this->splitEventVec(timeCalc, events, partials);
596}
597
598template <typename EventType>
599void TimeSplitter::splitEventVec(const std::function<const DateAndTime(const EventType &)> &timeCalc,
600 const std::vector<EventType> &events, std::map<int, EventList *> &partials) const {
601 // get a reference of the splitters as a vector
602 const auto &splittersVec = getSplittingIntervals(true);
603
604 // initialize the iterator over the splitter
605 auto itSplitter = splittersVec.cbegin();
606 const auto itSplitterEnd = splittersVec.cend();
607
608 // initialize iterator over the events
609 auto itEvent = events.cbegin();
610 const auto itEventEnd = events.cend();
611
612 // copy all events before first splitter to NO_TARGET
613 auto partial = partials.find(TimeSplitter::NO_TARGET);
614 {
615 const auto stop = itSplitter->start();
616 const bool shouldAppend = (partial != partials.end());
617 while (itEvent != itEventEnd && timeCalc(*itEvent) < stop) {
618 if (shouldAppend)
619 partial->second->addEventQuickly(*itEvent); // emplaces a copy of *itEvent in partial
620 // advance event iterator
621 itEvent++;
622 }
623 }
624
625 // iterate over all events. For each event try finding its destination event list, a.k.a. partial.
626 // If the partial is found, append the event to it. It is assumed events are sorted by (possibly corrected) time
627 while (itEvent != itEventEnd && itSplitter != itSplitterEnd) {
628 // Check if we need to advance the splitter and therefore select a different partial event list
629 const auto eventTime = timeCalc(*itEvent);
630 // advance to the new stopping boundary, and update the destination index as we go
631 if (eventTime > itSplitter->stop()) {
632 // first try next splitter
633 itSplitter++;
634 if (itSplitter == itSplitterEnd)
635 break;
636
637 // then try lower_bound
638 if (itSplitter->stop() < eventTime) {
639 itSplitter =
640 std::lower_bound(itSplitter, itSplitterEnd, eventTime,
641 [](const auto &splitter, const auto &eventTime) { return splitter.start() < eventTime; });
642 // may need to go back one
643 if ((std::prev(itSplitterEnd))->stop() > eventTime)
644 itSplitter = std::prev(itSplitter);
645 }
646 }
647 if (itSplitter == itSplitterEnd)
648 break;
649
650 // determine the new stop time and destination
651 const int destination = itSplitter->index();
652 const auto stop = itSplitter->stop();
653
654 // find the new partial to add to
655 partial = partials.find(destination);
656
657 // loop over events up to the end of the roi
658 const bool shouldAppend = (partial != partials.end());
659 while (itEvent != itEventEnd && timeCalc(*itEvent) < stop) {
660 if (shouldAppend)
661 partial->second->addEventQuickly(*itEvent); // emplaces a copy of *itEvent in partial
662 // advance event iterator
663 itEvent++;
664 }
665
666 // increment to the next interval
667 itSplitter++;
668 }
669
670 // copy all events after last splitter to NO_TARGET
671 if (itEvent != itEventEnd) {
672 partial = partials.find(TimeSplitter::NO_TARGET);
673 if (partial != partials.end()) {
674 for (; itEvent != itEventEnd; ++itEvent) {
675 partial->second->addEventQuickly(*itEvent); // emplaces a copy of *itEvent in partial
676 }
677 }
678 }
679}
680
690std::vector<std::pair<int, std::pair<size_t, size_t>>>
691TimeSplitter::calculate_target_indices(const std::vector<DateAndTime> &times) const {
692 const auto splittingIntervals = this->getSplittingIntervals(false);
693
694 std::vector<std::pair<int, std::pair<size_t, size_t>>> indices;
695 indices.reserve(splittingIntervals.size());
696
697 for (const auto &it : splittingIntervals) {
698 const auto startIdx = std::lower_bound(times.cbegin(), times.cend(), it.start());
699 if (startIdx != times.cend()) {
700 const auto stopIdx = std::lower_bound(times.cbegin(), times.cend(), it.stop());
701 if (stopIdx != times.cend()) {
702 if (startIdx != stopIdx) {
703 indices.emplace_back(it.index(), std::make_pair(std::distance(times.cbegin(), startIdx),
704 std::distance(times.cbegin(), stopIdx)));
705 }
706 } else {
707 indices.emplace_back(
708 it.index(), std::make_pair(std::distance(times.cbegin(), startIdx), std::numeric_limits<size_t>::max()));
709 }
710 }
711 }
712
713 return indices;
714}
715
724const TimeROI TimeSplitter::combinedTimeROI(const int64_t start_offset) const {
725 TimeROI combined;
726
727 auto it = m_roi_map.cbegin();
728 for (; it != std::prev(m_roi_map.cend()); it++) {
729 if (it->second == NO_TARGET)
730 continue;
731 DateAndTime intervalStart = it->first - start_offset;
732 DateAndTime intervalStop = std::next(it)->first;
733 combined.addROI(intervalStart, intervalStop);
734 }
735 return combined;
736}
737
738} // namespace DataObjects
739} // namespace Mantid
double value
The value of the point.
Definition FitMW.cpp:51
A class for holding :
Definition EventList.h:57
std::vector< Types::Event::TofEvent > & getEvents()
Return the list of TofEvents contained.
Mantid::API::EventType getEventType() const override
Return the type of Event vector contained within.
void sortPulseTime() const
Sort events by Frame.
std::vector< WeightedEvent > & getWeightedEvents()
Return the list of WeightedEvent contained.
void rebuildCachedSplittingIntervals(const bool includeNoTarget=true) const
const Kernel::TimeROI & getTimeROI(const int workspaceIndex) const
Returns a TimeROI for the requested workspace index.
std::map< DateAndTime, int > m_roi_map
bool empty() const
Check if the TimeSplitter is empty.
int valueAtTime(const DateAndTime &time) const
Find the destination index for an event with a given time.
const Kernel::TimeROI combinedTimeROI(const int64_t start_offset=0) const
Returns a combined TimeROI covering all intervals.
std::string debugPrint() const
Print the (destination index | DateAndTime boundary) pairs of this splitter.
const std::map< std::string, int > & getNameTargetMap() const
void splitEventVec(const std::vector< EventType > &events, std::map< int, EventList * > &partials, const bool pulseTof, const bool tofCorrect, const double factor, const double shift) const
Distribute a list of events by comparing a vector of times against the splitter boundaries.
std::map< int, std::string > m_index_name_map
const Kernel::SplittingIntervalVec & getSplittingIntervals(const bool includeNoTarget=true) const
Returns a vector of splitting intervals corresponding to the m_roi_map.
const std::map< DateAndTime, int > & getSplittersMap() const
const std::map< int, std::string > & getTargetNameMap() const
std::set< int > outputWorkspaceIndices() const
Return a set of the output workspace indices.
void addROI(const DateAndTime &start, const DateAndTime &stop, const int value)
std::vector< std::pair< int, std::pair< size_t, size_t > > > calculate_target_indices(const std::vector< DateAndTime > &times) const
Given a list of times, calculate the corresponding indices in the TimeSplitter.
static constexpr int NO_TARGET
std::map< std::string, int > m_name_index_map
std::string getWorkspaceIndexName(const int workspaceIndex, const int numericalShift=0) const
void clearAndReplace(const DateAndTime &start, const DateAndTime &stop, const int value)
std::size_t numRawValues() const
these methods are to aid in testing and not intended for use elsewhere
Kernel::SplittingIntervalVec m_cachedSplittingIntervals
std::map< int, Kernel::TimeROI > m_cachedPartialTimeROIs
void splitEventList(const EventList &events, std::map< int, EventList * > &partials, const bool pulseTof=false, const bool tofCorrect=false, const double factor=1.0, const double shift=0.0) const
Split a list of events according to Pulse time or Pulse + TOF time.
TimeSplitter & operator=(const TimeSplitter &other)
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
Class holding a start/end time and a destination for splitting event lists and logs.
int index() const
Return the index (destination of this split time block)
const Types::Core::DateAndTime & start() const
Beginning of the interval.
Definition DateAndTime.h:34
const Types::Core::DateAndTime & stop() const
End of the interval.
Definition DateAndTime.h:36
TimeROI : Object that holds information about when the time measurement was active.
Definition TimeROI.h:18
void addROI(const std::string &startTime, const std::string &stopTime)
Definition TimeROI.cpp:76
static const TimeROI USE_ALL
Constant for TimeROI where any time is used.
Definition TimeROI.h:23
std::shared_ptr< Column > Column_sptr
Definition Column.h:232
Kernel::Logger g_log("ExperimentInfo")
static logger object
EventType
What kind of event list is being stored.
Definition IEventList.h:18
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< SplittersWorkspace > SplittersWorkspace_sptr
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
EventSortType
How the event list is sorted.
Definition EventList.h:32
std::vector< SplittingInterval > SplittingIntervalVec
A typedef for splitting events according their pulse time.
Definition LogManager.h:28
Helper class which provides the Collimation Length for SANS instruments.
std::string to_string(const wide_integer< Bits, Signed > &n)