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();
1469 return histogram().countStandardDeviations();
1477 return histogram().frequencyStandardDeviations();
1482 throw std::runtime_error(
"'EventList::y()' called with no MRU set. This is not allowed.");
1488 throw std::runtime_error(
"'EventList::e()' called with no MRU set. This is not allowed.");
1501 yData =
mru->
findY(
static_cast<size_t>(thread),
this);
1510 yData = Kernel::make_cow<HistogramData::HistogramY>(std::move(
Y));
1515 auto eData = Kernel::make_cow<HistogramData::HistogramE>(std::move(E));
1539 eData = Kernel::make_cow<HistogramData::HistogramE>(std::move(E));
1554 throw std::runtime_error(
"'EventList::dataY()' called with no MRU set. This is not allowed.");
1568 throw std::runtime_error(
"'EventList::dataE()' called with no MRU set. This is not allowed.");
1576inline double calcNorm(
const double errorSquared) {
1577 if (errorSquared == 0.)
1579 else if (errorSquared == 1.)
1582 return 1. / std::sqrt(errorSquared);
1601 out.reserve(
events.size() / 20);
1604 double lastTof =
events.front().m_tof;
1606 double totalTof = 0;
1610 double errorSquared = 0;
1611 double normalization = 0.;
1613 double bin_end = lastTof;
1614 std::function<bool(
const double,
const double)> compareTof;
1615 std::function<double(
const double,
double)> next_bin;
1619 throw std::runtime_error(
"compressEvents with log binning doesn't work with negative TOF");
1625 compareTof = [](
const double lhs,
const double rhs) {
return lhs <
rhs; };
1626 next_bin = [
tolerance](
const double lastTof,
double bin_end) {
1628 while (lastTof >= bin_end)
1634 compareTof = [](
const double lhs,
const double rhs) {
return lhs <=
rhs; };
1635 next_bin = [
tolerance](
const double lastTof, double) {
return lastTof +
tolerance; };
1639 bin_end = next_bin(lastTof, bin_end);
1641 for (
auto it =
events.cbegin(); it !=
events.cend(); it++) {
1642 if (compareTof(it->m_tof, bin_end)) {
1644 weight += it->weight();
1645 errorSquared += it->errorSquared();
1648 const double norm = calcNorm(it->errorSquared());
1649 normalization += norm;
1650 totalTof += it->m_tof * norm;
1657 out.emplace_back(lastTof, weight, errorSquared);
1658 }
else if (num > 1) {
1659 out.emplace_back(totalTof / normalization, weight, errorSquared);
1663 const double norm = calcNorm(it->errorSquared());
1664 normalization = norm;
1665 totalTof = it->m_tof * norm;
1666 weight = it->weight();
1667 errorSquared = it->errorSquared();
1668 lastTof = it->m_tof;
1670 bin_end = next_bin(lastTof, bin_end);
1678 out.emplace_back(lastTof, weight, errorSquared);
1679 }
else if (num > 1) {
1680 out.emplace_back(totalTof / normalization, weight, errorSquared);
1684 size_t excess_limit = out.size() / 20;
1685 if ((out.capacity() - out.size()) > excess_limit) {
1686 out.shrink_to_fit();
1692 const double tolerance,
const Types::Core::DateAndTime &timeStart,
1693 const double seconds) {
1697 out.reserve(
events.size() / 20);
1700 double lastTof =
events.front().m_tof;
1702 double totalTof = 0;
1706 const int64_t pulsetimeStart = timeStart.totalNanoseconds();
1707 const auto pulsetimeDelta =
static_cast<int64_t
>(seconds * SEC_TO_NANO);
1710 std::vector<DateAndTime> pulsetimes;
1711 std::vector<double> pulsetimeWeights;
1715 double errorSquared = 0.;
1716 double tofNormalization = 0.;
1721 auto it =
events.cbegin();
1722 for (; it !=
events.cend(); ++it) {
1723 if (it->m_pulsetime >= timeStart)
1728 throw std::runtime_error(
"failed to find first pulse time in the events");
1731 int64_t lastPulseBin = (it->m_pulsetime.totalNanoseconds() - pulsetimeStart) / pulsetimeDelta;
1733 double bin_end = lastTof;
1735 std::function<bool(
const double,
const double)> compareTof;
1736 std::function<double(
const double,
double)> next_bin;
1740 compareTof = [](
const double lhs,
const double rhs) {
return lhs <
rhs; };
1741 next_bin = [
tolerance](
const double lastTof,
double bin_end) {
1743 while (lastTof >= bin_end)
1749 const auto event_min = std::min_element(
1750 events.cbegin(),
events.cend(), [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
1751 bin_end = tof_min = event_min->tof();
1754 throw std::runtime_error(
"compressEvents with log binning doesn't work with negative TOF");
1762 compareTof = [](
const double lhs,
const double rhs) {
return lhs <=
rhs; };
1763 next_bin = [
tolerance](
const double lastTof, double) {
return lastTof +
tolerance; };
1767 bin_end = next_bin(lastTof, bin_end);
1770 for (; it !=
events.cend(); ++it) {
1771 const int64_t eventPulseBin = (it->m_pulsetime.totalNanoseconds() - pulsetimeStart) / pulsetimeDelta;
1772 if ((eventPulseBin <= lastPulseBin) && compareTof(it->m_tof, bin_end)) {
1774 weight += it->weight();
1775 errorSquared += it->errorSquared();
1776 double norm = calcNorm(it->errorSquared());
1777 tofNormalization += norm;
1779 totalTof += it->m_tof * norm;
1781 pulsetimes.emplace_back(it->m_pulsetime);
1782 pulsetimeWeights.emplace_back(norm);
1785 if (!pulsetimes.empty()) {
1788 if (pulsetimes.size() == 1) {
1789 out.emplace_back(lastTof, pulsetimes.front(), weight, errorSquared);
1791 out.emplace_back(totalTof / tofNormalization,
1796 if (
tolerance < 0 && eventPulseBin != lastPulseBin)
1801 double norm = calcNorm(it->errorSquared());
1802 totalTof = it->m_tof * norm;
1803 weight = it->weight();
1804 errorSquared = it->errorSquared();
1805 tofNormalization = norm;
1806 lastTof = it->m_tof;
1807 lastPulseBin = eventPulseBin;
1809 pulsetimes.emplace_back(it->m_pulsetime);
1810 pulsetimeWeights.clear();
1811 pulsetimeWeights.emplace_back(norm);
1813 bin_end = next_bin(lastTof, bin_end);
1818 if (!pulsetimes.empty()) {
1821 if (pulsetimes.size() == 1) {
1822 out.emplace_back(lastTof, pulsetimes.front(), weight, errorSquared);
1824 out.emplace_back(totalTof / tofNormalization,
1830 size_t excess_limit = out.size() / 20;
1831 if ((out.capacity() - out.size()) > excess_limit) {
1832 out.shrink_to_fit();
1847 if (this->
empty()) {
1874 if (destination ==
this) {
1876 auto out = std::make_unique<std::vector<WeightedEventNoTime>>();
1906 const std::vector<T> &weight,
const std::vector<T> &
error) {
1908 for (
size_t i = 0; i < weight.size(); ++i) {
1909 const auto errors =
static_cast<float>(
error[i]);
1911 out.emplace_back(tof[i],
static_cast<float>(weight[i]), errors);
1917 const std::shared_ptr<std::vector<double>> histogram_bin_edges,
1919 const auto NUM_BINS = histogram_bin_edges->size() - 1;
1920 std::vector<double> tof(NUM_BINS, 0.);
1921 std::vector<double> normalization(NUM_BINS, 0.);
1922 std::vector<float> weight(NUM_BINS, 0.);
1923 std::vector<float>
error(NUM_BINS, 0.);
1924 for (
const auto &ev :
events) {
1925 const auto &bin_optional = findBin(*histogram_bin_edges.get(), ev.m_tof,
false);
1927 const auto bin = bin_optional.value();
1928 const double norm = calcNorm(ev.m_errorSquared);
1929 tof[bin] += ev.m_tof * norm;
1930 normalization[bin] += norm;
1931 weight[bin] += ev.m_weight;
1932 error[bin] += ev.m_errorSquared;
1937 std::transform(tof.begin(), tof.end(), normalization.begin(), tof.begin(), std::divides<double>());
1943 const std::shared_ptr<std::vector<double>> histogram_bin_edges) {
1944 if (this->
empty()) {
1949 const auto NUM_BINS = histogram_bin_edges->size() - 1;
1950 const auto xmin =
static_cast<double>(histogram_bin_edges->front());
1956 std::vector<double> tof(NUM_BINS, 0);
1957 std::vector<uint32_t>
count(NUM_BINS, 0);
1958 for (
const auto &ev : *this->
events) {
1959 const auto &bin_optional = findBin(*histogram_bin_edges.get(), ev.m_tof,
false);
1961 const auto bin = bin_optional.value();
1963 tof[bin] += ev.m_tof;
1968 std::transform(tof.begin(), tof.end(),
count.begin(), tof.begin(), std::divides<double>());
1981 if (destination ==
this) {
1983 auto out = std::make_unique<std::vector<WeightedEventNoTime>>();
2005 const double seconds,
EventList *destination) {
2006 if (this->
empty()) {
2009 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2013 throw std::invalid_argument(
"Cannot compress events that do not have pulsetime");
2016 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2021 if (destination ==
this) {
2023 auto out = std::make_unique<std::vector<WeightedEvent>>();
2028 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2053typename std::vector<T>::const_iterator
static findFirstEvent(
const std::vector<T> &events, T seek_tof) {
2054 return std::find_if_not(events.cbegin(), events.cend(), [seek_tof](
const T &
x) { return x < seek_tof; });
2069 const double seek_pulsetime) {
2070 auto itev =
events.cbegin();
2071 auto itev_end =
events.cend();
2074 while ((itev != itev_end) && (
static_cast<double>(itev->pulseTime().totalNanoseconds()) < seek_pulsetime))
2095typename std::vector<T>::const_iterator
2097 const double &tofOffset)
const {
2098 auto itev =
events.cbegin();
2099 auto itev_end =
events.cend();
2102 while ((itev != itev_end) &&
2103 (
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset)) < seek_time))
2120template <
class T>
typename std::vector<T>::iterator
static findFirstEvent(std::vector<T> &events, T seek_tof) {
2121 return std::find_if_not(events.begin(), events.end(), [seek_tof](
const T &
x) { return x < seek_tof; });
2138 size_t x_size =
X.size();
2147 bool mustFill = (
Y.size() == x_size - 1);
2149 Y.resize(x_size - 1, 0.0);
2152 E.resize(x_size - 1, 0.0);
2156 std::fill(
Y.begin(),
Y.end(), 0.0);
2157 std::fill(E.begin(), E.end(), 0.0);
2167 auto itev_end =
events.cend();
2170 if (itev == itev_end)
2177 double tof = itev->tof();
2178 while (bin < x_size - 1) {
2180 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
2183 Y[bin] += double(itev->m_weight);
2184 E[bin] += double(itev->m_errorSquared);
2193 while ((itev != itev_end) && (bin < x_size - 1)) {
2195 while (bin < x_size - 1) {
2199 if (tof <
X[bin + 1]) {
2202 Y[bin] += double(itev->m_weight);
2203 E[bin] += double(itev->m_errorSquared);
2213 std::transform(E.cbegin(), E.cend(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2233 size_t x_size =
X.size();
2242 bool mustFill = (
Y.size() == x_size - 1);
2243 Y.resize(x_size - 1, 0.0);
2244 E.resize(x_size - 1, 0.0);
2247 std::fill(
Y.begin(),
Y.end(), 0.0);
2248 std::fill(E.begin(), E.end(), 0.0);
2254 const auto xmin =
X.front();
2255 const auto xmax =
X.back();
2257 auto findBin =
FindBin(step, xmin);
2259 for (
const T &ev :
events) {
2260 const double tof = ev.tof();
2261 if (tof < xmin || tof >= xmax)
2264 std::optional<size_t> n_bin = findBin(
X, tof,
true);
2267 Y[n_bin.value()] += ev.weight();
2268 E[n_bin.value()] += ev.errorSquared();
2273 std::transform(E.cbegin(), E.cend(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2287 bool skipError)
const {
2300 throw std::runtime_error(
"Cannot histogram by pulse time on Weighted "
2301 "Events currently");
2304 throw std::runtime_error(
"Cannot histogram by pulse time on Weighted Events NoTime");
2320 const double &tofFactor,
const double &tofOffset,
bool skipError)
const {
2333 throw std::runtime_error(
"Cannot histogram by time at sample on Weighted "
2334 "Events currently");
2337 throw std::runtime_error(
"Cannot histogram by time at sample on Weighted Events NoTime");
2390 bool skipError)
const {
2421 size_t x_size =
X.size();
2432 Y.resize(x_size - 1, 0);
2437 if (!this->
events->empty()) {
2440 auto itev_end =
events->cend();
2443 if (itev == itev_end)
2451 double pulsetime =
static_cast<double>(itev->pulseTime().totalNanoseconds());
2452 while (bin < x_size - 1) {
2454 if ((pulsetime >=
X[bin]) && (pulsetime <
X[bin + 1])) {
2464 while ((itev != itev_end) && (bin < x_size - 1)) {
2465 pulsetime =
static_cast<double>(itev->pulseTime().totalNanoseconds());
2466 while (bin < x_size - 1) {
2468 if ((pulsetime >=
X[bin]) && (pulsetime <
X[bin + 1])) {
2494 const double TOF_min,
const double TOF_max)
const {
2496 if (this->
events->empty())
2499 size_t nBins =
Y.size();
2504 double step = (xMax - xMin) /
static_cast<double>(nBins);
2506 for (
const TofEvent &ev : *this->
events) {
2507 double pulsetime =
static_cast<double>(ev.pulseTime().totalNanoseconds());
2508 if (pulsetime < xMin || pulsetime >= xMax)
2510 if (ev.tof() < TOF_min || ev.tof() >= TOF_max)
2513 auto n_bin =
static_cast<size_t>((pulsetime - xMin) / step);
2528 const double &tofOffset)
const {
2530 const size_t x_size =
X.size();
2541 Y.resize(x_size - 1, 0);
2546 if (!this->
events->empty()) {
2549 std::vector<TofEvent>::const_iterator itev_end =
events->end();
2552 if (itev == itev_end)
2558 auto tAtSample =
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset));
2559 while (bin < x_size - 1) {
2561 if ((tAtSample >=
X[bin]) && (tAtSample <
X[bin + 1])) {
2571 while ((itev != itev_end) && (bin < x_size - 1)) {
2572 tAtSample =
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset));
2573 while (bin < x_size - 1) {
2575 if ((tAtSample >=
X[bin]) && (tAtSample <
X[bin + 1])) {
2594 size_t x_size =
X.size();
2605 Y.resize(x_size - 1, 0);
2611 if (!this->
events->empty()) {
2615 const auto itend = this->
events->end();
2617 for (
auto itx =
X.begin(); itev != itend; ++itev) {
2618 const double tof = itev->tof();
2619 itx = std::find_if(itx,
X.end(), [tof](
const double x) { return tof < x; });
2620 if (itx ==
X.end()) {
2623 const auto bin =
static_cast<size_t>(std::max(std::distance(
X.begin(), itx) - 1, std::ptrdiff_t{0}));
2640 const double offset,
const bool findExact) {
2641 const auto bin =
static_cast<size_t>(tof * divisor - offset);
2642 if (bin >=
X.size())
2643 return std::nullopt;
2669 const double offset,
const bool findExact) {
2670 const auto bin =
static_cast<size_t>(log(tof) * divisor - offset);
2671 if (bin >=
X.size())
2672 return std::nullopt;
2688 auto tof_of_bin =
X.begin() + n_bin;
2689 if (tof < *tof_of_bin)
2690 return std::move(n_bin - 1);
2694 if (tof >= *tof_of_bin)
2695 return std::move(n_bin + 1);
2698 return std::move(n_bin);
2714 size_t x_size =
X.size();
2723 bool mustFill = (
Y.size() == x_size - 1);
2725 Y.resize(x_size - 1, 0);
2727 std::fill(
Y.begin(),
Y.end(), 0.0);
2730 if (this->
events->empty())
2733 const auto xmin =
X.front();
2734 const auto xmax =
X.back();
2736 auto findBin =
FindBin(step, xmin);
2738 for (
const TofEvent &ev : *this->
events) {
2739 const double tof = ev.tof();
2740 if (tof < xmin || tof >= xmax)
2743 const std::optional<size_t> n_bin = findBin(
X, tof,
true);
2760 E.resize(
Y.size(), 0);
2763 std::transform(
Y.begin(),
Y.end(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2779 double &sum,
double &
error) {
2787 auto lowit =
events.cbegin();
2788 auto highit =
events.cend();
2797 if (lowit->tof() < minX)
2798 lowit = std::lower_bound(
events.cbegin(),
events.cend(), minX);
2800 if ((highit - 1)->tof() > maxX) {
2801 highit = std::upper_bound(lowit,
events.cend(), T(maxX));
2806 for (
auto it = lowit; it != highit; ++it) {
2807 sum += it->weight();
2808 error += it->errorSquared();
2823 double sum(0),
error(0);
2838 double &
error)
const {
2858 throw std::runtime_error(
"EventList: invalid event type value was found.");
2879 transform(
x.cbegin(),
x.cend(),
x.begin(), func);
2912 ev.m_tof = func(ev.m_tof);
2958 for (
auto &event :
events) {
2959 event.m_tof =
event.m_tof * factor + offset;
2987 for (
auto &event :
events) {
2988 event.m_pulsetime += seconds;
2999 auto eventIterEnd{
events.end()};
3000 auto secondsIter{seconds.cbegin()};
3001 for (
auto eventIter =
events.begin(); eventIter < eventIterEnd; ++eventIter, ++secondsIter) {
3002 eventIter->m_pulsetime += *secondsIter;
3024 throw std::runtime_error(
"EventList::addPulsetime() called on an event "
3025 "list with no pulse times. You must call this "
3026 "algorithm BEFORE CompressEvents.");
3040 throw std::runtime_error(
"");
3052 throw std::runtime_error(
"EventList::addPulsetime() called on an event "
3053 "list with no pulse times. You must call this "
3054 "algorithm BEFORE CompressEvents.");
3070 if (tofMin >
events.crbegin()->tof())
3072 if (tofMax <
events.cbegin()->tof())
3076 auto it_first = std::lower_bound(
events.begin(),
events.end(), tofMin);
3077 if ((it_first !=
events.end()) && (it_first->tof() < tofMax)) {
3080 auto it_last = std::upper_bound(it_first,
events.end(), T(tofMax));
3082 if (it_first >= it_last) {
3083 throw std::runtime_error(
"Event filter is all messed up");
3086 size_t tmp = std::size_t(std::distance(it_first, it_last));
3089 events.erase(it_first, it_last);
3105 if (tofMax <= tofMin)
3106 throw std::runtime_error(
"EventList::maskTof: tofMax must be > tofMin");
3120 numOrig = this->events->size();
3121 numDel = this->
maskTofHelper(*this->events, tofMin, tofMax);
3133 if (numDel >= numOrig)
3148 auto itm = std::find(mask.begin(), mask.end(),
false);
3149 auto first =
events.begin() + (itm - mask.begin());
3151 if (itm != mask.end()) {
3152 for (
auto ite = first; ++ite !=
events.end() && ++itm != mask.end();) {
3153 if (*itm !=
false) {
3154 *first++ = std::move(*ite);
3159 const auto n =
static_cast<size_t>(
events.end() - first);
3176 throw std::runtime_error(
"EventList::maskTof: tofMax must be > tofMin");
3187 numOrig = this->events->size();
3200 if (numDel >= numOrig)
3212 for (
auto itev =
events.cbegin(); itev !=
events.cend(); ++itev)
3213 tofs.emplace_back(itev->m_tof);
3242 std::vector<double> tofs;
3255 weights.reserve(
events.size());
3256 std::transform(
events.cbegin(),
events.cend(), std::back_inserter(weights),
3257 [](
const auto &event) { return event.weight(); });
3287 std::vector<double> weights;
3300 weightErrors.clear();
3301 weightErrors.reserve(
events.size());
3302 std::transform(
events.cbegin(),
events.cend(), std::back_inserter(weightErrors),
3303 [](
const auto &event) { return event.error(); });
3333 std::vector<double> weightErrors;
3335 return weightErrors;
3343template <
typename UnaryOperation>
3345 std::vector<DateAndTime> times;
3348 times.reserve(
events->size());
3349 std::transform(
events->cbegin(),
events->cend(), std::back_inserter(times), timesCalc);
3368 auto timeCalc = [](
const auto &event) {
return event.pulseTime(); };
3374 auto timeCalc = [](
const auto &event) {
return event.pulseTOFTime(); };
3383 auto timeCalc = [factor, shift](
const auto &event) {
return event.pulseTOFTimeAtSample(factor, shift); };
3390template <
class T>
double getTofMinimumHelper(
const std::vector<T> &events) {
3391 const auto result = std::min_element(events.cbegin(), events.cend(),
3392 [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
3393 return result->tof();
3396template <
class T>
double getTofMaximumHelper(
const std::vector<T> &events) {
3397 const auto result = std::max_element(events.cbegin(), events.cend(),
3398 [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
3399 return result->tof();
3408 double tMin = std::numeric_limits<double>::max();
3418 return this->events->front().tof();
3429 tMin = getTofMinimumHelper(*this->events);
3450 double tMax = std::numeric_limits<double>::lowest();
3460 return this->events->back().tof();
3471 tMax = getTofMaximumHelper(*this->events);
3489template <
class T> DateAndTime getPulseMinimumHelper(
const std::vector<T> &events) {
3490 const auto result = std::min_element(events.cbegin(), events.cend(), [](
const auto &
left,
const auto &
right) {
3491 return left.pulseTime() < right.pulseTime();
3493 return result->pulseTime();
3496template <
class T> DateAndTime getPulseMaximumHelper(
const std::vector<T> &events) {
3497 const auto result = std::max_element(events.cbegin(), events.cend(), [](
const auto &
left,
const auto &
right) {
3498 return left.pulseTime() < right.pulseTime();
3500 return result->pulseTime();
3510 return DateAndTime::maximum();
3516 return this->events->front().pulseTime();
3527 return getPulseMinimumHelper(*this->events);
3534 return DateAndTime::maximum();
3543 return DateAndTime::minimum();
3549 return this->events->back().pulseTime();
3560 return getPulseMaximumHelper(*this->events);
3567 return DateAndTime::minimum();
3571 Mantid::Types::Core::DateAndTime &tMax)
const {
3573 tMax = DateAndTime::minimum();
3574 tMin = DateAndTime::maximum();
3584 tMin = this->events->front().pulseTime();
3585 tMax = this->events->back().pulseTime();
3601 DateAndTime temp = tMax;
3602 for (
size_t i = 0; i <
numEvents; i++) {
3605 temp = this->events->at(i).pulseTime();
3623 DateAndTime tMax = DateAndTime::minimum();
3633 return calculateCorrectedFullTime(this->events->back(), tofFactor, tofOffset);
3635 return calculateCorrectedFullTime(this->
weightedEvents->back(), tofFactor, tofOffset);
3643 DateAndTime temp = tMax;
3644 for (
size_t i = 0; i <
numEvents; i++) {
3647 temp = calculateCorrectedFullTime(this->events->at(i), tofFactor, tofOffset);
3650 temp = calculateCorrectedFullTime(this->
weightedEvents->at(i), tofFactor, tofOffset);
3664 DateAndTime tMin = DateAndTime::maximum();
3674 return calculateCorrectedFullTime(this->events->front(), tofFactor, tofOffset);
3676 return calculateCorrectedFullTime(this->
weightedEvents->front(), tofFactor, tofOffset);
3684 DateAndTime temp = tMin;
3685 for (
size_t i = 0; i <
numEvents; i++) {
3688 temp = calculateCorrectedFullTime(this->events->at(i), tofFactor, tofOffset);
3691 temp = calculateCorrectedFullTime(this->
weightedEvents->at(i), tofFactor, tofOffset);
3713 size_t x_size = tofs.size();
3714 if (
events.size() != x_size)
3717 for (
size_t i = 0; i < x_size; ++i)
3760 auto itev_end =
events.end();
3764 for (
auto itev =
events.begin(); itev != itev_end; itev++) {
3765 itev->m_errorSquared =
static_cast<float>(itev->m_errorSquared * valueSquared);
3766 itev->m_weight *=
static_cast<float>(
value);
3771 for (
auto itev =
events.begin(); itev != itev_end; itev++) {
3772 itev->m_errorSquared =
3773 static_cast<float>(itev->m_errorSquared * valueSquared + errorSquared * itev->m_weight * itev->m_weight);
3774 itev->m_weight *=
static_cast<float>(
value);
3857 std::span<double const> E) {
3859 if ((
X.size() < 2) || (
Y.size() != E.size()) || (
X.size() != 1 +
Y.size())) {
3860 std::stringstream msg;
3861 msg <<
"EventList::multiply() was given invalid size or "
3862 "inconsistent histogram arrays: X["
3864 <<
"Y[" <<
Y.size() <<
" E[" << E.size() <<
"]";
3865 throw std::invalid_argument(msg.str());
3868 size_t x_size =
X.size();
3872 auto itev_end =
events.end();
3875 if (itev == itev_end)
3884 double valueSquared;
3885 double errorSquared;
3889 double tof = itev->tof();
3890 while (bin < x_size - 1) {
3892 if ((tof >=
X[bin]) && (tof <
X[bin + 1]))
3904 while ((itev != itev_end) && (bin < x_size - 1)) {
3906 while (bin < x_size - 1) {
3908 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
3910 itev->m_errorSquared =
3911 static_cast<float>(itev->m_errorSquared * valueSquared + errorSquared * itev->m_weight * itev->m_weight);
3912 itev->m_weight *=
static_cast<float>(
value);
3916 if (bin >= x_size - 1)
3982 std::span<double const> E) {
3984 if ((
X.size() < 2) || (
Y.size() != E.size()) || (
X.size() != 1 +
Y.size())) {
3985 std::stringstream msg;
3986 msg <<
"EventList::divide() was given invalid size or "
3987 "inconsistent histogram arrays: X["
3989 <<
"Y[" <<
Y.size() <<
" E[" << E.size() <<
"]";
3990 throw std::invalid_argument(msg.str());
3993 size_t x_size =
X.size();
3997 auto itev_end =
events.end();
4000 if (itev == itev_end)
4009 double valError_over_value_squared;
4013 double tof = itev->tof();
4014 while (bin < x_size - 1) {
4016 if ((tof >=
X[bin]) && (tof <
X[bin + 1]))
4027 value = std::numeric_limits<float>::quiet_NaN();
4028 valError_over_value_squared = 0;
4033 while ((itev !=
events.end()) && (bin < x_size - 1)) {
4035 while (bin < x_size - 1) {
4037 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
4039 double newWeight = itev->m_weight /
value;
4040 itev->m_errorSquared =
static_cast<float>(
4041 newWeight * newWeight *
4042 ((itev->m_errorSquared / (itev->m_weight * itev->m_weight)) + valError_over_value_squared));
4043 itev->m_weight =
static_cast<float>(newWeight);
4047 if (bin >= x_size - 1)
4056 value = std::numeric_limits<float>::quiet_NaN();
4057 valError_over_value_squared = 0;
4119 throw std::invalid_argument(
"EventList::divide() called with value of 0.0. Cannot divide by zero.");
4136 throw std::invalid_argument(
"EventList::divide() called with value of 0.0. Cannot divide by zero.");
4142 double invValue = 1.0 /
value;
4144 double invError = (
error /
value) * invValue;
4146 this->
multiply(invValue, invError);
4164 if (
this == &output) {
4165 throw std::invalid_argument(
"In-place filtering is not allowed");
4187 throw std::runtime_error(
"EventList::filterByPulseTime() called on an "
4188 "EventList that no longer has time information.");
4216 if ((timeRoi ==
nullptr) || (timeRoi->
useAll())) {
4217 throw std::invalid_argument(
"TimeROI can not use all time");
4220 if (intervals.empty())
4231 throw std::runtime_error(
"EventList::filterByPulseTime() called on an "
4232 "EventList that no longer has time information.");
4246 std::vector<T> &output) {
4247 std::copy_if(
events.begin(),
events.end(), std::back_inserter(output),
4248 [start, stop](
const T &t) { return (t.m_pulsetime >= start) && (t.m_pulsetime < stop); });
4261 auto itspl = intervals.cbegin();
4262 auto itspl_end = intervals.cend();
4264 auto itev =
events.cbegin();
4265 auto itev_end =
events.cend();
4268 while (itspl != itspl_end) {
4270 DateAndTime start = itspl->start();
4271 DateAndTime stop = itspl->stop();
4273 while ((itev != itev_end) && (itev->m_pulsetime < start))
4277 while ((itev != itev_end) && (itev->m_pulsetime < stop)) {
4279 const T eventCopy(*itev);
4287 if (itspl == itspl_end)
4291 if (itev == itev_end)
4302 if (timeRoi ==
nullptr) {
4303 throw std::runtime_error(
"TimeROI can not be a nullptr\n");
4306 throw std::invalid_argument(
"TimeROI can not be empty\n");
4320 throw std::runtime_error(
"EventList::filterInPlace() called on an "
4321 "EventList that no longer has time information.");
4357 auto itspl = splitter.cbegin();
4358 auto itspl_end = splitter.cend();
4359 DateAndTime start, stop;
4362 auto itev =
events.begin();
4363 auto itev_end =
events.end();
4367 auto itOut =
events.begin();
4370 while (itspl != itspl_end) {
4372 start = itspl->start();
4373 stop = itspl->stop();
4375 while ((itev != itev_end) && (itev->m_pulsetime < start))
4379 bool copyingInPlace = (itOut == itev);
4380 if (copyingInPlace) {
4381 while ((itev != itev_end) && (itev->m_pulsetime < stop))
4387 while ((itev != itev_end) && (itev->m_pulsetime < stop)) {
4397 if (itspl == itspl_end)
4401 if (itev == itev_end)
4407 events.resize(std::size_t(std::distance(
events.begin(), itOut)));
4417 bool removeDetIDs{
true};
4422 auto initPartial = [&](
EventList *partial) {
4423 partial->clear(removeDetIDs);
4424 partial->copyInfoFrom(*
this);
4425 partial->setHistogram(histogramLocal);
4426 partial->switchTo(eventTypeLocal);
4430 std::for_each(partials.cbegin(), partials.cend(),
4431 [&](
const std::pair<int, EventList *> &pair) { initPartial(pair.second); });
4482 for (
auto &itev :
events) {
4484 const double tof = fromUnit->
singleToTOF(itev.m_tof);
4500 if (!fromUnit || !toUnit)
4501 throw std::runtime_error(
"EventList::convertUnitsViaTof(): one of the units is NULL!");
4503 throw std::runtime_error(
"EventList::convertUnitsViaTof(): fromUnit is not initialized!");
4505 throw std::runtime_error(
"EventList::convertUnitsViaTof(): toUnit is not initialized!");
4529 for (
auto &event :
events) {
4531 event.m_tof = factor * std::pow(event.m_tof, power);
4562 if (
histogram.xMode() != HistogramData::Histogram::XMode::BinEdges)
4563 throw std::runtime_error(
"EventList: setting histogram with storage mode "
4564 "other than BinEdges is not possible");
4566 throw std::runtime_error(
"EventList: setting histogram data with non-null "
4567 "Y or E data is not possible");
4569 if (
histogram.yMode() == HistogramData::Histogram::YMode::Uninitialized)
4572 throw std::runtime_error(
"EventList: setting histogram data with different "
4573 "YMode is not possible");
4577 throw std::runtime_error(
"EventList: setting Points as X data is not "
4578 "possible, only BinEdges are supported");
4582 throw std::runtime_error(
"EventList: Cannot set Y or E data, these data are "
4583 "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.
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
bool compareEventPulseTime(const TofEvent &e1, const TofEvent &e2)
Compare two events' FRAME id, return true if e1 should be before e2.
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
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)