Go to the documentation of this file.00001 #include "FastSimulation/CaloRecHitsProducer/interface/EcalBarrelRecHitsMaker.h"
00002 #include "SimDataFormats/CaloHit/interface/PCaloHitContainer.h"
00003 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00004 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00005 #include "FastSimulation/Utilities/interface/GaussianTail.h"
00006
00007 #include "SimDataFormats/CrossingFrame/interface/CrossingFrame.h"
00008 #include "SimDataFormats/CrossingFrame/interface/MixCollection.h"
00009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00010 #include "FWCore/Framework/interface/ESHandle.h"
00011 #include "FWCore/Framework/interface/EventSetup.h"
00012 #include "FWCore/Framework/interface/Event.h"
00013 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00014 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00015 #include "Geometry/EcalAlgo/interface/EcalBarrelGeometry.h"
00016 #include "CondFormats/EcalObjects/interface/EcalIntercalibConstants.h"
00017 #include "CondFormats/DataRecord/interface/EcalIntercalibConstantsRcd.h"
00018 #include "CondFormats/EcalObjects/interface/EcalADCToGeVConstant.h"
00019 #include "CondFormats/DataRecord/interface/EcalADCToGeVConstantRcd.h"
00020 #include "CondFormats/EcalObjects/interface/EcalIntercalibConstantsMC.h"
00021 #include "CondFormats/DataRecord/interface/EcalIntercalibConstantsMCRcd.h"
00022 #include "Geometry/CaloTopology/interface/EcalTrigTowerConstituentsMap.h"
00023 #include "Geometry/CaloEventSetup/interface/CaloTopologyRecord.h"
00024 #include "Geometry/CaloTopology/interface/CaloTopology.h"
00025 #include "DataFormats/CaloTowers/interface/CaloTowerDetId.h"
00026 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00027
00028 #include "CLHEP/GenericFunctions/Erf.hh"
00029
00030
00031 EcalBarrelRecHitsMaker::EcalBarrelRecHitsMaker(edm::ParameterSet const & p,
00032 const RandomEngine* myrandom)
00033 : random_(myrandom)
00034 {
00035 edm::ParameterSet RecHitsParameters=p.getParameter<edm::ParameterSet>("ECALBarrel");
00036 inputCol_=RecHitsParameters.getParameter<edm::InputTag>("MixedSimHits");
00037 noise_ = RecHitsParameters.getParameter<double>("Noise");
00038 threshold_ = RecHitsParameters.getParameter<double>("Threshold");
00039 refactor_ = RecHitsParameters.getParameter<double> ("Refactor");
00040 refactor_mean_ = RecHitsParameters.getParameter<double> ("Refactor_mean");
00041 noiseADC_ = RecHitsParameters.getParameter<double>("NoiseADC");
00042 highNoiseParameters_ = RecHitsParameters.getParameter<std::vector<double> > ("HighNoiseParameters");
00043 SRThreshold_ = RecHitsParameters.getParameter<double> ("SRThreshold");
00044 SREtaSize_ = RecHitsParameters.getUntrackedParameter<int> ("SREtaSize",1);
00045 SRPhiSize_ = RecHitsParameters.getUntrackedParameter<int> ("SRPhiSize",1);
00046 applyZSCells_.resize(EBDetId::kSizeForDenseIndexing,true);
00047 theCalorimeterHits_.resize(EBDetId::kSizeForDenseIndexing,0.);
00048 crystalsinTT_.resize(2448);
00049 TTTEnergy_.resize(2448,0.);
00050 TTHighInterest_.resize(2448,0);
00051 treatedTTs_.resize(2448,false);
00052 theTTDetIds_.resize(2448);
00053 neighboringTTs_.resize(2448);
00054 sinTheta_.resize(86,0.);
00055 doCustomHighNoise_=false;
00056
00057
00058
00059
00060 doCustomHighNoise_=highNoiseParameters_.size()>=3;
00061 Genfun::Erf myErf;
00062 if( noise_>0. ) {
00063 EBHotFraction_ = 0.5-0.5*myErf(threshold_/noise_/sqrt(2.));
00064 myGaussianTailGenerator_ = new GaussianTail(random_, noise_, threshold_);
00065 edm::LogInfo("CaloRecHitsProducer") <<"Uniform noise simulation selected in the barrel";
00066 } else if (noise_==-1 && doCustomHighNoise_)
00067 {
00068 if(highNoiseParameters_.size()==4)
00069 EBHotFraction_ = 0.5-0.5*myErf(highNoiseParameters_[3]/highNoiseParameters_[2]/sqrt(2.));
00070 if(highNoiseParameters_.size()==3)
00071 EBHotFraction_ = highNoiseParameters_[2] ;
00072 edm::LogInfo("CaloRecHitsProducer")<< " The gaussian model for high noise fluctuation cells after ZS is selected (best model), hot fraction " << EBHotFraction_ << std::endl;
00073 }
00074
00075 noisified_ = (noise_==0.);
00076 edm::ParameterSet CalibParameters = RecHitsParameters.getParameter<edm::ParameterSet>("ContFact");
00077 double c1=CalibParameters.getParameter<double>("EBs25notContainment");
00078 calibfactor_=1./c1;
00079
00080
00081 }
00082
00083 EcalBarrelRecHitsMaker::~EcalBarrelRecHitsMaker()
00084 {;
00085 }
00086
00087
00088 void EcalBarrelRecHitsMaker::clean()
00089 {
00090
00091 unsigned size=theFiredCells_.size();
00092 for(unsigned ic=0;ic<size;++ic)
00093 {
00094 theCalorimeterHits_[theFiredCells_[ic]] = 0.;
00095 applyZSCells_[theFiredCells_[ic]] = true;
00096 }
00097 theFiredCells_.clear();
00098
00099 noisified_ = (noise_==0.);
00100
00101
00102 size=theFiredTTs_.size();
00103
00104 for(unsigned itt=0;itt<size;++itt)
00105 {
00106
00107 TTTEnergy_[theFiredTTs_[itt]]=0.;
00108 treatedTTs_[theFiredTTs_[itt]]=false;
00109 }
00110 theFiredTTs_.clear();
00111
00112 size=theTTofHighInterest_.size();
00113 for(unsigned itt=0;itt<size;++itt)
00114 TTHighInterest_[theTTofHighInterest_[itt]]=0;
00115 theTTofHighInterest_.clear();
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 }
00126
00127 void EcalBarrelRecHitsMaker::loadEcalBarrelRecHits(edm::Event &iEvent,EBRecHitCollection & ecalHits,EBDigiCollection & ecalDigis)
00128 {
00129
00130 clean();
00131 loadPCaloHits(iEvent);
00132
00133 unsigned nhit=theFiredCells_.size();
00134
00135 unsigned gain, adc;
00136 ecalDigis.reserve(nhit);
00137 ecalHits.reserve(nhit);
00138 for(unsigned ihit=0;ihit<nhit;++ihit)
00139 {
00140 unsigned icell = theFiredCells_[ihit];
00141
00142 EBDetId myDetId(barrelRawId_[icell]);
00143 EcalTrigTowerDetId towid= eTTmap_->towerOf(myDetId);
00144 int TThashedindex=towid.hashedIndex();
00145
00146 if(doDigis_)
00147 {
00148 ecalDigis.push_back( myDetId );
00149 EBDataFrame myDataFrame( ecalDigis.back() );
00150
00151
00152 geVtoGainAdc(theCalorimeterHits_[icell],gain,adc);
00153 myDataFrame.setSample(0,EcalMGPASample(adc,gain));
00154
00155
00156
00157 }
00158
00159
00160
00161 float energy=theCalorimeterHits_[icell];
00162
00163 if ( SRThreshold_ && energy < threshold_ && !isHighInterest(TThashedindex) && applyZSCells_[icell])
00164 {
00165
00166 theCalorimeterHits_[icell]=0.;
00167 energy=0.;
00168 }
00169
00170
00171
00172
00173 if (energy > sat_)
00174 {
00175 theCalorimeterHits_[icell]=sat_;
00176 energy=sat_;
00177 }
00178
00179
00180
00181 if(energy!=0.)
00182 ecalHits.push_back(EcalRecHit(myDetId,energy,0.));
00183
00184 }
00185
00186
00187 }
00188
00189 void EcalBarrelRecHitsMaker::loadPCaloHits(const edm::Event & iEvent)
00190 {
00191
00192 edm::Handle<CrossingFrame<PCaloHit> > cf;
00193 iEvent.getByLabel(inputCol_,cf);
00194 std::auto_ptr<MixCollection<PCaloHit> > colcalo(new MixCollection<PCaloHit>(cf.product(),std::pair<int,int>(0,0) ));
00195
00196
00197 theFiredCells_.reserve(colcalo->size());
00198
00199 MixCollection<PCaloHit>::iterator cficalo;
00200 MixCollection<PCaloHit>::iterator cficaloend=colcalo->end();
00201
00202 for (cficalo=colcalo->begin(); cficalo!=cficaloend;cficalo++)
00203 {
00204 unsigned hashedindex = EBDetId(cficalo->id()).hashedIndex();
00205
00206
00207 float calib = (doMisCalib_) ? calibfactor_*theCalibConstants_[hashedindex]:calibfactor_;
00208
00209 if(theCalorimeterHits_[hashedindex]==0.)
00210 {
00211 theFiredCells_.push_back(hashedindex);
00212 float noise=(noise_==-1.) ? noisesigma_[hashedindex] : noise_ ;
00213 if (!noisified_ ) theCalorimeterHits_[hashedindex] += random_->gaussShoot(0.,noise*calib);
00214 }
00215
00216
00217
00218
00219 float energy=(cficalo->energy()==0.) ? 0.000001 : cficalo->energy() ;
00220 energy*=calib;
00221 theCalorimeterHits_[hashedindex]+=energy;
00222
00223
00224 EBDetId myDetId(EBDetId(cficalo->id()));
00225 EcalTrigTowerDetId towid= eTTmap_->towerOf(myDetId);
00226
00227 int TThashedindex=towid.hashedIndex();
00228 if(TTTEnergy_[TThashedindex]==0.)
00229 {
00230 theFiredTTs_.push_back(TThashedindex);
00231
00232 }
00233
00234 TTTEnergy_[TThashedindex]+=energy*sinTheta_[myDetId.ietaAbs()];
00235
00236 }
00237 noisifyTriggerTowers();
00238 noisified_ = true;
00239 }
00240
00241 void EcalBarrelRecHitsMaker::noisifyTriggerTowers()
00242 {
00243 if(noise_==0.) return;
00244
00245
00246
00247
00248
00249 unsigned nTT=theFiredTTs_.size();
00250 for(unsigned itt=0;itt<nTT;++itt)
00251 {
00252
00253
00254 noisifyTriggerTower(theFiredTTs_[itt]);
00255
00256 const std::vector<int>& neighbors=neighboringTTs_[theFiredTTs_[itt]];
00257 unsigned nneighbors=neighbors.size();
00258
00259
00260 for(unsigned in=0;in<nneighbors;++in)
00261 {
00262
00263 if(!treatedTTs_[neighbors[in]])
00264 {
00265 noisifyTriggerTower(neighbors[in]);
00266 if(TTTEnergy_[neighbors[in]]==0.)
00267 theFiredTTs_.push_back(neighbors[in]);
00268
00269 }
00270 }
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 randomNoisifier();
00282 }
00283
00284 bool EcalBarrelRecHitsMaker::noisifyTriggerTower(unsigned tthi)
00285 {
00286
00287 if(treatedTTs_[tthi]) return false;
00288
00289
00290 const std::vector<int> & xtals(crystalsinTT_[tthi]);
00291 unsigned nxtals=xtals.size();
00292 unsigned counter =0 ;
00293 float energy=0.;
00294 for(unsigned ic=0;ic<nxtals;++ic)
00295 {
00296 unsigned hashedindex=xtals[ic];
00297
00298
00299 if(theCalorimeterHits_[hashedindex]==0)
00300 {
00301 float calib = (doMisCalib_) ? calibfactor_*theCalibConstants_[hashedindex]:calibfactor_;
00302 float noise = (noise_==-1.) ? noisesigma_[hashedindex]:noise_;
00303 float energy = calib*random_->gaussShoot(0.,noise);
00304 theCalorimeterHits_[hashedindex]=energy;
00305
00306 if(TTTEnergy_[tthi]==0.)
00307 theFiredTTs_.push_back(tthi);
00308 TTTEnergy_[tthi]+=energy*sinTheta_[EBDetId(barrelRawId_[hashedindex]).ietaAbs()];
00309
00310 theFiredCells_.push_back(hashedindex);
00311 ++counter;
00312 }
00313 else
00314 energy+=theCalorimeterHits_[hashedindex];
00315 }
00316
00317 treatedTTs_[tthi]=true;
00318 return true;
00319 }
00320
00321
00322
00323
00324 void EcalBarrelRecHitsMaker::randomNoisifier()
00325 {
00326
00327 double mean = (double)(EBDetId::kSizeForDenseIndexing-theFiredCells_.size())*EBHotFraction_;
00328 unsigned ncells= random_->poissonShoot(mean);
00329
00330
00331 bool fullInjection=(noise_==-1. && !doCustomHighNoise_);
00332 if(fullInjection)
00333 ncells = EBDetId::kSizeForDenseIndexing;
00334
00335
00336
00337 unsigned icell=0;
00338 while(icell < ncells)
00339 {
00340 unsigned cellindex= (unsigned)(floor(random_->flatShoot()*EBDetId::kSizeForDenseIndexing));
00341 if(theCalorimeterHits_[cellindex]==0.)
00342 {
00343 float energy=0.;
00344 if(noise_>0.)
00345 energy=myGaussianTailGenerator_->shoot();
00346 if(noise_==-1.)
00347 {
00348
00349
00350
00351 float noisemean = (doCustomHighNoise_)? highNoiseParameters_[0]*(*ICMC_)[cellindex]*adcToGeV_: 0.;
00352 float noisesigma = (doCustomHighNoise_)? highNoiseParameters_[1]*(*ICMC_)[cellindex]*adcToGeV_ : noisesigma_[cellindex];
00353 energy=random_->gaussShoot(noisemean,noisesigma);
00354
00355
00356 if(doCustomHighNoise_) applyZSCells_[cellindex]=false;
00357 }
00358 float calib = (doMisCalib_) ? calibfactor_*theCalibConstants_[cellindex]:calibfactor_;
00359 energy *= calib;
00360 theCalorimeterHits_[cellindex]=energy;
00361 theFiredCells_.push_back(cellindex);
00362 EBDetId myDetId(EBDetId::unhashIndex(cellindex));
00363
00364 int TThashedindex=(eTTmap_->towerOf(myDetId)).hashedIndex();
00365
00366 if(TTTEnergy_[TThashedindex]==0.)
00367 {
00368 theFiredTTs_.push_back(TThashedindex);
00369 TTTEnergy_[TThashedindex]+=energy*sinTheta_[myDetId.ietaAbs()];
00370
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 ++icell;
00385 }
00386 }
00387
00388 }
00389
00390 void EcalBarrelRecHitsMaker::init(const edm::EventSetup &es,bool doDigis,bool doMiscalib)
00391 {
00392
00393 doDigis_=doDigis;
00394 doMisCalib_=doMiscalib;
00395
00396 edm::ESHandle<EcalADCToGeVConstant> agc;
00397 es.get<EcalADCToGeVConstantRcd>().get(agc);
00398
00399 adcToGeV_= agc->getEBValue();
00400 minAdc_ = 200;
00401 maxAdc_ = 4085;
00402
00403 geVToAdc1_ = 1./adcToGeV_;
00404 geVToAdc2_ = geVToAdc1_/2.;
00405 geVToAdc3_ = geVToAdc1_/12.;
00406
00407 t1_ = ((int)maxAdc_-(int)minAdc_)*adcToGeV_;
00408 t2_ = 2.* t1_ ;
00409
00410
00411 sat_ = 12.*t1_*calibfactor_;
00412
00413 barrelRawId_.resize(EBDetId::kSizeForDenseIndexing);
00414 if (doMisCalib_ || noise_==-1.) theCalibConstants_.resize(EBDetId::kSizeForDenseIndexing);
00415 edm::ESHandle<CaloGeometry> pG;
00416 es.get<CaloGeometryRecord>().get(pG);
00417
00418
00419
00420
00421 edm::ESHandle<EcalTrigTowerConstituentsMap> hetm;
00422 es.get<IdealGeometryRecord>().get(hetm);
00423 eTTmap_ = &(*hetm);
00424
00425 const EcalBarrelGeometry * myEcalBarrelGeometry = dynamic_cast<const EcalBarrelGeometry*>(pG->getSubdetectorGeometry(DetId::Ecal,EcalBarrel));
00426
00427 const std::vector<DetId>& vec(myEcalBarrelGeometry->getValidDetIds(DetId::Ecal,EcalBarrel));
00428 unsigned size=vec.size();
00429 for(unsigned ic=0; ic<size; ++ic)
00430 {
00431 EBDetId myDetId(vec[ic]);
00432 int crystalHashedIndex=myDetId.hashedIndex();
00433 barrelRawId_[crystalHashedIndex]=vec[ic].rawId();
00434
00435 EcalTrigTowerDetId towid= eTTmap_->towerOf(EBDetId(vec[ic]));
00436 int TThashedindex=towid.hashedIndex();
00437 theTTDetIds_[TThashedindex]=towid;
00438 crystalsinTT_[TThashedindex].push_back(crystalHashedIndex);
00439 int ietaAbs=myDetId.ietaAbs();
00440 if(sinTheta_[ietaAbs]==0.)
00441 {
00442 sinTheta_[ietaAbs]=std::sin(myEcalBarrelGeometry->getGeometry(myDetId)->getPosition().theta());
00443
00444 }
00445 }
00446
00447
00448 unsigned nTTs=theTTDetIds_.size();
00449
00450
00452
00455
00456
00457
00458
00459
00460
00461
00462
00463 for(unsigned iTT=0;iTT<nTTs;++iTT)
00464 {
00465 int ietaPivot=theTTDetIds_[iTT].ieta();
00466 int iphiPivot=theTTDetIds_[iTT].iphi();
00467 int TThashedIndex=theTTDetIds_[iTT].hashedIndex();
00468
00469 int ietamin=std::max(ietaPivot-SREtaSize_,-17);
00470 if(ietamin==0) ietamin=-1;
00471 int ietamax=std::min(ietaPivot+SREtaSize_,17);
00472 if(ietamax==0) ietamax=1;
00473 int iphimin=iphiPivot-SRPhiSize_;
00474 int iphimax=iphiPivot+SRPhiSize_;
00475 for(int ieta=ietamin;ieta<=ietamax;)
00476 {
00477 int iz=(ieta>0)? 1 : -1;
00478 for(int iphi=iphimin;iphi<=iphimax;)
00479 {
00480 int riphi=iphi;
00481 if(riphi<1) riphi+=72;
00482 else if(riphi>72) riphi-=72;
00483 EcalTrigTowerDetId neighborTTDetId(iz,EcalBarrel,abs(ieta),riphi);
00484
00485 if(ieta!=ietaPivot||riphi!=iphiPivot)
00486 {
00487 neighboringTTs_[TThashedIndex].push_back(neighborTTDetId.hashedIndex());
00488 }
00489 ++iphi;
00490
00491 }
00492 ++ieta;
00493 if(ieta==0) ieta=1;
00494 }
00495 }
00496
00497
00498
00499
00500 if(doMisCalib_ || noise_==-1.)
00501 {
00502 double rms=0.;
00503 double mean=0.;
00504 unsigned ncells=0;
00505
00506 if(noise_==-1.)
00507 noisesigma_.resize(EBDetId::kSizeForDenseIndexing);
00508
00509
00510 edm::ESHandle<EcalIntercalibConstantsMC> pJcal;
00511 es.get<EcalIntercalibConstantsMCRcd>().get(pJcal);
00512 const EcalIntercalibConstantsMC* jcal = pJcal.product();
00513 const std::vector<float>& ICMC = jcal->barrelItems();
00514
00515
00516 ICMC_ = &ICMC;
00517
00518
00519
00520
00521 edm::ESHandle<EcalIntercalibConstants> pIcal;
00522 es.get<EcalIntercalibConstantsRcd>().get(pIcal);
00523 const EcalIntercalibConstants* ical = pIcal.product();
00524 const std::vector<float> & IC = ical->barrelItems();
00525
00526 float meanIC=0.;
00527 unsigned nic = IC.size();
00528 for ( unsigned ic=0; ic <nic ; ++ic ) {
00529
00530 float factor = IC[ic]/ICMC[ic];
00531 meanIC+=(IC[ic]-1.);
00532
00533 theCalibConstants_[ic] = refactor_mean_+(factor-1.)*refactor_;
00534
00535 rms+=(factor-1.)*(factor-1.);
00536 mean+=(factor-1.);
00537 ++ncells;
00538 if(noise_==-1.)
00539 {
00540
00541 noisesigma_[ic]=noiseADC_*adcToGeV_*ICMC[ic]/calibfactor_;
00542 }
00543
00544 }
00545
00546 mean/=(float)ncells;
00547 rms/=(float)ncells;
00548
00549 rms=sqrt(rms-mean*mean);
00550 meanIC = 1.+ meanIC/ncells;
00551
00552
00553
00554 edm::LogInfo("CaloRecHitsProducer") << "Found " << ncells << " cells in the barrel calibration map. RMS is " << rms << std::endl;
00555
00556 }
00557 }
00558
00559 void EcalBarrelRecHitsMaker::geVtoGainAdc(float e,unsigned & gain, unsigned &adc) const
00560 {
00561 if(e<t1_)
00562 {
00563 gain = 1;
00564
00565 adc = minAdc_ + (unsigned)(e*geVToAdc1_);
00566
00567 }
00568 else if (e<t2_)
00569 {
00570 gain = 2;
00571 adc = minAdc_ + (unsigned)(e*geVToAdc2_);
00572 }
00573 else
00574 {
00575 gain = 3;
00576 adc = std::min(minAdc_+(unsigned)(e*geVToAdc3_),maxAdc_);
00577 }
00578 }
00579
00580 bool EcalBarrelRecHitsMaker::isHighInterest(int tthi)
00581 {
00582
00583 if(TTHighInterest_[tthi]!=0) return (TTHighInterest_[tthi]>0);
00584
00585 TTHighInterest_[tthi]=(TTTEnergy_[tthi] > SRThreshold_) ? 1:-1;
00586
00587 if( TTHighInterest_[tthi]==1)
00588 {
00589 theTTofHighInterest_.push_back(tthi);
00590 return true;
00591 }
00592
00593
00594 const std::vector<int> & tts(neighboringTTs_[tthi]);
00595
00596 unsigned size=tts.size();
00597 bool result=false;
00598 for(unsigned itt=0;itt<size&&!result;++itt)
00599 {
00600 if(TTTEnergy_[tts[itt]] > SRThreshold_) result=true;
00601 }
00602 TTHighInterest_[tthi]=(result)? 1:-1;
00603 theTTofHighInterest_.push_back(tthi);
00604 return result;
00605 }