Belle II Software  release-08-01-10
SVDSimpleClusterizerModule.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 <svd/modules/svdReconstruction/SVDSimpleClusterizerModule.h>
10 
11 #include <framework/datastore/DataStore.h>
12 #include <framework/datastore/RelationArray.h>
13 #include <framework/datastore/RelationIndex.h>
14 #include <framework/logging/Logger.h>
15 
16 #include <svd/geometry/SensorInfo.h>
17 #include <svd/dataobjects/SVDEventInfo.h>
18 
19 using namespace std;
20 using namespace Belle2;
21 using namespace Belle2::SVD;
22 
23 
24 //-----------------------------------------------------------------
25 // Register the Module
26 //-----------------------------------------------------------------
27 REG_MODULE(SVDSimpleClusterizer);
28 
29 //-----------------------------------------------------------------
30 // Implementation
31 //-----------------------------------------------------------------
32 
33 SVDSimpleClusterizerModule::SVDSimpleClusterizerModule() : Module(),
34  m_cutSeed(5.0), m_cutAdjacent(3.0), m_sizeHeadTail(3), m_cutCluster(0), m_useDB(true)
35 {
36  //Set module properties
37  setDescription("Clusterize SVDRecoDigits fitted by the Center of Gravity estimator");
39 
40  // 1. Collections.
41  addParam("RecoDigits", m_storeRecoDigitsName,
42  "SVDRecoDigits collection name", string(""));
43  addParam("Clusters", m_storeClustersName,
44  "SVDCluster collection name", string(""));
45  addParam("SVDTrueHits", m_storeTrueHitsName,
46  "TrueHit collection name", string(""));
47  addParam("MCParticles", m_storeMCParticlesName,
48  "MCParticles collection name", string(""));
49  addParam("ShaperDigits", m_storeShaperDigitsName,
50  "SVDShaperDigits collection name",
51  string(""));//NOTE: This collection is not directly accessed in this module, but indirectly accessed through SimpleClusterCandidate to get clustered samples.
52 
53  // 2. Clustering
54  addParam("AdjacentSN", m_cutAdjacent,
55  "SN for digits to be considered for clustering", m_cutAdjacent);
56  addParam("SeedSN", m_cutSeed,
57  "SN for digits to be considered as seed", m_cutSeed);
58  addParam("HeadTailSize", m_sizeHeadTail,
59  "Cluster size at which to switch to Analog head tail algorithm", m_sizeHeadTail);
60  addParam("ClusterSN", m_cutCluster,
61  "minimum value of the SNR of the cluster", m_cutCluster);
62  addParam("timeAlgorithm", m_timeAlgorithm,
63  " int to choose time algorithm: 0 = 6-sample CoG (default for 6-sample acquisition mode), 1 = 3-sample CoG (default for 3-sample acquisition mode), 2 = 3-sample ELS",
65  addParam("Calibrate3SampleWithEventT0", m_calibrate3SampleWithEventT0,
66  " if true returns the calibrated time instead of the raw time for 3-sample time algorithms",
68  addParam("useDB", m_useDB,
69  "if false use clustering module parameters", m_useDB);
70  addParam("SVDEventInfoName", m_svdEventInfoSet,
71  "Set the SVDEventInfo to use", string("SVDEventInfoSim"));
72 
73 }
74 
76 {
77  //Register collections
82 
83  RelationArray relClusterDigits(m_storeClusters, m_storeDigits);
84  RelationArray relClusterTrueHits(m_storeClusters, m_storeTrueHits);
85  RelationArray relClusterMCParticles(m_storeClusters, m_storeMCParticles);
86  RelationArray relDigitTrueHits(m_storeDigits, m_storeTrueHits);
87  RelationArray relDigitMCParticles(m_storeDigits, m_storeMCParticles);
88 
89  relClusterDigits.registerInDataStore();
90  //Relations to simulation objects only if the ancestor relations exist
91  if (relDigitTrueHits.isOptional())
92  relClusterTrueHits.registerInDataStore();
93  if (relDigitMCParticles.isOptional())
94  relClusterMCParticles.registerInDataStore();
95 
96  //Store names to speed up creation later
101 
102  m_relClusterRecoDigitName = relClusterDigits.getName();
103  m_relClusterTrueHitName = relClusterTrueHits.getName();
104  m_relClusterMCParticleName = relClusterMCParticles.getName();
105  m_relRecoDigitTrueHitName = relDigitTrueHits.getName();
106  m_relRecoDigitMCParticleName = relDigitMCParticles.getName();
107 
108  // Report:
109  B2DEBUG(1, "SVDSimpleClusterizer Parameters (in default system unit, *=cannot be set directly):");
110 
111  B2DEBUG(1, " 1. COLLECTIONS:");
112  B2DEBUG(1, " --> MCParticles: " << DataStore::arrayName<MCParticle>(m_storeMCParticlesName));
113  B2DEBUG(1, " --> SVDRecoDigits: " << DataStore::arrayName<SVDRecoDigit>(m_storeRecoDigitsName));
114  B2DEBUG(1, " --> SVDClusters: " << DataStore::arrayName<SVDCluster>(m_storeClustersName));
115  B2DEBUG(1, " --> SVDTrueHits: " << DataStore::arrayName<SVDTrueHit>(m_storeTrueHitsName));
116  B2DEBUG(1, " --> DigitMCRel: " << m_relRecoDigitMCParticleName);
117  B2DEBUG(1, " --> ClusterMCRel: " << m_relClusterMCParticleName);
118  B2DEBUG(1, " --> ClusterDigitRel: " << m_relClusterRecoDigitName);
119  B2DEBUG(1, " --> DigitTrueRel: " << m_relRecoDigitTrueHitName);
120  B2DEBUG(1, " --> ClusterTrueRel: " << m_relClusterTrueHitName);
121  B2DEBUG(1, " 2. CLUSTERING:");
122  B2DEBUG(1, " --> Neighbour cut: " << m_cutAdjacent);
123  B2DEBUG(1, " --> Seed cut: " << m_cutSeed);
124  B2DEBUG(1, " --> Size HeadTail: " << m_sizeHeadTail);
125  B2DEBUG(1, " --> SVDEventInfoName: " << m_svdEventInfoSet);
126 }
127 
128 
129 
131 {
132  int nDigits = m_storeDigits.getEntries();
133  if (nDigits == 0)
134  return;
135 
137 
138  RelationArray relClusterMCParticle(m_storeClusters, m_storeMCParticles,
140  if (relClusterMCParticle) relClusterMCParticle.clear();
141 
144  if (relClusterDigit) relClusterDigit.clear();
145 
146  RelationArray relClusterTrueHit(m_storeClusters, m_storeTrueHits,
148  if (relClusterTrueHit) relClusterTrueHit.clear();
149 
150 
151  if (m_useDB) {
152  m_cutSeed = m_ClusterCal.getMinSeedSNR(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip());
153  m_cutAdjacent = m_ClusterCal.getMinAdjSNR(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip());
154  m_cutCluster = m_ClusterCal.getMinClusterSNR(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip());
155  }
156  //create a dummy cluster just to start
157  SimpleClusterCandidate clusterCandidate(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip(),
159 
160  //loop over the SVDRecoDigits
161  int i = 0;
162  while (i < nDigits) {
163 
164  //retrieve the VxdID, sensor and cellID of the current RecoDigit
165  VxdID thisSensorID = m_storeDigits[i]->getSensorID();
166  bool thisSide = m_storeDigits[i]->isUStrip();
167  int thisCellID = m_storeDigits[i]->getCellID();
168 
169  if (m_useDB) {
170  m_cutSeed = m_ClusterCal.getMinSeedSNR(thisSensorID, thisSide);
171  m_cutAdjacent = m_ClusterCal.getMinAdjSNR(thisSensorID, thisSide);
172  m_cutCluster = m_ClusterCal.getMinClusterSNR(thisSensorID, thisSide);
173  }
174 
175  //Ignore digits with insufficient signal
176  float thisNoise = m_NoiseCal.getNoiseInElectrons(thisSensorID, thisSide, thisCellID);
177  float thisCharge = m_storeDigits[i]->getCharge();
178  B2DEBUG(10, "Noise = " << thisNoise << " e-, Charge = " << thisCharge);
179 
180  if ((float)thisCharge / thisNoise < m_cutAdjacent) {
181  i++;
182  continue;
183  }
184 
185  //this strip has a sufficient S/N
186  stripInCluster aStrip;
187  aStrip.recoDigitIndex = i;
188  aStrip.charge = thisCharge;
189  aStrip.cellID = thisCellID;
190  aStrip.noise = thisNoise;
191  //this is the 6-sample CoG time and will be used to compute the 6-sample CoG cluster time, it will not be used for in 3-sample time algorithms:
192  aStrip.time = m_storeDigits[i]->getTime();
193  aStrip.timeError = m_storeDigits[i]->getTimeError();
194 
195  //try to add the strip to the existing cluster
196  if (! clusterCandidate.add(thisSensorID, thisSide, aStrip)) {
197 
198  //if the strip is not added, write the cluster, if present and good:
199  if (clusterCandidate.size() > 0) {
200  clusterCandidate.finalizeCluster();
201  if (clusterCandidate.isGoodCluster()) {
202  writeClusters(clusterCandidate);
203  }
204  }
205 
206  //prepare for the next cluster:
207  clusterCandidate = SimpleClusterCandidate(thisSensorID, thisSide, m_sizeHeadTail, m_cutSeed, m_cutAdjacent, m_cutCluster,
210 
211  //start another cluster:
212  if (! clusterCandidate.add(thisSensorID, thisSide, aStrip))
213  B2WARNING("this state is forbidden!!");
214 
215  }
216  i++;
217  } //exit loop on RecoDigits
218 
219  //write the last cluster, if good
220  if (clusterCandidate.size() > 0) {
221  clusterCandidate.finalizeCluster();
222  if (clusterCandidate.isGoodCluster())
223  writeClusters(clusterCandidate);
224  }
225 
226  B2DEBUG(1, "Number of clusters: " << m_storeClusters.getEntries());
227 }
228 
229 
231 {
232 
234 
237 
240 
241 
242  VxdID sensorID = cluster.getSensorID();
243  bool isU = cluster.isUSide();
244  float seedCharge = cluster.getSeedCharge();
245  float charge = cluster.getCharge();
246  float size = cluster.size();
247  float SNR = cluster.getSNR();
248  float position = cluster.getPosition();
249  float positionError = m_OldDefaultSF.getCorrectedClusterPositionError(sensorID, isU, size, cluster.getPositionError());
250  //this is the 6-sample CoG time, it will not be used for in 3-sample time algorithms:
251  float time = cluster.getTime();
252  float timeError = cluster.getTimeError();
253  int firstFrame = cluster.getFirstFrame();
254 
255  //first check SVDEventInfo name
256  std::string m_svdEventInfoName = m_svdEventInfoSet;
257  if (m_svdEventInfoSet == "SVDEventInfoSim") {
258  StoreObjPtr<SVDEventInfo> temp_eventinfo("SVDEventInfo");
259  m_svdEventInfoName = "SVDEventInfo";
260  if (!temp_eventinfo.isValid())
261  m_svdEventInfoName = m_svdEventInfoSet;
262  }
263 
264  StoreObjPtr<SVDEventInfo> eventinfo(m_svdEventInfoName);
265  if (!eventinfo) B2ERROR("No SVDEventInfo!");
266 
267  //depending on the algorithm, time contains different information:
268  //6-sample CoG (0): this is the calibrated time already
269  //3-sample CoG (1) or ELS (2) this is the raw time, you need to calibrate:
270  //It is possile to get the uncalibrated 3-sample raw time here
271  //to get the 6-sample raw time there is an option in SVDCoGTimeEstimatorModule
272  float caltime = time;
274  caltime = m_3CoGTimeCal.getCorrectedTime(sensorID, isU, -1, time, -1);
276  caltime = m_3ELSTimeCal.getCorrectedTime(sensorID, isU, -1, time, -1);
277 
278  // last step:
279  // shift cluster time by TB time AND by FirstFrame ( FF = 0 for the 6-sample CoG Time)
280  // the relative shift between 3- and 6-sample DAQ is also corrected
281  // NOTE: this shift is removed in the SVDTimeCalibrationCollector in the CAF
282  time = eventinfo->getTimeInFTSWReference(caltime, firstFrame);
283 
284  // Store Cluster into Datastore
285  m_storeClusters.appendNew(sensorID, isU, position, positionError, time, timeError, charge, seedCharge, size, SNR, -1, firstFrame);
286 
287  //register relation between RecoDigit and Cluster
288  int clsIndex = m_storeClusters.getEntries() - 1;
289 
290  map<int, float> mc_relations;
291  map<int, float> truehit_relations;
292 
293  vector<pair<int, float> > digit_weights;
294  digit_weights.reserve(size);
295 
296  std::vector<stripInCluster> strips = cluster.getStripsInCluster();
297 
298  for (auto strip : strips) {
299 
300  //Fill map with MCParticle relations
301  if (relDigitMCParticle) {
302  typedef const RelationIndex<SVDRecoDigit, MCParticle>::Element relMC_type;
303  for (relMC_type& mcRel : relDigitMCParticle.getElementsFrom(m_storeDigits[strip.recoDigitIndex])) {
304  //negative weights are from ignored particles, we don't like them and
305  //thus ignore them :D
306  if (mcRel.weight < 0) continue;
307  mc_relations[mcRel.indexTo] += mcRel.weight;
308  };
309  };
310  //Fill map with SVDTrueHit relations
311  if (relDigitTrueHit) {
312  typedef const RelationIndex<SVDRecoDigit, SVDTrueHit>::Element relTrueHit_type;
313  for (relTrueHit_type& trueRel : relDigitTrueHit.getElementsFrom(m_storeDigits[strip.recoDigitIndex])) {
314  //negative weights are from ignored particles, we don't like them and
315  //thus ignore them :D
316  if (trueRel.weight < 0) continue;
317  truehit_relations[trueRel.indexTo] += trueRel.weight;
318  };
319  };
320 
321  digit_weights.push_back(make_pair(strip.recoDigitIndex, strip.charge));
322  }
323 
324 
325  //Create Relations to this Digit
326  if (!mc_relations.empty()) {
327  relClusterMCParticle.add(clsIndex, mc_relations.begin(), mc_relations.end());
328  }
329  if (!truehit_relations.empty()) {
330  relClusterTrueHit.add(clsIndex, truehit_relations.begin(), truehit_relations.end());
331  }
332 
333  relClusterDigit.add(clsIndex, digit_weights.begin(), digit_weights.end());
334 }
@ 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
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.
Provides access to fast ( O(log n) ) bi-directional lookups on a specified relation.
Definition: RelationIndex.h:76
range_from getElementsFrom(const FROM *from) const
Return a range of all elements pointing from the given object.
double getCorrectedTime(const Belle2::VxdID &sensorID, const bool &isU, const unsigned short &strip, const double &raw_time, const int &bin) const
Return the charge (number of electrons/holes) collected on a specific strip, given the number of ADC ...
double getCorrectedTime(const Belle2::VxdID &sensorID, const bool &isU, const unsigned short &strip, const double &raw_time, const int &bin) const
Return the charge (number of electrons/holes) collected on a specific strip, given the number of ADC ...
double getMinClusterSNR(const Belle2::VxdID &sensorID, const bool &isU) const
Return the minimum SNR for the cluster.
double getMinSeedSNR(const Belle2::VxdID &sensorID, const bool &isU) const
Return the minimum SNR for the seed.
Definition: SVDClustering.h:55
double getMinAdjSNR(const Belle2::VxdID &sensorID, const bool &isU) const
Return the minimum SNR for the adjacent.
Definition: SVDClustering.h:77
float getNoiseInElectrons(const VxdID &sensorID, const bool &isU, const unsigned short &strip) const
This method provides the correct noise conversion into electrons, taking into account that the noise ...
double getCorrectedClusterPositionError(const Belle2::VxdID &sensorID, const bool &isU, const int &size, const double &raw_error) const
Return the corrected cluster position error.
std::string m_storeRecoDigitsName
Name of the collection to use for the SVDRecoDigits.
SVDOldDefaultErrorScaleFactors m_OldDefaultSF
SVDCluster calibrations db object.
StoreArray< SVDTrueHit > m_storeTrueHits
Collection of SVDTrueHits.
virtual void initialize() override
Initialize the module.
StoreArray< MCParticle > m_storeMCParticles
Collection of MCParticles.
std::string m_storeShaperDigitsName
Name of the collection to use for the SVDShaperDigits.
virtual void event() override
do the clustering
void writeClusters(SimpleClusterCandidate clusterCand)
write the cluster candidate to clusters
std::string m_relRecoDigitTrueHitName
Name of the relation between SVDRecoDigits and SVDTrueHits.
SVDNoiseCalibrations m_NoiseCal
SVDNoise calibrations db object.
double m_cutCluster
Cluster cut in units of m_elNoise, not included (yet?)
std::string m_storeTrueHitsName
Name of the collection to use for the SVDTrueHits.
SVD3SampleCoGTimeCalibrations m_3CoGTimeCal
SVD 3-sample CoG Time calibrations db object.
std::string m_relRecoDigitMCParticleName
Name of the relation between SVDRecoDigits and MCParticles.
std::string m_svdEventInfoSet
Name of the SVDEventInfo to be used instead of SVDEventInfo.
SVDClustering m_ClusterCal
SVDCluster calibrations db object.
SVD3SampleELSTimeCalibrations m_3ELSTimeCal
SVD 3-sample ELS Time calibrations db object.
std::string m_storeMCParticlesName
Name of the collection to use for the MCParticles.
StoreArray< SVDRecoDigit > m_storeDigits
Collection of SVDRecoDigits.
int m_sizeHeadTail
Size of the cluster at which we switch from Center of Gravity to Analog Head Tail.
int m_timeAlgorithm
selects the algorithm to compute the cluster time 0 = 6-sample CoG (default) 1 = 3-sample CoG (TO DO:...
std::string m_storeClustersName
Name of the collection to use for the SVDClusters.
double m_cutSeed
Seed cut in units of noise.
std::string m_relClusterMCParticleName
Name of the relation between SVDClusters and MCParticles.
bool m_calibrate3SampleWithEventT0
if true returns the calibrated time instead of the raw time for 3-sample time algorithms
StoreArray< SVDCluster > m_storeClusters
Collection of SVDClusters.
std::string m_relClusterRecoDigitName
Name of the relation between SVDClusters and SVDRecoDigits.
bool m_useDB
if true takes the clusterizer cuts from the DB object
double m_cutAdjacent
Adjacent cut in units of noise.
std::string m_relClusterTrueHitName
Name of the relation between SVDClusters and SVDTrueHits.
Class representing a cluster candidate during simple clustering of the SVD.
bool add(VxdID vxdID, bool isUside, struct stripInCluster &aStrip)
Add a Strip to the current cluster.
void finalizeCluster()
compute the position, time and their error of the cluster
bool isGoodCluster()
return true if the cluster candidate can be promoted to cluster
int size() const
return the cluster size (number of strips of the cluster
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
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:111
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
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
Namespace to encapsulate code needed for simulation and reconstrucion of the SVD.
Definition: GeoSVDCreator.h:23
Abstract base class for different kinds of events.
RelationElement::weight_type weight
weight of the relation.
structure containing the relevant informations of eachstrip of the cluster
float timeError
6-sample CoG strip time error
int recoDigitIndex
index of the reco digit
float time
6-sample CoG strip time