20#pragma warning(disable : 4180)
22#include "tbb/parallel_sort.h"
24#pragma warning(default : 4180)
35using std::runtime_error;
40using Types::Core::DateAndTime;
41using Types::Event::TofEvent;
46constexpr double SEC_TO_NANO{1.e9};
50constexpr size_t MIN_VEC_LENGTH_PARALLEL_SORT{2000};
59template <
typename EventType>
60int64_t calculateCorrectedFullTime(
const EventType &event,
const double tofFactor,
const double tofShift) {
61 return event.pulseTime().totalNanoseconds() +
62 static_cast<int64_t
>(tofFactor * (
event.tof() * 1.0E3) + (tofShift * 1.0E9));
68template <
typename EventType>
class CompareTimeAtSample {
74 CompareTimeAtSample(
const double tofFactor,
const double tofShift) :
m_tofFactor(tofFactor),
m_tofShift(tofShift) {}
86 const auto tAtSample1 = calculateCorrectedFullTime(e1, m_tofFactor, m_tofShift);
87 const auto tAtSample2 = calculateCorrectedFullTime(e2, m_tofFactor, m_tofShift);
88 return (tAtSample1 < tAtSample2);
110 if (e1.pulseTime() < e2.pulseTime()) {
112 }
else if ((e1.pulseTime() == e2.pulseTime()) && (e1.tof() < e2.tof())) {
122 :
startNano(start.totalNanoseconds()),
deltaNano(static_cast<int64_t>(seconds * SEC_TO_NANO)) {}
130 if (e1Pulse < e2Pulse) {
132 }
else if ((e1Pulse == e2Pulse) && (e1.tof() < e2.tof())) {
146 std::optional<size_t> (*
findBin)(std::span<double const>,
const double,
const double,
const double,
const bool);
150 divisor = 1. / log1p(abs(step));
159 std::optional<size_t>
operator()(std::span<double const>
X,
const double tof,
const bool findExact) {
167 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts),
168 eventType(event_type), order(
UNSORTED), mru(nullptr) {
171 this->
events = std::make_unique<std::vector<Mantid::Types::Event::TofEvent>>();
178 this->weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
184 this->weightedEventsNoTime = std::make_unique<std::vector<WeightedEventNoTime>>();
185 this->weightedEventsNoTime =
nullptr;
196 m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts),
197 weightedEvents(nullptr), weightedEventsNoTime(nullptr), eventType(
TOF), order(
UNSORTED), mru(mru) {
198 this->
events = std::make_unique<std::vector<Mantid::Types::Event::TofEvent>>();
212 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts),
213 weightedEvents(nullptr), weightedEventsNoTime(nullptr), eventType(
TOF), mru(nullptr) {
214 this->events = std::make_unique<std::vector<Mantid::Types::Event::TofEvent>>(
events.cbegin(),
events.cend());
222 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts), events(nullptr),
223 weightedEventsNoTime(nullptr), mru(nullptr) {
232 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts), events(nullptr),
233 weightedEvents(nullptr), mru(nullptr) {
245 }
catch (
const std::runtime_error &) {
263 sink.
events = std::make_unique<std::vector<Types::Event::TofEvent>>(
events->cbegin(),
events->cend());
265 sink.
events = std::make_unique<std::vector<Types::Event::TofEvent>>();
270 sink.
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
297 int MaxEventsPerBin) {
302 Mantid::HistogramData::HistogramX
const &
X = inSpec->
x();
303 Mantid::HistogramData::HistogramY
const &
Y = inSpec->
y();
304 Mantid::HistogramData::HistogramE
const &E = inSpec->
e();
305 if (
Y.size() + 1 !=
X.size()) {
306 throw std::runtime_error(
"Expected a histogram (X vector should be 1 longer than the Y vector)");
316 for (
size_t i = 0; i <
X.size() - 1; i++) {
317 double weight =
Y[i];
318 if ((weight != 0.0 || GenerateZeros) && std::isfinite(weight)) {
321 if (std::isfinite(
error)) {
322 if (GenerateMultipleEvents) {
326 double val = weight / E[i];
341 for (
size_t j = 0; j < size_t(
numEvents); j++) {
342 double tof =
X[i] + tofStep * (0.5 + double(j));
350 double tof = (
X[i] +
X[i + 1]) / 2.0;
352 double errorSquared = E[i];
353 errorSquared *= errorSquared;
380 IEventList::operator=(
rhs);
382 rhs.copyDataInto(*
this);
396 this->
events->emplace_back(event);
423 this->
events->insert(this->
events->end(), more_events.cbegin(), more_events.cend());
430 std::copy(more_events.cbegin(), more_events.cend(), std::back_inserter(*this->weightedEvents));
437 std::copy(more_events.cbegin(), more_events.cend(), std::back_inserter(*this->weightedEventsNoTime));
484 std::copy(more_events.cbegin(), more_events.cend(), std::back_inserter(*this->weightedEventsNoTime));
528 if (!more_events.
empty()) {
576 std::transform(more_events.cbegin(), more_events.cend(), std::back_inserter(
events),
577 [](
const auto &ev) { return T1(ev.tof(), ev.pulseTime(), ev.weight() * (-1.0), ev.errorSquared()); });
589 if (
this == &more_events) {
645bool vectorPtrEquals(
const std::unique_ptr<std::vector<T>> &
left,
const std::unique_ptr<std::vector<T>> &
right) {
669 if (!vectorPtrEquals(
events,
rhs.events))
687 const int64_t tolPulse)
const {
699 auto leftIter = this->
events->cbegin();
700 auto leftEnd = this->
events->cend();
701 auto rightIter =
rhs.events->cbegin();
702 while (leftIter != leftEnd) {
703 if (!leftIter->equals(*rightIter, tolTof, tolPulse))
705 leftIter = std::next(leftIter);
706 rightIter = std::next(rightIter);
713 auto rightIter =
rhs.weightedEvents->cbegin();
714 while (leftIter != leftEnd) {
715 if (!leftIter->equals(*rightIter, tolTof, tolWeight, tolPulse))
717 leftIter = std::next(leftIter);
718 rightIter = std::next(rightIter);
725 auto rightIter =
rhs.weightedEventsNoTime->cbegin();
726 while (leftIter != leftEnd) {
727 if (!leftIter->equals(*rightIter, tolTof, tolWeight))
729 leftIter = std::next(leftIter);
730 rightIter = std::next(rightIter);
756 throw std::runtime_error(
"EventList::switchTo() called on an EventList with weights to go down to TofEvent's. "
757 "This would remove weight information and therefore is not possible.");
783 throw std::runtime_error(
"EventList::switchToWeightedEvents() called on an EventList with WeightedEventNoTime's. "
784 "It has lost the pulse time information and can't go back to WeightedEvent's.");
858 return WeightedEvent(event.tof(), 0, event.weight(), event.errorSquared());
861 throw std::runtime_error(
"EventList: invalid event type value was found.");
878 throw std::runtime_error(
"EventList::getEvents() called for an EventList that has weights. Use getWeightedEvents() "
879 "or getWeightedEventsNoTime().");
883 throw std::runtime_error(
"unweighted event vector is not initialized");
894 throw std::runtime_error(
"EventList::getEvents() called for an EventList that has weights. Use getWeightedEvents() "
895 "or getWeightedEventsNoTime().");
899 throw std::runtime_error(
"unweighted event vector is not initialized");
911 throw std::runtime_error(
"EventList::getWeightedEvents() called for an EventList not of type WeightedEvent. Use "
912 "getEvents() or getWeightedEventsNoTime().");
916 throw std::runtime_error(
"weighted event vector is not initialized");
928 throw std::runtime_error(
"EventList::getWeightedEvents() called for an EventList not of type WeightedEvent. Use "
929 "getEvents() or getWeightedEventsNoTime().");
933 throw std::runtime_error(
"weighted event vector is not initialed");
943 throw std::runtime_error(
"EventList::getWeightedEventsNoTime() called for an EventList not of type "
944 "WeightedEventNoTime. Use getEvents() or getWeightedEvents().");
948 throw std::runtime_error(
"weighted event no time vector is not initialed");
958 throw std::runtime_error(
"EventList::getWeightedEventsNoTime() called for an EventList not of type "
959 "WeightedEventNoTime. Use getEvents() or getWeightedEvents().");
963 throw std::runtime_error(
"weighted event no time vector is not initialed");
973 }
catch (
const std::runtime_error &) {
982 if (!this->
empty()) {
985 std::vector<TofEvent>().swap(*this->
events);
1035 this->
events->reserve(num);
1064 throw std::invalid_argument(
"sorting by pulse time with delta requires "
1065 "extra parameters. Use sortPulseTimeTOFDelta "
1068 throw std::invalid_argument(
"sorting by time at sample requires extra "
1069 "parameters. Use sortTimeAtSample instead.");
1071 throw runtime_error(
"Invalid sort type in EventList::sort(EventSortType)");
1084template <
class RandomIt>
void switchable_sort(RandomIt first, RandomIt last) {
1085 const auto vec_size =
static_cast<size_t>(std::distance(first, last));
1088 else if (vec_size < MIN_VEC_LENGTH_PARALLEL_SORT)
1089 std::sort(first, last);
1091 tbb::parallel_sort(first, last);
1094template <
class RandomIt,
class Compare>
void switchable_sort(RandomIt first, RandomIt last, Compare comp) {
1095 const auto vec_size =
static_cast<size_t>(std::distance(first, last));
1098 else if (vec_size < MIN_VEC_LENGTH_PARALLEL_SORT)
1099 std::sort(first, last, std::move(comp));
1101 tbb::parallel_sort(first, last, comp);
1156 CompareTimeAtSample<TofEvent> comparitor(tofFactor, tofShift);
1157 switchable_sort(
events->begin(),
events->end(), comparitor);
1160 CompareTimeAtSample<WeightedEvent> comparitor(tofFactor, tofShift);
1164 CompareTimeAtSample<WeightedEventNoTime> comparitor(tofFactor, tofShift);
1245 switchable_sort(
events->begin(),
events->end(), std::move(comparator));
1278 std::reverse(
x.begin(),
x.end());
1284 std::reverse(this->
events->begin(), this->events->end());
1287 std::reverse(this->
weightedEvents->begin(), this->weightedEvents->end());
1315 throw std::runtime_error(
"EventList: invalid event type value was found.");
1325 return this->
events->empty();
1327 throw std::runtime_error(
"TOF events is nullptr");
1332 throw std::runtime_error(
"WEIGHTED events is nullptr");
1337 throw std::runtime_error(
"WEIGHTED_NOTIME events is nullptr");
1339 throw std::runtime_error(
"EventList: invalid event type value was found.");
1352 return this->
events->capacity() *
sizeof(TofEvent) +
sizeof(
EventList);
1358 throw std::runtime_error(
"EventList: invalid event type value was found.");
1365 size_t x_size =
x().size();
1381[[deprecated(
"The setX() method is deprecated in Mantid 7.0. Use setSharedX() instead.")]]
1391[[deprecated(
"The dataX() method is deprecated in Mantid 7.0. Use mutableX() instead.")]]
1407[[deprecated(
"The dataX() method is deprecated in Mantid 7.0. Use x() instead.")]]
1413[[deprecated(
"The readX() method is deprecated in Mantid 7.0. Use x() instead.")]]
1419[[deprecated(
"The sharedX() method is deprecated in Mantid 7.0. Use sharedX() instead,")]]
1427[[deprecated("The dataDx() method is deprecated in
Mantid 7.0. Use mutableDx() instead.")]]
1429 return m_histogram.
dataDx();
1434[[deprecated("The dataDx() method is deprecated in
Mantid 7.0. Use dx() instead.")]]
1436 return m_histogram.
dx().rawData();
1439[[deprecated(
"The readDx() method is deprecated in Mantid 7.0. Use dx() instead.")]]
1489 return histogram().countStandardDeviations();
1497 return histogram().frequencyStandardDeviations();
1502 throw std::runtime_error(
"'EventList::y()' called with no MRU set. This is not allowed.");
1508 throw std::runtime_error(
"'EventList::e()' called with no MRU set. This is not allowed.");
1521 yData =
mru->
findY(
static_cast<size_t>(thread),
this);
1530 yData = Kernel::make_cow<HistogramData::HistogramY>(std::move(
Y));
1535 auto eData = Kernel::make_cow<HistogramData::HistogramE>(std::move(E));
1559 eData = Kernel::make_cow<HistogramData::HistogramE>(std::move(E));
1574 throw std::runtime_error(
"'EventList::dataY()' called with no MRU set. This is not allowed.");
1588 throw std::runtime_error(
"'EventList::dataE()' called with no MRU set. This is not allowed.");
1596inline double calcNorm(
const double errorSquared) {
1597 if (errorSquared == 0.)
1599 else if (errorSquared == 1.)
1602 return 1. / std::sqrt(errorSquared);
1621 out.reserve(
events.size() / 20);
1624 double lastTof =
events.front().m_tof;
1626 double totalTof = 0;
1630 double errorSquared = 0;
1631 double normalization = 0.;
1633 double bin_end = lastTof;
1634 std::function<bool(
const double,
const double)> compareTof;
1635 std::function<double(
const double,
double)> next_bin;
1639 throw std::runtime_error(
"compressEvents with log binning doesn't work with negative TOF");
1645 compareTof = [](
const double lhs,
const double rhs) {
return lhs <
rhs; };
1646 next_bin = [
tolerance](
const double lastTof,
double bin_end) {
1648 while (lastTof >= bin_end)
1654 compareTof = [](
const double lhs,
const double rhs) {
return lhs <=
rhs; };
1655 next_bin = [
tolerance](
const double lastTof, double) {
return lastTof +
tolerance; };
1659 bin_end = next_bin(lastTof, bin_end);
1661 for (
auto it =
events.cbegin(); it !=
events.cend(); it++) {
1662 if (compareTof(it->m_tof, bin_end)) {
1664 weight += it->weight();
1665 errorSquared += it->errorSquared();
1668 const double norm = calcNorm(it->errorSquared());
1669 normalization += norm;
1670 totalTof += it->m_tof * norm;
1677 out.emplace_back(lastTof, weight, errorSquared);
1678 }
else if (num > 1) {
1679 out.emplace_back(totalTof / normalization, weight, errorSquared);
1683 const double norm = calcNorm(it->errorSquared());
1684 normalization = norm;
1685 totalTof = it->m_tof * norm;
1686 weight = it->weight();
1687 errorSquared = it->errorSquared();
1688 lastTof = it->m_tof;
1690 bin_end = next_bin(lastTof, bin_end);
1698 out.emplace_back(lastTof, weight, errorSquared);
1699 }
else if (num > 1) {
1700 out.emplace_back(totalTof / normalization, weight, errorSquared);
1704 size_t excess_limit = out.size() / 20;
1705 if ((out.capacity() - out.size()) > excess_limit) {
1706 out.shrink_to_fit();
1712 const double tolerance,
const Types::Core::DateAndTime &timeStart,
1713 const double seconds) {
1717 out.reserve(
events.size() / 20);
1720 double lastTof =
events.front().m_tof;
1722 double totalTof = 0;
1726 const int64_t pulsetimeStart = timeStart.totalNanoseconds();
1727 const auto pulsetimeDelta =
static_cast<int64_t
>(seconds * SEC_TO_NANO);
1730 std::vector<DateAndTime> pulsetimes;
1731 std::vector<double> pulsetimeWeights;
1735 double errorSquared = 0.;
1736 double tofNormalization = 0.;
1741 auto it =
events.cbegin();
1742 for (; it !=
events.cend(); ++it) {
1743 if (it->m_pulsetime >= timeStart)
1748 throw std::runtime_error(
"failed to find first pulse time in the events");
1751 int64_t lastPulseBin = (it->m_pulsetime.totalNanoseconds() - pulsetimeStart) / pulsetimeDelta;
1753 double bin_end = lastTof;
1755 std::function<bool(
const double,
const double)> compareTof;
1756 std::function<double(
const double,
double)> next_bin;
1760 compareTof = [](
const double lhs,
const double rhs) {
return lhs <
rhs; };
1761 next_bin = [
tolerance](
const double lastTof,
double bin_end) {
1763 while (lastTof >= bin_end)
1769 const auto event_min = std::min_element(
1770 events.cbegin(),
events.cend(), [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
1771 bin_end = tof_min = event_min->tof();
1774 throw std::runtime_error(
"compressEvents with log binning doesn't work with negative TOF");
1782 compareTof = [](
const double lhs,
const double rhs) {
return lhs <=
rhs; };
1783 next_bin = [
tolerance](
const double lastTof, double) {
return lastTof +
tolerance; };
1787 bin_end = next_bin(lastTof, bin_end);
1790 for (; it !=
events.cend(); ++it) {
1791 const int64_t eventPulseBin = (it->m_pulsetime.totalNanoseconds() - pulsetimeStart) / pulsetimeDelta;
1792 if ((eventPulseBin <= lastPulseBin) && compareTof(it->m_tof, bin_end)) {
1794 weight += it->weight();
1795 errorSquared += it->errorSquared();
1796 double norm = calcNorm(it->errorSquared());
1797 tofNormalization += norm;
1799 totalTof += it->m_tof * norm;
1801 pulsetimes.emplace_back(it->m_pulsetime);
1802 pulsetimeWeights.emplace_back(norm);
1805 if (!pulsetimes.empty()) {
1808 if (pulsetimes.size() == 1) {
1809 out.emplace_back(lastTof, pulsetimes.front(), weight, errorSquared);
1811 out.emplace_back(totalTof / tofNormalization,
1816 if (
tolerance < 0 && eventPulseBin != lastPulseBin)
1821 double norm = calcNorm(it->errorSquared());
1822 totalTof = it->m_tof * norm;
1823 weight = it->weight();
1824 errorSquared = it->errorSquared();
1825 tofNormalization = norm;
1826 lastTof = it->m_tof;
1827 lastPulseBin = eventPulseBin;
1829 pulsetimes.emplace_back(it->m_pulsetime);
1830 pulsetimeWeights.clear();
1831 pulsetimeWeights.emplace_back(norm);
1833 bin_end = next_bin(lastTof, bin_end);
1838 if (!pulsetimes.empty()) {
1841 if (pulsetimes.size() == 1) {
1842 out.emplace_back(lastTof, pulsetimes.front(), weight, errorSquared);
1844 out.emplace_back(totalTof / tofNormalization,
1850 size_t excess_limit = out.size() / 20;
1851 if ((out.capacity() - out.size()) > excess_limit) {
1852 out.shrink_to_fit();
1867 if (this->
empty()) {
1894 if (destination ==
this) {
1896 auto out = std::make_unique<std::vector<WeightedEventNoTime>>();
1926 const std::vector<T> &weight,
const std::vector<T> &
error) {
1928 for (
size_t i = 0; i < weight.size(); ++i) {
1929 const auto errors =
static_cast<float>(
error[i]);
1931 out.emplace_back(tof[i],
static_cast<float>(weight[i]), errors);
1937 const std::shared_ptr<std::vector<double>> histogram_bin_edges,
1939 const auto NUM_BINS = histogram_bin_edges->size() - 1;
1940 std::vector<double> tof(NUM_BINS, 0.);
1941 std::vector<double> normalization(NUM_BINS, 0.);
1942 std::vector<float> weight(NUM_BINS, 0.);
1943 std::vector<float>
error(NUM_BINS, 0.);
1944 for (
const auto &ev :
events) {
1945 const auto &bin_optional = findBin(*histogram_bin_edges.get(), ev.m_tof,
false);
1947 const auto bin = bin_optional.value();
1948 const double norm = calcNorm(ev.m_errorSquared);
1949 tof[bin] += ev.m_tof * norm;
1950 normalization[bin] += norm;
1951 weight[bin] += ev.m_weight;
1952 error[bin] += ev.m_errorSquared;
1957 std::transform(tof.begin(), tof.end(), normalization.begin(), tof.begin(), std::divides<double>());
1963 const std::shared_ptr<std::vector<double>> histogram_bin_edges) {
1964 if (this->
empty()) {
1969 const auto NUM_BINS = histogram_bin_edges->size() - 1;
1970 const auto xmin =
static_cast<double>(histogram_bin_edges->front());
1976 std::vector<double> tof(NUM_BINS, 0);
1977 std::vector<uint32_t>
count(NUM_BINS, 0);
1978 for (
const auto &ev : *this->
events) {
1979 const auto &bin_optional = findBin(*histogram_bin_edges.get(), ev.m_tof,
false);
1981 const auto bin = bin_optional.value();
1983 tof[bin] += ev.m_tof;
1988 std::transform(tof.begin(), tof.end(),
count.begin(), tof.begin(), std::divides<double>());
2001 if (destination ==
this) {
2003 auto out = std::make_unique<std::vector<WeightedEventNoTime>>();
2025 const double seconds,
EventList *destination) {
2026 if (this->
empty()) {
2029 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2033 throw std::invalid_argument(
"Cannot compress events that do not have pulsetime");
2036 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2041 if (destination ==
this) {
2043 auto out = std::make_unique<std::vector<WeightedEvent>>();
2048 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2073typename std::vector<T>::const_iterator
static findFirstEvent(
const std::vector<T> &events, T seek_tof) {
2074 return std::find_if_not(events.cbegin(), events.cend(), [seek_tof](
const T &
x) { return x < seek_tof; });
2089 const double seek_pulsetime) {
2090 auto itev =
events.cbegin();
2091 auto itev_end =
events.cend();
2094 while ((itev != itev_end) && (
static_cast<double>(itev->pulseTime().totalNanoseconds()) < seek_pulsetime))
2115typename std::vector<T>::const_iterator
2117 const double &tofOffset)
const {
2118 auto itev =
events.cbegin();
2119 auto itev_end =
events.cend();
2122 while ((itev != itev_end) &&
2123 (
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset)) < seek_time))
2140template <
class T>
typename std::vector<T>::iterator
static findFirstEvent(std::vector<T> &events, T seek_tof) {
2141 return std::find_if_not(events.begin(), events.end(), [seek_tof](
const T &
x) { return x < seek_tof; });
2158 size_t x_size =
X.size();
2167 bool mustFill = (
Y.size() == x_size - 1);
2169 Y.resize(x_size - 1, 0.0);
2172 E.resize(x_size - 1, 0.0);
2176 std::fill(
Y.begin(),
Y.end(), 0.0);
2177 std::fill(E.begin(), E.end(), 0.0);
2187 auto itev_end =
events.cend();
2190 if (itev == itev_end)
2197 double tof = itev->tof();
2198 while (bin < x_size - 1) {
2200 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
2203 Y[bin] += double(itev->m_weight);
2204 E[bin] += double(itev->m_errorSquared);
2213 while ((itev != itev_end) && (bin < x_size - 1)) {
2215 while (bin < x_size - 1) {
2219 if (tof <
X[bin + 1]) {
2222 Y[bin] += double(itev->m_weight);
2223 E[bin] += double(itev->m_errorSquared);
2233 std::transform(E.cbegin(), E.cend(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2253 size_t x_size =
X.size();
2262 bool mustFill = (
Y.size() == x_size - 1);
2263 Y.resize(x_size - 1, 0.0);
2264 E.resize(x_size - 1, 0.0);
2267 std::fill(
Y.begin(),
Y.end(), 0.0);
2268 std::fill(E.begin(), E.end(), 0.0);
2274 const auto xmin =
X.front();
2275 const auto xmax =
X.back();
2277 auto findBin =
FindBin(step, xmin);
2279 for (
const T &ev :
events) {
2280 const double tof = ev.tof();
2281 if (tof < xmin || tof >= xmax)
2284 std::optional<size_t> n_bin = findBin(
X, tof,
true);
2287 Y[n_bin.value()] += ev.weight();
2288 E[n_bin.value()] += ev.errorSquared();
2293 std::transform(E.cbegin(), E.cend(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2307 bool skipError)
const {
2320 throw std::runtime_error(
"Cannot histogram by pulse time on Weighted "
2321 "Events currently");
2324 throw std::runtime_error(
"Cannot histogram by pulse time on Weighted Events NoTime");
2340 const double &tofFactor,
const double &tofOffset,
bool skipError)
const {
2353 throw std::runtime_error(
"Cannot histogram by time at sample on Weighted "
2354 "Events currently");
2357 throw std::runtime_error(
"Cannot histogram by time at sample on Weighted Events NoTime");
2410 bool skipError)
const {
2441 size_t x_size =
X.size();
2452 Y.resize(x_size - 1, 0);
2457 if (!this->
events->empty()) {
2460 auto itev_end =
events->cend();
2463 if (itev == itev_end)
2471 double pulsetime =
static_cast<double>(itev->pulseTime().totalNanoseconds());
2472 while (bin < x_size - 1) {
2474 if ((pulsetime >=
X[bin]) && (pulsetime <
X[bin + 1])) {
2484 while ((itev != itev_end) && (bin < x_size - 1)) {
2485 pulsetime =
static_cast<double>(itev->pulseTime().totalNanoseconds());
2486 while (bin < x_size - 1) {
2488 if ((pulsetime >=
X[bin]) && (pulsetime <
X[bin + 1])) {
2514 const double TOF_min,
const double TOF_max)
const {
2516 if (this->
events->empty())
2519 size_t nBins =
Y.size();
2524 double step = (xMax - xMin) /
static_cast<double>(nBins);
2526 for (
const TofEvent &ev : *this->
events) {
2527 double pulsetime =
static_cast<double>(ev.pulseTime().totalNanoseconds());
2528 if (pulsetime < xMin || pulsetime >= xMax)
2530 if (ev.tof() < TOF_min || ev.tof() >= TOF_max)
2533 auto n_bin =
static_cast<size_t>((pulsetime - xMin) / step);
2548 const double &tofOffset)
const {
2550 const size_t x_size =
X.size();
2561 Y.resize(x_size - 1, 0);
2566 if (!this->
events->empty()) {
2569 std::vector<TofEvent>::const_iterator itev_end =
events->end();
2572 if (itev == itev_end)
2578 auto tAtSample =
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset));
2579 while (bin < x_size - 1) {
2581 if ((tAtSample >=
X[bin]) && (tAtSample <
X[bin + 1])) {
2591 while ((itev != itev_end) && (bin < x_size - 1)) {
2592 tAtSample =
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset));
2593 while (bin < x_size - 1) {
2595 if ((tAtSample >=
X[bin]) && (tAtSample <
X[bin + 1])) {
2614 size_t x_size =
X.size();
2625 Y.resize(x_size - 1, 0);
2631 if (!this->
events->empty()) {
2635 const auto itend = this->
events->end();
2637 for (
auto itx =
X.begin(); itev != itend; ++itev) {
2638 const double tof = itev->tof();
2639 itx = std::find_if(itx,
X.end(), [tof](
const double x) { return tof < x; });
2640 if (itx ==
X.end()) {
2643 const auto bin =
static_cast<size_t>(std::max(std::distance(
X.begin(), itx) - 1, std::ptrdiff_t{0}));
2660 const double offset,
const bool findExact) {
2661 const auto bin =
static_cast<size_t>(tof * divisor - offset);
2662 if (bin >=
X.size())
2663 return std::nullopt;
2689 const double offset,
const bool findExact) {
2690 const auto bin =
static_cast<size_t>(log(tof) * divisor - offset);
2691 if (bin >=
X.size())
2692 return std::nullopt;
2708 auto tof_of_bin =
X.begin() + n_bin;
2709 if (tof < *tof_of_bin)
2710 return std::move(n_bin - 1);
2714 if (tof >= *tof_of_bin)
2715 return std::move(n_bin + 1);
2718 return std::move(n_bin);
2734 size_t x_size =
X.size();
2743 bool mustFill = (
Y.size() == x_size - 1);
2745 Y.resize(x_size - 1, 0);
2747 std::fill(
Y.begin(),
Y.end(), 0.0);
2750 if (this->
events->empty())
2753 const auto xmin =
X.front();
2754 const auto xmax =
X.back();
2756 auto findBin =
FindBin(step, xmin);
2758 for (
const TofEvent &ev : *this->
events) {
2759 const double tof = ev.tof();
2760 if (tof < xmin || tof >= xmax)
2763 const std::optional<size_t> n_bin = findBin(
X, tof,
true);
2780 E.resize(
Y.size(), 0);
2783 std::transform(
Y.begin(),
Y.end(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2799 double &sum,
double &
error) {
2807 auto lowit =
events.cbegin();
2808 auto highit =
events.cend();
2817 if (lowit->tof() < minX)
2818 lowit = std::lower_bound(
events.cbegin(),
events.cend(), minX);
2820 if ((highit - 1)->tof() > maxX) {
2821 highit = std::upper_bound(lowit,
events.cend(), T(maxX));
2826 for (
auto it = lowit; it != highit; ++it) {
2827 sum += it->weight();
2828 error += it->errorSquared();
2843 double sum(0),
error(0);
2858 double &
error)
const {
2878 throw std::runtime_error(
"EventList: invalid event type value was found.");
2899 transform(
x.cbegin(),
x.cend(),
x.begin(), func);
2932 ev.m_tof = func(ev.m_tof);
2978 for (
auto &event :
events) {
2979 event.m_tof =
event.m_tof * factor + offset;
3007 for (
auto &event :
events) {
3008 event.m_pulsetime += seconds;
3019 auto eventIterEnd{
events.end()};
3020 auto secondsIter{seconds.cbegin()};
3021 for (
auto eventIter =
events.begin(); eventIter < eventIterEnd; ++eventIter, ++secondsIter) {
3022 eventIter->m_pulsetime += *secondsIter;
3044 throw std::runtime_error(
"EventList::addPulsetime() called on an event "
3045 "list with no pulse times. You must call this "
3046 "algorithm BEFORE CompressEvents.");
3060 throw std::runtime_error(
"");
3072 throw std::runtime_error(
"EventList::addPulsetime() called on an event "
3073 "list with no pulse times. You must call this "
3074 "algorithm BEFORE CompressEvents.");
3090 if (tofMin >
events.crbegin()->tof())
3092 if (tofMax <
events.cbegin()->tof())
3096 auto it_first = std::lower_bound(
events.begin(),
events.end(), tofMin);
3097 if ((it_first !=
events.end()) && (it_first->tof() < tofMax)) {
3100 auto it_last = std::upper_bound(it_first,
events.end(), T(tofMax));
3102 if (it_first >= it_last) {
3103 throw std::runtime_error(
"Event filter is all messed up");
3106 size_t tmp = std::size_t(std::distance(it_first, it_last));
3109 events.erase(it_first, it_last);
3125 if (tofMax <= tofMin)
3126 throw std::runtime_error(
"EventList::maskTof: tofMax must be > tofMin");
3140 numOrig = this->events->size();
3141 numDel = this->
maskTofHelper(*this->events, tofMin, tofMax);
3153 if (numDel >= numOrig)
3168 auto itm = std::find(mask.begin(), mask.end(),
false);
3169 auto first =
events.begin() + (itm - mask.begin());
3171 if (itm != mask.end()) {
3172 for (
auto ite = first; ++ite !=
events.end() && ++itm != mask.end();) {
3173 if (*itm !=
false) {
3174 *first++ = std::move(*ite);
3179 const auto n =
static_cast<size_t>(
events.end() - first);
3196 throw std::runtime_error(
"EventList::maskTof: tofMax must be > tofMin");
3207 numOrig = this->events->size();
3220 if (numDel >= numOrig)
3232 for (
auto itev =
events.cbegin(); itev !=
events.cend(); ++itev)
3233 tofs.emplace_back(itev->m_tof);
3262 std::vector<double> tofs;
3275 weights.reserve(
events.size());
3276 std::transform(
events.cbegin(),
events.cend(), std::back_inserter(weights),
3277 [](
const auto &event) { return event.weight(); });
3307 std::vector<double> weights;
3320 weightErrors.clear();
3321 weightErrors.reserve(
events.size());
3322 std::transform(
events.cbegin(),
events.cend(), std::back_inserter(weightErrors),
3323 [](
const auto &event) { return event.error(); });
3353 std::vector<double> weightErrors;
3355 return weightErrors;
3363template <
typename UnaryOperation>
3365 std::vector<DateAndTime> times;
3368 times.reserve(
events->size());
3369 std::transform(
events->cbegin(),
events->cend(), std::back_inserter(times), timesCalc);
3388 auto timeCalc = [](
const auto &event) {
return event.pulseTime(); };
3394 auto timeCalc = [](
const auto &event) {
return event.pulseTOFTime(); };
3403 auto timeCalc = [factor, shift](
const auto &event) {
return event.pulseTOFTimeAtSample(factor, shift); };
3410template <
class T>
double getTofMinimumHelper(
const std::vector<T> &events) {
3411 const auto result = std::min_element(events.cbegin(), events.cend(),
3412 [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
3413 return result->tof();
3416template <
class T>
double getTofMaximumHelper(
const std::vector<T> &events) {
3417 const auto result = std::max_element(events.cbegin(), events.cend(),
3418 [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
3419 return result->tof();
3428 double tMin = std::numeric_limits<double>::max();
3438 return this->events->front().tof();
3449 tMin = getTofMinimumHelper(*this->events);
3470 double tMax = std::numeric_limits<double>::lowest();
3480 return this->events->back().tof();
3491 tMax = getTofMaximumHelper(*this->events);
3509template <
class T> DateAndTime getPulseMinimumHelper(
const std::vector<T> &events) {
3510 const auto result = std::min_element(events.cbegin(), events.cend(), [](
const auto &
left,
const auto &
right) {
3511 return left.pulseTime() < right.pulseTime();
3513 return result->pulseTime();
3516template <
class T> DateAndTime getPulseMaximumHelper(
const std::vector<T> &events) {
3517 const auto result = std::max_element(events.cbegin(), events.cend(), [](
const auto &
left,
const auto &
right) {
3518 return left.pulseTime() < right.pulseTime();
3520 return result->pulseTime();
3530 return DateAndTime::maximum();
3536 return this->events->front().pulseTime();
3547 return getPulseMinimumHelper(*this->events);
3554 return DateAndTime::maximum();
3563 return DateAndTime::minimum();
3569 return this->events->back().pulseTime();
3580 return getPulseMaximumHelper(*this->events);
3587 return DateAndTime::minimum();
3591 Mantid::Types::Core::DateAndTime &tMax)
const {
3593 tMax = DateAndTime::minimum();
3594 tMin = DateAndTime::maximum();
3604 tMin = this->events->front().pulseTime();
3605 tMax = this->events->back().pulseTime();
3621 DateAndTime temp = tMax;
3622 for (
size_t i = 0; i <
numEvents; i++) {
3625 temp = this->events->at(i).pulseTime();
3643 DateAndTime tMax = DateAndTime::minimum();
3653 return calculateCorrectedFullTime(this->events->back(), tofFactor, tofOffset);
3655 return calculateCorrectedFullTime(this->
weightedEvents->back(), tofFactor, tofOffset);
3663 DateAndTime temp = tMax;
3664 for (
size_t i = 0; i <
numEvents; i++) {
3667 temp = calculateCorrectedFullTime(this->events->at(i), tofFactor, tofOffset);
3670 temp = calculateCorrectedFullTime(this->
weightedEvents->at(i), tofFactor, tofOffset);
3684 DateAndTime tMin = DateAndTime::maximum();
3694 return calculateCorrectedFullTime(this->events->front(), tofFactor, tofOffset);
3696 return calculateCorrectedFullTime(this->
weightedEvents->front(), tofFactor, tofOffset);
3704 DateAndTime temp = tMin;
3705 for (
size_t i = 0; i <
numEvents; i++) {
3708 temp = calculateCorrectedFullTime(this->events->at(i), tofFactor, tofOffset);
3711 temp = calculateCorrectedFullTime(this->
weightedEvents->at(i), tofFactor, tofOffset);
3733 size_t x_size = tofs.size();
3734 if (
events.size() != x_size)
3737 for (
size_t i = 0; i < x_size; ++i)
3780 auto itev_end =
events.end();
3784 for (
auto itev =
events.begin(); itev != itev_end; itev++) {
3785 itev->m_errorSquared =
static_cast<float>(itev->m_errorSquared * valueSquared);
3786 itev->m_weight *=
static_cast<float>(
value);
3791 for (
auto itev =
events.begin(); itev != itev_end; itev++) {
3792 itev->m_errorSquared =
3793 static_cast<float>(itev->m_errorSquared * valueSquared + errorSquared * itev->m_weight * itev->m_weight);
3794 itev->m_weight *=
static_cast<float>(
value);
3877 std::span<double const> E) {
3879 if ((
X.size() < 2) || (
Y.size() != E.size()) || (
X.size() != 1 +
Y.size())) {
3880 std::stringstream msg;
3881 msg <<
"EventList::multiply() was given invalid size or "
3882 "inconsistent histogram arrays: X["
3884 <<
"Y[" <<
Y.size() <<
" E[" << E.size() <<
"]";
3885 throw std::invalid_argument(msg.str());
3888 size_t x_size =
X.size();
3892 auto itev_end =
events.end();
3895 if (itev == itev_end)
3904 double valueSquared;
3905 double errorSquared;
3909 double tof = itev->tof();
3910 while (bin < x_size - 1) {
3912 if ((tof >=
X[bin]) && (tof <
X[bin + 1]))
3924 while ((itev != itev_end) && (bin < x_size - 1)) {
3926 while (bin < x_size - 1) {
3928 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
3930 itev->m_errorSquared =
3931 static_cast<float>(itev->m_errorSquared * valueSquared + errorSquared * itev->m_weight * itev->m_weight);
3932 itev->m_weight *=
static_cast<float>(
value);
3936 if (bin >= x_size - 1)
4002 std::span<double const> E) {
4004 if ((
X.size() < 2) || (
Y.size() != E.size()) || (
X.size() != 1 +
Y.size())) {
4005 std::stringstream msg;
4006 msg <<
"EventList::divide() was given invalid size or "
4007 "inconsistent histogram arrays: X["
4009 <<
"Y[" <<
Y.size() <<
" E[" << E.size() <<
"]";
4010 throw std::invalid_argument(msg.str());
4013 size_t x_size =
X.size();
4017 auto itev_end =
events.end();
4020 if (itev == itev_end)
4029 double valError_over_value_squared;
4033 double tof = itev->tof();
4034 while (bin < x_size - 1) {
4036 if ((tof >=
X[bin]) && (tof <
X[bin + 1]))
4047 value = std::numeric_limits<float>::quiet_NaN();
4048 valError_over_value_squared = 0;
4053 while ((itev !=
events.end()) && (bin < x_size - 1)) {
4055 while (bin < x_size - 1) {
4057 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
4059 double newWeight = itev->m_weight /
value;
4060 itev->m_errorSquared =
static_cast<float>(
4061 newWeight * newWeight *
4062 ((itev->m_errorSquared / (itev->m_weight * itev->m_weight)) + valError_over_value_squared));
4063 itev->m_weight =
static_cast<float>(newWeight);
4067 if (bin >= x_size - 1)
4076 value = std::numeric_limits<float>::quiet_NaN();
4077 valError_over_value_squared = 0;
4139 throw std::invalid_argument(
"EventList::divide() called with value of 0.0. Cannot divide by zero.");
4156 throw std::invalid_argument(
"EventList::divide() called with value of 0.0. Cannot divide by zero.");
4162 double invValue = 1.0 /
value;
4164 double invError = (
error /
value) * invValue;
4166 this->
multiply(invValue, invError);
4184 if (
this == &output) {
4185 throw std::invalid_argument(
"In-place filtering is not allowed");
4207 throw std::runtime_error(
"EventList::filterByPulseTime() called on an "
4208 "EventList that no longer has time information.");
4236 if ((timeRoi ==
nullptr) || (timeRoi->
useAll())) {
4237 throw std::invalid_argument(
"TimeROI can not use all time");
4240 if (intervals.empty())
4251 throw std::runtime_error(
"EventList::filterByPulseTime() called on an "
4252 "EventList that no longer has time information.");
4266 std::vector<T> &output) {
4267 std::copy_if(
events.begin(),
events.end(), std::back_inserter(output),
4268 [start, stop](
const T &t) { return (t.m_pulsetime >= start) && (t.m_pulsetime < stop); });
4281 auto itspl = intervals.cbegin();
4282 auto itspl_end = intervals.cend();
4284 auto itev =
events.cbegin();
4285 auto itev_end =
events.cend();
4288 while (itspl != itspl_end) {
4290 DateAndTime start = itspl->start();
4291 DateAndTime stop = itspl->stop();
4293 while ((itev != itev_end) && (itev->m_pulsetime < start))
4297 while ((itev != itev_end) && (itev->m_pulsetime < stop)) {
4299 const T eventCopy(*itev);
4307 if (itspl == itspl_end)
4311 if (itev == itev_end)
4322 if (timeRoi ==
nullptr) {
4323 throw std::runtime_error(
"TimeROI can not be a nullptr\n");
4326 throw std::invalid_argument(
"TimeROI can not be empty\n");
4340 throw std::runtime_error(
"EventList::filterInPlace() called on an "
4341 "EventList that no longer has time information.");
4377 auto itspl = splitter.cbegin();
4378 auto itspl_end = splitter.cend();
4379 DateAndTime start, stop;
4382 auto itev =
events.begin();
4383 auto itev_end =
events.end();
4387 auto itOut =
events.begin();
4390 while (itspl != itspl_end) {
4392 start = itspl->start();
4393 stop = itspl->stop();
4395 while ((itev != itev_end) && (itev->m_pulsetime < start))
4399 bool copyingInPlace = (itOut == itev);
4400 if (copyingInPlace) {
4401 while ((itev != itev_end) && (itev->m_pulsetime < stop))
4407 while ((itev != itev_end) && (itev->m_pulsetime < stop)) {
4417 if (itspl == itspl_end)
4421 if (itev == itev_end)
4427 events.resize(std::size_t(std::distance(
events.begin(), itOut)));
4437 bool removeDetIDs{
true};
4442 auto initPartial = [&](
EventList *partial) {
4443 partial->clear(removeDetIDs);
4444 partial->copyInfoFrom(*
this);
4445 partial->setHistogram(histogramLocal);
4446 partial->switchTo(eventTypeLocal);
4450 std::for_each(partials.cbegin(), partials.cend(),
4451 [&](
const std::pair<int, EventList *> &pair) { initPartial(pair.second); });
4502 for (
auto &itev :
events) {
4504 const double tof = fromUnit->
singleToTOF(itev.m_tof);
4520 if (!fromUnit || !toUnit)
4521 throw std::runtime_error(
"EventList::convertUnitsViaTof(): one of the units is NULL!");
4523 throw std::runtime_error(
"EventList::convertUnitsViaTof(): fromUnit is not initialized!");
4525 throw std::runtime_error(
"EventList::convertUnitsViaTof(): toUnit is not initialized!");
4549 for (
auto &event :
events) {
4551 event.m_tof = factor * std::pow(event.m_tof, power);
4582 if (
histogram.xMode() != HistogramData::Histogram::XMode::BinEdges)
4583 throw std::runtime_error(
"EventList: setting histogram with storage mode "
4584 "other than BinEdges is not possible");
4586 throw std::runtime_error(
"EventList: setting histogram data with non-null "
4587 "Y or E data is not possible");
4589 if (
histogram.yMode() == HistogramData::Histogram::YMode::Uninitialized)
4592 throw std::runtime_error(
"EventList: setting histogram data with different "
4593 "YMode is not possible");
4597 throw std::runtime_error(
"EventList: setting Points as X data is not "
4598 "possible, only BinEdges are supported");
4602 throw std::runtime_error(
"EventList: Cannot set Y or E data, these data are "
4603 "generated automatically based on the events");
std::vector< float > m_tof
sum of all time-of-flight within the bin
const std::vector< double > & rhs
double value
The value of the point.
#define PARALLEL_THREAD_NUMBER
#define GNU_DIAG_OFF(x)
This is a collection of macros for turning compiler warnings off in a controlled manner.
IEventList : Interface to Mantid::DataObjects::EventList class, used to expose to PythonAPI.
A "spectrum" is an object that holds the data for a particular spectrum, in particular:
void setHistogram(T &&...data)
Sets the Histogram associated with this spectrum.
void addDetectorIDs(const std::set< detid_t > &detIDs)
Add a set of detector IDs to the set of detector IDs.
const HistogramData::HistogramX & x() const
virtual const HistogramData::HistogramE & e() const
void setDetectorIDs(const std::set< detid_t > &detIDs)
Set the detector IDs to be the set given.
void clearDetectorIDs()
Clear the detector IDs set.
void copyInfoFrom(const ISpectrum &other)
Copy spectrum number and detector IDs, but not X vector, from another ISpectrum.
const HistogramData::HistogramDx & dx() const
Kernel::cow_ptr< HistogramData::HistogramX > sharedX() const
virtual const HistogramData::HistogramY & y() const
const std::set< detid_t > & getDetectorIDs() const
Get a const reference to the detector IDs set.
virtual void copyDataInto(DataObjects::EventList &) const
Override in child classes for polymorphic copying of data.
void setSharedX(const Kernel::cow_ptr< HistogramData::HistogramX > &x) &
HistogramData::HistogramX & mutableX() &
void sortTimeAtSample(const double &tofFactor, const double &tofShift, bool forceResort=false) const
Sort events by time at sample.
size_t getMemorySize() const override
Memory used by this event list.
static void getWeightErrorsHelper(const std::vector< T > &events, std::vector< double > &weightErrors)
Get the weight error member of all events in a list.
void addPulsetimes(const std::vector< double > &seconds) override
Add an offset to the pulsetime (wall-clock time) of each event in the list.
Mantid::Types::Core::DateAndTime getTimeAtSampleMax(const double &tofFactor, const double &tofOffset) const override
Get the maximum time at sample.
std::vector< Types::Core::DateAndTime > getPulseTimes() const override
Get the pulse times of each event in this EventList.
static std::optional< size_t > findLinearBin(std::span< double const > X, const double tof, const double divisor, const double offset, const bool findExact=true)
Find the bin which this TOF value falls in with linear binning, assumes TOF is in range of X.
void setTofs(const MantidVec &tofs) override
Set a list of TOFs to the current event list.
void maskTof(const double tofMin, const double tofMax) override
Mask out events that have a tof between tofMin and tofMax (inclusively).
EventList(const Mantid::API::EventType event_type=Mantid::API::EventType::TOF)
Constructor (empty)
void multiply(const double value, const double error=0.0) override
Multiply the weights in this event list by a scalar variable with an error; though the error can be 0...
void checkWorksWithPoints() const override
HistogramData::CountStandardDeviations countStandardDeviations() const override
void switchToWeightedEvents()
Switch the EventList to use WeightedEvents instead of TofEvent.
static size_t findExactBin(std::span< double const > X, const double tof, const size_t n_bin)
Find the exact bin which a TOF falls in starting from the provided estimated one.
EventList & operator=(const EventList &)
Copy into this event list from another.
void compressFatEvents(const double tolerance, const Types::Core::DateAndTime &timeStart, const double seconds, EventList *destination)
HistogramData::Histogram & mutableHistogramRef() override
void convertUnitsViaTofHelper(typename std::vector< T > &events, Mantid::Kernel::Unit const *fromUnit, Mantid::Kernel::Unit const *toUnit)
Helper function for the conversion to TOF.
static void histogramForWeightsHelper(const std::vector< T > &events, std::span< double const > X, MantidVec &Y, MantidVec &E)
Generates both the Y and E (error) histograms for an EventList with WeightedEvents.
HistogramData::Counts counts() const override
std::vector< double > getWeights() const override
Return the list of event weight values.
void convertUnitsQuickly(const double &factor, const double &power)
Convert the event's TOF (x) value according to a simple output = a * (input^b) relationship.
void compressEvents(double tolerance, EventList *destination)
Compress the event list by grouping events with the same TOF (within a given tolerance).
double getTofMax() const override
static void filterByTimeROIHelper(std::vector< T > &events, const std::vector< Kernel::TimeInterval > &intervals, EventList *output)
Filter a vector of events into another based on TimeROI.
virtual size_t histogram_size() const
Return the size of the histogram data.
HistogramData::Histogram histogram() const override
Returns the Histogram associated with this spectrum.
~EventList() override
Destructor.
std::vector< Types::Event::TofEvent > & getEvents()
Return the list of TofEvents contained.
HistogramData::FrequencyStandardDeviations frequencyStandardDeviations() const override
void setSortOrder(const EventSortType order) const
Manually set the event list sort order value.
static void processWeightedEvents(const std::vector< T > &events, std::vector< WeightedEventNoTime > &out, const std::shared_ptr< std::vector< double > > histogram_bin_edges, struct FindBin findBin)
HistogramData::Histogram m_histogram
Histogram object holding the histogram data. Currently only X.
void generateCountsHistogramPulseTime(const double &xMin, const double &xMax, MantidVec &Y, const double TofMin=std::numeric_limits< double >::lowest(), const double TofMax=std::numeric_limits< double >::max()) const
With respect to PulseTime fill a histogram given equal histogram bins.
double getTofMin() const override
static void compressEventsHelper(const std::vector< T > &events, std::vector< WeightedEventNoTime > &out, double tolerance)
Compress the event list by grouping events with the same TOF.
Mantid::API::EventType eventType
What type of event is in our list.
EventSortType getSortType() const
Return the type of sorting used in this event list.
void switchToWeightedEventsNoTime()
Switch the EventList to use WeightedEventNoTime's instead of TofEvent.
static void setTofsHelper(std::vector< T > &events, const std::vector< double > &tofs)
Set a list of TOFs to the current event list.
void addTof(const double offset) override
Add an offset to the TOF of each event in the list.
bool equals(const EventList &rhs, const double tolTof, const double tolWeight, const int64_t tolPulse) const
Kernel::cow_ptr< HistogramData::HistogramE > sharedE() const override
static std::size_t maskConditionHelper(std::vector< T > &events, const std::vector< bool > &mask)
Mask out events by the condition vector.
EventList & operator/=(const double value)
Operator to divide the weights in this EventList by an error-less scalar.
void checkAndSanitizeHistogram(HistogramData::Histogram &histogram) override
void copyDataInto(EventList &sink) const override
Used by copyDataFrom for dynamic dispatch for its source.
const HistogramData::HistogramY & y() const override
HistogramData::Frequencies frequencies() const override
void filterInPlace(const Kernel::TimeROI *timeRoi)
Use a SplittingIntervalVec to filter the event list in place.
std::size_t getNumberEvents() const override
Return the number of events in the list.
Mantid::API::EventType getEventType() const override
Return the type of Event vector contained within.
const MantidVec & readDx() const override
Deprecated, use dx() instead.
void scaleTof(const double factor) override
Convert the units in the TofEvent's m_tof field to some other value, by scaling by a multiplier.
void getPulseTimeMinMax(Mantid::Types::Core::DateAndTime &tMin, Mantid::Types::Core::DateAndTime &tM) const
static void multiplyHelper(std::vector< T > &events, const double value, const double error=0.0)
Helper method for multiplying an event list by a scalar value with/without error.
HistogramData::FrequencyVariances frequencyVariances() const override
std::vector< WeightedEventNoTime > & getWeightedEventsNoTime()
Return the list of WeightedEvent contained.
void setMRU(EventWorkspaceMRU *newMRU)
Sets the MRU list for this event list.
EventWorkspaceMRU * mru
MRU lists of the parent EventWorkspace.
void convertUnitsViaTof(Mantid::Kernel::Unit const *fromUnit, Mantid::Kernel::Unit const *toUnit)
Converts the X units in each event by going through TOF.
static void integrateHelper(std::vector< T > &events, const double minX, const double maxX, const bool entireRange, double &sum, double &error)
Integrate the events between a range of X values, or all events.
Mantid::Types::Core::DateAndTime getPulseTimeMax() const override
Kernel::cow_ptr< HistogramData::HistogramX > ptrX() const override
Deprecated, use sharedX() instead. Returns a pointer to the x data.
void generateHistogram(std::span< double const > X, MantidVec &Y, MantidVec &E, bool skipError=false) const override
Generates both the Y and E (error) histograms w.r.t TOF for an EventList with or without WeightedEven...
static void createWeightedEvents(std::vector< WeightedEventNoTime > &out, const std::vector< double > &tof, const std::vector< T > &weight, const std::vector< T > &error)
MantidVec & dataX() override
Deprecated, use mutableX() instead.
void generateCountsHistogram(std::span< double const > X, MantidVec &Y) const
Fill a histogram given specified histogram bounds.
void generateHistogramPulseTime(std::span< double const > X, MantidVec &Y, MantidVec &E, bool skipError=false) const override
Generates both the Y and E (error) histograms w.r.t Pulse Time for an EventList with or without Weigh...
void clearUnused()
Clear any unused event lists (the ones that do not match the currently used type).
MantidVec & dataDx() override
Deprecated, use mutableDx() instead.
bool operator==(const EventList &rhs) const
Equality operator between EventList's.
void generateCountsHistogramTimeAtSample(std::span< double const > X, MantidVec &Y, const double &tofFactor, const double &tofOffset) const
With respect to Time at Sample, fill a histogram given specified histogram bounds.
EventSortType order
Last sorting order.
static void divideHistogramHelper(std::vector< T > &events, std::span< double const > X, std::span< double const > Y, std::span< double const > E)
Helper method for dividing an event list by a histogram with error.
void convertTofHelper(std::vector< T > &events, const std::function< double(double)> &func)
void generateHistogramTimeAtSample(std::span< double const > X, MantidVec &Y, MantidVec &E, const double &tofFactor, const double &tofOffset, bool skipError=false) const override
Generates both the Y and E (error) histograms w.r.t Time at sample position.
void clearData() override
Mask the spectrum to this value. Removes all events.
EventList & operator+=(const Types::Event::TofEvent &event)
Append an event to the histogram.
static void minusHelper(std::vector< T1 > &events, const std::vector< T2 > &more_events)
SUBTRACT another EventList from this event list.
void addPulsetimesHelper(std::vector< T > &events, const std::vector< double > &seconds)
Add an offset per event to the pulsetime (wall-clock time) of each event in the list.
static std::optional< size_t > findLogBin(std::span< double const > X, const double tof, const double divisor, const double offset, const bool findExact=true)
Find the bin which this TOF value falls in with log binning, assumes TOF is in range of X.
void addPulsetime(const double seconds) override
Add an offset to the pulsetime (wall-clock time) of each event in the list.
HistogramData::Histogram getHistogram() const
Returns a copy of the Histogram associated with this spectrum.
void reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
void setX(const Kernel::cow_ptr< HistogramData::HistogramX > &X) override
Deprecated, use setSharedX() instead.
std::vector< double > getWeightErrors() const override
Return the list of event weight error values.
void sortTof() const
Sort events by TOF in one thread.
HistogramData::CountVariances countVariances() const override
MantidVec & dataE() override
Deprecated, use mutableE() instead.
static void compressFatEventsHelper(const std::vector< T > &events, std::vector< WeightedEvent > &out, const double tolerance, const Mantid::Types::Core::DateAndTime &timeStart, const double seconds)
MantidVec & dataY() override
Deprecated, use mutableY() instead.
Mantid::Types::Core::DateAndTime getTimeAtSampleMin(const double &tofFactor, const double &tofOffset) const override
Get the minimum time at sample.
const HistogramData::HistogramE & e() const override
std::vector< Types::Core::DateAndTime > getPulseTOFTimes() const
Get the Pulse-time + TOF for each event in this EventList.
bool isSortedByTof() const override
Return true if the event list is sorted by TOF.
bool operator!=(const EventList &rhs) const
Inequality comparator.
std::mutex m_sortMutex
Mutex that is locked while sorting an event list.
static void filterByPulseTimeHelper(std::vector< T > &events, Types::Core::DateAndTime start, Types::Core::DateAndTime stop, std::vector< T > &output)
std::unique_ptr< std::vector< WeightedEvent > > weightedEvents
List of WeightedEvent's.
void initializePartials(std::map< int, EventList * > partials) const
Initialize the detector ID's and event type of the destination event lists when splitting this list.
void reverse()
Reverse the histogram boundaries and the associated events if they are sorted by time-of-flight.
std::vector< Types::Core::DateAndTime > eventTimesCalculator(const UnaryOperation ×Calc) const
Compute a time (for instance, pulse-time plus TOF) associated to each event in the list.
void switchTo(Mantid::API::EventType newType) override
Switch the EventList to use the given EventType (TOF, WEIGHTED, or WEIGHTED_NOTIME)
void filterInPlaceHelper(Kernel::TimeROI const *timeRoi, typename std::vector< T > &events)
Perform an in-place filtering on a vector of either TofEvent's or WeightedEvent's.
bool empty() const
Much like stl containers, returns true if there is nothing in the event list.
const MantidVec & readX() const override
Deprecated, use x() instead. Returns the x data const.
WeightedEvent getEvent(size_t event_number)
Return the given event in the list.
void integrate(const double minX, const double maxX, const bool entireRange, double &sum, double &error) const
Integrate the events between a range of X values, or all events.
Kernel::cow_ptr< HistogramData::HistogramY > sharedY() const override
void createFromHistogram(const ISpectrum *inSpec, bool GenerateZeros, bool GenerateMultipleEvents, int MaxEventsPerBin)
Create an EventList from a histogram.
void convertUnitsQuicklyHelper(typename std::vector< T > &events, const double &factor, const double &power)
Convert the event's TOF (x) value according to a simple output = a * (input^b) relationship.
MantidVec * makeDataE() const
Calculates and returns a pointer to the E histogrammed data.
void checkIsYAndEWritable() const override
void sortPulseTimeTOF() const
void copyDataFrom(const ISpectrum &source) override
Copy data from another EventList, via ISpectrum reference.
void filterByPulseTime(Types::Core::DateAndTime start, Types::Core::DateAndTime stop, EventList &output) const
Filter this EventList into an output EventList, using keeping only events within the >= start and < e...
void addPulsetimeHelper(std::vector< T > &events, const double seconds)
Add an offset to the pulsetime (wall-clock time) of each event in the list.
std::vector< double > getTofs() const override
Get the times-of-flight of each event in this EventList.
static void multiplyHistogramHelper(std::vector< T > &events, std::span< double const > X, std::span< double const > Y, std::span< double const > E)
Helper method for multiplying an event list by a histogram with error.
EventList & operator*=(const double value)
Operator to multiply the weights in this EventList by an error-less scalar.
void convertTof(std::function< double(double)> func, const int sorting=0) override
Mantid::Types::Core::DateAndTime getPulseTimeMin() const override
std::unique_ptr< std::vector< WeightedEventNoTime > > weightedEventsNoTime
List of WeightedEvent's.
static void getWeightsHelper(const std::vector< T > &events, std::vector< double > &weights)
Get the weight member of all events in a list.
void maskCondition(const std::vector< bool > &mask) override
Mask out events by the condition vector.
void sortPulseTime() const
Sort events by Frame.
std::vector< T >::const_iterator findFirstTimeAtSampleEvent(const std::vector< T > &events, const double seek_time, const double &tofFactor, const double &tofOffset) const
Utility function: Returns the iterator into events of the first TofEvent with time at sample > seek_t...
void sortPulseTimeTOFDelta(const Types::Core::DateAndTime &start, const double seconds) const
Sort by the pulse time with a tolerance.
static std::size_t maskTofHelper(std::vector< T > &events, const double tofMin, const double tofMax)
Mask out events that have a tof between tofMin and tofMax (inclusively).
void addEventQuickly(const Types::Event::TofEvent &event)
Append an event to the histogram, without clearing the cache, to make it faster.
static std::vector< T >::const_iterator findFirstPulseEvent(const std::vector< T > &events, const double seek_pulsetime)
Utility function: Returns the iterator into events of the first TofEvent with pulsetime() > seek_puls...
std::vector< Types::Core::DateAndTime > getPulseTOFTimesAtSample(const double &factor, const double &shift) const
Get the Pulse-time + time-of-flight of the neutron up to the sample, for each event in this EventList...
void generateErrorsHistogram(std::span< double const > Y, MantidVec &E) const
Generate the Error histogram for the provided counts histogram.
EventList & operator-=(const EventList &more_events)
SUBTRACT another EventList from this event list.
void sort(const EventSortType order) const
Sort events by TOF or Frame.
MantidVec * makeDataY() const
Calculates and returns a pointer to the Y histogrammed data.
std::unique_ptr< std::vector< Types::Event::TofEvent > > events
List of TofEvent (no weights).
static void getTofsHelper(const std::vector< T > &events, std::vector< double > &tofs)
Get the m_tof member of all events in a list.
void clear(const bool removeDetIDs=true) override
Clear the list of events and any associated detector ID's.
std::vector< WeightedEvent > & getWeightedEvents()
Return the list of WeightedEvent contained.
void divide(const double value, const double error=0.0) override
Divide the weights in this event list by a scalar with an (optional) error.
This is a container for the MRU (most-recently-used) list of generated histograms.
void insertY(size_t thread_num, YType data, const EventList *index)
Insert a new histogram into the MRU.
EType findE(size_t thread_num, const EventList *index)
Find a Y histogram in the MRU.
void insertE(size_t thread_num, EType data, const EventList *index)
Insert a new histogram into the MRU.
void ensureEnoughBuffersE(size_t thread_num) const
This function makes sure that there are enough data buffers (MRU's) for E for the number of threads r...
YType findY(size_t thread_num, const EventList *index)
Find a Y histogram in the MRU.
void deleteIndex(const EventList *index)
Delete any entries in the MRU at the given index.
void ensureEnoughBuffersY(size_t thread_num) const
This function makes sure that there are enough data buffers (MRU's) for Y for the number of threads r...
1D histogram implementation.
Info about a single neutron detection event, including a weight and error value, but excluding the pu...
Info about a single neutron detection event, including a weight and error value:
TimeROI : Object that holds information about when the time measurement was active.
const std::vector< Kernel::TimeInterval > toTimeIntervals() const
This method is to lend itself to helping with transition.
bool useAll() const
TimeROI selects all time to be used.
The base units (abstract) class.
virtual double singleToTOF(const double x) const =0
Convert a single X value to TOF.
virtual double singleFromTOF(const double tof) const =0
Convert a single tof value to this unit.
bool isInitialized() const
Implements a copy on write data template.
EventType
What kind of event list is being stored.
std::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix)
Get the number of events in the currently opened group.
bool compareEventPulseTime(const TofEvent &e1, const TofEvent &e2)
Compare two events' FRAME id, return true if e1 should be before e2.
MANTID_DATAOBJECTS_DLL void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
static std::vector< T >::const_iterator findFirstEvent(const std::vector< T > &events, T seek_tof)
Utility function: Returns the iterator into events of the first TofEvent with tof() > seek_tof Will r...
EventSortType
How the event list is sorted.
@ PULSETIMETOF_DELTA_SORT
bool compareEventPulseTimeTOF(const TofEvent &e1, const TofEvent &e2)
Compare two events' FRAME id, return true if e1 should be before e2.
MANTID_KERNEL_DLL Types::Core::DateAndTime averageSorted(const std::vector< Types::Core::DateAndTime > ×)
averageSorted Assuming that the vector is sorted, find the average time
Helper class which provides the Collimation Length for SANS instruments.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
int32_t specnum_t
Typedef for a spectrum Number.
std::optional< size_t > operator()(std::span< double const > X, const double tof, const bool findExact)
FindBin(double step, double xmin)
std::optional< size_t >(* findBin)(std::span< double const >, const double, const double, const double, const bool)
bool operator()(const TofEvent &e1, const TofEvent &e2)
comparePulseTimeTOFDelta(const Types::Core::DateAndTime &start, const double seconds)