Belle II Software development
TimeDigitizer Class Reference

Time digitization of simulated hits in a single electronic channel. More...

#include <TimeDigitizer.h>

Classes

struct  Hit
 hit data other than time More...
 

Public Types

enum  EType {
  c_Hit = 0 ,
  c_ChargeShare = 1 ,
  c_CrossTalk = 2 ,
  c_CalPulse = 3
}
 hit type enumerators More...
 

Public Member Functions

 TimeDigitizer (int moduleID, int pixelID, double timeOffset, double calErrorsSq, int shift, double rmsNoise, const TOPSampleTimes &sampleTimes)
 Constructor.
 
void setSampleTimes (const TOPSampleTimes *sampleTimes)
 Sets sample times.
 
void setNoise (double rmsNoise)
 Sets noise level.
 
void addTimeOfHit (double t, double pulseHeight, EType type, const TOPSimHit *simHit=0)
 Add time of simulated hit.
 
int getModuleID () const
 Return bar ID.
 
int getPixelID () const
 Return pixel ID.
 
unsigned getUniqueID () const
 Return unique pixel ID.
 
unsigned getASICWindow () const
 Returns ASIC storage window number.
 
unsigned int getChannel () const
 Returns hardware channel number.
 
unsigned getScrodID () const
 Returns SCROD ID.
 
unsigned getCarrierNumber () const
 Returns carrier board number.
 
unsigned getASICNumber () const
 Returns ASIC number.
 
unsigned getASICChannel () const
 Returns ASIC channel number.
 
bool isValid () const
 Check if digitizer instance is valid (e.g.
 
void digitize (StoreArray< TOPRawDigit > &rawDigits, StoreArray< TOPDigit > &digits, int threshold=0, int thresholdCount=0, double timeJitter=0) const
 Do time digitization using simplified pile-up and double-hit-resolution model.
 
void digitize (StoreArray< TOPRawWaveform > &waveforms, StoreArray< TOPRawDigit > &rawDigits, StoreArray< TOPDigit > &digits, int threshold, int hysteresis=0, int thresholdCount=0) const
 Do full waveform time digitization.
 

Static Public Member Functions

static void setStorageDepth (unsigned storageDepth)
 Sets storage depth.
 
static void setReadoutWindows (unsigned numWin)
 Sets the number of readout windows.
 
static void setOffsetWindows (int offsetWin)
 Sets the number of windows before the first ASIC window.
 
static void setFirstWindow (unsigned window)
 Sets first ASIC window.
 
static void maskSamples (bool maskThem)
 Mask samples at the end of a window to emulate phase-2 data.
 
static void setTimeWalk (DBObjPtr< TOPCalTimeWalk > *timeWalk)
 Stores pointer to time walk DB object defined in TOPDigitizerModule.
 

Private Member Functions

double gauss (double x, double mean, double sigma) const
 Gauss function (pulse shape approximation)
 
std::vector< short > generateWaveform (int startSample, const std::vector< double > &baselines, const std::vector< double > &rmsNoises, const std::vector< double > &pedestals, int ADCRange) const
 Generate waveform.
 
double generateTimeWalk (double hitTime, double peakTime) const
 Generate time walk by taking into account pile-up of hits.
 

Private Attributes

int m_moduleID = 0
 module ID (1-based)
 
int m_pixelID = 0
 pixel (e.g.
 
double m_timeOffset = 0
 time offset [ns]
 
double m_calErrorsSq = 0
 calibration uncertainties squared
 
double m_rmsNoise = 0
 r.m.s of noise [ADC counts]
 
const TOPSampleTimesm_sampleTimes = 0
 sample times
 
int m_windowShift = 0
 additional wf window shift due to asic mis-alignment
 
unsigned m_channel = 0
 hardware channel number (0-based)
 
unsigned m_scrodID = 0
 SCROD ID.
 
unsigned m_carrier = 0
 carrier board number
 
unsigned m_asic = 0
 ASIC number.
 
unsigned m_chan = 0
 ASIC channel number.
 
bool m_valid = false
 true, if module/pixel is mapped to hardware
 
std::multimap< double, const Hitm_times
 hits sorted by time
 

Static Private Attributes

static unsigned s_storageDepth = 0
 ASIC analog storage depth.
 
static unsigned s_readoutWindows = 0
 number of readout windows
 
static int s_offsetWindows = 0
 number of windows before first wf window
 
static unsigned s_window = 0
 first window number
 
static bool s_maskSamples = false
 mask samples at window boundary (phase-2)
 
static DBObjPtr< TOPCalTimeWalk > * s_timeWalk = 0
 pointer to DB object
 

Detailed Description

Time digitization of simulated hits in a single electronic channel.

Definition at line 33 of file TimeDigitizer.h.

Member Enumeration Documentation

◆ EType

enum EType

hit type enumerators

Definition at line 40 of file TimeDigitizer.h.

40 {
41 c_Hit = 0,
42 c_ChargeShare = 1,
43 c_CrossTalk = 2,
44 c_CalPulse = 3
45 };

Constructor & Destructor Documentation

◆ TimeDigitizer()

TimeDigitizer ( int  moduleID,
int  pixelID,
double  timeOffset,
double  calErrorsSq,
int  shift,
double  rmsNoise,
const TOPSampleTimes sampleTimes 
)

Constructor.

Parameters
moduleIDTOP module ID
pixelIDpixel ID
timeOffsettime offset [ns]
calErrorsSqcalibration uncertainies squared
shiftshift of waveform window due to asic mis-alignment [num of windows]
rmsNoiser.m.s of noise [ADC counts]
sampleTimessample times

Definition at line 31 of file TimeDigitizer.cc.

33 :
34 m_moduleID(moduleID), m_pixelID(pixelID), m_timeOffset(timeOffset),
35 m_calErrorsSq(calErrorsSq), m_rmsNoise(rmsNoise), m_sampleTimes(&sampleTimes),
36 m_windowShift(shift)
37 {
38 const auto& channelMapper = TOPGeometryPar::Instance()->getChannelMapper();
39 m_channel = channelMapper.getChannel(pixelID);
40 if (!channelMapper.isChannelValid(m_channel)) {
41 B2ERROR("TimeDigitizer::TimeDigitizer: invalid channel");
42 return;
43 }
44
45 unsigned bs = 0;
46 channelMapper.splitChannelNumber(m_channel, bs, m_carrier, m_asic, m_chan);
47
48 const auto& frontEndMapper = TOPGeometryPar::Instance()->getFrontEndMapper();
49 const auto* map = frontEndMapper.getMap(m_moduleID, bs);
50 if (!map) {
51 B2ERROR("TimeDigitizer::TimeDigitizer: no valid frontend map found");
52 return;
53 }
54
55 m_scrodID = map->getScrodID();
56 m_valid = true;
57
58 }
const TOPFrontEndMap * getMap(int moduleID, int bs) const
Return map from TOP module side.
const ChannelMapper & getChannelMapper() const
Returns default channel mapper (mapping of channels to pixels)
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
const FrontEndMapper & getFrontEndMapper() const
Returns front-end mapper (mapping of SCROD's to positions within TOP modules)
unsigned m_asic
ASIC number.
int m_windowShift
additional wf window shift due to asic mis-alignment
unsigned m_scrodID
SCROD ID.
double m_rmsNoise
r.m.s of noise [ADC counts]
unsigned m_channel
hardware channel number (0-based)
double m_calErrorsSq
calibration uncertainties squared
const TOPSampleTimes * m_sampleTimes
sample times
int m_moduleID
module ID (1-based)
bool m_valid
true, if module/pixel is mapped to hardware
double m_timeOffset
time offset [ns]
unsigned m_carrier
carrier board number
unsigned m_chan
ASIC channel number.

Member Function Documentation

◆ addTimeOfHit()

void addTimeOfHit ( double  t,
double  pulseHeight,
EType  type,
const TOPSimHit simHit = 0 
)

Add time of simulated hit.

Parameters
ttime of simulated hit
pulseHeightsimulated pulse height
typehit type
simHitpointer to simulated hit

Definition at line 60 of file TimeDigitizer.cc.

62 {
63 Hit hit;
64 hit.pulseHeight = pulseHeight;
65 hit.type = type;
66 hit.simHit = simHit;
67 switch (type) {
68 case static_cast<int>(c_Hit):
70 break;
71 case static_cast<int>(c_ChargeShare):
73 break;
74 case static_cast<int>(c_CrossTalk):
75 hit.shape = 0;
76 B2ERROR("TOP::TimeDigitizer: waveform shape of cross-talk not yet available");
77 break;
78 case static_cast<int>(c_CalPulse):
80 break;
81 default:
82 hit.shape = 0;
83 }
84 m_times.insert(std::pair<double, const Hit>(t, hit));
85 }
const TOPSignalShape & getSignalShape() const
Returns single photon signal shape.
Definition: TOPGeometry.h:224
const TOPSignalShape & getCalPulseShape() const
Returns calibration pulse shape.
Definition: TOPGeometry.h:230
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
std::multimap< double, const Hit > m_times
hits sorted by time

◆ digitize() [1/2]

void digitize ( StoreArray< TOPRawDigit > &  rawDigits,
StoreArray< TOPDigit > &  digits,
int  threshold = 0,
int  thresholdCount = 0,
double  timeJitter = 0 
) const

Do time digitization using simplified pile-up and double-hit-resolution model.

As a result, the digitized hits are appended to TOPRawDigits, then they are converted to TOPDigits and the relations to TOPSimHits and MCParticles are set with proper weights.

Parameters
rawDigitsarray of TOPRawDigits
digitsarray of TOPDigits
thresholdpulse height threshold [ADC counts]
thresholdCountminimal number of samples above threshold
timeJittera r.m.s. of an additional time jitter due to electronics

Definition at line 93 of file TimeDigitizer.cc.

98 {
99
100 if (m_times.empty()) return;
101
102 // get parameters of the model
103 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
104 const auto& tdc = geo->getNominalTDC();
105 double hitResolveTime = tdc.getDoubleHitResolution();
106 double pileupTime = tdc.getPileupTime();
107
108 // split time pattern into multiple hits (according to double-hit resolution)
109 std::vector<Iterator> ranges;
110 ranges.push_back(m_times.begin());
111 double prevTime = m_times.begin()->first;
112 for (Iterator it = m_times.begin(); it != m_times.end(); ++it) {
113 if (it->first - prevTime > hitResolveTime) ranges.push_back(it);
114 prevTime = it->first;
115 }
116 ranges.push_back(m_times.end());
117
118 // loop over splitted regions
119 for (unsigned k = 0; k < ranges.size() - 1; k++) {
120
121 // temporary containers
122 std::vector<double> times;
123 std::vector<double> weights;
124 std::vector<const TOPSimHit*> simHits;
125
126 // take only hits within pileup time and discard others
127 prevTime = ranges[k]->first;
128 for (Iterator it = ranges[k]; it != ranges[k + 1]; ++it) {
129 if (it->first - prevTime > pileupTime) break;
130 times.push_back(it->first);
131 double pulseHeight = gRandom->Gaus(it->second.pulseHeight, m_rmsNoise);
132 weights.push_back(pulseHeight);
133 simHits.push_back(it->second.simHit);
134 prevTime = it->first;
135 }
136
137 // determine pulse height
138 double height = 0;
139 for (const auto& weight : weights) height += weight;
140
141 // set weights
142 for (auto& weight : weights) weight /= height;
143
144 // generate pulse width
145 double width = gRandom->Gaus(2.3, 0.4);
146 if (width < 0.5) width = 0.5;
147
148 // determine detection time
149 double time = 0;
150 for (unsigned j = 0; j < times.size(); j++) time += times[j] * weights[j];
151
152 // add additional time jitter
153 if (timeJitter > 0) time += gRandom->Gaus(0., timeJitter);
154
155 // emulate feature extraction data
156
157 double mean = time + width / 2;
158 double sigma = width / 2.35482;
159
160 int samplePeak = tdc.getSample(mean);
161 if (mean - tdc.getSampleTime(samplePeak) > tdc.getSampleWidth() / 2) samplePeak++;
162 short vPeak = height * gauss(tdc.getSampleTime(samplePeak), mean, sigma);
163 if (vPeak < threshold) continue;
164 if (vPeak > 3000) vPeak = 3000; // saturation - roughly (e.g. 4096 - pedestal)
165
166 double halfWid = sigma * sqrt(-2 * log(0.5 * vPeak / height));
167 int sampleRise = tdc.getSample(mean - halfWid);
168 if (!tdc.isSampleValid(sampleRise)) continue;
169 short vRise0 = height * gauss(tdc.getSampleTime(sampleRise), mean, sigma);
170 short vRise1 = height * gauss(tdc.getSampleTime(sampleRise + 1), mean, sigma);
171
172 int sampleFall = tdc.getSample(mean + halfWid);
173 if (!tdc.isSampleValid(sampleFall + 1)) continue;
174 short vFall0 = height * gauss(tdc.getSampleTime(sampleFall), mean, sigma);
175 short vFall1 = height * gauss(tdc.getSampleTime(sampleFall + 1), mean, sigma);
176
177 if (threshold > 0) {
178 double halfDt = sigma * sqrt(-2 * log(threshold / height));
179 int overThr = tdc.getSample(mean + halfDt) - tdc.getSample(mean - halfDt);
180 if (overThr < thresholdCount) continue;
181 }
182
183 // determine integral
184 int numSamples = (sampleFall - sampleRise) * 4; // according to topcaf
185 double sigmaIntegral = 0;
186 if (numSamples > 1) sigmaIntegral = m_rmsNoise * sqrt(numSamples - 1);
187 double integral = gRandom->Gaus(height * 7.0, sigmaIntegral);
188
189 // append new raw digit
190 auto* rawDigit = rawDigits.appendNew(m_scrodID, TOPRawDigit::c_MC);
191 rawDigit->setCarrierNumber(m_carrier);
192 rawDigit->setASICNumber(m_asic);
193 rawDigit->setASICChannel(m_chan);
194 rawDigit->setASICWindow(s_window);
195 rawDigit->setSampleRise(sampleRise);
196 rawDigit->setDeltaSamplePeak(samplePeak - sampleRise);
197 rawDigit->setDeltaSampleFall(sampleFall - sampleRise);
198 rawDigit->setValueRise0(vRise0);
199 rawDigit->setValueRise1(vRise1);
200 rawDigit->setValueFall0(vFall0);
201 rawDigit->setValueFall1(vFall1);
202 rawDigit->setValuePeak(vPeak);
203 rawDigit->setIntegral(integral);
204
205 double rawTime = rawDigit->getCFDLeadingTime();
206 double cfdTime = rawTime * tdc.getSampleWidth() - tdc.getOffset();
207 double cfdWidth = rawDigit->getFWHM() * tdc.getSampleWidth();
208 int sampleDivisions = 0x1 << tdc.getSubBits();
209 int tfine = int(rawTime * sampleDivisions) % sampleDivisions;
210 if (tfine < 0) tfine += sampleDivisions;
211 rawDigit->setTFine(tfine);
212
213 // append new digit
214
215 auto* digit = digits.appendNew(m_moduleID, m_pixelID, rawTime);
216 digit->setTime(cfdTime);
217 digit->setTimeError(timeJitter);
218 digit->setPulseHeight(rawDigit->getValuePeak());
219 digit->setIntegral(rawDigit->getIntegral());
220 digit->setPulseWidth(cfdWidth);
221 digit->setChannel(m_channel);
222 digit->setFirstWindow(rawDigit->getASICWindow());
223 digit->setStatus(TOPDigit::c_OffsetSubtracted);
225 digit->addStatus(TOPDigit::c_TimeBaseCalibrated);
226 }
227 digit->addRelationTo(rawDigit);
228
229 // set relations to simulated hits and MC particles
230
231 std::map<MCParticle*, double> relatedMCParticles;
232 for (unsigned j = 0; j < simHits.size(); j++) {
233 const auto* simHit = simHits[j];
234 const double& weight = weights[j];
235 if (simHit) {
236 digit->addRelationTo(simHit, weight);
237 RelationVector<MCParticle> particles = simHit->getRelationsFrom<MCParticle>();
238 for (unsigned i = 0; i < particles.size(); ++i) {
239 relatedMCParticles[particles[i]] += particles.weight(i) * weight;
240 }
241 }
242 }
243 for (const auto& x : relatedMCParticles) digit->addRelationTo(x.first, x.second);
244
245 } // end loop over splitted regions
246 }
const TOPNominalTDC & getNominalTDC() const
Returns nominal time-to-digit conversion parameters.
Definition: TOPGeometry.h:218
double getDoubleHitResolution() const
Returns double hit resolution time.
@ c_MC
from MC digitization
Definition: TOPRawDigit.h:43
bool isCalibrated() const
Returns calibration status.
static unsigned s_window
first window number
double gauss(double x, double mean, double sigma) const
Gauss function (pulse shape approximation)
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28

◆ digitize() [2/2]

void digitize ( StoreArray< TOPRawWaveform > &  waveforms,
StoreArray< TOPRawDigit > &  rawDigits,
StoreArray< TOPDigit > &  digits,
int  threshold,
int  hysteresis = 0,
int  thresholdCount = 0 
) const

Do full waveform time digitization.

As a result, the digitized hits are appended to TOPRawDigits, then they are converted to TOPDigits and the relations to TOPSimHits and MCParticles are set with proper weights.

Parameters
waveformsgenerated waveforms
rawDigitsarray of TOPRawDigits
digitsarray of TOPDigits
thresholdpulse height threshold [ADC counts]
hysteresispulse height threshold hysteresis [ADC counts]
thresholdCountminimal number of samples above threshold

Definition at line 251 of file TimeDigitizer.cc.

257 {
258
259 // get parameters of the model
260
261 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
262 const auto& tdc = geo->getNominalTDC();
263
264 // generate waveform
265
266 std::vector<unsigned short> windowNumbers;
267 int offsetWindows = s_offsetWindows + m_windowShift;
268 int winnum = s_window + offsetWindows;
269 if (winnum < 0) winnum += s_storageDepth;
270 windowNumbers.push_back(winnum % s_storageDepth);
271 for (unsigned i = 1; i < s_readoutWindows; i++) {
272 windowNumbers.push_back((windowNumbers.back() + 1) % s_storageDepth);
273 }
274 std::vector<double> baselines(windowNumbers.size(), 0);
275 std::vector<double> rmsNoises(windowNumbers.size(), m_rmsNoise);
276 double averagePedestal = tdc.getAveragePedestal();
277 std::vector<double> pedestals(windowNumbers.size(), averagePedestal);
278 int adcRange = tdc.getADCRange();
279
280 int startSample = -offsetWindows * TOPRawWaveform::c_WindowSize;
281 auto wfData = generateWaveform(startSample, baselines, rmsNoises, pedestals,
282 adcRange);
283
284 // store waveform
285
286 auto* waveform = waveforms.appendNew(m_moduleID, m_pixelID, m_channel, m_scrodID,
287 windowNumbers[0], 0, wfData);
288 waveform->setStorageWindows(windowNumbers);
289 waveform->setPedestalSubtractedFlag(true);
290
291 // do feature extraction
292
293 waveform->featureExtraction(threshold, hysteresis, thresholdCount);
294
295 // digits
296
297 for (const auto& feature : waveform->getFeatureExtractionData()) {
298 int sampleRise = feature.sampleRise;
299 if (sampleRise < 0) continue;
300 unsigned iwin = sampleRise / TOPRawWaveform::c_WindowSize;
301 if (iwin >= windowNumbers.size()) continue;
302 sampleRise -= iwin * TOPRawWaveform::c_WindowSize; // should fit raw data bits
303 if (s_maskSamples and (sampleRise % 64) > 55) continue;
304
305 unsigned DsamplePeak = feature.samplePeak - feature.sampleRise;
306 if ((DsamplePeak & 0x0F) != DsamplePeak) continue; // does not fit raw data bits
307
308 unsigned DsampleFall = feature.sampleFall - feature.sampleRise;
309 if ((DsampleFall & 0x0F) != DsampleFall) continue; // does not fit raw data bits
310
311 std::vector<unsigned short> winNumbers;
312 for (unsigned i = iwin; i < windowNumbers.size(); i++) {
313 winNumbers.push_back(windowNumbers[i]);
314 }
315
316 // append new raw digit and set it
317 auto* rawDigit = rawDigits.appendNew(m_scrodID, TOPRawDigit::c_ProductionDebug);
318 rawDigit->setCarrierNumber(m_carrier);
319 rawDigit->setASICNumber(m_asic);
320 rawDigit->setASICChannel(m_chan);
321 rawDigit->setASICWindow(windowNumbers[iwin]);
322 rawDigit->setStorageWindows(winNumbers);
323 rawDigit->setSampleRise(sampleRise);
324 rawDigit->setDeltaSamplePeak(DsamplePeak);
325 rawDigit->setDeltaSampleFall(DsampleFall);
326 rawDigit->setValueRise0(feature.vRise0);
327 rawDigit->setValueRise1(feature.vRise1);
328 rawDigit->setValueFall0(feature.vFall0);
329 rawDigit->setValueFall1(feature.vFall1);
330 rawDigit->setValuePeak(feature.vPeak);
331 rawDigit->setIntegral(feature.integral);
332 double rawTimeLeading = rawDigit->getCFDLeadingTime(); // time in [samples]
333 int sampleDivisions = 0x1 << tdc.getSubBits();
334 int tfine = int(rawTimeLeading * sampleDivisions) % sampleDivisions;
335 if (tfine < 0) tfine += sampleDivisions;
336 rawDigit->setTFine(tfine);
337 rawDigit->addRelationTo(waveform);
338
339 double rawTimeFalling = rawDigit->getCFDFallingTime(); // time in [samples]
340 double rawTimeErr = rawDigit->getCFDLeadingTimeError(m_rmsNoise); // in [samples]
341
342 // convert to [ns] using time base calibration
343 int nwin = iwin + offsetWindows;
344 rawTimeLeading += nwin * TOPRawDigit::c_WindowSize;
345 rawTimeFalling += nwin * TOPRawDigit::c_WindowSize;
346
347 double cfdTime = m_sampleTimes->getTime(s_window, rawTimeLeading) - m_timeOffset;
348 double width = m_sampleTimes->getDeltaTime(s_window,
349 rawTimeFalling,
350 rawTimeLeading);
351 int sample = static_cast<int>(rawTimeLeading);
352 if (rawTimeLeading < 0) sample--;
353 double timeError = rawTimeErr * m_sampleTimes->getTimeBin(s_window, sample);
354 double timeErrorSq = timeError * timeError + m_calErrorsSq;
355 int pulseHeight = rawDigit->getValuePeak();
356
357 if (s_timeWalk) {
358 cfdTime -= (*s_timeWalk)->getTimeWalk(pulseHeight);
359 timeErrorSq += (*s_timeWalk)->getSigmaSq(pulseHeight);
360 }
361
362 // append new digit and set it
363 auto* digit = digits.appendNew(m_moduleID, m_pixelID, rawTimeLeading);
364 digit->setTime(cfdTime);
365 digit->setTimeError(sqrt(timeErrorSq));
366 digit->setPulseHeight(pulseHeight);
367 digit->setIntegral(rawDigit->getIntegral());
368 digit->setPulseWidth(width);
369 digit->setChannel(m_channel);
370 digit->setFirstWindow(s_window);
372 digit->addStatus(TOPDigit::c_TimeBaseCalibrated);
373 }
374 digit->addRelationTo(rawDigit);
375
376 // check validity of feature extraction
377
378 if (!rawDigit->isFEValid() or rawDigit->isPedestalJump()) {
379 digit->setHitQuality(TOPDigit::c_Junk);
380 }
381
382 // set relations to simulated hits and MC particles, largest weight first
383
384 std::multimap<double, const Hit*, std::greater<double>> weights;
385 for (const auto& hit : m_times) {
386 double hitTime = hit.first;
387 double weight = 0;
388 const auto* pulseShape = hit.second.shape;
389 if (pulseShape) {
390 weight = fabs(pulseShape->getValue(cfdTime - hitTime));
391 }
392 if (weight > 0.01) {
393 weight *= hit.second.pulseHeight;
394 weights.insert(std::pair<double, const Hit*>(weight, &hit.second));
395 }
396 }
397 double sum = 0;
398 for (const auto& w : weights) sum += w.first;
399 if (sum == 0) continue; // noisy hit
400
401 std::map<MCParticle*, double> relatedMCParticles;
402 for (const auto& w : weights) {
403 auto weight = w.first / sum;
404 const auto* simHit = w.second->simHit;
405 if (simHit and weight > 0) {
406 digit->addRelationTo(simHit, weight);
407 RelationVector<MCParticle> particles = simHit->getRelationsFrom<MCParticle>();
408 for (unsigned i = 0; i < particles.size(); ++i) {
409 relatedMCParticles[particles[i]] += particles.weight(i) * weight;
410 }
411 } else if (w.second->type == c_CalPulse and weight > 0.90) {
412 digit->setHitQuality(TOPDigit::c_CalPulse);
413 }
414 }
415 for (const auto& x : relatedMCParticles) digit->addRelationTo(x.first, x.second);
416 }
417
418 }
@ c_ProductionDebug
from production debugging format
Definition: TOPRawDigit.h:46
@ c_WindowSize
number of samples per window
Definition: TOPRawDigit.h:54
@ c_WindowSize
number of samples per ASIC window
double getDeltaTime(int window, double sample2, double sample1) const
Returns time difference between sample2 and sample1.
double getTime(int window, double sample) const
Returns time w.r.t SSTin that corresponds to the window number.
std::vector< short > generateWaveform(int startSample, const std::vector< double > &baselines, const std::vector< double > &rmsNoises, const std::vector< double > &pedestals, int ADCRange) const
Generate waveform.
static unsigned s_storageDepth
ASIC analog storage depth.
static DBObjPtr< TOPCalTimeWalk > * s_timeWalk
pointer to DB object
static int s_offsetWindows
number of windows before first wf window
static bool s_maskSamples
mask samples at window boundary (phase-2)
static unsigned s_readoutWindows
number of readout windows
double getTimeBin(int window, int sampleNumber) const
Returns time bin of a given sample number and window (e.g.

◆ gauss()

double gauss ( double  x,
double  mean,
double  sigma 
) const
inlineprivate

Gauss function (pulse shape approximation)

Parameters
xargument
meanmean
sigmasigma
Returns
value

Definition at line 241 of file TimeDigitizer.h.

242 {
243 double xx = (x - mean) / sigma;
244 return exp(-0.5 * xx * xx);
245 }

◆ generateTimeWalk()

double generateTimeWalk ( double  hitTime,
double  peakTime 
) const
private

Generate time walk by taking into account pile-up of hits.

Parameters
hitTimetime of the hit
peakTimepeaking time of signal
Returns
time walk

Definition at line 516 of file TimeDigitizer.cc.

517 {
518 if (not s_timeWalk) return 0;
519
520 double pulseHeight = 0;
521 for (const auto& hit : m_times) {
522 double hTime = hit.first;
523 const auto* pulseShape = hit.second.shape;
524 if (not pulseShape) continue;
525 pulseHeight += hit.second.pulseHeight * pulseShape->getValue(hTime - hitTime + peakTime);
526 }
527
528 double t = (*s_timeWalk)->getTimeWalk(pulseHeight);
529 double sig = (*s_timeWalk)->getSigma(pulseHeight);
530
531 return gRandom->Gaus(t, sig);
532 }

◆ generateWaveform()

vector< short > generateWaveform ( int  startSample,
const std::vector< double > &  baselines,
const std::vector< double > &  rmsNoises,
const std::vector< double > &  pedestals,
int  ADCRange 
) const
private

Generate waveform.

The size (number of ASIC windows) is given by the size of first argument. The size of second argument must be the same as the first one.

Parameters
startSamplestarting sample w.r.t first window number
baselinespossible baseline shifts of ASIC windows
rmsNoisesnoise levels (r.m.s) per ASIC window
pedestalsaverage pedestals per ASIC window
ADCRangeADC range (2^NumBits)
Returns
generated waveform

Definition at line 421 of file TimeDigitizer.cc.

426 {
427
428 if (baselines.empty() or baselines.size() != rmsNoises.size() or
429 baselines.size() != pedestals.size())
430 B2FATAL("TOP::TimeDigitizer: inconsistent vector sizes");
431
432 // model parameters
433
434 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
435 const auto& tdc = geo->getNominalTDC();
436 const auto& signalShape = geo->getSignalShape();
437
438 double dt = tdc.getSampleWidth();
439 double fmax = 1 / (2 * dt); // Nyquist frequency
440 double tau1 = 1 / (2 * M_PI * signalShape.getPole1());
441 double tau2 = 1 / (2 * M_PI * signalShape.getPole2());
442 double bw1 = 1 / (4 * tau1); // bandwidth of first order filter
443 double bw2 = 1 / (4 * (tau1 + tau2)); // bandwidth of second order filter
444
445 // construct waveform vector containing white noise
446
447 vector<double> waveform;
448 for (auto rms : rmsNoises) {
449 double rms0 = rms * sqrt(fmax / bw2);
450 for (unsigned i = 0; i < TOPRawWaveform::c_WindowSize; i++) {
451 waveform.push_back(gRandom->Gaus(0, rms0));
452 }
453 }
454
455 // noise smoothing according to second order low pass filter
456
457 double a1 = exp(-dt / tau1);
458 double v0 = gRandom->Gaus(0, rmsNoises[0] * sqrt(bw1 / bw2));
459 double prevValue = v0;
460 for (auto& value : waveform) { // first order filter (pole1)
461 value = a1 * prevValue + (1 - a1) * value;
462 prevValue = value;
463 }
464 double a2 = exp(-dt / tau2);
465 prevValue = v0;
466 for (auto& value : waveform) { // first order filter again (pole2)
467 value = a2 * prevValue + (1 - a2) * value;
468 prevValue = value;
469 }
470
471 // add possible baseline shifts
472
473 int k = 0;
474 for (auto baseline : baselines) {
475 for (unsigned i = 0; i < TOPRawWaveform::c_WindowSize; i++) {
476 waveform[k] += baseline;
477 k++;
478 }
479 }
480
481 // add signal
482
483 for (const auto& hit : m_times) {
484 double hitTime = hit.first;
485 double pulseHeight = hit.second.pulseHeight;
486 const auto* pulseShape = hit.second.shape;
487 if (not pulseShape) continue;
488 double timeWalk = generateTimeWalk(hitTime, pulseShape->getPeakingTime());
489 int size = waveform.size();
490 for (int sample = 0; sample < size; sample++) {
491 double t = m_sampleTimes->getTime(s_window, sample - startSample) - m_timeOffset;
492 waveform[sample] += pulseHeight * pulseShape->getValue(t - timeWalk - hitTime);
493 }
494 }
495
496 // model saturation effects and convert to short
497 // (exact modelling would require pedestals for each sample)
498
499 vector<short> wf;
500 k = 0;
501 for (auto pedestal : pedestals) {
502 for (unsigned i = 0; i < TOPRawWaveform::c_WindowSize; i++) {
503 int adc = waveform[k] + pedestal;
504 if (adc < 0) adc = 0;
505 if (adc > adcRange) adc = adcRange;
506 adc -= pedestal;
507 wf.push_back(adc);
508 k++;
509 }
510 }
511
512 return wf;
513 }
double generateTimeWalk(double hitTime, double peakTime) const
Generate time walk by taking into account pile-up of hits.

◆ getASICChannel()

unsigned getASICChannel ( ) const
inline

Returns ASIC channel number.

Returns
ASIC channel number

Definition at line 186 of file TimeDigitizer.h.

186{return m_chan;}

◆ getASICNumber()

unsigned getASICNumber ( ) const
inline

Returns ASIC number.

Returns
ASIC number

Definition at line 180 of file TimeDigitizer.h.

180{return m_asic;}

◆ getASICWindow()

unsigned getASICWindow ( ) const
inline

Returns ASIC storage window number.

Returns
window number

Definition at line 156 of file TimeDigitizer.h.

156{return s_window;}

◆ getCarrierNumber()

unsigned getCarrierNumber ( ) const
inline

Returns carrier board number.

Returns
carrier board number

Definition at line 174 of file TimeDigitizer.h.

174{return m_carrier;}

◆ getChannel()

unsigned int getChannel ( ) const
inline

Returns hardware channel number.

Returns
hardware channel number

Definition at line 162 of file TimeDigitizer.h.

162{ return m_channel; }

◆ getModuleID()

int getModuleID ( ) const
inline

Return bar ID.

Returns
bar ID

Definition at line 138 of file TimeDigitizer.h.

138{ return m_moduleID; }

◆ getPixelID()

int getPixelID ( ) const
inline

Return pixel ID.

Returns
pixel ID (e.g. software channel)

Definition at line 144 of file TimeDigitizer.h.

144{ return m_pixelID; }

◆ getScrodID()

unsigned getScrodID ( ) const
inline

Returns SCROD ID.

Returns
SCROD ID

Definition at line 168 of file TimeDigitizer.h.

168{return m_scrodID;}

◆ getUniqueID()

unsigned getUniqueID ( ) const
inline

Return unique pixel ID.

Returns
unique pixel ID

Definition at line 150 of file TimeDigitizer.h.

150{return m_pixelID + (m_moduleID << 16);}

◆ isValid()

bool isValid ( ) const
inline

Check if digitizer instance is valid (e.g.

module/pixel is mapped to hardware)

Returns
true if valid

Definition at line 192 of file TimeDigitizer.h.

192{return m_valid;}

◆ maskSamples()

static void maskSamples ( bool  maskThem)
inlinestatic

Mask samples at the end of a window to emulate phase-2 data.

Parameters
maskThemmask (true) or not mask (false)

Definition at line 98 of file TimeDigitizer.h.

98{s_maskSamples = maskThem;}

◆ setFirstWindow()

static void setFirstWindow ( unsigned  window)
inlinestatic

Sets first ASIC window.

Parameters
windowstorage window number

Definition at line 92 of file TimeDigitizer.h.

92{s_window = window;}

◆ setNoise()

void setNoise ( double  rmsNoise)
inline

Sets noise level.

Parameters
rmsNoiser.m.s. of noise [ADC counts]

Definition at line 122 of file TimeDigitizer.h.

122{m_rmsNoise = rmsNoise;}

◆ setOffsetWindows()

static void setOffsetWindows ( int  offsetWin)
inlinestatic

Sets the number of windows before the first ASIC window.

Parameters
offsetWinnumber of offset windows

Definition at line 86 of file TimeDigitizer.h.

86{s_offsetWindows = offsetWin;}

◆ setReadoutWindows()

static void setReadoutWindows ( unsigned  numWin)
inlinestatic

Sets the number of readout windows.

Parameters
numWinnumber of readout windows

Definition at line 80 of file TimeDigitizer.h.

80{s_readoutWindows = numWin;}

◆ setSampleTimes()

void setSampleTimes ( const TOPSampleTimes sampleTimes)
inline

Sets sample times.

Parameters
sampleTimessample times

Definition at line 109 of file TimeDigitizer.h.

110 {
111 if (sampleTimes) {
112 m_sampleTimes = sampleTimes;
113 } else {
114 B2ERROR("TOP::TimeDigitizer::setSampleTimes: argument is NULL pointer");
115 }
116 }

◆ setStorageDepth()

static void setStorageDepth ( unsigned  storageDepth)
inlinestatic

Sets storage depth.

Parameters
storageDepthanalog storage depth

Definition at line 74 of file TimeDigitizer.h.

74{s_storageDepth = storageDepth;}

◆ setTimeWalk()

static void setTimeWalk ( DBObjPtr< TOPCalTimeWalk > *  timeWalk)
inlinestatic

Stores pointer to time walk DB object defined in TOPDigitizerModule.

Definition at line 103 of file TimeDigitizer.h.

103{s_timeWalk = timeWalk;}

Member Data Documentation

◆ m_asic

unsigned m_asic = 0
private

ASIC number.

Definition at line 290 of file TimeDigitizer.h.

◆ m_calErrorsSq

double m_calErrorsSq = 0
private

calibration uncertainties squared

Definition at line 282 of file TimeDigitizer.h.

◆ m_carrier

unsigned m_carrier = 0
private

carrier board number

Definition at line 289 of file TimeDigitizer.h.

◆ m_chan

unsigned m_chan = 0
private

ASIC channel number.

Definition at line 291 of file TimeDigitizer.h.

◆ m_channel

unsigned m_channel = 0
private

hardware channel number (0-based)

Definition at line 287 of file TimeDigitizer.h.

◆ m_moduleID

int m_moduleID = 0
private

module ID (1-based)

Definition at line 279 of file TimeDigitizer.h.

◆ m_pixelID

int m_pixelID = 0
private

pixel (e.g.

software channel) ID (1-based)

Definition at line 280 of file TimeDigitizer.h.

◆ m_rmsNoise

double m_rmsNoise = 0
private

r.m.s of noise [ADC counts]

Definition at line 283 of file TimeDigitizer.h.

◆ m_sampleTimes

const TOPSampleTimes* m_sampleTimes = 0
private

sample times

Definition at line 284 of file TimeDigitizer.h.

◆ m_scrodID

unsigned m_scrodID = 0
private

SCROD ID.

Definition at line 288 of file TimeDigitizer.h.

◆ m_timeOffset

double m_timeOffset = 0
private

time offset [ns]

Definition at line 281 of file TimeDigitizer.h.

◆ m_times

std::multimap<double, const Hit> m_times
private

hits sorted by time

Definition at line 294 of file TimeDigitizer.h.

◆ m_valid

bool m_valid = false
private

true, if module/pixel is mapped to hardware

Definition at line 292 of file TimeDigitizer.h.

◆ m_windowShift

int m_windowShift = 0
private

additional wf window shift due to asic mis-alignment

Definition at line 285 of file TimeDigitizer.h.

◆ s_maskSamples

bool s_maskSamples = false
staticprivate

mask samples at window boundary (phase-2)

Definition at line 276 of file TimeDigitizer.h.

◆ s_offsetWindows

int s_offsetWindows = 0
staticprivate

number of windows before first wf window

Definition at line 274 of file TimeDigitizer.h.

◆ s_readoutWindows

unsigned s_readoutWindows = 0
staticprivate

number of readout windows

Definition at line 273 of file TimeDigitizer.h.

◆ s_storageDepth

unsigned s_storageDepth = 0
staticprivate

ASIC analog storage depth.

Definition at line 272 of file TimeDigitizer.h.

◆ s_timeWalk

DBObjPtr< TOPCalTimeWalk > * s_timeWalk = 0
staticprivate

pointer to DB object

Definition at line 277 of file TimeDigitizer.h.

◆ s_window

unsigned s_window = 0
staticprivate

first window number

Definition at line 275 of file TimeDigitizer.h.


The documentation for this class was generated from the following files: