Belle II Software development
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
19using namespace std;
20using namespace Belle2;
21using namespace Belle2::SVD;
22
23
24//-----------------------------------------------------------------
25// Register the Module
26//-----------------------------------------------------------------
27REG_MODULE(SVDSimpleClusterizer);
28
29//-----------------------------------------------------------------
30// Implementation
31//-----------------------------------------------------------------
32
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
85 RelationArray relClusterMCParticles(m_storeClusters, 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
140 if (relClusterMCParticle) relClusterMCParticle.clear();
141
144 if (relClusterDigit) relClusterDigit.clear();
145
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) {
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:54
double getMinAdjSNR(const Belle2::VxdID &sensorID, const bool &isU) const
Return the minimum SNR for the adjacent.
Definition: SVDClustering.h:75
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
SVDSimpleClusterizerModule()
Constructor defining the parameters.
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
const std::string & getName() const
Return name under which the object is saved in the DataStore.
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
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.
STL namespace.
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