Belle II Software  release-06-01-15
CDCDigitizerModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <cdc/modules/cdcDigitizer/CDCDigitizerModule.h>
10 #include <cdc/modules/cdcDigitizer/EDepInGas.h>
11 #include <cdc/utilities/ClosestApproach.h>
12 
13 #include <framework/datastore/RelationArray.h>
14 //#include <framework/datastore/RelationIndex.h>
15 #include <framework/gearbox/Unit.h>
16 #include <framework/logging/Logger.h>
17 
18 #include <TRandom.h>
19 #include <map>
20 #include <utility>
21 
22 using namespace std;
23 using namespace Belle2;
24 using namespace CDC;
25 
26 // register module
27 REG_MODULE(CDCDigitizer)
29  m_cdcgp(), m_gcp(), m_aCDCSimHit(), m_posFlag(0),
30  m_driftLength(0.0), m_flightTime(0.0), m_globalTime(0.0),
31  m_tdcBinWidth(1.0), m_tdcBinWidthInv(1.0),
32  m_tdcResol(0.9825), m_driftV(4.0e-3),
33  m_driftVInv(250.0), m_propSpeedInv(27.25), m_align(true)
34 {
35  // Set description
36  setDescription("Creates CDCHits from CDCSimHits.");
37  setPropertyFlags(c_ParallelProcessingCertified);
38 
39  // Add parameters
40  // I/O
41  addParam("InputCDCSimHitsName", m_inputCDCSimHitsName, "Name of input array. Should consist of CDCSimHits.", string(""));
42  addParam("OutputCDCHitsName", m_outputCDCHitsName, "Name of output array. Will consist of CDCHits.", string(""));
43  addParam("OutputCDCHitsName4Trg", m_outputCDCHitsName4Trg,
44  "Name of output array for trigger. Can contain several hits per wire, "
45  "if they correspond to different time windows of 32ns.",
46  string("CDCHits4Trg"));
47 
48  //Relations
49  addParam("MCParticlesToCDCSimHitsName", m_MCParticlesToSimHitsName,
50  "Name of relation between MCParticles and CDCSimHits used", string(""));
51  addParam("CDCSimHistToCDCHitsName", m_SimHitsTOCDCHitsName,
52  "Name of relation between the CDCSimHits and the CDCHits used", string(""));
53 
54 
55  //Parameters for Digitization
56  addParam("UseSimpleDigitization", m_useSimpleDigitization,
57  "If true, a simple x-t with a constant velocity is used for the drift-length to -time conversion", false);
58 
59  //float Gauss Parameters
60  addParam("Fraction", m_fraction, "Fraction of first Gaussian used to smear drift length in cm", 1.0);
61  addParam("Mean1", m_mean1, "Mean value of first Gaussian used to smear drift length in cm", 0.0000);
62  addParam("Resolution1", m_resolution1, "Resolution of first Gaussian used to smear drift length in cm", 0.0130);
63  addParam("Mean2", m_mean2, "Mean value of second Gaussian used to smear drift length in cm", 0.0000);
64  addParam("Resolution2", m_resolution2, "Resolution of second Gaussian used to smear drift length in cm", 0.0000);
65 
66  //Switch to control smearing
67  addParam("DoSmearing", m_doSmearing,
68  "If false, drift length will not be smeared.", true);
69 
70  addParam("TrigTimeJitter", m_trigTimeJitter,
71  "Magnitude (w) of trigger timing jitter (ns). The trigger timing is randuminzed uniformly in a time window of [-w/2, +w/2].",
72  0.);
73  //Switches to control time information handling
74  addParam("AddTimeWalk", m_addTimeWalk, "A switch for time-walk (pulse-heght dep. delay); true: on; false: off", true);
75  addParam("AddInWirePropagationDelay", m_addInWirePropagationDelay,
76  "A switch used to control adding propagation delay in the wire into the final drift time or not; this is for signal hits.", true);
77  addParam("AddInWirePropagationDelay4Bg", m_addInWirePropagationDelay4Bg,
78  "The same switch but for beam bg. hits.", true);
79  addParam("AddTimeOfFlight", m_addTimeOfFlight,
80  "A switch used to control adding time of flight into the final drift time or not; this is for signal hits.", true);
81  addParam("AddTimeOfFlight4Bg", m_addTimeOfFlight4Bg,
82  "The same switch but for beam bg. hits.", true);
83  addParam("OutputNegativeDriftTime", m_outputNegativeDriftTime, "Output hits with negative drift time", true);
84  addParam("Output2ndHit", m_output2ndHit,
85  "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.",
86  false);
87  //Switch to control sense wire sag
88  addParam("CorrectForWireSag", m_correctForWireSag,
89  "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.",
90  true);
91  //Switch for negative-t0 wires
92  addParam("TreatNegT0WiresAsGood", m_treatNegT0WiresAsGood, "Treat wires with negative t0 (calibrated) as good wire4s.", true);
93 
94  //Threshold
95  addParam("TDCThreshold4Outer", m_tdcThreshold4Outer,
96  "TDC threshold (dE in eV) for Layers#8-56. The value corresponds to He-C2H6 gas", 250.);
97  addParam("TDCThreshold4Inner", m_tdcThreshold4Inner,
98  "Same as TDCThreshold4Outer but for Layers#0-7,", 150.);
99  addParam("EDepInGasMode", m_eDepInGasMode,
100  "Mode for extracting energy deposit in gas from energy deposit in gas+wire; =0: scaling using electron density; 1: scaling using most probab. energy deposit; 2: similar to 2 but slightly different; 3: extraction based on probability; 4: regeneration following probability",
101  0);
102 
103  //ADC Threshold
104  addParam("ADCThreshold", m_adcThreshold,
105  "Threshold for ADC-count (in unit of count). ADC-count < threshold is treated as count=0.", 2);
106  addParam("tMin", m_tMin, "Lower edge of time window in ns; valid only for UseDB4FEE=false", -100.);
107  addParam("tMaxOuter", m_tMaxOuter, "Upper edge of time window in ns for the normal-cell layers; valid only for UseDB4FEE=false",
108  500.);
109  addParam("tMaxInner", m_tMaxInner, "Upper edge of time window in ns for the small-cell layers; valid only for UseDB4FEE=false",
110  300.);
111  // The following doesn't make any sense. The only reasonable steerable would be a switch to decide if the jitter shall be
112  // activated. Then there has to be event by event jitter.
113  /* addParam("EventTime", m_eventTime,
114  "It is a timing of event, which includes a time jitter due to the trigger system, set in ns", float(0.0));*/
115 
116  //Switch for database
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);
121 
122  //Switch for synchronization
123  addParam("Synchronization", m_synchronization, "Synchronize timing with other sub-detectors", m_synchronization);
124  addParam("Randomization", m_randomization, "Randomize timing with other sub-detectors; valid only for Synchronization=false",
125  m_randomization);
126  addParam("OffsetForGetTriggerBin", m_offsetForTriggerBin, "Input to getCDCTriggerBin(offset), either of 0,1,2 or 3",
127  m_offsetForTriggerBin);
128  addParam("TrgTimingOffsetInCount", m_trgTimingOffsetInCount,
129  "L1 trigger timing offset in count, [0,7] in a trigger bin. The defaut value is from exp14, while the value from exp12 is 2. This run dependence may be taken into account later if needed",
130  m_trgTimingOffsetInCount);
131  addParam("ShiftOfTimeWindowIn32Count", m_shiftOfTimeWindowIn32Count,
132  "Shift of time window in 32count for synchronization (L1 timing=0)", m_shiftOfTimeWindowIn32Count);
133 
134  //Some FEE params.
135  addParam("TDCThresholdOffset", m_tdcThresholdOffset, "Offset for TDC (digital) threshold (mV)", 3828.);
136  addParam("AnalogGain", m_analogGain, "Analog gain (V/pC)", 1.09);
137  addParam("DigitalGain", m_digitalGain, "Digital gain (V/pC)", 7.);
138  addParam("ADCBinWidth", m_adcBinWidth, "ADC bin width (mV)", 2.);
139 
140  addParam("AddFudgeFactorForSigma", m_addFudgeFactorForSigma,
141  "Additional fudge factor for space resol. (common to all cells)", 1.);
142  addParam("SpaceChargeEffect", m_spaceChargeEffect, "Switch for space charge effect", true);
143  addParam("DegOfSPEOnThreshold", m_degOfSPEOnThreshold,
144  "Degree of space charge effect on timing threshold; specify the range [0,1]; =1: full effect on threshold; =0: no effect",
145  m_degOfSPEOnThreshold);
146 
147  addParam("AddXTalk", m_addXTalk, "A switch for crosstalk; true: on; false: off", true);
148  addParam("Issue2ndHitWarning", m_issue2ndHitWarning, "=true: issue a warning when a 2nd TDC hit is found.", true);
149  addParam("IncludeEarlyXTalks", m_includeEarlyXTalks, "=true: include earlier x-talks as well than the signal hit in question.",
150  true);
151  addParam("DebugLevel", m_debugLevel, "Debug level; 20-29 are usable.", 20);
152  addParam("DebugLevel4XTalk", m_debugLevel4XTalk, "Debug level for crosstalk; 20-29 are usable.", 21);
153 
154  //Gain smearing
155  addParam("GasGainSmearing", m_gasGainSmearing, "Switch for gas gain smearing; true: on; false: off", m_gasGainSmearing);
156  addParam("EffWForGasGainSmearing", m_effWForGasGainSmearing,
157  "Effective energy (keV) needed for one electron production for gas gain smearing; average for alpha- and beta-sources.",
158  m_effWForGasGainSmearing);
159  addParam("ThetaOfPolyaFunction", m_thetaOfPolya, "Theta of Polya function for gas gain smearing", m_thetaOfPolya);
160  addParam("ExtraADCSmearing", m_extraADCSmearing, "Switch for extra ADC smearing; true: on; false: off", m_extraADCSmearing);
161  // addParam("SigmaForExtraADCSmearing", m_sigmaForExtraADCSmearing, "Gaussian sigma for extra ADC smearing; specify range [0,1]", m_sigmaForExtraADCSmearing);
162 
163 #if defined(CDC_DEBUG)
164  cout << " " << endl;
165  cout << "CDCDigitizer constructor" << endl;
166 #endif
167 }
168 
169 void CDCDigitizerModule::initialize()
170 {
171  m_simHits.isRequired(m_inputCDCSimHitsName);
172  m_simClockState.isOptional();
173 
174  // Register the arrays in the DataStore, that are to be added in this module.
175  m_cdcHits.registerInDataStore(m_outputCDCHitsName);
176  m_simHits.registerRelationTo(m_cdcHits);
177  m_mcParticles.registerRelationTo(m_cdcHits);
178  // Arrays for trigger.
179  m_cdcHits4Trg.registerInDataStore(m_outputCDCHitsName4Trg);
180  m_simHits.registerRelationTo(m_cdcHits4Trg);
181  m_mcParticles.registerRelationTo(m_cdcHits4Trg);
182 
183  m_cdcgp = &(CDCGeometryPar::Instance());
184  CDCGeometryPar& cdcgp = *m_cdcgp;
185  m_tdcBinWidth = cdcgp.getTdcBinWidth();
186  m_tdcBinWidthInv = 1. / m_tdcBinWidth;
187  m_tdcResol = m_tdcBinWidth / sqrt(12.);
188  m_driftV = cdcgp.getNominalDriftV();
189  m_driftVInv = 1. / m_driftV;
190  m_propSpeedInv = 1. / cdcgp.getNominalPropSpeed();
191  m_gcp = &(CDCGeoControlPar::getInstance());
192  m_totalFudgeFactor = m_cdcgp->getFudgeFactorForSigma(2);
193  m_totalFudgeFactor *= m_addFudgeFactorForSigma;
194  B2DEBUG(m_debugLevel, "totalFugeF in Digi= " << m_totalFudgeFactor);
195  /*
196  m_fraction = 1.0;
197  m_resolution1 = cdcgp.getNominalSpaceResol();
198  m_resolution2 = 0.;
199  m_mean1 = 0.;
200  m_mean2 = 0.;
201  */
202 
203  if (m_useDB4FEE) {
204  m_fEElectronicsFromDB = new DBArray<CDCFEElectronics>;
205  if ((*m_fEElectronicsFromDB).isValid()) {
206  (*m_fEElectronicsFromDB).addCallback(this, &CDCDigitizerModule::setFEElectronics);
207  setFEElectronics();
208  } else {
209  B2FATAL("CDCDigitizer:: CDCFEElectronics not valid !");
210  }
211  }
212 
213  /*
214  if (m_useDB4EDepToADC) {
215  m_eDepToADCConversionsFromDB = new DBObjPtr<CDCEDepToADCConversions>;
216  if ((*m_eDepToADCConversionsFromDB).isValid()) {
217  (*m_eDepToADCConversionsFromDB).addCallback(this, &CDCDigitizerModule::setEDepToADCConversions);
218  setEDepToADCConversions();
219  } else {
220  B2FATAL("CDCDigitizer:: CDCEDepToADCConversions not valid !");
221  }
222  }
223  */
224 
225  if (m_useDB4RunGain) {
226  m_runGainFromDB = new DBObjPtr<CDCDedxRunGain>;
227  if ((*m_runGainFromDB).isValid()) {
228  (*m_runGainFromDB).addCallback(this, &CDCDigitizerModule::setSemiTotalGain);
229  } else {
230  B2FATAL("CDCDedxRunGain invalid!");
231  }
232 
233  m_gain0FromDB = new DBObjPtr<CDCDedxScaleFactor>;
234  if ((*m_gain0FromDB).isValid()) {
235  (*m_gain0FromDB).addCallback(this, &CDCDigitizerModule::setSemiTotalGain);
236  } else {
237  B2FATAL("CDCDedxScaleFactor invalid!");
238  }
239 
240  m_wireGainFromDB = new DBObjPtr<CDCDedxWireGain>;
241  if ((*m_wireGainFromDB).isValid()) {
242  (*m_wireGainFromDB).addCallback(this, &CDCDigitizerModule::setSemiTotalGain);
243  setSemiTotalGain();
244  } else {
245  B2FATAL("CDCDedxWireGain invalid!");
246  }
247  }
248 
249  if (m_addXTalk) {
250  m_xTalkFromDB = new DBObjPtr<CDCCrossTalkLibrary>;
251  if ((*m_xTalkFromDB).isValid()) {
252  } else {
253  B2FATAL("CDCCrossTalkLibrary invalid!");
254  }
255  }
256 
257 #if defined(CDC_DEBUG)
258  cout << " " << endl;
259  cout << "CDCDigitizer initialize" << endl;
260  // cout << "m_tdcOffset= " << m_tdcOffset << endl;
261  cout << "m_tdcBinWidth= " << m_tdcBinWidth << endl;
262  cout << "m_tdcResol= " << m_tdcResol << endl;
263  cout << "m_driftV= " << m_driftV << endl;
264  cout << "m_driftVInv= " << m_driftVInv << endl;
265  cout << "m_propSpeedInv= " << m_propSpeedInv << endl;
266  /*
267  cout << "m_fraction= " << m_fraction << endl;
268  cout << "m_resolution1= " << m_resolution1 << endl;
269  cout << "m_resolution2= " << m_resolution2 << endl;
270  cout << "m_mean1= " << m_mean1 << endl;
271  cout << "m_mean2= " << m_mean2 << endl;
272  */
273 #endif
274 
275  if (m_useDB4EDepToADC) {
276  if (m_cdcgp->getEDepToADCMainFactor(0, 0) == 0.) {
277  B2FATAL("CDCEDepToADCConversion payloads are unavailable!");
278  }
279  }
280 
281  // Set timing sim. mode
282  if (m_useDB4FEE) {
283  if (m_synchronization) { // syncronization
284  m_tSimMode = 0;
285  } else {
286  if (m_randomization) { // radomization
287  m_tSimMode = 1;
288  } else {
289  m_tSimMode = 2; // old sim.
290  }
291  }
292  } else {
293  m_tSimMode = 3; // old sim. w/o relying on fee db
294  }
295  B2DEBUG(m_debugLevel, "timing sim. mode= " << m_tSimMode);
296  if (m_tSimMode < 0 || m_tSimMode > 3) B2FATAL("invalid timing sim. mode= " << m_tSimMode);
297 }
298 
299 void CDCDigitizerModule::event()
300 {
301  // Get SimHit array, MCParticle array, and relation between the two.
302  RelationArray mcParticlesToCDCSimHits(m_mcParticles, m_simHits); //RelationArray created by CDC SensitiveDetector
303 
304 
305  //--- Start Digitization --------------------------------------------------------------------------------------------
306  // Merge the hits in the same cell and save them into CDC signal map.
307 
308  // Define signal map
309  map<WireID, SignalInfo> signalMap;
310  map<WireID, SignalInfo>::iterator iterSignalMap;
311  // Define adc map
312  map<WireID, unsigned short> adcMap;
313  map<WireID, unsigned short>::iterator iterADCMap;
314  // map<WireID, double> adcMap;
315  // map<WireID, double>::iterator iterADCMap;
316 
317  // signal map for trigger
318  map<pair<WireID, unsigned>, SignalInfo> signalMapTrg;
319  map<pair<WireID, unsigned>, SignalInfo>::iterator iterSignalMapTrg;
320 
321  // Set time window per event
322  if (m_tSimMode == 0 || m_tSimMode == 1) {
323  int trigBin = 0;
324  if (m_simClockState.isValid()) {
325  trigBin = m_simClockState->getCDCTriggerBin(m_offsetForTriggerBin);
326  } else {
327  if (m_tSimMode == 0) {
328  B2DEBUG(m_debugLevel, "SimClockState unavailable so switched the mode from synchro to random.");
329  m_tSimMode = 1;
330  }
331  trigBin = gRandom->Integer(4);
332  }
333  if (trigBin < 0 || trigBin > 3) B2ERROR("Invalid trigger bin; must be an integer [0,3]!");
334  unsigned short offs = 8 * trigBin + m_trgTimingOffsetInCount;
335  B2DEBUG(m_debugLevel, "tSimMode,trigBin,offs= " << m_tSimMode << " " << trigBin << " " << offs);
336 
337  //TODO: simplify the following 7 lines and setFEElectronics()
338  for (unsigned short bd = 1; bd < nBoards; ++bd) {
339  const short tMaxInCount = 32 * (m_shiftOfTimeWindowIn32Count - m_trgDelayInCount[bd]) - offs;
340  const short tMinInCount = tMaxInCount - 32 * m_widthOfTimeWindowInCount[bd];
341  B2DEBUG(m_debugLevel, bd << " " << tMinInCount << " " << tMaxInCount);
342  m_uprEdgeOfTimeWindow[bd] = m_tdcBinWidth * tMaxInCount;
343  m_lowEdgeOfTimeWindow[bd] = m_tdcBinWidth * tMinInCount;
344  }
345  }
346 
347  // Set trigger timing jitter for this event
348  double trigTiming = m_trigTimeJitter == 0. ? 0. : m_trigTimeJitter * (gRandom->Uniform() - 0.5);
349  // std::cout << "trigTiming= " << trigTiming << std::endl;
350  // Loop over all hits
351  int nHits = m_simHits.getEntries();
352  B2DEBUG(m_debugLevel, "Number of CDCSimHits in the current event: " << nHits);
353  for (int iHits = 0; iHits < nHits; ++iHits) {
354  // Get a hit
355  m_aCDCSimHit = m_simHits[iHits];
356 
357  // Hit geom. info
358  m_wireID = m_aCDCSimHit->getWireID();
359  // B2DEBUG(29, "Encoded wire number of current CDCSimHit: " << m_wireID);
360 
361  m_posFlag = m_aCDCSimHit->getLeftRightPassageRaw();
362  m_boardID = m_cdcgp->getBoardID(m_wireID);
363  // B2DEBUG(29, "m_boardID= " << m_boardID);
364  m_posWire = m_aCDCSimHit->getPosWire();
365  m_posTrack = m_aCDCSimHit->getPosTrack();
366  m_momentum = m_aCDCSimHit->getMomentum();
367  m_flightTime = m_aCDCSimHit->getFlightTime();
368  m_globalTime = m_aCDCSimHit->getGlobalTime();
369  m_driftLength = m_aCDCSimHit->getDriftLength() * Unit::cm;
370 
371  //include alignment effects
372  //basically align flag should be always on since on/off is controlled by the input alignment.xml file itself.
373  m_align = true;
374 
375  TVector3 bwpAlign = m_cdcgp->wireBackwardPosition(m_wireID, CDCGeometryPar::c_Aligned);
376  TVector3 fwpAlign = m_cdcgp->wireForwardPosition(m_wireID, CDCGeometryPar::c_Aligned);
377 
378  TVector3 bwp = m_cdcgp->wireBackwardPosition(m_wireID);
379  TVector3 fwp = m_cdcgp->wireForwardPosition(m_wireID);
380 
381  //skip correction for wire-position alignment if unnecessary
382  if ((bwpAlign - bwp).Mag() == 0. && (fwpAlign - fwp).Mag() == 0.) m_align = false;
383  // std::cout << "a m_align= " << m_align << std::endl;
384 
385  if (m_align || m_correctForWireSag) {
386 
387  bwp = bwpAlign;
388  fwp = fwpAlign;
389 
390  if (m_correctForWireSag) {
391  double zpos = m_posWire.z();
392  double bckYSag = bwp.y();
393  double forYSag = fwp.y();
394 
395  // CDCGeometryPar::EWirePosition set = m_align ?
396  // CDCGeometryPar::c_Aligned : CDCGeometryPar::c_Base;
397  CDCGeometryPar::EWirePosition set = CDCGeometryPar::c_Aligned;
398  const int layerID = m_wireID.getICLayer();
399  const int wireID = m_wireID.getIWire();
400  m_cdcgp->getWireSagEffect(set, layerID, wireID, zpos, bckYSag, forYSag);
401  bwp.SetY(bckYSag);
402  fwp.SetY(forYSag);
403  }
404 
405  const TVector3 L = 5. * m_momentum.Unit(); //(cm) tentative
406  TVector3 posIn = m_posTrack - L;
407  TVector3 posOut = m_posTrack + L;
408  TVector3 posTrack = m_posTrack;
409  TVector3 posWire = m_posWire;
410 
411  // m_driftLength = m_cdcgp->ClosestApproach(bwp, fwp, posIn, posOut, posTrack, posWire);
412  m_driftLength = ClosestApproach(bwp, fwp, posIn, posOut, posTrack, posWire);
413  // std::cout << "base-dl, sag-dl, diff= " << m_aCDCSimHit->getDriftLength() <<" "<< m_driftLength <<" "<< m_driftLength - m_aCDCSimHit->getDriftLength() << std::endl;
414  m_posTrack = posTrack;
415  m_posWire = posWire;
416 
417  double deltaTime = 0.; //tentative (probably ok...)
418  // double deltaTime = (posTrack - m_posTrack).Mag() / speed;
419  m_flightTime += deltaTime;
420  m_globalTime += deltaTime;
421  m_posFlag = m_cdcgp->getNewLeftRightRaw(m_posWire, m_posTrack, m_momentum);
422  }
423 
424  // Calculate measurement time.
425  // Smear drift length
426  double hitDriftLength = m_driftLength;
427  double dDdt = getdDdt(hitDriftLength);
428  if (m_doSmearing) {
429  hitDriftLength = smearDriftLength(hitDriftLength, dDdt);
430  }
431 
432  //set flags
433  bool addTof = m_addTimeOfFlight4Bg;
434  bool addDelay = m_addInWirePropagationDelay4Bg;
435  if (m_aCDCSimHit->getBackgroundTag() == 0) {
436  addTof = m_addTimeOfFlight;
437  addDelay = m_addInWirePropagationDelay;
438  }
439  double hitDriftTime = getDriftTime(hitDriftLength, addTof, addDelay);
440 
441  //add randamized event time for a beam bg. hit
442  if (m_aCDCSimHit->getBackgroundTag() != 0) {
443  hitDriftTime += m_globalTime - m_flightTime;
444  }
445 
446  //add trigger timing jitter
447  hitDriftTime += trigTiming;
448 
449  //apply time window cut
450  double tMin = m_tMin;
451  double tMax = m_tMaxOuter;
452  if (m_wireID.getISuperLayer() == 0) tMax = m_tMaxInner;
453  if (m_tSimMode <= 2) {
454  tMin = m_lowEdgeOfTimeWindow[m_boardID];
455  tMax = m_uprEdgeOfTimeWindow[m_boardID];
456  }
457  if (hitDriftTime < tMin || hitDriftTime > tMax) continue;
458 
459  //Sum ADC count
460  const double stepLength = m_aCDCSimHit->getStepLength() * Unit::cm;
461  const double costh = m_momentum.z() / m_momentum.Mag();
462  double hitdE = m_aCDCSimHit->getEnergyDep();
463  if (m_cdcgp->getMaterialDefinitionMode() != 2) { // for non wire-by-wire mode
464  static EDepInGas& edpg = EDepInGas::getInstance();
465  hitdE = edpg.getEDepInGas(m_eDepInGasMode, m_aCDCSimHit->getPDGCode(), m_momentum.Mag(), stepLength, hitdE);
466  }
467 
468  double convFactorForThreshold = 1;
469  //TODO: modify the following function so that it can output timing signal in Volt in future
470  unsigned short adcCount = 0;
471  makeSignalsAfterShapers(m_wireID, hitdE, stepLength, costh, adcCount, convFactorForThreshold);
472  const unsigned short adcTh = m_useDB4FEE ? m_adcThresh[m_boardID] : m_adcThreshold;
473  // B2DEBUG(29, "adcTh,adcCount,convFactorForThreshold= " << adcTh <<" "<< adcCount <<" "<< convFactorForThreshold);
474  if (adcCount < adcTh) adcCount = 0;
475  iterADCMap = adcMap.find(m_wireID);
476  if (iterADCMap == adcMap.end()) {
477  adcMap.insert(make_pair(m_wireID, adcCount));
478  // adcMap.insert(make_pair(m_wireID, hitdE));
479  } else {
480  iterADCMap->second += adcCount;
481  // iterADCMap->second += hitdE;
482  }
483 
484  //Apply energy threshold
485  // If hitdE < dEThreshold, the hit is ignored
486  // M. Uchida 2012.08.31
487  double dEThreshold = 0.;
488  if (m_useDB4FEE && m_useDB4EDepToADC) {
489  dEThreshold = m_tdcThresh[m_boardID] / convFactorForThreshold * Unit::keV;
490  } else {
491  dEThreshold = (m_wireID.getISuperLayer() == 0) ? m_tdcThreshold4Inner : m_tdcThreshold4Outer;
492  dEThreshold *= Unit::eV;
493  }
494  B2DEBUG(m_debugLevel, "hitdE,dEThreshold,driftLength " << hitdE << " " << dEThreshold << " " << hitDriftLength);
495 
496  if (hitdE < dEThreshold) {
497  B2DEBUG(m_debugLevel, "Below Ethreshold: " << hitdE << " " << dEThreshold);
498  continue;
499  }
500 
501  // add one hit per trigger time window to the trigger signal map
502  unsigned short trigWindow = floor((hitDriftTime - tMin) * m_tdcBinWidthInv / 32);
503  iterSignalMapTrg = signalMapTrg.find(make_pair(m_wireID, trigWindow));
504  if (iterSignalMapTrg == signalMapTrg.end()) {
505  // signalMapTrg.insert(make_pair(make_pair(m_wireID, trigWindow),
506  // SignalInfo(iHits, hitDriftTime, hitdE)));
507  signalMapTrg.insert(make_pair(make_pair(m_wireID, trigWindow),
508  SignalInfo(iHits, hitDriftTime, adcCount)));
509  } else {
510  if (hitDriftTime < iterSignalMapTrg->second.m_driftTime) {
511  iterSignalMapTrg->second.m_driftTime = hitDriftTime;
512  iterSignalMapTrg->second.m_simHitIndex = iHits;
513  }
514  // iterSignalMapTrg->second.m_charge += hitdE;
515  iterSignalMapTrg->second.m_charge += adcCount;
516  }
517 
518  // Reject totally-dead wire; to be replaced by isDeadWire() in future
519  // N.B. The following lines for badwire must be after the above lines for trigger becuse badwires are different between trigger and tracking.
520  // Badwires for trigger are taken into account separately in the tsim module
521  if (m_cdcgp->isBadWire(m_wireID)) {
522  // std::cout<<"badwire= " << m_wireID.getICLayer() <<" "<< m_wireID.getIWire() << std::endl;
523  continue;
524  }
525  // Reject partly-dead wire as well
526  double eff = 1.;
527  if (m_cdcgp->isDeadWire(m_wireID, eff)) {
528  // std::cout << "wid,eff= " << m_wireID << " " << eff << std::endl;
529  if (eff < gRandom->Uniform()) continue;
530  }
531 
532  // For TOT simulation, calculate drift length from In to the wire, and Out to the wire. The calculation is apprximate ignoring wire sag (this would be ok because TOT simulation is not required to be so accurate).
533  const double a = bwpAlign.X();
534  const double b = bwpAlign.Y();
535  const double c = bwpAlign.Z();
536  const TVector3 fmbAlign = fwpAlign - bwpAlign;
537  const double lmn = 1. / fmbAlign.Mag();
538  const double l = fmbAlign.X() * lmn;
539  const double m = fmbAlign.Y() * lmn;
540  const double n = fmbAlign.Z() * lmn;
541 
542  double dx = m_aCDCSimHit->getPosIn().X() - a;
543  double dy = m_aCDCSimHit->getPosIn().Y() - b;
544  double dz = m_aCDCSimHit->getPosIn().Z() - c;
545  double sub = l * dx + m * dy + n * dz;
546  const double driftLFromIn = sqrt(dx * dx + dy * dy + dz * dz - sub * sub);
547 
548  dx = m_aCDCSimHit->getPosOut().X() - a;
549  dy = m_aCDCSimHit->getPosOut().Y() - b;
550  dz = m_aCDCSimHit->getPosOut().Z() - c;
551  sub = l * dx + m * dy + n * dz;
552  const double driftLFromOut = sqrt(dx * dx + dy * dy + dz * dz - sub * sub);
553 
554  const double maxDriftL = std::max(driftLFromIn, driftLFromOut);
555  const double minDriftL = m_driftLength;
556  B2DEBUG(m_debugLevel, "driftLFromIn= " << driftLFromIn << " driftLFromOut= " << driftLFromOut << " minDriftL= " << minDriftL <<
557  " maxDriftL= "
558  <<
559  maxDriftL << "m_driftLength= " << m_driftLength);
560 
561  iterSignalMap = signalMap.find(m_wireID);
562 
563  if (iterSignalMap == signalMap.end()) {
564  // new entry
565  // signalMap.insert(make_pair(m_wireID, SignalInfo(iHits, hitDriftTime, hitdE)));
566  signalMap.insert(make_pair(m_wireID, SignalInfo(iHits, hitDriftTime, adcCount, maxDriftL, minDriftL)));
567  B2DEBUG(m_debugLevel, "Creating new Signal with encoded wire number: " << m_wireID);
568  } else {
569  // ... smallest drift time has to be checked, ...
570  if (hitDriftTime < iterSignalMap->second.m_driftTime) {
571  iterSignalMap->second.m_driftTime3 = iterSignalMap->second.m_driftTime2;
572  iterSignalMap->second.m_simHitIndex3 = iterSignalMap->second.m_simHitIndex2;
573  iterSignalMap->second.m_driftTime2 = iterSignalMap->second.m_driftTime;
574  iterSignalMap->second.m_simHitIndex2 = iterSignalMap->second.m_simHitIndex;
575  iterSignalMap->second.m_driftTime = hitDriftTime;
576  iterSignalMap->second.m_simHitIndex = iHits;
577  B2DEBUG(m_debugLevel, "hitDriftTime of current Signal: " << hitDriftTime << ", hitDriftLength: " << hitDriftLength);
578  } else if (hitDriftTime < iterSignalMap->second.m_driftTime2) {
579  iterSignalMap->second.m_driftTime3 = iterSignalMap->second.m_driftTime2;
580  iterSignalMap->second.m_simHitIndex3 = iterSignalMap->second.m_simHitIndex2;
581  iterSignalMap->second.m_driftTime2 = hitDriftTime;
582  iterSignalMap->second.m_simHitIndex2 = iHits;
583  } else if (hitDriftTime < iterSignalMap->second.m_driftTime3) {
584  iterSignalMap->second.m_driftTime3 = hitDriftTime;
585  iterSignalMap->second.m_simHitIndex3 = iHits;
586  }
587  // ... total charge has to be updated.
588  // iterSignalMap->second.m_charge += hitdE;
589  iterSignalMap->second.m_charge += adcCount;
590 
591  // set max and min driftLs
592  if (iterSignalMap->second.m_maxDriftL < maxDriftL) iterSignalMap->second.m_maxDriftL = maxDriftL;
593  if (iterSignalMap->second.m_minDriftL > minDriftL) iterSignalMap->second.m_minDriftL = minDriftL;
594  B2DEBUG(m_debugLevel, "maxDriftL in struct= " << iterSignalMap->second.m_maxDriftL << "minDriftL in struct= " <<
595  iterSignalMap->second.m_minDriftL);
596  }
597 
598  } // end loop over SimHits.
599 
600  //--- Now Store the results into CDCHits and
601  // create corresponding relations between SimHits and CDCHits.
602 
603  unsigned int iCDCHits = 0;
604  RelationArray cdcSimHitsToCDCHits(m_simHits, m_cdcHits); //SimHit<->CDCHit
605  RelationArray mcParticlesToCDCHits(m_mcParticles, m_cdcHits); //MCParticle<->CDCHit
606 
607  for (iterSignalMap = signalMap.begin(); iterSignalMap != signalMap.end(); ++iterSignalMap) {
608 
609  //add time-walk (here for simplicity)
610  // unsigned short adcCount = getADCCount(iterSignalMap->second.m_charge);
611  // unsigned short adcCount = iterSignalMap->second.m_charge;
612  iterADCMap = adcMap.find(iterSignalMap->first);
613  unsigned short adcCount = iterADCMap != adcMap.end() ? iterADCMap->second : 0;
614  /*
615  unsigned short adcCount = 0;
616  if (iterADCMap != adcMap.end()) {
617  adcCount = getADCCount(iterSignalMap->first, iterADCMap->second, 1., 0.);
618  unsigned short boardID = m_cdcgp->getBoardID(iterSignalMap->first);
619  // B2DEBUG(29, "boardID= " << boardID);
620  const unsigned short adcTh = m_useDB4FEE ? m_adcThresh[boardID] : m_adcThreshold;
621  if (adcCount < adcTh) adcCount = 0;
622  }
623  */
624 
625  if (m_addTimeWalk) {
626  B2DEBUG(m_debugLevel, "timewalk= " << m_cdcgp->getTimeWalk(iterSignalMap->first, adcCount));
627  iterSignalMap->second.m_driftTime += m_cdcgp->getTimeWalk(iterSignalMap->first, adcCount);
628  }
629 
630  //remove negative drift time (TDC) upon request
631  if (!m_outputNegativeDriftTime &&
632  iterSignalMap->second.m_driftTime < 0.) {
633  continue;
634  }
635 
636  //N.B. No bias (+ or -0.5 count) is introduced on average in digitization by the real TDC (info. from KEK electronics division). So round off (t0 - drifttime) below.
637  unsigned short tdcCount = static_cast<unsigned short>((getPositiveT0(iterSignalMap->first) - iterSignalMap->second.m_driftTime) *
638  m_tdcBinWidthInv + 0.5);
639 
640  //calculate tot; hard-coded currently
641  double deltaDL = iterSignalMap->second.m_maxDriftL - iterSignalMap->second.m_minDriftL;
642  if (deltaDL < 0.) {
643  B2DEBUG(m_debugLevel, "negative deltaDL= " << deltaDL);
644  deltaDL = 0.;
645  }
646  const unsigned short boardID = m_cdcgp->getBoardID(iterSignalMap->first);
647  unsigned short tot = std::min(std::round(5.92749 * deltaDL + 2.59706), static_cast<double>(m_widthOfTimeWindowInCount[boardID]));
648  if (m_adcThresh[boardID] > 0) {
649  tot = std::min(static_cast<int>(tot), static_cast<int>(adcCount / m_adcThresh[boardID]));
650  }
651 
652  CDCHit* firstHit = m_cdcHits.appendNew(tdcCount, adcCount, iterSignalMap->first, 0, tot);
653  // std::cout <<"firsthit?= " << firstHit->is2ndHit() << std::endl;
654  //set a relation: CDCSimHit -> CDCHit
655  cdcSimHitsToCDCHits.add(iterSignalMap->second.m_simHitIndex, iCDCHits);
656 
657  //set a relation: MCParticle -> CDCHit
658  RelationVector<MCParticle> rels = m_simHits[iterSignalMap->second.m_simHitIndex]->getRelationsFrom<MCParticle>();
659  if (rels.size() != 0) {
660  //assumption: only one MCParticle
661  const MCParticle* mcparticle = rels[0];
662  double weight = rels.weight(0);
663  mcparticle->addRelationTo(firstHit, weight);
664  }
665 
666  //Set 2nd-hit related things if it exists
667  if (m_output2ndHit && iterSignalMap->second.m_simHitIndex2 >= 0) {
668  unsigned short tdcCount2 = static_cast<unsigned short>((getPositiveT0(iterSignalMap->first) - iterSignalMap->second.m_driftTime2) *
669  m_tdcBinWidthInv + 0.5);
670  if (tdcCount2 != tdcCount) {
671  CDCHit* secondHit = m_cdcHits.appendNew(tdcCount2, adcCount, iterSignalMap->first, 0, tot);
672  secondHit->set2ndHitFlag();
673  secondHit->setOtherHitIndices(firstHit);
674  // std::cout <<"2ndhit?= " << secondHit->is2ndHit() << std::endl;
675  // std::cout <<"1st-otherhitindex= " << firstHit->getOtherHitIndex() << std::endl;
676  // std::cout <<"2nd-otherhitindex= " << secondHit->getOtherHitIndex() << std::endl;
677  // secondHit->setOtherHitIndex(firstHit->getArrayIndex());
678  // firstHit->setOtherHitIndex(secondHit->getArrayIndex());
679  // std::cout <<"1st-otherhitindex= " << firstHit->getOtherHitIndex() << std::endl;
680  // std::cout <<"2nd-otherhitindex= " << secondHit->getOtherHitIndex() << std::endl;
681 
682  //set a relation: CDCSimHit -> CDCHit
683  ++iCDCHits;
684  cdcSimHitsToCDCHits.add(iterSignalMap->second.m_simHitIndex2, iCDCHits);
685  // std::cout << "settdc2 " << firstHit->getTDCCount() << " " << secondHit->getTDCCount() << std::endl;
686 
687  //set a relation: MCParticle -> CDCHit
688  rels = m_simHits[iterSignalMap->second.m_simHitIndex2]->getRelationsFrom<MCParticle>();
689  if (rels.size() != 0) {
690  //assumption: only one MCParticle
691  const MCParticle* mcparticle = rels[0];
692  double weight = rels.weight(0);
693  mcparticle->addRelationTo(secondHit, weight);
694  }
695  } else { //Check the 3rd hit when tdcCount = tdcCount2
696  // std::cout << "tdcCount1=2" << std::endl;
697  if (iterSignalMap->second.m_simHitIndex3 >= 0) {
698  unsigned short tdcCount3 = static_cast<unsigned short>((getPositiveT0(iterSignalMap->first) - iterSignalMap->second.m_driftTime3) *
699  m_tdcBinWidthInv + 0.5);
700  // std::cout << "tdcCount3= " << tdcCount3 << " " << tdcCount << std::endl;
701  if (tdcCount3 != tdcCount) {
702  CDCHit* secondHit = m_cdcHits.appendNew(tdcCount3, adcCount, iterSignalMap->first, 0, tot);
703  secondHit->set2ndHitFlag();
704  secondHit->setOtherHitIndices(firstHit);
705  // secondHit->setOtherHitIndex(firstHit->getArrayIndex());
706  // firstHit->setOtherHitIndex(secondHit->getArrayIndex());
707  // std::cout <<"2ndhit?= " << secondHit->is2ndHit() << std::endl;
708 
709  //set a relation: CDCSimHit -> CDCHit
710  ++iCDCHits;
711  cdcSimHitsToCDCHits.add(iterSignalMap->second.m_simHitIndex3, iCDCHits);
712  // std::cout << "settdc3 " << firstHit->getTDCCount() << " " << secondHit->getTDCCount() << std::endl;
713 
714  //set a relation: MCParticle -> CDCHit
715  rels = m_simHits[iterSignalMap->second.m_simHitIndex3]->getRelationsFrom<MCParticle>();
716  if (rels.size() != 0) {
717  //assumption: only one MCParticle
718  const MCParticle* mcparticle = rels[0];
719  double weight = rels.weight(0);
720  mcparticle->addRelationTo(secondHit, weight);
721  }
722  }
723  }
724  } //end of checking tdcCount 1=2 ?
725  } //end of 2nd hit setting
726 
727  // std::cout <<"t0= " << m_cdcgp->getT0(iterSignalMap->first) << std::endl;
728  /* unsigned short tdcInCommonStop = static_cast<unsigned short>((m_tdcOffset - iterSignalMap->second.m_driftTime) * m_tdcBinWidthInv);
729  float driftTimeFromTDC = static_cast<float>(m_tdcOffset - (tdcInCommonStop + 0.5)) * m_tdcBinWidth;
730  std::cout <<"driftT bf digitization, TDC in common stop, digitized driftT = " << iterSignalMap->second.m_driftTime <<" "<< tdcInCommonStop <<" "<< driftTimeFromTDC << std::endl;
731  */
732  ++iCDCHits;
733  }
734 
735  //Add crosstalk
736  if (m_addXTalk) addXTalk();
737 
738  // Store the results with trigger time window in a separate array
739  // with corresponding relations.
740  for (iterSignalMapTrg = signalMapTrg.begin(); iterSignalMapTrg != signalMapTrg.end(); ++iterSignalMapTrg) {
741  /*
742  unsigned short adcCount = getADCCount(iterSignalMapTrg->first.first, iterSignalMapTrg->second.m_charge, 1., 0.);
743  unsigned short boardID = m_cdcgp->getBoardID(iterSignalMapTrg->first.first);
744  // B2DEBUG(29, "boardID= " << boardID);
745  const unsigned short adcTh = m_useDB4FEE ? m_adcThresh[boardID] : m_adcThreshold;
746  if (adcCount < adcTh) adcCount = 0;
747  */
748  // unsigned short adcCount = getADCCount(iterSignalMapTrg->second.m_charge);
749  unsigned short adcCount = iterSignalMapTrg->second.m_charge;
750  unsigned short tdcCount =
751  static_cast<unsigned short>((getPositiveT0(iterSignalMapTrg->first.first) -
752  iterSignalMapTrg->second.m_driftTime) * m_tdcBinWidthInv + 0.5);
753  const CDCHit* cdcHit = m_cdcHits4Trg.appendNew(tdcCount, adcCount, iterSignalMapTrg->first.first);
754 
755  // relations
756  m_simHits[iterSignalMapTrg->second.m_simHitIndex]->addRelationTo(cdcHit);
757  RelationVector<MCParticle> rels = m_simHits[iterSignalMapTrg->second.m_simHitIndex]->getRelationsFrom<MCParticle>();
758  if (rels.size() != 0) {
759  //assumption: only one MCParticle
760  const MCParticle* mcparticle = rels[0];
761  double weight = rels.weight(0);
762  mcparticle->addRelationTo(cdcHit, weight);
763  }
764  }
765 
766  /*
767  std::cout << " " << std::endl;
768  RelationIndex<MCParticle, CDCHit> mcp_to_hit(mcParticles, cdcHits);
769  if (!mcp_to_hit) B2FATAL("No MCParticle -> CDCHit relation founf!");
770  typedef RelationIndex<MCParticle, CDCHit>::Element RelationElement;
771  int ncdcHits = cdcHits.getEntries();
772  for (int j = 0; j < ncdcHits; ++j) {
773  for (const RelationElement& rel : mcp_to_hit.getElementsTo(cdcHits[j])) {
774  std::cout << j << " " << cdcHits[j]->is2ndHit() <<" "<< rel.from->getIndex() << " " << rel.weight << std::endl;
775  }
776  }
777  */
778 }
779 
780 double CDCDigitizerModule::smearDriftLength(const double driftLength, const double dDdt)
781 {
782  double mean = 0.;
783  double resolution;
784 
785  if (m_useSimpleDigitization) {
786  if (gRandom->Uniform() <= m_fraction) {
787  mean = m_mean1;
788  resolution = m_resolution1;
789  } else {
790  mean = m_mean2;
791  resolution = m_resolution2;
792  }
793  } else {
794  const unsigned short leftRight = m_posFlag;
795  double alpha = m_cdcgp->getAlpha(m_posWire, m_momentum);
796  double theta = m_cdcgp->getTheta(m_momentum);
797  resolution = m_cdcgp->getSigma(driftLength, m_wireID.getICLayer(), leftRight, alpha, theta);
798  resolution *= m_totalFudgeFactor;
799  }
800 
801  //subtract resol. due to digitization, which'll be added later in the digitization
802 
803  double diff = resolution - dDdt * m_tdcResol;
804  if (diff > 0.) {
805  resolution = sqrt(diff * (resolution + dDdt * m_tdcResol));
806  } else {
807  resolution = 0.;
808  }
809 
810 #if defined(CDC_DEBUG)
811  cout << " " << endl;
812  cout << "CDCDigitizerModule::smearDriftLength" << endl;
813  cout << "tdcResol= " << m_tdcResol << endl;
814  cout << "dDdt,resolution= " << dDdt << " " << resolution << endl;
815 #endif
816 
817  // Smear drift length
818  double newDL = gRandom->Gaus(driftLength + mean , resolution);
819  while (newDL <= 0.) newDL = gRandom->Gaus(driftLength + mean, resolution);
820  // cout << "totalFugeF in Digi= " << m_totalFudgeFactor << endl;
821  return newDL;
822 }
823 
824 
825 double CDCDigitizerModule::getdDdt(const double driftL)
826 {
827  //---------------------------------------------------------------------------------
828  // Calculates the 1'st derivative: dD/dt, where D: drift length before smearing; t: drift time
829  //---------------------------------------------------------------------------------
830 
831  double dDdt = m_driftV;
832 
833  if (!m_useSimpleDigitization) {
834  const unsigned short layer = m_wireID.getICLayer();
835  const unsigned short leftRight = m_posFlag;
836  double alpha = m_cdcgp->getAlpha(m_posWire, m_momentum);
837  double theta = m_cdcgp->getTheta(m_momentum);
838  double t = m_cdcgp->getDriftTime(driftL, layer, leftRight, alpha, theta);
839  dDdt = m_cdcgp->getDriftV(t, layer, leftRight, alpha, theta);
840 
841 #if defined(CDC_DEBUG)
842  cout << " " << endl;
843  cout << "CDCDigitizerModule::getdDdt" << endl;
844  cout << "**layer= " << layer << endl;
845  cout << "alpha= " << 180.*alpha / M_PI << std::endl;
846  if (layer == 55) {
847  int lr = 0;
848  for (int i = 0; i < 1000; ++i) {
849  t = 1.0 * i;
850  double d = m_cdcgp->getDriftLength(t, layer, lr, alpha, theta);
851  cout << t << " " << d << endl;
852  }
853 
854  cout << " " << endl;
855 
856  lr = 1;
857  for (int i = 0; i < 100; ++i) {
858  t = 5 * i;
859  double d = m_cdcgp->getDriftLength(t, layer, lr, alpha, theta);
860  cout << t << " " << d << endl;
861  }
862  exit(-1);
863  }
864 #endif
865  }
866 
867  return dDdt;
868 }
869 
870 
871 double CDCDigitizerModule::getDriftTime(const double driftLength, const bool addTof, const bool addDelay)
872 {
873  //---------------------------------------------------------------------------------
874  // Method returning electron drift time (parameters: position in cm)
875  // T(drift) = TOF + T(true drift time) + T(propagation delay in wire) - T(event),
876  // T(event) is a timing of event, which includes a time jitter due to
877  // the trigger system.
878  //---------------------------------------------------------------------------------
879 
880  double driftT = 0.;
881 
882  if (m_useSimpleDigitization) {
883  driftT = (driftLength / Unit::cm) * m_driftVInv;
884 
885 #if defined(CDC_DEBUG)
886  cout << " " << endl;
887  cout << "CDCDigitizerModule::getDriftTime" << endl;
888  cout << "driftvinv= " << m_driftVInv << endl;
889 #endif
890  } else {
891  const unsigned short layer = m_wireID.getICLayer();
892  const unsigned short leftRight = m_posFlag;
893  double alpha = m_cdcgp->getAlpha(m_posWire, m_momentum);
894  double theta = m_cdcgp->getTheta(m_momentum);
895  driftT = m_cdcgp->getDriftTime(driftLength, layer, leftRight, alpha, theta);
896  // std::cout <<"alpha,theta,driftT= " << alpha <<" "<< theta <<" "<< driftT << std::endl;
897  }
898 
899  if (addTof) {
900  driftT += m_flightTime; // in ns
901  }
902 
903  if (addDelay) {
904  //calculate signal propagation length in the wire
905  CDCGeometryPar::EWirePosition set = m_align ? CDCGeometryPar::c_Aligned : CDCGeometryPar::c_Base;
906  TVector3 backWirePos = m_cdcgp->wireBackwardPosition(m_wireID, set);
907 
908  double propLength = (m_posWire - backWirePos).Mag();
909  // if (m_cdcgp->getSenseWireZposMode() == 1) {
910  //TODO: replace the following with cached reference
911  // std::cout << m_gcp->getInstance().getSenseWireZposMode() << std::endl;
912  if (m_gcp->getSenseWireZposMode() == 1) {
913  const unsigned short layer = m_wireID.getICLayer();
914  propLength += m_cdcgp->getBwdDeltaZ(layer);
915  }
916  // B2DEBUG(29, "Propagation in wire length: " << propLength);
917 
918  if (m_useSimpleDigitization) {
919  driftT += (propLength / Unit::cm) * m_propSpeedInv;
920 
921 #if defined(CDC_DEBUG)
922  cout << "pseedinv= " << m_propSpeedInv << endl;
923 #endif
924  } else {
925  const unsigned short layer = m_wireID.getICLayer();
926  driftT += (propLength / Unit::cm) * m_cdcgp->getPropSpeedInv(layer);
927 #if defined(CDC_DEBUG)
928  cout << "layer,pseedinv= " << layer << " " << m_cdcgp->getPropSpeedInv(layer) << endl;
929 #endif
930  }
931  }
932 
933  return driftT;
934 }
935 
936 
937 void CDCDigitizerModule::makeSignalsAfterShapers(const WireID& wid, double dEinGeV, double dx, double costh,
938  unsigned short& adcCount, double& convFactorForThreshold)
939 {
940  static double conv00 = (100.0 / 3.2); //keV -> coun (original from some test beam results)
941  convFactorForThreshold = conv00;
942  adcCount = 0;
943  if (dEinGeV <= 0. || dx <= 0.) return;
944 
945  const unsigned short layer = wid.getICLayer();
946  const unsigned short cell = wid.getIWire();
947  double dEInkeV = dEinGeV / Unit::keV;
948 
949  double conv = conv00;
950  if (m_spaceChargeEffect) {
951  if (m_useDB4EDepToADC) {
952  conv = m_cdcgp->getEDepToADCConvFactor(layer, cell, dEInkeV, dx, costh);
953  double conv0 = m_cdcgp->getEDepToADCMainFactor(layer, cell, costh);
954  convFactorForThreshold = (conv0 + m_degOfSPEOnThreshold * (conv - conv0));
955  }
956  } else {
957  if (m_useDB4EDepToADC) conv = m_cdcgp->getEDepToADCMainFactor(layer, cell, costh);
958  convFactorForThreshold = conv;
959  }
960 
961  if (convFactorForThreshold > 0.) {
962  convFactorForThreshold *= getSemiTotalGain(layer, cell);
963  } else {
964  convFactorForThreshold = conv00;
965  }
966 
967  if (m_gasGainSmearing) {
968  //TODO: replace the following sum with a gaussian for large nElectrons if gas-gain smearing turns out to be important
969  const double nElectrons = dEInkeV / m_effWForGasGainSmearing;
970  double relGain = 0;
971  if (nElectrons >= 1) {
972  for (int i = 1; i <= nElectrons; ++i) {
973  relGain += Polya();
974  }
975  relGain /= nElectrons;
976  } else {
977  relGain = 1;
978  }
979  conv *= relGain;
980  }
981 
982  if (m_extraADCSmearing) {
983  conv *= max(0., gRandom->Gaus(1., m_cdcgp->getEDepToADCSigma(layer, cell)));
984  }
985 
986  conv *= getSemiTotalGain(layer, cell);
987 
988  //The ADCcount is obtained by rounding-up (measured voltage)/bin in real ADC. This is true both for pedestal and signal voltages, so the pedestal-subtracted ADCcount (simulated here) is rounded.
989  adcCount = static_cast<unsigned short>(std::round(conv * dEInkeV));
990  return;
991 }
992 
993 
994 double CDCDigitizerModule::Polya(double xmax)
995 {
996  double x = 0;
997  double y = 1;
998  double fx = 0;
999  double urndm[2];
1000  static double ymax = pow(m_thetaOfPolya, m_thetaOfPolya) * exp(-m_thetaOfPolya);
1001  while (y > fx) {
1002  gRandom->RndmArray(2, urndm);
1003  x = xmax * urndm[0];
1004  double a = (1 + m_thetaOfPolya) * x;
1005  fx = pow(a, m_thetaOfPolya) * exp(-a);
1006  y = ymax * urndm[1];
1007  }
1008  return x;
1009 }
1010 
1011 
1012 // Set FEE parameters (from DB)
1013 void CDCDigitizerModule::setFEElectronics()
1014 {
1015  const double& off = m_tdcThresholdOffset;
1016  const double& gA = m_analogGain;
1017  const double& gD = m_digitalGain;
1018  const double& adcBW = m_adcBinWidth;
1019  const double convF = gA / gD / adcBW;
1020  const double el1TrgLatency = m_cdcgp->getMeanT0(); // ns
1021  B2DEBUG(m_debugLevel, "L1TRGLatency= " << el1TrgLatency);
1022  const double c = 32. * m_tdcBinWidth;
1023 
1024  if (!m_fEElectronicsFromDB) B2FATAL("No FEEElectronics dbobject!");
1025  const CDCFEElectronics& fp = *((*m_fEElectronicsFromDB)[0]);
1026  int mode = (fp.getBoardID() == -1) ? 1 : 0;
1027  int iNBoards = static_cast<int>(nBoards);
1028 
1029  //set typical values for all channels first if mode=1
1030  if (mode == 1) {
1031  for (int bdi = 1; bdi < iNBoards; ++bdi) {
1032  m_uprEdgeOfTimeWindow[bdi] = el1TrgLatency - c * (fp.getTrgDelay() + 1);
1033  if (m_uprEdgeOfTimeWindow[bdi] < 0.) B2FATAL("CDCDigitizer: Upper edge of time window < 0!");
1034  m_lowEdgeOfTimeWindow[bdi] = m_uprEdgeOfTimeWindow[bdi] - c * (fp.getWidthOfTimeWindow() + 1);
1035  if (m_lowEdgeOfTimeWindow[bdi] > 0.) B2FATAL("CDCDigitizer: Lower edge of time window > 0!");
1036  m_adcThresh[bdi] = fp.getADCThresh();
1037  m_tdcThresh[bdi] = convF * (off - fp.getTDCThreshInMV());
1038  m_widthOfTimeWindowInCount[bdi] = fp.getWidthOfTimeWindow() + 1;
1039  m_trgDelayInCount [bdi] = fp.getTrgDelay();
1040  }
1041  }
1042 
1043  //ovewrite values for specific channels if mode=1
1044  //set typical values for all channels if mode=0
1045  for (const auto& fpp : (*m_fEElectronicsFromDB)) {
1046  int bdi = fpp.getBoardID();
1047  if (mode == 0 && bdi == 0) continue; //bdi=0 is dummy (not used)
1048  if (mode == 1 && bdi == -1) continue; //skip typical case
1049  if (bdi < 0 || bdi >= iNBoards) B2FATAL("CDCDigitizer:: Invalid no. of FEE board!");
1050  m_uprEdgeOfTimeWindow[bdi] = el1TrgLatency - c * (fpp.getTrgDelay() + 1);
1051  if (m_uprEdgeOfTimeWindow[bdi] < 0.) B2FATAL("CDCDigitizer: Upper edge of time window < 0!");
1052  m_lowEdgeOfTimeWindow[bdi] = m_uprEdgeOfTimeWindow[bdi] - c * (fpp.getWidthOfTimeWindow() + 1);
1053  if (m_lowEdgeOfTimeWindow[bdi] > 0.) B2FATAL("CDCDigitizer: Lower edge of time window > 0!");
1054  m_adcThresh[bdi] = fpp.getADCThresh();
1055  m_tdcThresh[bdi] = convF * (off - fpp.getTDCThreshInMV());
1056  m_widthOfTimeWindowInCount[bdi] = fpp.getWidthOfTimeWindow() + 1;
1057  m_trgDelayInCount [bdi] = fpp.getTrgDelay();
1058  }
1059 
1060  //debug
1061  B2DEBUG(m_debugLevel, "mode= " << mode);
1062  for (int bdi = 1; bdi < iNBoards; ++bdi) {
1063  B2DEBUG(m_debugLevel, bdi << " " << m_lowEdgeOfTimeWindow[bdi] << " " << m_uprEdgeOfTimeWindow[bdi] << " " << m_adcThresh[bdi] <<
1064  " " <<
1065  m_tdcThresh[bdi]);
1066  }
1067 }
1068 
1069 // Set Run-gain (from DB)
1070 void CDCDigitizerModule::setSemiTotalGain()
1071 {
1072  B2DEBUG(m_debugLevel, " ");
1073 
1074  //read individual wire gains
1075  const int nLyrs = MAX_N_SLAYERS;
1076  B2DEBUG(m_debugLevel, "nLyrs= " << nLyrs);
1077  int nGoodL[nLyrs] = {};
1078  float wgL[nLyrs] = {};
1079  int nGoodSL[nSuperLayers] = {};
1080  float wgSL[nSuperLayers] = {};
1081  int nGoodAll = 0;
1082  float wgAll = 0;
1083  int iw = -1;
1084  for (int lyr = 0; lyr < nLyrs; ++lyr) {
1085  int nWs = m_cdcgp->nWiresInLayer(lyr);
1086  for (int w = 0; w < nWs; ++w) {
1087  ++iw;
1088  float wg = (*m_wireGainFromDB)->getWireGain(iw);
1089  m_semiTotalGain[lyr][w] = wg;
1090  if (wg > 0) {
1091  ++nGoodL[lyr];
1092  wgL[lyr] += wg;
1093  WireID wid(lyr, w);
1094  ++nGoodSL[wid.getISuperLayer()];
1095  wgSL[wid.getISuperLayer()] += wg;
1096  ++nGoodAll;
1097  wgAll += wg;
1098  }
1099  }
1100  }
1101 
1102  //calculate mean gain per layer
1103  for (int lyr = 0; lyr < nLyrs; ++lyr) {
1104  if (nGoodL[lyr] > 0) wgL[lyr] /= nGoodL[lyr];
1105  B2DEBUG(m_debugLevel, "lyr,ngood,gain= " << lyr << " " << nGoodL[lyr] << " " << wgL[lyr]);
1106  }
1107  //calculate mean gain per superlayer
1108  for (unsigned int sl = 0; sl < nSuperLayers; ++sl) {
1109  if (nGoodSL[sl] > 0) wgSL[sl] /= nGoodSL[sl];
1110  B2DEBUG(m_debugLevel, "slyr,ngood,gain= " << sl << " " << nGoodSL[sl] << " " << wgSL[sl]);
1111  }
1112 
1113 
1114  //calculate mean gain over all wires
1115  if (nGoodAll > 0) {
1116  wgAll /= nGoodAll;
1117  } else {
1118  B2FATAL("No good wires !");
1119  }
1120  B2DEBUG(m_debugLevel, "ngoodAll,gain= " << nGoodAll << " " << wgAll);
1121 
1122  //set gain also for bad/dead wires (bad/dead in terms of dE/dx pid)
1123  for (int lyr = 0; lyr < nLyrs; ++lyr) {
1124  int nWs = m_cdcgp->nWiresInLayer(lyr);
1125  for (int w = 0; w < nWs; ++w) {
1126  if (m_semiTotalGain[lyr][w] <= 0) {
1127  if (wgL[lyr] > 0) {
1128  m_semiTotalGain[lyr][w] = wgL[lyr];
1129  } else {
1130  WireID wid(lyr, w);
1131  m_semiTotalGain[lyr][w] = wgSL[wid.getISuperLayer()];
1132  }
1133  }
1134  }
1135  }
1136 
1137  //check if all gains > 0
1138  for (int lyr = 0; lyr < nLyrs; ++lyr) {
1139  int nWs = m_cdcgp->nWiresInLayer(lyr);
1140  for (int w = 0; w < nWs; ++w) {
1141  if (m_semiTotalGain[lyr][w] <= 0) {
1142  B2WARNING("Gain for lyr and wire " << lyr << " " << w << "not > 0. Strange! Replace it with " << wgAll << ".");
1143  m_semiTotalGain[lyr][w] = wgAll;
1144  }
1145  }
1146  }
1147 
1148 //multiply common factor for all wires
1149  m_runGain = (*m_runGainFromDB)->getRunGain();
1150  double cgain = (*m_gain0FromDB)->getScaleFactor();
1151  B2DEBUG(m_debugLevel, "runGain, sf= " << m_runGain << " " << cgain);
1152  cgain *= m_runGain * m_overallGainFactor;
1153  for (int lyr = 0; lyr < nLyrs; ++lyr) {
1154  int nWs = m_cdcgp->nWiresInLayer(lyr);
1155  for (int w = 0; w < nWs; ++w) {
1156  m_semiTotalGain[lyr][w] *= cgain;
1157  B2DEBUG(m_debugLevel, "lyr,wire,gain= " << lyr << " " << w << " " << m_semiTotalGain[lyr][w]);
1158  }
1159  }
1160 }
1161 
1162 
1163 void CDCDigitizerModule::addXTalk()
1164 {
1165  map<WireID, XTalkInfo> xTalkMap;
1166  map<WireID, XTalkInfo> xTalkMap1;
1167  map<WireID, XTalkInfo>::iterator iterXTalkMap1;
1168 
1169  // Loop over all cdc hits to create a xtalk map
1170  int OriginalNoOfHits = m_cdcHits.getEntries();
1171  B2DEBUG(m_debugLevel4XTalk, "\n \n" << "#CDCHits " << OriginalNoOfHits);
1172  for (const auto& aHit : m_cdcHits) {
1173  if (m_issue2ndHitWarning && aHit.is2ndHit()) {
1174  B2WARNING("2nd TDC hit found, but not ready for it!");
1175  }
1176  WireID wid(aHit.getID());
1177  // B2DEBUG(m_debugLevel4XTalk, "Encoded wireid of current CDCHit: " << wid);
1178  short tdcCount = aHit.getTDCCount();
1179  short adcCount = aHit.getADCCount();
1180  short tot = aHit.getTOT();
1181  short board = m_cdcgp->getBoardID(wid);
1182  short channel = m_cdcgp->getChannelID(wid);
1183  const vector<pair<short, asicChannel>> xTalks = (*m_xTalkFromDB)->getLibraryCrossTalk(channel, tdcCount, adcCount, tot);
1184 
1185  int nXTalks = xTalks.size();
1186  for (int i = 0; i < nXTalks; ++i) {
1187  const unsigned short tdcCount4XTalk = xTalks[i].second.TDC;
1188  if (i == 0) {
1189  B2DEBUG(m_debugLevel4XTalk, "\n" << " signal: " << channel << " " << tdcCount << " " << adcCount << " " << tot);
1190  }
1191  B2DEBUG(m_debugLevel4XTalk, "xtalk: " << xTalks[i].first << " " << tdcCount4XTalk << " " << xTalks[i].second.ADC << " " <<
1192  xTalks[i].second.TOT);
1193  WireID widx = m_cdcgp->getWireID(board, xTalks[i].first);
1194  if (!m_cdcgp->isBadWire(widx)) { // for non-bad wire
1195  if (m_includeEarlyXTalks || (xTalks[i].second.TDC <= tdcCount)) {
1196  const double t0 = getPositiveT0(widx);
1197  const double ULOfTDC = (t0 - m_lowEdgeOfTimeWindow[board]) * m_tdcBinWidthInv;
1198  const double LLOfTDC = (t0 - m_uprEdgeOfTimeWindow[board]) * m_tdcBinWidthInv;
1199  if (LLOfTDC <= tdcCount4XTalk && tdcCount4XTalk <= ULOfTDC) {
1200  const unsigned short status = 0;
1201  xTalkMap.insert(make_pair(widx, XTalkInfo(tdcCount4XTalk, xTalks[i].second.ADC, xTalks[i].second.TOT, status)));
1202  }
1203  }
1204  // } else {
1205  // cout<<"badwire= " << widx.getICLayer() <<" "<< widx.getIWire() << endl;
1206  }
1207  } //end of xtalk loop
1208  } //end of cdc hit loop
1209 
1210  //Loop over all xtalk hits to creat a new xtalk map with only the fastest hits kept (approx.)
1211  B2DEBUG(m_debugLevel4XTalk, "#xtalk hits: " << xTalkMap.size());
1212  for (const auto& aHit : xTalkMap) {
1213  WireID wid = aHit.first;
1214 
1215  iterXTalkMap1 = xTalkMap1.find(wid);
1216  unsigned short tdcCount = aHit.second.m_tdc;
1217  unsigned short adcCount = aHit.second.m_adc;
1218  unsigned short tot = aHit.second.m_tot;
1219  unsigned short status = aHit.second.m_status;
1220 
1221  if (iterXTalkMap1 == xTalkMap1.end()) { // new entry
1222  xTalkMap1.insert(make_pair(wid, XTalkInfo(tdcCount, adcCount, tot, status)));
1223  // B2DEBUG(m_debugLevel4XTalk, "Creating a new xtalk hit with encoded wire no.: " << wid);
1224  } else { // not new; check if fastest
1225  if (tdcCount < iterXTalkMap1->second.m_tdc) {
1226  iterXTalkMap1->second.m_tdc = tdcCount;
1227  B2DEBUG(m_debugLevel4XTalk, "TDC-count of current xtalk: " << tdcCount);
1228  }
1229  iterXTalkMap1->second.m_adc += adcCount;
1230  iterXTalkMap1->second.m_tot += tot; // approx.
1231  }
1232  } // end of xtalk loop
1233 
1234  //add xtalk in the same way as the beam bg. overlay
1235  B2DEBUG(m_debugLevel4XTalk, "#xtalk1 hits: " << xTalkMap1.size());
1236  for (const auto& aX : xTalkMap1) {
1237  bool append = true;
1238  const unsigned short tdc4Bg = aX.second.m_tdc;
1239  const unsigned short adc4Bg = aX.second.m_adc;
1240  const unsigned short tot4Bg = aX.second.m_tot;
1241  const unsigned short status4Bg = aX.second.m_status;
1242 
1243  for (int iHit = 0; iHit < OriginalNoOfHits; ++iHit) {
1244  CDCHit& aH = *(m_cdcHits[iHit]);
1245  if (aH.getID() != aX.first.getEWire()) { //wire id unmatched
1246  continue;
1247  } else { //wire id matched
1248  append = false;
1249  const unsigned short tdc4Sg = aH.getTDCCount();
1250  const unsigned short adc4Sg = aH.getADCCount();
1251  const unsigned short tot4Sg = aH.getTOT();
1252  // B2DEBUG(m_debuglevel4XTalk, "Sg tdc,adc,tot= " << tdc4Sg << " " << adc4Sg << " " << tot4Sg);
1253  // B2DEBUG(m_debugLevel4XTalk, "Bg tdc,adc,tot= " << tdc4Bg << " " << adc4Bg << " " << tot4Bg);
1254 
1255  // If the BG hit is faster than the true hit, the TDC count is replaced, and
1256  // the relations are removed. ADC counts are summed up.
1257  if (tdc4Sg < tdc4Bg) {
1258  aH.setTDCCount(tdc4Bg);
1259  aH.setStatus(status4Bg);
1260  auto relSimHits = aH.getRelationsFrom<CDCSimHit>();
1261  for (int i = relSimHits.size() - 1; i >= 0; --i) {
1262  relSimHits.remove(i);
1263  }
1264  auto relMCParticles = aH.getRelationsFrom<MCParticle>();
1265  for (int i = relMCParticles.size() - 1; i >= 0; --i) {
1266  relMCParticles.remove(i);
1267  }
1268  }
1269 
1270  aH.setADCCount(adc4Sg + adc4Bg);
1271 
1272  //Set TOT for signal+background case. It is assumed that the start timing
1273  //of a pulse (input to ADC) is given by the TDC-count. This is an
1274  //approximation becasue analog (for ADC) and digital (for TDC) parts are
1275  //different in the front-end electronics.
1276  unsigned short s1 = tdc4Sg; //start time of 1st pulse
1277  unsigned short s2 = tdc4Bg; //start time of 2nd pulse
1278  unsigned short w1 = tot4Sg; //its width
1279  unsigned short w2 = tot4Bg; //its width
1280  if (tdc4Sg < tdc4Bg) {
1281  s1 = tdc4Bg;
1282  w1 = tot4Bg;
1283  s2 = tdc4Sg;
1284  w2 = tot4Sg;
1285  }
1286  w1 *= 32;
1287  w2 *= 32;
1288  const unsigned short e1 = s1 - w1; //end time of 1st pulse
1289  const unsigned short e2 = s2 - w2; //end time of 2nd pulse
1290  // B2DEBUG(m_debuglevel4Xtalk, "s1,e1,w1,s2,e2,w2= " << s1 << " " << e1 << " " << w1 << " " << s2 << " " << e2 << " " << w2);
1291 
1292  double pulseW = w1 + w2;
1293  if (e1 <= e2) {
1294  pulseW = w1;
1295  } else if (e1 <= s2) {
1296  pulseW = s1 - e2;
1297  }
1298 
1299  unsigned short board = m_cdcgp->getBoardID(aX.first);
1300  aH.setTOT(std::min(std::round(pulseW / 32.), static_cast<double>(m_widthOfTimeWindowInCount[board])));
1301  B2DEBUG(m_debugLevel4XTalk, "replaced tdc,adc,tot,wid,status= " << aH.getTDCCount() << " " << aH.getADCCount() << " " << aH.getTOT()
1302  <<
1303  " " << aH.getID() << " " << aH.getStatus());
1304  break;
1305  }
1306  } //end of cdc hit loop
1307 
1308  if (append) {
1309  m_cdcHits.appendNew(tdc4Bg, adc4Bg, aX.first, status4Bg, tot4Bg);
1310  B2DEBUG(m_debugLevel4XTalk, "appended tdc,adc,tot,wid,status= " << tdc4Bg << " " << adc4Bg << " " << tot4Bg << " " << aX.first <<
1311  " " <<
1312  status4Bg);
1313  }
1314  } //end of x-talk loop
1315  B2DEBUG(m_debugLevel4XTalk, "original #hits, #hits= " << OriginalNoOfHits << " " << m_cdcHits.getEntries());
1316 }
1317 
1318 
1319 double CDCDigitizerModule::getPositiveT0(const WireID& wid)
1320 {
1321  double t0 = m_cdcgp->getT0(wid);
1322  if (t0 <= 0 && m_treatNegT0WiresAsGood) t0 = m_cdcgp->getMeanT0();
1323  // B2DEBUG(m_debugLevel, m_cdcgp->getT0(wid) <<" "<< m_cdcgp->getMeanT0() <<" "<< t0);
1324  return t0;
1325 }
The Class for Detailed Digitization of CDC.
Database object for Fron-endt electronics params.
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
void setTDCCount(short tdcCount)
Setter for TDC count.
Definition: CDCHit.h:128
void set2ndHitFlag()
Setter for 2nd hit flag.
Definition: CDCHit.h:113
short getTDCCount() const
Getter for TDC count.
Definition: CDCHit.h:219
void setTOT(unsigned short tot)
Setter for TOT.
Definition: CDCHit.h:160
unsigned short getID() const
Getter for encoded wire number.
Definition: CDCHit.h:193
unsigned short getStatus() const
Getter for CDCHit status.
Definition: CDCHit.h:199
void setADCCount(unsigned short adcCount)
Setter for ADC count.
Definition: CDCHit.h:135
unsigned short getADCCount() const
Getter for integrated charge.
Definition: CDCHit.h:230
unsigned short getTOT() const
Getter for TOT.
Definition: CDCHit.h:248
void setOtherHitIndices(CDCHit *otherHit)
Setter for the other hit indices.
Definition: CDCHit.h:147
void setStatus(unsigned short status)
Setter for CDCHit status.
Definition: CDCHit.h:106
Example Detector.
Definition: CDCSimHit.h:22
The Class for CDC Geometry Parameters.
double getNominalPropSpeed() const
Return the nominal propagation speed of the sense wire (default: 27.25 cm/nsec).
EWirePosition
Wire position set.
double getTdcBinWidth() const
Return TDC bin width (nsec).
double getNominalDriftV() const
Return the nominal drift velocity of He-ethane gas (default: 4.0x10^-3 cm/nsec).
The Class for Energy deposit in the gas.
Definition: EDepInGas.h:20
double getEDepInGas(int mode, int pdg, double p, double dx, double e3) const
Return the energy deosite in the gas.
Definition: EDepInGas.cc:137
void addCallback(std::function< void(const std::string &)> callback, bool onDestruction=false)
Add a callback method.
Class for accessing arrays of objects in the database.
Definition: DBArray.h:26
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
Base class for Modules.
Definition: Module.h:72
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
float weight(int index) const
Get weight with index.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
RelationVector< FROM > getRelationsFrom(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from another store array to this object.
Class to identify a wire inside the CDC.
Definition: WireID.h:34
unsigned short getICLayer() const
Getter for continuous layer numbering.
Definition: WireID.cc:24
unsigned short getIWire() const
Getter for wire within the layer.
Definition: WireID.h:145
unsigned short getISuperLayer() const
Getter for Super-Layer.
Definition: WireID.h:130
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
double ClosestApproach(const TVector3 &bwp, const TVector3 &fwp, const TVector3 &posIn, const TVector3 &posOut, TVector3 &hitPosition, TVector3 &wirePosition)
Returns a closest distance between a track and a wire.
Abstract base class for different kinds of events.
Structure for saving the signal information.
Structure for saving the x-talk information.