Belle II Software  release-08-01-10
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 
21 namespace 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 cant 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.