00001
00002
00003
00004
00005
00006
00007
00016 #include "EgammaAnalysis/ElectronTools/plugins/CalibratedElectronProducer.h"
00017
00018 #include "FWCore/Framework/interface/Frameworkfwd.h"
00019 #include "FWCore/Framework/interface/MakerMacros.h"
00020 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00021 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00022 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00023 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00024 #include "FWCore/ParameterSet/interface/FileInPath.h"
00025
00026 #include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h"
00027 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
00028 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00029 #include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h"
00030 #include "Geometry/CaloEventSetup/interface/CaloTopologyRecord.h"
00031 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00032 #include "EgammaAnalysis/ElectronTools/interface/SuperClusterHelper.h"
00033
00034 #include <iostream>
00035
00036 using namespace edm ;
00037 using namespace std ;
00038 using namespace reco ;
00039
00040 CalibratedElectronProducer::CalibratedElectronProducer( const edm::ParameterSet & cfg )
00041 {
00042 inputElectrons_ = cfg.getParameter<edm::InputTag>("inputElectronsTag");
00043
00044 nameEnergyReg_ = cfg.getParameter<edm::InputTag>("nameEnergyReg");
00045 nameEnergyErrorReg_ = cfg.getParameter<edm::InputTag>("nameEnergyErrorReg");
00046
00047 recHitCollectionEB_ = cfg.getParameter<edm::InputTag>("recHitCollectionEB");
00048 recHitCollectionEE_ = cfg.getParameter<edm::InputTag>("recHitCollectionEE");
00049
00050
00051 nameNewEnergyReg_ = cfg.getParameter<std::string>("nameNewEnergyReg");
00052 nameNewEnergyErrorReg_ = cfg.getParameter<std::string>("nameNewEnergyErrorReg");
00053 newElectronName_ = cfg.getParameter<std::string>("outputGsfElectronCollectionLabel");
00054
00055
00056 dataset = cfg.getParameter<std::string>("inputDataset");
00057 isMC = cfg.getParameter<bool>("isMC");
00058 updateEnergyError = cfg.getParameter<bool>("updateEnergyError");
00059 lumiRatio = cfg.getParameter<double>("lumiRatio");
00060 correctionsType = cfg.getParameter<int>("correctionsType");
00061 applyLinearityCorrection = cfg.getParameter<bool>("applyLinearityCorrection");
00062 combinationType = cfg.getParameter<int>("combinationType");
00063 verbose = cfg.getParameter<bool>("verbose");
00064 synchronization = cfg.getParameter<bool>("synchronization");
00065 combinationRegressionInputPath = cfg.getParameter<std::string>("combinationRegressionInputPath");
00066 scaleCorrectionsInputPath = cfg.getParameter<std::string>("scaleCorrectionsInputPath");
00067 linCorrectionsInputPath = cfg.getParameter<std::string>("linearityCorrectionsInputPath");
00068
00069
00070 if ( isMC && ( dataset != "Summer11" && dataset != "Fall11"
00071 && dataset!= "Summer12" && dataset != "Summer12_DR53X_HCP2012"
00072 && dataset != "Summer12_LegacyPaper" ) )
00073 {
00074 throw cms::Exception("CalibratedgsfElectronProducer|ConfigError") << "Unknown MC dataset";
00075 }
00076 if ( !isMC && ( dataset != "Prompt" && dataset != "ReReco"
00077 && dataset != "Jan16ReReco" && dataset != "ICHEP2012"
00078 && dataset != "Moriond2013" && dataset != "22Jan2013ReReco" ) )
00079 {
00080 throw cms::Exception("CalibratedgsfElectronProducer|ConfigError") << "Unknown Data dataset";
00081 }
00082
00083
00084 if(combinationType!=3 && applyLinearityCorrection)
00085 {
00086 std::cout << "[CalibratedElectronProducer] "
00087 << "Warning: you chose combinationType!=3 and applyLinearityCorrection=True. Linearity corrections are only applied on top of combination 3." << std::endl;
00088 }
00089
00090 std::cout << "[CalibratedGsfElectronProducer] Correcting scale for dataset " << dataset << std::endl;
00091
00092
00093 std::string pathToDataCorr;
00094 switch (correctionsType)
00095 {
00096 case 0:
00097 break;
00098 case 1:
00099 if ( verbose )
00100 {
00101 std::cout << "You choose regression 1 scale corrections" << std::endl;
00102 }
00103 break;
00104 case 2:
00105 if ( verbose )
00106 {
00107 std::cout << "You choose regression 2 scale corrections." << std::endl;
00108 }
00109 break;
00110 case 3:
00111 throw cms::Exception("CalibratedgsfElectronProducer|ConfigError")
00112 << "You choose standard non-regression ecal energy scale corrections. They are not implemented yet.";
00113 break;
00114 default:
00115 throw cms::Exception("CalibratedgsfElectronProducer|ConfigError")
00116 << "Unknown correctionsType !!!" ;
00117 }
00118
00119 theEnCorrector = new ElectronEnergyCalibrator
00120 (
00121 edm::FileInPath(scaleCorrectionsInputPath.c_str()).fullPath().c_str(),
00122 edm::FileInPath(linCorrectionsInputPath.c_str()).fullPath().c_str(),
00123 dataset,
00124 correctionsType,
00125 applyLinearityCorrection,
00126 lumiRatio,
00127 isMC,
00128 updateEnergyError,
00129 verbose,
00130 synchronization
00131 );
00132
00133 if ( verbose )
00134 {
00135 std::cout<<"[CalibratedGsfElectronProducer] "
00136 << "ElectronEnergyCalibrator object is created" << std::endl;
00137 }
00138
00139 myEpCombinationTool = new EpCombinationTool();
00140 myEpCombinationTool->init
00141 (
00142 edm::FileInPath(combinationRegressionInputPath.c_str()).fullPath().c_str(),
00143 "CombinationWeight"
00144 );
00145
00146 myCombinator = new ElectronEPcombinator();
00147
00148 if ( verbose )
00149 {
00150 std::cout << "[CalibratedGsfElectronProducer] "
00151 << "Combination tools are created and initialized" << std::endl;
00152 }
00153
00154 produces<edm::ValueMap<double> >(nameNewEnergyReg_);
00155 produces<edm::ValueMap<double> >(nameNewEnergyErrorReg_);
00156 produces<GsfElectronCollection> (newElectronName_);
00157 geomInitialized_ = false;
00158 }
00159
00160 CalibratedElectronProducer::~CalibratedElectronProducer()
00161 {}
00162
00163 void CalibratedElectronProducer::produce( edm::Event & event, const edm::EventSetup & setup )
00164 {
00165 if (!geomInitialized_)
00166 {
00167 edm::ESHandle<CaloTopology> theCaloTopology;
00168 setup.get<CaloTopologyRecord>().get(theCaloTopology);
00169 ecalTopology_ = & (*theCaloTopology);
00170
00171 edm::ESHandle<CaloGeometry> theCaloGeometry;
00172 setup.get<CaloGeometryRecord>().get(theCaloGeometry);
00173 caloGeometry_ = & (*theCaloGeometry);
00174 geomInitialized_ = true;
00175 }
00176
00177
00178 edm::Handle<reco::GsfElectronCollection> oldElectronsH ;
00179 event.getByLabel(inputElectrons_,oldElectronsH) ;
00180
00181
00182 edm::Handle< EcalRecHitCollection > pEBRecHits;
00183 edm::Handle< EcalRecHitCollection > pEERecHits;
00184 event.getByLabel( recHitCollectionEB_, pEBRecHits );
00185 event.getByLabel( recHitCollectionEE_, pEERecHits );
00186
00187
00188 edm::Handle<edm::ValueMap<double> > valMapEnergyH;
00189 event.getByLabel(nameEnergyReg_,valMapEnergyH);
00190 edm::Handle<edm::ValueMap<double> > valMapEnergyErrorH;
00191 event.getByLabel(nameEnergyErrorReg_,valMapEnergyErrorH);
00192
00193
00194 std::auto_ptr<GsfElectronCollection> electrons( new reco::GsfElectronCollection ) ;
00195
00196 std::auto_ptr<edm::ValueMap<double> > regrNewEnergyMap(new edm::ValueMap<double>() );
00197 edm::ValueMap<double>::Filler energyFiller(*regrNewEnergyMap);
00198
00199 std::auto_ptr<edm::ValueMap<double> > regrNewEnergyErrorMap(new edm::ValueMap<double>() );
00200 edm::ValueMap<double>::Filler energyErrorFiller(*regrNewEnergyErrorMap);
00201
00202
00203 unsigned nElectrons = oldElectronsH->size();
00204 for( unsigned iele = 0; iele < nElectrons; ++iele )
00205 {
00206 electrons->push_back((*oldElectronsH)[iele]);
00207 }
00208
00209 std::vector<double> regressionValues;
00210 std::vector<double> regressionErrorValues;
00211 regressionValues.reserve(nElectrons);
00212 regressionErrorValues.reserve(nElectrons);
00213
00214 if ( correctionsType != 0 )
00215 {
00216 for ( unsigned iele = 0; iele < nElectrons ; ++iele)
00217 {
00218 reco::GsfElectron & ele ( (*electrons)[iele]);
00219 reco::GsfElectronRef elecRef(oldElectronsH,iele);
00220 double regressionEnergy = (*valMapEnergyH)[elecRef];
00221 double regressionEnergyError = (*valMapEnergyErrorH)[elecRef];
00222
00223 regressionValues.push_back(regressionEnergy);
00224 regressionErrorValues.push_back(regressionEnergyError);
00225
00226
00227 const EcalRecHitCollection * recHits=0;
00228 if( ele.isEB() )
00229 {
00230 recHits = pEBRecHits.product();
00231 } else recHits = pEERecHits.product();
00232
00233 SuperClusterHelper mySCHelper( &(ele), recHits, ecalTopology_, caloGeometry_ );
00234
00235 int elClass = -1;
00236 int run = event.run();
00237
00238 float r9 = mySCHelper.r9();
00239 double correctedEcalEnergy = ele.correctedEcalEnergy();
00240 double correctedEcalEnergyError = ele.correctedEcalEnergyError();
00241 double trackMomentum = ele.trackMomentumAtVtx().R();
00242 double trackMomentumError = ele.trackMomentumError();
00243 double combinedMomentum = ele.p();
00244 double combinedMomentumError = ele.p4Error(ele.candidateP4Kind());
00245
00246
00247
00248 if( !ele.ecalDrivenSeed() )
00249 {
00250 double error = 999. ;
00251 double momentum = (combinedMomentum<15. ? 15. : combinedMomentum);
00252 if ( ele.isEB() )
00253 {
00254 float parEB[3] = { 5.24e-02, 2.01e-01, 1.00e-02};
00255 error = momentum * sqrt( pow(parEB[0]/sqrt(momentum),2) + pow(parEB[1]/momentum,2) + pow(parEB[2],2) );
00256 }
00257 else if ( ele.isEE() )
00258 {
00259 float parEE[3] = { 1.46e-01, 9.21e-01, 1.94e-03} ;
00260 error = momentum * sqrt( pow(parEE[0]/sqrt(momentum),2) + pow(parEE[1]/momentum,2) + pow(parEE[2],2) );
00261 }
00262 combinedMomentumError = error;
00263 }
00264
00265 if (ele.classification() == reco::GsfElectron::GOLDEN) {elClass = 0;}
00266 if (ele.classification() == reco::GsfElectron::BIGBREM) {elClass = 1;}
00267 if (ele.classification() == reco::GsfElectron::BADTRACK) {elClass = 2;}
00268 if (ele.classification() == reco::GsfElectron::SHOWERING) {elClass = 3;}
00269 if (ele.classification() == reco::GsfElectron::GAP) {elClass = 4;}
00270
00271 SimpleElectron mySimpleElectron
00272 (
00273 run,
00274 elClass,
00275 r9,
00276 correctedEcalEnergy,
00277 correctedEcalEnergyError,
00278 trackMomentum,
00279 trackMomentumError,
00280 regressionEnergy,
00281 regressionEnergyError,
00282 combinedMomentum,
00283 combinedMomentumError,
00284 ele.superCluster()->eta(),
00285 ele.isEB(),
00286 isMC,
00287 ele.ecalDriven(),
00288 ele.trackerDrivenSeed()
00289 );
00290
00291
00292 if ( ele.core()->ecalDrivenSeed() || correctionsType==2 || combinationType==3 )
00293 {
00294 theEnCorrector->calibrate(mySimpleElectron);
00295
00296
00297
00298 switch ( combinationType )
00299 {
00300 case 0:
00301 if ( verbose )
00302 {
00303 std::cout << "[CalibratedGsfElectronProducer] "
00304 << "You choose not to combine." << std::endl;
00305 }
00306 break;
00307 case 1:
00308 if ( verbose )
00309 {
00310 std::cout << "[CalibratedGsfElectronProducer] "
00311 << "You choose corrected regression energy for standard combination" << std::endl;
00312 }
00313 myCombinator->setCombinationMode(1);
00314 myCombinator->combine(mySimpleElectron);
00315 break;
00316 case 2:
00317 if ( verbose )
00318 {
00319 std::cout << "[CalibratedGsfElectronProducer] "
00320 << "You choose uncorrected regression energy for standard combination" << std::endl;
00321 }
00322 myCombinator->setCombinationMode(2);
00323 myCombinator->combine(mySimpleElectron);
00324 break;
00325 case 3:
00326 if ( verbose )
00327 {
00328 std::cout << "[CalibratedGsfElectronProducer] "
00329 << "You choose regression combination." << std::endl;
00330 }
00331 myEpCombinationTool->combine(mySimpleElectron);
00332 theEnCorrector->correctLinearity(mySimpleElectron);
00333 break;
00334 default:
00335 throw cms::Exception("CalibratedgsfElectronProducer|ConfigError")
00336 << "Unknown combination Type !!!" ;
00337 }
00338
00339 math::XYZTLorentzVector oldMomentum = ele.p4() ;
00340 math::XYZTLorentzVector newMomentum_ ;
00341 newMomentum_ = math::XYZTLorentzVector
00342 ( oldMomentum.x()*mySimpleElectron.getCombinedMomentum()/oldMomentum.t(),
00343 oldMomentum.y()*mySimpleElectron.getCombinedMomentum()/oldMomentum.t(),
00344 oldMomentum.z()*mySimpleElectron.getCombinedMomentum()/oldMomentum.t(),
00345 mySimpleElectron.getCombinedMomentum() ) ;
00346
00347 ele.correctMomentum
00348 (
00349 newMomentum_,
00350 mySimpleElectron.getTrackerMomentumError(),
00351 mySimpleElectron.getCombinedMomentumError()
00352 );
00353
00354 if ( verbose )
00355 {
00356 std::cout << "[CalibratedGsfElectronProducer] Combined momentum after saving "
00357 << ele.p4().t() << std::endl;
00358 }
00359 }
00360 }
00361 } else
00362 {
00363 if ( verbose )
00364 {
00365 std::cout << "[CalibratedGsfElectronProducer] "
00366 << "You choose not to correct. Uncorrected Regression Energy is taken." << std::endl;
00367 }
00368 }
00369
00370
00371 const edm::OrphanHandle<reco::GsfElectronCollection> gsfNewElectronHandle = event.put(electrons, newElectronName_) ;
00372 energyFiller.insert(gsfNewElectronHandle,regressionValues.begin(),regressionValues.end());
00373 energyFiller.fill();
00374 energyErrorFiller.insert(gsfNewElectronHandle,regressionErrorValues.begin(),regressionErrorValues.end());
00375 energyErrorFiller.fill();
00376
00377 event.put(regrNewEnergyMap,nameNewEnergyReg_);
00378 event.put(regrNewEnergyErrorMap,nameNewEnergyErrorReg_);
00379 }
00380
00381 #include "FWCore/Framework/interface/MakerMacros.h"
00382 #include "FWCore/Framework/interface/ESProducer.h"
00383 #include "FWCore/Framework/interface/ModuleFactory.h"
00384 DEFINE_FWK_MODULE(CalibratedElectronProducer);