CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HcalAmplifier.cc
Go to the documentation of this file.
15 
17 
18 #include "CLHEP/Random/RandGaussQ.h"
19 #include "CLHEP/Random/RandFlat.h"
20 
21 #include <cmath>
22 #include <math.h>
23 
24 HcalAmplifier::HcalAmplifier(const CaloVSimParameterMap * parameters, bool addNoise, bool PreMix1, bool PreMix2) :
25  theDbService(nullptr),
26  theParameterMap(parameters),
27  theNoiseSignalGenerator(nullptr),
28  myCholeskys(nullptr),
29  myADCPeds(nullptr),
30  theIonFeedbackSim(nullptr),
31  theTimeSlewSim(nullptr),
32  theStartingCapId(0),
33  addNoise_(addNoise),
34  preMixDigi_(PreMix1),
35  preMixAdd_(PreMix2),
36  useOldHB(false),
37  useOldHE(false),
38  useOldHF(false),
39  useOldHO(false)
40 { }
41 
42 
46 }
47 
48 
49 void HcalAmplifier::amplify(CaloSamples & frame, CLHEP::HepRandomEngine* engine) const {
51  {
52  theIonFeedbackSim->addThermalNoise(frame, engine);
53  }
54  pe2fC(frame);
55  // don't bother for blank signals
56  if(theTimeSlewSim && frame[4] > 1.e-6)
57  {
58  theTimeSlewSim->delay(frame, engine);
59  }
60 
61  // if we are combining pre-mixed digis, we need noise and peds
63  {
64  addPedestals(frame, engine);
65  }
66  LogDebug("HcalAmplifier") << frame;
67 }
68 
69 
70 void HcalAmplifier::pe2fC(CaloSamples & frame) const
71 {
73  frame *= parameters.photoelectronsToAnalog(frame.id());
74 }
75 
76 void HcalAmplifier::setHBtuningParameter(double tp) { HB_ff = tp; }
77 void HcalAmplifier::setHEtuningParameter(double tp) { HE_ff = tp; }
78 void HcalAmplifier::setHFtuningParameter(double tp) { HF_ff = tp; }
79 void HcalAmplifier::setHOtuningParameter(double tp) { HO_ff = tp; }
80 void HcalAmplifier::setUseOldHB(bool useOld) { useOldHB = useOld; }
81 void HcalAmplifier::setUseOldHE(bool useOld) { useOldHE = useOld; }
82 void HcalAmplifier::setUseOldHF(bool useOld) { useOldHF = useOld; }
83 void HcalAmplifier::setUseOldHO(bool useOld) { useOldHO = useOld; }
84 
85 void HcalAmplifier::addPedestals(CaloSamples & frame, CLHEP::HepRandomEngine* engine) const
86 {
87  assert(theDbService != 0);
88  HcalGenericDetId hcalGenDetId(frame.id());
89  HcalGenericDetId::HcalGenericSubdetector hcalSubDet = hcalGenDetId.genericSubdet();
90 
91  bool useOld=false;
92  if(hcalSubDet==HcalGenericDetId::HcalGenBarrel) useOld = useOldHB;
93  if(hcalSubDet==HcalGenericDetId::HcalGenEndcap) useOld = useOldHE;
94  if(hcalSubDet==HcalGenericDetId::HcalGenForward) useOld = useOldHF;
95  if(hcalSubDet==HcalGenericDetId::HcalGenOuter) useOld = useOldHO;
96 
97  if(useOld)
98  {
99  const HcalCalibrationWidths & calibWidths =
100  theDbService->getHcalCalibrationWidths(hcalGenDetId);
101  const HcalCalibrations& calibs = theDbService->getHcalCalibrations(hcalGenDetId);
102 
103  double noise [32] = {0.}; //big enough
104  if(addNoise_)
105  {
106  double gauss [32]; //big enough
107  for (int i = 0; i < frame.size(); i++) gauss[i] = CLHEP::RandGaussQ::shoot(engine, 0., 1.);
108  makeNoiseOld(hcalSubDet, calibWidths, frame.size(), gauss, noise);
109  }
110 
111  if(!preMixDigi_){ // if we are doing initial premix, no pedestals
112  for (int tbin = 0; tbin < frame.size(); ++tbin) {
113  int capId = (theStartingCapId + tbin)%4;
114  double pedestal = calibs.pedestal(capId) + noise[tbin];
115 
116  frame[tbin] += pedestal;
117  }
118  }
119  return;
120  }
121 
122 
123  double fudgefactor = 1;
124  if(hcalSubDet==HcalGenericDetId::HcalGenBarrel) fudgefactor = HB_ff;
125  if(hcalSubDet==HcalGenericDetId::HcalGenEndcap) fudgefactor = HE_ff;
126  if(hcalSubDet==HcalGenericDetId::HcalGenForward) fudgefactor = HF_ff;
127  if(hcalSubDet==HcalGenericDetId::HcalGenOuter) fudgefactor = HO_ff;
128 
129  if ( !( (frame.id().subdetId()==HcalGenericDetId::HcalGenBarrel) ||
132  (frame.id().subdetId()==HcalGenericDetId::HcalGenOuter) ) ) return;
133 
134  if(hcalGenDetId.isHcalCastorDetId()) return;
135  if(hcalGenDetId.isHcalZDCDetId()) return;
136 
137  int theStartingCapId_2 = (int)floor(CLHEP::RandFlat::shoot(engine, 0., 4.));
138  double noise [32] = {0.}; //big enough
139 
140  if( myCholeskys ) {
141  const HcalCholeskyMatrix * thisChanCholesky = myCholeskys->getValues(hcalGenDetId,false);
142  if ( !thisChanCholesky ) {
143  edm::LogWarning("HcalAmplifier") << "no Cholesky " << hcalSubDet << " "
144  << hcalGenDetId.rawId() << " "
145  << frame.id().subdetId();
146  return;
147  }
148 
149  if(addNoise_)
150  {
151  double gauss [32]; //big enough
152  for (int i = 0; i < frame.size(); i++) gauss[i] = CLHEP::RandGaussQ::shoot(engine, 0., 1.);
153  makeNoise(*thisChanCholesky, frame.size(), gauss, noise, (int)theStartingCapId_2);
154  }
155  } else if(addNoise_) {
156  /* TODO: Re-add the Cholesky matrix when computing the noise.
157  * The payloads currently stored in Condition DB suffer a bug in ROOT5 streamer.
158  * The workaround here is to fall back to the old noise computation when the matrix is not provided.
159  * When a permanent fix is found, this condition should be removed:
160  * when Cholesky matrix is not set from the digitizer, issue a warning.
161  * -Salvatore Di Guida
162  */
163  const HcalCalibrationWidths & calibWidths = theDbService->getHcalCalibrationWidths(hcalGenDetId);
164  double gauss [32]; //big enough
165  for (int i = 0; i < frame.size(); i++) gauss[i] = CLHEP::RandGaussQ::shoot(engine, 0., 1.);
166  makeNoiseOld(hcalSubDet, calibWidths, frame.size(), gauss, noise);
167  } else {
168  edm::LogWarning("HcalAmplifier") << "No Cholesky Matrices provided for new HCAL noise simulation.";
169  }
170 
171  if( myADCPeds ) {
172  const HcalPedestal* thisChanADCPeds = myADCPeds->getValues(hcalGenDetId);
173  const HcalQIECoder* coder = theDbService->getHcalCoder(hcalGenDetId);
174  const HcalQIEShape* shape = theDbService->getHcalShape(coder);
175 
176  for (int tbin = 0; tbin < frame.size(); ++tbin) {
177  int capId = (theStartingCapId_2 + tbin)%4;
178  double x = noise[tbin] * fudgefactor + thisChanADCPeds->getValue(capId);//*(values+capId); //*.70 goes here!
179  int x1=(int)std::floor(x);
180  int x2=(int)std::floor(x+1);
181  float y2=coder->charge(*shape,x2,capId);
182  float y1=coder->charge(*shape,x1,capId);
183  frame[tbin] = (y2-y1)*(x-x1)+y1;
184  }
185  } else {
186  edm::LogWarning("HcalAmplifier") << "No ADC pedestals provided for new HCAL simulation.";
187  }
188 }
189 
190 void HcalAmplifier::makeNoise (const HcalCholeskyMatrix & thisChanCholesky, int fFrames, double* fGauss, double* fNoise, int m) const {
191  if(fFrames > 10) return;
192 
193  for(int i = 0; i != 10; i++){
194  for(int j = 0; j != 10; j++){ //fNoise is initialized to zero in function above! Must be zero before this step
195  fNoise[i] += thisChanCholesky.getValue(m,i,j) * fGauss[j];
196  }
197  }
198 }
199 
200 void HcalAmplifier::makeNoiseOld (HcalGenericDetId::HcalGenericSubdetector hcalSubDet, const HcalCalibrationWidths& width, int fFrames, double* fGauss, double* fNoise) const
201 {
202  // This is a simplified noise generation scheme using only the diagonal elements
203  // (proposed by Salavat Abduline).
204  // This is direct adaptation of the code in HcalPedestalWidth.cc
205 
206  // average over capId's
207  double s_xx_mean = 0.25 * (width.pedestal(0)*width.pedestal(0) +
208  width.pedestal(1)*width.pedestal(1) +
209  width.pedestal(2)*width.pedestal(2) +
210  width.pedestal(3)*width.pedestal(3));
211 
212 
213  // Off-diagonal element approximation
214  // In principle should come from averaging the values of elements (0.1), (1,2), (2,3), (3,0)
215  // For now use the definition below (but keep structure of the code structure for development)
216  double s_xy_mean = -0.5 * s_xx_mean;
217  // Use different parameter for HF to reproduce the noise rate after zero suppression.
218  // Steven Won/Jim Hirschauer/Radek Ofierzynski 18.03.2010
219  if (hcalSubDet == HcalGenericDetId::HcalGenForward) s_xy_mean = 0.08 * s_xx_mean;
220 
221  double term = s_xx_mean*s_xx_mean - 2.*s_xy_mean*s_xy_mean;
222 
223  if (term < 0.) term = 1.e-50 ;
224  double sigma = sqrt (0.5 * (s_xx_mean + sqrt(term)));
225  double corr = sigma == 0. ? 0. : 0.5*s_xy_mean / sigma;
226 
227  for (int i = 0; i < fFrames; i++) {
228  fNoise [i] = fGauss[i]*sigma;
229  if (i > 0) fNoise [i] += fGauss[i-1]*corr;
230  if (i < fFrames-1) fNoise [i] += fGauss[i+1]*corr;
231  }
232 }
233 
#define LogDebug(id)
void setUseOldHB(bool useOld)
float getValue(int capid, int i, int j) const
void setHOtuningParameter(double tp)
void makeNoiseOld(HcalGenericDetId::HcalGenericSubdetector hcalSubDet, const HcalCalibrationWidths &width, int fFrames, double *fGauss, double *fNoise) const
void setDbService(const HcalDbService *service)
the Producer will probably update this every event
const CaloVNoiseSignalGenerator * theNoiseSignalGenerator
Definition: HcalAmplifier.h:65
int i
Definition: DBlmapReader.cc:9
dictionary parameters
Definition: Parameters.py:2
const CaloVSimParameterMap * theParameterMap
Definition: HcalAmplifier.h:64
void setUseOldHF(bool useOld)
double pedestal(int fCapId) const
get pedestal for capid=0..3
const Item * getValues(DetId fId, bool throwOnFail=true) const
void setHFtuningParameter(double tp)
#define nullptr
Main class for Parameters in different subdetectors.
HcalAmplifier(const CaloVSimParameterMap *parameters, bool addNoise, bool PreMix1, bool PreMix2)
void addThermalNoise(CaloSamples &samples, CLHEP::HepRandomEngine *)
void setUseOldHO(bool useOld)
void delay(CaloSamples &samples, CLHEP::HepRandomEngine *) const
void setHEtuningParameter(double tp)
void setUseOldHE(bool useOld)
double pedestal(int fCapId) const
get pedestal width for capid=0..3
const HcalDbService * theDbService
Definition: HcalAmplifier.h:63
T sqrt(T t)
Definition: SSEVec.h:48
bool contains(const DetId &detId) const
int j
Definition: DBlmapReader.cc:9
virtual const CaloSimParameters & simParameters(const DetId &id) const =0
float getValue(int fCapId) const
get value for capId = 0..3
Definition: HcalPedestal.h:21
int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:37
const HcalCalibrationWidths & getHcalCalibrationWidths(const HcalGenericDetId &fId) const
virtual void amplify(CaloSamples &linearFrame, CLHEP::HepRandomEngine *) const
HcalTimeSlewSim * theTimeSlewSim
Definition: HcalAmplifier.h:69
JetCorrectorParameters corr
Definition: classes.h:5
int size() const
get the size
Definition: CaloSamples.h:24
void makeNoise(const HcalCholeskyMatrix &thisChanCholesky, int fFrames, double *fGauss, double *fNoise, int m) const
const HcalQIECoder * getHcalCoder(const HcalGenericDetId &fId) const
const HcalQIEShape * getHcalShape(const HcalGenericDetId &fId) const
unsigned theStartingCapId
Definition: HcalAmplifier.h:70
void addPedestals(CaloSamples &frame, CLHEP::HepRandomEngine *) const
void pe2fC(CaloSamples &frame) const
volatile std::atomic< bool > shutdown_flag false
DetId id() const
get the (generic) id
Definition: CaloSamples.h:21
HPDIonFeedbackSim * theIonFeedbackSim
Definition: HcalAmplifier.h:68
HcalGenericSubdetector genericSubdet() const
Definition: DDAxes.h:10
void setHBtuningParameter(double tp)
const HcalCholeskyMatrix * getValues(DetId fId, bool throwOnFail=true) const
const HcalCalibrations & getHcalCalibrations(const HcalGenericDetId &fId) const
void setDbService(const HcalDbService *service)
const HcalPedestals * myADCPeds
Definition: HcalAmplifier.h:67
double photoelectronsToAnalog() const
the factor which goes from photoelectrons to whatever gets read by ADCs
const HcalCholeskyMatrices * myCholeskys
Definition: HcalAmplifier.h:66
float charge(const HcalQIEShape &fShape, unsigned fAdc, unsigned fCapId) const
ADC [0..127] + capid [0..3] -&gt; fC conversion.
Definition: HcalQIECoder.cc:22