9 #include <svd/modules/svdReconstruction/SVDClusterizerModule.h>
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 #include <framework/core/Environment.h>
17 #include <svd/geometry/SensorInfo.h>
18 #include <svd/dataobjects/SVDEventInfo.h>
20 #include <svd/reconstruction/SVDReconstructionBase.h>
22 #include <svd/reconstruction/SVDRecoTimeFactory.h>
23 #include <svd/reconstruction/SVDRecoChargeFactory.h>
24 #include <svd/reconstruction/SVDRecoPositionFactory.h>
42 m_cutSeed(5.0), m_cutAdjacent(3.0), m_useDB(true)
45 setDescription(
"This module produces SVDClusters from SVDShaperDigits, providing 1-D hit position, charge and time on SVD sensors.");
46 setPropertyFlags(c_ParallelProcessingCertified);
49 addParam(
"ShaperDigits", m_storeShaperDigitsName,
50 "SVDShaperDigits collection name.",
string(
""));
51 addParam(
"Clusters", m_storeClustersName,
52 "SVDCluster collection name.",
string(
""));
53 addParam(
"SVDTrueHits", m_storeTrueHitsName,
54 "TrueHit collection name.",
string(
""));
55 addParam(
"MCParticles", m_storeMCParticlesName,
56 "MCParticles collection name.",
string(
""));
59 addParam(
"AdjacentSN", m_cutAdjacent,
60 "minimum SNR for strips to be considered for clustering. Overwritten by the dbobject, unless you set useDB = False.",
62 addParam(
"returnClusterRawTime", m_returnRawClusterTime,
63 "if True, returns the raw cluster time (to be used for time calibration).",
64 m_returnRawClusterTime);
65 addParam(
"SeedSN", m_cutSeed,
66 "minimum SNR for strips to be considered as cluster seed. Overwritten by the dbobject, unless you set useDB = False.", m_cutSeed);
67 addParam(
"ClusterSN", m_cutCluster,
68 "minimum value of the SNR of the cluster. Overwritten by the dbobject, unless you set useDB = False.", m_cutCluster);
69 addParam(
"timeAlgorithm6Samples", m_timeRecoWith6SamplesAlgorithm,
70 "cluster-time reconstruction algorithm for the 6-sample DAQ mode: CoG6 = 6-sample CoG (default), CoG3 = 3-sample CoG, ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
71 m_timeRecoWith6SamplesAlgorithm);
72 addParam(
"timeAlgorithm3Samples", m_timeRecoWith3SamplesAlgorithm,
73 "cluster-time reconstruction algorithm for the 3-sample DAQ mode: CoG6 = 6-sample CoG, CoG3 = 3-sample CoG (default), ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
74 m_timeRecoWith3SamplesAlgorithm);
75 addParam(
"chargeAlgorithm6Samples", m_chargeRecoWith6SamplesAlgorithm,
76 "cluster-charge reconstruction algorithm for 6-sample DAQ mode: MaxSample (default), SumSamples, ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
77 m_chargeRecoWith6SamplesAlgorithm);
78 addParam(
"chargeAlgorithm3Samples", m_chargeRecoWith3SamplesAlgorithm,
79 "cluster-charge reconstruction algorithm for 3-sample DAQ mode: MaxSample (default), SumSamples, ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
80 m_chargeRecoWith3SamplesAlgorithm);
81 addParam(
"positionAlgorithm6Samples", m_positionRecoWith6SamplesAlgorithm,
82 "cluster-position reconstruction algorithm for 6-sample DAQ mode: old (default), CoGOnly. Overwritten by the dbobject, unless you set useDB = False.",
83 m_positionRecoWith6SamplesAlgorithm);
84 addParam(
"positionAlgorithm3Samples", m_positionRecoWith3SamplesAlgorithm,
85 "cluster-position reconstruction algorithm for 3-sample DAQ mode: old (default), CoGOnly. Overwritten by the dbobject, unless you set useDB = False.",
86 m_positionRecoWith3SamplesAlgorithm);
88 addParam(
"stripTimeAlgorithm6Samples", m_stripTimeRecoWith6SamplesAlgorithm,
89 "strip-time reconstruction algorithm used for cluster position reconstruction for the 6-sample DAQ mode: dontdo = not done (default), CoG6 = 6-sample CoG, CoG3 = 3-sample CoG, ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
90 m_stripTimeRecoWith6SamplesAlgorithm);
91 addParam(
"stripTimeAlgorithm3Samples", m_stripTimeRecoWith3SamplesAlgorithm,
92 "strip-time reconstruction algorithm used for cluster position reconstruction for the 3-sample DAQ mode: dontdo = not done (default), CoG6 = 6-sample CoG, CoG3 = 3-sample CoG, ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
93 m_stripTimeRecoWith3SamplesAlgorithm);
94 addParam(
"stripChargeAlgorithm6Samples", m_stripChargeRecoWith6SamplesAlgorithm,
95 "strip-charge reconstruction algorithm used for cluster position reconstruction for the 6-sample DAQ mode: dontdo = not done, MaxSample, SumSamples, ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
96 m_stripChargeRecoWith6SamplesAlgorithm);
97 addParam(
"stripChargeAlgorithm3Samples", m_stripChargeRecoWith3SamplesAlgorithm,
98 "strip-charge reconstruction algorithm used for cluster position reconstruction for the 3-sample DAQ mode: dontdo = not done, MaxSample, SumSamples, ELS3 = 3-sample ELS. Overwritten by the dbobject, unless you set useDB = False.",
99 m_stripChargeRecoWith3SamplesAlgorithm);
101 addParam(
"useDB", m_useDB,
102 "if False, use clustering and reconstruction configuration module parameters", m_useDB);
106 void SVDClusterizerModule::beginRun()
109 if (!m_recoConfig.isValid())
110 B2FATAL(
"no valid configuration found for SVD reconstruction");
112 B2INFO(
"SVDRecoConfiguration: from now on we are using " << m_recoConfig->get_uniqueID());
114 m_timeRecoWith6SamplesAlgorithm = m_recoConfig->getTimeRecoWith6Samples();
115 m_timeRecoWith3SamplesAlgorithm = m_recoConfig->getTimeRecoWith3Samples();
116 m_chargeRecoWith6SamplesAlgorithm = m_recoConfig->getChargeRecoWith6Samples();
117 m_chargeRecoWith3SamplesAlgorithm = m_recoConfig->getChargeRecoWith3Samples();
118 m_positionRecoWith6SamplesAlgorithm = m_recoConfig->getPositionRecoWith6Samples();
119 m_positionRecoWith3SamplesAlgorithm = m_recoConfig->getPositionRecoWith3Samples();
122 m_stripTimeRecoWith6SamplesAlgorithm = m_recoConfig->getStripTimeRecoWith6Samples();
123 m_stripTimeRecoWith3SamplesAlgorithm = m_recoConfig->getStripTimeRecoWith3Samples();
124 m_stripChargeRecoWith6SamplesAlgorithm = m_recoConfig->getStripChargeRecoWith6Samples();
125 m_stripChargeRecoWith3SamplesAlgorithm = m_recoConfig->getStripChargeRecoWith3Samples();
132 B2WARNING(
"cluster time algorithm " << m_timeRecoWith6SamplesAlgorithm <<
" is NOT available, using CoG3");
133 m_timeRecoWith6SamplesAlgorithm =
"CoG3";
137 B2WARNING(
"cluster time algorithm " << m_timeRecoWith3SamplesAlgorithm <<
" is NOT available, using CoG3");
138 m_timeRecoWith3SamplesAlgorithm =
"CoG3";
141 B2WARNING(
"cluster charge algorithm " << m_chargeRecoWith6SamplesAlgorithm <<
" is NOT available, using MaxSample");
142 m_chargeRecoWith6SamplesAlgorithm =
"MaxSample";
145 B2WARNING(
"cluster charge algorithm " << m_chargeRecoWith3SamplesAlgorithm <<
" is NOT available, using MaxSample");
146 m_chargeRecoWith3SamplesAlgorithm =
"MaxSample";
149 B2WARNING(
"cluster position algorithm " << m_positionRecoWith6SamplesAlgorithm <<
" is NOT available, using OldDefault");
150 m_positionRecoWith6SamplesAlgorithm =
"OldDefault";
153 B2WARNING(
"cluster position algorithm " << m_positionRecoWith3SamplesAlgorithm <<
" is NOT available, using OldDefault");
154 m_positionRecoWith3SamplesAlgorithm =
"OldDefault";
158 m_time6SampleClass = SVDRecoTimeFactory::NewTime(m_timeRecoWith6SamplesAlgorithm, m_returnRawClusterTime);
159 m_time3SampleClass = SVDRecoTimeFactory::NewTime(m_timeRecoWith3SamplesAlgorithm, m_returnRawClusterTime);
160 m_charge6SampleClass = SVDRecoChargeFactory::NewCharge(m_chargeRecoWith6SamplesAlgorithm);
161 m_charge3SampleClass = SVDRecoChargeFactory::NewCharge(m_chargeRecoWith3SamplesAlgorithm);
162 m_position6SampleClass = SVDRecoPositionFactory::NewPosition(m_positionRecoWith6SamplesAlgorithm);
163 m_position6SampleClass->set_stripChargeAlgo(m_stripChargeRecoWith6SamplesAlgorithm);
164 m_position6SampleClass->set_stripTimeAlgo(m_stripTimeRecoWith6SamplesAlgorithm);
165 m_position3SampleClass = SVDRecoPositionFactory::NewPosition(m_positionRecoWith3SamplesAlgorithm);
166 m_position3SampleClass->set_stripChargeAlgo(m_stripChargeRecoWith3SamplesAlgorithm);
167 m_position3SampleClass->set_stripTimeAlgo(m_stripTimeRecoWith3SamplesAlgorithm);
169 string israwtime =
"";
170 if (m_returnRawClusterTime) israwtime =
" (raw)";
171 B2INFO(
"SVD 6-sample DAQ, cluster time algorithm: " << m_timeRecoWith6SamplesAlgorithm << israwtime <<
172 ", cluster charge algorithm: " <<
173 m_chargeRecoWith6SamplesAlgorithm <<
", cluster position algorithm: " << m_positionRecoWith6SamplesAlgorithm);
174 B2INFO(
" with strip charge reconstructed with " << m_stripChargeRecoWith6SamplesAlgorithm <<
" and strip time reconstructed with "
176 m_stripTimeRecoWith6SamplesAlgorithm);
178 B2INFO(
"SVD 3-sample DAQ, cluster time algorithm: " << m_timeRecoWith3SamplesAlgorithm << israwtime <<
179 ", cluster charge algorithm: " <<
180 m_chargeRecoWith3SamplesAlgorithm <<
", cluster position algorithm: " << m_positionRecoWith3SamplesAlgorithm);
181 B2INFO(
" with strip charge reconstructed with " << m_stripChargeRecoWith3SamplesAlgorithm <<
" and strip time reconstructed with "
183 m_stripTimeRecoWith3SamplesAlgorithm);
186 void SVDClusterizerModule::initialize()
189 m_storeClusters.registerInDataStore(m_storeClustersName, DataStore::c_ErrorIfAlreadyRegistered);
190 m_storeDigits.isRequired(m_storeShaperDigitsName);
191 m_storeTrueHits.isOptional(m_storeTrueHitsName);
192 m_storeMCParticles.isOptional(m_storeMCParticlesName);
194 RelationArray relClusterDigits(m_storeClusters, m_storeDigits);
195 RelationArray relClusterTrueHits(m_storeClusters, m_storeTrueHits);
196 RelationArray relClusterMCParticles(m_storeClusters, m_storeMCParticles);
197 RelationArray relDigitTrueHits(m_storeDigits, m_storeTrueHits);
198 RelationArray relDigitMCParticles(m_storeDigits, m_storeMCParticles);
210 m_storeClustersName = m_storeClusters.getName();
211 m_storeShaperDigitsName = m_storeDigits.getName();
212 m_storeTrueHitsName = m_storeTrueHits.getName();
213 m_storeMCParticlesName = m_storeMCParticles.getName();
215 m_relClusterShaperDigitName = relClusterDigits.
getName();
216 m_relClusterTrueHitName = relClusterTrueHits.
getName();
217 m_relClusterMCParticleName = relClusterMCParticles.
getName();
218 m_relShaperDigitTrueHitName = relDigitTrueHits.
getName();
219 m_relShaperDigitMCParticleName = relDigitMCParticles.
getName();
222 B2DEBUG(20,
"SVDClusterizer Parameters (in default system unit, *=cannot be set directly):");
224 B2DEBUG(20,
" 1. COLLECTIONS:");
225 B2DEBUG(20,
" --> MCParticles: " << m_storeMCParticlesName);
226 B2DEBUG(20,
" --> SVDShaperDigits: " << m_storeShaperDigitsName);
227 B2DEBUG(20,
" --> SVDClusters: " << m_storeClustersName);
228 B2DEBUG(20,
" --> SVDTrueHits: " << m_storeTrueHitsName);
229 B2DEBUG(20,
" 2. RELATIONS:");
230 B2DEBUG(20,
" --> DigitMCRel: " << m_relShaperDigitMCParticleName);
231 B2DEBUG(20,
" --> ClusterMCRel: " << m_relClusterMCParticleName);
232 B2DEBUG(20,
" --> ClusterDigitRel: " << m_relClusterShaperDigitName);
233 B2DEBUG(20,
" --> DigitTrueRel: " << m_relShaperDigitTrueHitName);
234 B2DEBUG(20,
" --> ClusterTrueRel: " << m_relClusterTrueHitName);
235 B2DEBUG(20,
" 3. CLUSTERING:");
236 B2DEBUG(20,
" --> Neighbour cut: " << m_cutAdjacent);
237 B2DEBUG(20,
" --> Seed cut: " << m_cutSeed);
242 void SVDClusterizerModule::event()
244 int nDigits = m_storeDigits.getEntries();
248 m_storeClusters.clear();
251 RelationArray relClusterMCParticle(m_storeClusters, m_storeMCParticles,
252 m_relClusterMCParticleName);
253 if (relClusterMCParticle) relClusterMCParticle.
clear();
255 RelationArray relClusterDigit(m_storeClusters, m_storeDigits,
256 m_relClusterShaperDigitName);
257 if (relClusterDigit) relClusterDigit.
clear();
259 RelationArray relClusterTrueHit(m_storeClusters, m_storeTrueHits,
260 m_relClusterTrueHitName);
261 if (relClusterTrueHit) relClusterTrueHit.
clear();
264 m_cutSeed = m_ClusterCal.getMinSeedSNR(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip());
265 m_cutAdjacent = m_ClusterCal.getMinAdjSNR(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip());
266 m_cutCluster = m_ClusterCal.getMinClusterSNR(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip());
270 RawCluster rawCluster(m_storeDigits[0]->getSensorID(), m_storeDigits[0]->isUStrip(), m_cutSeed, m_cutAdjacent,
271 m_storeShaperDigitsName);
277 VxdID thisSensorID = currentDigit.getSensorID();
278 bool thisSide = currentDigit.isUStrip();
279 int thisCellID = currentDigit.getCellID();
282 m_cutSeed = m_ClusterCal.getMinSeedSNR(thisSensorID, thisSide);
283 m_cutAdjacent = m_ClusterCal.getMinAdjSNR(thisSensorID, thisSide);
284 m_cutCluster = m_ClusterCal.getMinClusterSNR(thisSensorID, thisSide);
288 float thisNoise = m_NoiseCal.getNoise(thisSensorID, thisSide, thisCellID);
289 int thisCharge = currentDigit.getMaxADCCounts();
290 B2DEBUG(20,
"Noise = " << thisNoise <<
" ADC, MaxSample = " << thisCharge <<
" ADC");
292 if ((
float)thisCharge / thisNoise < m_cutAdjacent)
299 aStrip.
cellID = thisCellID;
300 aStrip.
noise = thisNoise;
301 aStrip.
samples = currentDigit.getSamples();
304 if (! rawCluster.
add(thisSensorID, thisSide, aStrip)) {
308 finalizeCluster(rawCluster);
311 rawCluster =
RawCluster(thisSensorID, thisSide, m_cutSeed, m_cutAdjacent, m_storeShaperDigitsName);
314 if (! rawCluster.
add(thisSensorID, thisSide, aStrip))
315 B2WARNING(
"this state is forbidden!!");
322 finalizeCluster(rawCluster);
324 B2DEBUG(20,
"Number of clusters: " << m_storeClusters.getEntries());
332 bool isU = rawCluster.
isUSide();
333 int size = rawCluster.
getSize();
337 std::string m_svdEventInfoName =
"SVDEventInfo";
339 m_svdEventInfoName =
"SVDEventInfoSim";
341 if (!eventinfo) B2ERROR(
"No SVDEventInfo!");
343 m_numberOfAcquiredSamples = eventinfo->getNSamples();
348 double time = std::numeric_limits<double>::quiet_NaN();
349 double timeError = std::numeric_limits<double>::quiet_NaN();
350 int firstFrame = std::numeric_limits<int>::quiet_NaN();
352 double charge = std::numeric_limits<double>::quiet_NaN();
353 double seedCharge = std::numeric_limits<float>::quiet_NaN();
354 double SNR = std::numeric_limits<double>::quiet_NaN();
356 double position = std::numeric_limits<float>::quiet_NaN();
357 double positionError = std::numeric_limits<float>::quiet_NaN();
360 if (m_numberOfAcquiredSamples == 6) {
363 m_time6SampleClass->computeClusterTime(rawCluster, time, timeError, firstFrame);
365 m_charge6SampleClass->computeClusterCharge(rawCluster, charge, SNR, seedCharge);
368 m_position6SampleClass->computeClusterPosition(rawCluster, position, positionError);
369 }
else if (m_numberOfAcquiredSamples == 3) {
371 m_time3SampleClass->computeClusterTime(rawCluster, time, timeError, firstFrame);
374 m_charge3SampleClass->computeClusterCharge(rawCluster, charge, SNR, seedCharge);
377 m_position3SampleClass->computeClusterPosition(rawCluster, position, positionError);
380 B2FATAL(
"SVD Reconstruction not available for this cluster (unrecognized or not supported number of acquired APV samples!!");
383 time = eventinfo->getTimeInFTSWReference(time, firstFrame);
386 position = applyLorentzShiftCorrection(position, sensorID, isU);
389 if (SNR > m_cutCluster) {
390 m_storeClusters.appendNew(sensorID, isU, position, positionError, time, timeError, charge, seedCharge, size, SNR, -1,
393 B2DEBUG(20,
"CLUSTER SIZE = " << size);
394 B2DEBUG(20,
" time = " << time <<
", timeError = " << timeError <<
", firstframe = " << firstFrame);
395 B2DEBUG(20,
" charge = " << charge <<
", SNR = " << SNR <<
", seedCharge = " << seedCharge);
396 B2DEBUG(20,
" position = " << position <<
", positionError = " << positionError);
399 writeClusterRelations(rawCluster);
405 RelationArray relClusterDigit(m_storeClusters, m_storeDigits, m_relClusterShaperDigitName);
407 RelationArray relClusterMCParticle(m_storeClusters, m_storeMCParticles, m_relClusterMCParticleName);
408 RelationArray relClusterTrueHit(m_storeClusters, m_storeTrueHits, m_relClusterTrueHitName);
415 int clsIndex = m_storeClusters.getEntries() - 1;
417 map<int, float> mc_relations;
418 map<int, float> truehit_relations;
420 vector<pair<int, float> > digit_weights;
421 digit_weights.reserve(m_storeClusters[clsIndex]->getSize());
425 for (
const auto& strip : strips) {
428 if (relDigitMCParticle) {
430 for (relMC_type& mcRel : relDigitMCParticle.
getElementsFrom(m_storeDigits[strip.shaperDigitIndex])) {
433 if (mcRel.weight < 0)
continue;
434 mc_relations[mcRel.indexTo] += mcRel.
weight;
438 if (relDigitTrueHit) {
440 for (relTrueHit_type& trueRel : relDigitTrueHit.
getElementsFrom(m_storeDigits[strip.shaperDigitIndex])) {
443 if (trueRel.weight < 0)
continue;
444 truehit_relations[trueRel.indexTo] += trueRel.
weight;
448 digit_weights.push_back(make_pair(strip.shaperDigitIndex, strip.maxSample));
452 if (!mc_relations.empty()) {
453 relClusterMCParticle.
add(clsIndex, mc_relations.begin(), mc_relations.end());
455 if (!truehit_relations.empty()) {
456 relClusterTrueHit.
add(clsIndex, truehit_relations.begin(), truehit_relations.end());
459 relClusterDigit.
add(clsIndex, digit_weights.begin(), digit_weights.end());
463 double SVDClusterizerModule::applyLorentzShiftCorrection(
double position,
VxdID vxdID,
bool isU)
471 bool isMC = Environment::Instance().isMC();
480 void SVDClusterizerModule::endRun()
483 delete m_time6SampleClass;
484 delete m_time3SampleClass;
485 delete m_charge6SampleClass;
486 delete m_charge3SampleClass;
487 delete m_position6SampleClass;
488 delete m_position3SampleClass;
Low-level class to create/modify relations between StoreArrays.
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.
range_from getElementsFrom(const FROM *from) const
Return a range of all elements pointing from the given object.
The SVD ShaperDigit class.
Class representing a raw cluster candidate during clustering of the SVD.
bool add(VxdID vxdID, bool isUside, struct StripInRawCluster &aStrip)
Add a Strip to the current cluster.
VxdID getSensorID() const
const std::vector< StripInRawCluster > getStripsInRawCluster() const
Class to check whether the reconstruction algorithms are available or not.
bool isChargeAlgorithmAvailable(TString chargeAlg)
bool isTimeAlgorithmAvailable(TString timeAlg)
bool isPositionAlgorithmAvailable(TString positionAlg)
Specific implementation of SensorInfo for SVD Sensors which provides additional sensor specific infor...
const TVector3 & getLorentzShift(double uCoord, double vCoord) const
Calculate Lorentz shift along a given coordinate in a magnetic field at a given position.
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.
Type-safe access to single objects in the data store.
bool isValid() const
Check whether the object was created.
Class to uniquely identify a any structure of the PXD and SVD.
baseType getLayerNumber() const
Get the layer id.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Namespace to encapsulate code needed for simulation and reconstrucion of the SVD.
Abstract base class for different kinds of events.
Element type for the index.
RelationElement::weight_type weight
weight of the relation.
structure containing the relevant informations of each strip of the raw cluster
Belle2::SVDShaperDigit::APVFloatSamples samples
ADC of the acquired samples.
int shaperDigitIndex
index of the shaper digit
int maxSample
ADC max of the acquired samples.