CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/SimCalorimetry/EcalSimAlgos/interface/ESFastTDigitizer.h

Go to the documentation of this file.
00001 #ifndef EcalSimAlgos_ESFastTDigitizer_h
00002 #define EcalSimAlgos_ESFastTDigitizer_h
00003 
00004 /*  Based on CaloTDigitizer
00005     Turns hits into digis.  Assumes that 
00006     there's an ESElectronicsSimFast class with the
00007     interface analogToDigital(const CaloSamples &, Digi &);
00008 */
00009 #include "FWCore/ServiceRegistry/interface/Service.h"
00010 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00011 #include "SimCalorimetry/CaloSimAlgos/interface/CaloHitResponse.h"
00012 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVNoiseHitGenerator.h"
00013 #include "SimDataFormats/CrossingFrame/interface/MixCollection.h"
00014 #include "SimDataFormats/CaloHit/interface/PCaloHit.h"
00015 
00016 #include "CLHEP/Random/RandGeneral.h"
00017 #include "CLHEP/Random/RandPoissonQ.h"
00018 #include "CLHEP/Random/RandFlat.h"
00019 #include <gsl/gsl_sf_erf.h>
00020 #include <gsl/gsl_sf_result.h>
00021 
00022 #include "TH3F.h"
00023 #include <vector>
00024 #include <cstdlib>
00025 
00026 class ESFastTDigitizer
00027 {
00028  public:
00029   
00030   ESFastTDigitizer(CaloHitResponse * hitResponse, ESElectronicsSimFast * electronicsSim, bool addNoise, int numESdetId)
00031     :  theHitResponse(hitResponse),
00032     theNoiseHitGenerator(0),              
00033     theElectronicsSim(electronicsSim),
00034     theDetIds(0),
00035     addNoise_(addNoise),
00036     numESdetId_(numESdetId),  
00037        refHistos_ ( 0 ),
00038        histoDistribution_(0)
00039   {        
00040   
00041     setRefFile_ = true;
00042 
00043   }
00044   
00045   ~ESFastTDigitizer() 
00046       { delete histoDistribution_;
00047          delete [] refHistos_; }
00048 
00050   void setGain (const int gain) { 
00051 
00052     ESGain_ = gain; 
00053 
00054     if (ESGain_ == 1) {
00055       zsThreshold_ = 3;
00056       refFile_ = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_LG.txt";
00057     } else if (ESGain_ == 2) {
00058       zsThreshold_ = 4;
00059       refFile_ = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_HG.txt";
00060     }
00061 
00062     if (addNoise_ && setRefFile_) {
00063       readHistosFromFile();
00064       setRefFile_ = false;  
00065     }
00066   }
00067 
00069   void readHistosFromFile( ) {
00070 
00071     m_histofile = new ifstream (edm::FileInPath(refFile_).fullPath().c_str());
00072     if (m_histofile == 0){ 
00073       throw edm::Exception(edm::errors::InvalidReference,"NullPointer")
00074         << "Reference histos file not opened" ;
00075       return ;
00076     }
00077     
00078     // number of bins
00079     char buffer[200];
00080     int thisLine = 0;
00081     while( thisLine==0 ) {
00082       m_histofile->getline(buffer,400);
00083       if (!strstr(buffer,"#") && !(strspn(buffer," ") == strlen(buffer))){      
00084         float histoBin; 
00085         sscanf(buffer,"%f",&histoBin); 
00086         histoBin_ = (double)histoBin;
00087         thisLine++;
00088       }
00089     }
00090     int histoBin3 = (int)(histoBin_*histoBin_*histoBin_);
00091     refHistos_ = new double[histoBin3];    
00092     
00093     // all info
00094     int thisBin = -2;
00095     while( !(m_histofile->eof()) ){
00096       m_histofile->getline(buffer,400);
00097       if (!strstr(buffer,"#") && !(strspn(buffer," ") == strlen(buffer))){
00098         if(thisBin==-2){ float histoInf; sscanf(buffer,"%f",&histoInf); histoInf_ = (double)histoInf; }
00099         if(thisBin==-1){ float histoSup; sscanf(buffer,"%f",&histoSup); histoSup_ = (double)histoSup; }
00100         
00101         if (thisBin>=0){ 
00102           float refBin; 
00103           sscanf(buffer,"%f",&refBin);
00104           refHistos_[thisBin] = (double)refBin;
00105         }
00106         thisBin++;
00107       }
00108     }
00109 
00110     // creating the reference distribution to extract random numbers
00111     edm::Service<edm::RandomNumberGenerator> rng;   
00112     if ( ! rng.isAvailable()) {
00113       throw cms::Exception("Configuration")
00114         << "ESFastTDigitizer requires the RandomNumberGeneratorService\n"
00115         "which is not present in the configuration file.  You must add the service\n"
00116         "in the configuration file or remove the modules that require it.";
00117     }
00118     CLHEP::HepRandomEngine& engine = rng->getEngine();
00119     histoDistribution_ = new CLHEP::RandGeneral(engine, refHistos_, histoBin3, 0);
00120 
00121     m_histofile->close();
00122     delete m_histofile;
00123   }
00124 
00126   void createNoisyList(std::vector<int> & abThreshCh) {
00127     
00128     edm::Service<edm::RandomNumberGenerator> rng;   
00129     if ( ! rng.isAvailable()) {
00130       throw cms::Exception("Configuration")
00131         << "ESFastTDigitizer requires the RandomNumberGeneratorService\n"
00132         "which is not present in the configuration file.  You must add the service\n"
00133         "in the configuration file or remove the modules that require it.";
00134     }
00135     CLHEP::RandPoissonQ poissonDistribution_(rng->getEngine());
00136     CLHEP::RandFlat flatDistribution_(rng->getEngine());
00137     
00138     gsl_sf_result result;
00139     int status  = gsl_sf_erf_Q_e(zsThreshold_, &result);
00140     if (status != 0) std::cerr<<"ESFastTDigitizer::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
00141     double probabilityLeft = result.val; 
00142     double meanNumberOfNoisyChannels = probabilityLeft * numESdetId_;
00143     int numberOfNoisyChannels = poissonDistribution_.fire(meanNumberOfNoisyChannels);
00144     abThreshCh.reserve(numberOfNoisyChannels);
00145     for (int i = 0; i < numberOfNoisyChannels; i++) {
00146       std::vector<int>::iterator theChannel;
00147       int theChannelNumber = 0;
00148       do {
00149         theChannelNumber = (int)flatDistribution_.fire(numESdetId_);
00150         theChannel = find(abThreshCh.begin(), abThreshCh.end(), theChannelNumber);
00151       }
00152       while ( theChannel!=abThreshCh.end() );
00153 
00154       abThreshCh.push_back(theChannelNumber);
00155     }
00156   }
00157   
00158   
00160   void setDetIds(const std::vector<DetId> & detIds) {theDetIds = &detIds;}
00161   
00162   void setNoiseHitGenerator(CaloVNoiseHitGenerator * generator) {
00163     theNoiseHitGenerator = generator;
00164   }
00165   
00167   void run(MixCollection<PCaloHit> & input, ESDigiCollection & output) {
00168 
00169     assert( 0 != theDetIds &&
00170             0 != theDetIds->size() );
00171     
00172     theHitResponse->run(input);
00173 
00174     if(theNoiseHitGenerator != 0) addNoiseHits();  
00175 
00176     theElectronicsSim->newEvent();
00177 
00178     // reserve space for how many digis we expect 
00179     int nDigisExpected = addNoise_ ? theDetIds->size() : theHitResponse->nSignals();
00180     output.reserve(nDigisExpected);
00181 
00182     // random generation of channel above threshold
00183     std::vector<int> abThreshCh;                                            
00184     if (addNoise_) createNoisyList(abThreshCh);
00185 
00186     // make a raw digi for evey cell where we have noise
00187     int idxDetId=0;
00188     for(std::vector<DetId>::const_iterator idItr = theDetIds->begin();
00189         idItr != theDetIds->end(); ++idItr,++idxDetId) {
00190 
00191       bool needToDeleteSignal = false;
00192       CaloSamples * analogSignal = theHitResponse->findSignal(*idItr);
00193         
00194       // signal or just noise?
00195       bool wasEmpty = false;
00196       
00197       if (!analogSignal){       // no signal here
00198         wasEmpty = true;
00199         if (!addNoise_) continue; 
00200         else { 
00201           std::vector<int>::iterator thisChannel;
00202           thisChannel = find( abThreshCh.begin(), abThreshCh.end(), idxDetId);            
00203           if( thisChannel != abThreshCh.end() ) {
00204             analogSignal = new CaloSamples(theHitResponse->makeBlankSignal(*idItr));
00205             needToDeleteSignal = true;
00206           }
00207         }
00208       }
00209       
00210       if (analogSignal != 0){ 
00211         // either we have a signal or we need to generate noise samples           
00212           
00213         ESDataFrame digi(*idItr);
00214         theElectronicsSim->analogToDigital(*analogSignal , digi, wasEmpty, histoDistribution_, histoInf_, histoSup_, histoBin_);        
00215         output.push_back(digi);  
00216         if (needToDeleteSignal) delete analogSignal;
00217       }
00218     }   
00219     
00220     // free up some memory
00221     theHitResponse->clear();
00222   }
00223   
00224   
00225   void addNoiseHits() {
00226     std::vector<PCaloHit> noiseHits;
00227     theNoiseHitGenerator->getNoiseHits(noiseHits);
00228     for(std::vector<PCaloHit>::const_iterator hitItr = noiseHits.begin(),
00229           hitEnd = noiseHits.end(); hitItr != hitEnd; ++hitItr) {
00230       theHitResponse->add(*hitItr);
00231     }
00232   }
00233   
00234   
00235  private:
00236 
00237   CaloHitResponse * theHitResponse;
00238   CaloVNoiseHitGenerator * theNoiseHitGenerator;  
00239   ESElectronicsSimFast * theElectronicsSim;
00240   const std::vector<DetId>* theDetIds;
00241   bool addNoise_;
00242   bool setRefFile_;
00243   int numESdetId_;
00244   int ESGain_;
00245   double zsThreshold_;
00246 
00247   std::string refFile_;
00248   ifstream *m_histofile;
00249   double* refHistos_;
00250   double  histoBin_;
00251   double  histoInf_;
00252   double  histoSup_;
00253 
00254   CLHEP::RandGeneral *histoDistribution_;
00255 };
00256 
00257 #endif
00258