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.
257 {
258
259
260
263
264
265
266 std::vector<unsigned short> windowNumbers;
268 int winnum =
s_window + offsetWindows;
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
281 auto wfData =
generateWaveform(startSample, baselines, rmsNoises, pedestals,
282 adcRange);
283
284
285
287 windowNumbers[0], 0, wfData);
288 waveform->setStorageWindows(windowNumbers);
289 waveform->setPedestalSubtractedFlag(true);
290
291
292
293 waveform->featureExtraction(threshold, hysteresis, thresholdCount);
294
295
296
297 for (const auto& feature : waveform->getFeatureExtractionData()) {
298 int sampleRise = feature.sampleRise;
299 if (sampleRise < 0) continue;
301 if (iwin >= windowNumbers.size()) continue;
304
305 unsigned DsamplePeak = feature.samplePeak - feature.sampleRise;
306 if ((DsamplePeak & 0x0F) != DsamplePeak) continue;
307
308 unsigned DsampleFall = feature.sampleFall - feature.sampleRise;
309 if ((DsampleFall & 0x0F) != DsampleFall) continue;
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
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();
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();
340 double rawTimeErr = rawDigit->getCFDLeadingTimeError(
m_rmsNoise);
341
342
343 int nwin = iwin + offsetWindows;
346
349 rawTimeFalling,
350 rawTimeLeading);
351 int sample = static_cast<int>(rawTimeLeading);
352 if (rawTimeLeading < 0) sample--;
355 int pulseHeight = rawDigit->getValuePeak();
356
358 cfdTime -= (*s_timeWalk)->getTimeWalk(pulseHeight);
359 timeErrorSq += (*s_timeWalk)->getSigmaSq(pulseHeight);
360 }
361
362
364 digit->setTime(cfdTime);
365 digit->setTimeError(
sqrt(timeErrorSq));
366 digit->setPulseHeight(pulseHeight);
367 digit->setIntegral(rawDigit->getIntegral());
368 digit->setPulseWidth(width);
372 digit->addStatus(TOPDigit::c_TimeBaseCalibrated);
373 }
374 digit->addRelationTo(rawDigit);
375
376
377
378 if (!rawDigit->isFEValid() or rawDigit->isPedestalJump()) {
379 digit->setHitQuality(TOPDigit::c_Junk);
380 }
381
382
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;
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
@ c_WindowSize
number of samples per 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.