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