9 #include <svd/modules/svdReconstruction/SVDCoGTimeEstimatorModule.h>
25 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.");
26 setPropertyFlags(c_ParallelProcessingCertified);
28 addParam(
"SVDEventInfo", m_svdEventInfoName,
29 "SVDEventInfo name",
string(
""));
30 addParam(
"ShaperDigits", m_storeShaperDigitsName,
31 "ShaperDigits collection name",
string(
""));
32 addParam(
"RecoDigits", m_storeRecoDigitsName,
33 "RecoDigits collection name",
string(
""));
34 addParam(
"StripPeakTimeCorrection", m_corrPeakTime,
35 "Correct for the different peaking times of the strips, obtained from local run calibration",
true);
36 addParam(
"CalibrationWithEventT0", m_calEventT0,
37 "Use the timing informations of the EventT0 in order to calibrate the CoG.",
50 m_storeTrueHits.isOptional();
51 m_storeMCParticles.isOptional();
54 m_storeShaper.isRequired(m_storeShaperDigitsName);
56 if (!m_storeSVDEvtInfo.isOptional(m_svdEventInfoName)) m_svdEventInfoName =
"SVDEventInfoSim";
57 m_storeSVDEvtInfo.isRequired(m_svdEventInfoName);
62 RelationArray relRecoDigitShaperDigits(m_storeReco, m_storeShaper);
64 RelationArray relRecoDigitTrueHits(m_storeReco, m_storeTrueHits);
65 RelationArray relRecoDigitMCParticles(m_storeReco, m_storeMCParticles);
66 RelationArray relShaperDigitTrueHits(m_storeShaper, m_storeTrueHits);
67 RelationArray relShaperDigitMCParticles(m_storeShaper, m_storeMCParticles);
76 m_storeTrueHitsName = m_storeTrueHits.getName();
77 m_storeMCParticlesName = m_storeMCParticles.getName();
79 m_relRecoDigitShaperDigitName = relRecoDigitShaperDigits.
getName();
80 m_relRecoDigitTrueHitName = relRecoDigitTrueHits.
getName();
81 m_relRecoDigitMCParticleName = relRecoDigitMCParticles.
getName();
82 m_relShaperDigitTrueHitName = relShaperDigitTrueHits.
getName();
83 m_relShaperDigitMCParticleName = relShaperDigitMCParticles.
getName();
85 B2DEBUG(25,
" 1. COLLECTIONS:");
86 B2DEBUG(25,
" --> MCParticles: " << m_storeMCParticlesName);
87 B2DEBUG(25,
" --> Digits: " << m_storeShaperDigitsName);
88 B2DEBUG(25,
" --> RecoDigits: " << m_storeRecoDigitsName);
89 B2DEBUG(25,
" --> TrueHits: " << m_storeTrueHitsName);
90 B2DEBUG(25,
" --> DigitMCRel: " << m_relShaperDigitMCParticleName);
91 B2DEBUG(25,
" --> RecoDigitMCRel: " << m_relRecoDigitMCParticleName);
92 B2DEBUG(25,
" --> RecoDigitDigitRel: " << m_relRecoDigitShaperDigitName);
93 B2DEBUG(25,
" --> DigitTrueRel: " << m_relShaperDigitTrueHitName);
94 B2DEBUG(25,
" --> RecoDigitTrueRel: " << m_relRecoDigitTrueHitName);
106 std::vector<float> probabilities = {0.5};
109 if (!m_storeShaper || !m_storeShaper.getEntries() || !m_storeSVDEvtInfo.isValid())
return;
111 SVDModeByte modeByte = m_storeSVDEvtInfo->getModeByte();
112 size_t nDigits = m_storeShaper.getEntries();
114 RelationArray relRecoDigitShaperDigit(m_storeReco, m_storeShaper,
115 m_relRecoDigitShaperDigitName);
116 if (relRecoDigitShaperDigit) relRecoDigitShaperDigit.
clear();
119 RelationArray relShaperDigitMCParticle(m_storeShaper, m_storeMCParticles, m_relShaperDigitMCParticleName);
120 RelationArray relShaperDigitTrueHit(m_storeShaper, m_storeTrueHits, m_relShaperDigitTrueHitName);
122 RelationArray relRecoDigitMCParticle(m_storeReco, m_storeMCParticles,
123 m_relRecoDigitMCParticleName);
124 if (relRecoDigitMCParticle) relRecoDigitMCParticle.
clear();
127 RelationArray relRecoDigitTrueHit(m_storeReco, m_storeTrueHits,
128 m_relRecoDigitTrueHitName);
129 if (relRecoDigitTrueHit) relRecoDigitTrueHit.
clear();
132 createRelationLookup(relShaperDigitMCParticle, m_mcRelation, nDigits);
133 createRelationLookup(relShaperDigitTrueHit, m_trueRelation, nDigits);
138 m_NumberOfAPVSamples = m_storeSVDEvtInfo->getNSamples();
140 B2DEBUG(25,
"number of APV samples = " << m_NumberOfAPVSamples);
144 m_StopCreationReco =
false;
147 if (m_StopCreationReco)
150 samples_vec = shaper.getSamples();
153 VxdID thisSensorID = shaper.getSensorID();
154 bool thisSide = shaper.isUStrip();
155 int thisCellID = shaper.getCellID();
158 m_weightedMeanTime = CalculateWeightedMeanPeakTime(samples_vec);
159 if (m_StopCreationReco)
161 m_amplitude = CalculateAmplitude(samples_vec);
162 m_amplitudeError = CalculateAmplitudeError(thisSensorID, thisSide, thisCellID);
165 m_weightedMeanTimeError = CalculateWeightedMeanPeakTimeError(samples_vec);
167 m_chi2 = CalculateChi2();
170 if (m_amplitude > 255)
171 B2DEBUG(25,
"ERROR: m_amplitude = " << m_amplitude <<
", should be <= 255");
175 m_amplitude = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitude);
176 m_amplitudeError = m_PulseShapeCal.getChargeFromADC(thisSensorID, thisSide, thisCellID, m_amplitudeError);
179 m_weightedMeanTime -= m_PulseShapeCal.getPeakTime(thisSensorID, thisSide, thisCellID);
183 m_weightedMeanTime = m_TimeCal.getCorrectedTime(thisSensorID, thisSide, thisCellID, m_weightedMeanTime, triggerBin);
184 m_weightedMeanTimeError = m_TimeCal.getCorrectedTimeError(thisSensorID, thisSide, thisCellID, m_weightedMeanTime,
185 m_weightedMeanTimeError, triggerBin);
189 if (m_amplitude > 100000) {
190 B2DEBUG(25,
"Charge = " << m_amplitude);
191 B2DEBUG(25,
"corresponding ADC = " << m_PulseShapeCal.getADCFromCharge(thisSensorID, thisSide, thisCellID, m_amplitude));
192 B2DEBUG(25,
"thisLayerNumber = " << thisSensorID.
getLayerNumber());
195 B2DEBUG(25,
"thisSide = " << thisSide);
196 B2DEBUG(25,
"thisCellID = " << thisCellID);
197 B2DEBUG(25,
"-----");
201 m_storeReco.appendNew(shaper.getSensorID(), shaper.isUStrip(), shaper.getCellID(), m_amplitude, m_amplitudeError,
202 m_weightedMeanTime, m_weightedMeanTimeError, probabilities, m_chi2);
205 int recoDigitIndex = m_storeReco.getEntries() - 1;
206 vector<pair<unsigned int, float> > digit_weights;
207 digit_weights.reserve(1);
208 digit_weights.emplace_back(shaper.getArrayIndex(), 1.0);
209 relRecoDigitShaperDigit.
add(recoDigitIndex, digit_weights.begin(), digit_weights.end());
212 map<unsigned int, float> mc_relations;
213 map<unsigned int, float> truehit_relations;
216 fillRelationMap(m_mcRelation, mc_relations, shaper.getArrayIndex());
217 fillRelationMap(m_trueRelation, truehit_relations, shaper.getArrayIndex());
220 if (!mc_relations.empty()) {
221 relRecoDigitMCParticle.
add(recoDigitIndex, mc_relations.begin(), mc_relations.end());
223 if (!truehit_relations.empty()) {
224 relRecoDigitTrueHit.
add(recoDigitIndex, truehit_relations.begin(), truehit_relations.end());
243 float averagetime = 0;
244 float sumAmplitudes = 0;
246 for (
int k = 0; k < m_NumberOfAPVSamples; k ++) {
247 averagetime += k * samples[k];
248 sumAmplitudes += samples[k];
250 if (sumAmplitudes != 0) {
251 averagetime /= (sumAmplitudes);
252 averagetime *= m_DeltaT;
255 m_StopCreationReco =
true;
256 B2WARNING(
"Trying to divide by 0 (ZERO)! Sum of amplitudes is nullptr! Skipping this SVDShaperDigit!");
266 for (
int k = 0; k < m_NumberOfAPVSamples; k ++) {
267 if (samples[k] > amplitude)
268 amplitude = samples[k];
285 for (
int k = 0; k < m_NumberOfAPVSamples; k ++) {
287 tmpResSq += TMath::Power(k * m_DeltaT - m_weightedMeanTime, 2);
290 return m_amplitudeError / Atot * TMath::Sqrt(tmpResSq);
297 stripnoise = m_NoiseCal.getNoise(ThisSensorID, ThisSide, ThisCellID);
314 if (!relation)
return;
316 lookup.resize(digits);
317 for (
const auto& element : relation) {
318 lookup[element.getFromIndex()] = &element;
323 std::map<unsigned int, float>& relation,
unsigned int index)
326 if (!lookup.empty() && lookup[index]) {
328 const unsigned int size = element.getSize();
330 for (
unsigned int i = 0; i < size; ++i) {
333 if (element.getWeight(i) < 0)
continue;
334 relation[element.getToIndex(i)] += element.getWeight(i);
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
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.
This module builds the SVDRecoDigits (calibrated and fitted strips) from the SVDShaperDigits.
float CalculateAmplitudeError(VxdID ThisSensorID, bool ThisSide, int ThisCellID)
Function to calculate the amplitude error as the noise of the strip.
virtual void initialize() override
Initialize the SVDCoGTimeEstimator.
virtual void event() override
This method is the core of the SVDCoGTimeEstimator.
std::vector< const RelationElement * > RelationLookup
Container for a RelationArray Lookup table.
float CalculateAmplitude(Belle2::SVDShaperDigit::APVFloatSamples samples)
Function to calculate the amplitude of the shaper, obtained as the largest of the 6 samples.
virtual void endRun() override
This method is called if the current run ends.
virtual ~SVDCoGTimeEstimatorModule()
default destructor
virtual void terminate() override
This method is called at the end of the event processing.
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.
float CalculateWeightedMeanPeakTimeError(Belle2::SVDShaperDigit::APVFloatSamples samples)
Function to calculate the peak time error.
float CalculateChi2()
Function to calculate chi2, that is not used here, so just set at 0.01.
virtual void beginRun() override
Called when entering a new run.
void createRelationLookup(const RelationArray &relation, RelationLookup &lookup, size_t digits)
Create lookup maps for relations FIXME: This has to be significantly simplified here,...
float CalculateWeightedMeanPeakTime(Belle2::SVDShaperDigit::APVFloatSamples samples)
Function to calculate the peak time, obtained as the weighted mean of the time of the samples,...
Class to store SVD mode information.
baseType getTriggerBin() const
Get the triggerBin id.
uint8_t baseType
The base integer type for SVDModeByte.
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.
baseType getSensorNumber() const
Get the sensor id.
baseType getLadderNumber() const
Get the ladder id.
baseType getLayerNumber() const
Get the layer id.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.