Mantid
Loading...
Searching...
No Matches
BankCalibration.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2025 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7
9#include <algorithm>
10#include <stdexcept>
11
13
14namespace {
15void copy_values_from_map_to_offset_vector(const std::map<detid_t, double> &map_values, const detid_t idmin,
16 const detid_t idmax, std::vector<double> &vector_values) {
17 // allocate memory and set the default value to 1
18 vector_values.assign(static_cast<size_t>(idmax - idmin + 1), 1.);
19
20 // set up iterators for copying data - assumes ordered map
21 auto iter = std::find_if(map_values.cbegin(), map_values.cend(),
22 [idmin](const auto &itervalue) { return itervalue.first >= idmin; });
23 if (iter == map_values.end())
24 throw std::runtime_error("Failed to find idmin=" + std::to_string(idmin) + " in map");
25 auto iter_end =
26 std::find_if(iter, map_values.cend(), [idmax](const auto itervalue) { return itervalue.first > idmax; });
27
28 // copy over values that matter
29 for (; iter != iter_end; ++iter) {
30 const auto index = static_cast<size_t>(iter->first - idmin);
31 vector_values[index] = iter->second;
32 }
33}
34} // namespace
35
36// ------------------------ BankCalibration object
49BankCalibration::BankCalibration(const double time_conversion, const std::set<detid_t> &det_in_group,
50 const std::map<detid_t, double> &calibration_map,
51 const std::map<detid_t, double> &scale_at_sample, const std::set<detid_t> &mask) {
52 if (det_in_group.empty())
53 return;
54
55 // determine the range
56 const detid_t idmin_found = *det_in_group.begin();
57 const detid_t idmax_found = *std::prev(det_in_group.end());
58
59 // all the outputs are vectors that are offset by the minimum detid in the bank
60 m_detid_offset = idmin_found;
61
62 // get the values copied over for calibration
63 copy_values_from_map_to_offset_vector(calibration_map, idmin_found, idmax_found, m_calibration);
64 // apply time conversion here so it is effectively applied for each detector once rather than on each event
65 if (time_conversion != 1.) {
66 std::transform(m_calibration.begin(), m_calibration.end(), m_calibration.begin(),
67 [time_conversion](const auto &value) { return std::move(time_conversion * value); });
68 }
69
70 // get the values copied over for scale_at_sample
71 if (!scale_at_sample.empty())
72 copy_values_from_map_to_offset_vector(scale_at_sample, idmin_found, idmax_found, m_scale_at_sample);
73
74 // mask values that are in the mask or not in the detector group
75
76 // mask anything that isn't in the group this assumes both are sorted
77 // find the first and last detector id that is in the range being used
78 for (size_t i = 0; i < m_calibration.size(); ++i) {
79 if (m_calibration[i] != IGNORE_PIXEL) {
80 const detid_t detid = static_cast<detid_t>(i) + m_detid_offset;
81 if (!det_in_group.contains(detid) || mask.contains(detid)) {
82 m_calibration[i] = IGNORE_PIXEL; // not in the list or masked
83 }
84 }
85 }
86}
87
88bool BankCalibration::detidInRange(const detid_t detid) const {
89 return (!(detid < this->idmin() || detid > this->idmax())); // doesn't always check both
90}
91
96const double &BankCalibration::value_calibration(const detid_t detid) const {
97 if (this->detidInRange(detid))
98 return m_calibration[detid - m_detid_offset];
99 else
100 return IGNORE_PIXEL;
101}
102
103double BankCalibration::value_scale_at_sample(const detid_t detid) const {
104 if (this->detidInRange(detid))
105 return m_scale_at_sample[detid - m_detid_offset];
106 else
107 return IGNORE_PIXEL;
108}
109
111detid_t BankCalibration::idmax() const { return m_detid_offset + static_cast<detid_t>(m_calibration.size()) - 1; }
112
113bool BankCalibration::empty() const { return m_calibration.empty(); }
114
115// ----------------- BankCalibrationFactory implementation
116BankCalibrationFactory::BankCalibrationFactory(const std::map<detid_t, double> &calibration_map,
117 const std::map<detid_t, double> &scale_at_sample,
118 const std::map<size_t, std::set<detid_t>> &grouping,
119 const std::set<detid_t> &mask,
120 const std::map<size_t, std::set<detid_t>> &bank_detids)
121 : m_calibration_map(calibration_map), m_scale_at_sample(scale_at_sample), m_grouping(grouping), m_mask(mask),
122 m_bank_detids(bank_detids) {}
123
124std::vector<BankCalibration> BankCalibrationFactory::getCalibrations(const double time_conversion,
125 const size_t bank_index) const {
126
127 std::vector<BankCalibration> calibrations;
128
129 // When arbitrary grouping is used, we need to calculate the intersection of each group with the bank detids. The
130 // intersection may be empty which means that no detectors from that bank are in this group.
131 if (!m_bank_detids.contains(bank_index))
132 return calibrations; // empty
133
134 const auto &bank_detids = m_bank_detids.at(bank_index);
135
136 calibrations.reserve(m_grouping.size());
137
138 std::transform(m_grouping.begin(), m_grouping.end(), std::back_inserter(calibrations),
139 [this, time_conversion, bank_detids](const auto &pair) {
140 std::set<detid_t> detids_intersection;
141 std::set_intersection(pair.second.begin(), pair.second.end(), bank_detids.begin(), bank_detids.end(),
142 std::inserter(detids_intersection, detids_intersection.begin()));
143 return BankCalibration(time_conversion, detids_intersection, m_calibration_map, m_scale_at_sample,
144 m_mask);
145 });
146
147 return calibrations;
148}
149
150} // namespace Mantid::DataHandling::AlignAndFocusPowderSlim
double value
The value of the point.
Definition FitMW.cpp:51
std::map< DeltaEMode::Type, std::string > index
const std::map< size_t, std::set< detid_t > > & m_grouping
detector ids for output workspace index
const std::map< size_t, std::set< detid_t > > & m_bank_detids
std::vector< BankCalibration > getCalibrations(const double time_conversion, const size_t bank_index) const
Select which detector ids go into the output group.
BankCalibrationFactory(const std::map< detid_t, double > &calibration_map, const std::map< detid_t, double > &scale_at_sample, const std::map< size_t, std::set< detid_t > > &grouping, const std::set< detid_t > &mask, const std::map< size_t, std::set< detid_t > > &bank_detids)
const double & value_calibration(const detid_t detid) const
This assumes that everything is in range.
BankCalibration(const double time_conversion, const std::set< detid_t > &det_in_group, const std::map< detid_t, double > &calibration_map, const std::map< detid_t, double > &scale_at_sample, const std::set< detid_t > &mask)
Calibration of a subset of pixels as requested in the constructor.
double value_scale_at_sample(const detid_t detid) const
This returns a value with no bounds checking.
int32_t detid_t
Typedef for a detector ID.
std::string to_string(const wide_integer< Bits, Signed > &n)