12#include <tbb/parallel_sort.h>
17namespace DataHandling {
20 : m_histogram_edges(
std::move(histogram_bin_edges)), m_initialized(false) {
34 throw std::runtime_error(
"Haven't implemented this compression binning strategy");
42 const auto &binIter =
m_histogram_edges->cbegin() +
static_cast<std::vector<double>::difference_type
>(bin);
43 return 0.5 * ((*binIter) + *(std::next(binIter)));
57constexpr size_t MIN_VEC_LENGTH_PARALLEL_SORT{5000};
60constexpr size_t EXP_COMRESS_RATIO{10};
65class CompressSparseFloat :
public CompressEventAccumulator {
68 CompressSparseFloat(std::shared_ptr<std::vector<double>> histogram_bin_edges,
const size_t numEvents,
70 : CompressEventAccumulator(histogram_bin_edges, divisor, bin_mode),
m_is_sorted(false) {
75 double totalWeight()
const override {
return static_cast<double>(
m_tof.size()); }
80 void addEvent(
const float tof)
override {
92 if (
m_tof.size() < 2) {
98 const auto &iter = m_histogram_edges->cbegin();
99 const auto delta = 1. /
static_cast<float>((*(iter + 1)) - (*iter));
102 if (
m_tof.size() < MIN_VEC_LENGTH_PARALLEL_SORT)
108 return std::floor(left * delta) < std::floor(right * delta);
114 void createWeightedEvents(std::vector<Mantid::DataObjects::WeightedEventNoTime> *raw_events)
const override {
120 }
else if (
m_tof.size() == 1) {
123 raw_events->emplace_back(
m_tof.front(), 1., 1.);
130 raw_events->reserve(
m_tof.size() / EXP_COMRESS_RATIO);
134 const auto optional_bin_first = this->findBin(
m_tof.front());
135 size_t lastBin = optional_bin_first.value();
136 double nextTof = m_histogram_edges->at(lastBin + 1);
138 for (
const auto &tof :
m_tof) {
139 if (lastBin + 1 >= m_histogram_edges->size()) {
148 const auto evtof = this->getBinCenter(lastBin);
149 const auto counts_f =
static_cast<float>(counts);
150 raw_events->emplace_back(evtof, counts_f, counts_f);
156 if (
static_cast<double>(tof) < m_histogram_edges->operator[](lastBin + 2)) {
161 const auto optional_bin = this->findBin(tof);
162 lastBin = optional_bin.value();
164 nextTof = m_histogram_edges->operator[](lastBin + 1);
170 const auto evtof = this->getBinCenter(lastBin);
171 const auto counts_f =
static_cast<float>(counts);
172 raw_events->emplace_back(evtof, counts_f, counts_f);
193class CompressSparseInt :
public CompressEventAccumulator {
196 CompressSparseInt(std::shared_ptr<std::vector<double>> histogram_bin_edges,
const size_t numEvents,
198 : CompressEventAccumulator(histogram_bin_edges, divisor, bin_mode),
m_is_sorted(
false) {
200 m_initialized =
true;
203 double totalWeight()
const override {
return static_cast<double>(
m_tof_bin.size()); }
208 void addEvent(
const float tof)
override {
210 const auto &bin_optional = this->findBin(tof);
212 m_tof_bin.push_back(
static_cast<uint32_t
>(bin_optional.value()));
226 if (
m_tof_bin.size() < MIN_VEC_LENGTH_PARALLEL_SORT)
233 void createWeightedEvents(std::vector<Mantid::DataObjects::WeightedEventNoTime> *raw_events)
const override {
242 const auto tof = this->getBinCenter(
m_tof_bin.front());
243 raw_events->emplace_back(tof, 1., 1.);
244 }
else if (
m_tof_bin.size() < (MAX_EVENTS / 10)) {
248 while (std::distance(
m_tof_bin.begin(), last_end) > 0) {
250 const auto bin = *(last_end - 1);
254 auto new_end = std::remove(
m_tof_bin.begin(), last_end, bin);
257 const auto counts =
static_cast<float>(std::distance(new_end, last_end));
263 const auto tof = this->getBinCenter(bin);
264 raw_events->emplace_back(tof, counts, counts);
268 raw_events->reserve(
m_tof_bin.size() / EXP_COMRESS_RATIO);
277 while (iter != iter_end) {
278 auto range = std::equal_range(iter, iter_end, *iter);
280 const auto counts =
static_cast<float>(std::distance(range.first, range.second));
282 const auto tof = this->getBinCenter(*iter);
283 raw_events->emplace_back(tof, counts, counts);
309class CompressDense :
public CompressEventAccumulator {
312 CompressDense(std::shared_ptr<std::vector<double>> histogram_bin_edges,
const double divisor,
314 : CompressEventAccumulator(histogram_bin_edges, divisor, bin_mode) {}
316 double totalWeight()
const override {
return std::accumulate(
m_count.cbegin(),
m_count.cend(), 0.); }
321 void addEvent(
const float tof)
override {
322 if (!m_initialized) {
323 this->allocateFineHistogram();
324 m_initialized =
true;
328 const auto &bin_optional = this->findBin(tof);
330 m_count[bin_optional.value()]++;
334 void createWeightedEvents(std::vector<Mantid::DataObjects::WeightedEventNoTime> *raw_events)
const override {
338 const auto NUM_BINS =
m_count.size();
339 for (
size_t i = 0; i < NUM_BINS; ++i) {
341 const auto counts =
static_cast<float>(
m_count[i]);
343 const auto tof = this->getBinCenter(i);
344 raw_events->emplace_back(tof, counts, counts);
352 void allocateFineHistogram() {
353 const auto NUM_BINS =
static_cast<size_t>(m_histogram_edges->size() - 1);
366 std::shared_ptr<std::vector<double>> histogram_bin_edges,
const double divisor,
CompressBinningMode bin_mode)
367 : m_divisor(divisor), m_bin_mode(bin_mode), m_histogram_edges(
std::move(histogram_bin_edges)) {}
387 if (num_events > NUM_EDGES) {
390 }
else if (num_events < CompressSparseInt::MAX_EVENTS) {
std::vector< float > m_tof
sum of all time-of-flight within the bin
std::vector< uint32_t > m_tof_bin
std::vector< uint32_t > m_count
sum of all events seen in an individual bin
static constexpr size_t MAX_EVENTS
CompressEventAccumulatorFactory(std::shared_ptr< std::vector< double > > histogram_bin_edges, const double divisor, CompressBinningMode bin_mode)
CompressBinningMode m_bin_mode
std::unique_ptr< CompressEventAccumulator > create(const std::size_t num_events)
const std::shared_ptr< std::vector< double > > m_histogram_edges
std::optional< size_t >(* m_findBin)(const MantidVec &, const double, const double, const double, const bool)
function pointer on how to find the bin boundaries
std::optional< size_t > findBin(const float tof) const
CompressEventAccumulator(std::shared_ptr< std::vector< double > > histogram_bin_edges, const double divisor, CompressBinningMode bin_mode)
double getBinCenter(const INT_TYPE bin) const
const std::shared_ptr< std::vector< double > > m_histogram_edges
shared pointer for the histogram bin boundaries
std::size_t numberHistBins() const
double m_divisor
keep track if the m_tof is already sorted
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.
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.
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.
EventSortType
How the event list is sorted.
Helper class which provides the Collimation Length for SANS instruments.