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 ()
 
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, int thickness, CLHEP::HepRandomEngine *engine, float cce=1.0)
 switches according to the firmware version More...
 
void runShaperWithToT (DFr &dataFrame, hgc::HGCSimHitData &chargeColl, hgc::HGCSimHitData &toa, int thickness, CLHEP::HepRandomEngine *engine, float cce=1.0)
 implements pulse shape and switch to time over threshold including deadtime More...
 
void runSimpleShaper (DFr &dataFrame, hgc::HGCSimHitData &chargeColl, int thickness, float cce=1.0)
 applies a shape to each time sample and propagates the tails to the subsequent time samples More...
 
void runTrivialShaper (DFr &dataFrame, hgc::HGCSimHitData &chargeColl, int thickness, float cce=1.0)
 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_
 
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 24 of file HGCFEElectronics.h.

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

Definition at line 25 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, objects.autophobj::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 >::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 >::thresholdFollowsMIP_, HGCFEElectronics< DFr >::toaLSB_ns_, HGCFEElectronics< DFr >::toaMode_, heppy_batch::val, and HGCFEElectronics< DFr >::WEIGHTEDBYE.

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

DTOR.

Definition at line 93 of file HGCFEElectronics.h.

93 {}

Member Function Documentation

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

returns the LSB in MIP currently configured

Definition at line 62 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::adcLSB_fC_.

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

Definition at line 64 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::adcThreshold_fC_.

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

Definition at line 66 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::tdcForToAOnset_fC_.

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

Definition at line 63 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::tdcLSB_fC_.

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

Definition at line 65 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::tdcOnset_fC_.

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

Definition at line 51 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().

51  {
52  float A2 = jitterNoise2_ns_.at(thickness-1);
53  float C2 = jitterConstant2_ns_.at(thickness-1);
54  float X2 = pow((totalCharge/noise_fC_.at(thickness-1)), 2.);
55  float jitter2 = A2 / X2 + C2;
56  return sqrt(jitter2);
57  };
T sqrt(T t)
Definition: SSEVec.h:18
std::vector< float > noise_fC_
std::array< float, 3 > jitterNoise2_ns_
std::array< float, 3 > jitterConstant2_ns_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
template<class DFr >
void HGCFEElectronics< DFr >::runShaper ( DFr &  dataFrame,
hgc::HGCSimHitData chargeColl,
hgc::HGCSimHitData toa,
int  thickness,
CLHEP::HepRandomEngine *  engine,
float  cce = 1.0 
)
inline

switches according to the firmware version

Definition at line 35 of file HGCFEElectronics.h.

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

37  {
38  switch(fwVersion_)
39  {
40  case SIMPLE : { runSimpleShaper(dataFrame,chargeColl, thickness, cce); break; }
41  case WITHTOT : { runShaperWithToT(dataFrame,chargeColl,toa, thickness, engine, cce); break; }
42  default : { runTrivialShaper(dataFrame,chargeColl, thickness, cce); break; }
43  }
44  }
void runShaperWithToT(DFr &dataFrame, hgc::HGCSimHitData &chargeColl, hgc::HGCSimHitData &toa, int thickness, CLHEP::HepRandomEngine *engine, float cce=1.0)
implements pulse shape and switch to time over threshold including deadtime
void runSimpleShaper(DFr &dataFrame, hgc::HGCSimHitData &chargeColl, int thickness, float cce=1.0)
applies a shape to each time sample and propagates the tails to the subsequent time samples ...
void runTrivialShaper(DFr &dataFrame, hgc::HGCSimHitData &chargeColl, int thickness, float cce=1.0)
converts charge to digis without pulse shape
template<class DFr >
void HGCFEElectronics< DFr >::runShaperWithToT ( DFr &  dataFrame,
hgc::HGCSimHitData chargeColl,
hgc::HGCSimHitData toa,
int  thickness,
CLHEP::HepRandomEngine *  engine,
float  cce = 1.0 
)

implements pulse shape and switch to time over threshold including deadtime

Definition at line 192 of file HGCFEElectronics.cc.

References HGCFEElectronics< DFr >::adcLSB_fC_, HGCFEElectronics< DFr >::adcPulse_, HGCFEElectronics< DFr >::adcSaturation_fC_, HGCFEElectronics< DFr >::adcThreshold_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 >::thresholdFollowsMIP_, 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().

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

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

Definition at line 140 of file HGCFEElectronics.cc.

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

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

141 {
142  //convolute with pulse shape to compute new ADCs
143  newCharge.fill(0.f);
144  bool debug(false);
145  for(int it=0; it<(int)(chargeColl.size()); it++)
146  {
147  const float charge(chargeColl[it]);
148  if(charge==0.f) continue;
149 
150 #ifdef EDM_ML_DEBUG
152 #endif
153 
154  if(debug) edm::LogVerbatim("HGCFE") << "\t Redistributing SARS ADC" << charge << " @ " << it;
155 
156  for(int ipulse=-2; ipulse<(int)(adcPulse_.size())-2; ipulse++)
157  {
158  if(it+ipulse<0) continue;
159  if(it+ipulse>=(int)(dataFrame.size())) continue;
160  const float chargeLeak=charge*adcPulse_[(ipulse+2)];
161  newCharge[it+ipulse]+= chargeLeak;
162 
163  if(debug) edm::LogVerbatim("HGCFE") << " | " << it+ipulse << " " << chargeLeak;
164  }
165 
166  if(debug) edm::LogVerbatim("HGCFE") << std::endl;
167  }
168 
169  //set new ADCs
170  const float adj_thresh = thresholdFollowsMIP_ ? thickness*adcThreshold_fC_*cce : thickness*adcThreshold_fC_;
171 
172  for(int it=0; it<(int)(newCharge.size()); it++)
173  {
174  //brute force saturation, maybe could to better with an exponential like saturation
175  const float saturatedCharge(std::min(newCharge[it],adcSaturation_fC_));
176  HGCSample newSample;
177  newSample.set(newCharge[it]>adj_thresh,false,0,std::floor(saturatedCharge/adcLSB_fC_));
178  dataFrame.setSample(it,newSample);
179 
180  if(debug) edm::LogVerbatim("HGCFE") << std::floor(saturatedCharge/adcLSB_fC_) << " (" << saturatedCharge << "/" << adcLSB_fC_ <<" ) " ;
181  }
182 
183  if(debug) {
184  std::ostringstream msg;
185  dataFrame.print(msg);
186  edm::LogVerbatim("HGCFE") << msg.str() << std::endl;
187  }
188 }
wrapper for a data word
Definition: HGCSample.h:13
double f[11][100]
T min(T a, T b)
Definition: MathUtil.h:58
#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 toa, uint16_t data)
Definition: HGCSample.h:35
hgc::HGCSimHitData newCharge
template<class DFr >
void HGCFEElectronics< DFr >::runTrivialShaper ( DFr &  dataFrame,
hgc::HGCSimHitData chargeColl,
int  thickness,
float  cce = 1.0 
)

converts charge to digis without pulse shape

Definition at line 107 of file HGCFEElectronics.cc.

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

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

108 {
109  bool debug(false);
110 
111 #ifdef EDM_ML_DEBUG
112  for(int it=0; it<(int)(chargeColl.size()); it++) debug |= (chargeColl[it]>adcThreshold_fC_);
113 #endif
114 
115  if(debug) edm::LogVerbatim("HGCFE") << "[runTrivialShaper]" << std::endl;
116 
117  //set new ADCs
118  const float adj_thresh = thresholdFollowsMIP_ ? thickness*adcThreshold_fC_*cce : thickness*adcThreshold_fC_;
119 
120  for(int it=0; it<(int)(chargeColl.size()); it++)
121  {
122  //brute force saturation, maybe could to better with an exponential like saturation
123  const uint32_t adc=std::floor( std::min(chargeColl[it],adcSaturation_fC_) / adcLSB_fC_ );
124  HGCSample newSample;
125  newSample.set(chargeColl[it]>adj_thresh,false,0,adc);
126  dataFrame.setSample(it,newSample);
127 
128  if(debug) edm::LogVerbatim("HGCFE") << adc << " (" << chargeColl[it] << "/" << adcLSB_fC_ << ") ";
129  }
130 
131  if(debug) {
132  std::ostringstream msg;
133  dataFrame.print(msg);
134  edm::LogVerbatim("HGCFE") << msg.str() << std::endl;
135  }
136 }
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 toa, uint16_t data)
Definition: HGCSample.h:35
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 47 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::noise_fC_.

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

returns how ToT will be computed

Definition at line 88 of file HGCFEElectronics.h.

References HGCFEElectronics< DFr >::toaMode_.

88 { 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 109 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 >
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
template<class DFr >
std::array<bool,hgc::nSamples> HGCFEElectronics< DFr >::toaFlags
private

Definition at line 109 of file HGCFEElectronics.h.

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

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

Definition at line 110 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 109 of file HGCFEElectronics.h.

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