CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/SimCalorimetry/HcalSimAlgos/src/HPDIonFeedbackSim.cc

Go to the documentation of this file.
00001 
00002 // --------------------------------------------------------
00003 // A class to simulated HPD ion feedback noise.
00004 // The deliverable of the class is the ion feedback noise
00005 // for an HcalDetId units of fC or GeV
00006 //
00007 // Project: HPD ion feedback
00008 // Author: T.Yetkin University of Iowa, Feb. 16, 2010
00009 // $Id: HPDIonFeedbackSim.cc,v 1.6 2011/11/14 11:08:16 abdullin Exp $
00010 // --------------------------------------------------------
00011 
00012 #include "SimCalorimetry/HcalSimAlgos/interface/HPDIonFeedbackSim.h"
00013 #include "SimCalorimetry/HcalSimAlgos/interface/HcalShapes.h"
00014 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVShape.h"
00015 #include "CondFormats/HcalObjects/interface/HcalGain.h"
00016 #include "CondFormats/HcalObjects/interface/HcalGainWidth.h"
00017 #include "DataFormats/HcalDetId/interface/HcalGenericDetId.h"
00018 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00019 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00020 #include "FWCore/ServiceRegistry/interface/Service.h"
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022 #include "FWCore/PluginManager/interface/PluginManager.h"
00023 #include "FWCore/PluginManager/interface/standard.h"
00024 
00025 
00026 using namespace edm;
00027 using namespace std;
00028 
00029 // constants for simulation/parameterization
00030 double pe2Charge = 0.333333;    // fC/p.e.
00031 
00032 HPDIonFeedbackSim::HPDIonFeedbackSim(const edm::ParameterSet & iConfig, const CaloShapes * shapes)
00033 : theDbService(0), theShapes(shapes),
00034  theRandBinomial(0), theRandFlat(0), theRandGauss(0), theRandPoissonQ(0)
00035 {
00036 }
00037 
00038 HPDIonFeedbackSim::~HPDIonFeedbackSim() 
00039 {
00040     if(theRandBinomial) delete theRandBinomial;
00041     if (theRandFlat) delete theRandFlat;
00042     if (theRandGauss) delete theRandGauss;
00043     if (theRandPoissonQ) delete theRandPoissonQ;
00044 }
00045 
00046 
00047 void HPDIonFeedbackSim::setRandomEngine(CLHEP::HepRandomEngine & engine) 
00048 {
00049     if(theRandBinomial) delete theRandBinomial;
00050     if (theRandFlat) delete theRandFlat;
00051     if (theRandGauss) delete theRandGauss;
00052     if (theRandPoissonQ) delete theRandPoissonQ;
00053 
00054     theRandBinomial = new CLHEP::RandBinomial(engine);
00055     theRandFlat = new CLHEP::RandFlat(engine);
00056     theRandGauss = new CLHEP::RandGaussQ(engine);
00057     theRandPoissonQ = new CLHEP::RandPoissonQ(engine);
00058 }
00059 
00060 double HPDIonFeedbackSim::getIonFeedback(DetId detId, double signal, double pedWidth, bool doThermal, bool isInGeV) 
00061 {
00062     
00063   //    HcalDetId id = detId; 
00064     
00065     double GeVperfC = 1.;
00066     if(isInGeV) GeVperfC = 1./fCtoGeV(detId);
00067     
00068     double charge = signal / GeVperfC;
00069     
00070     double noise = 0.;          // fC
00071     if (charge > 3. * pedWidth) {    // 3 sigma away from pedestal mean
00072         int npe = int (charge / pe2Charge);
00073         if(doThermal) {
00074           double electronEmission = 0.08;
00075           npe += theRandPoissonQ->fire(electronEmission);
00076         }
00077 
00078         noise = correctPE(detId, npe) - npe;
00079     }
00080     return (noise * GeVperfC);
00081 
00082 }
00083 
00084 
00085 double HPDIonFeedbackSim::correctPE(const DetId & detId, double npe) const
00086 {
00087     double rateInTail = 0.000211988;//read this from XML file
00088     double rateInSecondTail = 4.61579e-06;//read this from XML file
00089 
00090     // three gauss fit is applied to data to get ion feedback distribution
00091     // parameters (in fC)
00092     // first gaussian
00093     // double p0 = 9.53192e+05;
00094     // double p1 = -3.13653e-01;
00095     // double p2 = 2.78350e+00;
00096 
00097     // second gaussian
00098     // double p3 = 2.41611e+03;
00099     double p4 = 2.06117e+01;
00100     double p5 = 1.09239e+01;
00101 
00102     // third gaussian
00103     // double p6 = 3.42793e+01;
00104     double p7 = 5.45548e+01;
00105     double p8 = 1.59696e+01;
00106 
00107     double noise = 0.;          // fC
00108     int nFirst  = (int)(theRandBinomial->fire(npe, rateInTail));
00109     int nSecond = (int)(theRandBinomial->fire(npe, rateInSecondTail));
00110 
00111     for (int j = 0; j < nFirst; ++j) {
00112       noise += theRandGauss->fire(p4, p5);
00113     }
00114     for (int j = 0; j < nSecond; ++j) {
00115       noise += theRandGauss->fire(p7, p8);
00116     }
00117 
00118     return npe + std::max(noise/pe2Charge, 0.);
00119 }
00120 
00121 
00122 void HPDIonFeedbackSim::addThermalNoise(CaloSamples & samples)
00123 {
00124   // make some chance to add a PE (with a chance of feedback)
00125   // for each time sample
00126   double meanPE = 0.02;
00127   DetId detId(samples.id());
00128   int nSamples = samples.size();
00129   const CaloVShape * shape = theShapes->shape(detId);
00130   for(int i = 0; i < nSamples; ++i) 
00131   {
00132     double npe = theRandPoissonQ->fire(meanPE);
00133     // TODOprobably should time-smear these
00134     if(npe > 0.)
00135     {
00136       // chance of feedback
00137       npe = correctPE(detId, npe);
00138       for(int j = i; j < nSamples; ++j)
00139       {
00140         double timeFromPE = (j-i) * 25.;
00141         samples[j] += (*shape)(timeFromPE) * npe;
00142       }
00143     }
00144   }
00145 }
00146 
00147 
00148 double HPDIonFeedbackSim::fCtoGeV(const DetId & detId) const
00149 {
00150   assert(theDbService != 0);
00151   HcalGenericDetId hcalGenDetId(detId);
00152   const HcalGain* gains = theDbService->getGain(hcalGenDetId);
00153   const HcalGainWidth* gwidths = theDbService->getGainWidth(hcalGenDetId);
00154   if (!gains || !gwidths )
00155   {
00156     edm::LogError("HcalAmplifier") << "Could not fetch HCAL conditions for channel " << hcalGenDetId;
00157   }
00158   // only one gain will be recorded per channel, so just use capID 0 for now
00159   double result = gains->getValue(0);
00160   return result;
00161 }