Go to the documentation of this file.00001 #ifndef EcalSimAlgos_ESFastTDigitizer_h
00002 #define EcalSimAlgos_ESFastTDigitizer_h
00003
00004
00005
00006
00007
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
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
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
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
00179 int nDigisExpected = addNoise_ ? theDetIds->size() : theHitResponse->nSignals();
00180 output.reserve(nDigisExpected);
00181
00182
00183 std::vector<int> abThreshCh;
00184 if (addNoise_) createNoisyList(abThreshCh);
00185
00186
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
00195 bool wasEmpty = false;
00196
00197 if (!analogSignal){
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
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
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