Belle II Software development
SVDCoGTimeEstimatorModule.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/SVDCoGTimeEstimatorModule.h>
10#include <framework/utilities/MathHelpers.h>
11#include <TMath.h>
12
13using namespace Belle2;
14using namespace std;
15
16//-----------------------------------------------------------------
17// Register the Module
18//-----------------------------------------------------------------
19REG_MODULE(SVDCoGTimeEstimator);
20
21//-----------------------------------------------------------------
22// Implementation
23//-----------------------------------------------------------------
24
26{
27 setDescription("From SVDShaperDigit to SVDRecoDigit. Strip charge is evaluated as the max of the 6 samples; hit time is evaluated as a corrected Centre of Gravity (CoG) time.");
29
30 addParam("SVDEventInfo", m_svdEventInfoName,
31 "SVDEventInfo name", string(""));
32 addParam("ShaperDigits", m_storeShaperDigitsName,
33 "ShaperDigits collection name", string(""));
34 addParam("RecoDigits", m_storeRecoDigitsName,
35 "RecoDigits collection name", string(""));
36 addParam("StripPeakTimeCorrection", m_corrPeakTime,
37 "Correct for the different peaking times of the strips, obtained from local run calibration", true);
38 addParam("CalibrationWithEventT0", m_calEventT0,
39 "Use the timing information of the EventT0 in order to calibrate the CoG.",
40 true);
41
42}
43
44
48
49
51{
52 m_storeTrueHits.isOptional();
53 m_storeMCParticles.isOptional();
54
55 //Initialization of needed store array
57
58 if (!m_storeSVDEvtInfo.isOptional(m_svdEventInfoName)) m_svdEventInfoName = "SVDEventInfoSim";
60
61 //Initialize the new RecoDigit
63
64 RelationArray relRecoDigitShaperDigits(m_storeReco, m_storeShaper);
65 relRecoDigitShaperDigits.registerInDataStore();
66 RelationArray relRecoDigitTrueHits(m_storeReco, m_storeTrueHits);
67 RelationArray relRecoDigitMCParticles(m_storeReco, m_storeMCParticles);
68 RelationArray relShaperDigitTrueHits(m_storeShaper, m_storeTrueHits);
69 RelationArray relShaperDigitMCParticles(m_storeShaper, m_storeMCParticles);
70
71 //Relations to simulation objects only if the ancestor relations exist
72 if (relShaperDigitTrueHits.isOptional())
73 relRecoDigitTrueHits.registerInDataStore();
74 if (relShaperDigitMCParticles.isOptional())
75 relRecoDigitMCParticles.registerInDataStore();
76
77 //Store names to speed up creation later
80
81 m_relRecoDigitShaperDigitName = relRecoDigitShaperDigits.getName();
82 m_relRecoDigitTrueHitName = relRecoDigitTrueHits.getName();
83 m_relRecoDigitMCParticleName = relRecoDigitMCParticles.getName();
84 m_relShaperDigitTrueHitName = relShaperDigitTrueHits.getName();
85 m_relShaperDigitMCParticleName = relShaperDigitMCParticles.getName();
86
87 B2DEBUG(25, " 1. COLLECTIONS:");
88 B2DEBUG(25, " --> MCParticles: " << m_storeMCParticlesName);
89 B2DEBUG(25, " --> Digits: " << m_storeShaperDigitsName);
90 B2DEBUG(25, " --> RecoDigits: " << m_storeRecoDigitsName);
91 B2DEBUG(25, " --> TrueHits: " << m_storeTrueHitsName);
92 B2DEBUG(25, " --> DigitMCRel: " << m_relShaperDigitMCParticleName);
93 B2DEBUG(25, " --> RecoDigitMCRel: " << m_relRecoDigitMCParticleName);
94 B2DEBUG(25, " --> RecoDigitDigitRel: " << m_relRecoDigitShaperDigitName);
95 B2DEBUG(25, " --> DigitTrueRel: " << m_relShaperDigitTrueHitName);
96 B2DEBUG(25, " --> RecoDigitTrueRel: " << m_relRecoDigitTrueHitName);
97
98}
102
103
105{
106
108 std::vector<float> probabilities = {0.5};
109
110 // If no digits or no SVDEventInfo, nothing to do
111 if (!m_storeShaper || !m_storeShaper.getEntries() || !m_storeSVDEvtInfo.isValid()) return;
112
113 SVDModeByte modeByte = m_storeSVDEvtInfo->getModeByte();
114 size_t nDigits = m_storeShaper.getEntries();
115
116 RelationArray relRecoDigitShaperDigit(m_storeReco, m_storeShaper,
118 if (relRecoDigitShaperDigit) relRecoDigitShaperDigit.clear();
119
120
123
124 RelationArray relRecoDigitMCParticle(m_storeReco, m_storeMCParticles,
126 if (relRecoDigitMCParticle) relRecoDigitMCParticle.clear();
127
128
129 RelationArray relRecoDigitTrueHit(m_storeReco, m_storeTrueHits,
131 if (relRecoDigitTrueHit) relRecoDigitTrueHit.clear();
132
133 //Build lookup tables for relations
134 createRelationLookup(relShaperDigitMCParticle, m_mcRelation, nDigits);
135 createRelationLookup(relShaperDigitTrueHit, m_trueRelation, nDigits);
136
137 //start loop on SVDSHaperDigits
139
141
142 B2DEBUG(25, "number of APV samples = " << m_NumberOfAPVSamples);
143
144 for (const SVDShaperDigit& shaper : m_storeShaper) {
145
146 m_StopCreationReco = false;
147
148 samples_vec = shaper.getSamples();
149
150 //retrieve the VxdID, sensor and cellID of the current RecoDigit
151 VxdID thisSensorID = shaper.getSensorID();
152 bool thisSide = shaper.isUStrip();
153 int thisCellID = shaper.getCellID();
154
155 //call of the functions doomed to calculate the required quantities
158 continue;
159 m_amplitude = CalculateAmplitude(samples_vec);
160 m_amplitudeError = CalculateAmplitudeError(thisSensorID, thisSide, thisCellID);
161
162 //need the amplitudeError in ADC as the noise of the strip to computer the error on time
164
166
167 //check too high ADC
168 if (m_amplitude > 255)
169 B2DEBUG(25, "ERROR: m_amplitude = " << m_amplitude << ", should be <= 255");
170
171 //CALIBRATION
172 //convert ADC into #e- and apply offset to shift estimated peak time to hit time (to be completed)
173 m_amplitude = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitude);
174 m_amplitudeError = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitudeError);
175
176 if (m_corrPeakTime)
177 m_weightedMeanTime -= m_PulseShapeCal.getPeakTime(thisSensorID, thisSide, thisCellID);
178 SVDModeByte::baseType triggerBin = modeByte.getTriggerBin();
179
180 if (m_calEventT0) {
181 m_weightedMeanTime = m_TimeCal.getCorrectedTime(thisSensorID, thisSide, thisCellID, m_weightedMeanTime, triggerBin);
182 m_weightedMeanTimeError = m_TimeCal.getCorrectedTimeError(thisSensorID, thisSide, thisCellID, m_weightedMeanTime,
183 m_weightedMeanTimeError, triggerBin);
184 }
185
186 //check high charges and too high ADC
187 if (m_amplitude > 100000) {
188 B2DEBUG(25, "Charge = " << m_amplitude);
189 B2DEBUG(25, "corresponding ADC = " << m_PulseShapeCal.getADCFromCharge(thisSensorID, thisSide, thisCellID, m_amplitude));
190 B2DEBUG(25, "thisLayerNumber = " << thisSensorID.getLayerNumber());
191 B2DEBUG(25, "thisLadderNumber = " << thisSensorID.getLadderNumber());
192 B2DEBUG(25, "thisSensorNumber = " << thisSensorID.getSensorNumber());
193 B2DEBUG(25, "thisSide = " << thisSide);
194 B2DEBUG(25, "thisCellID = " << thisCellID);
195 B2DEBUG(25, "-----");
196 }
197
198 //recording of the RecoDigit
199 m_storeReco.appendNew(shaper.getSensorID(), shaper.isUStrip(), shaper.getCellID(), m_amplitude, m_amplitudeError,
201
202 //Add digit to the RecoDigit->ShaperDigit relation list
203 int recoDigitIndex = m_storeReco.getEntries() - 1;
204 vector<pair<unsigned int, float> > digit_weights;
205 digit_weights.reserve(1);
206 digit_weights.emplace_back(shaper.getArrayIndex(), 1.0);
207 relRecoDigitShaperDigit.add(recoDigitIndex, digit_weights.begin(), digit_weights.end());
208
209 // Finally, we save the RecoDigit and its relations.
210 map<unsigned int, float> mc_relations;
211 map<unsigned int, float> truehit_relations;
212
213 // Store relations to MCParticles and SVDTrueHits
214 fillRelationMap(m_mcRelation, mc_relations, shaper.getArrayIndex());
215 fillRelationMap(m_trueRelation, truehit_relations, shaper.getArrayIndex());
216
217 //Create relations to the cluster
218 if (!mc_relations.empty()) {
219 relRecoDigitMCParticle.add(recoDigitIndex, mc_relations.begin(), mc_relations.end());
220 }
221 if (!truehit_relations.empty()) {
222 relRecoDigitTrueHit.add(recoDigitIndex, truehit_relations.begin(), truehit_relations.end());
223 }
224
225 }
226}
227
228
232
233
237
238
240{
241 float averagetime = 0;
242 float sumAmplitudes = 0;
243 //calculate weighted average time
244 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
245 averagetime += k * samples[k];
246 sumAmplitudes += samples[k];
247 }
248 if (sumAmplitudes != 0) {
249 averagetime /= (sumAmplitudes);
250 averagetime *= m_DeltaT;
251 } else {
252 averagetime = -1;
253 m_StopCreationReco = true;
254 B2WARNING("Trying to divide by 0 (ZERO)! Sum of amplitudes is nullptr! Skipping this SVDShaperDigit!");
255 }
256
257 return averagetime;
258}
259
261{
262 float amplitude = 0;
263 //calculate amplitude
264 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
265 if (samples[k] > amplitude)
266 amplitude = samples[k];
267 }
268
269 return amplitude;
270}
271
273{
274
275 //assuming that noise of the samples are totally UNcorrelated
276 //in MC this hypothesis is correct
277
278 //sum of samples amplitudes
279 float Atot = 0;
280 //sum of time residuals squared
281 float tmpResSq = 0;
282
283 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
284 Atot += samples[k];
285 tmpResSq += square(k * m_DeltaT - m_weightedMeanTime);
286 }
287
288 return m_amplitudeError / Atot * TMath::Sqrt(tmpResSq);
289
290}
291
292float SVDCoGTimeEstimatorModule::CalculateAmplitudeError(VxdID ThisSensorID, bool ThisSide, int ThisCellID)
293{
294 float stripnoise;
295 stripnoise = m_NoiseCal.getNoise(ThisSensorID, ThisSide, ThisCellID);
296
297 return stripnoise;
298}
299
301{
302 return 0.01;
303}
304
305
306
308 RelationLookup& lookup, size_t digits)
309{
310 lookup.clear();
311 //If we don't have a relation we don't build a lookuptable
312 if (!relation) return;
313 //Resize to number of digits and set all values
314 lookup.resize(digits);
315 for (const auto& element : relation) {
316 lookup[element.getFromIndex()] = &element;
317 }
318}
319
321 std::map<unsigned int, float>& relation, unsigned int index)
322{
323 //If the lookup table is not empty and the element is set
324 if (!lookup.empty() && lookup[index]) {
325 const RelationElement& element = *lookup[index];
326 const unsigned int size = element.getSize();
327 //Add all Relations to the map
328 for (unsigned int i = 0; i < size; ++i) {
329 //negative weights are from ignored particles, we don't like them and
330 //thus ignore them :D
331 if (element.getWeight(i) < 0) continue;
332 relation[element.getToIndex(i)] += element.getWeight(i);
333 }
334 }
335}
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition DataStore.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
Module()
Constructor.
Definition Module.cc:30
@ 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.
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.
std::string m_storeRecoDigitsName
Name of the collection to use for the SVDRecoDigits.
float m_chi2
Chi2, to be defined here.
SVDCoGTimeEstimatorModule()
Constructor defining the parameters.
StoreArray< SVDTrueHit > m_storeTrueHits
SVDTrueHits store array.
float CalculateAmplitudeError(VxdID ThisSensorID, bool ThisSide, int ThisCellID)
Function to calculate the amplitude error as the noise of the strip.
std::string m_relShaperDigitMCParticleName
Name of the relation between SVDShaperDigits and MCParticles.
SVDCoGTimeCalibrations m_TimeCal
SVD CoG Time calibrations db object.
bool m_corrPeakTime
correction of peakTime per strip from local calibrations
virtual void initialize() override
Initialize the SVDCoGTimeEstimator.
StoreArray< MCParticle > m_storeMCParticles
MCParticles Store array.
std::string m_storeShaperDigitsName
Name of the collection to use for the SVDShaperDigits.
virtual void event() override
This method is the core of the SVDCoGTimeEstimator.
std::vector< const RelationElement * > RelationLookup
Container for a RelationArray Lookup table.
std::string m_relRecoDigitTrueHitName
Name of the relation between SVDRecoDigits and SVDTrueHits.
float CalculateAmplitude(Belle2::SVDShaperDigit::APVFloatSamples samples)
Function to calculate the amplitude of the shaper, obtained as the largest of the 6 samples.
SVDNoiseCalibrations m_NoiseCal
SVDNoise calibrations db object.
virtual void endRun() override
This method is called if the current run ends.
std::string m_storeTrueHitsName
Name of the collection to use for the SVDTrueHits.
virtual ~SVDCoGTimeEstimatorModule()
default destructor
virtual void terminate() override
This method is called at the end of the event processing.
std::string m_relRecoDigitMCParticleName
Name of the relation between SVDRecoDigits and MCParticles.
void fillRelationMap(const RelationLookup &lookup, std::map< unsigned int, float > &relation, unsigned int index)
Add the relation from a given SVDShaperDigit index to a map.
std::string m_storeMCParticlesName
Name of the collection to use for the MCParticles.
StoreArray< SVDRecoDigit > m_storeReco
SVDRecoDigits store array.
float CalculateWeightedMeanPeakTimeError(Belle2::SVDShaperDigit::APVFloatSamples samples)
Function to calculate the peak time error.
SVDPulseShapeCalibrations m_PulseShapeCal
SVDPulseShaper calibrations db object.
float CalculateChi2()
Function to calculate chi2, that is not used here, so just set at 0.01.
std::string m_relShaperDigitTrueHitName
Name of the relation between SVDShaperDigits and SVDTrueHits.
RelationLookup m_trueRelation
Lookup table for SVDShaperDigit->SVDTrueHit relation.
virtual void beginRun() override
Called when entering a new run.
StoreArray< SVDShaperDigit > m_storeShaper
store arrays
float m_weightedMeanTime
The peak time estimation.
std::string m_svdEventInfoName
Name of the SVDEventInfo object.
void createRelationLookup(const RelationArray &relation, RelationLookup &lookup, size_t digits)
Create lookup maps for relations FIXME: This has to be significantly simplified here,...
float m_DeltaT
Time width of a sampling.
RelationLookup m_mcRelation
Lookup table for SVDShaperDigit->MCParticle relation.
bool m_StopCreationReco
To stop creation of the SVDShaperDigit if something is wrong.
StoreObjPtr< SVDEventInfo > m_storeSVDEvtInfo
storage for SVDEventInfo object
float m_weightedMeanTimeError
The peak time estimation error.
bool m_calEventT0
Parameters for the corrections.
float CalculateWeightedMeanPeakTime(Belle2::SVDShaperDigit::APVFloatSamples samples)
Function to calculate the peak time, obtained as the weighted mean of the time of the samples,...
float m_amplitudeError
The shaper amplitude estimation error.
float m_amplitude
The shaper amplitude estimation.
std::string m_relRecoDigitShaperDigitName
Name of the relation between SVDRecoDigits and SVDShaperDigits.
Class to store SVD mode information.
Definition SVDModeByte.h:69
baseType getTriggerBin() const
Get the triggerBin id.
uint8_t baseType
The base integer type for SVDModeByte.
Definition SVDModeByte.h:72
The SVD ShaperDigit class.
std::array< APVFloatSampleType, c_nAPVSamples > APVFloatSamples
array of APVFloatSampleType objects
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.
Class to uniquely identify a any structure of the PXD and SVD.
Definition VxdID.h:32
baseType getSensorNumber() const
Get the sensor id.
Definition VxdID.h:99
baseType getLadderNumber() const
Get the ladder id.
Definition VxdID.h:97
baseType getLayerNumber() const
Get the layer id.
Definition VxdID.h:95
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:559
constexpr T square(const T &x)
Calculate the square of the input.
Definition MathHelpers.h:21
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
Abstract base class for different kinds of events.
STL namespace.