CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
HPDIonFeedbackSim.cc
Go to the documentation of this file.
1 
2 // --------------------------------------------------------
3 // A class to simulated HPD ion feedback noise.
4 // The deliverable of the class is the ion feedback noise
5 // for an HcalDetId units of fC or GeV
6 //
7 // Project: HPD ion feedback
8 // Author: T.Yetkin University of Iowa, Feb. 16, 2010
9 // --------------------------------------------------------
10 
21 
22 #include "CLHEP/Random/RandBinomial.h"
23 #include "CLHEP/Random/RandGaussQ.h"
24 #include "CLHEP/Random/RandPoissonQ.h"
25 
26 using namespace edm;
27 using namespace std;
28 
29 // constants for simulation/parameterization
30 static const double pe2Charge = 0.333333; // fC/p.e.
31 
33  : theDbService(nullptr), theShapes(shapes) {}
34 
36 
38  DetId detId, double signal, double pedWidth, bool doThermal, bool isInGeV, CLHEP::HepRandomEngine* engine) {
39  // HcalDetId id = detId;
40 
41  double GeVperfC = 1.;
42  if (isInGeV)
43  GeVperfC = 1. / fCtoGeV(detId);
44 
45  double charge = signal / GeVperfC;
46 
47  double noise = 0.; // fC
48  if (charge > 3. * pedWidth) { // 3 sigma away from pedestal mean
49  int npe = int(charge / pe2Charge);
50  if (doThermal) {
51  double electronEmission = 0.08;
52  CLHEP::RandPoissonQ theRandPoissonQ(*engine, electronEmission);
53  npe += theRandPoissonQ.fire();
54  }
55 
56  noise = correctPE(detId, npe, engine) - npe;
57  }
58  return (noise * GeVperfC);
59 }
60 
61 double HPDIonFeedbackSim::correctPE(const DetId& detId, double npe, CLHEP::HepRandomEngine* engine) const {
62  double rateInTail = 0.000211988; //read this from XML file
63  double rateInSecondTail = 4.61579e-06; //read this from XML file
64 
65  // three gauss fit is applied to data to get ion feedback distribution
66  // parameters (in fC)
67  // first gaussian
68  // double p0 = 9.53192e+05;
69  // double p1 = -3.13653e-01;
70  // double p2 = 2.78350e+00;
71 
72  // second gaussian
73  // double p3 = 2.41611e+03;
74  double p4 = 2.06117e+01;
75  double p5 = 1.09239e+01;
76 
77  // third gaussian
78  // double p6 = 3.42793e+01;
79  double p7 = 5.45548e+01;
80  double p8 = 1.59696e+01;
81 
82  double noise = 0.; // fC
83  int nFirst = (int)(CLHEP::RandBinomial::shoot(engine, npe, rateInTail));
84  int nSecond = (int)(CLHEP::RandBinomial::shoot(engine, npe, rateInSecondTail));
85 
86  for (int j = 0; j < nFirst; ++j) {
87  noise += CLHEP::RandGaussQ::shoot(engine, p4, p5);
88  }
89  for (int j = 0; j < nSecond; ++j) {
90  noise += CLHEP::RandGaussQ::shoot(engine, p7, p8);
91  }
92 
93  return npe + std::max(noise / pe2Charge, 0.);
94 }
95 
96 void HPDIonFeedbackSim::addThermalNoise(CaloSamples& samples, CLHEP::HepRandomEngine* engine) {
97  // make some chance to add a PE (with a chance of feedback)
98  // for each time sample
99  double meanPE = 0.02;
100  DetId detId(samples.id());
101  int nSamples = samples.size();
102  const CaloVShape* shape = theShapes->shape(detId);
103  for (int i = 0; i < nSamples; ++i) {
104  CLHEP::RandPoissonQ theRandPoissonQ(*engine, meanPE);
105  double npe = theRandPoissonQ.fire();
106  // TODOprobably should time-smear these
107  if (npe > 0.) {
108  // chance of feedback
109  npe = correctPE(detId, npe, engine);
110  for (int j = i; j < nSamples; ++j) {
111  double timeFromPE = (j - i) * 25.;
112  samples[j] += (*shape)(timeFromPE)*npe;
113  }
114  }
115  }
116 }
117 
118 double HPDIonFeedbackSim::fCtoGeV(const DetId& detId) const {
119  assert(theDbService != nullptr);
120  HcalGenericDetId hcalGenDetId(detId);
121  const HcalGain* gains = theDbService->getGain(hcalGenDetId);
122  const HcalGainWidth* gwidths = theDbService->getGainWidth(hcalGenDetId);
123  double result = 0.0;
124  if (!gains || !gwidths) {
125  edm::LogError("HcalAmplifier") << "Could not fetch HCAL conditions for channel " << hcalGenDetId;
126  } else {
127  // only one gain will be recorded per channel, so just use capID 0 for now
128  result = gains->getValue(0);
129  }
130  return result;
131 }
HPDIonFeedbackSim(const edm::ParameterSet &, const CaloShapes *shapes)
need a shaper in order to set thermal noise
const HcalGainWidth * getGainWidth(const HcalGenericDetId &fId) const
~HPDIonFeedbackSim() override
double getIonFeedback(DetId detId, double signal, double pedWidth, bool doThermal, bool isInGeV, CLHEP::HepRandomEngine *)
virtual const CaloVShape * shape(const DetId &detId, bool precise=false) const
Definition: CaloShapes.h:14
static const double pe2Charge
double fCtoGeV(const DetId &detId) const
Electronic response of the preamp.
Definition: CaloVShape.h:11
Log< level::Error, false > LogError
float getValue(int fCapId) const
get value for capId = 0..3
Definition: HcalGain.h:21
assert(be >=bs)
tuple result
Definition: mps_fire.py:311
const HcalDbService * theDbService
void addThermalNoise(CaloSamples &samples, CLHEP::HepRandomEngine *)
double correctPE(const DetId &detId, double npe, CLHEP::HepRandomEngine *) const override
constexpr size_t nSamples
__shared__ int noise
Definition: DetId.h:17
int size() const
get the size
Definition: CaloSamples.h:24
const HcalGain * getGain(const HcalGenericDetId &fId) const
const CaloShapes * theShapes
DetId id() const
get the (generic) id
Definition: CaloSamples.h:21