Belle II Software  release-08-01-10
PXDClusterizerModule.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 <pxd/modules/pxdReconstruction/PXDClusterizerModule.h>
10 
11 #include <framework/datastore/DataStore.h>
12 #include <framework/datastore/StoreArray.h>
13 #include <framework/datastore/RelationArray.h>
14 #include <framework/logging/Logger.h>
15 
16 #include <vxd/geometry/GeoCache.h>
17 
18 #include <mdst/dataobjects/MCParticle.h>
19 #include <pxd/dataobjects/PXDDigit.h>
20 #include <pxd/dataobjects/PXDCluster.h>
21 #include <pxd/dataobjects/PXDTrueHit.h>
22 #include <pxd/geometry/SensorInfo.h>
23 
24 #include <pxd/reconstruction/PXDClusterPositionEstimator.h>
25 
26 #include <pxd/utilities/PXDUtilities.h>
27 
28 using namespace std;
29 using namespace Belle2;
30 using namespace Belle2::PXD;
31 
32 //-----------------------------------------------------------------
33 // Register the Module
34 //-----------------------------------------------------------------
35 REG_MODULE(PXDClusterizer);
36 
37 //-----------------------------------------------------------------
38 // Implementation
39 //-----------------------------------------------------------------
40 
41 PXDClusterizerModule::PXDClusterizerModule() : Module()
42  , m_elNoise(0.7), m_cutSeed(5.0), m_cutAdjacent(3.0), m_cutCluster(8.0)
43  , m_cutAdjacentSignal(0), m_sizeHeadTail(3), m_clusterCacheSize(0)
44 {
45  //Set module properties
46  setDescription("Cluster PXDHits");
48 
49  addParam("ElectronicNoise", m_elNoise,
50  "Noise added by the electronics, set in ADU", m_elNoise);
51  addParam("NoiseSN", m_cutAdjacent,
52  "SN for digits to be considered for clustering", m_cutAdjacent);
53  addParam("SeedSN", m_cutSeed, "SN for digits to be considered as seed",
54  m_cutSeed);
55  addParam("ClusterSN", m_cutCluster, "Minimum SN for clusters", m_cutCluster);
56  addParam("ClusterCacheSize", m_clusterCacheSize,
57  "Maximum desired number of sensor rows", 0);
58  addParam("HeadTailSize", m_sizeHeadTail,
59  "Minimum cluster size to switch to Analog head tail algorithm for cluster center",
61  addParam("Digits", m_storeDigitsName, "Digits collection name", string(""));
62  addParam("Clusters", m_storeClustersName, "Cluster collection name",
63  string(""));
64  addParam("TrueHits", m_storeTrueHitsName, "TrueHit collection name",
65  string(""));
66  addParam("MCParticles", m_storeMCParticlesName, "MCParticles collection name",
67  string(""));
68  addParam("ErrorFromDB", m_errorFromDB, "Assign cluster position error from DB", true);
69  addParam("PositionErrorUPayloadName", m_positionErrorUName, "Payload name for cluster position error in U",
70  string("PXDClusterPositionErrorUPar"));
71  addParam("PositionErrorVPayloadName", m_positionErrorVName, "Payload name for cluster position error in V",
72  string("PXDClusterPositionErrorVPar"));
73 
74 }
75 
77 {
78  //Register collections
83 
85  storeDigits.isRequired();
86  storeTrueHits.isOptional();
87  storeMCParticles.isOptional();
88 
89  RelationArray relClusterDigits(storeClusters, storeDigits);
90  RelationArray relClusterTrueHits(storeClusters, storeTrueHits);
91  RelationArray relClusterMCParticles(storeClusters, storeMCParticles);
92  RelationArray relDigitMCParticles(storeDigits, storeMCParticles);
93  RelationArray relDigitTrueHits(storeDigits, storeTrueHits);
94 
95  relClusterDigits.registerInDataStore();
96  //Relations to Simulation objects are only needed if the parent one already
97  //exists
98  if (relDigitTrueHits.isOptional()) {
99  relClusterTrueHits.registerInDataStore();
100  }
101  if (relDigitMCParticles.isOptional()) {
102  relClusterMCParticles.registerInDataStore();
103  }
104 
105  //Now save all names to speed creation later, mainly if they had default names
106  m_storeClustersName = storeClusters.getName();
107  m_storeDigitsName = storeDigits.getName();
108  m_storeTrueHitsName = storeTrueHits.getName();
109  m_storeMCParticlesName = storeMCParticles.getName();
110 
111  m_relClusterDigitName = relClusterDigits.getName();
112  m_relClusterTrueHitName = relClusterTrueHits.getName();
113  m_relClusterMCParticleName = relClusterMCParticles.getName();
114  m_relDigitTrueHitName = relDigitTrueHits.getName();
115  m_relDigitMCParticleName = relDigitMCParticles.getName();
116 
117  B2DEBUG(20,
118  "PXDClusterizer Parameters (in default system units, *=cannot be set directly):");
119  B2DEBUG(20, " --> ElectronicNoise: " << m_elNoise);
120  B2DEBUG(20, " --> NoiseSN: " << m_cutAdjacent);
121  B2DEBUG(20, " --> SeedSN: " << m_cutSeed);
122  B2DEBUG(20, " --> ClusterSN: " << m_cutCluster);
123  B2DEBUG(20,
124  " --> MCParticles: " << DataStore::arrayName<MCParticle>(m_storeMCParticlesName));
125  B2DEBUG(20,
126  " --> Digits: " << DataStore::arrayName<PXDDigit>(m_storeDigitsName));
127  B2DEBUG(20,
128  " --> Clusters: " << DataStore::arrayName<PXDCluster>(m_storeClustersName));
129  B2DEBUG(20,
130  " --> TrueHits: " << DataStore::arrayName<PXDTrueHit>(m_storeTrueHitsName));
131  B2DEBUG(20, " --> DigitMCRel: " << m_relDigitMCParticleName);
132  B2DEBUG(20, " --> ClusterMCRel: " << m_relClusterMCParticleName);
133  B2DEBUG(20, " --> ClusterDigitRel: " << m_relClusterDigitName);
134  B2DEBUG(20, " --> DigitTrueRel: " << m_relDigitTrueHitName);
135  B2DEBUG(20, " --> ClusterTrueRel: " << m_relClusterTrueHitName);
136 
137 
140  if (m_clusterCacheSize > 0)
141  m_cache = std::unique_ptr<ClusterCache>(new ClusterCache(m_clusterCacheSize));
142  else
143  m_cache = std::unique_ptr<ClusterCache>(new ClusterCache());
144 
145  // Cluster position error from DB
146  if (m_errorFromDB) {
147  if (!m_positionErrorUName.size() || !m_positionErrorVName.size()) {
148  B2WARNING("You chose to use cluster position erros from DB but did not provide PositionErrorUPayloadName ("
149  << m_positionErrorUName << ") and/or PositionErrorVPayloadName (" << m_positionErrorVName
150  << "). Disabling DB option.");
151  m_errorFromDB = false;
152  }
153  m_clusterPositionErrorUPar = std::make_unique<DBObjPtr<PXDClusterPositionErrorPar>>(m_positionErrorUName);
154  m_clusterPositionErrorVPar = std::make_unique<DBObjPtr<PXDClusterPositionErrorPar>>(m_positionErrorVName);
155  if (m_clusterPositionErrorUPar == nullptr || m_clusterPositionErrorVPar == nullptr) {
156  B2FATAL("DB objects for ClusterPositionError not valid");
157  }
158  }
159 
160 }
161 
163 {
164  // Need to check if payload should be re-loaded at run change (currently just one revision for the entire period)
165  if (m_errorFromDB && (!m_clusterPositionErrorUPar->isValid() || !m_clusterPositionErrorVPar.get()->isValid())) {
166  B2FATAL("DB objects for ClusterPositionError not valid for this run");
167  }
168 }
169 
171 {
172  const StoreArray<MCParticle> storeMCParticles(m_storeMCParticlesName);
173  const StoreArray<PXDTrueHit> storeTrueHits(m_storeTrueHitsName);
174  const StoreArray<PXDDigit> storeDigits(m_storeDigitsName);
176 
177  storeClusters.clear();
178 
179  RelationArray relClusterMCParticle(storeClusters, storeMCParticles,
181  if (relClusterMCParticle) relClusterMCParticle.clear();
182 
183  RelationArray relClusterDigit(storeClusters, storeDigits,
185  if (relClusterDigit) relClusterDigit.clear();
186 
187  RelationArray relClusterTrueHit(storeClusters, storeTrueHits,
189  if (relClusterTrueHit) relClusterTrueHit.clear();
190 
191  int nPixels = storeDigits.getEntries();
192  if (nPixels == 0)
193  return;
194 
195  //Build lookup tables for relations
196  RelationArray relDigitMCParticle(storeDigits, storeMCParticles, m_relDigitMCParticleName);
197  RelationArray relDigitTrueHit(storeDigits, storeTrueHits, m_relDigitTrueHitName);
198  createRelationLookup(relDigitMCParticle, m_mcRelation, storeDigits.getEntries());
199  createRelationLookup(relDigitTrueHit, m_trueRelation, storeDigits.getEntries());
200 
201  m_cache->clear();
202 
203  //We require all pixels are already sorted and directly cluster them. Once
204  //the sensorID changes, we write out all existing clusters and continue.
205  VxdID sensorID(0);
206  //To check sorting
207  Pixel lastPixel;
208  for (int i = 0; i < nPixels; i++) {
209  const PXDDigit* const storeDigit = storeDigits[i];
210  Pixel px(storeDigit, i);
211  //New sensor, write clusters
212  if (sensorID != storeDigit->getSensorID()) {
213  writeClusters(sensorID);
214  sensorID = storeDigit->getSensorID();
215  //Load the correct noise map for the new sensor
216  m_noiseMap.setSensorID(sensorID);
217  } else if (px <= lastPixel) {
218  //Check for sorting as precaution
219  B2FATAL("Pixels are not sorted correctly, please include the "
220  "PXDDigitSorter module before running the Clusterizer or fix "
221  "the input to be ordered by v,u in ascending order");
222  }
223  //Remember last pixel to check sorting
224  lastPixel = px;
225 
226  //Ignore digits with not enough signal. Has to be done after the check of
227  //the SensorID to make sure we compare to the correct noise level
228  if (!m_noiseMap(px, m_cutAdjacent)) continue;
229 
230  // TODO: If we would like to cluster across dead channels we would need a
231  // sorted list of dead pixels. Assuming we have such a list m_deadChannels
232  // containing Pixel instances with all dead channels of this sensor and
233  // m_currentDeadChannel is an iterator to that list (initialized to
234  // begin(m_deadChannels) when the sensorID changes), we would do
235  //
236  // while(m_currentDeadChannel != end(m_deadChannels) && *m_currentDeadChannel < px){
237  // m_cache->findCluster(m_currentDeadChannel->getU(), m_currentDeadChannel->getV());
238  // m_currentDeadChannel++;
239  // }
240  //
241  // This would have the effect of marking the pixel address as belonging
242  // to a cluster but would not modify the clusters itself (except for
243  // possible merging of clusters) so we would end up with clusters that
244  // contain holes or are disconnected.
245 
246  // Find correct cluster and add pixel to cluster
247  try {
248  m_cache->findCluster(px.getU(), px.getV()).add(px);
249  } catch (std::out_of_range& e) {
250  B2WARNING("PXD clustering: Ignoring pixel " << px.getU() << "," << px.getV() << ": " << e.what());
251  }
252  }
253  writeClusters(sensorID);
254 }
255 
256 void PXDClusterizerModule::createRelationLookup(const RelationArray& relation, RelationLookup& lookup, size_t digits)
257 {
258  lookup.clear();
259  //If we don't have a relation we don't build a lookuptable
260  if (!relation) return;
261  //Resize to number of digits and set all values
262  lookup.resize(digits);
263  for (const RelationElement& element : relation) {
264  lookup[element.getFromIndex()] = &element;
265  }
266 }
267 
268 void PXDClusterizerModule::fillRelationMap(const RelationLookup& lookup, std::map<unsigned int, float>& relation,
269  unsigned int index)
270 {
271  //If the lookup table is not empty and the element is set
272  if (!lookup.empty() && lookup[index]) {
273  const RelationElement& element = *lookup[index];
274  const unsigned int size = element.getSize();
275  //Add all Relations to the map
276  for (unsigned int i = 0; i < size; ++i) {
277  //negative weights are from ignored particles, we don't like them and
278  //thus ignore them :D
279  if (element.getWeight(i) < 0) continue;
280  relation[element.getToIndex(i)] += element.getWeight(i);
281  }
282  }
283 }
284 
286 {
287  if (m_cache->empty())
288  return;
289 
290  //Get all datastore elements
291  const StoreArray<MCParticle> storeMCParticles(m_storeMCParticlesName);
292  const StoreArray<PXDDigit> storeDigits(m_storeDigitsName);
293  const StoreArray<PXDTrueHit> storeTrueHits(m_storeTrueHitsName);
295  RelationArray relClusterMCParticle(storeClusters, storeMCParticles,
297  RelationArray relClusterDigit(storeClusters, storeDigits,
299  RelationArray relClusterTrueHit(storeClusters, storeTrueHits,
301 
302  //Get Geometry information
303  const SensorInfo& info = dynamic_cast<const SensorInfo&>(VXD::GeoCache::get(
304  sensorID));
305 
306  map<unsigned int, float> mc_relations;
307  map<unsigned int, float> truehit_relations;
308  vector<pair<unsigned int, float> > digit_weights;
309 
310 
311  for (ClusterCandidate& cls : *m_cache) {
312  //Check for noise cuts
313  if (!(cls.size() > 0 && m_noiseMap(cls.getCharge(), m_cutCluster) && m_noiseMap(cls.getSeed(), m_cutSeed))) continue;
314 
315  double rho(0);
316  ClusterProjection projU, projV;
317  mc_relations.clear();
318  truehit_relations.clear();
319  digit_weights.clear();
320  digit_weights.reserve(cls.size());
321 
322  const Pixel& seed = cls.getSeed();
323 
324  for (const PXD::Pixel& px : cls.pixels()) {
325  //Add the Pixel information to the two projections
326  projU.add(px.getU(), info.getUCellPosition(px.getU()), px.getCharge());
327  projV.add(px.getV(), info.getVCellPosition(px.getV()), px.getCharge());
328 
329  //Obtain relations from MCParticles
330  fillRelationMap(m_mcRelation, mc_relations, px.getIndex());
331  //Obtain relations from PXDTrueHits
332  fillRelationMap(m_trueRelation, truehit_relations, px.getIndex());
333  //Save the weight of the digits for the Cluster->Digit relation
334  digit_weights.emplace_back(px.getIndex(), px.getCharge());
335  }
336  projU.finalize();
337  projV.finalize();
338 
339  const double pitchU = info.getUPitch();
340  const double pitchV = info.getVPitch(projV.getPos());
341  // Calculate shape correlation coefficient: only for non-trivial shapes
342  if (projU.getSize() > 1 && projV.getSize() > 1) {
343  // Add in-pixel position noise to smear the correlation
344  double posUU = cls.getCharge() * pitchU * pitchU / 12.0;
345  double posVV = cls.getCharge() * pitchV * pitchV / 12.0;
346  double posUV(0);
347  for (const Pixel& px : cls.pixels()) {
348  const double du = info.getUCellPosition(px.getU()) - projU.getPos();
349  const double dv = info.getVCellPosition(px.getV()) - projV.getPos();
350  posUU += px.getCharge() * du * du;
351  posVV += px.getCharge() * dv * dv;
352  posUV += px.getCharge() * du * dv;
353  }
354  rho = posUV / sqrt(posUU * posVV);
355  }
356 
357  //Calculate position and error with u as primary axis, fixed pitch size
358  calculatePositionError(cls, projU, projV, pitchU, pitchU, pitchU);
359  //Calculate position and error with v as primary axis, possibly different pitch sizes
360  calculatePositionError(cls, projV, projU, info.getVPitch(projV.getMinPos()), pitchV, info.getVPitch(projV.getMaxPos()));
361 
362  if (m_errorFromDB) { // Overwrite cluster position error with value from DB (keep the above calculation untouched for now)
363  unsigned int uID = info.getUCellID(projU.getPos());
364  unsigned int vID = info.getVCellID(projV.getPos());
365  bool isUedge = PXD::isClusterAtUEdge(sensorID, projU.getMinCell(), projU.getMaxCell());
366  bool isVedge = (PXD::isClusterAtVEdge(sensorID, projV.getMinCell(), projV.getMaxCell())
367  || PXD::isClusterAtLadderJoint(sensorID, projV.getMinCell(), projV.getMaxCell()));
368  assignPositionErrorFromDB(projU, **m_clusterPositionErrorUPar, sensorID, uID, vID, pitchU, isUedge, isVedge);
369  assignPositionErrorFromDB(projV, **m_clusterPositionErrorVPar, sensorID, uID, vID, pitchV, isUedge, isVedge);
370  }
371 
372  ROOT::Math::XYZVector lorentzShift = info.getLorentzShift(projU.getPos(), projV.getPos());
373  projU.setPos(projU.getPos() - lorentzShift.X());
374  projV.setPos(projV.getPos() - lorentzShift.Y());
375  B2DEBUG(20, "Lorentz shift: " << lorentzShift.X() << " " << lorentzShift.Y());
376 
377  // Pre classification of cluster looking at pitch type of pixels and if they touch sensor edges
378  int clusterkind = PXDClusterPositionEstimator::getInstance().getClusterkind(cls.pixels(), sensorID);
379 
380  // Compute sorted set of pixel
381  // FIXME: I am not 100% sure if cls.pixels() are sorted
382  set<Pixel> pixelSet(cls.pixels().begin(), cls.pixels().end());
383 
384  // Compute classifier variables needed for later retrival of position correction in PXD CKF
385  vector<float> sectorEtaValues = {0, 0, 0, 0};
386  sectorEtaValues[0] = PXDClusterPositionEstimator::getInstance().computeEta(pixelSet, projV.getMinCell(), projV.getSize(), +1.0,
387  +1.0);
388  sectorEtaValues[1] = PXDClusterPositionEstimator::getInstance().computeEta(pixelSet, projV.getMinCell(), projV.getSize(), -1.0,
389  +1.0);
390  sectorEtaValues[2] = PXDClusterPositionEstimator::getInstance().computeEta(pixelSet, projV.getMinCell(), projV.getSize(), -1.0,
391  -1.0);
392  sectorEtaValues[3] = PXDClusterPositionEstimator::getInstance().computeEta(pixelSet, projV.getMinCell(), projV.getSize(), +1.0,
393  -1.0);
394 
395  vector<int> sectorShapeIndices = { -1, -1, -1, -1};
396  sectorShapeIndices[0] = PXDClusterPositionEstimator::getInstance().computeShapeIndex(pixelSet, projU.getMinCell(),
397  projV.getMinCell(), projV.getSize(), +1.0, +1.0);
398  sectorShapeIndices[1] = PXDClusterPositionEstimator::getInstance().computeShapeIndex(pixelSet, projU.getMinCell(),
399  projV.getMinCell(), projV.getSize(), -1.0, +1.0);
400  sectorShapeIndices[2] = PXDClusterPositionEstimator::getInstance().computeShapeIndex(pixelSet, projU.getMinCell(),
401  projV.getMinCell(), projV.getSize(), -1.0, -1.0);
402  sectorShapeIndices[3] = PXDClusterPositionEstimator::getInstance().computeShapeIndex(pixelSet, projU.getMinCell(),
403  projV.getMinCell(), projV.getSize(), +1.0, -1.0);
404 
405  //Store Cluster into Datastore ...
406  int clsIndex = storeClusters.getEntries();
407  storeClusters.appendNew(sensorID, projU.getPos(), projV.getPos(), projU.getError(), projV.getError(),
408  rho, cls.getCharge(), seed.getCharge(),
409  cls.size(), projU.getSize(), projV.getSize(), projU.getMinCell(), projV.getMinCell(), clusterkind,
410  sectorEtaValues, sectorShapeIndices
411  );
412 
413  //Create Relations to this Digit
414  if (!mc_relations.empty()) relClusterMCParticle.add(clsIndex, mc_relations.begin(), mc_relations.end());
415  if (!truehit_relations.empty()) relClusterTrueHit.add(clsIndex, truehit_relations.begin(), truehit_relations.end());
416  relClusterDigit.add(clsIndex, digit_weights.begin(), digit_weights.end());
417  }
418 
419  m_cache->clear();
420 }
421 
423  const ClusterProjection& secondary, double minPitch, double centerPitch, double maxPitch)
424 {
425  if (primary.getSize() >= static_cast<unsigned int>(m_sizeHeadTail)) { //Analog head tail
426  //Average charge in the central area
427  const double centerCharge = primary.getCenterCharge() / (primary.getSize() - 2);
428  const double minCharge = (primary.getMinCharge() < centerCharge) ? primary.getMinCharge() : centerCharge;
429  const double maxCharge = (primary.getMaxCharge() < centerCharge) ? primary.getMaxCharge() : centerCharge;
430  primary.setPos(0.5 * (primary.getMinPos() + primary.getMaxPos()
431  + (maxCharge * maxPitch - minCharge * minPitch) / centerCharge));
432  const double snHead = centerCharge / m_cutAdjacentSignal / minPitch;
433  const double snTail = centerCharge / m_cutAdjacentSignal / maxPitch;
434  const double landauHead = minCharge / centerCharge * minPitch;
435  const double landauTail = maxCharge / centerCharge * maxPitch;
436  primary.setError(0.5 * sqrt(1.0 / snHead / snHead + 1.0 / snTail / snTail
437  + 0.5 * landauHead * landauHead + 0.5 * landauTail * landauTail));
438  } else if (primary.getSize() <= 2) { // Add a phantom charge to second strip
439  primary.setError(centerPitch * (secondary.getSize() + 2) * m_cutAdjacentSignal / (primary.getCharge() +
440  (secondary.getSize() + 3) * m_cutAdjacentSignal));
441  } else {
442  const double sn = cls.getSeedCharge() / m_elNoise;
443  primary.setError(2.0 * centerPitch / sn);
444  }
445 }
446 
448  VxdID sensorID, unsigned int uCell, unsigned int vCell, double centerPitch,
449  bool isAtUEdge, bool isAtVEdge, bool isAdjacentDead)
450 {
451  // Get bins from cell ID
452  unsigned short uBin = PXD::getBinU(sensorID, uCell, vCell, errorPar.getBinsU());
453  unsigned short vBin = PXD::getBinV(sensorID, vCell, errorPar.getBinsV());
454  // Get error from DB [in units of pix]
455  double error = errorPar.getContent(sensorID.getID(), uBin, vBin, primary.getSize());
456  double sf = 1.;
457  // Apply additional factor if at sensor edges or adjacent to daed rows/colums
458  if (isAtUEdge) sf *= errorPar.getSensorUEdgeFactor(sensorID.getID(), uBin, vBin, primary.getSize());
459  if (isAtVEdge) sf *= errorPar.getSensorVEdgeFactor(sensorID.getID(), uBin, vBin, primary.getSize());
460  if (isAdjacentDead) sf *= errorPar.getDeadNeighbourFactor(sensorID.getID(), uBin, vBin, primary.getSize());
461  // Set error (convert to [um])
462  if (error) primary.setError(sf * error * centerPitch); // zero means default values to use analytic error
463 
464 }
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
The payload class for PXD cluster position error.
float getContent(unsigned short sensorID, unsigned short globalID) const
Get content.
unsigned short getBinsV() const
Get number of bins along sensor v side.
float getDeadNeighbourFactor(unsigned short sensorID, unsigned short globalID) const
Get scaling factor when neighbouring dead rows/column.
unsigned short getBinsU() const
Get number of bins along sensor u side.
float getSensorVEdgeFactor(unsigned short sensorID, unsigned short globalID) const
Get scaling factor at sensor edge in V.
float getSensorUEdgeFactor(unsigned short sensorID, unsigned short globalID) const
Get scaling factor at sensor edge in U.
The PXD digit class.
Definition: PXDDigit.h:27
VxdID getSensorID() const
Get the sensor ID.
Definition: PXDDigit.h:64
Class to remember recently assigned clusters This class will remember the current and the last pixel ...
Definition: ClusterCache.h:77
Class representing a possible cluster during clustering of the PXD It supports merging of different c...
float getSeedCharge() const
get the seed charge of the cluster
Helper struct to collect information about the 1D projection of a Pixel cluster.
double getMinPos() const
Return the position of the minimum cell of the cluster.
void add(unsigned int cell, float position, float charge)
Add Pixel information to the projection.
double getMaxCharge() const
Return the charge in the maximum cell of the cluster.
void finalize()
Finish calculation of center of gravity and set correct cluster size.
unsigned int getMinCell() const
Return the minimum cell part of the cluster.
double getCharge() const
Return the total charge of the cluster.
unsigned int getMaxCell() const
Return the maximum cell part of the cluster.
void setPos(double pos)
Set the position of the cluster.
double getMinCharge() const
Return the charge in the minimum cell of the cluster.
void setError(double error)
Set the error of the cluster.
double getError() const
Return the error of the cluster.
double getMaxPos() const
Return the position of the maximum cell of the cluster.
double getPos() const
Return the projected position of the cluster.
double getCenterCharge() const
Return the center charge of the cluster, that is total charge minus minimum and maximum cell charge.
unsigned int getSize() const
Return the projected size of the cluster.
void setNoiseLevel(float noise)
Set the noise level.
Definition: NoiseMap.h:33
virtual void setSensorID(VxdID)
Set the sensorID currently used.
Definition: NoiseMap.h:38
static PXDClusterPositionEstimator & getInstance()
Main (and only) way to access the PXDClusterPositionEstimator.
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...
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.
int getClusterkind(const PXDCluster &cluster) const
Return kind of cluster needed to find cluster position correction.
NoiseMap m_noiseMap
Noise map for the currently active sensor.
int m_clusterCacheSize
Size of cluster Cache (0 = default)
std::unique_ptr< DBObjPtr< PXDClusterPositionErrorPar > > m_clusterPositionErrorVPar
DB object for cluster posotion errors in V.
double m_cutAdjacentSignal
Signal in ADU for Adjacent cut, basically m_elNoise*m_cutAdjacent.
virtual void initialize() override
Initialize the module.
std::string m_positionErrorVName
Name of the DB payload containing cluster posotion errors in V.
std::string m_relDigitMCParticleName
Name of the relation between PXDDigits and MCParticles.
virtual void event() override
do the clustering
void calculatePositionError(const ClusterCandidate &cls, ClusterProjection &primary, const ClusterProjection &secondary, double minPitch, double centerPitch, double maxPitch)
Calculate position and error for a given cluster.
std::vector< const RelationElement * > RelationLookup
Container for a RelationArray Lookup table.
std::string m_relClusterDigitName
Name of the relation between PXDClusters and PXDDigits.
double m_cutCluster
Cluster cut in sigma.
std::string m_storeTrueHitsName
Name of the collection to use for the PXDTrueHits.
void fillRelationMap(const RelationLookup &lookup, std::map< unsigned int, float > &relation, unsigned int index)
Add the relation from a given PXDDigit index to a map.
std::string m_storeMCParticlesName
Name of the collection to use for the MCParticles.
RelationLookup m_trueRelation
Lookup table for PXDDigit->PXDTrueHit relation.
std::string m_positionErrorUName
Name of the DB payload containing cluster posotion errors in U.
virtual void beginRun() override
do at every run change
std::unique_ptr< DBObjPtr< PXDClusterPositionErrorPar > > m_clusterPositionErrorUPar
DB object for cluster posotion errors in U.
void assignPositionErrorFromDB(ClusterProjection &primary, PXDClusterPositionErrorPar errorPar, VxdID sensorID, unsigned int uCell, unsigned int vCell, double centerPitch, bool isAtUEdge=false, bool isAtVEdge=false, bool isAdjacentDead=false)
Assign position error for a given cluster from DB.
int m_sizeHeadTail
Size of the cluster at which we switch from Center of Gravity to Analog Head Tail.
std::string m_storeDigitsName
Name of the collection to use for the PXDDigits.
void createRelationLookup(const RelationArray &relation, RelationLookup &lookup, size_t digits)
Create lookup maps for Relations We do not use the RelationIndex as we know much more about the relat...
std::string m_storeClustersName
Name of the collection to use for the PXDClusters.
void writeClusters(VxdID sensorID)
Write clusters to collection.
std::string m_relDigitTrueHitName
Name of the relation between PXDDigits and PXDTrueHits.
std::string m_relClusterMCParticleName
Name of the relation between PXDClusters and MCParticles.
RelationLookup m_mcRelation
Lookup table for PXDDigit->MCParticle relation.
std::unique_ptr< ClusterCache > m_cache
cache of the last seen clusters to speed up clustering
bool m_errorFromDB
Flag to set cluster position error from DB (default = true)
double m_cutAdjacent
Noise cut in sigma.
std::string m_relClusterTrueHitName
Name of the relation between PXDClusters and PXDTrueHits.
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 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
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
void clear() override
Clear all elements from the relation.
Class to store a single element of a relation.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
void clear() override
Delete all entries in this array.
Definition: StoreArray.h:207
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
baseType getID() const
Get the unique id.
Definition: VxdID.h:94
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Namespace to encapsulate code needed for simulation and reconstrucion of the PXD.
unsigned short getBinU(VxdID id, unsigned int uid, unsigned int vid, unsigned short nBinsU)
Function to return a bin number for equal sized binning in U.
Definition: PXDUtilities.h:162
unsigned short getBinV(VxdID id, unsigned int vid, unsigned short nBinsV)
Function to return a bin number for equal sized binning in V.
Definition: PXDUtilities.h:172
bool isClusterAtVEdge(VxdID id, unsigned int vmin, unsigned int vmax)
Helper function to check if one of the end pixels are at the edge of the sensor.
Definition: PXDUtilities.h:137
bool isClusterAtUEdge(VxdID id, unsigned int umin, unsigned int umax)
Helper function to check if one of the end pixels are at the edge of the sensor.
Definition: PXDUtilities.h:126
bool isClusterAtLadderJoint(VxdID id, unsigned int vmin, unsigned int vmax)
Helper function to check if one of the end pixels are at the ladder joint.
Definition: PXDUtilities.h:149
Abstract base class for different kinds of events.