Belle II Software release-09-00-00
SVDNNClusterizerModule.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/SVDNNClusterizerModule.h>
10
11#include <framework/datastore/StoreArray.h>
12#include <framework/logging/Logger.h>
13
14#include <vxd/geometry/GeoCache.h>
15#include <svd/geometry/SensorInfo.h>
16
17#include <mdst/dataobjects/MCParticle.h>
18#include <svd/dataobjects/SVDTrueHit.h>
19#include <svd/dataobjects/SVDShaperDigit.h>
20#include <svd/dataobjects/SVDRecoDigit.h>
21#include <svd/dataobjects/SVDCluster.h>
22#include <mva/dataobjects/DatabaseRepresentationOfWeightfile.h>
23
24#include <svd/reconstruction/NNWaveFitTool.h>
25
26#include <algorithm>
27#include <numeric>
28#include <functional>
29#include <cassert>
30
31using namespace std;
32using namespace Belle2;
33using namespace Belle2::SVD;
34
35//-----------------------------------------------------------------
36// Register the Module
37//-----------------------------------------------------------------
38REG_MODULE(SVDNNClusterizer);
39
40//-----------------------------------------------------------------
41// Implementation
42//-----------------------------------------------------------------
43
45{
46 B2DEBUG(200, "SVDNNClusterizerModule ctor");
47 //Set module properties
48 setDescription("Clusterize SVDRecoDigits and reconstruct hits");
50
51 // 1. Collections.
53 "RecoDigits collection name", string(""));
54 addParam("Clusters", m_storeClustersName,
55 "Cluster collection name", string(""));
56 addParam("TrueHits", m_storeTrueHitsName,
57 "TrueHit collection name", string(""));
58 addParam("MCParticles", m_storeMCParticlesName,
59 "MCParticles collection name", string(""));
60
61 // 2. Calibration and time fitter sources
62 addParam("TimeFitterName", m_timeFitterName,
63 "Name of time fitter data file", string("SVDTimeNet_6samples"));
64 addParam("CalibratePeak", m_calibratePeak, "Use calibrattion (vs. default) for peak widths and positions", bool(false));
65
66 // 3. Clustering
67 // FIXME: Idiotic names of parameters kept for compatibility with the old clusterizer.
68 addParam("NoiseSN", m_cutAdjacent,
69 "SN for digits to be considered for clustering", m_cutAdjacent);
70 addParam("SeedSN", m_cutSeed,
71 "SN for digits to be considered as seed", m_cutSeed);
72 addParam("ClusterSN", m_cutCluster,
73 "Minimum SN for clusters", m_cutCluster);
74 addParam("HeadTailSize", m_sizeHeadTail,
75 "Cluster size at which to switch to Analog head tail algorithm", m_sizeHeadTail);
76
77}
78
80{
81 //Register collections
86
87 storeClusters.registerInDataStore();
88 storeRecoDigits.isRequired();
89 storeTrueHits.isOptional();
90 storeMCParticles.isOptional();
91
92 RelationArray relClusterRecoDigits(storeClusters, storeRecoDigits);
93 RelationArray relClusterTrueHits(storeClusters, storeTrueHits);
94 RelationArray relClusterMCParticles(storeClusters, storeMCParticles);
95 RelationArray relRecoDigitTrueHits(storeRecoDigits, storeTrueHits);
96 RelationArray relRecoDigitMCParticles(storeRecoDigits, storeMCParticles);
97
98 relClusterRecoDigits.registerInDataStore();
99 //Relations to simulation objects only if the ancestor relations exist
100 if (relRecoDigitTrueHits.isOptional())
101 relClusterTrueHits.registerInDataStore();
102 if (relRecoDigitMCParticles.isOptional())
103 relClusterMCParticles.registerInDataStore();
104
105 //Store names to speed up creation later
106 m_storeClustersName = storeClusters.getName();
107 m_storeRecoDigitsName = storeRecoDigits.getName();
108 m_storeTrueHitsName = storeTrueHits.getName();
109 m_storeMCParticlesName = storeMCParticles.getName();
110
111 m_relClusterRecoDigitName = relClusterRecoDigits.getName();
112 m_relClusterTrueHitName = relClusterTrueHits.getName();
113 m_relClusterMCParticleName = relClusterMCParticles.getName();
114 m_relRecoDigitTrueHitName = relRecoDigitTrueHits.getName();
115 m_relRecoDigitMCParticleName = relRecoDigitMCParticles.getName();
116
117 B2INFO(" 1. COLLECTIONS:");
118 B2INFO(" --> MCParticles: " << m_storeMCParticlesName);
119 B2INFO(" --> Digits: " << m_storeRecoDigitsName);
120 B2INFO(" --> Clusters: " << m_storeClustersName);
121 B2INFO(" --> TrueHits: " << m_storeTrueHitsName);
122 B2INFO(" --> DigitMCRel: " << m_relRecoDigitMCParticleName);
123 B2INFO(" --> ClusterMCRel: " << m_relClusterMCParticleName);
124 B2INFO(" --> ClusterDigitRel: " << m_relClusterRecoDigitName);
125 B2INFO(" --> DigitTrueRel: " << m_relRecoDigitTrueHitName);
126 B2INFO(" --> ClusterTrueRel: " << m_relClusterTrueHitName);
127 B2INFO(" 2. CALIBRATION DATA:");
128 B2INFO(" --> Time NN: " << m_timeFitterName);
129 B2INFO(" 4. CLUSTERING:");
130 B2INFO(" --> Neighbour cut: " << m_cutAdjacent);
131 B2INFO(" --> Seed cut: " << m_cutSeed);
132 B2INFO(" --> Cluster charge cut: " << m_cutCluster);
133 B2INFO(" --> HT for clusters >: " << m_sizeHeadTail);
134
135 // Properly initialize the NN time fitter
136 // FIXME: Should be moved to beginRun
137 // FIXME: No support for 3/6 sample switching within a run/event
139 m_fitter.setNetwrok(dbXml->m_data);
140}
141
143 RelationLookup& lookup, size_t digits)
144{
145 lookup.clear();
146 //If we don't have a relation we don't build a lookuptable
147 if (!relation) return;
148 //Resize to number of digits and set all values
149 lookup.resize(digits);
150 for (const auto& element : relation) {
151 lookup[element.getFromIndex()] = &element;
152 }
153}
154
156 std::map<unsigned int, float>& relation, unsigned int index)
157{
158 //If the lookup table is not empty and the element is set
159 if (!lookup.empty() && lookup[index]) {
160 const RelationElement& element = *lookup[index];
161 const unsigned int size = element.getSize();
162 //Add all Relations to the map
163 for (unsigned int i = 0; i < size; ++i) {
164 //negative weights are from ignored particles, we don't like them and
165 //thus ignore them :D
166 if (element.getWeight(i) < 0) continue;
167 relation[element.getToIndex(i)] += element.getWeight(i);
168 }
169 }
170}
171
173{
174 const StoreArray<SVDRecoDigit> storeRecoDigits(m_storeRecoDigitsName);
175 // If no recodigits, nothing to do
176 if (!storeRecoDigits || !storeRecoDigits.getEntries()) return;
177
178 size_t nDigits = storeRecoDigits.getEntries();
179 B2DEBUG(90, "Initial size of RecoDigits array: " << nDigits);
180
181 const StoreArray<MCParticle> storeMCParticles(m_storeMCParticlesName);
182 const StoreArray<SVDTrueHit> storeTrueHits(m_storeTrueHitsName);
183
184 RelationArray relRecoDigitMCParticle(storeRecoDigits, storeMCParticles, m_relRecoDigitMCParticleName);
185 RelationArray relRecoDigitTrueHit(storeRecoDigits, storeTrueHits, m_relRecoDigitTrueHitName);
186
188 storeClusters.clear();
189
190 RelationArray relClusterMCParticle(storeClusters, storeMCParticles,
192 if (relClusterMCParticle) relClusterMCParticle.clear();
193
194 RelationArray relClusterRecoDigit(storeClusters, storeRecoDigits,
196 if (relClusterRecoDigit) relClusterRecoDigit.clear();
197
198 RelationArray relClusterTrueHit(storeClusters, storeTrueHits,
200 if (relClusterTrueHit) relClusterTrueHit.clear();
201
202 //Build lookup tables for relations
203 createRelationLookup(relRecoDigitMCParticle, m_mcRelation, nDigits);
204 createRelationLookup(relRecoDigitTrueHit, m_trueRelation, nDigits);
205
206 // Create fit tool object
208
209 // I. Group digits by sensor/side.
210 vector<pair<unsigned short, unsigned short> > sensorDigits;
211 VxdID lastSensorID(0);
212 size_t firstSensorDigit = 0;
213 for (size_t iDigit = 0; iDigit < nDigits; ++iDigit) {
214 const SVDRecoDigit& adigit = *storeRecoDigits[iDigit];
215 VxdID sensorID = adigit.getSensorID();
216 sensorID.setSegmentNumber(adigit.isUStrip() ? 1 : 0);
217 if (sensorID != lastSensorID) { // we have a new sensor side
218 sensorDigits.push_back(make_pair(firstSensorDigit, iDigit));
219 firstSensorDigit = iDigit;
220 lastSensorID = sensorID;
221 }
222 }
223 // save last VxdID
224 sensorDigits.push_back(make_pair(firstSensorDigit, nDigits));
225
226 // ICYCLE OVER SENSORS
227 for (auto id_indices : sensorDigits) {
228 // Retrieve parameters from sensorDigits
229 unsigned int firstDigit = id_indices.first;
230 unsigned int lastDigit = id_indices.second;
231 // Get VXDID from the first digit
232 const SVDRecoDigit& sampleRecoDigit = *storeRecoDigits[firstDigit];
233 VxdID sensorID = sampleRecoDigit.getSensorID();
234 bool isU = sampleRecoDigit.isUStrip();
235
236 // Retrieve sensor parameters from GeoCache
237 const SensorInfo& sensorInfo = dynamic_cast<const SensorInfo&>(VXD::GeoCache::get(sensorID));
238
239 // 4. Cycle through digits and form clusters on the way.
240
241 // Identify contiguous groups of strips
242 // We maintain two pointers: firstDigit and lastDigit. We also keep track of last seen
243 // strip number.
244 // We start with firstDigit = lastDigit = 0
245 // If there is a gap in strip numbers or the current digit/strip is invalid, we save the
246 // current group (fd, cd), unless empty, and set fd = cd.
247 // If current strip is valid, we include it: ld = cd+1.
248
249 vector<pair<size_t, size_t> > stripGroups;
250 size_t firstClusterDigit = firstDigit;
251 size_t lastClusterDigit = firstDigit;
252 short lastStrip = -2;
253
254 B2DEBUG(300, "Clustering digits " << firstDigit << " to " << lastDigit);
255 for (size_t iDigit = firstDigit; iDigit < lastDigit; ++iDigit) {
256
257 const SVDRecoDigit& recoDigit = *storeRecoDigits[iDigit];
258 unsigned short currentStrip = recoDigit.getCellID();
259 B2DEBUG(300, "Digit " << iDigit << ", strip: " << currentStrip << ", lastStrip: " << lastStrip);
260 B2DEBUG(300, "First CD: " << firstClusterDigit << " Last CD: " << lastClusterDigit);
261
262 // See if we have a gap in strip numbers.
263 bool consecutive = ((currentStrip - lastStrip) == 1);
264 lastStrip = currentStrip;
265
266 B2DEBUG(300, (consecutive ? "consecutive" : "gap"));
267
268 // If we have a gap, we save if there is something to save
269 if (!consecutive && (firstClusterDigit < lastClusterDigit)) {
270 B2DEBUG(300, "Saving (" << firstClusterDigit << ", " << lastClusterDigit << ")");
271 stripGroups.emplace_back(firstClusterDigit, lastClusterDigit);
272 }
273
274 // Update counters
275 if (consecutive) {// consecutive : include in cluster
276 lastClusterDigit = iDigit + 1;
277 } else { // valid after a gap = new cluster
278 firstClusterDigit = iDigit;
279 lastClusterDigit = iDigit + 1;
280 }
281 } // for digits
282 // save last if any
283 if (firstClusterDigit < lastClusterDigit) {
284 B2DEBUG(300, "Saving (" << firstClusterDigit << ", " << lastDigit << ")");
285 stripGroups.emplace_back(firstClusterDigit, lastDigit);
286 }
287
288 ostringstream os;
289 os << "StripGroups: " << endl;
290 for (auto item : stripGroups) {
291 os << "(" << item.first << ", " << item.second << "), ";
292 }
293 B2DEBUG(300, os.str());
294
295 // 5. Now we loop through stripGroups and form clusters.
296 // We are still keeping digit indices, so we are keeping hold on the relations as wwell.
297 double pitch = isU ? sensorInfo.getUPitch() : sensorInfo.getVPitch();
298
299 // FIXME: Pretty stupid. There should be ClusterCandidate type to hold all this, as
300 // well as normed samples. It could calculate a lot of things by itself and make the
301 // code cleaner.
302 vector<unsigned short> stripNumbers;
303 vector<float> stripPositions;
304 vector<float> stripNoises;
305 vector<float> stripGains;
306 vector<float> timeShifts;
307 vector<float> waveWidths;
308 vector<apvSamples> storedNormedSamples;
309 vector<SVDRecoDigit::OutputProbArray> storedPDFs;
310
311 // Now reconstruct clusters
312 for (auto clusterBounds : stripGroups) {
313
314 unsigned short clusterSize = clusterBounds.second - clusterBounds.first;
315 assert(clusterSize > 0);
316
317 stripNumbers.clear();
318 stripPositions.clear();
319 stripNoises.clear();
320 stripGains.clear();
321 timeShifts.clear();
322 waveWidths.clear();
323
324 for (size_t iDigit = clusterBounds.first; iDigit < clusterBounds.second; ++iDigit) {
325 // Now we take the normed samples and calculate the common
326 // cluster probability distribution and, from it, the time and its error, and
327 // the probability of the hit being from beam background.
328 const SVDRecoDigit& recoDigit = *storeRecoDigits[iDigit];
329
330 unsigned short stripNo = recoDigit.getCellID();
331 stripNumbers.push_back(stripNo);
332 // Is the calibrations interface sensible?
333 double stripNoiseADU = m_noiseCal.getNoise(sensorID, isU, stripNo);
334 stripNoises.push_back(
335 m_pulseShapeCal.getChargeFromADC(sensorID, isU, stripNo, stripNoiseADU)
336 );
337 // Some calibrations magic.
338 // FIXME: Only use calibration on real data. Until simulations correspond to
339 // default calibrtion, we cannot use it.
340 double peakWidth = 270;
341 double timeShift = isU ? 4.0 : 0.0;
342 if (m_calibratePeak) {
343 peakWidth = 1.988 * m_pulseShapeCal.getWidth(sensorID, isU, stripNo);
344 timeShift = m_pulseShapeCal.getPeakTime(sensorID, isU, stripNo)
345 - 0.25 * peakWidth;
346 }
347 waveWidths.push_back(peakWidth);
348 timeShifts.push_back(timeShift);
349 stripPositions.push_back(
350 isU ? sensorInfo.getUCellPosition(stripNo) : sensorInfo.getVCellPosition(stripNo)
351 );
352 // Recover samples from ShaperDigits and store them.
353 apvSamples normedSamples;
354 const SVDShaperDigit* shaperDigit = recoDigit.getRelatedTo<SVDShaperDigit>();
355 if (!shaperDigit) // PANIC, this should not happen.
356 B2FATAL("Missing SVDRecoDigits->SVDShaperDigits relation. This should not happen.");
357 auto samples = shaperDigit->getSamples();
358 transform(samples.begin(), samples.end(), normedSamples.begin(),
359 bind2nd(divides<float>(), stripNoiseADU));
360
361 // These are from ShaperDigit, we need to zeroSuppress again,
362 // just in case.
363 zeroSuppress(normedSamples, m_cutAdjacent);
364 storedNormedSamples.emplace_back(normedSamples);
365 storedPDFs.emplace_back(recoDigit.getProbabilities());
366 }
367 // The formulas don't take into account differences in strip noises. So we take RMS
368 // strip noise as cluster noise.
369 // clusterNoise is noise in electrons.
370 float clusterNoise = sqrt(
371 1.0 / clusterSize
372 * inner_product(stripNoises.begin(), stripNoises.end(), stripNoises.begin(), 0.0)
373 );
374 B2DEBUG(200, "RMS cluster noise: " << clusterNoise);
375
376 // This will hold component pdfs. We may want to rememeber them to study
377 // homogeneity of cluster times.
378 shared_ptr<nnFitterBinData> pStrip;
379 // This will aggregate the components pdfs to get cluster time pdf
380 nnFitterBinData pCluster(m_fitter.getBinCenters().size());
381 fill(pCluster.begin(), pCluster.end(), double(1.0));
382
383 for (size_t iClusterStrip = 0; iClusterStrip < clusterSize; ++iClusterStrip) {
384 size_t iDigit = clusterBounds.first + iClusterStrip;
385 ostringstream os1;
386 os1 << "Input to NNFitter: iDigit = " << iDigit << endl << "Samples: ";
387 copy(storedNormedSamples[iClusterStrip].begin(), storedNormedSamples[iClusterStrip].end(),
388 ostream_iterator<double>(os1, " "));
389 os1 << endl;
390 os1 << "PDF from RecoDigit: " << endl;
391 copy(storedPDFs[iClusterStrip].begin(), storedPDFs[iClusterStrip].end(), ostream_iterator<double>(os1, " "));
392 os1 << endl;
393 fitTool.multiply(pCluster, storedPDFs[iClusterStrip]);
394 os1 << "Accummulated: " << endl;
395 copy(pCluster.begin(), pCluster.end(), ostream_iterator<double>(os1, " "));
396 B2DEBUG(200, os1.str());
397 }
398 // We can now calculate clsuter time and its error.
399 double clusterTime, clusterTimeErr;
400 tie(clusterTime, clusterTimeErr) = fitTool.getTimeShift(pCluster);
401 B2DEBUG(200, "Time: " << clusterTime << " +/- " << clusterTimeErr);
402 // Now we have the cluster time pdf, so we can calculate amplitudes.
403 // In the next cycle thrugh cluster's digits, we calculate ampltidues and their
404 // errors.
405 vector<double> stripAmplitudes(stripNoises.size());
406 vector<double> stripAmplitudeErrors(stripNoises.size());
407 double clusterChi2 = 0.0;
408 for (size_t iClusterStrip = 0; iClusterStrip < clusterSize; ++iClusterStrip) {
409 size_t iDigit = clusterBounds.first + iClusterStrip;
410 double snAmp, snAmpError, chi2;
411 tie(snAmp, snAmpError, chi2) =
412 fitTool.getAmplitudeChi2(storedNormedSamples[iClusterStrip], clusterTime, waveWidths[iClusterStrip]);
413 // We have to de-normalize: Multiply amplitudes in SN units by noises in electrons.
414 stripAmplitudes[iClusterStrip] = stripNoises[iClusterStrip] * snAmp;
415 stripAmplitudeErrors[iClusterStrip] = stripNoises[iClusterStrip] * snAmpError;
416 clusterChi2 += chi2;
417 B2DEBUG(200, "Digit " << iDigit << " Noise: " << stripNoises[iClusterStrip]
418 << " Amplitude: " << stripAmplitudes[iClusterStrip]
419 << " +/- " << stripAmplitudeErrors[iClusterStrip]
420 << " Chi2: " << chi2
421 );
422 }
423 // Cluster charge, S/N, chi2
424 float clusterCharge = accumulate(stripAmplitudes.begin(), stripAmplitudes.end(), 0.0);
425 float clusterChargeError = sqrt(
426 inner_product(stripAmplitudeErrors.begin(), stripAmplitudeErrors.end(),
427 stripAmplitudeErrors.begin(), 0.0)
428 );
429 float clusterSN = (clusterChargeError > 0) ? clusterCharge / clusterChargeError : clusterCharge;
430 // FIXME: Return chi2 and ndf from GetApmplitude, this is ugly.
431 clusterChi2 /= clusterSize;
432 // Cluster seed
433 size_t seedIndex = distance(stripAmplitudes.begin(), max_element(
434 stripAmplitudes.begin(), stripAmplitudes.end()));
435 float clusterSeedCharge = stripAmplitudes[seedIndex];
436 B2DEBUG(200, "Cluster parameters:");
437 B2DEBUG(200, "Charge: " << clusterCharge << " +/- " << clusterChargeError);
438 B2DEBUG(200, "Seed: " << clusterSeedCharge << " +/- " << stripAmplitudeErrors[seedIndex]);
439 B2DEBUG(200, "S/N: " << clusterSN);
440 B2DEBUG(200, "chi2: " << clusterChi2);
441
442 // Hit position
443 float clusterPosition, clusterPositionError;
444
445 // Now censoring:
446 // NB: We don't censor strip charges again. The requirement of 3 consecutive samples
447 // above threshold is a good enough safeguard.
448 if ((clusterCharge < clusterNoise * m_cutCluster) || (clusterSeedCharge < clusterNoise * m_cutSeed))
449 continue;
450
451 if (clusterSize < m_sizeHeadTail) { // centre of gravity
452 clusterPosition = 1.0 / clusterCharge * inner_product(
453 stripAmplitudes.begin(), stripAmplitudes.end(), stripPositions.begin(), 0.0
454 );
455 // Strip charge equal to zero-suppression threshold
456 float phantomCharge = m_cutAdjacent * clusterNoise;
457 if (clusterSize == 1) {
458 clusterPositionError = pitch * phantomCharge / (clusterCharge + phantomCharge);
459 } else {
460 clusterPositionError = pitch * phantomCharge / clusterCharge;
461 }
462 } else { // Head-tail
463 float leftStripCharge = stripAmplitudes.front();
464 float leftPos = stripPositions.front();
465 float rightStripCharge = stripAmplitudes.back();
466 float rightPos = stripPositions.back();
467 float centreCharge = (clusterCharge - leftStripCharge - rightStripCharge) / (clusterSize - 2);
468 leftStripCharge = (leftStripCharge < centreCharge) ? leftStripCharge : centreCharge;
469 rightStripCharge = (rightStripCharge < centreCharge) ? rightStripCharge : centreCharge;
470 clusterPosition = 0.5 * (leftPos + rightPos)
471 + 0.5 * (rightStripCharge - leftStripCharge) / centreCharge * pitch;
472 float sn = centreCharge / m_cutAdjacent / clusterNoise;
473 // Rough estimates of Landau noise
474 float landauHead = leftStripCharge / centreCharge;
475 double landauTail = rightStripCharge / centreCharge;
476 clusterPositionError = 0.5 * pitch * sqrt(1.0 / sn / sn
477 + 0.5 * landauHead * landauHead + 0.5 * landauTail * landauTail);
478 }
479 //Lorentz shift correction
480 clusterPosition -= sensorInfo.getLorentzShift(isU, clusterPosition);
481
482 // Finally, we save the cluster and its relations.
483 map<unsigned int, float> mc_relations;
484 map<unsigned int, float> truehit_relations;
485 vector<pair<unsigned int, float> > digit_weights;
486 digit_weights.reserve(clusterSize);
487
488 for (size_t iDigit = clusterBounds.first; iDigit < clusterBounds.second; ++iDigit) {
489 // Store relations to MCParticles and SVDTrueHits
490 fillRelationMap(m_mcRelation, mc_relations, iDigit);
491 fillRelationMap(m_trueRelation, truehit_relations, iDigit);
492 //Add digit to the Cluster->Digit relation list
493 digit_weights.emplace_back(iDigit, stripAmplitudes[iDigit - clusterBounds.first]);
494 }
495
496 //Store the cluster into Datastore ...
497 int clsIndex = storeClusters.getEntries();
498 VxdID clusterSensorID = sensorID;
499 clusterSensorID.setSegmentNumber(0);
500 storeClusters.appendNew(
501 SVDCluster(sensorID, isU, clusterPosition, clusterPositionError, clusterTime,
502 clusterTimeErr, clusterCharge, clusterSeedCharge, clusterSize, clusterSN, clusterChi2)
503 );
504
505 //Create relations to the cluster
506 if (!mc_relations.empty()) {
507 relClusterMCParticle.add(clsIndex, mc_relations.begin(), mc_relations.end());
508 }
509 if (!truehit_relations.empty()) {
510 relClusterTrueHit.add(clsIndex, truehit_relations.begin(), truehit_relations.end());
511 }
512 relClusterRecoDigit.add(clsIndex, digit_weights.begin(), digit_weights.end());
513 } // CYCLE OVER CLUSTERS for stripGroups
514
515 } // CYCLE OVER SENSORS for items in sensorDigits
516
517 B2DEBUG(100, "Number of clusters: " << storeClusters.getEntries());
518
519} // event()
520
521
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
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.
Class to store a single element of a relation.
TO * getRelatedTo(const std::string &name="", const std::string &namedRelation="") const
Get the object to which this object has a relation.
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
Definition: SVDCluster.h:29
float getNoise(const VxdID &sensorID, const bool &isU, const unsigned short &strip) const
This is the method for getting the noise.
double getChargeFromADC(const Belle2::VxdID &sensorID, const bool &isU, const unsigned short &strip, const double &pulseADC) const
Return the charge (number of electrons/holes) collected on a specific strip, given the number of ADC ...
float getPeakTime(const VxdID &sensorID, const bool &isU, const unsigned short &strip) const
Return the peaking time of the strip.
float getWidth(const VxdID &sensorID, const bool &isU, const unsigned short &strip) const
Return the width of the pulse shape for a given strip.
The SVD RecoDigit class.
Definition: SVDRecoDigit.h:43
OutputProbArray getProbabilities() const
Get signal time pdf.
Definition: SVDRecoDigit.h:144
VxdID getSensorID() const
Get the sensor ID.
Definition: SVDRecoDigit.h:98
short int getCellID() const
Get strip ID.
Definition: SVDRecoDigit.h:114
bool isUStrip() const
Get strip direction.
Definition: SVDRecoDigit.h:109
The SVD ShaperDigit class.
APVFloatSamples getSamples() const
Get array of samples.
The class holds arrays of bins and bin centers, and a wave generator object containing information on...
Definition: NNWaveFitTool.h:91
std::tuple< double, double, double > getAmplitudeChi2(const apvSamples &samples, double timeShift, double tau)
Return std::tuple with signal amplitude, its error, and chi2 of the fit.
std::tuple< double, double > getTimeShift(const nnFitterBinData &p)
Return std::tuple containing time shift and its error.
void multiply(nnFitterBinData &p, const nnFitterBinData &p1)
Multiply probabilities.
void setNetwrok(const std::string &xmlData)
Set proper network definition file.
const NNWaveFitTool & getFitTool() const
Get a handle to a NNWaveFit object.
Definition: NNWaveFitter.h:98
const nnFitterBinData & getBinCenters() const
Get bin times of the network output.
Definition: NNWaveFitter.h:104
std::string m_storeRecoDigitsName
Name of the collection to use for the SVDRecoDigits.
virtual void initialize() override
Initialize the module.
virtual void event() override
do the clustering
std::vector< const RelationElement * > RelationLookup
Container for a RelationArray Lookup table.
std::string m_relRecoDigitTrueHitName
Name of the relation between SVDRecoDigits and SVDTrueHits.
double m_cutCluster
Cluster cut in units of m_elNoise.
std::string m_storeTrueHitsName
Name of the collection to use for the SVDTrueHits.
std::string m_relRecoDigitMCParticleName
Name of the relation between SVDRecoDigits and MCParticles.
std::string m_timeFitterName
Name of the time fitter (db label)
void fillRelationMap(const RelationLookup &lookup, std::map< unsigned int, float > &relation, unsigned int index)
Add the relation from a given SVDRecoDigit index to a map.
std::string m_storeMCParticlesName
Name of the collection to use for the MCParticles.
RelationLookup m_trueRelation
Lookup table for SVDRecoDigit->SVDTrueHit relation.
SVDPulseShapeCalibrations m_pulseShapeCal
Calibrations: pusle shape and gain.
SVDNoiseCalibrations m_noiseCal
Calibrations: noise.
int m_sizeHeadTail
Size of the cluster at which we switch from Center of Gravity to Analog Head Tail.
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 SVDClusters.
double m_cutSeed
Seed cut in units of m_elNoise.
std::string m_relClusterMCParticleName
Name of the relation between SVDClusters and MCParticles.
SVDNNClusterizerModule()
Constructor defining the parameters.
RelationLookup m_mcRelation
Lookup table for SVDRecoDigit->MCParticle relation.
std::string m_relClusterRecoDigitName
Name of the relation between SVDClusters and SVDRecoDigits.
bool m_calibratePeak
Use peak widths and peak time calibrations? Unitl this is also simulated, set to true only for testbe...
double m_cutAdjacent
Noise (cluster member) cut in units of m_elNoise.
std::string m_relClusterTrueHitName
Name of the relation between SVDClusters and SVDTrueHits.
Specific implementation of SensorInfo for SVD Sensors which provides additional sensor specific infor...
Definition: SensorInfo.h:25
const ROOT::Math::XYZVector & getLorentzShift(double uCoord, double vCoord) const
Calculate Lorentz shift along a given coordinate in a magnetic field at a given position.
Definition: SensorInfo.cc:104
const std::string & getName() const
Return name under which the object is saved in the DataStore.
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.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
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
double getVCellPosition(int vID) const
Return the position of a specific strip/pixel in v direction.
double getUPitch(double v=0) const
Return the pitch of the sensor.
double getUCellPosition(int uID, int vID=-1) const
Return the position of a specific strip/pixel in u direction.
double getVPitch(double v=0) const
Return the pitch of the sensor.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
void setSegmentNumber(baseType segment)
Set the sensor segment.
Definition: VxdID.h:113
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 SVD.
Definition: GeoSVDCreator.h:23
std::array< apvSampleBaseType, nAPVSamples > apvSamples
vector od apvSample BaseType objects
std::vector< double > nnFitterBinData
Vector of values defined for bins, such as bin times or bin probabilities.
Definition: NNWaveFitTool.h:30
void zeroSuppress(T &a, double thr)
pass zero suppression
Abstract base class for different kinds of events.
STL namespace.