Belle II Software  release-08-01-10
SVDClusterPosition.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 <framework/logging/Logger.h>
10 #include <svd/reconstruction/SVDClusterPosition.h>
11 #include <svd/reconstruction/SVDCoG3Time.h>
12 #include <svd/reconstruction/SVDELS3Time.h>
13 #include <svd/reconstruction/SVDELS3Charge.h>
14 #include <svd/reconstruction/SVDMaxSampleCharge.h>
15 #include <svd/reconstruction/SVDSumSamplesCharge.h>
16 #include <svd/reconstruction/SVDMaxSumAlgorithm.h>
17 #include <vxd/geometry/GeoCache.h>
18 #include <svd/geometry/SensorInfo.h>
19 
20 #include <TMath.h>
21 #include <Eigen/Dense>
22 
23 using namespace std;
24 
25 namespace Belle2 {
31  namespace SVD {
32 
33 
34  void SVDClusterPosition::applyCoGPosition(const Belle2::SVD::RawCluster& rawCluster, double& position, double& positionError)
35  {
36 
37  const VXD::GeoCache& geo = VXD::GeoCache::getInstance();
38  const VXD::SensorInfoBase& info = geo.getSensorInfo(rawCluster.getSensorID());
39 
40  position = 0;
41  double charge = 0;
42 
43  //take the strips in the rawCluster
44  std::vector<Belle2::SVD::StripInRawCluster> strips = rawCluster.getStripsInRawCluster();
45 
46  for (auto aStrip : strips) {
47 
48  double stripPos = rawCluster.isUSide() ? info.getUCellPosition(aStrip.cellID) : info.getVCellPosition(aStrip.cellID);
49 
50  //getting the charge of the strip
51  double stripCharge = aStrip.charge;
52 
53  position += stripPos * stripCharge;
54  charge += stripCharge;
55  }
56 
57  position /= charge;
58 
59  //now compute position error
60  positionError = 0;
61  double pitch = rawCluster.isUSide() ? info.getUPitch() : info.getVPitch();
62  double sumStripCharge = getSumOfStripCharges(rawCluster);
63 
64  positionError = m_CoGOnlyErr.getPositionError(rawCluster.getSensorID(), rawCluster.isUSide(), 0,
65  sumStripCharge / getClusterNoise(rawCluster), rawCluster.getSize(), pitch);
66 
67  }
68 
69 
70 
71  void SVDClusterPosition::applyAHTPosition(const Belle2::SVD::RawCluster& rawCluster, double& position, double& positionError)
72  {
73 
74  // NOTE:
75  // tail and head are the two strips at the edge of the cluster
76 
77  const VXD::GeoCache& geo = VXD::GeoCache::getInstance();
78  const VXD::SensorInfoBase& info = geo.getSensorInfo(rawCluster.getSensorID());
79  double pitch = rawCluster.isUSide() ? info.getUPitch() : info.getVPitch();
80 
81  //take the strips in the rawCluster
82  std::vector<Belle2::SVD::StripInRawCluster> strips = rawCluster.getStripsInRawCluster();
83 
84  //informations about the head strip
85  int headStripCellID = strips.at(strips.size() - 1).cellID;
86  double headStripCharge = strips.at(strips.size() - 1).charge;
87  //informations about the tail strip
88  int tailStripCellID = strips.at(0).cellID;
89  double tailStripCharge = strips.at(0).charge;
90 
91  // average strip charge of the center of the cluster
92 
93  double centreCharge = (getSumOfStripCharges(rawCluster) - tailStripCharge - headStripCharge) / (strips.size() - 2);
94 
95  tailStripCharge = (tailStripCharge < centreCharge) ? tailStripCharge : centreCharge;
96  headStripCharge = (headStripCharge < centreCharge) ? headStripCharge : centreCharge;
97  double tailPos = rawCluster.isUSide() ? info.getUCellPosition(tailStripCellID) : info.getVCellPosition(tailStripCellID);
98  double headPos = rawCluster.isUSide() ? info.getUCellPosition(headStripCellID) : info.getVCellPosition(headStripCellID);
99  position = 0.5 * (tailPos + headPos + (headStripCharge - tailStripCharge) / centreCharge * pitch);
100 
101  //now compute position error
102  double cutAdjacent = m_ClusterCal.getMinAdjSNR(rawCluster.getSensorID(), rawCluster.isUSide());
103  double sn = centreCharge / cutAdjacent / getClusterNoise(rawCluster);
104 
105  // Rough estimates of Landau noise
106  double landauHead = tailStripCharge / centreCharge;
107  double landauTail = headStripCharge / centreCharge;
108  positionError = 0.5 * pitch * sqrt(1.0 / sn / sn +
109  0.5 * landauHead * landauHead +
110  0.5 * landauTail * landauTail);
111 
112  }
113 
114  double SVDClusterPosition::getSumOfStripCharges(const Belle2::SVD::RawCluster& rawCluster)
115  {
116 
117  double sumStripCharge = 0;
118 
119  //take the strips in the rawCluster
120  std::vector<Belle2::SVD::StripInRawCluster> strips = rawCluster.getStripsInRawCluster();
121 
122  // compute the sum of strip charges
123  for (auto aStrip : strips) {
124 
125  double stripCharge = aStrip.charge;
126  sumStripCharge += stripCharge;
127  }
128  return sumStripCharge;
129  }
130 
131  double SVDClusterPosition::getClusterNoise(const Belle2::SVD::RawCluster& rawCluster)
132  {
133 
134  double clusterNoise = 0;
135 
136  //take the strips in the rawCluster
137  std::vector<Belle2::SVD::StripInRawCluster> strips = rawCluster.getStripsInRawCluster();
138 
139  // compute the cluster noise as sum in quadrature of strip noise
140  for (auto aStrip : strips) {
141 
142  float averageNoiseInElectrons = m_NoiseCal.getNoiseInElectrons(rawCluster.getSensorID(), rawCluster.isUSide(), aStrip.cellID);
143  clusterNoise += averageNoiseInElectrons * averageNoiseInElectrons;
144  }
145  return sqrt(clusterNoise);
146  }
147 
148  double SVDClusterPosition::getAverageStripNoise(const Belle2::SVD::RawCluster& rawCluster)
149  {
150 
151  double averageNoise = 0;
152 
153  //take the strips in the rawCluster
154  std::vector<Belle2::SVD::StripInRawCluster> strips = rawCluster.getStripsInRawCluster();
155 
156  // compute the average strip noise
157  for (auto aStrip : strips) {
158 
159  float averageNoiseInElectrons = m_NoiseCal.getNoiseInElectrons(rawCluster.getSensorID(), rawCluster.isUSide(), aStrip.cellID);
160  averageNoise += averageNoiseInElectrons;
161  }
162  return averageNoise / strips.size();
163  }
164 
165  void SVDClusterPosition::reconstructStrips(Belle2::SVD::RawCluster& rawCluster)
166  {
167 
168 
169  std::vector<Belle2::SVD::StripInRawCluster> strips = rawCluster.getStripsInRawCluster();
170 
171  //loop on strips
172  for (int i = 0; i < (int)strips.size(); i++) {
173 
174  Belle2::SVD::StripInRawCluster strip = strips.at(i);
175 
176  RawCluster tmp(rawCluster.getSensorID(), rawCluster.isUSide(), 0, 0);
177  if (tmp.add(rawCluster.getSensorID(), rawCluster.isUSide(), strip)) {
178 
179  // time computation
180  if (m_stripTimeAlgo.compare("dontdo") != 0) {
181 
182  double time = 0;
183  double timeError = 0;
184  int firstFrame = 0;
185 
186  if (m_stripTimeAlgo == "ELS3") {
187  SVDELS3Time ct;
188  ct.computeClusterTime(tmp, time, timeError, firstFrame);
189 
190  } else if (m_stripTimeAlgo == "CoG3") {
191  SVDCoG3Time ct;
192  ct.computeClusterTime(tmp, time, timeError, firstFrame);
193  }
194  rawCluster.setStripTime(i, time);
195  }
196 
197  // charge computation
198  // may be not needed in case the cluster position is computed using APV samples
199  // and not using reconstructed strips
200  if (m_stripChargeAlgo.compare("dontdo") != 0) {
201  double charge = 0;
202  double SNR;
203  double seedCharge;
204 
205  if (m_stripChargeAlgo == "ELS3") {
206  // ELS3 can return non-sense values for off-time or low-charge strips)
207  // if returned charge is negative or more than 30% different than MaxSample, we use MaxSample
208  // without notice to the user!
209 
210  SVDELS3Charge cc;
211  cc.computeClusterCharge(tmp, charge, SNR, seedCharge);
212 
213  double maxSample_charge = 0;
214  SVDMaxSampleCharge maxSample_cc;
215  maxSample_cc.computeClusterCharge(tmp, maxSample_charge, SNR, seedCharge);
216 
217  if ((abs(charge - maxSample_charge) / maxSample_charge > 0.3) || charge < 0)
218  rawCluster.setStripCharge(i, maxSample_charge);
219  else
220  rawCluster.setStripCharge(i, charge);
221 
222  } else if (m_stripChargeAlgo == "SumSamples") {
224  cc.computeClusterCharge(tmp, charge, SNR, seedCharge);
225  rawCluster.setStripCharge(i, charge);
226  } else {
227  // MaxSample is used when the algorithm is not recognized
229  cc.computeClusterCharge(tmp, charge, SNR, seedCharge);
230  rawCluster.setStripCharge(i, charge);
231  }
232  }
233  } else
234  B2ERROR("this should not happen...");
235 
236  }
237 
238  }
239 
240  void SVDClusterPosition::applyUnfolding(Belle2::SVD::RawCluster& rawCluster)
241  {
242 
243 
244  std::vector<Belle2::SVD::StripInRawCluster> strips = rawCluster.getStripsInRawCluster();
245  double unfoldingCoefficient = m_ClusterCal.getUnfoldingCoeff(rawCluster.getSensorID(), rawCluster.isUSide());
246  unsigned int Size = strips.size();
247  double threshold = 0;
248  Eigen::VectorXd Charges(Size);
249  Eigen::MatrixXd Couplings(Size, Size);
250  // Unfolding Matrix
251  for (unsigned int i = 0; i < Size; ++i) {
252  for (unsigned int j = 0; j < Size; ++j) {
253  if (i == j) {Couplings(i, j) = 1 - 2 * unfoldingCoefficient;}
254  else if (j == i + 1) {Couplings(i, j) = unfoldingCoefficient;}
255  else if (j == i - 1) {Couplings(i, j) = unfoldingCoefficient;}
256  else {Couplings(i, j) = 0;}
257  }
258 
259  Belle2::SVD::StripInRawCluster strip = strips.at(i);
260 
261  RawCluster tmp(rawCluster.getSensorID(), rawCluster.isUSide(), 0, 0);
262  if (tmp.add(rawCluster.getSensorID(), rawCluster.isUSide(), strip)) {
263  //Fill a vector with strip charges
264  Charges(i) = strip.charge;
265  }
266 
267  }
268  //Apply the unfolding
269  Charges = Couplings.inverse() * Charges;
270  for (unsigned i = 0; i < Size; i++) {
271  if (Charges(i) < threshold) {Charges(i) = 0;}
272  rawCluster.setStripCharge(i, Charges(i));
273  }
274 
275  }
276 
277  } //SVD namespace
279 } //Belle2 namespace
Class representing a raw cluster candidate during clustering of the SVD.
Definition: RawCluster.h:33
void setStripCharge(int index, double charge)
set the strip charge
Definition: RawCluster.h:127
bool isUSide() const
Definition: RawCluster.h:85
VxdID getSensorID() const
Definition: RawCluster.h:80
const std::vector< StripInRawCluster > getStripsInRawCluster() const
Definition: RawCluster.h:110
void setStripTime(int index, double time)
set the strip time
Definition: RawCluster.h:133
Derived Class representing the SVD cluster time computed with the CoG3 algorithm.
Definition: SVDCoG3Time.h:22
void computeClusterTime(Belle2::SVD::RawCluster &rawCluster, double &time, double &timeError, int &firstFrame) override
computes the cluster time, timeError and FirstFrame with the CoG3 algorithm
Definition: SVDCoG3Time.cc:21
Derived Class representing the SVD cluster charge computed with the ELS3 algorithm.
Definition: SVDELS3Charge.h:26
Derived Class representing the SVD cluster time computed with the ELS3 algorithm.
Definition: SVDELS3Time.h:24
void computeClusterTime(Belle2::SVD::RawCluster &rawCluster, double &time, double &timeError, int &firstFrame) override
computes the cluster time, timeError and FirstFrame with the ELS3 algorithm
Definition: SVDELS3Time.cc:22
Derived Class representing the SVD cluster charge computed summing the max sample of each strip.
void computeClusterCharge(Belle2::SVD::RawCluster &rawCluster, double &charge, double &SNR, double &seedCharge) override
compute the cluster charge, charge error and SNR with MaxSample
Derived Class representing the SVD cluster charge computed summing the samples of each strip.
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:39
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a referecne to the SensorInfo of a given SensorID.
Definition: GeoCache.cc:67
Base class to provide Sensor Information for PXD and SVD.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.
structure containing the relevant informations of each strip of the raw cluster
Definition: RawCluster.h:20
double charge
strip charge
Definition: RawCluster.h:26