9 #include <ecl/modules/eclDigitizer/ECLDigitizerModule.h>
17 #include <framework/logging/Logger.h>
18 #include <framework/utilities/FileSystem.h>
19 #include <framework/gearbox/Unit.h>
22 #include <ecl/digitization/algorithms.h>
23 #include <ecl/digitization/shaperdsp.h>
24 #include <ecl/digitization/ECLCompress.h>
25 #include <ecl/geometry/ECLGeometryPar.h>
26 #include <ecl/dbobjects/ECLCrystalCalib.h>
27 #include <ecl/dbobjects/ECLWaveformData.h>
28 #include <ecl/dataobjects/ECLHit.h>
29 #include <ecl/dataobjects/ECLSimHit.h>
30 #include <ecl/dataobjects/ECLDigit.h>
31 #include <ecl/dataobjects/ECLDsp.h>
32 #include <ecl/dataobjects/ECLDspWithExtraMCInfo.h>
33 #include <ecl/dataobjects/ECLTrig.h>
34 #include <ecl/dataobjects/ECLWaveforms.h>
35 #include <ecl/utility/ECLDspUtilities.h>
53 setDescription(
"Creates ECLDigiHits from ECLHits.");
54 setPropertyFlags(c_ParallelProcessingCertified);
55 addParam(
"TriggerTime", m_trigTime,
56 "Flag to use crate trigger times from beam background overlay if there are any (default: false)",
false);
57 addParam(
"Background", m_background,
"Flag to use the Digitizer configuration with backgrounds (default: false)",
false);
58 addParam(
"Calibration", m_calibration,
"Flag to use the Digitizer for Waveform fit Covariance Matrix calibration (default: false)",
60 addParam(
"DiodeDeposition", m_inter,
61 "Flag to take into account energy deposition in photodiodes; Default diode is sensitive detector (default: true)",
true);
62 addParam(
"WaveformMaker", m_waveformMaker,
"Flag to produce background waveform digits (default: false)",
false);
63 addParam(
"CompressionAlgorithm", m_compAlgo,
"Waveform compression algorithm (default: 0u)", 0u);
64 addParam(
"eclWaveformsName", m_eclWaveformsName,
"Name of the output/input collection (digitized waveforms)",
string(
""));
65 addParam(
"HadronPulseShapes", m_HadronPulseShape,
"Flag to include hadron component in pulse shape construction (default: true)",
67 addParam(
"ADCThreshold", m_ADCThreshold,
"ADC threshold for waveform fits (default: 25)", 25);
68 addParam(
"WaveformThresholdOverride", m_WaveformThresholdOverride,
69 "If gt 0 value is applied to all crystals for waveform saving threshold. If lt 0 dbobject is used. (GeV)", -1.0);
70 addParam(
"StoreDspWithExtraMCInfo", m_storeDspWithExtraMCInfo,
71 "Flag to store Dsp with extra MC information in addition to normal Dsp (default: false)",
false);
72 addParam(
"DspWithExtraMCInfoThreshold", m_DspWithExtraMCInfoThreshold,
73 "Threshold above with to store Dsp with extra MC information [GeV]",
75 addParam(
"DspDataTest", m_dspDataTest,
76 "Use DSP coefficients from the database for the processing. This "
77 "will significantly reduce performance so this option is to be "
78 "used for testing only.",
false);
82 ECLDigitizerModule::~ECLDigitizerModule()
86 void ECLDigitizerModule::initialize()
88 m_eclDsps.registerInDataStore();
89 if (m_storeDspWithExtraMCInfo) m_eclDspsWithExtraMCInfo.registerInDataStore();
90 m_eclDigits.registerInDataStore();
91 m_eclTrigs.registerInDataStore();
93 if (m_HadronPulseShape) {
95 "Hadron pulse shapes for ECL simulations are enabled. Pulse shape simulations use techniques validated with test beam data documented in: S. Longo and J. M. Roney 2018 JINST 13 P03018");
97 B2DEBUG(20,
"Hadron pulse shapes for ECL simulations are disabled.");
101 B2DEBUG(20,
"Diode-crossing pulse shapes for ECL simulations are enabled.");
103 B2DEBUG(20,
"Diode-crossing pulse shapes for ECL simulations are disabled.");
106 m_eclDiodeHits.registerInDataStore(
"ECLDiodeHits");
108 m_eclDsps.registerRelationTo(m_eclDigits);
109 if (m_storeDspWithExtraMCInfo)
110 m_eclDspsWithExtraMCInfo.registerRelationTo(m_eclDigits);
111 m_eclDigits.registerRelationTo(m_eclHits);
113 m_eclWaveforms.registerInDataStore(m_eclWaveformsName);
117 m_adc.resize(EclConfiguration::m_nch);
119 EclConfiguration::get().setBackground(m_background);
122 void ECLDigitizerModule::beginRun()
126 Ael(
"ECLCrystalElectronics"),
127 Aen(
"ECLCrystalEnergy"),
128 Tel(
"ECLCrystalElectronicsTime"),
129 Ten(
"ECLCrystalTimeOffset"),
130 Tct(
"ECLCrateTimeOffset"),
131 Tmc(
"ECLMCTimeOffset"),
132 Awave(
"ECL_FPGA_StoreWaveform");
133 double ns_per_tick = 1.0 / (4.0 * ec.
m_rf) * 1e3;
136 m_calib.assign(8736, def);
138 if (Ael)
for (
int i = 0; i < 8736; i++) m_calib[i].ascale /= Ael->getCalibVector()[i];
139 if (Aen)
for (
int i = 0; i < 8736; i++) m_calib[i].ascale /= Aen->getCalibVector()[i] * 20000.0;
141 if (Tel)
for (
int i = 0; i < 8736; i++) m_calib[i].tshift += Tel->getCalibVector()[i] * ns_per_tick;
142 if (Ten)
for (
int i = 0; i < 8736; i++) m_calib[i].tshift += Ten->getCalibVector()[i] * ns_per_tick;
143 if (Tct)
for (
int i = 0; i < 8736; i++) m_calib[i].tshift += Tct->getCalibVector()[i] * ns_per_tick;
144 if (Tmc)
for (
int i = 0; i < 8736; i++) m_calib[i].tshift += Tmc->getCalibVector()[i] * ns_per_tick;
146 m_Awave.assign(8736, -1);
147 if (m_WaveformThresholdOverride < 0) {
148 if (Awave)
for (
int i = 0; i < 8736; i++) m_Awave[i] = Awave->getCalibVector()[i];
151 for (
int i = 0; i < 8736; i++) m_Awave[i] = m_WaveformThresholdOverride * m_calib[i].ascale;
154 if (m_HadronPulseShape) callbackHadronSignalShapes();
158 if (!m_eclMapper.initFromDB()) {
159 B2FATAL(
"ECL Packer: Can't initialize eclChannelMapper!");
164 void ECLDigitizerModule::shapeFitterWrapper(
const int j,
const int* FitA,
const int ttrig,
165 int& m_lar,
int& m_ltr,
int& m_lq,
int& m_chi)
const
172 if (!m_dspDataTest) {
173 short int*
id = (
short int*)m_idn[t.idn].id;
175 int A0 = (
int) * (
id + 0) - 128;
176 int Askip = (int) * (
id + 1) - 128;
178 int Ahard = (int) * (
id + 2);
179 int k_a = (int) * ((
unsigned char*)
id + 26);
180 int k_b = (int) * ((
unsigned char*)
id + 27);
181 int k_c = (int) * ((
unsigned char*)
id + 28);
182 int k_16 = (int) * ((
unsigned char*)
id + 29);
183 int k1_chi = (int) * ((
unsigned char*)
id + 24);
184 int k2_chi = (int) * ((
unsigned char*)
id + 25);
186 int chi_thres = (int) * (
id + 15);
188 int trg_time = ttrig;
190 result = lftda_((
int*)r.f, (
int*)r.f1, (
int*)r.fg41, (
int*)r.fg43,
191 (
int*)r.fg31, (
int*)r.fg32, (
int*)r.fg33, (
int*)FitA,
192 trg_time, A0, Ahard, Askip, k_a, k_b, k_c, k_16, k1_chi,
195 std::vector<int> adc(31);
196 for (
int i = 0; i < 31; i++) adc[i] = FitA[i];
201 int ttrig_packed = ttrig / 6 * 8 + ttrig % 6;
202 result = ECLDspUtilities::shapeFitter(j + 1, adc, ttrig_packed);
207 m_lq = result.quality;
211 int discarded_bits = 0;
212 if ((m_chi & 0x7800000) != 0) {
214 }
else if ((m_chi & 0x0600000) != 0) {
216 }
else if ((m_chi & 0x0180000) != 0) {
218 }
else if ((m_chi & 0x0060000) != 0) {
220 }
else if ((m_chi & 0x0018000) != 0) {
222 }
else if ((m_chi & 0x0006000) != 0) {
224 }
else if ((m_chi & 0x0001800) != 0) {
226 }
else if ((m_chi & 0x0000600) != 0) {
229 if (discarded_bits > 0) {
230 m_chi >>= discarded_bits;
231 m_chi <<= discarded_bits;
235 void ECLDigitizerModule::shapeSignals()
241 const double tscale = 2 * trgtick, toff = ec.
s_clock / (2 * ec.
m_rf);
244 memset(m_adc.data(), 0, m_adc.size()*
sizeof(
adccounts_t));
246 const double E2GeV = 1 / Unit::GeV;
247 const double T2us = 1 / Unit::us;
250 for (
const auto& hit : m_eclSimHits) {
251 int cellId = hit.getCellId();
253 int id = m_eclMapper.getCrateID(cellId) - 1;
254 double timeOffset = tscale * m_ttime[id] - toff;
255 double hitE = hit.getEnergyDep() * m_calib[j].ascale * E2GeV;
256 double hitTimeAve = (hit.getFlightTime() + m_calib[j].tshift + eclp->time2sensor(j, hit.getPosition())) * T2us;
258 m_adc[j].energyConversion = m_calib[j].ascale * E2GeV * 20000;
259 m_adc[j].flighttime += hit.getFlightTime() * hit.getEnergyDep();
260 m_adc[j].timeshift += m_calib[j].tshift * hit.getEnergyDep();
261 m_adc[j].timetosensor += eclp->time2sensor(j, hit.getPosition()) * hit.getEnergyDep();
262 m_adc[j].totalHadronDep += hit.getHadronEnergyDep();
263 m_adc[j].totalDep += hit.getEnergyDep();
265 if (m_HadronPulseShape ==
true) {
266 double hitHadronE = hit.getHadronEnergyDep() * m_calib[j].ascale * E2GeV;
267 m_adc[j].AddHit(hitE - hitHadronE, hitTimeAve + timeOffset, m_ss_HadronShapeSimulations[0]);
268 m_adc[j].AddHit(hitHadronE, hitTimeAve + timeOffset, m_ss_HadronShapeSimulations[1]);
270 m_adc[j].AddHit(hitE, hitTimeAve + timeOffset, m_ss[m_tbl[j].iss]);
275 for (
const auto& hit : m_eclHits) {
276 if (hit.getBackgroundTag() == BackgroundMetaData::bg_none)
continue;
277 int cellId = hit.getCellId();
279 int id = m_eclMapper.getCrateID(cellId) - 1;
280 double timeOffset = tscale * m_ttime[id] - toff;
281 double hitE = hit.getEnergyDep() * m_calib[j].ascale * E2GeV;
282 double hitTimeAve = (hit.getTimeAve() + m_calib[j].tshift) * T2us;
283 m_adc[j].AddHit(hitE, hitTimeAve + timeOffset, m_ss[m_tbl[j].iss]);
291 const double diodeEdep2crystalEdep = E2GeV * (1 / (5000 * 3.6e-6));
292 for (
const auto& hit : m_eclDiodeHits) {
293 int cellId = hit.getCellId();
295 int id = m_eclMapper.getCrateID(cellId) - 1;
296 double timeOffset = tscale * m_ttime[id] - toff;
297 double hitE = hit.getEnergyDep() * m_calib[j].ascale * diodeEdep2crystalEdep;
298 double hitTimeAve = (hit.getTimeAve() + m_calib[j].tshift) * T2us;
303 if (m_HadronPulseShape) {
304 a.AddHit(hitE, hitTimeAve + timeOffset, m_ss_HadronShapeSimulations[2]);
306 a.AddHit(hitE, hitTimeAve + timeOffset, m_ss[1]);
315 double hitE = 0.1, hitTimeAve = 0.0;
316 for (
int j = 0; j < ec.
m_nch; j++) {
318 int id = m_eclMapper.getCrateID(cellId) - 1;
319 double timeOffset = tscale * m_ttime[id] - toff;
320 m_adc[j].AddHit(hitE, hitTimeAve + timeOffset, m_ss[m_tbl[j].iss]);
325 void ECLDigitizerModule::makeElectronicNoiseAndPedestal(
int J,
int* FitA)
330 for (
int i = 0; i < ec.
m_nsmp; i++) z[i] = gRandom->Gaus(0, 1);
331 m_noise[m_tbl[J].inoise].generateCorrelatedNoise(z, AdcNoise);
332 for (
int i = 0; i < ec.
m_nsmp; i++) FitA[i] = 20 * AdcNoise[i] + 3000;
335 void ECLDigitizerModule::makeWaveforms()
339 out.putNBits(m_compAlgo & 0xff, 8);
342 B2FATAL(
"Unknown compression algorithm: " << m_compAlgo);
346 for (
int j = 0; j < ec.
m_nch; j++) {
348 makeElectronicNoiseAndPedestal(j, FitA);
349 for (
int i = 0; i < ec.
m_nsmp; i++) {
350 int A = 20000 * a.c[i] + FitA[i];
351 FitA[i] = max(0, min(A, (1 << 18) - 1));
358 m_eclWaveforms.assign(wf);
360 std::swap(out.getStore(), wf->
getStore());
361 if (comp)
delete comp;
364 void ECLDigitizerModule::event()
369 struct ch_t {
int cell, id;};
371 for (
const auto& hit : m_eclHits) {
372 int j = hit.getCellId() - 1;
373 if (hit.getBackgroundTag() == BackgroundMetaData::bg_none) hitmap.push_back({j, hit.getArrayIndex()});
377 bool isBGOverlay = m_eclWaveforms.isValid(), isTrigTime =
false;
383 std::swap(out.getStore(), m_eclWaveforms->getStore());
385 unsigned int compAlgo = out.getNBits(8);
386 comp = selectAlgo(compAlgo & 0x7f);
388 B2FATAL(
"Unknown compression algorithm: " << compAlgo);
389 isTrigTime = compAlgo >> 7;
391 for (
int i = 0; i < ECL::ECL_CRATES; i++) {
392 unsigned char t = out.getNBits(7);
398 if (!m_trigTime || !isTrigTime) {
399 int DeltaT = gRandom->Uniform(0,
double(ec.
m_ntrg) * 0.5);
400 for (
int id = 0;
id < ECL::ECL_CRATES;
id++) m_ttime[
id] = DeltaT;
403 int triggerTag0 = m_EventMetaData->getEvent();
404 for (
int id = 0;
id < ECL::ECL_CRATES;
id++) {
405 auto eclTrig = m_eclTrigs.appendNew();
406 int triggerPhase0 = 2 * (m_ttime[id] + m_ttime[id] / 3);
407 eclTrig->setTrigId(
id);
408 eclTrig->setTimeTrig(triggerPhase0);
409 eclTrig->setTrigTag(triggerTag0);
416 if (m_waveformMaker) { makeWaveforms();
return; }
421 for (
int j = 0; j < ec.
m_nch; j++) {
425 if (m_adc[j].totalDep > 0) {
426 m_adc[j].flighttime /= m_adc[j].totalDep;
427 m_adc[j].timeshift /= m_adc[j].totalDep;
428 m_adc[j].timetosensor /= m_adc[j].totalDep;
437 if (a.total < 0.0001)
continue;
438 makeElectronicNoiseAndPedestal(j, FitA);
441 for (
int i = 0; i < ec.
m_nsmp; i++) {
442 int A = 20000 * a.c[i] + FitA[i];
443 FitA[i] = max(0, min(A, (1 << 18) - 1));
451 int id = m_eclMapper.getCrateID(j + 1) - 1;
452 int ttrig = 2 * m_ttime[id];
454 shapeFitterWrapper(j, FitA, ttrig, energyFit, tFit, qualityFit, chi);
456 if (energyFit > m_ADCThreshold) {
460 if (energyFit > m_Awave[CellId - 1]) {
462 const auto eclDsp = m_eclDsps.appendNew();
463 eclDsp->setCellId(CellId);
464 eclDsp->setDspA(FitA);
468 if (m_storeDspWithExtraMCInfo and a.totalDep >= m_DspWithExtraMCInfoThreshold) {
469 const auto eclDspWithExtraMCInfo = m_eclDspsWithExtraMCInfo.appendNew();
470 eclDspWithExtraMCInfo->setCellId(CellId);
471 eclDspWithExtraMCInfo->setDspA(FitA);
472 eclDspWithExtraMCInfo->setEnergyDep(a.totalDep);
473 eclDspWithExtraMCInfo->setHadronEnergyDep(a.totalHadronDep);
474 eclDspWithExtraMCInfo->setFlightTime(a.flighttime);
475 eclDspWithExtraMCInfo->setTimeShift(a.timeshift);
476 eclDspWithExtraMCInfo->setTimeToSensor(a.timetosensor);
477 eclDspWithExtraMCInfo->setEnergyConversion(a.energyConversion * 20000);
480 const auto eclDigit = m_eclDigits.appendNew();
481 eclDigit->setCellId(CellId);
482 eclDigit->setAmp(energyFit);
483 eclDigit->setTimeFit(tFit);
484 eclDigit->setQuality(qualityFit);
486 eclDigit->setChi(chi);
487 else eclDigit->setChi(0);
488 for (
const auto& hit : hitmap)
489 if (hit.cell == j) eclDigit->addRelationTo(m_eclHits[hit.id]);
492 for (
auto& DspWithExtraMCInfo : m_eclDspsWithExtraMCInfo) {
493 if (eclDigit->getCellId() == DspWithExtraMCInfo.getCellId()) DspWithExtraMCInfo.addRelationTo(eclDigit);
497 if (comp)
delete comp;
500 void ECLDigitizerModule::endRun()
504 void ECLDigitizerModule::terminate()
508 void ECLDigitizerModule::callbackHadronSignalShapes()
511 if (m_waveformParametersMC.hasChanged()) {
513 m_ss_HadronShapeSimulations.resize(3);
516 float photonParsPSD[10];
517 float hadronParsPSD[10];
518 float diodeParsPSD[10];
519 for (
int i = 0; i < 10; i++) {
520 photonParsPSD[i] = m_waveformParametersMC->getPhotonParameters()[i + 1];
521 hadronParsPSD[i] = m_waveformParametersMC->getHadronParameters()[i + 1];
522 diodeParsPSD[i] = m_waveformParametersMC->getDiodeParameters()[i + 1];
526 m_ss_HadronShapeSimulations[0].InitSample(photonParsPSD, m_waveformParametersMC->getPhotonParameters()[0]);
527 m_ss_HadronShapeSimulations[1].InitSample(hadronParsPSD, m_waveformParametersMC->getHadronParameters()[0]);
528 m_ss_HadronShapeSimulations[2].InitSample(diodeParsPSD, m_waveformParametersMC->getDiodeParameters()[0]);
534 void ECLDigitizerModule::readDSPDB()
540 dataFileName = FileSystem::findFile(
"/data/ecl/ECL-WF-BG.root");
541 B2DEBUG(150,
"ECLDigitizer: Reading configuration data with background from: " << dataFileName);
543 dataFileName = FileSystem::findFile(
"/data/ecl/ECL-WF.root");
544 B2DEBUG(150,
"ECLDigitizer: Reading configuration data without background from: " << dataFileName);
546 assert(! dataFileName.empty());
548 TFile rootfile(dataFileName.c_str());
549 TTree* tree = (TTree*) rootfile.Get(
"EclWF");
550 TTree* tree2 = (TTree*) rootfile.Get(
"EclAlgo");
551 TTree* tree3 = (TTree*) rootfile.Get(
"EclNoise");
553 if (tree == 0 || tree2 == 0 || tree3 == 0) B2FATAL(
"Data not found");
555 m_tbl.resize(ec.
m_nch);
557 const int maxncellid = 512;
559 vector<int> cellId(maxncellid);
561 tree->SetBranchAddress(
"ncellId", &ncellId);
562 tree->SetBranchAddress(
"cellId", cellId.data());
564 vector<int> eclWaveformDataTable(ec.
m_nch);
565 for (Long64_t j = 0, jmax = tree->GetEntries(); j < jmax; j++) {
567 assert(ncellId <= maxncellid);
568 for (
int i = 0; i < ncellId; ++i)
569 eclWaveformDataTable[cellId[i] - 1] = j;
571 B2DEBUG(150,
"ECLDigitizer: " << tree->GetEntries() <<
" sets of wave form covariance matricies will be used.");
574 tree2->SetBranchAddress(
"Algopars", &algo);
575 tree2->SetBranchAddress(
"ncellId", &ncellId);
576 tree2->SetBranchAddress(
"cellId", cellId.data());
577 Long64_t jmax2 = tree2->GetEntries();
578 vector<ECLWFAlgoParams> eclWFAlgoParams;
579 eclWFAlgoParams.reserve(jmax2);
580 for (Long64_t j = 0; j < jmax2; j++) {
582 assert(ncellId <= maxncellid);
583 eclWFAlgoParams.push_back(*algo);
584 for (
int i = 0; i < ncellId; ++i)
585 m_tbl[cellId[i] - 1].idn = j;
587 if (algo)
delete algo;
588 B2DEBUG(150,
"ECLDigitizer: " << eclWFAlgoParams.size() <<
" parameter sets of fitting algorithm were read.");
591 tree3->SetBranchAddress(
"NoiseM", &noise);
592 tree3->SetBranchAddress(
"ncellId", &ncellId);
593 tree3->SetBranchAddress(
"cellId", cellId.data());
595 Long64_t jmax3 = tree3->GetEntries();
596 m_noise.reserve(jmax3);
597 for (Long64_t j = 0; j < jmax3; j++) {
599 assert(ncellId <= maxncellid);
600 m_noise.push_back(*noise);
602 for (
int i = 0; i < ec.
m_nch; i++)
606 for (
int i = 0; i < ncellId; ++i)
607 m_tbl[cellId[i] - 1].inoise = j;
610 if (noise)
delete noise;
611 B2DEBUG(150,
"ECLDigitizer: " << eclWFAlgoParams.size() <<
" noise matricies were loaded.");
614 m_idn.resize(eclWFAlgoParams.size());
615 for (
int i = 0, imax = eclWFAlgoParams.size(); i < imax; i++)
616 repack(eclWFAlgoParams[i], m_idn[i]);
618 vector<uint_pair_t> pairIdx;
619 for (
int i = 0; i < ec.
m_nch; i++) {
620 unsigned int wfIdx = eclWaveformDataTable[i];
621 unsigned int algoIdx = m_tbl[i].idn;
623 vector<uint_pair_t>::iterator ip = find(pairIdx.begin(), pairIdx.end(), p);
624 if (ip != pairIdx.end()) {
625 m_tbl[i].ifunc = ip - pairIdx.begin();
627 m_tbl[i].ifunc = pairIdx.size();
628 pairIdx.push_back(p);
633 m_fitparams.resize(pairIdx.size());
636 tree->SetBranchAddress(
"CovarianceM", &eclWFData);
637 tree->SetBranchStatus(
"ncellId", 0);
638 tree->SetBranchStatus(
"cellId", 0);
641 for (
unsigned int ip = 0; ip < pairIdx.size(); ip++) {
643 tree->GetEntry(p.first);
644 getfitparams(*eclWFData, eclWFAlgoParams[p.second], m_fitparams[ip]);
646 B2DEBUG(150,
"ECLDigitizer: " << m_fitparams.size() <<
" fitting crystals groups were created.");
652 m_ss[0].InitSample(MP, 27.7221);
658 for (
int i = 0; i < ec.
m_nch; i++) m_tbl[i].iss = 0;
662 double diode_params[] = {0 + 0.5, 0.100002, 0.756483, 0.456153, 0.0729031, 0.3906 / 9.98822, 2.85128, 0.842469, 0.854184, 0.110284};
663 m_ss[1].InitSample(diode_params, 0.9569100 * 9.98822);
665 B2DEBUG(150,
"ECLDigitizer: " << m_ss.size() <<
" sampled signal templates were created.");
667 if (eclWFData)
delete eclWFData;
675 t.id[ 0] = eclWFAlgo.
getlAT() + 128;
676 t.id[ 1] = eclWFAlgo.
getsT() + 128;
677 t.id[ 2] = eclWFAlgo.
gethT();
689 t.ic[12 * 2 + 0] = eclWFAlgo.
getk1();
690 t.ic[12 * 2 + 1] = eclWFAlgo.
getk2();
691 t.ic[13 * 2 + 0] = eclWFAlgo.
getka();
692 t.ic[13 * 2 + 1] = eclWFAlgo.
getkb();
693 t.ic[14 * 2 + 0] = eclWFAlgo.
getkc();
694 t.ic[14 * 2 + 1] = eclWFAlgo.
gety0s() - 16;
697 t.id[15] = eclWFAlgo.
getcT();
706 vector<double> MP(10);
712 int ia = 1 << eclWFAlgo.
getka();
713 int ib = 1 << eclWFAlgo.
getkb();
714 int ic = 1 << eclWFAlgo.
getkc();
732 double g0g0 = 0, g0g1 = 0, g1g1 = 0, g0g2 = 0, g1g2 = 0, g2g2 = 0;
733 double sg0[16], sg1[16], sg2[16];
734 for (
int j = 0; j < 16; j++) {
735 double g0 = 0, g1 = 0, g2 = 0;
736 for (
int i = 0; i < 16; i++) {
737 g0 += ssd[j][i] * f[i].first;
738 g1 += ssd[j][i] * f[i].second;
741 g0g0 += g0 * f[j].first;
742 g0g1 += g1 * f[j].first;
743 g1g1 += g1 * f[j].second;
752 double a00 = g1g1 * g2g2 - g1g2 * g1g2;
753 double a11 = g0g0 * g2g2 - g0g2 * g0g2;
754 double a22 = g0g0 * g1g1 - g0g1 * g0g1;
755 double a01 = g1g2 * g0g2 - g0g1 * g2g2;
756 double a02 = g0g1 * g1g2 - g1g1 * g0g2;
757 double a12 = g0g1 * g0g2 - g0g0 * g1g2;
759 double igg2 = 1 / (a11 * g1g1 + g0g1 * a01 + g1g2 * a12);
762 const double isd = 3. / 4., sd = 1 / isd ;
763 for (
int i = 0; i < 16; i++) {
764 double w = i ? 1.0 : 1. / 16.;
766 ref_f [k][i] = lrint(f[i].first * iff * w);
767 ref_f1 [k][i] = lrint(f[i].second * iff * w * sd);
769 double fg31 = (a00 * sg0[i] + a01 * sg1[i] + a02 * sg2[i]) * igg2;
770 double fg32 = (a01 * sg0[i] + a11 * sg1[i] + a12 * sg2[i]) * igg2;
771 double fg33 = (a02 * sg0[i] + a12 * sg1[i] + a22 * sg2[i]) * igg2;
773 ref_fg31[k][i] = lrint(fg31 * ia * w);
774 ref_fg32[k][i] = lrint(fg32 * ib * w * isd);
775 ref_fg33[k][i] = lrint(fg33 * ic * w);
779 int jk = 23 + ((48 - k) >> 2);
780 if (jk >= 0 && jk < 24 && (48 - k) % 4 == 0) {
782 double igg1 = 1 / a11;
784 for (
int i = 0; i < 16; i++) {
785 double w = i ? 1.0 : 1. / 16.;
787 double fg41 = (g2g2 * sg0[i] - g0g2 * sg2[i]) * igg1;
788 double fg43 = (g0g0 * sg2[i] - g0g2 * sg0[i]) * igg1;
789 ref_fg41[jk][i] = lrint(fg41 * ia * w);
790 ref_fg43[jk][i] = lrint(fg43 * ic * w);
Class for accessing objects in the database.
std::pair< unsigned int, unsigned int > uint_pair_t
a pair of unsigned ints
fitparams_t::int_array_192x16_t int_array_192x16_t
weighting coefficients for time and amplitude calculation
fitparams_t::int_array_24x16_t int_array_24x16_t
weighting coefficients amplitude calculation.
Container for constant matrix used to generate electronic noise.
Container for constant parameters used in waveform fits.
int getkc() const
getter for multipliers power of 2 for fg33,fg43
int getlAT() const
getter for the threshold to calculate time
int getsT() const
getter for the threshold to send data to collector
int getcT() const
getter for the chi2 threshold for quality bit
int getk1() const
getter for the multipliers power of 2 for f
int getk2() const
getter for multipliers power of 2 for chi2 calculation
int getkb() const
getter for multipliers power of 2 for fg32
int gethT() const
getter for the hardware threshold
int gety0s() const
getter for the start point for pedestal calculation
int getka() const
getter for multipliers power of 2 for fg31 fg41
Abstract class (interface) for ECL waveform compression/decompression to/from the BitStream storage.
virtual void uncompress(BitStream &in, int *adc)=0
Decompress the ECL waveform.
virtual void compress(BitStream &out, const int *adc)=0
Compress the ECL waveform.
The Class for ECL Geometry Parameters.
singleton class to hold the ECL configuration
static constexpr double m_step
time between points in internal units t_{asrto}*m_rf/2.
static constexpr double s_clock
digitization clock in RF units
static constexpr double m_rf
accelerating RF, http://ptep.oxfordjournals.org/content/2013/3/03A006.full.pdf
static constexpr int m_nch
total number of electronic channels (crystals) in calorimeter
static constexpr int m_ntrg
number of trigger counts per ADC clock tick
static constexpr int m_ndt
number of points per ADC tick where signal fit procedure parameters are evaluated
static constexpr int m_nsmp
number of ADC measurements for signal fitting
Class include function that calculate electronic response from energy deposit
void fillvector(std::vector< double > &) const
fill vector with response function values and its derivative
void settimeseed(double)
set initial time
void settimestride(double)
set grid step for function calculation
void nextseed()
substruct toffset to tzero
void setseedoffset(double)
set timeoffset
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.
calibration constants per channel
ffsets for storages of ECL channels
ShaperDSP fit results from _lftda function.
a struct for the ADC count
a struct for the parameters of the algorithm
a struct for the fit parameters