15#include "tbb/parallel_for.h"
19namespace DataHandling {
21 API::Progress *prog, std::shared_ptr<std::vector<uint32_t>> event_detid,
22 std::shared_ptr<std::vector<float>> event_tof,
size_t startAt,
23 std::shared_ptr<std::vector<uint64_t>> event_index,
24 std::shared_ptr<BankPulseTimes> bankPulseTimes, detid_t min_detid,
26 std::shared_ptr<std::vector<double>> histogram_bin_edges,
28 :
Task(), m_loader(m_loader), m_entry_name(entry_name), m_prog(prog), m_event_detid(
std::move(event_detid)),
29 m_event_tof(
std::move(event_tof)), m_firstEventIndex(startAt), m_event_index(
std::move(event_index)),
30 m_bankPulseTimes(
std::move(bankPulseTimes)),
m_detid_min(min_detid), m_detid_max(max_detid),
31 m_tof_min(static_cast<float>(histogram_bin_edges->front())),
32 m_tof_max(static_cast<float>(histogram_bin_edges->back())) {
43 const auto divisor_abs = abs(divisor);
44 m_factory = std::make_unique<CompressEventAccumulatorFactory>(histogram_bin_edges, divisor_abs, bin_mode);
48size_t estimate_avg_events(
const size_t num_events,
const size_t num_dets,
const size_t num_periods) {
49 double result =
static_cast<double>(num_events) /
static_cast<double>(num_dets) /
static_cast<double>(num_periods);
50 return static_cast<size_t>(result);
57 const auto NUM_EVENTS_AVG = estimate_avg_events(
m_event_detid->size(), NUM_DETS, NUM_PERIODS);
59 std::vector<size_t> counts;
61 const auto detid_min =
static_cast<size_t>(
m_detid_min);
62 const auto detid_max =
static_cast<size_t>(
m_detid_max);
63 counts.assign(NUM_DETS + 1, 0);
65 if (!(detid < detid_min || detid > detid_max))
66 counts[detid - detid_min]++;
71 for (
size_t periodIndex = 0; periodIndex < NUM_PERIODS; ++periodIndex) {
73 for (
size_t det_index = 0; det_index <= NUM_DETS; ++det_index) {
93 const auto tof =
m_event_tof->operator[](event_index);
99 const auto det_index =
static_cast<size_t>(detid -
m_detid_min);
112 std::vector<size_t> pulseROI;
113 if (alg->m_is_time_filtered) {
114 pulseROI =
m_bankPulseTimes->getPulseIndices(alg->filter_time_start, alg->filter_time_stop);
117 if (alg->filter_bad_pulses) {
119 pulseROI,
m_bankPulseTimes->getPulseIndices(alg->bad_pulses_timeroi->toTimeIntervals()));
123 for (
const auto &pulseIter : pulseIndexer) {
124 const int logPeriodNumber =
m_bankPulseTimes->periodNumber(pulseIter.pulseIndex);
125 const auto periodIndex =
static_cast<size_t>(logPeriodNumber - 1);
128 for (std::size_t eventIndex = pulseIter.eventIndexStart; eventIndex < pulseIter.eventIndexStop; ++eventIndex) {
129 this->
addEvent(periodIndex, eventIndex);
134 constexpr size_t periodIndex{0};
135 for (std::size_t eventIndex = 0; eventIndex < NUM_EVENTS; ++eventIndex) {
136 this->
addEvent(periodIndex, eventIndex);
156 std::vector<Mantid::DataObjects::WeightedEventNoTime> *raw_events) {
158 std::stringstream msg;
159 msg <<
"Encountered invalid detid=" << detid;
160 throw std::runtime_error(msg.str());
163 const auto det_index =
static_cast<size_t>(detid -
m_detid_min);
164 m_spectra_accum[period_index][det_index]->createWeightedEvents(raw_events);
173class EventCreationTask {
175 EventCreationTask(std::vector<std::unique_ptr<DataHandling::CompressEventAccumulator>> *accumulators,
176 std::vector<std::vector<Mantid::DataObjects::WeightedEventNoTime> *> *eventlists,
177 const detid_t detid_min, std::vector<DataObjects::EventSortType> *sorting)
181 void operator()(
const tbb::blocked_range<size_t> &range)
const {
184 if (accumulator->totalWeight() > 0.) {
189 if (
static_cast<double>(raw_events->capacity()) > 1.1 *
static_cast<double>(raw_events->size()))
190 raw_events->shrink_to_fit();
200 std::vector<std::unique_ptr<DataHandling::CompressEventAccumulator>> *
m_accumulators;
201 std::vector<std::vector<Mantid::DataObjects::WeightedEventNoTime> *> *
m_eventlists;
213 for (
size_t period_index = 0; period_index < num_periods; ++period_index) {
218 const size_t grainsize = std::min<size_t>(20, num_dets / 20);
219 tbb::parallel_for(tbb::blocked_range<size_t>(0, num_dets, grainsize), create_task);
251 const detid_t detid_offset = detid + pixelID_to_wi_offset;
252 if (!(detid_offset < 0 || detid_offset >= pixelIDtoWSVec_size)) {
254 if (wi < numEventLists) {
256 outputWS.getSpectrum(wi).setSortOrder(sortOrder);
262 if (alg->getLogger().isDebug())
263 alg->getLogger().debug() <<
"Time to ProcessBankCompressed " <<
m_entry_name <<
" " << timer <<
"\n";
268 double totalWeightedEvents = std::accumulate(
270 return current + std::accumulate(period_spectra.cbegin(), period_spectra.cend(), 0.,
271 [](const auto ¤t, const auto &spectra_accum) {
272 return current + spectra_accum->totalWeight();
275 return totalWeightedEvents;
std::map< DeltaEMode::Type, std::string > index
std::vector< std::unique_ptr< DataHandling::CompressEventAccumulator > > * m_accumulators
std::vector< DataObjects::EventSortType > * m_sorting
std::vector< std::vector< Mantid::DataObjects::WeightedEventNoTime > * > * m_eventlists
Kernel::Logger & getLogger() const
Returns a reference to the logger.
Helper class for reporting progress from algorithms.
Helper class for LoadEventNexus that is specific to the current default loading code for NXevent_data...
std::vector< std::vector< std::vector< Mantid::DataObjects::WeightedEventNoTime > * > > weightedNoTimeEventVectors
Vector where index = event_id; value = ptr to std::vector<WeightedEventNoTime> in the event list.
bool precount
Do we pre-count the # of events in each pixel ID?
std::vector< size_t > pixelID_to_wi_vector
Vector where (index = pixel ID+pixelID_to_wi_offset), value = workspace index)
detid_t pixelID_to_wi_offset
Offset in the pixelID_to_wi_vector to use.
EventWorkspaceCollection & m_ws
size_t getNumberHistograms() const
std::vector< DataObjects::EventSortType > m_sorting
std::shared_ptr< BankPulseTimes > m_bankPulseTimes
Pulse times for this bank.
void addEvent(const size_t period_index, const size_t event_index)
std::unique_ptr< CompressEventAccumulatorFactory > m_factory
factory for creating accumulators
std::shared_ptr< std::vector< uint64_t > > m_event_index
vector of event index (length of # of pulses)
DefaultEventLoader & m_loader
Algorithm being run.
double totalWeight() const
method only intended for testing
const size_t m_firstEventIndex
index of the first event from event_index
std::shared_ptr< std::vector< uint32_t > > m_event_detid
event pixel ID array
API::Progress * m_prog
Progress reporting.
const std::string m_entry_name
std::shared_ptr< std::vector< float > > m_event_tof
event TOF array
void createAccumulators(const bool precount)
void createWeightedEvents(const size_t period_index, const detid_t detid, std::vector< Mantid::DataObjects::WeightedEventNoTime > *raw_events)
const detid_t m_detid_max
void run() override
Main method that performs the work for the task.
const detid_t m_detid_min
std::vector< std::vector< std::unique_ptr< DataHandling::CompressEventAccumulator > > > m_spectra_accum
Objects holding individual spectra.
PulseIndexer contains information for mapping from pulse index/number to event index.
void debug(const std::string &msg)
Logs at debug level.
bool isDebug() const
Returns true if log level is at least debug.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
A Task is a unit of work to be scheduled and run by a ThreadPool.
double m_cost
Cached computational cost for the thread.
A simple class that provides a wall-clock (not processor time) timer.
std::vector< TYPE > calculate_intersection(const std::vector< TYPE > &left, const std::vector< TYPE > &right)
This calculates the intersection of two sorted vectors that represent regions of interest (ROI).
Helper class which provides the Collimation Length for SANS instruments.
int32_t detid_t
Typedef for a detector ID.