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
00333 if(fullInjection)
00334 ncells = EBDetId::kSizeForDenseIndexing;
00335
00336
00337
00338 unsigned icell=0;
00339 while(icell < ncells)
00340 {
00341 unsigned cellindex= (!fullInjection) ?
00342 (unsigned)(floor(random_->flatShoot()*EBDetId::kSizeForDenseIndexing)): icell ;
00343
00344 if(theCalorimeterHits_[cellindex]==0.)
00345 {
00346 float energy=0.;
00347 if(noise_>0.)
00348 energy=myGaussianTailGenerator_->shoot();
00349 if(noise_==-1.)
00350 {
00351
00352
00353
00354 float noisemean = (doCustomHighNoise_)? highNoiseParameters_[0]*(*ICMC_)[cellindex]*adcToGeV_: 0.;
00355 float noisesigma = (doCustomHighNoise_)? highNoiseParameters_[1]*(*ICMC_)[cellindex]*adcToGeV_ : noisesigma_[cellindex];
00356 energy=random_->gaussShoot(noisemean,noisesigma);
00357
00358
00359 if(doCustomHighNoise_) applyZSCells_[cellindex]=false;
00360 }
00361 float calib = (doMisCalib_) ? calibfactor_*theCalibConstants_[cellindex]:calibfactor_;
00362 energy *= calib;
00363 theCalorimeterHits_[cellindex]=energy;
00364 theFiredCells_.push_back(cellindex);
00365 EBDetId myDetId(EBDetId::unhashIndex(cellindex));
00366
00367 int TThashedindex=(eTTmap_->towerOf(myDetId)).hashedIndex();
00368
00369 if(TTTEnergy_[TThashedindex]==0.)
00370 {
00371 theFiredTTs_.push_back(TThashedindex);
00372 TTTEnergy_[TThashedindex]+=energy*sinTheta_[myDetId.ietaAbs()];
00373
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 if(noise_>0.)
00388 ++icell;
00389 }
00390 if(noise_==-1.)
00391 ++icell;
00392 }
00393
00394 }
00395
00396 void EcalBarrelRecHitsMaker::init(const edm::EventSetup &es,bool doDigis,bool doMiscalib)
00397 {
00398
00399 doDigis_=doDigis;
00400 doMisCalib_=doMiscalib;
00401
00402 edm::ESHandle<EcalADCToGeVConstant> agc;
00403 es.get<EcalADCToGeVConstantRcd>().get(agc);
00404
00405 adcToGeV_= agc->getEBValue();
00406 minAdc_ = 200;
00407 maxAdc_ = 4085;
00408
00409 geVToAdc1_ = 1./adcToGeV_;
00410 geVToAdc2_ = geVToAdc1_/2.;
00411 geVToAdc3_ = geVToAdc1_/12.;
00412
00413 t1_ = ((int)maxAdc_-(int)minAdc_)*adcToGeV_;
00414 t2_ = 2.* t1_ ;
00415
00416
00417 sat_ = 12.*t1_*calibfactor_;
00418
00419 barrelRawId_.resize(EBDetId::kSizeForDenseIndexing);
00420 if (doMisCalib_ || noise_==-1.) theCalibConstants_.resize(EBDetId::kSizeForDenseIndexing);
00421 edm::ESHandle<CaloGeometry> pG;
00422 es.get<CaloGeometryRecord>().get(pG);
00423
00424
00425
00426
00427 edm::ESHandle<EcalTrigTowerConstituentsMap> hetm;
00428 es.get<IdealGeometryRecord>().get(hetm);
00429 eTTmap_ = &(*hetm);
00430
00431 const EcalBarrelGeometry * myEcalBarrelGeometry = dynamic_cast<const EcalBarrelGeometry*>(pG->getSubdetectorGeometry(DetId::Ecal,EcalBarrel));
00432
00433 const std::vector<DetId>& vec(myEcalBarrelGeometry->getValidDetIds(DetId::Ecal,EcalBarrel));
00434 unsigned size=vec.size();
00435 for(unsigned ic=0; ic<size; ++ic)
00436 {
00437 EBDetId myDetId(vec[ic]);
00438 int crystalHashedIndex=myDetId.hashedIndex();
00439 barrelRawId_[crystalHashedIndex]=vec[ic].rawId();
00440
00441 EcalTrigTowerDetId towid= eTTmap_->towerOf(EBDetId(vec[ic]));
00442 int TThashedindex=towid.hashedIndex();
00443 theTTDetIds_[TThashedindex]=towid;
00444 crystalsinTT_[TThashedindex].push_back(crystalHashedIndex);
00445 int ietaAbs=myDetId.ietaAbs();
00446 if(sinTheta_[ietaAbs]==0.)
00447 {
00448 sinTheta_[ietaAbs]=std::sin(myEcalBarrelGeometry->getGeometry(myDetId)->getPosition().theta());
00449
00450 }
00451 }
00452
00453
00454 unsigned nTTs=theTTDetIds_.size();
00455
00456
00458
00461
00462
00463
00464
00465
00466
00467
00468
00469 for(unsigned iTT=0;iTT<nTTs;++iTT)
00470 {
00471 int ietaPivot=theTTDetIds_[iTT].ieta();
00472 int iphiPivot=theTTDetIds_[iTT].iphi();
00473 int TThashedIndex=theTTDetIds_[iTT].hashedIndex();
00474
00475 int ietamin=std::max(ietaPivot-SREtaSize_,-17);
00476 if(ietamin==0) ietamin=-1;
00477 int ietamax=std::min(ietaPivot+SREtaSize_,17);
00478 if(ietamax==0) ietamax=1;
00479 int iphimin=iphiPivot-SRPhiSize_;
00480 int iphimax=iphiPivot+SRPhiSize_;
00481 for(int ieta=ietamin;ieta<=ietamax;)
00482 {
00483 int iz=(ieta>0)? 1 : -1;
00484 for(int iphi=iphimin;iphi<=iphimax;)
00485 {
00486 int riphi=iphi;
00487 if(riphi<1) riphi+=72;
00488 else if(riphi>72) riphi-=72;
00489 EcalTrigTowerDetId neighborTTDetId(iz,EcalBarrel,abs(ieta),riphi);
00490
00491 if(ieta!=ietaPivot||riphi!=iphiPivot)
00492 {
00493 neighboringTTs_[TThashedIndex].push_back(neighborTTDetId.hashedIndex());
00494 }
00495 ++iphi;
00496
00497 }
00498 ++ieta;
00499 if(ieta==0) ieta=1;
00500 }
00501 }
00502
00503
00504
00505
00506 if(doMisCalib_ || noise_==-1.)
00507 {
00508 double rms=0.;
00509 double mean=0.;
00510 unsigned ncells=0;
00511
00512 if(noise_==-1.)
00513 noisesigma_.resize(EBDetId::kSizeForDenseIndexing);
00514
00515
00516 edm::ESHandle<EcalIntercalibConstantsMC> pJcal;
00517 es.get<EcalIntercalibConstantsMCRcd>().get(pJcal);
00518 const EcalIntercalibConstantsMC* jcal = pJcal.product();
00519 const std::vector<float>& ICMC = jcal->barrelItems();
00520
00521
00522 ICMC_ = &ICMC;
00523
00524
00525
00526
00527 edm::ESHandle<EcalIntercalibConstants> pIcal;
00528 es.get<EcalIntercalibConstantsRcd>().get(pIcal);
00529 const EcalIntercalibConstants* ical = pIcal.product();
00530 const std::vector<float> & IC = ical->barrelItems();
00531
00532 float meanIC=0.;
00533 unsigned nic = IC.size();
00534 for ( unsigned ic=0; ic <nic ; ++ic ) {
00535
00536 float factor = IC[ic]/ICMC[ic];
00537 meanIC+=(IC[ic]-1.);
00538
00539 theCalibConstants_[ic] = refactor_mean_+(factor-1.)*refactor_;
00540
00541 rms+=(factor-1.)*(factor-1.);
00542 mean+=(factor-1.);
00543 ++ncells;
00544 if(noise_==-1.)
00545 {
00546
00547 noisesigma_[ic]=noiseADC_*adcToGeV_*ICMC[ic]/calibfactor_;
00548 }
00549
00550 }
00551
00552 mean/=(float)ncells;
00553 rms/=(float)ncells;
00554
00555 rms=sqrt(rms-mean*mean);
00556 meanIC = 1.+ meanIC/ncells;
00557
00558
00559
00560 edm::LogInfo("CaloRecHitsProducer") << "Found " << ncells << " cells in the barrel calibration map. RMS is " << rms << std::endl;
00561
00562 }
00563 }
00564
00565 void EcalBarrelRecHitsMaker::geVtoGainAdc(float e,unsigned & gain, unsigned &adc) const
00566 {
00567 if(e<t1_)
00568 {
00569 gain = 1;
00570
00571 adc = minAdc_ + (unsigned)(e*geVToAdc1_);
00572
00573 }
00574 else if (e<t2_)
00575 {
00576 gain = 2;
00577 adc = minAdc_ + (unsigned)(e*geVToAdc2_);
00578 }
00579 else
00580 {
00581 gain = 3;
00582 adc = std::min(minAdc_+(unsigned)(e*geVToAdc3_),maxAdc_);
00583 }
00584 }
00585
00586 bool EcalBarrelRecHitsMaker::isHighInterest(int tthi)
00587 {
00588
00589 if(TTHighInterest_[tthi]!=0) return (TTHighInterest_[tthi]>0);
00590
00591 TTHighInterest_[tthi]=(TTTEnergy_[tthi] > SRThreshold_) ? 1:-1;
00592
00593 if( TTHighInterest_[tthi]==1)
00594 {
00595 theTTofHighInterest_.push_back(tthi);
00596 return true;
00597 }
00598
00599
00600 const std::vector<int> & tts(neighboringTTs_[tthi]);
00601
00602 unsigned size=tts.size();
00603 bool result=false;
00604 for(unsigned itt=0;itt<size&&!result;++itt)
00605 {
00606 if(TTTEnergy_[tts[itt]] > SRThreshold_) result=true;
00607 }
00608 TTHighInterest_[tthi]=(result)? 1:-1;
00609 theTTofHighInterest_.push_back(tthi);
00610 return result;
00611 }