Belle II Software development
Position.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// THIS
10#include "ecl/utility/Position.h"
11
12// GEOMETRY
13#include <ecl/geometry/ECLGeometryPar.h>
14
15// FRAMEWORK
16#include <framework/logging/Logger.h>
17
18// OTHER
19#include "TMath.h"
20
21namespace Belle2 {
26 namespace ECL {
27 // computePositionLiLo
28 B2Vector3D computePositionLiLo(const std::vector<ECLCalDigit>& digits, std::vector<double>& weights,
29 const std::vector<double>& parameters)
30 {
31
32 // Total weighted sum.
33 const double energySum = computeEnergySum(digits, weights);
34 if (energySum <= 0.0) {
35 B2WARNING("ECL computePositionLiLo() energy sum zero or negative: " << energySum << ", return (0, 0, 0)");
36 B2Vector3D liloPointError(0, 0, 0);
37 return liloPointError;
38 }
39
40 // Offset from user input constants: offset = A-B * exp(-C * energysum).
41 const double offset = parameters[0] - parameters[1] * TMath::Exp(-parameters[2] * energySum);
42
43 // Geometry information for crystal positions.
44 ECLGeometryPar* geom = ECLGeometryPar::Instance();
45
46 // Log-weighted position calculation
47 B2Vector3D liloPoint(1, 1, 1); // anything is fine as long its not zero length
48 B2Vector3D linearPositionVector(0, 0, 0);
49 B2Vector3D logPositionVector(0, 0, 0);
50 double logWeightSum = 0.0;
51 int nTotal = 0;
52 int nInLogWeightSum = 0;
53 double firstPhi = -999.;
54 double firstTheta = -999.;
55 bool foundSecondPhi = false;
56 bool foundSecondTheta = false;
57
58 // Loop over all digits in the vector.
59 for (const auto& digit : digits) {
60 const double energy = digit.getEnergy();
61 const int cellid = digit.getCellId();
62 const double weight = weights.at(nTotal);
63 const B2Vector3D position = geom->GetCrystalPos(cellid - 1); // v = crystal center - (0, 0, 0)
64 const double theta = position.Theta();
65 const double phi = position.Phi();
66 ++nTotal;
67
68 // Weights.
69 const double linearWeight = energy * weight / energySum; // fraction of this digit energy to the total shower energy
70 const double logWeight = offset + TMath::Log(linearWeight);
71
72 // Update the linear position vector.
73 linearPositionVector += linearWeight * position;
74
75 // Only digits with a positive weight are included.
76 if (logWeight > 0.0) {
77
78 // Update the log position vector.
79 logPositionVector += logWeight * position;
80 logWeightSum += logWeight;
81 ++nInLogWeightSum;
82
83 // We have to avoid that only crystals with the same theta or phi values are used (this will bias the position towards the crystal center
84 if (nInLogWeightSum == 1) {
85 firstTheta = theta;
86 firstPhi = phi;
87 } else {
88 if (!foundSecondPhi and fabs(phi - firstPhi) > 1e-4) { // we can't use phi id in the endcaps
89 foundSecondPhi = true;
90 }
91 if (!foundSecondTheta
92 and fabs(theta - firstTheta) > 1e-4) { // we could probably use thetaid since this works in the endcaps as well
93 foundSecondTheta = true;
94 }
95 }
96 } // end if logWeight
97 } // end digit
98
99 // Check if at least one digit has a positive weight in the logweightsum.
100 if (nInLogWeightSum > 0) logPositionVector *= 1. / logWeightSum;
101
102 // The direction is filled, now get the distance to the center. It can happen, that it is outside of the crystals
103 // if the shower is in the barrel/endcap overlap regions?!
104 liloPoint.SetTheta(foundSecondTheta ? logPositionVector.Theta() : linearPositionVector.Theta());
105 liloPoint.SetPhi(foundSecondPhi ? logPositionVector.Phi() : linearPositionVector.Phi());
106 liloPoint.SetMag(nInLogWeightSum > 0 ? logPositionVector.Mag() : linearPositionVector.Mag());
107
108 return liloPoint;
109 }
110
111 // helper: computeEnergySum
112 double computeEnergySum(const std::vector<ECLCalDigit>& digits, std::vector<double>& weights)
113 {
114 int n = 0;
115 double sum = 0.0;
116
117 for (const auto& digit : digits) {
118 sum += digit.getEnergy() * weights.at(n);
119 ++n;
120 }
121
122 return sum;
123 }
124
125// // helper: findClosestCrystal
126// int findClosestCrystal(std::vector<ECLCalDigit>& digits, TVector3& direction)
127// {
128// ECLGeometryPar* geom = ECLGeometryPar::Instance();
129//
130// int best = -1;
131// double min = 999.;
132// for (const auto& digit : digits) {
133// const int crystalid = digit.getCellId() - 1;
134// const double alpha = direction.Angle(geom->GetCrystalVec(crystalid));
135// const double R = (geom->GetCrystalPos(crystalid)).Mag();
136// const double distance = 2.0 * R * TMath::Sin(alpha / 2.0); // chord distance
137//
138// if (distance < min) {
139// min = distance;
140// best = crystalid;
141// }
142// }
143// return best;
144// }
145
146 // ...
147
148 }
150}
static ECLGeometryPar * Instance()
Static method to get a reference to the ECLGeometryPar instance.
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
Abstract base class for different kinds of events.