ATLAS Offline Software
Loading...
Searching...
No Matches
BinningData.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3*/
4
6// BinningData.h, (c) ATLAS Detector software
8
9#ifndef TRKDETDESCRUTILS_BINNINGDATA_H
10#define TRKDETDESCRUTILS_BINNINGDATA_H
11
12// Gaudi
13#include "GaudiKernel/GaudiException.h"
14// Eigen
17
18#include <cmath>
19
20#include <utility>
21#include <vector>
22
23class MsgStream;
24
25namespace Trk {
26
31{
33 next = 1
34};
35
45
46class BinningData final
47{
48public:
53 size_t bins;
54 float min;
55 float max;
56 float step;
57 float subStep;
58 float refphi; // ref Phi for binH
59 std::vector<float> boundaries;
60 std::vector<std::pair<int, float>> hbounds; // boundary for binH
61
62 /* Default ctor,copy,move assignment,dtor*/
63 BinningData(const BinningData&) = default;
65 BinningData& operator=(const BinningData&) = default;
67 ~BinningData() = default;
68
71 BinningOption bOption,
72 BinningValue bValue,
73 size_t bBins,
74 float bMin,
75 float bMax,
76 float bStep,
77 float bSubStep = 0,
78 std::vector<float> bBoundaries = std::vector<float>())
79 : type(bType)
80 , option(bOption)
81 , binvalue(bValue)
82 , bins(bBins)
83 , min(bMin)
84 , max(bMax)
85 , step(bStep != 0. ? bStep : 1.)
86 , subStep(bSubStep)
87 , refphi(0.)
88 , boundaries(std::move(bBoundaries))
89 , hbounds(std::vector<std::pair<int, float>>())
90 , m_mixPtr(nullptr)
91 {
92 if (bType == Trk::equidistant)
94 else if (bType == Trk::biequidistant)
96 else
98 }
99
102 float bRefPhi,
103 const std::vector<std::pair<int, float>>& bBoundaries)
104 : type(Trk::arbitrary)
105 , option(bOption)
106 , binvalue(Trk::binH)
107 , bins(bOption == Trk::open ? bBoundaries.size() - 1 : bBoundaries.size())
108 , min(bBoundaries.front().second)
109 , max(bBoundaries.back().second)
110 , step(1.)
111 , subStep(0.) // non-zero value needed for next()
112 , refphi(bRefPhi)
113 , boundaries(std::vector<float>())
114 , hbounds(bBoundaries)
115 , m_functionPtr(nullptr)
117 {}
118
120 float value(const Amg::Vector2D& lposition) const
121 {
122 // ordered after occurence
124 return lposition[0];
125 if (binvalue == Trk::binPhi)
126 return gaugePhi(lposition[1]);
127 return lposition[1];
128 }
129
131 float value(const Amg::Vector3D& position) const
132 {
133 // ordered after occurence
135 return (position.perp());
136 if (binvalue == Trk::binRPhi)
137 return (position.perp() * position.phi());
138 if (binvalue == Trk::binEta)
139 return (position.eta());
140 if (binvalue < 3)
141 return (position[binvalue]);
142 // phi gauging
143 return gaugePhi(position.phi());
144 }
145
147 float gaugePhi(float phi) const
148 {
149 if (max > M_PI && phi < min && phi < 0.) {
150 phi = M_PI + phi;
151 phi += M_PI;
152 }
153 return phi;
154 }
155
157 std::pair<float, float> valueH(const Amg::Vector2D& lposition) const
158 {
159 return (std::pair<double, double>(lposition[0], lposition[0] * cos(fabs(refphi - lposition[1]))));
160 }
161
163 std::pair<float, float> valueH(const Amg::Vector3D& position) const
164 {
165 return (std::pair<double, double>(position.perp(), position.perp() * cos(fabs(position.phi() - refphi))));
166 }
167
169 bool inside(const Amg::Vector3D& position) const
170 {
171 // closed one is always inside
172 if (option == Trk::closed)
173 return true;
174 // all other options except value H
175 if (binvalue != Trk::binH) {
176 float val = value(position);
177 return (val > min - 0.001 && val < max + 0.001);
178 }
179 // value H case
180 std::pair<double, double> valH = valueH(position);
181 float valmin = hbounds.front().first == 0 ? valH.first : valH.second;
182 float valmax = hbounds.back().first == 0 ? valH.first : valH.second;
183 return (valmin > min - 0.001 && valmax < max + 0.001);
184 }
185
187 bool inside(const Amg::Vector2D& lp) const
188 {
189 if (option == Trk::closed)
190 return true;
191 if (binvalue != Trk::binH) {
192 float val = value(lp);
193 return (val > min - 0.001 && val < max + 0.001);
194 }
195 std::pair<double, double> valH = valueH(lp);
196 float valmin = hbounds.front().first == 0 ? valH.first : valH.second;
197 float valmax = hbounds.back().first == 0 ? valH.first : valH.second;
198 return (valmin > min - 0.001 && valmax < max + 0.001);
199 }
200
202 size_t searchLocal(const Amg::Vector2D& lposition) const
203 {
204 return (binvalue == Trk::binH) ? searchH(valueH(lposition)) : search(value(lposition));
205 }
206
208 size_t searchGlobal(const Amg::Vector3D& position) const
209 {
210 return (binvalue == Trk::binH) ? searchH(valueH(position)) : search(value(position));
211 }
212
214 size_t search(float value) const
215 {
216 assert(m_functionPtr != nullptr);
217 return (*m_functionPtr)(value, *this);
218 }
219
221 size_t searchH(std::pair<double, double> value) const
222 {
223 assert(m_mixPtr != nullptr);
224 return (*m_mixPtr)(value, *this);
225 }
226
228 size_t entry(const Amg::Vector3D& position) const
229 {
230 size_t bin = (binvalue == Trk::binH) ? searchH(valueH(position)) : search(value(position));
231 return (bin < bins - bin) ? bin : bins - 1;
232 }
233
235 size_t next(const Amg::Vector3D& position, const Amg::Vector3D& dir) const
236 {
237 float val = value(position);
238 Amg::Vector3D probe = position + 0.5 * step * dir.normalized();
239 float nextval = value(probe);
240 int bin = (binvalue == Trk::binH) ? searchH(valueH(position)) : search(val);
241 bin = (nextval > val && bin != int(bins - 1)) ? bin + 1 : (bin) ? bin - 1 : 0;
242 // closed setup
243 if (option == closed)
244 return (bin < 0 || bin + 1 > int(bins)) ? ((bin < 0) ? bins - 1 : 0) : bin;
245 // open setup
246 return bin;
247 }
248
250 std::pair<size_t, float> distanceToNext(const Amg::Vector3D& position, const Amg::Vector3D& dir) const
251 {
252 // current value
253 float val = (binvalue == Trk::binH) ? valueH(position).first : value(position);
254 // probe value
255 Amg::Vector3D probe = position + 0.5 * step * dir.normalized();
256 float nextval = (binvalue == Trk::binH) ? valueH(probe).first : value(probe);
257 // current bin
258 int bin0 = (binvalue == Trk::binH) ? searchH(valueH(position)) : search(val);
259 // next bin
260 int bin = (nextval - val) > 0. ? bin0 + 1 : bin0 - 1;
261 if (bin > int(bins) - 1)
262 bin = (option == closed) ? 0 : bin0;
263 if (bin < 0)
264 bin = (option == closed) ? bins - 1 : 0;
265
266 // boundary value
267 float bval = 0.;
268 if (binvalue == Trk::binH) {
269 bval = (nextval > val) ? hbounds[bin0 + 1].second : hbounds[bin0].second; // non-equidistant
270
271 // may need to recalculate current value and probe
272 if (nextval > val) {
273 if (hbounds[bin0 + 1].first > 0) {
274 val = valueH(position).second;
275 nextval = valueH(probe).second;
276 }
277 } else {
278 if (hbounds[bin0].first > 0) {
279 val = valueH(position).second;
280 nextval = valueH(probe).second;
281 }
282 }
283 } else {
284 bval = (nextval > val) ? boundaries[bin0 + 1] : boundaries[bin0]; // non-equidistant
285 if (type == Trk::equidistant)
286 bval = min + bin0 * step;
287 }
288 // differential
289 float dd = 2 * (nextval - val) / step;
290 // distance estimate
291 float dist = std::fabs(dd) > 1.e-06 ? (bval - val) / dd : 1.e06;
292 return std::pair<size_t, float>(bin, dist);
293 }
294
296 LayerOrder orderDirection(const Amg::Vector3D& position, const Amg::Vector3D& dir) const
297 {
298 float val = (binvalue == Trk::binH) ? valueH(position).first : value(position);
299 Amg::Vector3D probe = position + 0.5 * step * dir.normalized();
300 float nextval = (binvalue == Trk::binH) ? valueH(probe).first : value(probe);
301 return (nextval > val) ? Trk::next : Trk::previous;
302 }
303
305 float binPosition(size_t bin, float pos) const
306 {
307
308 if (type == Trk::equidistant)
309 return (min + (2. * bin + pos + 1.) * step / 2.);
310
311 float bmin = (binvalue == Trk::binH) ? hbounds[bin].second : boundaries[bin];
312 float bmax = (binvalue == Trk::binH) ? hbounds[bin + 1].second
313 : bin + 1 < boundaries.size() ? boundaries[bin + 1] : boundaries[bin] + step;
314
315 return (bmin + 0.5 * (pos + 1.) * (bmax - bmin));
316 }
317
318private:
320 size_t (*m_functionPtr)(float, const BinningData&);
321 size_t (*m_mixPtr)(std::pair<float, float>, const BinningData&);
322
324 static size_t searchEaquidstantWithBoundary(float value, const BinningData& bData)
325 {
326 int bin = ((value - bData.min) / bData.step);
327 // special treatment of the 0 bin for closed
328 if (bData.option == closed) {
329 if (value < bData.min)
330 return (bData.bins - 1);
331 if (value > bData.max)
332 return 0;
333 }
334 // if outside boundary : return boundary for open, opposite bin for closed
335 bin = bin < 0 ? ((bData.option == Trk::open) ? 0 : (bData.bins - 1)) : bin;
336 return size_t((bin <= int(bData.bins - 1)) ? bin : ((bData.option == open) ? (bData.bins - 1) : 0));
337 }
338
340 static size_t searchBiequidistantWithBoundary(float value, const BinningData& bData)
341 {
342 // the easy exits (first / last)
343 if (value < bData.min)
344 return (bData.option == closed) ? (bData.bins - 1) : 0;
345 if (value > bData.max)
346 return (bData.option == closed) ? 0 : (bData.bins - 1);
347 // special treatment for first and last bin
348 if (value > bData.max - bData.step)
349 return bData.bins - 1;
350 // decide the leading bin number (low leading bin)
351 size_t leadbin = int((value - bData.min) / bData.step);
352 float bDist = value - (bData.min + (leadbin + 1) * bData.step);
353 int addon = int(bDist / bData.subStep) ? 0 : 1;
354 // return the bin
355 return leadbin * 2 + addon;
356 }
357
359 static size_t searchInVectorWithBoundary(float value, const BinningData& bData)
360 {
361 if (bData.binvalue == binPhi)
362 while (value < bData.boundaries[0])
363 value += 2 * M_PI;
364 if (bData.binvalue == binPhi)
365 while (value > bData.max)
366 value -= 2 * M_PI;
367 // lower boundary
368 if (value <= bData.boundaries[0]) {
369 return (bData.option == closed) ? (bData.bins - 1) : 0;
370 }
371 // higher boundary
372 if (value >= bData.max)
373 return (bData.option == closed) ? 0 : (bData.bins - 1);
374 // search
375 std::vector<float>::const_iterator vIter = bData.boundaries.begin();
376 size_t bin = 0;
377 for (; vIter != bData.boundaries.end(); ++vIter, ++bin)
378 if ((*vIter) > value)
379 break;
380 return (bin - 1);
381 }
382
384 static size_t binarySearchWithBoundary(float value, const BinningData& bData)
385 {
386 // Binary search in an array of n values to locate value
387 if (bData.binvalue == binPhi)
388 while (value < bData.boundaries[0])
389 value += 2 * acos(-1.);
390 if (bData.binvalue == binPhi)
391 while (value > bData.max)
392 value -= 2 * acos(-1.);
393 // underflow
394 if (value <= bData.boundaries[0])
395 return (bData.option == closed) ? (bData.bins - 1) : 0;
396 size_t nabove;
397 size_t nbelow;
398 size_t middle;
399 // overflow
400 nabove = bData.boundaries.size() + 1;
401 if (value >= bData.max)
402 return (bData.option == closed) ? 0 : nabove - 2;
403 // binary search
404 nbelow = 0;
405 while (nabove - nbelow > 1) {
406 middle = (nabove + nbelow) / 2;
407 if (value == bData.boundaries[middle - 1])
408 return middle - 1;
409 if (value < bData.boundaries[middle - 1])
410 nabove = middle;
411 else
412 nbelow = middle;
413 }
414 return nbelow - 1;
415 }
416
418 static size_t searchInVectorWithMixedBoundary(std::pair<float, float> val, const BinningData& bData)
419 {
420 if ((bData.hbounds[0].first == 0 ? val.first : val.second) < bData.hbounds[0].second)
421 return (bData.option == closed) ? (bData.bins - 1) : 0;
422 if ((bData.hbounds.back().first == 0 ? val.first : val.second) >= bData.max)
423 return (bData.option == closed) ? 0 : (bData.bins - 1);
424
425 if (bData.hbounds.size() < 10) {
426 std::vector<std::pair<int, float>>::const_iterator vBeg = bData.hbounds.begin();
427 std::vector<std::pair<int, float>>::const_iterator vIter = vBeg + 1;
428 for (; vIter != bData.hbounds.end(); ++vIter)
429 if ((*vIter).second > ((*vIter).first == 0 ? val.first : val.second))
430 break;
431 return (vIter != bData.hbounds.end() ? vIter - vBeg - 1 : bData.bins - 1);
432 }
433
434 // Binary search in an array of n values to locate value
435 size_t nabove;
436 size_t nbelow;
437 size_t middle;
438 nabove = bData.hbounds.size();
439 // binary search
440 nbelow = 0;
441 while (nabove - nbelow > 1) {
442 middle = (nabove + nbelow) / 2;
443 float valm = bData.hbounds[middle].first == 0 ? val.first : val.second;
444 if (valm == bData.hbounds[middle].second) {
445 nbelow = middle;
446 break;
447 }
448 if (valm < bData.hbounds[middle].second)
449 nabove = middle;
450 else
451 nbelow = middle;
452 }
453
454 if (nbelow > bData.bins - 1)
455 return bData.bins - 1;
456 return nbelow;
457 }
458};
459
460}
461
462#endif
#define M_PI
std::vector< float > boundaries
Definition BinningData.h:59
static size_t binarySearchWithBoundary(float value, const BinningData &bData)
A binary search with underflow/overflow - faster than vector search for O(50) objects.
BinningOption option
Definition BinningData.h:51
size_t(* m_functionPtr)(float, const BinningData &)
the pointer to the function to be used
float binPosition(size_t bin, float pos) const
bin->BinningValue navigation : pos=+-1.
std::pair< float, float > valueH(const Amg::Vector2D &lposition) const
take float values for binH
BinningValue binvalue
Definition BinningData.h:52
BinningData(BinningOption bOption, float bRefPhi, const std::vector< std::pair< int, float > > &bBoundaries)
Constructor for binH type : non-equidistant binning assumed.
LayerOrder orderDirection(const Amg::Vector3D &position, const Amg::Vector3D &dir) const
layer order is needed for value H binning
std::vector< std::pair< int, float > > hbounds
Definition BinningData.h:60
static size_t searchInVectorWithMixedBoundary(std::pair< float, float > val, const BinningData &bData)
Search in mixed vector - linear in O-10 bins, otherwise binary.
size_t entry(const Amg::Vector3D &position) const
the entry bin
float value(const Amg::Vector2D &lposition) const
take the right float value - assumes the correct local position expression
size_t(* m_mixPtr)(std::pair< float, float >, const BinningData &)
size_t searchGlobal(const Amg::Vector3D &position) const
generic search from a 3D position
static size_t searchInVectorWithBoundary(float value, const BinningData &bData)
Linear search in vector - superior in O(10) searches: arbitraty 2.
std::pair< float, float > valueH(const Amg::Vector3D &position) const
take float values for binH
float value(const Amg::Vector3D &position) const
take the right float value
std::pair< size_t, float > distanceToNext(const Amg::Vector3D &position, const Amg::Vector3D &dir) const
distance to the next bin : gives -1 if the next one is outside
BinningData & operator=(BinningData &&)=default
bool inside(const Amg::Vector3D &position) const
Check if bin is inside from Vector3D.
BinningType type
holding all the data for binning calculatuion
Definition BinningData.h:50
static size_t searchEaquidstantWithBoundary(float value, const BinningData &bData)
Equidistant search : equidist 0.
size_t searchLocal(const Amg::Vector2D &lposition) const
generic search from a 2D position — corresponds to local coordinate schema
BinningData(BinningData &&)=default
BinningData & operator=(const BinningData &)=default
static size_t searchBiequidistantWithBoundary(float value, const BinningData &bData)
Biequidistant search : biequidist 1.
bool inside(const Amg::Vector2D &lp) const
Check if bin is inside from Vector2D.
BinningData(BinningType bType, BinningOption bOption, BinningValue bValue, size_t bBins, float bMin, float bMax, float bStep, float bSubStep=0, std::vector< float > bBoundaries=std::vector< float >())
Constructor with arguments.
Definition BinningData.h:70
size_t searchH(std::pair< double, double > value) const
generic search - forwards to correct function pointer
size_t search(float value) const
generic search - forwards to correct function pointer
~BinningData()=default
float gaugePhi(float phi) const
gauge phi
BinningData(const BinningData &)=default
size_t next(const Amg::Vector3D &position, const Amg::Vector3D &dir) const
the next bin : gives -1 if the next one is outside
STL class.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
LayerOrder
This enum is used to declare Layers as previous/next in respect of a 1-dimensional binned array.
Definition BinningData.h:31
@ next
Definition BinningData.h:33
@ previous
Definition BinningData.h:32
BinningOption
enum BinValue
Definition BinningType.h:39
@ open
Definition BinningType.h:40
@ closed
Definition BinningType.h:41
@ phi
Definition ParamDefs.h:75
BinningType
, BinningOption & BinningAccess
Definition BinningType.h:31
@ biequidistant
Definition BinningType.h:33
@ equidistant
Definition BinningType.h:32
@ arbitrary
Definition BinningType.h:34
BinningValue
how to take the global / local position
Definition BinningType.h:46
@ binEta
Definition BinningType.h:54
@ binR
Definition BinningType.h:50
@ binPhi
Definition BinningType.h:51
@ binRPhi
Definition BinningType.h:52
@ binX
Definition BinningType.h:47
@ binH
Definition BinningType.h:53
STL namespace.