CMS 3D CMS Logo

List of all members | Public Types | Public Member Functions | Private Attributes
HGCFEElectronics< DFr > Class Template Reference

models the behavior of the front-end electronics More...

#include <HGCFEElectronics.h>

Public Types

enum  HGCFEElectronicsFirmwareVersion { TRIVIAL, SIMPLE, WITHTOT }
 
enum  HGCFEElectronicsTOTMode { WEIGHTEDBYE, SIMPLETHRESHOLD }
 

Public Member Functions

float getADClsb ()
 returns the LSB in MIP currently configured More...
 
float getADCThreshold ()
 
int getTargetMipValue ()
 
std::array< float, 3 > getTDCForToAOnset ()
 
float getTDClsb ()
 
float getTDCOnset ()
 
float getTimeJitter (float totalCharge, int thickness)
 
 HGCFEElectronics (const edm::ParameterSet &ps)
 CTOR. More...
 
void runShaper (DFr &dataFrame, hgc::HGCSimHitData &chargeColl, hgc::HGCSimHitData &toa, CLHEP::HepRandomEngine *engine, uint32_t thrADC=0, float lsbADC=-1, uint32_t gainIdx=0, float maxADC=-1, int thickness=1)
 switches according to the firmware version More...
 
void runShaperWithToT (DFr &dataFrame, hgc::HGCSimHitData &chargeColl, hgc::HGCSimHitData &toa, CLHEP::HepRandomEngine *engine, uint32_t thrADC, float lsbADC, uint32_t gainIdx, float maxADC, int thickness)
 implements pulse shape and switch to time over threshold including deadtime More...
 
void runSimpleShaper (DFr &dataFrame, hgc::HGCSimHitData &chargeColl, uint32_t thrADC, float lsbADC, uint32_t gainIdx, float maxADC)
 applies a shape to each time sample and propagates the tails to the subsequent time samples More...
 
void runTrivialShaper (DFr &dataFrame, hgc::HGCSimHitData &chargeColl, uint32_t thrADC, float lsbADC, uint32_t gainIdx, float maxADC)
 converts charge to digis without pulse shape More...
 
void setADClsb (float newLSB)
 
void SetNoiseValues (const std::vector< float > &noise_fC)
 
uint32_t toaMode () const
 returns how ToT will be computed More...
 
 ~HGCFEElectronics ()
 DTOR. More...
 

Private Attributes

float adcLSB_fC_
 
std::array< float, 6 > adcPulse_
 
float adcSaturation_fC_
 
float adcThreshold_fC_
 
std::array< bool, hgc::nSamples > busyFlags
 
uint32_t fwVersion_
 
std::array< float, 3 > jitterConstant2_ns_
 
std::array< float, 3 > jitterNoise2_ns_
 
hgc::HGCSimHitData newCharge
 
std::vector< float > noise_fC_
 
std::array< float, 6 > pulseAvgT_
 
uint32_t targetMIPvalue_ADC_
 
std::vector< float > tdcChargeDrainParameterisation_
 
std::array< float, 3 > tdcForToAOnset_fC_
 
float tdcLSB_fC_
 
float tdcOnset_fC_
 
float tdcResolutionInNs_
 
float tdcSaturation_fC_
 
bool thresholdFollowsMIP_
 
std::array< bool, hgc::nSamples > toaFlags
 
hgc::HGCSimHitData toaFromToT
 
float toaLSB_ns_
 
uint32_t toaMode_
 
std::array< bool, hgc::nSamples > totFlags
 

Detailed Description

template<class DFr>
class HGCFEElectronics< DFr >

models the behavior of the front-end electronics

Definition at line 20 of file HGCFEElectronics.h.

Member Enumeration Documentation

Enumerator
TRIVIAL 
SIMPLE 
WITHTOT 

Definition at line 22 of file HGCFEElectronics.h.

template<class DFr >
enum HGCFEElectronics::HGCFEElectronicsTOTMode
Enumerator
WEIGHTEDBYE 
SIMPLETHRESHOLD 

Definition at line 23 of file HGCFEElectronics.h.

Constructor & Destructor Documentation

template<class DFr >
HGCFEElectronics< DFr >::HGCFEElectronics ( const edm::ParameterSet ps)

CTOR.

Definition at line 11 of file HGCFEElectronics.cc.

References HGCFEElectronics< DFr >::adcLSB_fC_, HGCalUncalibRecHit_cfi::adcNbits, HGCFEElectronics< DFr >::adcPulse_, HGCFEElectronics< DFr >::adcSaturation_fC_, HGCFEElectronics< DFr >::adcThreshold_fC_, MillePedeFileConverter_cfg::e, Exception, dqmMemoryStats::float, HGCFEElectronics< DFr >::fwVersion_, edm::ParameterSet::getParameter(), mps_fire::i, HGCFEElectronics< DFr >::jitterConstant2_ns_, HGCFEElectronics< DFr >::jitterNoise2_ns_, HGCFEElectronics< DFr >::noise_fC_, funct::pow(), HGCFEElectronics< DFr >::pulseAvgT_, HGCFEElectronics< DFr >::targetMIPvalue_ADC_, HGCFEElectronics< DFr >::tdcChargeDrainParameterisation_, HGCFEElectronics< DFr >::tdcForToAOnset_fC_, HGCFEElectronics< DFr >::tdcLSB_fC_, HGCalUncalibRecHit_cfi::tdcNbits, HGCFEElectronics< DFr >::tdcOnset_fC_, HGCFEElectronics< DFr >::tdcResolutionInNs_, HGCFEElectronics< DFr >::tdcSaturation_fC_, groupFilesInBlocks::temp, HGCFEElectronics< DFr >::toaLSB_ns_, HGCFEElectronics< DFr >::toaMode_, heppy_batch::val, and HGCFEElectronics< DFr >::WEIGHTEDBYE.

12  : fwVersion_{ps.getParameter<uint32_t>("fwVersion")},
13  adcPulse_{},
14  pulseAvgT_{},
16  adcSaturation_fC_{-1.0},
17  adcLSB_fC_{},
18  tdcLSB_fC_{},
19  tdcSaturation_fC_{-1.0},
21  tdcOnset_fC_{},
22  toaLSB_ns_{},
23  tdcResolutionInNs_{1e-9}, // set time resolution very small by default
27  noise_fC_{},
29  edm::LogVerbatim("HGCFE") << "[HGCFEElectronics] running with version " << fwVersion_ << std::endl;
30  if (ps.exists("adcPulse")) {
31  auto temp = ps.getParameter<std::vector<double> >("adcPulse");
32  for (unsigned i = 0; i < temp.size(); ++i) {
33  adcPulse_[i] = (float)temp[i];
34  }
35  // normalize adc pulse
36  for (unsigned i = 0; i < adcPulse_.size(); ++i) {
37  adcPulse_[i] = adcPulse_[i] / adcPulse_[2];
38  }
39  temp = ps.getParameter<std::vector<double> >("pulseAvgT");
40  for (unsigned i = 0; i < temp.size(); ++i) {
41  pulseAvgT_[i] = (float)temp[i];
42  }
43  }
44  if (ps.exists("adcNbits")) {
45  uint32_t adcNbits = ps.getParameter<uint32_t>("adcNbits");
46  adcSaturation_fC_ = ps.getParameter<double>("adcSaturation_fC");
47  adcLSB_fC_ = adcSaturation_fC_ / pow(2., adcNbits);
48  edm::LogVerbatim("HGCFE") << "[HGCFEElectronics] " << adcNbits << " bit ADC defined"
49  << " with LSB=" << adcLSB_fC_ << " saturation to occur @ " << adcSaturation_fC_
50  << std::endl;
51  }
52 
53  if (ps.exists("tdcNbits")) {
54  uint32_t tdcNbits = ps.getParameter<uint32_t>("tdcNbits");
55  tdcSaturation_fC_ = ps.getParameter<double>("tdcSaturation_fC");
56  tdcLSB_fC_ = tdcSaturation_fC_ / pow(2., tdcNbits);
57  edm::LogVerbatim("HGCFE") << "[HGCFEElectronics] " << tdcNbits << " bit TDC defined with LSB=" << tdcLSB_fC_
58  << " saturation to occur @ " << tdcSaturation_fC_ << std::endl;
59  }
60  if (ps.exists("targetMIPvalue_ADC"))
61  targetMIPvalue_ADC_ = ps.getParameter<uint32_t>("targetMIPvalue_ADC");
62  if (ps.exists("adcThreshold_fC"))
63  adcThreshold_fC_ = ps.getParameter<double>("adcThreshold_fC");
64  if (ps.exists("tdcOnset_fC"))
65  tdcOnset_fC_ = ps.getParameter<double>("tdcOnset_fC");
66  if (ps.exists("tdcForToAOnset_fC")) {
67  auto temp = ps.getParameter<std::vector<double> >("tdcForToAOnset_fC");
68  if (temp.size() == tdcForToAOnset_fC_.size()) {
69  std::copy_n(temp.begin(), temp.size(), tdcForToAOnset_fC_.begin());
70  } else {
71  throw cms::Exception("BadConfiguration") << " HGCFEElectronics wrong size for ToA thresholds ";
72  }
73  }
74  if (ps.exists("toaLSB_ns"))
75  toaLSB_ns_ = ps.getParameter<double>("toaLSB_ns");
76  if (ps.exists("tdcChargeDrainParameterisation")) {
77  for (auto val : ps.getParameter<std::vector<double> >("tdcChargeDrainParameterisation")) {
78  tdcChargeDrainParameterisation_.push_back((float)val);
79  }
80  }
81  if (ps.exists("tdcResolutionInPs"))
82  tdcResolutionInNs_ = ps.getParameter<double>("tdcResolutionInPs") * 1e-3; // convert to ns
83  if (ps.exists("toaMode"))
84  toaMode_ = ps.getParameter<uint32_t>("toaMode");
85 
86  if (ps.exists("jitterNoise_ns")) {
87  auto temp = ps.getParameter<std::vector<double> >("jitterNoise_ns");
88  if (temp.size() == jitterNoise2_ns_.size()) {
89  std::copy_n(temp.begin(), temp.size(), jitterNoise2_ns_.begin());
90  } else {
91  throw cms::Exception("BadConfiguration") << " HGCFEElectronics wrong size for ToA jitterNoise ";
92  }
93  }
94  if (ps.exists("jitterConstant_ns")) {
95  auto temp = ps.getParameter<std::vector<double> >("jitterConstant_ns");
96  if (temp.size() == jitterConstant2_ns_.size()) {
97  std::copy_n(temp.begin(), temp.size(), jitterConstant2_ns_.begin());
98  } else {
99  throw cms::Exception("BadConfiguration") << " HGCFEElectronics wrong size for ToA jitterConstant ";
100  }
101  }
102 }
T getParameter(std::string const &) const
std::array< float, 3 > jitterConstant2_ns_
bool exists(std::string const &parameterName) const
checks if a parameter exists
std::array< float, 3 > jitterNoise2_ns_
uint32_t targetMIPvalue_ADC_
std::vector< float > noise_fC_
std::array< float, 6 > adcPulse_
std::array< float, 6 > pulseAvgT_
std::vector< float > tdcChargeDrainParameterisation_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:30
std::array< float, 3 > tdcForToAOnset_fC_
template<class DFr >
HGCFEElectronics< DFr >::~HGCFEElectronics ( )
inline

DTOR.

Definition at line 114 of file HGCFEElectronics.h.

114 {}

Member Function Documentation

template<class DFr >
float HGCFEElectronics< DFr >::getADClsb ( )
inline

returns the LSB in MIP currently configured

Definition at line 73 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::adcLSB_fC_.

73 { return adcLSB_fC_; }
template<class DFr >
float HGCFEElectronics< DFr >::getADCThreshold ( )
inline

Definition at line 76 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::adcThreshold_fC_.

76 { return adcThreshold_fC_; }
template<class DFr >
int HGCFEElectronics< DFr >::getTargetMipValue ( )
inline

Definition at line 75 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::targetMIPvalue_ADC_.

75 { return targetMIPvalue_ADC_; }
uint32_t targetMIPvalue_ADC_
template<class DFr >
std::array<float, 3> HGCFEElectronics< DFr >::getTDCForToAOnset ( )
inline

Definition at line 78 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::tdcForToAOnset_fC_.

78 { return tdcForToAOnset_fC_; }
std::array< float, 3 > tdcForToAOnset_fC_
template<class DFr >
float HGCFEElectronics< DFr >::getTDClsb ( )
inline

Definition at line 74 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::tdcLSB_fC_.

74 { return tdcLSB_fC_; }
template<class DFr >
float HGCFEElectronics< DFr >::getTDCOnset ( )
inline

Definition at line 77 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::tdcOnset_fC_.

77 { return tdcOnset_fC_; }
template<class DFr >
float HGCFEElectronics< DFr >::getTimeJitter ( float  totalCharge,
int  thickness 
)
inline

Definition at line 62 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::jitterConstant2_ns_, HGCFEElectronics< DFr >::jitterNoise2_ns_, HGCFEElectronics< DFr >::noise_fC_, funct::pow(), and mathSSE::sqrt().

Referenced by HGCFEElectronics< DFr >::runShaperWithToT().

62  {
63  float A2 = jitterNoise2_ns_.at(thickness - 1);
64  float C2 = jitterConstant2_ns_.at(thickness - 1);
65  float X2 = pow((totalCharge / noise_fC_.at(thickness - 1)), 2.);
66  float jitter2 = A2 / X2 + C2;
67  return sqrt(jitter2);
68  };
std::array< float, 3 > jitterConstant2_ns_
std::array< float, 3 > jitterNoise2_ns_
T sqrt(T t)
Definition: SSEVec.h:19
std::vector< float > noise_fC_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:30
template<class DFr >
void HGCFEElectronics< DFr >::runShaper ( DFr &  dataFrame,
hgc::HGCSimHitData chargeColl,
hgc::HGCSimHitData toa,
CLHEP::HepRandomEngine *  engine,
uint32_t  thrADC = 0,
float  lsbADC = -1,
uint32_t  gainIdx = 0,
float  maxADC = -1,
int  thickness = 1 
)
inline

switches according to the firmware version

Definition at line 33 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::fwVersion_, HGCFEElectronics< DFr >::runShaperWithToT(), HGCFEElectronics< DFr >::runSimpleShaper(), HGCFEElectronics< DFr >::runTrivialShaper(), HGCFEElectronics< DFr >::SIMPLE, and Calorimetry_cff::thickness.

41  {
42  switch (fwVersion_) {
43  case SIMPLE: {
44  runSimpleShaper(dataFrame, chargeColl, thrADC, lsbADC, gainIdx, maxADC);
45  break;
46  }
47  case WITHTOT: {
48  runShaperWithToT(dataFrame, chargeColl, toa, engine, thrADC, lsbADC, gainIdx, maxADC, thickness);
49  break;
50  }
51  default: {
52  runTrivialShaper(dataFrame, chargeColl, thrADC, lsbADC, gainIdx, maxADC);
53  break;
54  }
55  }
56  }
void runShaperWithToT(DFr &dataFrame, hgc::HGCSimHitData &chargeColl, hgc::HGCSimHitData &toa, CLHEP::HepRandomEngine *engine, uint32_t thrADC, float lsbADC, uint32_t gainIdx, float maxADC, int thickness)
implements pulse shape and switch to time over threshold including deadtime
void runTrivialShaper(DFr &dataFrame, hgc::HGCSimHitData &chargeColl, uint32_t thrADC, float lsbADC, uint32_t gainIdx, float maxADC)
converts charge to digis without pulse shape
void runSimpleShaper(DFr &dataFrame, hgc::HGCSimHitData &chargeColl, uint32_t thrADC, float lsbADC, uint32_t gainIdx, float maxADC)
applies a shape to each time sample and propagates the tails to the subsequent time samples ...
template<class DFr >
void HGCFEElectronics< DFr >::runShaperWithToT ( DFr &  dataFrame,
hgc::HGCSimHitData chargeColl,
hgc::HGCSimHitData toa,
CLHEP::HepRandomEngine *  engine,
uint32_t  thrADC,
float  lsbADC,
uint32_t  gainIdx,
float  maxADC,
int  thickness 
)

implements pulse shape and switch to time over threshold including deadtime

Definition at line 198 of file HGCFEElectronics.cc.

References ecalMGPA::adc(), HGCFEElectronics< DFr >::adcLSB_fC_, HGCFEElectronics< DFr >::adcPulse_, HGCFEElectronics< DFr >::adcSaturation_fC_, HGCFEElectronics< DFr >::busyFlags, ALCARECOTkAlJpsiMuMu_cff::charge, constexpr, debug, MillePedeFileConverter_cfg::e, f, myMath::fast_expf(), HGCFEElectronics< DFr >::getTimeJitter(), createfilelist::int, SiStripPI::max, min(), mps_check::msg, HGCFEElectronics< DFr >::newCharge, HGCFEElectronics< DFr >::pulseAvgT_, HGCSample::set(), HGCSample::setToAValid(), HGCFEElectronics< DFr >::tdcChargeDrainParameterisation_, HGCFEElectronics< DFr >::tdcLSB_fC_, HGCFEElectronics< DFr >::tdcOnset_fC_, HGCFEElectronics< DFr >::tdcResolutionInNs_, HGCFEElectronics< DFr >::tdcSaturation_fC_, HGCFEElectronics< DFr >::toaFlags, HGCFEElectronics< DFr >::toaFromToT, HGCFEElectronics< DFr >::toaLSB_ns_, HGCFEElectronics< DFr >::toaMode_, HGCFEElectronics< DFr >::totFlags, and HGCFEElectronics< DFr >::WEIGHTEDBYE.

Referenced by HGCFEElectronics< DFr >::runShaper(), and HGCFEElectronics< DFr >::setADClsb().

206  {
207  busyFlags.fill(false);
208  totFlags.fill(false);
209  toaFlags.fill(false);
210  newCharge.fill(0.f);
211  toaFromToT.fill(0.f);
212 
213 #ifdef EDM_ML_DEBUG
214  constexpr bool debug_state(true);
215 #else
216  constexpr bool debug_state(false);
217 #endif
218 
219  bool debug = debug_state;
220  float timeToA = 0.f;
221 
222  //first look at time
223  //for pileup look only at intime signals
224  //ToA is in central BX if fired -- std::floor(BX/25.)+9;
225  int fireBX = 9;
226  //noise fluctuation on charge is added after ToA computation
227  //do not recheck the ToA firing threshold tdcForToAOnset_fC_[thickness-1] not to bias the efficiency
228  //to be done properly with realistic ToA shaper and jitter for the moment accounted in the smearing
229  if (toaColl[fireBX] != 0.f) {
230  timeToA = toaColl[fireBX];
231  float jitter = getTimeJitter(chargeColl[fireBX], thickness);
232  if (jitter != 0)
233  timeToA = CLHEP::RandGaussQ::shoot(engine, timeToA, jitter);
234  else if (tdcResolutionInNs_ != 0)
235  timeToA = CLHEP::RandGaussQ::shoot(engine, timeToA, tdcResolutionInNs_);
236  if (timeToA >= 0.f && timeToA <= 25.f)
237  toaFlags[fireBX] = true;
238  }
239 
240  //now look at charge
241  //first identify bunches which will trigger ToT
242  //if(debug_state) edm::LogVerbatim("HGCFE") << "[runShaperWithToT]" << std::endl;
243  for (int it = 0; it < (int)(chargeColl.size()); ++it) {
244  debug = debug_state;
245  //if already flagged as busy it can't be re-used to trigger the ToT
246  if (busyFlags[it])
247  continue;
248 
249  //if below TDC onset will be handled by SARS ADC later
250  float charge = chargeColl[it];
251  if (charge < tdcOnset_fC_) {
252  debug = false;
253  continue;
254  }
255 
256  //raise TDC mode for charge computation
257  //ToA anyway fired independently will be sorted out with realistic ToA dedicated shaper
258  float toa = timeToA;
259  totFlags[it] = true;
260 
261  if (debug)
262  edm::LogVerbatim("HGCFE") << "\t q=" << charge << " fC with <toa>=" << toa << " ns, triggers ToT @ " << it
263  << std::endl;
264 
265  //compute total charge to be integrated and integration time
266  //needs a loop as ToT will last as long as there is charge to dissipate
267  int busyBxs(0);
268  float totalCharge(charge), finalToA(toa), integTime(0);
269  while (true) {
270  //compute integration time in ns and # bunches
271  //float newIntegTime(0);
272  int poffset = 0;
273  float charge_offset = 0.f;
274  const float charge_kfC(totalCharge * 1e-3);
275  if (charge_kfC < tdcChargeDrainParameterisation_[3]) {
276  //newIntegTime=tdcChargeDrainParameterisation_[0]*pow(charge_kfC,2)+tdcChargeDrainParameterisation_[1]*charge_kfC+tdcChargeDrainParameterisation_[2];
277  } else if (charge_kfC < tdcChargeDrainParameterisation_[7]) {
278  poffset = 4;
279  charge_offset = tdcChargeDrainParameterisation_[3];
280  //newIntegTime=tdcChargeDrainParameterisation_[4]*pow(charge_kfC-tdcChargeDrainParameterisation_[3],2)+tdcChargeDrainParameterisation_[5]*(charge_kfC-tdcChargeDrainParameterisation_[3])+tdcChargeDrainParameterisation_[6];
281  } else {
282  poffset = 8;
283  charge_offset = tdcChargeDrainParameterisation_[7];
284  //newIntegTime=tdcChargeDrainParameterisation_[8]*pow(charge_kfC-tdcChargeDrainParameterisation_[7],2)+tdcChargeDrainParameterisation_[9]*(charge_kfC-tdcChargeDrainParameterisation_[7])+tdcChargeDrainParameterisation_[10];
285  }
286  const float charge_mod = charge_kfC - charge_offset;
287  const float newIntegTime =
288  ((tdcChargeDrainParameterisation_[poffset] * charge_mod + tdcChargeDrainParameterisation_[poffset + 1]) *
289  charge_mod +
290  tdcChargeDrainParameterisation_[poffset + 2]);
291 
292  const int newBusyBxs = std::floor(newIntegTime / 25.f) + 1;
293 
294  //if no update is needed regarding the number of bunches,
295  //then the ToT integration time has converged
296  integTime = newIntegTime;
297  if (newBusyBxs == busyBxs)
298  break;
299 
300  //update charge integrated during ToT
301  if (debug) {
302  if (busyBxs == 0)
303  edm::LogVerbatim("HGCFE") << "\t Intial busy estimate=" << integTime << " ns = " << newBusyBxs << " bxs"
304  << std::endl;
305  else
306  edm::LogVerbatim("HGCFE") << "\t ...integrated charge overflows initial busy estimate, interating again"
307  << std::endl;
308  }
309 
310  //update number of busy bunches
311  busyBxs = newBusyBxs;
312 
313  //reset charge to be integrated
314  totalCharge = charge;
315  if (toaMode_ == WEIGHTEDBYE)
316  finalToA = toa * charge;
317 
318  //add leakage from previous bunches in SARS ADC mode
319  for (int jt = 0; jt < it; ++jt) {
320  const unsigned int deltaT = (it - jt);
321  if ((deltaT + 2) >= adcPulse_.size() || chargeColl[jt] == 0.f || totFlags[jt] || busyFlags[jt])
322  continue;
323 
324  const float leakCharge = chargeColl[jt] * adcPulse_[deltaT + 2];
325  totalCharge += leakCharge;
326  if (toaMode_ == WEIGHTEDBYE)
327  finalToA += leakCharge * pulseAvgT_[deltaT + 2];
328 
329  if (debug)
330  edm::LogVerbatim("HGCFE") << "\t\t leaking " << chargeColl[jt] << " fC @ deltaT=-" << deltaT << " -> +"
331  << leakCharge << " with avgT=" << pulseAvgT_[deltaT + 2] << std::endl;
332  }
333 
334  //add contamination from posterior bunches
335  for (int jt = it + 1; jt < it + busyBxs && jt < dataFrame.size(); ++jt) {
336  //this charge will be integrated in TDC mode
337  //disable for SARS ADC
338  busyFlags[jt] = true;
339 
340  const float extraCharge = chargeColl[jt];
341  if (extraCharge == 0.f)
342  continue;
343  if (debug)
344  edm::LogVerbatim("HGCFE") << "\t\t adding " << extraCharge << " fC @ deltaT=+" << (jt - it) << std::endl;
345 
346  totalCharge += extraCharge;
347  if (toaMode_ == WEIGHTEDBYE)
348  finalToA += extraCharge * toaColl[jt];
349  }
350 
351  //finalize ToA contamination
352  if (toaMode_ == WEIGHTEDBYE)
353  finalToA /= totalCharge;
354  }
355  newCharge[it] = (totalCharge - tdcOnset_fC_);
356 
357  if (debug)
358  edm::LogVerbatim("HGCFE") << "\t Final busy estimate=" << integTime << " ns = " << busyBxs << " bxs" << std::endl
359  << "\t Total integrated=" << totalCharge << " fC <toa>=" << toaFromToT[it]
360  << " (raw=" << finalToA << ") ns " << std::endl;
361 
362  //last fC (tdcOnset) are dissipated trough pulse
363  if (it + busyBxs < (int)(newCharge.size())) {
364  const float deltaT2nextBx((busyBxs * 25 - integTime));
365  const float tdcOnsetLeakage(tdcOnset_fC_ * vdt::fast_expf(-deltaT2nextBx / tdcChargeDrainParameterisation_[11]));
366  if (debug)
367  edm::LogVerbatim("HGCFE") << "\t Leaking remainder of TDC onset " << tdcOnset_fC_ << " fC, to be dissipated in "
368  << deltaT2nextBx << " DeltaT/tau=" << deltaT2nextBx << " / "
369  << tdcChargeDrainParameterisation_[11] << " ns, adds " << tdcOnsetLeakage << " fC @ "
370  << it + busyBxs << " bx (first free bx)" << std::endl;
371  newCharge[it + busyBxs] += tdcOnsetLeakage;
372  }
373  }
374 
375  //including the leakage from bunches in SARS ADC when not declared busy or in ToT
376  auto runChargeSharing = [&]() {
377  int ipulse = 0;
378  for (int it = 0; it < (int)(chargeColl.size()); ++it) {
379  //if busy, charge has been already integrated
380  //if(debug) edm::LogVerbatim("HGCFE") << "\t SARS ADC pulse activated @ " << it << " : ";
381  if (!totFlags[it] & !busyFlags[it]) {
382  const int start = std::max(0, 2 - it);
383  const int stop = std::min((int)adcPulse_.size(), (int)newCharge.size() - it + 2);
384  for (ipulse = start; ipulse < stop; ++ipulse) {
385  const int itoffset = it + ipulse - 2;
386  //notice that if the channel is already busy,
387  //it has already been affected by the leakage of the SARS ADC
388  //if(totFlags[itoffset] || busyFlags[itoffset]) continue;
389  if (!totFlags[itoffset] & !busyFlags[itoffset]) {
390  newCharge[itoffset] += chargeColl[it] * adcPulse_[ipulse];
391  }
392  //if(debug) edm::LogVerbatim("HGCFE") << " | " << itoffset << " " << chargeColl[it]*adcPulse_[ipulse] << "( " << chargeColl[it] << "->";
393  //if(debug) edm::LogVerbatim("HGCFE") << newCharge[itoffset] << ") ";
394  }
395  }
396 
397  if (debug)
398  edm::LogVerbatim("HGCFE") << std::endl;
399  }
400  };
401  runChargeSharing();
402 
403  //For the future need to understand how to deal with toa for out of time signals
404  //and for that should keep track of the BX firing the ToA somewhere (also to restore the use of finalToA)
405  /*
406  float finalToA(0.);
407  for(int it=0; it<(int)(newCharge.size()); it++){
408  if(toaFlags[it]){
409  finalToA = toaFromToT[it];
410  //to avoid +=25 for small negative time taken as 0
411  while(finalToA < -1.e-5) finalToA+=25.f;
412  while(finalToA > 25.f) finalToA-=25.f;
413  toaFromToT[it] = finalToA;
414  }
415  }
416  */
417  //timeToA is already in 0-25ns range by construction
418 
419  //set new ADCs and ToA
420  if (debug)
421  edm::LogVerbatim("HGCFE") << "\t final result : ";
422  if (lsbADC < 0)
423  lsbADC = adcLSB_fC_;
424  if (maxADC < 0)
425  maxADC = adcSaturation_fC_;
426  for (int it = 0; it < (int)(newCharge.size()); it++) {
427  if (debug)
428  edm::LogVerbatim("HGCFE") << chargeColl[it] << " -> " << newCharge[it] << " ";
429 
430  HGCSample newSample;
431  if (totFlags[it] || busyFlags[it]) {
432  if (totFlags[it]) {
433  //brute force saturation, maybe could to better with an exponential like saturation
434  const float saturatedCharge(std::min(newCharge[it], tdcSaturation_fC_));
435  //working version for in-time PU and signal
436  newSample.set(
437  true, true, gainIdx, (uint16_t)(timeToA / toaLSB_ns_), (uint16_t)(std::floor(saturatedCharge / tdcLSB_fC_)));
438  if (toaFlags[it])
439  newSample.setToAValid(true);
440  } else {
441  newSample.set(false, true, gainIdx, 0, 0);
442  }
443  } else {
444  //brute force saturation, maybe could to better with an exponential like saturation
445  const uint16_t adc = std::floor(std::min(newCharge[it], maxADC) / lsbADC);
446  //working version for in-time PU and signal
447  newSample.set(adc > thrADC, false, gainIdx, (uint16_t)(timeToA / toaLSB_ns_), adc);
448  if (toaFlags[it])
449  newSample.setToAValid(true);
450  }
451  dataFrame.setSample(it, newSample);
452  }
453 
454  if (debug) {
455  std::ostringstream msg;
456  dataFrame.print(msg);
457  edm::LogVerbatim("HGCFE") << msg.str() << std::endl;
458  }
459 }
Definition: start.py:1
std::array< bool, hgc::nSamples > busyFlags
hgc::HGCSimHitData toaFromToT
wrapper for a data word
Definition: HGCSample.h:13
float getTimeJitter(float totalCharge, int thickness)
double f[11][100]
T min(T a, T b)
Definition: MathUtil.h:58
constexpr int adc(sample_type sample)
get the ADC sample (12 bits)
void setToAValid(bool toaFired)
Definition: HGCSample.h:47
#define debug
Definition: HDRShower.cc:19
std::array< bool, hgc::nSamples > totFlags
tuple msg
Definition: mps_check.py:285
std::array< float, 6 > adcPulse_
float fast_expf(float x)
std::array< float, 6 > pulseAvgT_
std::vector< float > tdcChargeDrainParameterisation_
void set(bool thr, bool mode, uint16_t gain, uint16_t toa, uint16_t data)
Definition: HGCSample.h:49
hgc::HGCSimHitData newCharge
#define constexpr
std::array< bool, hgc::nSamples > toaFlags
template<class DFr >
void HGCFEElectronics< DFr >::runSimpleShaper ( DFr &  dataFrame,
hgc::HGCSimHitData chargeColl,
uint32_t  thrADC,
float  lsbADC,
uint32_t  gainIdx,
float  maxADC 
)

applies a shape to each time sample and propagates the tails to the subsequent time samples

Definition at line 145 of file HGCFEElectronics.cc.

References ecalMGPA::adc(), HGCFEElectronics< DFr >::adcPulse_, HGCFEElectronics< DFr >::adcThreshold_fC_, ALCARECOTkAlJpsiMuMu_cff::charge, debug, f, createfilelist::int, min(), mps_check::msg, HGCFEElectronics< DFr >::newCharge, and HGCSample::set().

Referenced by HGCFEElectronics< DFr >::runShaper(), and HGCFEElectronics< DFr >::setADClsb().

146  {
147  //convolute with pulse shape to compute new ADCs
148  newCharge.fill(0.f);
149  bool debug(false);
150  for (int it = 0; it < (int)(chargeColl.size()); it++) {
151  const float charge(chargeColl[it]);
152  if (charge == 0.f)
153  continue;
154 
155 #ifdef EDM_ML_DEBUG
157 #endif
158 
159  if (debug)
160  edm::LogVerbatim("HGCFE") << "\t Redistributing SARS ADC" << charge << " @ " << it;
161 
162  for (int ipulse = -2; ipulse < (int)(adcPulse_.size()) - 2; ipulse++) {
163  if (it + ipulse < 0)
164  continue;
165  if (it + ipulse >= (int)(dataFrame.size()))
166  continue;
167  const float chargeLeak = charge * adcPulse_[(ipulse + 2)];
168  newCharge[it + ipulse] += chargeLeak;
169 
170  if (debug)
171  edm::LogVerbatim("HGCFE") << " | " << it + ipulse << " " << chargeLeak;
172  }
173 
174  if (debug)
175  edm::LogVerbatim("HGCFE") << std::endl;
176  }
177 
178  for (int it = 0; it < (int)(newCharge.size()); it++) {
179  //brute force saturation, maybe could to better with an exponential like saturation
180  const uint32_t adc = std::floor(std::min(newCharge[it], maxADC) / lsbADC);
181  HGCSample newSample;
182  newSample.set(adc > thrADC, false, gainIdx, 0, adc);
183  dataFrame.setSample(it, newSample);
184 
185  if (debug)
186  edm::LogVerbatim("HGCFE") << adc << " (" << std::min(newCharge[it], maxADC) << "/" << lsbADC << " ) ";
187  }
188 
189  if (debug) {
190  std::ostringstream msg;
191  dataFrame.print(msg);
192  edm::LogVerbatim("HGCFE") << msg.str() << std::endl;
193  }
194 }
wrapper for a data word
Definition: HGCSample.h:13
double f[11][100]
T min(T a, T b)
Definition: MathUtil.h:58
constexpr int adc(sample_type sample)
get the ADC sample (12 bits)
#define debug
Definition: HDRShower.cc:19
tuple msg
Definition: mps_check.py:285
std::array< float, 6 > adcPulse_
void set(bool thr, bool mode, uint16_t gain, uint16_t toa, uint16_t data)
Definition: HGCSample.h:49
hgc::HGCSimHitData newCharge
template<class DFr >
void HGCFEElectronics< DFr >::runTrivialShaper ( DFr &  dataFrame,
hgc::HGCSimHitData chargeColl,
uint32_t  thrADC,
float  lsbADC,
uint32_t  gainIdx,
float  maxADC 
)

converts charge to digis without pulse shape

Definition at line 106 of file HGCFEElectronics.cc.

References ecalMGPA::adc(), HGCFEElectronics< DFr >::adcLSB_fC_, HGCFEElectronics< DFr >::adcSaturation_fC_, HGCFEElectronics< DFr >::adcThreshold_fC_, debug, MillePedeFileConverter_cfg::e, createfilelist::int, min(), mps_check::msg, and HGCSample::set().

Referenced by HGCFEElectronics< DFr >::runShaper(), and HGCFEElectronics< DFr >::setADClsb().

107  {
108  bool debug(false);
109 
110 #ifdef EDM_ML_DEBUG
111  for (int it = 0; it < (int)(chargeColl.size()); it++)
112  debug |= (chargeColl[it] > adcThreshold_fC_);
113 #endif
114 
115  if (debug)
116  edm::LogVerbatim("HGCFE") << "[runTrivialShaper]" << std::endl;
117 
118  if (lsbADC < 0)
119  lsbADC = adcLSB_fC_;
120  if (maxADC < 0)
121  // lower adcSaturation_fC_ by one part in a million
122  // to esure largest charge convertred in bits is 0xfff==4095, not 0x1000
123  // no effect on charges loewer than; no impact on cpu time, only done once
124  maxADC = adcSaturation_fC_ * (1 - 1e-6);
125  for (int it = 0; it < (int)(chargeColl.size()); it++) {
126  //brute force saturation, maybe could to better with an exponential like saturation
127  const uint32_t adc = std::floor(std::min(chargeColl[it], maxADC) / lsbADC);
128  HGCSample newSample;
129  newSample.set(adc > thrADC, false, gainIdx, 0, adc);
130  dataFrame.setSample(it, newSample);
131 
132  if (debug)
133  edm::LogVerbatim("HGCFE") << adc << " (" << chargeColl[it] << "/" << adcLSB_fC_ << ") ";
134  }
135 
136  if (debug) {
137  std::ostringstream msg;
138  dataFrame.print(msg);
139  edm::LogVerbatim("HGCFE") << msg.str() << std::endl;
140  }
141 }
wrapper for a data word
Definition: HGCSample.h:13
T min(T a, T b)
Definition: MathUtil.h:58
constexpr int adc(sample_type sample)
get the ADC sample (12 bits)
#define debug
Definition: HDRShower.cc:19
tuple msg
Definition: mps_check.py:285
void set(bool thr, bool mode, uint16_t gain, uint16_t toa, uint16_t data)
Definition: HGCSample.h:49
template<class DFr >
void HGCFEElectronics< DFr >::setADClsb ( float  newLSB)
inline
template<class DFr >
void HGCFEElectronics< DFr >::SetNoiseValues ( const std::vector< float > &  noise_fC)
inline

Definition at line 58 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::noise_fC_.

58  {
59  noise_fC_.insert(noise_fC_.end(), noise_fC.begin(), noise_fC.end());
60  };
std::vector< float > noise_fC_
template<class DFr >
uint32_t HGCFEElectronics< DFr >::toaMode ( ) const
inline

returns how ToT will be computed

Definition at line 109 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::toaMode_.

109 { return toaMode_; }

Member Data Documentation

template<class DFr >
float HGCFEElectronics< DFr >::adcLSB_fC_
private
template<class DFr >
std::array<float, 6> HGCFEElectronics< DFr >::adcPulse_
private
template<class DFr >
float HGCFEElectronics< DFr >::adcSaturation_fC_
private
template<class DFr >
float HGCFEElectronics< DFr >::adcThreshold_fC_
private
template<class DFr >
std::array<bool, hgc::nSamples> HGCFEElectronics< DFr >::busyFlags
private

Definition at line 130 of file HGCFEElectronics.h.

Referenced by HGCFEElectronics< DFr >::runShaperWithToT().

template<class DFr >
uint32_t HGCFEElectronics< DFr >::fwVersion_
private
template<class DFr >
std::array<float, 3> HGCFEElectronics< DFr >::jitterConstant2_ns_
private
template<class DFr >
std::array<float, 3> HGCFEElectronics< DFr >::jitterNoise2_ns_
private
template<class DFr >
hgc::HGCSimHitData HGCFEElectronics< DFr >::newCharge
private
template<class DFr >
std::vector<float> HGCFEElectronics< DFr >::noise_fC_
private
template<class DFr >
std::array<float, 6> HGCFEElectronics< DFr >::pulseAvgT_
private
template<class DFr >
uint32_t HGCFEElectronics< DFr >::targetMIPvalue_ADC_
private
template<class DFr >
std::vector<float> HGCFEElectronics< DFr >::tdcChargeDrainParameterisation_
private
template<class DFr >
std::array<float, 3> HGCFEElectronics< DFr >::tdcForToAOnset_fC_
private
template<class DFr >
float HGCFEElectronics< DFr >::tdcLSB_fC_
private
template<class DFr >
float HGCFEElectronics< DFr >::tdcOnset_fC_
private
template<class DFr >
float HGCFEElectronics< DFr >::tdcResolutionInNs_
private
template<class DFr >
float HGCFEElectronics< DFr >::tdcSaturation_fC_
private
template<class DFr >
bool HGCFEElectronics< DFr >::thresholdFollowsMIP_
private

Definition at line 128 of file HGCFEElectronics.h.

template<class DFr >
std::array<bool, hgc::nSamples> HGCFEElectronics< DFr >::toaFlags
private

Definition at line 130 of file HGCFEElectronics.h.

Referenced by HGCFEElectronics< DFr >::runShaperWithToT().

template<class DFr >
hgc::HGCSimHitData HGCFEElectronics< DFr >::toaFromToT
private

Definition at line 131 of file HGCFEElectronics.h.

Referenced by HGCFEElectronics< DFr >::runShaperWithToT().

template<class DFr >
float HGCFEElectronics< DFr >::toaLSB_ns_
private
template<class DFr >
uint32_t HGCFEElectronics< DFr >::toaMode_
private
template<class DFr >
std::array<bool, hgc::nSamples> HGCFEElectronics< DFr >::totFlags
private

Definition at line 130 of file HGCFEElectronics.h.

Referenced by HGCFEElectronics< DFr >::runShaperWithToT().