Belle II Software development
CDCDedxCosineCor.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <cdc/dbobjects/CDCDedxCosineCor.h>
10
11#include <cmath>
12
13using namespace Belle2;
14
16 const std::vector<std::vector<double>>& groupCosgains,
17 const std::vector<unsigned int>& layerToGroup)
18{
19
20 // 1. check groups exist
21 if (groupCosgains.empty()) {
22 B2ERROR("CDCDedxCosineCor: groupCosgains is empty.");
23 return;
24 }
25
26 // 2. check layer mapping exists
27 if (layerToGroup.empty()) {
28 B2ERROR("CDCDedxCosineCor: layerToGroup is empty.");
29 return;
30 }
31
32 for (size_t g = 0; g < groupCosgains.size(); ++g) {
33 if (groupCosgains[g].empty()) {
34 B2ERROR("CDCDedx1DCell: group " << g << " is empty.");
35 return;
36 }
37 }
38
39 // 4. check Layer -> group mapping
40 for (size_t layer = 0; layer < layerToGroup.size(); layer++) {
41
42 if (layerToGroup[layer] >= groupCosgains.size()) {
43 B2ERROR("CDCDedxCosineCor: layer " << layer
44 << " refers to invalid group "
45 << layerToGroup[layer]);
46 return;
47 }
48 }
49
50 // 5. store data only after checks pass
51 m_groupCosgains = groupCosgains;
52 m_layerToGroup = layerToGroup;
53
54// summary
55 B2INFO("Cosine groups: " << m_groupCosgains.size());
56 B2INFO("Cosine bins per group: " << m_groupCosgains[0].size());
57
58 for (size_t layer = 0; layer < m_layerToGroup.size(); layer++) {
59 B2INFO("layer " << layer << " -> group " << m_layerToGroup[layer]);
60 }
61
62}
63
64void CDCDedxCosineCor::setCosCor(unsigned int bin, double value)
65{
66 if (bin < m_cosgains.size()) m_cosgains[bin] = value;
67 else B2ERROR("CDCDedxCosineCor: invalid bin number, value not set");
68}
69
70void CDCDedxCosineCor::setCosCor(unsigned int group, unsigned int bin, double value)
71{
72 if (group >= m_groupCosgains.size()) {
73 B2ERROR("CDCDedxCosineCor: invalid group number, value not set");
74 return;
75 }
76
77 if (bin >= m_groupCosgains[group].size()) {
78 B2ERROR("CDCDedxCosineCor: invalid bin number, value not set");
79 return;
80 }
81
82 m_groupCosgains[group][bin] = value;
83}
84
86{
87 // Check that grouped cosine constants exist
88 if (m_groupCosgains.empty()) {
89 B2ERROR("CDCDedxCosineCor : no gain groups");
90 return false;
91 }
92
93 // Check that the layer-to-group mapping exists
94 if (m_layerToGroup.empty()) return false;
95
96 // Verify that every layer refers to a valid group index
97 for (unsigned int layer = 0; layer < m_layerToGroup.size(); ++layer) {
98 if (m_layerToGroup[layer] >= m_groupCosgains.size()) {
99 B2ERROR("CDCDedxCosineCor: layer-to-group map points to invalid group");
100 return false;
101 }
102 }
103
104 for (unsigned int g = 0; g < m_groupCosgains.size(); ++g) {
105 if (m_groupCosgains[g].empty()) {
106 B2ERROR("CDCDedxCosineCor: group " << g << " is empty");
107 return false;
108 }
109 }
110
111 // All checks passed
112 return true;
113}
114
115double CDCDedxCosineCor::getMean(unsigned int bin) const
116{
117 if (bin < m_cosgains.size()) return m_cosgains[bin];
118 B2WARNING("CDCDedxCosineCor: bin out of range, returning value (1.0)");
119 return 1.0;
120}
121
122double CDCDedxCosineCor::getMean(double costh) const
123{
124 if (m_cosgains.empty()) return 1.0;
125 return getMeanFromVector(m_cosgains, costh);
126}
127
128
129double CDCDedxCosineCor::getMean(unsigned int layer, unsigned int bin) const
130{
131 if (isGrouped()) {
132 if (!isValidGroupedPayload()) return 1.0;
133
134 if (layer >= m_layerToGroup.size()) {
135 B2ERROR("CDCDedxCosineCor: invalid layer index");
136 return 1.0;
137 }
138
139 const unsigned int group = m_layerToGroup[layer];
140 if (bin >= m_groupCosgains[group].size()) {
141 B2ERROR("CDCDedxCosineCor: invalid bin number");
142 return 1.0;
143 }
144
145 return m_groupCosgains[group][bin];
146 }
147
148 return getMean(bin);
149}
150
151double CDCDedxCosineCor::getMean(unsigned int layer, double costh) const
152{
153 if (isGrouped()) {
154 if (!isValidGroupedPayload()) return 1.0;
155
156 if (layer >= m_layerToGroup.size()) {
157 B2ERROR("CDCDedxCosineCor: invalid layer index");
158 return 1.0;
159 }
160
161 const unsigned int group = m_layerToGroup[layer];
162 return getMeanFromVector(m_groupCosgains[group], costh);
163 }
164
165 return getMean(costh);
166}
167
168
169double CDCDedxCosineCor::getMeanFromVector(const std::vector<double>& gains, double costh) const
170{
171 if (std::abs(costh) > 1.0) return 0.0;
172 if (gains.empty()) return 1.0;
173
174 // gains are stored at the center of the bins
175 // find the bin center immediately preceding this value of costh
176 const double binsize = 2.0 / gains.size();
177 const int bin = std::floor((costh - 0.5 * binsize + 1.0) / binsize);
178
179 int thisbin = bin;
180 int nextbin = bin + 1;
181
182 // extrapolation
183 // extrapolate backward for lowest half-bin and center positive half-bin
184 // extrapolate forward for highest half-bin and center negative half-bin
185 double halfBin = binsize / 2.0;
186 if ((costh + 1.0) < halfBin || (costh > 0.0 && costh < halfBin)) {
187 thisbin = bin + 1;
188 nextbin = bin + 2;
189 } else if ((costh - 1.0) > -1.0 * halfBin || (costh < 0.0 && costh > -1.0 * halfBin)) {
190 thisbin = bin - 1;
191 nextbin = bin;
192 }
193
194 const double frac = ((costh - 0.5 * binsize + 1.0) / binsize) - thisbin;
195
196 if (thisbin < 0 || static_cast<unsigned int>(nextbin) >= gains.size()) {
197 B2WARNING("Problem with extrapolation of CDC dE/dx cosine correction");
198 return 1.0;
199 }
200
201 return (gains[nextbin] - gains[thisbin]) * frac + gains[thisbin];
202}
203
204bool CDCDedxCosineCor::multiplyGains(std::vector<double>& lhs, const std::vector<double>& rhs) const
205{
206 if (rhs.empty() || lhs.size() % rhs.size() != 0) {
207 return false;
208 }
209
210 const int scale = std::floor(static_cast<double>(lhs.size()) / rhs.size() + 0.001);
211
212 for (unsigned int bin = 0; bin < lhs.size(); ++bin) {
213 lhs[bin] *= rhs[std::floor(bin / static_cast<double>(scale) + 0.001)];
214 }
215
216 return true;
217}
218
220{
221 // old x old
222 if (!isGrouped() && !rhs.isGrouped()) {
223 if (!multiplyGains(m_cosgains, rhs.getCosCor())) {
224 B2WARNING("Cosine gain parameters do not match, cannot merge!");
225 }
226 return *this;
227 }
228
229 // grouped x grouped
230 if (isGrouped() && rhs.isGrouped()) {
232 B2WARNING("Invalid grouped cosine payload, cannot merge!");
233 return *this;
234 }
235
236 if (m_layerToGroup != rhs.getLayerMap()) {
237 B2WARNING("layer grouping does not match, cannot merge grouped cosine payloads!");
238 return *this;
239 }
240
241 const std::vector<std::vector<double>>& rhsGroups = rhs.getGroupCosCor();
242
243 if (m_groupCosgains.size() != rhsGroups.size()) {
244 B2WARNING("Number of cosine groups does not match, cannot merge!");
245 return *this;
246 }
247
248 for (unsigned int group = 0; group < m_groupCosgains.size(); ++group) {
249 if (!multiplyGains(m_groupCosgains[group], rhsGroups[group])) {
250 B2WARNING("Grouped cosine gain parameters do not match, cannot merge!");
251 return *this;
252 }
253 }
254 return *this;
255 }
256
257 B2WARNING("Cannot merge old-style and grouped cosine payloads directly!");
258 return *this;
259}
std::vector< std::vector< double > > m_groupCosgains
grouped dE/dx gains [group][bin]
std::vector< unsigned int > m_layerToGroup
map from layer index to group index
CDCDedxCosineCor()
Default constructor.
void setCosCor(unsigned int bin, double value)
Set old-style cosine correction.
double getMeanFromVector(const std::vector< double > &gains, double costh) const
Helper to interpolate/extrapolate from one vector of gains.
bool multiplyGains(std::vector< double > &lhs, const std::vector< double > &rhs) const
Multiply lhs by rhs with possible rebinning.
bool isGrouped() const
Check whether grouped mode is used.
const std::vector< std::vector< double > > & getGroupCosCor() const
Get the grouped calibration constants.
CDCDedxCosineCor & operator*=(const CDCDedxCosineCor &rhs)
Combine payloads.
std::vector< double > m_cosgains
old-style dE/dx gains in cos(theta) bins
bool isValidGroupedPayload() const
Validate grouped payload content.
const std::vector< double > & getCosCor() const
Get the old-style calibration constants.
const std::vector< unsigned int > & getLayerMap() const
Get the Layer-to-group map.
double getMean(unsigned int bin) const
Return dE/dx mean value for the given bin in old mode.
Abstract base class for different kinds of events.