33 std::vector<std::string> &bankEntryNames, H5::H5File &h5file,
const bool is_time_filtered,
34 std::vector<int> &workspaceIndices, std::vector<API::MatrixWorkspace_sptr> &wksps,
35 const std::map<detid_t, double> &calibration,
const std::map<detid_t, double> &scale_at_sample,
36 const std::set<detid_t> &masked,
const size_t events_per_chunk,
const size_t grainsize_event,
37 const std::vector<PulseROI> &pulse_indices,
const std::map<Mantid::Types::Core::DateAndTime, int> &splitterMap,
38 std::shared_ptr<API::Progress> &progress)
39 : m_h5file(h5file), m_bankEntries(bankEntryNames),
40 m_loader(
std::make_shared<
NexusLoader>(is_time_filtered, pulse_indices)), m_workspaceIndices(workspaceIndices),
41 m_wksps(wksps), m_calibration(calibration), m_scale_at_sample(scale_at_sample), m_masked(masked),
42 m_events_per_chunk(events_per_chunk), m_splitterMap(splitterMap), m_grainsize_event(grainsize_event),
43 m_progress(progress) {}
46 std::vector<std::string> &bankEntryNames, H5::H5File &h5file, std::shared_ptr<NexusLoader> loader,
47 std::vector<int> &workspaceIndices, std::vector<API::MatrixWorkspace_sptr> &wksps,
48 const std::map<detid_t, double> &calibration,
const std::map<detid_t, double> &scale_at_sample,
49 const std::set<detid_t> &masked,
const size_t events_per_chunk,
const size_t grainsize_event,
50 const std::map<Mantid::Types::Core::DateAndTime, int> &splitterMap, std::shared_ptr<API::Progress> &progress)
51 : m_h5file(h5file), m_bankEntries(bankEntryNames), m_loader(
std::move(loader)),
52 m_workspaceIndices(workspaceIndices), m_wksps(wksps), m_calibration(calibration),
53 m_scale_at_sample(scale_at_sample), m_masked(masked), m_events_per_chunk(events_per_chunk),
54 m_splitterMap(splitterMap), m_grainsize_event(grainsize_event), m_progress(progress) {}
57 auto entry =
m_h5file.openGroup(
"entry");
58 for (
size_t wksp_index = range.begin(); wksp_index < range.end(); ++wksp_index) {
61 if (bankName.empty()) {
65 g_log.
debug() << bankName <<
" start" << std::endl;
68 auto event_group = entry.openGroup(bankName);
72 const int64_t total_events =
static_cast<size_t>(tof_SDS.getSpace().getSelectNpoints());
73 if (total_events == 0) {
78 std::unique_ptr<std::vector<uint64_t>> event_index = std::make_unique<std::vector<uint64_t>>();
79 auto eventRanges =
m_loader->getEventIndexRanges(event_group, total_events, &event_index);
83 std::vector<API::ISpectrum *> spectra;
84 std::vector<std::vector<uint32_t>> y_temps;
85 for (
const auto &wksp :
m_wksps) {
86 spectra.push_back(&wksp->getSpectrum(wksp_index));
87 y_temps.emplace_back(spectra.back()->dataY().size());
91 std::unique_ptr<BankCalibration> calibration =
nullptr;
99 const auto frequency_log =
101 if (!frequency_log) {
102 throw std::runtime_error(
"Frequency log not found");
104 const auto pulse_times =
105 std::make_unique<std::vector<Mantid::Types::Core::DateAndTime>>(frequency_log->timesAsVector());
108 auto event_detid = std::make_unique<std::vector<uint32_t>>();
109 auto event_time_of_flight = std::make_unique<std::vector<float>>();
110 auto pulse_times_idx = std::make_unique<std::vector<size_t>>();
113 while (!eventRanges.empty()) {
117 std::vector<size_t> offsets;
118 std::vector<size_t> slabsizes;
120 size_t total_events_to_read = 0;
124 auto eventRange = eventRanges.top();
127 size_t range_size = eventRange.second - eventRange.first;
131 if (range_size > remaining_chunk) {
133 offsets.push_back(eventRange.first);
134 slabsizes.push_back(remaining_chunk);
135 total_events_to_read += remaining_chunk;
137 eventRanges.emplace(eventRange.first + remaining_chunk, eventRange.second);
140 offsets.push_back(eventRange.first);
141 slabsizes.push_back(range_size);
142 total_events_to_read += range_size;
148 std::ostringstream oss;
149 oss <<
"Processing " << bankName <<
" with " << total_events_to_read <<
" events in the ranges: ";
150 for (
size_t i = 0; i < offsets.size(); ++i) {
151 oss <<
"[" << offsets[i] <<
", " << (offsets[i] + slabsizes[i]) <<
"), ";
157 tbb::parallel_invoke(
159 m_loader->loadData(detID_SDS, event_detid, offsets, slabsizes);
163 if ((!calibration) || (calibration->idmin() >
static_cast<detid_t>(
minval)) ||
171 m_loader->loadData(tof_SDS, event_time_of_flight, offsets, slabsizes);
174 pulse_times_idx->resize(total_events_to_read);
177 auto event_index_it = event_index->cbegin();
178 for (
size_t i = 0; i < offsets.size(); ++i) {
179 const size_t off = offsets[i];
180 const size_t slab = slabsizes[i];
181 for (
size_t j = 0; j < slab; ++j) {
182 const uint64_t global_idx =
static_cast<uint64_t
>(off + j);
184 while (event_index_it != event_index->cend() && *event_index_it <= global_idx) {
187 size_t pulse_idx = 0;
188 if (event_index_it != event_index->cbegin()) {
189 pulse_idx =
static_cast<size_t>(std::distance(event_index->cbegin(), event_index_it) - 1);
191 (*pulse_times_idx)[pos++] = pulse_idx;
197 tbb::blocked_range<size_t>(0,
m_workspaceIndices.size()), [&](
const tbb::blocked_range<size_t> &r) {
198 for (size_t idx = r.begin(); idx != r.end(); ++idx) {
199 int i = m_workspaceIndices[idx];
202 std::vector<size_t> indices;
203 auto splitter_it = m_splitterMap.cbegin();
204 for (size_t k = 0; k < event_detid->size(); ++k) {
207 const double correctionFactor =
208 calibration->value_scale_at_sample(static_cast<detid_t>((*event_detid)[k]));
210 const auto tof_in_nanoseconds =
211 static_cast<int64_t>(static_cast<double>((*event_time_of_flight)[k]) * correctionFactor);
212 const auto pulsetime = (*pulse_times)[(*pulse_times_idx)[k]];
213 const Mantid::Types::Core::DateAndTime full_time = pulsetime + tof_in_nanoseconds;
219 while (splitter_it != m_splitterMap.end() &&
220 splitter_it->first <= pulsetime - static_cast<int64_t>(PULSETIME_OFFSET)) {
227 auto full_time_it = splitter_it;
228 while (full_time_it != m_splitterMap.end() && full_time_it->first <= full_time) {
234 if (full_time_it == m_splitterMap.begin()) {
238 if (full_time_it != m_splitterMap.end() && full_time_it->second == i) {
239 indices.push_back(k);
244 auto event_id_view_for_target =
245 indices | std::views::transform([&event_detid](const auto &k) { return (*event_detid)[k]; });
246 auto event_tof_view_for_target = indices | std::views::transform([&event_time_of_flight](const auto &k) {
247 return (*event_time_of_flight)[k];
250 ProcessEventsTask task(&event_id_view_for_target, &event_tof_view_for_target, calibration.get(),
251 &spectra[idx]->readX());
253 const tbb::blocked_range<size_t> range_info(0, indices.size(), m_grainsize_event);
254 tbb::parallel_reduce(range_info, task);
256 std::transform(y_temps[idx].begin(), y_temps[idx].end(), task.y_temp.begin(), y_temps[idx].begin(),
257 std::plus<uint32_t>());
263 tbb::parallel_for(
size_t(0),
m_wksps.size(), [&](
size_t i) {
264 auto &y_values = spectra[i]->dataY();
265 std::copy(y_temps[i].cbegin(), y_temps[i].cend(), y_values.begin());
268 g_log.
debug() << bankName <<
" stop" << timer << std::endl;