Belle II Software  release-08-01-10
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 
12 using namespace Belle2;
13 using namespace std;
14 
15 //-----------------------------------------------------------------
16 // Register the Module
17 //-----------------------------------------------------------------
18 REG_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 
139  m_NumberOfAPVSamples = m_storeSVDEvtInfo->getNSamples();
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
156  if (m_StopCreationReco)
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 
164  m_chi2 = CalculateChi2();
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);
181  m_weightedMeanTimeError = m_TimeCal.getCorrectedTimeError(thisSensorID, thisSide, thisCellID, m_weightedMeanTime,
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 
291 float 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
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.
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
REG_MODULE(arichBtest)
Register the Module.
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
Abstract base class for different kinds of events.