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}
99
101{
102
104 std::vector<float> probabilities = {0.5};
105
106 // If no digits or no SVDEventInfo, nothing to do
107 if (!m_storeShaper || !m_storeShaper.getEntries() || !m_storeSVDEvtInfo.isValid()) return;
108
109 SVDModeByte modeByte = m_storeSVDEvtInfo->getModeByte();
110 size_t nDigits = m_storeShaper.getEntries();
111
112 RelationArray relRecoDigitShaperDigit(m_storeReco, m_storeShaper,
114 if (relRecoDigitShaperDigit) relRecoDigitShaperDigit.clear();
115
116
119
120 RelationArray relRecoDigitMCParticle(m_storeReco, m_storeMCParticles,
122 if (relRecoDigitMCParticle) relRecoDigitMCParticle.clear();
123
124
125 RelationArray relRecoDigitTrueHit(m_storeReco, m_storeTrueHits,
127 if (relRecoDigitTrueHit) relRecoDigitTrueHit.clear();
128
129 //Build lookup tables for relations
130 createRelationLookup(relShaperDigitMCParticle, m_mcRelation, nDigits);
131 createRelationLookup(relShaperDigitTrueHit, m_trueRelation, nDigits);
132
133 //start loop on SVDSHaperDigits
134
136
137 B2DEBUG(25, "number of APV samples = " << m_NumberOfAPVSamples);
138
139 for (const SVDShaperDigit& shaper : m_storeShaper) {
140
141 m_StopCreationReco = false;
142
144 samples_vec = shaper.getSamples();
145
146 //retrieve the VxdID, sensor and cellID of the current RecoDigit
147 VxdID thisSensorID = shaper.getSensorID();
148 bool thisSide = shaper.isUStrip();
149 int thisCellID = shaper.getCellID();
150
151 //call of the functions doomed to calculate the required quantities
154 continue;
155 m_amplitude = CalculateAmplitude(samples_vec);
156 m_amplitudeError = CalculateAmplitudeError(thisSensorID, thisSide, thisCellID);
157
158 //need the amplitudeError in ADC as the noise of the strip to computer the error on time
160
162
163 //check too high ADC
164 if (m_amplitude > 255)
165 B2DEBUG(25, "ERROR: m_amplitude = " << m_amplitude << ", should be <= 255");
166
167 //CALIBRATION
168 //convert ADC into #e- and apply offset to shift estimated peak time to hit time (to be completed)
169 m_amplitude = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitude);
170 m_amplitudeError = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitudeError);
171
172 if (m_corrPeakTime)
173 m_weightedMeanTime -= m_PulseShapeCal.getPeakTime(thisSensorID, thisSide, thisCellID);
174 SVDModeByte::baseType triggerBin = modeByte.getTriggerBin();
175
176 if (m_calEventT0) {
177 m_weightedMeanTime = m_TimeCal.getCorrectedTime(thisSensorID, thisSide, thisCellID, m_weightedMeanTime, triggerBin);
178 m_weightedMeanTimeError = m_TimeCal.getCorrectedTimeError(thisSensorID, thisSide, thisCellID, m_weightedMeanTime,
179 m_weightedMeanTimeError, triggerBin);
180 }
181
182 //check high charges and too high ADC
183 if (m_amplitude > 100000) {
184 B2DEBUG(25, "Charge = " << m_amplitude);
185 B2DEBUG(25, "corresponding ADC = " << m_PulseShapeCal.getADCFromCharge(thisSensorID, thisSide, thisCellID, m_amplitude));
186 B2DEBUG(25, "thisLayerNumber = " << thisSensorID.getLayerNumber());
187 B2DEBUG(25, "thisLadderNumber = " << thisSensorID.getLadderNumber());
188 B2DEBUG(25, "thisSensorNumber = " << thisSensorID.getSensorNumber());
189 B2DEBUG(25, "thisSide = " << thisSide);
190 B2DEBUG(25, "thisCellID = " << thisCellID);
191 B2DEBUG(25, "-----");
192 }
193
194 //recording of the RecoDigit
195 m_storeReco.appendNew(shaper.getSensorID(), shaper.isUStrip(), shaper.getCellID(), m_amplitude, m_amplitudeError,
197
198 //Add digit to the RecoDigit->ShaperDigit relation list
199 int recoDigitIndex = m_storeReco.getEntries() - 1;
200 vector<pair<unsigned int, float> > digit_weights;
201 digit_weights.reserve(1);
202 digit_weights.emplace_back(shaper.getArrayIndex(), 1.0);
203 relRecoDigitShaperDigit.add(recoDigitIndex, digit_weights.begin(), digit_weights.end());
204
205 // Finally, we save the RecoDigit and its relations.
206 map<unsigned int, float> mc_relations;
207 map<unsigned int, float> truehit_relations;
208
209 // Store relations to MCParticles and SVDTrueHits
210 fillRelationMap(m_mcRelation, mc_relations, shaper.getArrayIndex());
211 fillRelationMap(m_trueRelation, truehit_relations, shaper.getArrayIndex());
212
213 //Create relations to the cluster
214 if (!mc_relations.empty()) {
215 relRecoDigitMCParticle.add(recoDigitIndex, mc_relations.begin(), mc_relations.end());
216 }
217 if (!truehit_relations.empty()) {
218 relRecoDigitTrueHit.add(recoDigitIndex, truehit_relations.begin(), truehit_relations.end());
219 }
220
221 }
222}
223
224
225
226
228{
229 float averagetime = 0;
230 float sumAmplitudes = 0;
231 //calculate weighted average time
232 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
233 averagetime += k * samples[k];
234 sumAmplitudes += samples[k];
235 }
236 if (sumAmplitudes != 0) {
237 averagetime /= (sumAmplitudes);
238 averagetime *= m_DeltaT;
239 } else {
240 averagetime = -1;
241 m_StopCreationReco = true;
242 B2WARNING("Trying to divide by 0 (ZERO)! Sum of amplitudes is nullptr! Skipping this SVDShaperDigit!");
243 }
244
245 return averagetime;
246}
247
249{
250 float amplitude = 0;
251 //calculate amplitude
252 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
253 if (samples[k] > amplitude)
254 amplitude = samples[k];
255 }
256
257 return amplitude;
258}
259
261{
262
263 //assuming that noise of the samples are totally UNcorrelated
264 //in MC this hypothesis is correct
265
266 //sum of samples amplitudes
267 float Atot = 0;
268 //sum of time residuals squared
269 float tmpResSq = 0;
270
271 for (int k = 0; k < m_NumberOfAPVSamples; k ++) {
272 Atot += samples[k];
273 tmpResSq += square(k * m_DeltaT - m_weightedMeanTime);
274 }
275
276 return m_amplitudeError / Atot * TMath::Sqrt(tmpResSq);
277
278}
279
280float SVDCoGTimeEstimatorModule::CalculateAmplitudeError(VxdID ThisSensorID, bool ThisSide, int ThisCellID)
281{
282 float stripnoise;
283 stripnoise = m_NoiseCal.getNoise(ThisSensorID, ThisSide, ThisCellID);
284
285 return stripnoise;
286}
287
289{
290 return 0.01;
291}
292
293
294
296 RelationLookup& lookup, size_t digits)
297{
298 lookup.clear();
299 //If we don't have a relation we don't build a lookuptable
300 if (!relation) return;
301 //Resize to number of digits and set all values
302 lookup.resize(digits);
303 for (const auto& element : relation) {
304 lookup[element.getFromIndex()] = &element;
305 }
306}
307
309 std::map<unsigned int, float>& relation, unsigned int index)
310{
311 //If the lookup table is not empty and the element is set
312 if (!lookup.empty() && lookup[index]) {
313 const RelationElement& element = *lookup[index];
314 const unsigned int size = element.getSize();
315 //Add all Relations to the map
316 for (unsigned int i = 0; i < size; ++i) {
317 //negative weights are from ignored particles, we don't like them and
318 //thus ignore them :D
319 if (element.getWeight(i) < 0) continue;
320 relation[element.getToIndex(i)] += element.getWeight(i);
321 }
322 }
323}
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
@ 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.
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.
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.
static 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 ~SVDCoGTimeEstimatorModule() override
default destructor
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.