19#pragma warning(disable : 4180)
21#include "tbb/parallel_sort.h"
23#pragma warning(default : 4180)
34using std::runtime_error;
39using Types::Core::DateAndTime;
40using Types::Event::TofEvent;
45constexpr double SEC_TO_NANO{1.e9};
49constexpr size_t MIN_VEC_LENGTH_PARALLEL_SORT{2000};
58template <
typename EventType>
59int64_t calculateCorrectedFullTime(
const EventType &event,
const double tofFactor,
const double tofShift) {
60 return event.pulseTime().totalNanoseconds() +
61 static_cast<int64_t
>(tofFactor * (
event.tof() * 1.0E3) + (tofShift * 1.0E9));
67template <
typename EventType>
class CompareTimeAtSample {
73 CompareTimeAtSample(
const double tofFactor,
const double tofShift) :
m_tofFactor(tofFactor),
m_tofShift(tofShift) {}
85 const auto tAtSample1 = calculateCorrectedFullTime(e1, m_tofFactor, m_tofShift);
86 const auto tAtSample2 = calculateCorrectedFullTime(e2, m_tofFactor, m_tofShift);
87 return (tAtSample1 < tAtSample2);
109 if (e1.pulseTime() < e2.pulseTime()) {
111 }
else if ((e1.pulseTime() == e2.pulseTime()) && (e1.tof() < e2.tof())) {
121 :
startNano(start.totalNanoseconds()),
deltaNano(static_cast<int64_t>(seconds * SEC_TO_NANO)) {}
129 if (e1Pulse < e2Pulse) {
131 }
else if ((e1Pulse == e2Pulse) && (e1.tof() < e2.tof())) {
149 divisor = 1. / log1p(abs(step));
166 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts),
167 eventType(event_type), order(
UNSORTED), mru(nullptr) {
170 this->
events = std::make_unique<std::vector<Mantid::Types::Event::TofEvent>>();
177 this->weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
183 this->weightedEventsNoTime = std::make_unique<std::vector<WeightedEventNoTime>>();
184 this->weightedEventsNoTime =
nullptr;
195 m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts),
196 weightedEvents(nullptr), weightedEventsNoTime(nullptr), eventType(
TOF), order(
UNSORTED), mru(mru) {
197 this->
events = std::make_unique<std::vector<Mantid::Types::Event::TofEvent>>();
211 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts),
212 weightedEvents(nullptr), weightedEventsNoTime(nullptr), eventType(
TOF), mru(nullptr) {
213 this->events = std::make_unique<std::vector<Mantid::Types::Event::TofEvent>>(
events.cbegin(),
events.cend());
221 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts), events(nullptr),
222 weightedEventsNoTime(nullptr), mru(nullptr) {
231 : m_histogram(HistogramData::Histogram::XMode::BinEdges, HistogramData::Histogram::YMode::Counts), events(nullptr),
232 weightedEvents(nullptr), mru(nullptr) {
244 }
catch (
const std::runtime_error &) {
262 sink.
events = std::make_unique<std::vector<Types::Event::TofEvent>>(
events->cbegin(),
events->cend());
264 sink.
events = std::make_unique<std::vector<Types::Event::TofEvent>>();
269 sink.
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
296 int MaxEventsPerBin) {
304 if (
Y.size() + 1 !=
X.size())
305 throw std::runtime_error(
"Expected a histogram (X vector should be 1 longer than the Y vector)");
314 for (
size_t i = 0; i <
X.size() - 1; i++) {
315 double weight =
Y[i];
316 if ((weight != 0.0 || GenerateZeros) && std::isfinite(weight)) {
319 if (std::isfinite(
error)) {
320 if (GenerateMultipleEvents) {
324 double val = weight / E[i];
339 for (
size_t j = 0; j < size_t(
numEvents); j++) {
340 double tof =
X[i] + tofStep * (0.5 + double(j));
348 double tof = (
X[i] +
X[i + 1]) / 2.0;
350 double errorSquared = E[i];
351 errorSquared *= errorSquared;
378 IEventList::operator=(
rhs);
380 rhs.copyDataInto(*
this);
394 this->
events->emplace_back(event);
421 this->
events->insert(this->
events->end(), more_events.cbegin(), more_events.cend());
428 std::copy(more_events.cbegin(), more_events.cend(), std::back_inserter(*this->weightedEvents));
435 std::copy(more_events.cbegin(), more_events.cend(), std::back_inserter(*this->weightedEventsNoTime));
482 std::copy(more_events.cbegin(), more_events.cend(), std::back_inserter(*this->weightedEventsNoTime));
526 if (!more_events.
empty()) {
574 std::transform(more_events.cbegin(), more_events.cend(), std::back_inserter(
events),
575 [](
const auto &ev) { return T1(ev.tof(), ev.pulseTime(), ev.weight() * (-1.0), ev.errorSquared()); });
587 if (
this == &more_events) {
643bool vectorPtrEquals(
const std::unique_ptr<std::vector<T>> &
left,
const std::unique_ptr<std::vector<T>> &
right) {
667 if (!vectorPtrEquals(
events,
rhs.events))
685 const int64_t tolPulse)
const {
697 auto leftIter = this->
events->cbegin();
698 auto leftEnd = this->
events->cend();
699 auto rightIter =
rhs.events->cbegin();
700 while (leftIter != leftEnd) {
701 if (!leftIter->equals(*rightIter, tolTof, tolPulse))
703 leftIter = std::next(leftIter);
704 rightIter = std::next(rightIter);
711 auto rightIter =
rhs.weightedEvents->cbegin();
712 while (leftIter != leftEnd) {
713 if (!leftIter->equals(*rightIter, tolTof, tolWeight, tolPulse))
715 leftIter = std::next(leftIter);
716 rightIter = std::next(rightIter);
723 auto rightIter =
rhs.weightedEventsNoTime->cbegin();
724 while (leftIter != leftEnd) {
725 if (!leftIter->equals(*rightIter, tolTof, tolWeight))
727 leftIter = std::next(leftIter);
728 rightIter = std::next(rightIter);
754 throw std::runtime_error(
"EventList::switchTo() called on an EventList with weights to go down to TofEvent's. "
755 "This would remove weight information and therefore is not possible.");
781 throw std::runtime_error(
"EventList::switchToWeightedEvents() called on an EventList with WeightedEventNoTime's. "
782 "It has lost the pulse time information and can't go back to WeightedEvent's.");
856 return WeightedEvent(event.tof(), 0, event.weight(), event.errorSquared());
859 throw std::runtime_error(
"EventList: invalid event type value was found.");
876 throw std::runtime_error(
"EventList::getEvents() called for an EventList that has weights. Use getWeightedEvents() "
877 "or getWeightedEventsNoTime().");
881 throw std::runtime_error(
"unweighted event vector is not initialized");
892 throw std::runtime_error(
"EventList::getEvents() called for an EventList that has weights. Use getWeightedEvents() "
893 "or getWeightedEventsNoTime().");
897 throw std::runtime_error(
"unweighted event vector is not initialized");
909 throw std::runtime_error(
"EventList::getWeightedEvents() called for an EventList not of type WeightedEvent. Use "
910 "getEvents() or getWeightedEventsNoTime().");
914 throw std::runtime_error(
"weighted event vector is not initialized");
926 throw std::runtime_error(
"EventList::getWeightedEvents() called for an EventList not of type WeightedEvent. Use "
927 "getEvents() or getWeightedEventsNoTime().");
931 throw std::runtime_error(
"weighted event vector is not initialed");
941 throw std::runtime_error(
"EventList::getWeightedEventsNoTime() called for an EventList not of type "
942 "WeightedEventNoTime. Use getEvents() or getWeightedEvents().");
946 throw std::runtime_error(
"weighted event no time vector is not initialed");
956 throw std::runtime_error(
"EventList::getWeightedEventsNoTime() called for an EventList not of type "
957 "WeightedEventNoTime. Use getEvents() or getWeightedEvents().");
961 throw std::runtime_error(
"weighted event no time vector is not initialed");
971 }
catch (
const std::runtime_error &) {
980 if (!this->
empty()) {
983 std::vector<TofEvent>().swap(*this->
events);
1033 this->
events->reserve(num);
1062 throw std::invalid_argument(
"sorting by pulse time with delta requires "
1063 "extra parameters. Use sortPulseTimeTOFDelta "
1066 throw std::invalid_argument(
"sorting by time at sample requires extra "
1067 "parameters. Use sortTimeAtSample instead.");
1069 throw runtime_error(
"Invalid sort type in EventList::sort(EventSortType)");
1082template <
class RandomIt>
void switchable_sort(RandomIt first, RandomIt last) {
1083 const auto vec_size =
static_cast<size_t>(std::distance(first, last));
1086 else if (vec_size < MIN_VEC_LENGTH_PARALLEL_SORT)
1087 std::sort(first, last);
1089 tbb::parallel_sort(first, last);
1092template <
class RandomIt,
class Compare>
void switchable_sort(RandomIt first, RandomIt last, Compare comp) {
1093 const auto vec_size =
static_cast<size_t>(std::distance(first, last));
1096 else if (vec_size < MIN_VEC_LENGTH_PARALLEL_SORT)
1097 std::sort(first, last, std::move(comp));
1099 tbb::parallel_sort(first, last, comp);
1154 CompareTimeAtSample<TofEvent> comparitor(tofFactor, tofShift);
1155 switchable_sort(
events->begin(),
events->end(), comparitor);
1158 CompareTimeAtSample<WeightedEvent> comparitor(tofFactor, tofShift);
1162 CompareTimeAtSample<WeightedEventNoTime> comparitor(tofFactor, tofShift);
1243 switchable_sort(
events->begin(),
events->end(), std::move(comparator));
1273 std::reverse(
x.begin(),
x.end());
1279 std::reverse(this->
events->begin(), this->events->end());
1282 std::reverse(this->
weightedEvents->begin(), this->weightedEvents->end());
1310 throw std::runtime_error(
"EventList: invalid event type value was found.");
1320 return this->
events->empty();
1322 throw std::runtime_error(
"TOF events is nullptr");
1327 throw std::runtime_error(
"WEIGHTED events is nullptr");
1332 throw std::runtime_error(
"WEIGHTED_NOTIME events is nullptr");
1334 throw std::runtime_error(
"EventList: invalid event type value was found.");
1347 return this->
events->capacity() *
sizeof(TofEvent) +
sizeof(
EventList);
1353 throw std::runtime_error(
"EventList: invalid event type value was found.");
1360 size_t x_size =
readX().size();
1453 return histogram().countStandardDeviations();
1461 return histogram().frequencyStandardDeviations();
1466 throw std::runtime_error(
"'EventList::y()' called with no MRU set. This is not allowed.");
1472 throw std::runtime_error(
"'EventList::e()' called with no MRU set. This is not allowed.");
1485 yData =
mru->
findY(
static_cast<size_t>(thread),
this);
1494 yData = Kernel::make_cow<HistogramData::HistogramY>(std::move(
Y));
1499 auto eData = Kernel::make_cow<HistogramData::HistogramE>(std::move(E));
1523 eData = Kernel::make_cow<HistogramData::HistogramE>(std::move(E));
1538 throw std::runtime_error(
"'EventList::dataY()' called with no MRU set. This is not allowed.");
1552 throw std::runtime_error(
"'EventList::dataE()' called with no MRU set. This is not allowed.");
1560inline double calcNorm(
const double errorSquared) {
1561 if (errorSquared == 0.)
1563 else if (errorSquared == 1.)
1566 return 1. / std::sqrt(errorSquared);
1585 out.reserve(
events.size() / 20);
1588 double lastTof =
events.front().m_tof;
1590 double totalTof = 0;
1594 double errorSquared = 0;
1595 double normalization = 0.;
1597 double bin_end = lastTof;
1598 std::function<bool(
const double,
const double)> compareTof;
1599 std::function<double(
const double,
double)> next_bin;
1603 throw std::runtime_error(
"compressEvents with log binning doesn't work with negative TOF");
1609 compareTof = [](
const double lhs,
const double rhs) {
return lhs <
rhs; };
1610 next_bin = [
tolerance](
const double lastTof,
double bin_end) {
1612 while (lastTof >= bin_end)
1618 compareTof = [](
const double lhs,
const double rhs) {
return lhs <=
rhs; };
1619 next_bin = [
tolerance](
const double lastTof, double) {
return lastTof +
tolerance; };
1623 bin_end = next_bin(lastTof, bin_end);
1625 for (
auto it =
events.cbegin(); it !=
events.cend(); it++) {
1626 if (compareTof(it->m_tof, bin_end)) {
1628 weight += it->weight();
1629 errorSquared += it->errorSquared();
1632 const double norm = calcNorm(it->errorSquared());
1633 normalization += norm;
1634 totalTof += it->m_tof * norm;
1641 out.emplace_back(lastTof, weight, errorSquared);
1642 }
else if (num > 1) {
1643 out.emplace_back(totalTof / normalization, weight, errorSquared);
1647 const double norm = calcNorm(it->errorSquared());
1648 normalization = norm;
1649 totalTof = it->m_tof * norm;
1650 weight = it->weight();
1651 errorSquared = it->errorSquared();
1652 lastTof = it->m_tof;
1654 bin_end = next_bin(lastTof, bin_end);
1662 out.emplace_back(lastTof, weight, errorSquared);
1663 }
else if (num > 1) {
1664 out.emplace_back(totalTof / normalization, weight, errorSquared);
1668 size_t excess_limit = out.size() / 20;
1669 if ((out.capacity() - out.size()) > excess_limit) {
1670 out.shrink_to_fit();
1676 const double tolerance,
const Types::Core::DateAndTime &timeStart,
1677 const double seconds) {
1681 out.reserve(
events.size() / 20);
1684 double lastTof =
events.front().m_tof;
1686 double totalTof = 0;
1690 const int64_t pulsetimeStart = timeStart.totalNanoseconds();
1691 const auto pulsetimeDelta =
static_cast<int64_t
>(seconds * SEC_TO_NANO);
1694 std::vector<DateAndTime> pulsetimes;
1695 std::vector<double> pulsetimeWeights;
1699 double errorSquared = 0.;
1700 double tofNormalization = 0.;
1705 auto it =
events.cbegin();
1706 for (; it !=
events.cend(); ++it) {
1707 if (it->m_pulsetime >= timeStart)
1712 throw std::runtime_error(
"failed to find first pulse time in the events");
1715 int64_t lastPulseBin = (it->m_pulsetime.totalNanoseconds() - pulsetimeStart) / pulsetimeDelta;
1717 double bin_end = lastTof;
1719 std::function<bool(
const double,
const double)> compareTof;
1720 std::function<double(
const double,
double)> next_bin;
1724 compareTof = [](
const double lhs,
const double rhs) {
return lhs <
rhs; };
1725 next_bin = [
tolerance](
const double lastTof,
double bin_end) {
1727 while (lastTof >= bin_end)
1733 const auto event_min = std::min_element(
1734 events.cbegin(),
events.cend(), [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
1735 bin_end = tof_min = event_min->tof();
1738 throw std::runtime_error(
"compressEvents with log binning doesn't work with negative TOF");
1746 compareTof = [](
const double lhs,
const double rhs) {
return lhs <=
rhs; };
1747 next_bin = [
tolerance](
const double lastTof, double) {
return lastTof +
tolerance; };
1751 bin_end = next_bin(lastTof, bin_end);
1754 for (; it !=
events.cend(); ++it) {
1755 const int64_t eventPulseBin = (it->m_pulsetime.totalNanoseconds() - pulsetimeStart) / pulsetimeDelta;
1756 if ((eventPulseBin <= lastPulseBin) && compareTof(it->m_tof, bin_end)) {
1758 weight += it->weight();
1759 errorSquared += it->errorSquared();
1760 double norm = calcNorm(it->errorSquared());
1761 tofNormalization += norm;
1763 totalTof += it->m_tof * norm;
1765 pulsetimes.emplace_back(it->m_pulsetime);
1766 pulsetimeWeights.emplace_back(norm);
1769 if (!pulsetimes.empty()) {
1772 if (pulsetimes.size() == 1) {
1773 out.emplace_back(lastTof, pulsetimes.front(), weight, errorSquared);
1775 out.emplace_back(totalTof / tofNormalization,
1780 if (
tolerance < 0 && eventPulseBin != lastPulseBin)
1785 double norm = calcNorm(it->errorSquared());
1786 totalTof = it->m_tof * norm;
1787 weight = it->weight();
1788 errorSquared = it->errorSquared();
1789 tofNormalization = norm;
1790 lastTof = it->m_tof;
1791 lastPulseBin = eventPulseBin;
1793 pulsetimes.emplace_back(it->m_pulsetime);
1794 pulsetimeWeights.clear();
1795 pulsetimeWeights.emplace_back(norm);
1797 bin_end = next_bin(lastTof, bin_end);
1802 if (!pulsetimes.empty()) {
1805 if (pulsetimes.size() == 1) {
1806 out.emplace_back(lastTof, pulsetimes.front(), weight, errorSquared);
1808 out.emplace_back(totalTof / tofNormalization,
1814 size_t excess_limit = out.size() / 20;
1815 if ((out.capacity() - out.size()) > excess_limit) {
1816 out.shrink_to_fit();
1831 if (this->
empty()) {
1858 if (destination ==
this) {
1860 auto out = std::make_unique<std::vector<WeightedEventNoTime>>();
1890 const std::vector<T> &weight,
const std::vector<T> &
error) {
1892 for (
size_t i = 0; i < weight.size(); ++i) {
1893 const auto errors =
static_cast<float>(
error[i]);
1895 out.emplace_back(tof[i],
static_cast<float>(weight[i]), errors);
1901 const std::shared_ptr<std::vector<double>> histogram_bin_edges,
1903 const auto NUM_BINS = histogram_bin_edges->size() - 1;
1904 std::vector<double> tof(NUM_BINS, 0.);
1905 std::vector<double> normalization(NUM_BINS, 0.);
1906 std::vector<float> weight(NUM_BINS, 0.);
1907 std::vector<float>
error(NUM_BINS, 0.);
1908 for (
const auto &ev :
events) {
1909 const auto &bin_optional = findBin(*histogram_bin_edges.get(), ev.m_tof,
false);
1911 const auto bin = bin_optional.value();
1912 const double norm = calcNorm(ev.m_errorSquared);
1913 tof[bin] += ev.m_tof * norm;
1914 normalization[bin] += norm;
1915 weight[bin] += ev.m_weight;
1916 error[bin] += ev.m_errorSquared;
1921 std::transform(tof.begin(), tof.end(), normalization.begin(), tof.begin(), std::divides<double>());
1927 const std::shared_ptr<std::vector<double>> histogram_bin_edges) {
1928 if (this->
empty()) {
1933 const auto NUM_BINS = histogram_bin_edges->size() - 1;
1934 const auto xmin =
static_cast<double>(histogram_bin_edges->front());
1940 std::vector<double> tof(NUM_BINS, 0);
1941 std::vector<uint32_t>
count(NUM_BINS, 0);
1942 for (
const auto &ev : *this->
events) {
1943 const auto &bin_optional = findBin(*histogram_bin_edges.get(), ev.m_tof,
false);
1945 const auto bin = bin_optional.value();
1947 tof[bin] += ev.m_tof;
1952 std::transform(tof.begin(), tof.end(),
count.begin(), tof.begin(), std::divides<double>());
1965 if (destination ==
this) {
1967 auto out = std::make_unique<std::vector<WeightedEventNoTime>>();
1989 const double seconds,
EventList *destination) {
1990 if (this->
empty()) {
1993 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
1997 throw std::invalid_argument(
"Cannot compress events that do not have pulsetime");
2000 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2005 if (destination ==
this) {
2007 auto out = std::make_unique<std::vector<WeightedEvent>>();
2012 destination->
weightedEvents = std::make_unique<std::vector<WeightedEvent>>();
2037typename std::vector<T>::const_iterator
static findFirstEvent(
const std::vector<T> &events, T seek_tof) {
2038 return std::find_if_not(events.cbegin(), events.cend(), [seek_tof](
const T &
x) { return x < seek_tof; });
2053 const double seek_pulsetime) {
2054 auto itev =
events.cbegin();
2055 auto itev_end =
events.cend();
2058 while ((itev != itev_end) && (
static_cast<double>(itev->pulseTime().totalNanoseconds()) < seek_pulsetime))
2079typename std::vector<T>::const_iterator
2081 const double &tofOffset)
const {
2082 auto itev =
events.cbegin();
2083 auto itev_end =
events.cend();
2086 while ((itev != itev_end) &&
2087 (
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset)) < seek_time))
2104template <
class T>
typename std::vector<T>::iterator
static findFirstEvent(std::vector<T> &events, T seek_tof) {
2105 return std::find_if_not(events.begin(), events.end(), [seek_tof](
const T &
x) { return x < seek_tof; });
2122 size_t x_size =
X.size();
2131 bool mustFill = (
Y.size() == x_size - 1);
2133 Y.resize(x_size - 1, 0.0);
2136 E.resize(x_size - 1, 0.0);
2140 std::fill(
Y.begin(),
Y.end(), 0.0);
2141 std::fill(E.begin(), E.end(), 0.0);
2151 auto itev_end =
events.cend();
2154 if (itev == itev_end)
2161 double tof = itev->tof();
2162 while (bin < x_size - 1) {
2164 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
2167 Y[bin] += double(itev->m_weight);
2168 E[bin] += double(itev->m_errorSquared);
2177 while ((itev != itev_end) && (bin < x_size - 1)) {
2179 while (bin < x_size - 1) {
2183 if (tof <
X[bin + 1]) {
2186 Y[bin] += double(itev->m_weight);
2187 E[bin] += double(itev->m_errorSquared);
2197 std::transform(E.cbegin(), E.cend(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2217 size_t x_size =
X.size();
2226 bool mustFill = (
Y.size() == x_size - 1);
2227 Y.resize(x_size - 1, 0.0);
2228 E.resize(x_size - 1, 0.0);
2231 std::fill(
Y.begin(),
Y.end(), 0.0);
2232 std::fill(E.begin(), E.end(), 0.0);
2238 const auto xmin =
X.front();
2239 const auto xmax =
X.back();
2241 auto findBin =
FindBin(step, xmin);
2243 for (
const T &ev :
events) {
2244 const double tof = ev.tof();
2245 if (tof < xmin || tof >= xmax)
2248 std::optional<size_t> n_bin = findBin(
X, tof,
true);
2251 Y[n_bin.value()] += ev.weight();
2252 E[n_bin.value()] += ev.errorSquared();
2257 std::transform(E.cbegin(), E.cend(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2283 throw std::runtime_error(
"Cannot histogram by pulse time on Weighted "
2284 "Events currently");
2287 throw std::runtime_error(
"Cannot histogram by pulse time on Weighted Events NoTime");
2303 const double &tofOffset,
bool skipError)
const {
2316 throw std::runtime_error(
"Cannot histogram by time at sample on Weighted "
2317 "Events currently");
2320 throw std::runtime_error(
"Cannot histogram by time at sample on Weighted Events NoTime");
2373 bool skipError)
const {
2404 size_t x_size =
X.size();
2415 Y.resize(x_size - 1, 0);
2420 if (!this->
events->empty()) {
2423 auto itev_end =
events->cend();
2426 if (itev == itev_end)
2434 double pulsetime =
static_cast<double>(itev->pulseTime().totalNanoseconds());
2435 while (bin < x_size - 1) {
2437 if ((pulsetime >=
X[bin]) && (pulsetime <
X[bin + 1])) {
2447 while ((itev != itev_end) && (bin < x_size - 1)) {
2448 pulsetime =
static_cast<double>(itev->pulseTime().totalNanoseconds());
2449 while (bin < x_size - 1) {
2451 if ((pulsetime >=
X[bin]) && (pulsetime <
X[bin + 1])) {
2477 const double TOF_min,
const double TOF_max)
const {
2479 if (this->
events->empty())
2482 size_t nBins =
Y.size();
2487 double step = (xMax - xMin) /
static_cast<double>(nBins);
2489 for (
const TofEvent &ev : *this->
events) {
2490 double pulsetime =
static_cast<double>(ev.pulseTime().totalNanoseconds());
2491 if (pulsetime < xMin || pulsetime >= xMax)
2493 if (ev.tof() < TOF_min || ev.tof() >= TOF_max)
2496 auto n_bin =
static_cast<size_t>((pulsetime - xMin) / step);
2511 const double &tofOffset)
const {
2513 const size_t x_size =
X.size();
2524 Y.resize(x_size - 1, 0);
2529 if (!this->
events->empty()) {
2532 std::vector<TofEvent>::const_iterator itev_end =
events->end();
2535 if (itev == itev_end)
2541 auto tAtSample =
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset));
2542 while (bin < x_size - 1) {
2544 if ((tAtSample >=
X[bin]) && (tAtSample <
X[bin + 1])) {
2554 while ((itev != itev_end) && (bin < x_size - 1)) {
2555 tAtSample =
static_cast<double>(calculateCorrectedFullTime(*itev, tofFactor, tofOffset));
2556 while (bin < x_size - 1) {
2558 if ((tAtSample >=
X[bin]) && (tAtSample <
X[bin + 1])) {
2577 size_t x_size =
X.size();
2588 Y.resize(x_size - 1, 0);
2594 if (!this->
events->empty()) {
2598 const auto itend = this->
events->end();
2600 for (
auto itx =
X.cbegin(); itev != itend; ++itev) {
2601 const double tof = itev->tof();
2602 itx = std::find_if(itx,
X.cend(), [tof](
const double x) { return tof < x; });
2603 if (itx ==
X.cend()) {
2606 const auto bin =
static_cast<size_t>(std::max(std::distance(
X.cbegin(), itx) - 1, std::ptrdiff_t{0}));
2623 const double offset,
const bool findExact) {
2624 const auto bin =
static_cast<size_t>(tof * divisor - offset);
2625 if (bin >=
X.size())
2626 return std::nullopt;
2652 const double offset,
const bool findExact) {
2653 const auto bin =
static_cast<size_t>(log(tof) * divisor - offset);
2654 if (bin >=
X.size())
2655 return std::nullopt;
2671 auto tof_of_bin =
X.cbegin() + n_bin;
2672 if (tof < *tof_of_bin)
2673 return std::move(n_bin - 1);
2677 if (tof >= *tof_of_bin)
2678 return std::move(n_bin + 1);
2681 return std::move(n_bin);
2697 size_t x_size =
X.size();
2706 bool mustFill = (
Y.size() == x_size - 1);
2708 Y.resize(x_size - 1, 0);
2710 std::fill(
Y.begin(),
Y.end(), 0.0);
2713 if (this->
events->empty())
2716 const auto xmin =
X.front();
2717 const auto xmax =
X.back();
2719 auto findBin =
FindBin(step, xmin);
2721 for (
const TofEvent &ev : *this->
events) {
2722 const double tof = ev.tof();
2723 if (tof < xmin || tof >= xmax)
2726 const std::optional<size_t> n_bin = findBin(
X, tof,
true);
2743 E.resize(
Y.size(), 0);
2746 std::transform(
Y.cbegin(),
Y.cend(), E.begin(),
static_cast<double (*)(
double)
>(sqrt));
2762 double &sum,
double &
error) {
2770 auto lowit =
events.cbegin();
2771 auto highit =
events.cend();
2780 if (lowit->tof() < minX)
2781 lowit = std::lower_bound(
events.cbegin(),
events.cend(), minX);
2783 if ((highit - 1)->tof() > maxX) {
2784 highit = std::upper_bound(lowit,
events.cend(), T(maxX));
2789 for (
auto it = lowit; it != highit; ++it) {
2790 sum += it->weight();
2791 error += it->errorSquared();
2806 double sum(0),
error(0);
2821 double &
error)
const {
2841 throw std::runtime_error(
"EventList: invalid event type value was found.");
2859 transform(
x.cbegin(),
x.cend(),
x.begin(), func);
2892 ev.m_tof = func(ev.m_tof);
2938 for (
auto &event :
events) {
2939 event.m_tof =
event.m_tof * factor + offset;
2967 for (
auto &event :
events) {
2968 event.m_pulsetime += seconds;
2979 auto eventIterEnd{
events.end()};
2980 auto secondsIter{seconds.cbegin()};
2981 for (
auto eventIter =
events.begin(); eventIter < eventIterEnd; ++eventIter, ++secondsIter) {
2982 eventIter->m_pulsetime += *secondsIter;
3004 throw std::runtime_error(
"EventList::addPulsetime() called on an event "
3005 "list with no pulse times. You must call this "
3006 "algorithm BEFORE CompressEvents.");
3020 throw std::runtime_error(
"");
3032 throw std::runtime_error(
"EventList::addPulsetime() called on an event "
3033 "list with no pulse times. You must call this "
3034 "algorithm BEFORE CompressEvents.");
3050 if (tofMin >
events.crbegin()->tof())
3052 if (tofMax <
events.cbegin()->tof())
3056 auto it_first = std::lower_bound(
events.begin(),
events.end(), tofMin);
3057 if ((it_first !=
events.end()) && (it_first->tof() < tofMax)) {
3060 auto it_last = std::upper_bound(it_first,
events.end(), T(tofMax));
3062 if (it_first >= it_last) {
3063 throw std::runtime_error(
"Event filter is all messed up");
3066 size_t tmp = std::size_t(std::distance(it_first, it_last));
3069 events.erase(it_first, it_last);
3085 if (tofMax <= tofMin)
3086 throw std::runtime_error(
"EventList::maskTof: tofMax must be > tofMin");
3100 numOrig = this->events->size();
3101 numDel = this->
maskTofHelper(*this->events, tofMin, tofMax);
3113 if (numDel >= numOrig)
3128 auto itm = std::find(mask.begin(), mask.end(),
false);
3129 auto first =
events.begin() + (itm - mask.begin());
3131 if (itm != mask.end()) {
3132 for (
auto ite = first; ++ite !=
events.end() && ++itm != mask.end();) {
3133 if (*itm !=
false) {
3134 *first++ = std::move(*ite);
3139 const auto n =
static_cast<size_t>(
events.end() - first);
3156 throw std::runtime_error(
"EventList::maskTof: tofMax must be > tofMin");
3167 numOrig = this->events->size();
3180 if (numDel >= numOrig)
3192 for (
auto itev =
events.cbegin(); itev !=
events.cend(); ++itev)
3193 tofs.emplace_back(itev->m_tof);
3222 std::vector<double> tofs;
3235 weights.reserve(
events.size());
3236 std::transform(
events.cbegin(),
events.cend(), std::back_inserter(weights),
3237 [](
const auto &event) { return event.weight(); });
3267 std::vector<double> weights;
3280 weightErrors.clear();
3281 weightErrors.reserve(
events.size());
3282 std::transform(
events.cbegin(),
events.cend(), std::back_inserter(weightErrors),
3283 [](
const auto &event) { return event.error(); });
3313 std::vector<double> weightErrors;
3315 return weightErrors;
3323template <
typename UnaryOperation>
3325 std::vector<DateAndTime> times;
3328 times.reserve(
events->size());
3329 std::transform(
events->cbegin(),
events->cend(), std::back_inserter(times), timesCalc);
3348 auto timeCalc = [](
const auto &event) {
return event.pulseTime(); };
3354 auto timeCalc = [](
const auto &event) {
return event.pulseTOFTime(); };
3363 auto timeCalc = [factor, shift](
const auto &event) {
return event.pulseTOFTimeAtSample(factor, shift); };
3370template <
class T>
double getTofMinimumHelper(
const std::vector<T> &events) {
3371 const auto result = std::min_element(events.cbegin(), events.cend(),
3372 [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
3373 return result->tof();
3376template <
class T>
double getTofMaximumHelper(
const std::vector<T> &events) {
3377 const auto result = std::max_element(events.cbegin(), events.cend(),
3378 [](
const auto &
left,
const auto &
right) { return left.tof() < right.tof(); });
3379 return result->tof();
3388 double tMin = std::numeric_limits<double>::max();
3398 return this->events->front().tof();
3409 tMin = getTofMinimumHelper(*this->events);
3430 double tMax = std::numeric_limits<double>::lowest();
3440 return this->events->back().tof();
3451 tMax = getTofMaximumHelper(*this->events);
3469template <
class T> DateAndTime getPulseMinimumHelper(
const std::vector<T> &events) {
3470 const auto result = std::min_element(events.cbegin(), events.cend(), [](
const auto &
left,
const auto &
right) {
3471 return left.pulseTime() < right.pulseTime();
3473 return result->pulseTime();
3476template <
class T> DateAndTime getPulseMaximumHelper(
const std::vector<T> &events) {
3477 const auto result = std::max_element(events.cbegin(), events.cend(), [](
const auto &
left,
const auto &
right) {
3478 return left.pulseTime() < right.pulseTime();
3480 return result->pulseTime();
3490 return DateAndTime::maximum();
3496 return this->events->front().pulseTime();
3507 return getPulseMinimumHelper(*this->events);
3514 return DateAndTime::maximum();
3523 return DateAndTime::minimum();
3529 return this->events->back().pulseTime();
3540 return getPulseMaximumHelper(*this->events);
3547 return DateAndTime::minimum();
3551 Mantid::Types::Core::DateAndTime &tMax)
const {
3553 tMax = DateAndTime::minimum();
3554 tMin = DateAndTime::maximum();
3564 tMin = this->events->front().pulseTime();
3565 tMax = this->events->back().pulseTime();
3581 DateAndTime temp = tMax;
3582 for (
size_t i = 0; i <
numEvents; i++) {
3585 temp = this->events->at(i).pulseTime();
3603 DateAndTime tMax = DateAndTime::minimum();
3613 return calculateCorrectedFullTime(this->events->back(), tofFactor, tofOffset);
3615 return calculateCorrectedFullTime(this->
weightedEvents->back(), tofFactor, tofOffset);
3623 DateAndTime temp = tMax;
3624 for (
size_t i = 0; i <
numEvents; i++) {
3627 temp = calculateCorrectedFullTime(this->events->at(i), tofFactor, tofOffset);
3630 temp = calculateCorrectedFullTime(this->
weightedEvents->at(i), tofFactor, tofOffset);
3644 DateAndTime tMin = DateAndTime::maximum();
3654 return calculateCorrectedFullTime(this->events->front(), tofFactor, tofOffset);
3656 return calculateCorrectedFullTime(this->
weightedEvents->front(), tofFactor, tofOffset);
3664 DateAndTime temp = tMin;
3665 for (
size_t i = 0; i <
numEvents; i++) {
3668 temp = calculateCorrectedFullTime(this->events->at(i), tofFactor, tofOffset);
3671 temp = calculateCorrectedFullTime(this->
weightedEvents->at(i), tofFactor, tofOffset);
3693 size_t x_size = tofs.size();
3694 if (
events.size() != x_size)
3697 for (
size_t i = 0; i < x_size; ++i)
3740 auto itev_end =
events.end();
3744 for (
auto itev =
events.begin(); itev != itev_end; itev++) {
3745 itev->m_errorSquared =
static_cast<float>(itev->m_errorSquared * valueSquared);
3746 itev->m_weight *=
static_cast<float>(
value);
3751 for (
auto itev =
events.begin(); itev != itev_end; itev++) {
3752 itev->m_errorSquared =
3753 static_cast<float>(itev->m_errorSquared * valueSquared + errorSquared * itev->m_weight * itev->m_weight);
3754 itev->m_weight *=
static_cast<float>(
value);
3839 if ((
X.size() < 2) || (
Y.size() != E.size()) || (
X.size() != 1 +
Y.size())) {
3840 std::stringstream msg;
3841 msg <<
"EventList::multiply() was given invalid size or "
3842 "inconsistent histogram arrays: X["
3844 <<
"Y[" <<
Y.size() <<
" E[" << E.size() <<
"]";
3845 throw std::invalid_argument(msg.str());
3848 size_t x_size =
X.size();
3852 auto itev_end =
events.end();
3855 if (itev == itev_end)
3864 double valueSquared;
3865 double errorSquared;
3869 double tof = itev->tof();
3870 while (bin < x_size - 1) {
3872 if ((tof >=
X[bin]) && (tof <
X[bin + 1]))
3884 while ((itev != itev_end) && (bin < x_size - 1)) {
3886 while (bin < x_size - 1) {
3888 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
3890 itev->m_errorSquared =
3891 static_cast<float>(itev->m_errorSquared * valueSquared + errorSquared * itev->m_weight * itev->m_weight);
3892 itev->m_weight *=
static_cast<float>(
value);
3896 if (bin >= x_size - 1)
3964 if ((
X.size() < 2) || (
Y.size() != E.size()) || (
X.size() != 1 +
Y.size())) {
3965 std::stringstream msg;
3966 msg <<
"EventList::divide() was given invalid size or "
3967 "inconsistent histogram arrays: X["
3969 <<
"Y[" <<
Y.size() <<
" E[" << E.size() <<
"]";
3970 throw std::invalid_argument(msg.str());
3973 size_t x_size =
X.size();
3977 auto itev_end =
events.end();
3980 if (itev == itev_end)
3989 double valError_over_value_squared;
3993 double tof = itev->tof();
3994 while (bin < x_size - 1) {
3996 if ((tof >=
X[bin]) && (tof <
X[bin + 1]))
4007 value = std::numeric_limits<float>::quiet_NaN();
4008 valError_over_value_squared = 0;
4013 while ((itev !=
events.end()) && (bin < x_size - 1)) {
4015 while (bin < x_size - 1) {
4017 if ((tof >=
X[bin]) && (tof <
X[bin + 1])) {
4019 double newWeight = itev->m_weight /
value;
4020 itev->m_errorSquared =
static_cast<float>(
4021 newWeight * newWeight *
4022 ((itev->m_errorSquared / (itev->m_weight * itev->m_weight)) + valError_over_value_squared));
4023 itev->m_weight =
static_cast<float>(newWeight);
4027 if (bin >= x_size - 1)
4036 value = std::numeric_limits<float>::quiet_NaN();
4037 valError_over_value_squared = 0;
4099 throw std::invalid_argument(
"EventList::divide() called with value of 0.0. Cannot divide by zero.");
4116 throw std::invalid_argument(
"EventList::divide() called with value of 0.0. Cannot divide by zero.");
4122 double invValue = 1.0 /
value;
4124 double invError = (
error /
value) * invValue;
4126 this->
multiply(invValue, invError);
4144 if (
this == &output) {
4145 throw std::invalid_argument(
"In-place filtering is not allowed");
4167 throw std::runtime_error(
"EventList::filterByPulseTime() called on an "
4168 "EventList that no longer has time information.");
4196 if ((timeRoi ==
nullptr) || (timeRoi->
useAll())) {
4197 throw std::invalid_argument(
"TimeROI can not use all time");
4200 if (intervals.empty())
4211 throw std::runtime_error(
"EventList::filterByPulseTime() called on an "
4212 "EventList that no longer has time information.");
4226 std::vector<T> &output) {
4227 std::copy_if(
events.begin(),
events.end(), std::back_inserter(output),
4228 [start, stop](
const T &t) { return (t.m_pulsetime >= start) && (t.m_pulsetime < stop); });
4241 auto itspl = intervals.cbegin();
4242 auto itspl_end = intervals.cend();
4244 auto itev =
events.cbegin();
4245 auto itev_end =
events.cend();
4248 while (itspl != itspl_end) {
4250 DateAndTime start = itspl->start();
4251 DateAndTime stop = itspl->stop();
4253 while ((itev != itev_end) && (itev->m_pulsetime < start))
4257 while ((itev != itev_end) && (itev->m_pulsetime < stop)) {
4259 const T eventCopy(*itev);
4267 if (itspl == itspl_end)
4271 if (itev == itev_end)
4282 if (timeRoi ==
nullptr) {
4283 throw std::runtime_error(
"TimeROI can not be a nullptr\n");
4286 throw std::invalid_argument(
"TimeROI can not be empty\n");
4300 throw std::runtime_error(
"EventList::filterInPlace() called on an "
4301 "EventList that no longer has time information.");
4337 auto itspl = splitter.cbegin();
4338 auto itspl_end = splitter.cend();
4339 DateAndTime start, stop;
4342 auto itev =
events.begin();
4343 auto itev_end =
events.end();
4347 auto itOut =
events.begin();
4350 while (itspl != itspl_end) {
4352 start = itspl->start();
4353 stop = itspl->stop();
4355 while ((itev != itev_end) && (itev->m_pulsetime < start))
4359 bool copyingInPlace = (itOut == itev);
4360 if (copyingInPlace) {
4361 while ((itev != itev_end) && (itev->m_pulsetime < stop))
4367 while ((itev != itev_end) && (itev->m_pulsetime < stop)) {
4377 if (itspl == itspl_end)
4381 if (itev == itev_end)
4387 events.resize(std::size_t(std::distance(
events.begin(), itOut)));
4397 bool removeDetIDs{
true};
4402 auto initPartial = [&](
EventList *partial) {
4403 partial->clear(removeDetIDs);
4404 partial->copyInfoFrom(*
this);
4405 partial->setHistogram(histogramLocal);
4406 partial->switchTo(eventTypeLocal);
4410 std::for_each(partials.cbegin(), partials.cend(),
4411 [&](
const std::pair<int, EventList *> &pair) { initPartial(pair.second); });
4462 for (
auto &itev :
events) {
4464 const double tof = fromUnit->
singleToTOF(itev.m_tof);
4480 if (!fromUnit || !toUnit)
4481 throw std::runtime_error(
"EventList::convertUnitsViaTof(): one of the units is NULL!");
4483 throw std::runtime_error(
"EventList::convertUnitsViaTof(): fromUnit is not initialized!");
4485 throw std::runtime_error(
"EventList::convertUnitsViaTof(): toUnit is not initialized!");
4509 for (
auto &event :
events) {
4511 event.m_tof = factor * std::pow(event.m_tof, power);
4542 if (
histogram.xMode() != HistogramData::Histogram::XMode::BinEdges)
4543 throw std::runtime_error(
"EventList: setting histogram with storage mode "
4544 "other than BinEdges is not possible");
4546 throw std::runtime_error(
"EventList: setting histogram data with non-null "
4547 "Y or E data is not possible");
4549 if (
histogram.yMode() == HistogramData::Histogram::YMode::Uninitialized)
4552 throw std::runtime_error(
"EventList: setting histogram data with different "
4553 "YMode is not possible");
4557 throw std::runtime_error(
"EventList: setting Points as X data is not "
4558 "possible, only BinEdges are supported");
4562 throw std::runtime_error(
"EventList: Cannot set Y or E data, these data are "
4563 "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
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.
virtual const MantidVec & readX() const =0
void setDetectorIDs(const std::set< detid_t > &detIDs)
Set the detector IDs to be the set given.
virtual const MantidVec & readE() const
Deprecated, use e() instead. Returns the y error data const.
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.
virtual const MantidVec & readY() const
Deprecated, use y() instead. Returns the y data 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.
virtual Kernel::cow_ptr< HistogramData::HistogramX > ptrX() const =0
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 size_t findExactBin(const MantidVec &X, const double tof, const size_t n_bin)
Find the exact bin which a TOF falls in starting from the provided estimated one.
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.
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 std::optional< size_t > findLinearBin(const MantidVec &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.
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.
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.
void generateHistogram(const MantidVec &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...
~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.
void generateErrorsHistogram(const MantidVec &Y, MantidVec &E) const
Generate the Error histogram for the provided counts histogram.
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.
void generateCountsHistogram(const MantidVec &X, MantidVec &Y) const
Fill a histogram given specified histogram bounds.
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.
static void multiplyHistogramHelper(std::vector< T > &events, const MantidVec &X, const MantidVec &Y, const MantidVec &E)
Helper method for multiplying an event list by a histogram with error.
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.
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 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.
EventSortType order
Last sorting order.
void convertTofHelper(std::vector< T > &events, const std::function< double(double)> &func)
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.
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 generateCountsHistogramTimeAtSample(const MantidVec &X, MantidVec &Y, const double &tofFactor, const double &tofOffset) const
With respect to Time at Sample, fill a histogram given specified histogram bounds.
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)
static void divideHistogramHelper(std::vector< T > &events, const MantidVec &X, const MantidVec &Y, const MantidVec &E)
Helper method for dividing an event list by a histogram with error.
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.
static void histogramForWeightsHelper(const std::vector< T > &events, const MantidVec &X, MantidVec &Y, MantidVec &E)
Generates both the Y and E (error) histograms for an EventList with WeightedEvents.
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.
static std::optional< size_t > findLogBin(const MantidVec &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 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 generateHistogramTimeAtSample(const MantidVec &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 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 generateHistogramPulseTime(const MantidVec &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 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.
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...
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, const Nexus::NexusDescriptor &descriptor)
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.
FindBin(double step, double xmin)
std::optional< size_t > operator()(const Mantid::MantidVec &X, const double tof, const bool findExact)
std::optional< size_t >(* findBin)(const Mantid::MantidVec &, 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)