Belle II Software  release-08-01-10
PXDClusterPositionEstimator.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 <pxd/reconstruction/PXDClusterPositionEstimator.h>
11 #include <vxd/dataobjects/VxdID.h>
12 #include <pxd/geometry/SensorInfo.h>
13 #include <vxd/geometry/GeoCache.h>
14 #include <TMath.h>
15 
16 #include <cmath>
17 #include <numeric>
18 
19 using namespace std;
20 
21 //namespace Belle2 {
22 // namespace PXD {
23 
25 {
26  m_shapeIndexFromDB = unique_ptr<Belle2::DBObjPtr<Belle2::PXDClusterShapeIndexPar>>(new
28  m_positionEstimatorFromDB = unique_ptr<Belle2::DBObjPtr<Belle2::PXDClusterPositionEstimatorPar>>
30 
31  if ((*m_shapeIndexFromDB).isValid() && (*m_positionEstimatorFromDB).isValid()) {
32  setShapeIndexFromDB();
33  (*m_shapeIndexFromDB).addCallback(this, &Belle2::PXD::PXDClusterPositionEstimator::setShapeIndexFromDB);
34 
35  setPositionEstimatorFromDB();
36  (*m_positionEstimatorFromDB).addCallback(this, &Belle2::PXD::PXDClusterPositionEstimator::setPositionEstimatorFromDB);
37  }
38 }
39 
41 {
42  m_shapeIndexPar = **m_shapeIndexFromDB;
43 }
44 
46 {
47  m_positionEstimatorPar = **m_positionEstimatorFromDB;
48 }
49 
51 {
52  static std::unique_ptr<Belle2::PXD::PXDClusterPositionEstimator> instance(new Belle2::PXD::PXDClusterPositionEstimator());
53  return *instance;
54 }
55 
56 
58  double tu,
59  double tv) const
60 {
61  double thetaU = TMath::ATan2(tu, 1.0) * 180.0 / M_PI;
62  double thetaV = TMath::ATan2(tv, 1.0) * 180.0 / M_PI;
63  int sector_index = getSectorIndex(thetaU, thetaV);
64 
65  int clusterkind = cluster.getKind();
66  int shape_index = cluster.getSectorShapeIndices().at(sector_index);
67  float eta = cluster.getSectorEtaValues().at(sector_index);
68  return m_positionEstimatorPar.getOffset(shape_index, eta, thetaU, thetaV, clusterkind);
69 }
70 
71 
73 {
74  double thetaU = TMath::ATan2(tu, 1.0) * 180.0 / M_PI;
75  double thetaV = TMath::ATan2(tv, 1.0) * 180.0 / M_PI;
76  int clusterkind = cluster.getKind();
77  int sector_index = getSectorIndex(thetaU, thetaV);
78  int shape_index = cluster.getSectorShapeIndices().at(sector_index);
79  return m_positionEstimatorPar.getShapeLikelyhood(shape_index, thetaU, thetaV, clusterkind);
80 }
81 
82 
83 float Belle2::PXD::PXDClusterPositionEstimator::computeEta(const std::set<Belle2::PXD::Pixel>& pixels, int vStart, int vSize,
84  double thetaU, double thetaV) const
85 {
86  const Belle2::PXD::Pixel& headPixel = getHeadPixel(pixels, vStart, vSize, thetaU, thetaV);
87  const Belle2::PXD::Pixel& tailPixel = getTailPixel(pixels, vStart, vSize, thetaU, thetaV);
88  float eta = 0;
89  if (headPixel.getIndex() != tailPixel.getIndex()) {
90  eta = tailPixel.getCharge();
91  eta /= (tailPixel.getCharge() + headPixel.getCharge());
92  } else {
93  eta = tailPixel.getCharge();
94  }
95  return eta;
96 }
97 
98 const Belle2::PXD::Pixel& Belle2::PXD::PXDClusterPositionEstimator::getHeadPixel(const std::set<Belle2::PXD::Pixel>& pixels,
99  int vStart, int vSize, double thetaU,
100  double thetaV) const
101 {
102  if (thetaV >= 0) {
103  if (thetaU >= 0) {
104  return getLastPixelWithVOffset(pixels, vStart, vSize - 1);
105  } else {
106  return getFirstPixelWithVOffset(pixels, vStart, vSize - 1);
107  }
108  } else {
109  if (thetaU >= 0) {
110  return getLastPixelWithVOffset(pixels, vStart, 0);
111  } else {
112  return getFirstPixelWithVOffset(pixels, vStart, 0);
113  }
114  }
115 }
116 
117 const Belle2::PXD::Pixel& Belle2::PXD::PXDClusterPositionEstimator::getTailPixel(const std::set<Belle2::PXD::Pixel>& pixels,
118  int vStart, int vSize, double thetaU,
119  double thetaV) const
120 {
121  if (thetaV >= 0) {
122  if (thetaU >= 0) {
123  return getFirstPixelWithVOffset(pixels, vStart, 0);
124  } else {
125  return getLastPixelWithVOffset(pixels, vStart, 0);
126  }
127  } else {
128  if (thetaU >= 0) {
129  return getFirstPixelWithVOffset(pixels, vStart, vSize - 1);
130  } else {
131  return getLastPixelWithVOffset(pixels, vStart, vSize - 1);
132  }
133  }
134 }
135 
137  pixels,
138  int vStart, int vOffset) const
139 {
140  for (auto pxit = pixels.cbegin(); pxit != pixels.cend(); ++pxit) {
141  int v = pxit->getV() - vStart;
142  if (vOffset < v) {
143  if (pxit == pixels.cbegin()) {
144  } else {
145  pxit--;
146  return *pxit;
147  }
148  }
149  }
150  if (pixels.empty())
151  B2FATAL("Found cluster with empty pixel set. ");
152 
153  auto pxit = --pixels.cend();
154  return *pxit;
155 }
156 
158  const std::set<Belle2::PXD::Pixel>& pixels,
159  int vStart, int vOffset) const
160 {
161  for (const Belle2::PXD::Pixel& px : pixels) {
162  int v = px.getV() - vStart;
163  if (vOffset == v) {
164  return px;
165  }
166  }
167  if (pixels.empty())
168  B2FATAL("Found cluster with empty pixel set. ");
169 
170  return *pixels.cbegin();
171 }
172 
173 const std::string Belle2::PXD::PXDClusterPositionEstimator::getShortName(const std::set<Belle2::PXD::Pixel>& pixels, int uStart,
174  int vStart, int vSize, double thetaU,
175  double thetaV) const
176 {
177  const Belle2::PXD::Pixel& headPixel = getHeadPixel(pixels, vStart, vSize, thetaU, thetaV);
178  const Belle2::PXD::Pixel& tailPixel = getTailPixel(pixels, vStart, vSize, thetaU, thetaV);
179  std::string name = "S";
180 
181  name += "D" + std::to_string(tailPixel.getV() - vStart) + '.' + std::to_string(tailPixel.getU() - uStart);
182 
183  if (headPixel.getIndex() != tailPixel.getIndex()) {
184  name += "D" + std::to_string(headPixel.getV() - vStart) + '.' + std::to_string(headPixel.getU() - uStart);
185  }
186  return name;
187 }
188 
189 int Belle2::PXD::PXDClusterPositionEstimator::computeShapeIndex(const std::set<Belle2::PXD::Pixel>& pixels, int uStart, int vStart,
190  int vSize, double thetaU,
191  double thetaV) const
192 {
193  // Compute shape name
194  auto shape_name = getShortName(pixels, uStart, vStart, vSize, thetaU, thetaV);
195  // Return shape index
196  return m_shapeIndexPar.getShapeIndex(shape_name);
197 }
198 
199 
200 const std::string Belle2::PXD::PXDClusterPositionEstimator::getMirroredShortName(const std::set<Belle2::PXD::Pixel>& pixels,
201  int uStart,
202  int vStart, int vSize, double thetaU,
203  double thetaV) const
204 {
205  const Belle2::PXD::Pixel& headPixel = getHeadPixel(pixels, vStart, vSize, thetaU, thetaV);
206  const Belle2::PXD::Pixel& tailPixel = getTailPixel(pixels, vStart, vSize, thetaU, thetaV);
207  int vmax = vSize - 1;
208 
209  std::string name = "S";
210  name += "D" + std::to_string(vmax - tailPixel.getV() + vStart) + '.' + std::to_string(tailPixel.getU() - uStart);
211 
212  if (headPixel.getIndex() != tailPixel.getIndex()) {
213  name += "D" + std::to_string(vmax - headPixel.getV() + vStart) + '.' + std::to_string(headPixel.getU() - uStart);
214  }
215  return name;
216 }
217 
218 const std::string Belle2::PXD::PXDClusterPositionEstimator::getFullName(const std::set<Belle2::PXD::Pixel>& pixels, int uStart,
219  int vStart) const
220 {
221  return std::accumulate(pixels.begin(), pixels.end(), std::string("F"),
222  [uStart, vStart](auto name, auto px) {
223  return name + "D" + std::to_string(px.getV() - vStart) + "." + std::to_string(px.getU() - uStart);
224  });
225 }
226 
228 {
229  std::set<int> pixelkinds;
230  bool uEdge = false;
231  bool vEdge = false;
232 
233  Belle2::VxdID sensorID = cluster.getSensorID();
234  const Belle2::PXD::SensorInfo& Info = dynamic_cast<const Belle2::PXD::SensorInfo&>(Belle2::VXD::GeoCache::get(sensorID));
235 
236  for (const Belle2::PXDDigit& digit : cluster.getRelationsTo<Belle2::PXDDigit>("PXDDigits")) {
237  int pixelkind = Info.getPixelKindNew(sensorID, digit.getVCellID());
238  pixelkinds.insert(pixelkind);
239 
240  // Cluster at v sensor edge
241  if (digit.getVCellID() == 0 or digit.getVCellID() >= 767)
242  vEdge = true;
243  // Cluster at u sensor edge
244  if (digit.getUCellID() == 0 or digit.getUCellID() >= 249)
245  uEdge = true;
246  }
247 
248  // In most cases, clusterkind is just pixelkind of first digit
249  int clusterkind = *pixelkinds.begin();
250 
251  // Clusters with different pixelkinds or edge digits are special
252  // TODO: At the moment, clusterkind >3 will not be corrected
253  if (pixelkinds.size() > 1 || uEdge || vEdge)
254  clusterkind = 4;
255 
256  return clusterkind;
257 }
258 
259 int Belle2::PXD::PXDClusterPositionEstimator::getClusterkind(const std::vector<Belle2::PXD::Pixel>& pixels,
260  const Belle2::VxdID& sensorID) const
261 {
262  std::set<int> pixelkinds;
263  bool uEdge = false;
264  bool vEdge = false;
265 
266  const Belle2::PXD::SensorInfo& Info = dynamic_cast<const Belle2::PXD::SensorInfo&>(Belle2::VXD::GeoCache::get(sensorID));
267 
268  for (const Belle2::PXD::Pixel& pix : pixels) {
269  int pixelkind = Info.getPixelKindNew(sensorID, pix.getV());
270  pixelkinds.insert(pixelkind);
271 
272  // Cluster at v sensor edge
273  if (pix.getV() == 0 or pix.getV() >= 767)
274  vEdge = true;
275  // Cluster at u sensor edge
276  if (pix.getU() == 0 or pix.getU() >= 249)
277  uEdge = true;
278  }
279 
280  // In most cases, clusterkind is just pixelkind of first digit
281  int clusterkind = *pixelkinds.begin();
282 
283  // Clusters with different pixelkinds or edge digits are special
284  // TODO: At the moment, clusterkind >3 will not be corrected
285  if (pixelkinds.size() > 1 || uEdge || vEdge)
286  clusterkind = 4;
287 
288  return clusterkind;
289 }
290 
291 int Belle2::PXD::PXDClusterPositionEstimator::getSectorIndex(double thetaU, double thetaV) const
292 {
293  int sectorIndex = 0;
294  if (thetaU >= 0) {
295  if (thetaV >= 0) {
296  sectorIndex = 0;
297  } else {
298  sectorIndex = 3;
299  }
300  } else {
301  if (thetaV >= 0) {
302  sectorIndex = 1;
303  } else {
304  sectorIndex = 2;
305  }
306  }
307  return sectorIndex;
308 }
309 
310 
311 
312 // }
313 //}
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
The class for PXD cluster position offset payload.
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
Definition: PXDCluster.h:30
The PXD digit class.
Definition: PXDDigit.h:27
Singleton class that estimates cluster positions taking into account the estimated track incidence an...
void initialize()
Initialize PXDClusterPositionEstimator from DB.
const std::string getFullName(const std::set< Pixel > &pixels, int uStart, int vStart) const
Return a name for the pixel set.
static PXDClusterPositionEstimator & getInstance()
Main (and only) way to access the PXDClusterPositionEstimator.
int getSectorIndex(double thetaU, double thetaV) const
Get sector index from angles.
const Pixel & getTailPixel(const std::set< Pixel > &pixels, int vStart, int vSize, double thetaU, double thetaV) const
Return reference to the tail pixel in pixel set.
const std::string getMirroredShortName(const std::set< Pixel > &pixels, int uStart, int vStart, int vSize, double thetaU, double thetaV) const
Return the mirrored name for the pixel set.
const Pixel & getLastPixelWithVOffset(const std::set< Pixel > &pixels, int vStart, int vOffset) const
Return reference to the last pixel in pixel set with given vOffset from vStart.
const PXDClusterOffsetPar * getClusterOffset(const PXDCluster &cluster, double tu, double tv) const
Return pointer to cluster offsets, can be nullptr.
float computeEta(const std::set< Pixel > &pixels, int vStart, int vSize, double thetaU, double thetaV) const
Return the normed charge ratio between head and tail pixels (size>=2) or the charge of the seed (size...
float getShapeLikelyhood(const PXDCluster &cluster, double tu, double tv) const
Return cluster shape likelyhood.
int computeShapeIndex(const std::set< Pixel > &pixels, int uStart, int vStart, int vSize, double thetaU, double thetaV) const
Return the shape index of the pixels.
void setPositionEstimatorFromDB()
Set PositionEstimator from DB.
const std::string getShortName(const std::set< Pixel > &pixels, int uStart, int vStart, int vSize, double thetaU, double thetaV) const
Return the name for the pixel set.
int getClusterkind(const PXDCluster &cluster) const
Return kind of cluster needed to find cluster position correction.
const Pixel & getFirstPixelWithVOffset(const std::set< Pixel > &pixels, int vStart, int vOffset) const
Return reference to the first pixel in pixel set with given vOffset from vStart.
const Pixel & getHeadPixel(const std::set< Pixel > &pixels, int vStart, int vSize, double thetaU, double thetaV) const
Return reference to the head pixel in pixel set.
Class to represent one pixel, used in clustering for fast access.
Definition: Pixel.h:36
unsigned short getU() const
Return the CellID in u.
Definition: Pixel.h:66
unsigned int getIndex() const
Return the Index of the digit.
Definition: Pixel.h:72
float getCharge() const
Return the Charge of the Pixel.
Definition: Pixel.h:70
unsigned short getV() const
Return the CellID in v.
Definition: Pixel.h:68
Specific implementation of SensorInfo for PXD Sensors which provides additional pixel specific inform...
Definition: SensorInfo.h:23
int getPixelKindNew(const VxdID &sensorID, int vID) const
Return pixel kind ID.
Definition: SensorInfo.cc:78
static const SensorInfoBase & get(Belle2::VxdID id)
Return a reference to the SensorInfo of a given SensorID.
Definition: GeoCache.h:139
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33