11 #include <cdc/modules/cdcDigitizer/CDCDigitizerModule.h>
12 #include <cdc/utilities/ClosestApproach.h>
14 #include <framework/datastore/RelationArray.h>
16 #include <framework/gearbox/Unit.h>
17 #include <framework/logging/Logger.h>
31 m_cdcgp(), m_gcp(), m_aCDCSimHit(), m_posFlag(0),
32 m_driftLength(0.0), m_flightTime(0.0), m_globalTime(0.0),
33 m_tdcBinWidth(1.0), m_tdcBinWidthInv(1.0),
34 m_tdcResol(0.9825), m_driftV(4.0e-3),
35 m_driftVInv(250.0), m_propSpeedInv(27.25), m_align(true)
38 setDescription(
"Creates CDCHits from CDCSimHits.");
39 setPropertyFlags(c_ParallelProcessingCertified);
43 addParam(
"InputCDCSimHitsName", m_inputCDCSimHitsName,
"Name of input array. Should consist of CDCSimHits.",
string(
""));
44 addParam(
"OutputCDCHitsName", m_outputCDCHitsName,
"Name of output array. Will consist of CDCHits.",
string(
""));
45 addParam(
"OutputCDCHitsName4Trg", m_outputCDCHitsName4Trg,
46 "Name of output array for trigger. Can contain several hits per wire, "
47 "if they correspond to different time windows of 32ns.",
48 string(
"CDCHits4Trg"));
51 addParam(
"MCParticlesToCDCSimHitsName", m_MCParticlesToSimHitsName,
52 "Name of relation between MCParticles and CDCSimHits used",
string(
""));
53 addParam(
"CDCSimHistToCDCHitsName", m_SimHitsTOCDCHitsName,
54 "Name of relation between the CDCSimHits and the CDCHits used",
string(
""));
58 addParam(
"UseSimpleDigitization", m_useSimpleDigitization,
59 "If true, a simple x-t with a constant velocity is used for the drift-length to -time conversion",
false);
62 addParam(
"Fraction", m_fraction,
"Fraction of first Gaussian used to smear drift length in cm", 1.0);
63 addParam(
"Mean1", m_mean1,
"Mean value of first Gaussian used to smear drift length in cm", 0.0000);
64 addParam(
"Resolution1", m_resolution1,
"Resolution of first Gaussian used to smear drift length in cm", 0.0130);
65 addParam(
"Mean2", m_mean2,
"Mean value of second Gaussian used to smear drift length in cm", 0.0000);
66 addParam(
"Resolution2", m_resolution2,
"Resolution of second Gaussian used to smear drift length in cm", 0.0000);
69 addParam(
"DoSmearing", m_doSmearing,
70 "If false, drift length will not be smeared.",
true);
72 addParam(
"TrigTimeJitter", m_trigTimeJitter,
73 "Magnitude (w) of trigger timing jitter (ns). The trigger timing is randuminzed uniformly in a time window of [-w/2, +w/2].",
76 addParam(
"AddTimeWalk", m_addTimeWalk,
"A switch for time-walk (pulse-heght dep. delay); true: on; false: off",
true);
77 addParam(
"AddInWirePropagationDelay", m_addInWirePropagationDelay,
78 "A switch used to control adding propagation delay in the wire into the final drift time or not; this is for signal hits.",
true);
79 addParam(
"AddInWirePropagationDelay4Bg", m_addInWirePropagationDelay4Bg,
80 "The same switch but for beam bg. hits.",
true);
81 addParam(
"AddTimeOfFlight", m_addTimeOfFlight,
82 "A switch used to control adding time of flight into the final drift time or not; this is for signal hits.",
true);
83 addParam(
"AddTimeOfFlight4Bg", m_addTimeOfFlight4Bg,
84 "The same switch but for beam bg. hits.",
true);
85 addParam(
"OutputNegativeDriftTime", m_outputNegativeDriftTime,
"Output hits with negative drift time",
true);
86 addParam(
"Output2ndHit", m_output2ndHit,
87 "Output the 2nd hit if exists in the time window. Note that it is not well-simulated at all, partly because no cross-talk betw. channels is simulated.",
90 addParam(
"CorrectForWireSag", m_correctForWireSag,
91 "A switch for sense wire sag effect; true: drift-time is calculated with the sag taken into account; false: not. Here, sag means the perturbative part which corresponds to alignment in case of wire-position. The main part (corresponding to design+displacement in wire-position) is taken into account in FullSim; you can control it via CDCJobCntlParModifier.",
94 addParam(
"TreatNegT0WiresAsGood", m_treatNegT0WiresAsGood,
"Treat wires with negative t0 (calibrated) as good wire4s.",
true);
97 addParam(
"TDCThreshold4Outer", m_tdcThreshold4Outer,
98 "TDC threshold (dE in eV) for Layers#8-56. The value corresponds to He-C2H6 gas; for the gas+wire (MaterialDefinitionMode=0) case, (this value)*f will be used, where f is specified by GasToGasWire",
100 addParam(
"TDCThreshold4Inner", m_tdcThreshold4Inner,
101 "Same as TDCThreshold4Outer but for Layers#0-7,", 25.0);
102 addParam(
"GasToGasWire", m_gasToGasWire,
103 "(Approximate) ratio of dE in He/C2H6-gas to dE in gas+wire, where dE is energy deposit.", 1. / 1.478);
106 addParam(
"ADCThreshold", m_adcThreshold,
107 "Threshold for ADC-count (in unit of count). ADC-count < threshold is treated as count=0.", 2);
108 addParam(
"tMin", m_tMin,
"Lower edge of time window in ns", -100.);
109 addParam(
"tMaxOuter", m_tMaxOuter,
"Upper edge of time window in ns for the normal-cell layers", 500.);
110 addParam(
"tMaxInner", m_tMaxInner,
"Upper edge of time window in ns for the small-cell layers", 300.);
117 addParam(
"UseDB4FEE", m_useDB4FEE,
"Fetch and use FEE params. from database or not",
true);
118 addParam(
"UseDB4EDepToADC", m_useDB4EDepToADC,
"Uuse edep-to-ADC conversion params. from database or not",
true);
119 addParam(
"UseDB4RunGain", m_useDB4RunGain,
"Fetch and use run gain from database or not",
true);
120 addParam(
"OverallGainFactor", m_overallGainFactor,
"Overall gain factor for adjustment", 1.0);
123 addParam(
"TDCThresholdOffset", m_tdcThresholdOffset,
"Offset for TDC (digital) threshold (mV)", 3820.);
124 addParam(
"AnalogGain", m_analogGain,
"Analog gain (V/pC)", 1.1);
125 addParam(
"DigitalGain", m_digitalGain,
"Digital gain (V/pC)", 15.);
126 addParam(
"ADCBinWidth", m_adcBinWidth,
"ADC bin width (mV)", 2.);
128 addParam(
"AddFudgeFactorForSigma", m_addFudgeFactorForSigma,
129 "Additional fudge factor for space resol. (common to all cells)", 1.);
130 addParam(
"SpaceChargeEffect", m_spaceChargeEffect,
"Switch for space charge effect",
true);
132 addParam(
"AddXTalk", m_addXTalk,
"A switch for crosstalk; true: on; false: off",
true);
133 addParam(
"Issue2ndHitWarning", m_issue2ndHitWarning,
"=true: issue a warning when a 2nd TDC hit is found.",
true);
134 addParam(
"IncludeEarlyXTalks", m_includeEarlyXTalks,
"=true: include earlier x-talks as well than the signal hit in question.",
136 addParam(
"DebugLevel4XTalk", m_debugLevel4XTalk,
"Debug level fr crosstalk; 20-29 are usable.", 20);
139 #if defined(CDC_DEBUG)
141 cout <<
"CDCDigitizer constructor" << endl;
145 void CDCDigitizerModule::initialize()
147 m_simHits.isRequired(m_inputCDCSimHitsName);
150 m_cdcHits.registerInDataStore(m_outputCDCHitsName);
151 m_simHits.registerRelationTo(m_cdcHits);
152 m_mcParticles.registerRelationTo(m_cdcHits);
154 m_cdcHits4Trg.registerInDataStore(m_outputCDCHitsName4Trg);
155 m_simHits.registerRelationTo(m_cdcHits4Trg);
156 m_mcParticles.registerRelationTo(m_cdcHits4Trg);
158 m_cdcgp = &(CDCGeometryPar::Instance());
161 m_tdcBinWidthInv = 1. / m_tdcBinWidth;
162 m_tdcResol = m_tdcBinWidth / sqrt(12.);
164 m_driftVInv = 1. / m_driftV;
167 if (m_cdcgp->getMaterialDefinitionMode() == 0) {
168 m_scaleFac = m_gasToGasWire;
170 m_scaleFac *= Unit::GeV;
171 m_gcp = &(CDCGeoControlPar::getInstance());
172 m_totalFudgeFactor = m_cdcgp->getFudgeFactorForSigma(2);
173 m_totalFudgeFactor *= m_addFudgeFactorForSigma;
174 B2DEBUG(29,
"totalFugeF in Digi= " << m_totalFudgeFactor);
185 if ((*m_fEElectronicsFromDB).isValid()) {
186 (*m_fEElectronicsFromDB).
addCallback(
this, &CDCDigitizerModule::setFEElectronics);
189 B2FATAL(
"CDCDigitizer:: CDCFEElectronics not valid !");
205 if (m_useDB4RunGain) {
207 if ((*m_runGainFromDB).isValid()) {
208 (*m_runGainFromDB).
addCallback(
this, &CDCDigitizerModule::setRunGain);
211 B2FATAL(
"CDCDedxRunGain invalid!");
214 B2DEBUG(29,
"run-gain = " << m_runGain);
218 if ((*m_xTalkFromDB).isValid()) {
220 B2FATAL(
"CDCCrossTalkLibrary invalid!");
224 #if defined(CDC_DEBUG)
226 cout <<
"CDCDigitizer initialize" << endl;
228 cout <<
"m_tdcBinWidth= " << m_tdcBinWidth << endl;
229 cout <<
"m_tdcResol= " << m_tdcResol << endl;
230 cout <<
"m_driftV= " << m_driftV << endl;
231 cout <<
"m_driftVInv= " << m_driftVInv << endl;
232 cout <<
"m_propSpeedInv= " << m_propSpeedInv << endl;
242 if (m_useDB4EDepToADC) {
243 if (m_cdcgp->getEDepToADCMainFactor(0, 0) == 0.) {
244 B2FATAL(
"CDCEDepToADCConversion payloads are unavailable!");
250 void CDCDigitizerModule::event()
253 RelationArray mcParticlesToCDCSimHits(m_mcParticles, m_simHits);
260 map<WireID, SignalInfo> signalMap;
261 map<WireID, SignalInfo>::iterator iterSignalMap;
263 map<WireID, unsigned short> adcMap;
264 map<WireID, unsigned short>::iterator iterADCMap;
269 map<pair<WireID, unsigned>,
SignalInfo> signalMapTrg;
270 map<pair<WireID, unsigned>,
SignalInfo>::iterator iterSignalMapTrg;
273 double trigTiming = m_trigTimeJitter == 0. ? 0. : m_trigTimeJitter * (gRandom->Uniform() - 0.5);
276 int nHits = m_simHits.getEntries();
277 B2DEBUG(29,
"Number of CDCSimHits in the current event: " << nHits);
278 for (
int iHits = 0; iHits < nHits; ++iHits) {
280 m_aCDCSimHit = m_simHits[iHits];
283 m_wireID = m_aCDCSimHit->getWireID();
286 m_posFlag = m_aCDCSimHit->getLeftRightPassageRaw();
287 m_boardID = m_cdcgp->getBoardID(m_wireID);
289 m_posWire = m_aCDCSimHit->getPosWire();
290 m_posTrack = m_aCDCSimHit->getPosTrack();
291 m_momentum = m_aCDCSimHit->getMomentum();
292 m_flightTime = m_aCDCSimHit->getFlightTime();
293 m_globalTime = m_aCDCSimHit->getGlobalTime();
294 m_driftLength = m_aCDCSimHit->getDriftLength() * Unit::cm;
300 TVector3 bwpAlign = m_cdcgp->wireBackwardPosition(m_wireID, CDCGeometryPar::c_Aligned);
301 TVector3 fwpAlign = m_cdcgp->wireForwardPosition(m_wireID, CDCGeometryPar::c_Aligned);
303 TVector3 bwp = m_cdcgp->wireBackwardPosition(m_wireID);
304 TVector3 fwp = m_cdcgp->wireForwardPosition(m_wireID);
307 if ((bwpAlign - bwp).Mag() == 0. && (fwpAlign - fwp).Mag() == 0.) m_align =
false;
310 if (m_align || m_correctForWireSag) {
315 if (m_correctForWireSag) {
316 double zpos = m_posWire.z();
317 double bckYSag = bwp.y();
318 double forYSag = fwp.y();
323 const int layerID = m_wireID.getICLayer();
324 const int wireID = m_wireID.getIWire();
325 m_cdcgp->getWireSagEffect(set, layerID, wireID, zpos, bckYSag, forYSag);
330 const TVector3 L = 5. * m_momentum.Unit();
331 TVector3 posIn = m_posTrack - L;
332 TVector3 posOut = m_posTrack + L;
333 TVector3 posTrack = m_posTrack;
334 TVector3 posWire = m_posWire;
337 m_driftLength =
ClosestApproach(bwp, fwp, posIn, posOut, posTrack, posWire);
339 m_posTrack = posTrack;
342 double deltaTime = 0.;
344 m_flightTime += deltaTime;
345 m_globalTime += deltaTime;
346 m_posFlag = m_cdcgp->getNewLeftRightRaw(m_posWire, m_posTrack, m_momentum);
351 double hitDriftLength = m_driftLength;
352 double dDdt = getdDdt(hitDriftLength);
354 hitDriftLength = smearDriftLength(hitDriftLength, dDdt);
358 bool addTof = m_addTimeOfFlight4Bg;
359 bool addDelay = m_addInWirePropagationDelay4Bg;
360 if (m_aCDCSimHit->getBackgroundTag() == 0) {
361 addTof = m_addTimeOfFlight;
362 addDelay = m_addInWirePropagationDelay;
364 double hitDriftTime = getDriftTime(hitDriftLength, addTof, addDelay);
367 if (m_aCDCSimHit->getBackgroundTag() != 0) {
368 hitDriftTime += m_globalTime - m_flightTime;
372 hitDriftTime += trigTiming;
375 double tMin = m_tMin;
376 double tMax = m_tMaxOuter;
377 if (m_wireID.getISuperLayer() == 0) tMax = m_tMaxInner;
379 tMin = m_lowEdgeOfTimeWindow[m_boardID];
380 tMax = m_uprEdgeOfTimeWindow[m_boardID];
382 if (hitDriftTime < tMin || hitDriftTime > tMax)
continue;
385 const double stepLength = m_aCDCSimHit->getStepLength() * Unit::cm;
386 const double costh = m_momentum.z() / m_momentum.Mag();
387 const double hitdE = m_scaleFac * m_aCDCSimHit->getEnergyDep();
389 unsigned short layerID = m_wireID.getICLayer();
390 unsigned short cellID = m_wireID.getIWire();
392 unsigned short adcCount = getADCCount(m_wireID, hitdE, stepLength, costh);
393 const unsigned short adcTh = m_useDB4FEE ? m_adcThresh[m_boardID] : m_adcThreshold;
395 if (adcCount < adcTh) adcCount = 0;
396 iterADCMap = adcMap.find(m_wireID);
397 if (iterADCMap == adcMap.end()) {
398 adcMap.insert(make_pair(m_wireID, adcCount));
401 iterADCMap->second += adcCount;
408 double dEThreshold = 0.;
409 if (m_useDB4FEE && m_useDB4EDepToADC) {
410 dEThreshold = (m_tdcThresh[m_boardID] / m_cdcgp->getEDepToADCMainFactor(layerID, cellID)) * Unit::keV;
412 dEThreshold = (m_wireID.getISuperLayer() == 0) ? m_tdcThreshold4Inner : m_tdcThreshold4Outer;
413 dEThreshold *= Unit::eV;
415 B2DEBUG(29,
"hitdE,dEThreshold,driftLength " << hitdE <<
" " << dEThreshold <<
" " << hitDriftLength);
417 if (hitdE < dEThreshold) {
418 B2DEBUG(29,
"Below Ethreshold: " << hitdE <<
" " << dEThreshold);
423 unsigned short trigWindow = floor((hitDriftTime - m_tMin) * m_tdcBinWidthInv / 32);
424 iterSignalMapTrg = signalMapTrg.find(make_pair(m_wireID, trigWindow));
425 if (iterSignalMapTrg == signalMapTrg.end()) {
428 signalMapTrg.insert(make_pair(make_pair(m_wireID, trigWindow),
431 if (hitDriftTime < iterSignalMapTrg->second.m_driftTime) {
432 iterSignalMapTrg->second.m_driftTime = hitDriftTime;
433 iterSignalMapTrg->second.m_simHitIndex = iHits;
436 iterSignalMapTrg->second.m_charge += adcCount;
440 if (m_cdcgp->isBadWire(m_wireID)) {
446 if (m_cdcgp->isDeadWire(m_wireID, eff)) {
448 if (eff < gRandom->Uniform())
continue;
452 const double a = bwpAlign.X();
453 const double b = bwpAlign.Y();
454 const double c = bwpAlign.Z();
455 const TVector3 fmbAlign = fwpAlign - bwpAlign;
456 const double lmn = 1. / fmbAlign.Mag();
457 const double l = fmbAlign.X() * lmn;
458 const double m = fmbAlign.Y() * lmn;
459 const double n = fmbAlign.Z() * lmn;
461 double dx = m_aCDCSimHit->getPosIn().X() - a;
462 double dy = m_aCDCSimHit->getPosIn().Y() - b;
463 double dz = m_aCDCSimHit->getPosIn().Z() - c;
464 double sub = l * dx + m * dy + n * dz;
465 const double driftLFromIn = sqrt(dx * dx + dy * dy + dz * dz - sub * sub);
467 dx = m_aCDCSimHit->getPosOut().X() - a;
468 dy = m_aCDCSimHit->getPosOut().Y() - b;
469 dz = m_aCDCSimHit->getPosOut().Z() - c;
470 sub = l * dx + m * dy + n * dz;
471 const double driftLFromOut = sqrt(dx * dx + dy * dy + dz * dz - sub * sub);
473 const double maxDriftL = std::max(driftLFromIn, driftLFromOut);
474 const double minDriftL = m_driftLength;
475 B2DEBUG(29,
"driftLFromIn= " << driftLFromIn <<
" driftLFromOut= " << driftLFromOut <<
" minDriftL= " << minDriftL <<
" maxDriftL= "
477 maxDriftL <<
"m_driftLength= " << m_driftLength);
479 iterSignalMap = signalMap.find(m_wireID);
481 if (iterSignalMap == signalMap.end()) {
484 signalMap.insert(make_pair(m_wireID,
SignalInfo(iHits, hitDriftTime, adcCount, maxDriftL, minDriftL)));
485 B2DEBUG(29,
"Creating new Signal with encoded wire number: " << m_wireID);
488 if (hitDriftTime < iterSignalMap->second.m_driftTime) {
489 iterSignalMap->second.m_driftTime3 = iterSignalMap->second.m_driftTime2;
490 iterSignalMap->second.m_simHitIndex3 = iterSignalMap->second.m_simHitIndex2;
491 iterSignalMap->second.m_driftTime2 = iterSignalMap->second.m_driftTime;
492 iterSignalMap->second.m_simHitIndex2 = iterSignalMap->second.m_simHitIndex;
493 iterSignalMap->second.m_driftTime = hitDriftTime;
494 iterSignalMap->second.m_simHitIndex = iHits;
495 B2DEBUG(29,
"hitDriftTime of current Signal: " << hitDriftTime <<
", hitDriftLength: " << hitDriftLength);
496 }
else if (hitDriftTime < iterSignalMap->second.m_driftTime2) {
497 iterSignalMap->second.m_driftTime3 = iterSignalMap->second.m_driftTime2;
498 iterSignalMap->second.m_simHitIndex3 = iterSignalMap->second.m_simHitIndex2;
499 iterSignalMap->second.m_driftTime2 = hitDriftTime;
500 iterSignalMap->second.m_simHitIndex2 = iHits;
501 }
else if (hitDriftTime < iterSignalMap->second.m_driftTime3) {
502 iterSignalMap->second.m_driftTime3 = hitDriftTime;
503 iterSignalMap->second.m_simHitIndex3 = iHits;
507 iterSignalMap->second.m_charge += adcCount;
510 if (iterSignalMap->second.m_maxDriftL < maxDriftL) iterSignalMap->second.m_maxDriftL = maxDriftL;
511 if (iterSignalMap->second.m_minDriftL > minDriftL) iterSignalMap->second.m_minDriftL = minDriftL;
512 B2DEBUG(29,
"maxDriftL in struct= " << iterSignalMap->second.m_maxDriftL <<
"minDriftL in struct= " <<
513 iterSignalMap->second.m_minDriftL);
521 unsigned int iCDCHits = 0;
523 RelationArray mcParticlesToCDCHits(m_mcParticles, m_cdcHits);
525 for (iterSignalMap = signalMap.begin(); iterSignalMap != signalMap.end(); ++iterSignalMap) {
530 iterADCMap = adcMap.find(iterSignalMap->first);
531 unsigned short adcCount = iterADCMap != adcMap.end() ? iterADCMap->second : 0;
544 B2DEBUG(29,
"timewalk= " << m_cdcgp->getTimeWalk(iterSignalMap->first, adcCount));
545 iterSignalMap->second.m_driftTime += m_cdcgp->getTimeWalk(iterSignalMap->first, adcCount);
549 if (!m_outputNegativeDriftTime &&
550 iterSignalMap->second.m_driftTime < 0.) {
555 unsigned short tdcCount =
static_cast<unsigned short>((getPositiveT0(iterSignalMap->first) - iterSignalMap->second.m_driftTime) *
556 m_tdcBinWidthInv + 0.5);
559 double deltaDL = iterSignalMap->second.m_maxDriftL - iterSignalMap->second.m_minDriftL;
561 B2DEBUG(29,
"negative deltaDL= " << deltaDL);
564 const unsigned short boardID = m_cdcgp->getBoardID(iterSignalMap->first);
565 unsigned short tot = std::min(std::round(5.92749 * deltaDL + 2.59706),
static_cast<double>(m_widthOfTimeWindow[boardID]));
566 if (m_adcThresh[boardID] > 0) {
567 tot = std::min(
static_cast<int>(tot),
static_cast<int>(adcCount / m_adcThresh[boardID]));
570 CDCHit* firstHit = m_cdcHits.appendNew(tdcCount, adcCount, iterSignalMap->first, 0, tot);
573 cdcSimHitsToCDCHits.
add(iterSignalMap->second.m_simHitIndex, iCDCHits);
577 if (rels.
size() != 0) {
580 double weight = rels.
weight(0);
585 if (m_output2ndHit && iterSignalMap->second.m_simHitIndex2 >= 0) {
586 unsigned short tdcCount2 =
static_cast<unsigned short>((getPositiveT0(iterSignalMap->first) - iterSignalMap->second.m_driftTime2) *
587 m_tdcBinWidthInv + 0.5);
588 if (tdcCount2 != tdcCount) {
589 CDCHit* secondHit = m_cdcHits.appendNew(tdcCount2, adcCount, iterSignalMap->first, 0, tot);
602 cdcSimHitsToCDCHits.
add(iterSignalMap->second.m_simHitIndex2, iCDCHits);
606 rels = m_simHits[iterSignalMap->second.m_simHitIndex2]->getRelationsFrom<
MCParticle>();
607 if (rels.
size() != 0) {
610 double weight = rels.
weight(0);
615 if (iterSignalMap->second.m_simHitIndex3 >= 0) {
616 unsigned short tdcCount3 =
static_cast<unsigned short>((getPositiveT0(iterSignalMap->first) - iterSignalMap->second.m_driftTime3) *
617 m_tdcBinWidthInv + 0.5);
619 if (tdcCount3 != tdcCount) {
620 CDCHit* secondHit = m_cdcHits.appendNew(tdcCount3, adcCount, iterSignalMap->first, 0, tot);
629 cdcSimHitsToCDCHits.
add(iterSignalMap->second.m_simHitIndex3, iCDCHits);
633 rels = m_simHits[iterSignalMap->second.m_simHitIndex3]->getRelationsFrom<
MCParticle>();
634 if (rels.
size() != 0) {
637 double weight = rels.
weight(0);
654 if (m_addXTalk) addXTalk();
658 for (iterSignalMapTrg = signalMapTrg.begin(); iterSignalMapTrg != signalMapTrg.end(); ++iterSignalMapTrg) {
667 unsigned short adcCount = iterSignalMapTrg->second.m_charge;
668 unsigned short tdcCount =
669 static_cast<unsigned short>((getPositiveT0(iterSignalMapTrg->first.first) -
670 iterSignalMapTrg->second.m_driftTime) * m_tdcBinWidthInv + 0.5);
671 const CDCHit* cdcHit = m_cdcHits4Trg.appendNew(tdcCount, adcCount, iterSignalMapTrg->first.first);
674 m_simHits[iterSignalMapTrg->second.m_simHitIndex]->
addRelationTo(cdcHit);
676 if (rels.
size() != 0) {
679 double weight = rels.
weight(0);
698 double CDCDigitizerModule::smearDriftLength(
const double driftLength,
const double dDdt)
703 if (m_useSimpleDigitization) {
704 if (gRandom->Uniform() <= m_fraction) {
706 resolution = m_resolution1;
709 resolution = m_resolution2;
712 const unsigned short leftRight = m_posFlag;
713 double alpha = m_cdcgp->getAlpha(m_posWire, m_momentum);
714 double theta = m_cdcgp->getTheta(m_momentum);
715 resolution = m_cdcgp->getSigma(driftLength, m_wireID.getICLayer(), leftRight, alpha, theta);
716 resolution *= m_totalFudgeFactor;
721 double diff = resolution - dDdt * m_tdcResol;
723 resolution = sqrt(diff * (resolution + dDdt * m_tdcResol));
728 #if defined(CDC_DEBUG)
730 cout <<
"CDCDigitizerModule::smearDriftLength" << endl;
731 cout <<
"tdcResol= " << m_tdcResol << endl;
732 cout <<
"dDdt,resolution= " << dDdt <<
" " << resolution << endl;
736 double newDL = gRandom->Gaus(driftLength + mean , resolution);
737 while (newDL <= 0.) newDL = gRandom->Gaus(driftLength + mean, resolution);
743 double CDCDigitizerModule::getdDdt(
const double driftL)
749 double dDdt = m_driftV;
751 if (!m_useSimpleDigitization) {
752 const unsigned short layer = m_wireID.getICLayer();
753 const unsigned short leftRight = m_posFlag;
754 double alpha = m_cdcgp->getAlpha(m_posWire, m_momentum);
755 double theta = m_cdcgp->getTheta(m_momentum);
756 double t = m_cdcgp->getDriftTime(driftL, layer, leftRight, alpha, theta);
757 dDdt = m_cdcgp->getDriftV(t, layer, leftRight, alpha, theta);
759 #if defined(CDC_DEBUG)
761 cout <<
"CDCDigitizerModule::getdDdt" << endl;
762 cout <<
"**layer= " << layer << endl;
763 cout <<
"alpha= " << 180.*alpha / M_PI << std::endl;
766 for (
int i = 0; i < 1000; ++i) {
768 double d = m_cdcgp->getDriftLength(t, layer, lr, alpha, theta);
769 cout << t <<
" " << d << endl;
775 for (
int i = 0; i < 100; ++i) {
777 double d = m_cdcgp->getDriftLength(t, layer, lr, alpha, theta);
778 cout << t <<
" " << d << endl;
789 double CDCDigitizerModule::getDriftTime(
const double driftLength,
const bool addTof,
const bool addDelay)
800 if (m_useSimpleDigitization) {
801 driftT = (driftLength / Unit::cm) * m_driftVInv;
803 #if defined(CDC_DEBUG)
805 cout <<
"CDCDigitizerModule::getDriftTime" << endl;
806 cout <<
"driftvinv= " << m_driftVInv << endl;
809 const unsigned short layer = m_wireID.getICLayer();
810 const unsigned short leftRight = m_posFlag;
811 double alpha = m_cdcgp->getAlpha(m_posWire, m_momentum);
812 double theta = m_cdcgp->getTheta(m_momentum);
813 driftT = m_cdcgp->getDriftTime(driftLength, layer, leftRight, alpha, theta);
818 driftT += m_flightTime;
824 TVector3 backWirePos = m_cdcgp->wireBackwardPosition(m_wireID, set);
826 double propLength = (m_posWire - backWirePos).Mag();
830 if (m_gcp->getSenseWireZposMode() == 1) {
831 const unsigned short layer = m_wireID.getICLayer();
832 propLength += m_cdcgp->getBwdDeltaZ(layer);
836 if (m_useSimpleDigitization) {
837 driftT += (propLength / Unit::cm) * m_propSpeedInv;
839 #if defined(CDC_DEBUG)
840 cout <<
"pseedinv= " << m_propSpeedInv << endl;
843 const unsigned short layer = m_wireID.getICLayer();
844 driftT += (propLength / Unit::cm) * m_cdcgp->getPropSpeedInv(layer);
845 #if defined(CDC_DEBUG)
846 cout <<
"layer,pseedinv= " << layer <<
" " << m_cdcgp->getPropSpeedInv(layer) << endl;
856 unsigned short CDCDigitizerModule::getADCCount(
const WireID& wid,
double dEinGeV,
double dx,
double costh)
858 unsigned short adcCount = 0;
859 if (dEinGeV <= 0. || dx <= 0.)
return adcCount;
864 double conv = (100.0 / 3.2);
865 const unsigned short layer = wid.
getICLayer();
866 const unsigned short cell = wid.
getIWire();
867 double dEInkeV = dEinGeV / Unit::keV;
868 if (m_spaceChargeEffect) {
869 if (m_useDB4EDepToADC) conv = m_cdcgp->getEDepToADCConvFactor(layer, cell, dEInkeV, dx, costh);
871 if (m_useDB4EDepToADC) conv = m_cdcgp->getEDepToADCMainFactor(layer, cell);
876 adcCount =
static_cast<unsigned short>(std::round(conv * dEInkeV));
882 void CDCDigitizerModule::setFEElectronics()
884 const double& off = m_tdcThresholdOffset;
885 const double& gA = m_analogGain;
886 const double& gD = m_digitalGain;
887 const double& adcBW = m_adcBinWidth;
888 const double convF = gA / gD / adcBW;
889 const double el1TrgLatency = m_cdcgp->getMeanT0();
890 B2DEBUG(29,
"L1TRGLatency= " << el1TrgLatency);
891 const double c = 32. * m_tdcBinWidth;
893 if (!m_fEElectronicsFromDB) B2FATAL(
"No FEEElectronics dbobject!");
895 int mode = (fp.getBoardID() == -1) ? 1 : 0;
896 int iNBoards =
static_cast<int>(nBoards);
900 for (
int bdi = 1; bdi < iNBoards; ++bdi) {
901 m_uprEdgeOfTimeWindow[bdi] = el1TrgLatency - c * (fp.getTrgDelay() + 1);
902 if (m_uprEdgeOfTimeWindow[bdi] < 0.) B2FATAL(
"CDCDigitizer: Upper edge of time window < 0!");
903 m_lowEdgeOfTimeWindow[bdi] = m_uprEdgeOfTimeWindow[bdi] - c * (fp.getWidthOfTimeWindow() + 1);
904 if (m_lowEdgeOfTimeWindow[bdi] > 0.) B2FATAL(
"CDCDigitizer: Lower edge of time window > 0!");
905 m_adcThresh[bdi] = fp.getADCThresh();
906 m_tdcThresh[bdi] = convF * (off - fp.getTDCThreshInMV());
907 m_widthOfTimeWindow[bdi] = fp.getWidthOfTimeWindow() + 1;
913 for (
const auto& fpp : (*m_fEElectronicsFromDB)) {
914 int bdi = fpp.getBoardID();
915 if (mode == 0 && bdi == 0)
continue;
916 if (mode == 1 && bdi == -1)
continue;
917 if (bdi < 0 || bdi >= iNBoards) B2FATAL(
"CDCDigitizer:: Invalid no. of FEE board!");
918 m_uprEdgeOfTimeWindow[bdi] = el1TrgLatency - c * (fpp.getTrgDelay() + 1);
919 if (m_uprEdgeOfTimeWindow[bdi] < 0.) B2FATAL(
"CDCDigitizer: Upper edge of time window < 0!");
920 m_lowEdgeOfTimeWindow[bdi] = m_uprEdgeOfTimeWindow[bdi] - c * (fpp.getWidthOfTimeWindow() + 1);
921 if (m_lowEdgeOfTimeWindow[bdi] > 0.) B2FATAL(
"CDCDigitizer: Lower edge of time window > 0!");
922 m_adcThresh[bdi] = fpp.getADCThresh();
923 m_tdcThresh[bdi] = convF * (off - fpp.getTDCThreshInMV());
924 m_widthOfTimeWindow[bdi] = fpp.getWidthOfTimeWindow() + 1;
928 B2DEBUG(29,
"mode= " << mode);
929 for (
int bdi = 1; bdi < iNBoards; ++bdi) {
930 B2DEBUG(29, bdi <<
" " << m_lowEdgeOfTimeWindow[bdi] <<
" " << m_uprEdgeOfTimeWindow[bdi] <<
" " << m_adcThresh[bdi] <<
" " <<
936 void CDCDigitizerModule::setRunGain()
938 m_runGain = (*m_runGainFromDB)->getRunGain();
939 m_runGain *= m_overallGainFactor;
942 void CDCDigitizerModule::addXTalk()
944 map<WireID, XTalkInfo> xTalkMap;
945 map<WireID, XTalkInfo> xTalkMap1;
946 map<WireID, XTalkInfo>::iterator iterXTalkMap1;
949 int OriginalNoOfHits = m_cdcHits.getEntries();
950 B2DEBUG(m_debugLevel4XTalk,
"\n \n" <<
"#CDCHits " << OriginalNoOfHits);
951 for (
const auto& aHit : m_cdcHits) {
952 if (m_issue2ndHitWarning && aHit.is2ndHit()) {
953 B2WARNING(
"2nd TDC hit found, but not ready for it!");
957 short tdcCount = aHit.getTDCCount();
958 short adcCount = aHit.getADCCount();
959 short tot = aHit.getTOT();
960 short board = m_cdcgp->getBoardID(wid);
961 short channel = m_cdcgp->getChannelID(wid);
962 const vector<pair<short, asicChannel>> xTalks = (*m_xTalkFromDB)->getLibraryCrossTalk(channel, tdcCount, adcCount, tot);
964 int nXTalks = xTalks.size();
965 for (
int i = 0; i < nXTalks; ++i) {
966 const unsigned short tdcCount4XTalk = xTalks[i].second.TDC;
968 B2DEBUG(m_debugLevel4XTalk,
"\n" <<
" signal: " << channel <<
" " << tdcCount <<
" " << adcCount <<
" " << tot);
970 B2DEBUG(m_debugLevel4XTalk,
"xtalk: " << xTalks[i].first <<
" " << tdcCount4XTalk <<
" " << xTalks[i].second.ADC <<
" " <<
971 xTalks[i].second.TOT);
972 WireID widx = m_cdcgp->getWireID(board, xTalks[i].first);
973 if (!m_cdcgp->isBadWire(widx)) {
974 if (m_includeEarlyXTalks || (xTalks[i].second.TDC <= tdcCount)) {
975 const double t0 = getPositiveT0(widx);
976 const double ULOfTDC = (t0 - m_lowEdgeOfTimeWindow[board]) * m_tdcBinWidthInv;
977 const double LLOfTDC = (t0 - m_uprEdgeOfTimeWindow[board]) * m_tdcBinWidthInv;
978 if (LLOfTDC <= tdcCount4XTalk && tdcCount4XTalk <= ULOfTDC) {
979 const unsigned short status = 0;
980 xTalkMap.insert(make_pair(widx,
XTalkInfo(tdcCount4XTalk, xTalks[i].second.ADC, xTalks[i].second.TOT, status)));
990 B2DEBUG(m_debugLevel4XTalk,
"#xtalk hits: " << xTalkMap.size());
991 for (
const auto& aHit : xTalkMap) {
994 iterXTalkMap1 = xTalkMap1.find(wid);
995 unsigned short tdcCount = aHit.second.m_tdc;
996 unsigned short adcCount = aHit.second.m_adc;
997 unsigned short tot = aHit.second.m_tot;
998 unsigned short status = aHit.second.m_status;
1000 if (iterXTalkMap1 == xTalkMap1.end()) {
1001 xTalkMap1.insert(make_pair(wid,
XTalkInfo(tdcCount, adcCount, tot, status)));
1004 if (tdcCount < iterXTalkMap1->second.m_tdc) {
1005 iterXTalkMap1->second.m_tdc = tdcCount;
1006 B2DEBUG(m_debugLevel4XTalk,
"TDC-count of current xtalk: " << tdcCount);
1008 iterXTalkMap1->second.m_adc += adcCount;
1009 iterXTalkMap1->second.m_tot += tot;
1014 B2DEBUG(m_debugLevel4XTalk,
"#xtalk1 hits: " << xTalkMap1.size());
1015 for (
const auto& aX : xTalkMap1) {
1017 const unsigned short tdc4Bg = aX.second.m_tdc;
1018 const unsigned short adc4Bg = aX.second.m_adc;
1019 const unsigned short tot4Bg = aX.second.m_tot;
1020 const unsigned short status4Bg = aX.second.m_status;
1022 for (
int iHit = 0; iHit < OriginalNoOfHits; ++iHit) {
1023 CDCHit& aH = *(m_cdcHits[iHit]);
1024 if (aH.
getID() != aX.first.getEWire()) {
1030 const unsigned short tot4Sg = aH.
getTOT();
1036 if (tdc4Sg < tdc4Bg) {
1040 for (
int i = relSimHits.size() - 1; i >= 0; --i) {
1041 relSimHits.remove(i);
1044 for (
int i = relMCParticles.size() - 1; i >= 0; --i) {
1045 relMCParticles.remove(i);
1055 unsigned short s1 = tdc4Sg;
1056 unsigned short s2 = tdc4Bg;
1057 unsigned short w1 = tot4Sg;
1058 unsigned short w2 = tot4Bg;
1059 if (tdc4Sg < tdc4Bg) {
1067 const unsigned short e1 = s1 - w1;
1068 const unsigned short e2 = s2 - w2;
1071 double pulseW = w1 + w2;
1074 }
else if (e1 <= s2) {
1078 unsigned short board = m_cdcgp->getBoardID(aX.first);
1079 aH.
setTOT(std::min(std::round(pulseW / 32.),
static_cast<double>(m_widthOfTimeWindow[board])));
1088 m_cdcHits.appendNew(tdc4Bg, adc4Bg, aX.first, status4Bg, tot4Bg);
1089 B2DEBUG(m_debugLevel4XTalk,
"appended tdc,adc,tot,wid,status= " << tdc4Bg <<
" " << adc4Bg <<
" " << tot4Bg <<
" " << aX.first <<
1094 B2DEBUG(m_debugLevel4XTalk,
"original #hits, #hits= " << OriginalNoOfHits <<
" " << m_cdcHits.getEntries());
1098 double CDCDigitizerModule::getPositiveT0(
const WireID& wid)
1100 double t0 = m_cdcgp->getT0(wid);
1101 if (t0 <= 0 && m_treatNegT0WiresAsGood) t0 = m_cdcgp->getMeanT0();