CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/src/SimCalorimetry/HcalSimAlgos/src/HcalAmplifier.cc

Go to the documentation of this file.
00001 #include "SimCalorimetry/HcalSimAlgos/interface/HcalAmplifier.h"
00002 #include "SimCalorimetry/HcalSimAlgos/interface/HcalSimParameters.h"
00003 #include "SimCalorimetry/HcalSimAlgos/interface/HPDIonFeedbackSim.h"
00004 #include "SimCalorimetry/HcalSimAlgos/interface/HcalTimeSlewSim.h"
00005 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVSimParameterMap.h"
00006 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVNoiseSignalGenerator.h"
00007 #include "CalibFormats/HcalObjects/interface/HcalDbService.h"
00008 #include "CondFormats/HcalObjects/interface/HcalPedestal.h"
00009 #include "CondFormats/HcalObjects/interface/HcalGain.h"
00010 #include "CondFormats/HcalObjects/interface/HcalPedestalWidth.h"
00011 #include "CondFormats/HcalObjects/interface/HcalGainWidth.h"
00012 #include "CalibFormats/CaloObjects/interface/CaloSamples.h"
00013 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 
00016 #include "CalibFormats/HcalObjects/interface/HcalCalibrations.h"
00017 
00018 #include<iostream>
00019 #include <cmath>
00020 #include <math.h>
00021 
00022 HcalAmplifier::HcalAmplifier(const CaloVSimParameterMap * parameters, bool addNoise) :
00023   theDbService(0), 
00024   theRandGaussQ(0),
00025   theRandFlat(0),
00026   theParameterMap(parameters),
00027   theNoiseSignalGenerator(0),
00028   theIonFeedbackSim(0),
00029   theTimeSlewSim(0),
00030   theStartingCapId(0), 
00031   addNoise_(addNoise),
00032   useOldHB(false),
00033   useOldHE(false),
00034   useOldHF(false),
00035   useOldHO(false)
00036 {
00037 }
00038 
00039 
00040 void HcalAmplifier::setDbService(const HcalDbService * service) {
00041   theDbService = service;
00042   if(theIonFeedbackSim) theIonFeedbackSim->setDbService(service);
00043 }
00044 
00045 
00046 void HcalAmplifier::setRandomEngine(CLHEP::HepRandomEngine & engine)
00047 {
00048   theRandGaussQ = new CLHEP::RandGaussQ(engine);
00049   theRandFlat = new CLHEP::RandFlat(engine);
00050   if(theIonFeedbackSim) theIonFeedbackSim->setRandomEngine(engine);
00051 }
00052 
00053 
00054 void HcalAmplifier::amplify(CaloSamples & frame) const {
00055   if(theIonFeedbackSim)
00056   {
00057     theIonFeedbackSim->addThermalNoise(frame);
00058   }
00059   pe2fC(frame);
00060   // don't bother for blank signals
00061   if(theTimeSlewSim && frame[4] > 1.e-6)
00062   {
00063     theTimeSlewSim->delay(frame);
00064   }
00065   if(theNoiseSignalGenerator==0 || !theNoiseSignalGenerator->contains(frame.id()))
00066   {
00067     addPedestals(frame);
00068   }
00069   LogDebug("HcalAmplifier") << frame;
00070 }
00071 
00072 
00073 void HcalAmplifier::pe2fC(CaloSamples & frame) const
00074 {
00075   const CaloSimParameters & parameters = theParameterMap->simParameters(frame.id());
00076   frame *= parameters.photoelectronsToAnalog(frame.id());
00077 }
00078 
00079 void HcalAmplifier::setHBtuningParameter(double tp) { HB_ff = tp; }
00080 void HcalAmplifier::setHEtuningParameter(double tp) { HE_ff = tp; }
00081 void HcalAmplifier::setHFtuningParameter(double tp) { HF_ff = tp; }
00082 void HcalAmplifier::setHOtuningParameter(double tp) { HO_ff = tp; }
00083 void HcalAmplifier::setUseOldHB(bool useOld) { useOldHB = useOld; }
00084 void HcalAmplifier::setUseOldHE(bool useOld) { useOldHE = useOld; }
00085 void HcalAmplifier::setUseOldHF(bool useOld) { useOldHF = useOld; }
00086 void HcalAmplifier::setUseOldHO(bool useOld) { useOldHO = useOld; }
00087 
00088 void HcalAmplifier::addPedestals(CaloSamples & frame) const
00089 {
00090    assert(theDbService != 0);
00091    HcalGenericDetId hcalGenDetId(frame.id());
00092    HcalGenericDetId::HcalGenericSubdetector hcalSubDet = hcalGenDetId.genericSubdet();
00093 
00094    bool useOld=false;
00095    if(hcalSubDet==HcalGenericDetId::HcalGenBarrel) useOld = useOldHB;
00096    if(hcalSubDet==HcalGenericDetId::HcalGenEndcap) useOld = useOldHE;
00097    if(hcalSubDet==HcalGenericDetId::HcalGenForward) useOld = useOldHF;
00098    if(hcalSubDet==HcalGenericDetId::HcalGenOuter) useOld = useOldHO;
00099    
00100    if(useOld)
00101    {
00102      const HcalCalibrationWidths & calibWidths =
00103        theDbService->getHcalCalibrationWidths(hcalGenDetId);
00104      const HcalCalibrations& calibs = theDbService->getHcalCalibrations(hcalGenDetId);
00105    
00106      double noise [32] = {0.}; //big enough
00107      if(addNoise_)
00108      {
00109        double gauss [32]; //big enough
00110        for (int i = 0; i < frame.size(); i++) gauss[i] = theRandGaussQ->fire(0., 1.);
00111        makeNoiseOld(hcalSubDet, calibWidths, frame.size(), gauss, noise);
00112      }
00113    
00114      for (int tbin = 0; tbin < frame.size(); ++tbin) {
00115        int capId = (theStartingCapId + tbin)%4;
00116        double pedestal = calibs.pedestal(capId) + noise[tbin];
00117        frame[tbin] += pedestal;
00118      }
00119      return;
00120    }
00121 
00122 
00123   double fudgefactor = 1;
00124   if(hcalSubDet==HcalGenericDetId::HcalGenBarrel) fudgefactor = HB_ff;
00125   if(hcalSubDet==HcalGenericDetId::HcalGenEndcap) fudgefactor = HE_ff;
00126   if(hcalSubDet==HcalGenericDetId::HcalGenForward) fudgefactor = HF_ff;
00127   if(hcalSubDet==HcalGenericDetId::HcalGenOuter) fudgefactor = HO_ff;
00128   if(hcalGenDetId.isHcalCastorDetId()) return;
00129   if(hcalGenDetId.isHcalZDCDetId()) return;
00130 
00131   const HcalCholeskyMatrix * thisChanCholesky = myCholeskys->getValues(hcalGenDetId);
00132   const HcalPedestal * thisChanADCPeds = myADCPeds->getValues(hcalGenDetId);
00133   int theStartingCapId_2 = (int)floor(theRandFlat->fire(0.,4.));
00134 
00135   double noise [32] = {0.}; //big enough
00136   if(addNoise_)
00137   {
00138     double gauss [32]; //big enough
00139     for (int i = 0; i < frame.size(); i++) gauss[i] = theRandGaussQ->fire(0., 1.);
00140     makeNoise(*thisChanCholesky, frame.size(), gauss, noise, (int)theStartingCapId_2);
00141   }
00142 
00143   const HcalQIECoder* coder = theDbService->getHcalCoder(hcalGenDetId);
00144   const HcalQIEShape* shape = theDbService->getHcalShape();
00145 
00146   for (int tbin = 0; tbin < frame.size(); ++tbin) {
00147     int capId = (theStartingCapId_2 + tbin)%4;
00148     double x = noise[tbin] * fudgefactor + thisChanADCPeds->getValue(capId);//*(values+capId); //*.70 goes here!
00149     int x1=(int)std::floor(x);
00150     int x2=(int)std::floor(x+1);
00151     float y2=coder->charge(*shape,x2,capId);
00152     float y1=coder->charge(*shape,x1,capId);
00153     frame[tbin] = (y2-y1)*(x-x1)+y1;
00154   }
00155 }
00156 
00157 void HcalAmplifier::makeNoise (const HcalCholeskyMatrix & thisChanCholesky, int fFrames, double* fGauss, double* fNoise, int m) const {
00158    if(fFrames > 10) return;
00159 
00160    for(int i = 0; i != 10; i++){
00161       for(int j = 0; j != 10; j++){ //fNoise is initialized to zero in function above! Must be zero before this step
00162          fNoise[i] += thisChanCholesky.getValue(m,i,j) * fGauss[j];
00163       }
00164    }
00165 }
00166 
00167 void HcalAmplifier::makeNoiseOld (HcalGenericDetId::HcalGenericSubdetector hcalSubDet, const HcalCalibrationWidths& width, int fFrames, double* fGauss, double* fNoise) const 
00168 {
00169   // This is a simplified noise generation scheme using only the diagonal elements
00170   // (proposed by Salavat Abduline).
00171   // This is direct adaptation of the code in HcalPedestalWidth.cc
00172   
00173   // average over capId's
00174   double s_xx_mean =  0.25 * (width.pedestal(0)*width.pedestal(0) + 
00175                               width.pedestal(1)*width.pedestal(1) + 
00176                               width.pedestal(2)*width.pedestal(2) + 
00177                               width.pedestal(3)*width.pedestal(3));
00178 
00179 
00180   // Off-diagonal element approximation
00181   // In principle should come from averaging the values of elements (0.1), (1,2), (2,3), (3,0)
00182   // For now use the definition below (but keep structure of the code structure for development) 
00183   double s_xy_mean = -0.5 * s_xx_mean;
00184   // Use different parameter for HF to reproduce the noise rate after zero suppression.
00185   // Steven Won/Jim Hirschauer/Radek Ofierzynski 18.03.2010
00186   if (hcalSubDet == HcalGenericDetId::HcalGenForward) s_xy_mean = 0.08 * s_xx_mean;
00187 
00188   double term  = s_xx_mean*s_xx_mean - 2.*s_xy_mean*s_xy_mean;
00189 
00190   if (term < 0.) term = 1.e-50 ;
00191   double sigma = sqrt (0.5 * (s_xx_mean + sqrt(term)));
00192   double corr = sigma == 0. ? 0. : 0.5*s_xy_mean / sigma;
00193 
00194   for (int i = 0; i < fFrames; i++) {
00195     fNoise [i] = fGauss[i]*sigma;
00196     if (i > 0) fNoise [i] += fGauss[i-1]*corr;
00197     if (i < fFrames-1) fNoise [i] += fGauss[i+1]*corr;
00198   }
00199 }
00200