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 <TMath.h>
11
12using namespace Belle2;
13using namespace std;
14
15//-----------------------------------------------------------------
16// Register the Module
17//-----------------------------------------------------------------
18REG_MODULE(SVDCoGTimeEstimator);
19
20//-----------------------------------------------------------------
21// Implementation
22//-----------------------------------------------------------------
23
25{
26 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.");
28
29 addParam("SVDEventInfo", m_svdEventInfoName,
30 "SVDEventInfo name", string(""));
31 addParam("ShaperDigits", m_storeShaperDigitsName,
32 "ShaperDigits collection name", string(""));
33 addParam("RecoDigits", m_storeRecoDigitsName,
34 "RecoDigits collection name", string(""));
35 addParam("StripPeakTimeCorrection", m_corrPeakTime,
36 "Correct for the different peaking times of the strips, obtained from local run calibration", true);
37 addParam("CalibrationWithEventT0", m_calEventT0,
38 "Use the timing informations of the EventT0 in order to calibrate the CoG.",
39 true);
40
41}
42
43
45{
46}
47
48
50{
51 m_storeTrueHits.isOptional();
53
54 //Inizialization of needed store array
56
57 if (!m_storeSVDEvtInfo.isOptional(m_svdEventInfoName)) m_svdEventInfoName = "SVDEventInfoSim";
59
60 //Initialize the new RecoDigit
62
63 RelationArray relRecoDigitShaperDigits(m_storeReco, m_storeShaper);
64 relRecoDigitShaperDigits.registerInDataStore();
65 RelationArray relRecoDigitTrueHits(m_storeReco, m_storeTrueHits);
66 RelationArray relRecoDigitMCParticles(m_storeReco, m_storeMCParticles);
67 RelationArray relShaperDigitTrueHits(m_storeShaper, m_storeTrueHits);
68 RelationArray relShaperDigitMCParticles(m_storeShaper, m_storeMCParticles);
69
70 //Relations to simulation objects only if the ancestor relations exist
71 if (relShaperDigitTrueHits.isOptional())
72 relRecoDigitTrueHits.registerInDataStore();
73 if (relShaperDigitMCParticles.isOptional())
74 relRecoDigitMCParticles.registerInDataStore();
75
76 //Store names to speed up creation later
79
80 m_relRecoDigitShaperDigitName = relRecoDigitShaperDigits.getName();
81 m_relRecoDigitTrueHitName = relRecoDigitTrueHits.getName();
82 m_relRecoDigitMCParticleName = relRecoDigitMCParticles.getName();
83 m_relShaperDigitTrueHitName = relShaperDigitTrueHits.getName();
84 m_relShaperDigitMCParticleName = relShaperDigitMCParticles.getName();
85
86 B2DEBUG(25, " 1. COLLECTIONS:");
87 B2DEBUG(25, " --> MCParticles: " << m_storeMCParticlesName);
88 B2DEBUG(25, " --> Digits: " << m_storeShaperDigitsName);
89 B2DEBUG(25, " --> RecoDigits: " << m_storeRecoDigitsName);
90 B2DEBUG(25, " --> TrueHits: " << m_storeTrueHitsName);
91 B2DEBUG(25, " --> DigitMCRel: " << m_relShaperDigitMCParticleName);
92 B2DEBUG(25, " --> RecoDigitMCRel: " << m_relRecoDigitMCParticleName);
93 B2DEBUG(25, " --> RecoDigitDigitRel: " << m_relRecoDigitShaperDigitName);
94 B2DEBUG(25, " --> DigitTrueRel: " << m_relShaperDigitTrueHitName);
95 B2DEBUG(25, " --> RecoDigitTrueRel: " << m_relRecoDigitTrueHitName);
96
97}
99{
100}
101
102
104{
105
107 std::vector<float> probabilities = {0.5};
108
109 // If no digits or no SVDEventInfo, nothing to do
110 if (!m_storeShaper || !m_storeShaper.getEntries() || !m_storeSVDEvtInfo.isValid()) return;
111
112 SVDModeByte modeByte = m_storeSVDEvtInfo->getModeByte();
113 size_t nDigits = m_storeShaper.getEntries();
114
115 RelationArray relRecoDigitShaperDigit(m_storeReco, m_storeShaper,
117 if (relRecoDigitShaperDigit) relRecoDigitShaperDigit.clear();
118
119
122
123 RelationArray relRecoDigitMCParticle(m_storeReco, m_storeMCParticles,
125 if (relRecoDigitMCParticle) relRecoDigitMCParticle.clear();
126
127
128 RelationArray relRecoDigitTrueHit(m_storeReco, m_storeTrueHits,
130 if (relRecoDigitTrueHit) relRecoDigitTrueHit.clear();
131
132 //Build lookup tables for relations
133 createRelationLookup(relShaperDigitMCParticle, m_mcRelation, nDigits);
134 createRelationLookup(relShaperDigitTrueHit, m_trueRelation, nDigits);
135
136 //start loop on SVDSHaperDigits
138
140
141 B2DEBUG(25, "number of APV samples = " << m_NumberOfAPVSamples);
142
143 for (const SVDShaperDigit& shaper : m_storeShaper) {
144
145 m_StopCreationReco = false;
146
147 samples_vec = shaper.getSamples();
148
149 //retrieve the VxdID, sensor and cellID of the current RecoDigit
150 VxdID thisSensorID = shaper.getSensorID();
151 bool thisSide = shaper.isUStrip();
152 int thisCellID = shaper.getCellID();
153
154 //call of the functions doomed to calculate the required quantities
157 continue;
158 m_amplitude = CalculateAmplitude(samples_vec);
159 m_amplitudeError = CalculateAmplitudeError(thisSensorID, thisSide, thisCellID);
160
161 //need the amplitudeError in ADC as the noise of the strip to computer the error on time
163
165
166 //check too high ADC
167 if (m_amplitude > 255)
168 B2DEBUG(25, "ERROR: m_amplitude = " << m_amplitude << ", should be <= 255");
169
170 //CALIBRATION
171 //convert ADC into #e- and apply offset to shift estimated peak time to hit time (to be completed)
172 m_amplitude = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitude);
173 m_amplitudeError = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitudeError);
174
175 if (m_corrPeakTime)
176 m_weightedMeanTime -= m_PulseShapeCal.getPeakTime(thisSensorID, thisSide, thisCellID);
177 SVDModeByte::baseType triggerBin = modeByte.getTriggerBin();
178
179 if (m_calEventT0) {
180 m_weightedMeanTime = m_TimeCal.getCorrectedTime(thisSensorID, thisSide, thisCellID, m_weightedMeanTime, triggerBin);
182 m_weightedMeanTimeError, triggerBin);
183 }
184
185 //check high charges and too high ADC
186 if (m_amplitude > 100000) {
187 B2DEBUG(25, "Charge = " << m_amplitude);
188 B2DEBUG(25, "corresponding ADC = " << m_PulseShapeCal.getADCFromCharge(thisSensorID, thisSide, thisCellID, m_amplitude));
189 B2DEBUG(25, "thisLayerNumber = " << thisSensorID.getLayerNumber());
190 B2DEBUG(25, "thisLadderNumber = " << thisSensorID.getLadderNumber());
191 B2DEBUG(25, "thisSensorNumber = " << thisSensorID.getSensorNumber());
192 B2DEBUG(25, "thisSide = " << thisSide);
193 B2DEBUG(25, "thisCellID = " << thisCellID);
194 B2DEBUG(25, "-----");
195 }
196
197 //recording of the RecoDigit
198 m_storeReco.appendNew(shaper.getSensorID(), shaper.isUStrip(), shaper.getCellID(), m_amplitude, m_amplitudeError,
200
201 //Add digit to the RecoDigit->ShaperDigit relation list
202 int recoDigitIndex = m_storeReco.getEntries() - 1;
203 vector<pair<unsigned int, float> > digit_weights;
204 digit_weights.reserve(1);
205 digit_weights.emplace_back(shaper.getArrayIndex(), 1.0);
206 relRecoDigitShaperDigit.add(recoDigitIndex, digit_weights.begin(), digit_weights.end());
207
208 // Finally, we save the RecoDigit and its relations.
209 map<unsigned int, float> mc_relations;
210 map<unsigned int, float> truehit_relations;
211
212 // Store relations to MCParticles and SVDTrueHits
213 fillRelationMap(m_mcRelation, mc_relations, shaper.getArrayIndex());
214 fillRelationMap(m_trueRelation, truehit_relations, shaper.getArrayIndex());
215
216 //Create relations to the cluster
217 if (!mc_relations.empty()) {
218 relRecoDigitMCParticle.add(recoDigitIndex, mc_relations.begin(), mc_relations.end());
219 }
220 if (!truehit_relations.empty()) {
221 relRecoDigitTrueHit.add(recoDigitIndex, truehit_relations.begin(), truehit_relations.end());
222 }
223
224 }
225}
226
227
229{
230}
231
232
234{
235}
236
237
239{
240 float averagetime = 0;
241 float sumAmplitudes = 0;
242 //calculate weighted average time
243 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
244 averagetime += k * samples[k];
245 sumAmplitudes += samples[k];
246 }
247 if (sumAmplitudes != 0) {
248 averagetime /= (sumAmplitudes);
249 averagetime *= m_DeltaT;
250 } else {
251 averagetime = -1;
252 m_StopCreationReco = true;
253 B2WARNING("Trying to divide by 0 (ZERO)! Sum of amplitudes is nullptr! Skipping this SVDShaperDigit!");
254 }
255
256 return averagetime;
257}
258
260{
261 float amplitude = 0;
262 //calculate amplitude
263 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
264 if (samples[k] > amplitude)
265 amplitude = samples[k];
266 }
267
268 return amplitude;
269}
270
272{
273
274 //assuming that noise of the samples are totally UNcorrelated
275 //in MC this hypothesis is correct
276
277 //sum of samples amplitudes
278 float Atot = 0;
279 //sum of time residuals squared
280 float tmpResSq = 0;
281
282 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
283 Atot += samples[k];
284 tmpResSq += TMath::Power(k * m_DeltaT - m_weightedMeanTime, 2);
285 }
286
287 return m_amplitudeError / Atot * TMath::Sqrt(tmpResSq);
288
289}
290
291float SVDCoGTimeEstimatorModule::CalculateAmplitudeError(VxdID ThisSensorID, bool ThisSide, int ThisCellID)
292{
293 float stripnoise;
294 stripnoise = m_NoiseCal.getNoise(ThisSensorID, ThisSide, ThisCellID);
295
296 return stripnoise;
297}
298
300{
301 return 0.01;
302}
303
304
305
307 RelationLookup& lookup, size_t digits)
308{
309 lookup.clear();
310 //If we don't have a relation we don't build a lookuptable
311 if (!relation) return;
312 //Resize to number of digits and set all values
313 lookup.resize(digits);
314 for (const auto& element : relation) {
315 lookup[element.getFromIndex()] = &element;
316 }
317}
318
320 std::map<unsigned int, float>& relation, unsigned int index)
321{
322 //If the lookup table is not empty and the element is set
323 if (!lookup.empty() && lookup[index]) {
324 const RelationElement& element = *lookup[index];
325 const unsigned int size = element.getSize();
326 //Add all Relations to the map
327 for (unsigned int i = 0; i < size; ++i) {
328 //negative weights are from ignored particles, we don't like them and
329 //thus ignore them :D
330 if (element.getWeight(i) < 0) continue;
331 relation[element.getToIndex(i)] += element.getWeight(i);
332 }
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
@ 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.
Class to store a single element of a relation.
double getCorrectedTimeError(const Belle2::VxdID &sensorID, const bool &isU, const unsigned short &strip, const double &raw_time, const double &raw_timeErr, const int &bin) const
Return the strip time error, given the raw strip time, and tje raw time error.
double getCorrectedTime(const Belle2::VxdID &sensorID, const bool &isU, const unsigned short &strip, const double &raw_time, const int &bin) const
Return the strip time, given the raw strip time.
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.
Definition: SVDModeByte.h:140
uint8_t baseType
The base integer type for SVDModeByte.
Definition: SVDModeByte.h:72
float getNoise(const VxdID &sensorID, const bool &isU, const unsigned short &strip) const
This is the method for getting the noise.
long int getADCFromCharge(const Belle2::VxdID &sensorID, const bool &isU, const unsigned short &strip, const double &charge) const
Return a signed long integer corresponding to the ADC pulse height per strip, provided the charge [e]...
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.
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:33
baseType getSensorNumber() const
Get the sensor id.
Definition: VxdID.h:100
baseType getLadderNumber() const
Get the ladder id.
Definition: VxdID.h:98
baseType getLayerNumber() const
Get the layer id.
Definition: VxdID.h:96
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
Abstract base class for different kinds of events.
STL namespace.