00001 #include <iostream>
00002 #include <vector>
00003 #include <memory>
00004
00005
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "FWCore/Utilities/interface/Exception.h"
00008
00009 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00010 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00011 #include "Geometry/CaloTopology/interface/CaloTopology.h"
00012 #include "Geometry/CaloEventSetup/interface/CaloTopologyRecord.h"
00013
00014
00015 #include "DataFormats/VertexReco/interface/Vertex.h"
00016 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00017 #include "DataFormats/EgammaReco/interface/ClusterShape.h"
00018 #include "DataFormats/EgammaCandidates/interface/PhotonCore.h"
00019 #include "DataFormats/EgammaCandidates/interface/Photon.h"
00020 #include "DataFormats/EgammaCandidates/interface/PhotonFwd.h"
00021 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
00022
00023 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
00024 #include "RecoCaloTools/Selectors/interface/CaloConeSelector.h"
00025 #include "RecoEgamma/EgammaPhotonProducers/interface/PhotonProducer.h"
00026 #include "RecoEgamma/EgammaIsolationAlgos/interface/EgammaTowerIsolation.h"
00027
00028
00029 PhotonProducer::PhotonProducer(const edm::ParameterSet& config) :
00030 conf_(config)
00031 {
00032
00033
00034
00035 photonCoreProducer_ = conf_.getParameter<edm::InputTag>("photonCoreProducer");
00036 barrelEcalHits_ = conf_.getParameter<edm::InputTag>("barrelEcalHits");
00037 endcapEcalHits_ = conf_.getParameter<edm::InputTag>("endcapEcalHits");
00038 vertexProducer_ = conf_.getParameter<std::string>("primaryVertexProducer");
00039 hcalTowers_ = conf_.getParameter<edm::InputTag>("hcalTowers");
00040 hOverEConeSize_ = conf_.getParameter<double>("hOverEConeSize");
00041 highEt_ = conf_.getParameter<double>("highEt");
00042
00043 minR9Barrel_ = conf_.getParameter<double>("minR9Barrel");
00044 minR9Endcap_ = conf_.getParameter<double>("minR9Endcap");
00045 usePrimaryVertex_ = conf_.getParameter<bool>("usePrimaryVertex");
00046 runMIPTagger_ = conf_.getParameter<bool>("runMIPTagger");
00047
00048 edm::ParameterSet posCalcParameters =
00049 config.getParameter<edm::ParameterSet>("posCalcParameters");
00050 posCalculator_ = PositionCalc(posCalcParameters);
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("minSCEtBarrel"));
00063 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("maxHoverEBarrel"));
00064 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("ecalRecHitSumEtOffsetBarrel"));
00065 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("ecalRecHitSumEtSlopeBarrel"));
00066 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("hcalTowerSumEtOffsetBarrel"));
00067 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("hcalTowerSumEtSlopeBarrel"));
00068 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("nTrackSolidConeBarrel"));
00069 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("nTrackHollowConeBarrel"));
00070 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("trackPtSumSolidConeBarrel"));
00071 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("trackPtSumHollowConeBarrel"));
00072 preselCutValuesBarrel_.push_back(conf_.getParameter<double>("sigmaIetaIetaCutBarrel"));
00073
00074 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("minSCEtEndcap"));
00075 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("maxHoverEEndcap"));
00076 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("ecalRecHitSumEtOffsetEndcap"));
00077 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("ecalRecHitSumEtSlopeEndcap"));
00078 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("hcalTowerSumEtOffsetEndcap"));
00079 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("hcalTowerSumEtSlopeEndcap"));
00080 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("nTrackSolidConeEndcap"));
00081 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("nTrackHollowConeEndcap"));
00082 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("trackPtSumSolidConeEndcap"));
00083 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("trackPtSumHollowConeEndcap"));
00084 preselCutValuesEndcap_.push_back(conf_.getParameter<double>("sigmaIetaIetaCutEndcap"));
00085
00086 energyCorrectionF = EcalClusterFunctionFactory::get()->create("EcalClusterEnergyCorrection", conf_);
00087
00088
00089 produces< reco::PhotonCollection >(PhotonCollection_);
00090
00091 }
00092
00093 PhotonProducer::~PhotonProducer() {
00094
00095 delete energyCorrectionF;
00096
00097 }
00098
00099
00100
00101 void PhotonProducer::beginRun (edm::Run& r, edm::EventSetup const & theEventSetup) {
00102
00103 thePhotonIsolationCalculator_ = new PhotonIsolationCalculator();
00104 edm::ParameterSet isolationSumsCalculatorSet = conf_.getParameter<edm::ParameterSet>("isolationSumsCalculatorSet");
00105 thePhotonIsolationCalculator_->setup(isolationSumsCalculatorSet);
00106
00107
00108
00109 thePhotonMIPHaloTagger_ = new PhotonMIPHaloTagger();
00110 edm::ParameterSet mipVariableSet = conf_.getParameter<edm::ParameterSet>("mipVariableSet");
00111 thePhotonMIPHaloTagger_->setup(mipVariableSet);
00112
00113
00114
00115 }
00116
00117 void PhotonProducer::endRun (edm::Run& r, edm::EventSetup const & theEventSetup) {
00118
00119 delete thePhotonIsolationCalculator_;
00120 delete thePhotonMIPHaloTagger_;
00121
00122 }
00123
00124
00125
00126
00127 void PhotonProducer::produce(edm::Event& theEvent, const edm::EventSetup& theEventSetup) {
00128
00129 using namespace edm;
00130
00131
00132 reco::PhotonCollection outputPhotonCollection;
00133 std::auto_ptr< reco::PhotonCollection > outputPhotonCollection_p(new reco::PhotonCollection);
00134
00135
00136
00137 bool validPhotonCoreHandle=true;
00138 Handle<reco::PhotonCoreCollection> photonCoreHandle;
00139 theEvent.getByLabel(photonCoreProducer_,photonCoreHandle);
00140 if (!photonCoreHandle.isValid()) {
00141 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<photonCoreProducer_.label();
00142 validPhotonCoreHandle=false;
00143 }
00144
00145
00146 bool validEcalRecHits=true;
00147 Handle<EcalRecHitCollection> barrelHitHandle;
00148 EcalRecHitCollection barrelRecHits;
00149 theEvent.getByLabel(barrelEcalHits_, barrelHitHandle);
00150 if (!barrelHitHandle.isValid()) {
00151 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<barrelEcalHits_.label();
00152 validEcalRecHits=false;
00153 }
00154 if ( validEcalRecHits) barrelRecHits = *(barrelHitHandle.product());
00155
00156
00157 Handle<EcalRecHitCollection> endcapHitHandle;
00158 theEvent.getByLabel(endcapEcalHits_, endcapHitHandle);
00159 EcalRecHitCollection endcapRecHits;
00160 if (!endcapHitHandle.isValid()) {
00161 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<endcapEcalHits_.label();
00162 validEcalRecHits=false;
00163 }
00164 if( validEcalRecHits) endcapRecHits = *(endcapHitHandle.product());
00165
00166
00167
00168 Handle<CaloTowerCollection> hcalTowersHandle;
00169 theEvent.getByLabel(hcalTowers_, hcalTowersHandle);
00170
00171
00172
00173 theEventSetup.get<CaloGeometryRecord>().get(theCaloGeom_);
00174
00175
00176
00177 energyCorrectionF->init(theEventSetup);
00178
00179 edm::ESHandle<CaloTopology> pTopology;
00180 theEventSetup.get<CaloTopologyRecord>().get(theCaloTopo_);
00181 const CaloTopology *topology = theCaloTopo_.product();
00182
00183
00184 Handle<reco::VertexCollection> vertexHandle;
00185 reco::VertexCollection vertexCollection;
00186 bool validVertex=true;
00187 if ( usePrimaryVertex_ ) {
00188 theEvent.getByLabel(vertexProducer_, vertexHandle);
00189 if (!vertexHandle.isValid()) {
00190 edm::LogWarning("PhotonProducer") << "Error! Can't get the product primary Vertex Collection "<< "\n";
00191 validVertex=false;
00192 }
00193 if (validVertex) vertexCollection = *(vertexHandle.product());
00194 }
00195 math::XYZPoint vtx(0.,0.,0.);
00196 if (vertexCollection.size()>0) vtx = vertexCollection.begin()->position();
00197
00198
00199 int iSC=0;
00200
00201 if ( validPhotonCoreHandle)
00202 fillPhotonCollection(theEvent,
00203 theEventSetup,
00204 photonCoreHandle,
00205 topology,
00206 &barrelRecHits,
00207 &endcapRecHits,
00208 hcalTowersHandle,
00209 vtx,
00210 outputPhotonCollection,
00211 iSC);
00212
00213
00214
00215 edm::LogInfo("PhotonProducer") << " Put in the event " << iSC << " Photon Candidates \n";
00216 outputPhotonCollection_p->assign(outputPhotonCollection.begin(),outputPhotonCollection.end());
00217 theEvent.put( outputPhotonCollection_p, PhotonCollection_);
00218
00219 }
00220
00221 void PhotonProducer::fillPhotonCollection(edm::Event& evt,
00222 edm::EventSetup const & es,
00223 const edm::Handle<reco::PhotonCoreCollection> & photonCoreHandle,
00224 const CaloTopology* topology,
00225 const EcalRecHitCollection* ecalBarrelHits,
00226 const EcalRecHitCollection* ecalEndcapHits,
00227 const edm::Handle<CaloTowerCollection> & hcalTowersHandle,
00228 math::XYZPoint & vtx,
00229 reco::PhotonCollection & outputPhotonCollection, int& iSC) {
00230
00231 const CaloGeometry* geometry = theCaloGeom_.product();
00232 const CaloSubdetectorGeometry* subDetGeometry =0 ;
00233 const CaloSubdetectorGeometry* geometryES = theCaloGeom_->getSubdetectorGeometry(DetId::Ecal, EcalPreshower);
00234 const EcalRecHitCollection* hits = 0 ;
00235 std::vector<double> preselCutValues;
00236 float minR9=0;
00237
00238
00239
00240 for(unsigned int lSC=0; lSC < photonCoreHandle->size(); lSC++) {
00241
00242 reco::PhotonCoreRef coreRef(reco::PhotonCoreRef(photonCoreHandle, lSC));
00243 reco::SuperClusterRef scRef=coreRef->superCluster();
00244 const reco::SuperCluster* pClus=&(*scRef);
00245 iSC++;
00246
00247 int subdet = scRef->seed()->hitsAndFractions()[0].first.subdetId();
00248 subDetGeometry = theCaloGeom_->getSubdetectorGeometry(DetId::Ecal, subdet);
00249
00250 if (subdet==EcalBarrel)
00251 {
00252 preselCutValues = preselCutValuesBarrel_;
00253 minR9=minR9Barrel_;
00254 hits= ecalBarrelHits;
00255 }
00256 else if (subdet==EcalEndcap)
00257 {
00258 preselCutValues = preselCutValuesEndcap_;
00259 minR9=minR9Endcap_;
00260 hits= ecalEndcapHits;
00261 }
00262 else
00263 { edm::LogWarning("")<<"PhotonProducer: do not know if it is a barrel or endcap SuperCluster" ; }
00264
00265
00266
00267 if (scRef->energy()/cosh(scRef->eta()) <= preselCutValues[0] ) continue;
00268
00269 const CaloTowerCollection* hcalTowersColl = hcalTowersHandle.product();
00270 EgammaTowerIsolation towerIso1(hOverEConeSize_,0.,0.,1,hcalTowersColl) ;
00271 EgammaTowerIsolation towerIso2(hOverEConeSize_,0.,0.,2,hcalTowersColl) ;
00272 double HoE1=towerIso1.getTowerESum(&(*scRef))/scRef->energy();
00273 double HoE2=towerIso2.getTowerESum(&(*scRef))/scRef->energy();
00274
00275
00276
00277
00278
00279 math::XYZPoint unconvPos = posCalculator_.Calculate_Location(scRef->seed()->hitsAndFractions(),hits,subDetGeometry,geometryES);
00280
00281
00282 float maxXtal = EcalClusterTools::eMax( *(scRef->seed()), &(*hits) );
00283 float e1x5 = EcalClusterTools::e1x5( *(scRef->seed()), &(*hits), &(*topology));
00284 float e2x5 = EcalClusterTools::e2x5Max( *(scRef->seed()), &(*hits), &(*topology));
00285 float e3x3 = EcalClusterTools::e3x3( *(scRef->seed()), &(*hits), &(*topology));
00286 float e5x5 = EcalClusterTools::e5x5( *(scRef->seed()), &(*hits), &(*topology));
00287 std::vector<float> cov = EcalClusterTools::covariances( *(scRef->seed()), &(*hits), &(*topology), geometry);
00288 float sigmaEtaEta = sqrt(cov[0]);
00289 std::vector<float> locCov = EcalClusterTools::localCovariances( *(scRef->seed()), &(*hits), &(*topology));
00290 float sigmaIetaIeta = sqrt(locCov[0]);
00291
00292 float r9 =e3x3/(scRef->rawEnergy());
00293
00294 math::XYZPoint caloPosition;
00295 double photonEnergy=0;
00296 if (r9>minR9) {
00297 caloPosition = unconvPos;
00298
00299 double deltaE = energyCorrectionF->getValue(*pClus, 1);
00300 if (subdet==EcalBarrel) e5x5 = e5x5 * (1.0 + deltaE/scRef->rawEnergy() );
00301 photonEnergy= e5x5 + scRef->preshowerEnergy() ;
00302 } else {
00303 caloPosition = scRef->position();
00304 photonEnergy=scRef->energy();
00305 }
00306
00307
00308
00309
00310
00311 math::XYZVector direction = caloPosition - vtx;
00312 math::XYZVector momentum = direction.unit() * photonEnergy ;
00313
00314
00315 const reco::Particle::LorentzVector p4(momentum.x(), momentum.y(), momentum.z(), photonEnergy );
00316 reco::Photon newCandidate(p4, caloPosition, coreRef, vtx);
00317
00318
00319 reco::Photon::FiducialFlags fiducialFlags;
00320 reco::Photon::IsolationVariables isolVarR03, isolVarR04;
00321 thePhotonIsolationCalculator_-> calculate ( &newCandidate,evt,es,fiducialFlags,isolVarR04, isolVarR03);
00322 newCandidate.setFiducialVolumeFlags( fiducialFlags );
00323 newCandidate.setIsolationVariables(isolVarR04, isolVarR03 );
00324
00326 reco::Photon::ShowerShape showerShape;
00327 showerShape.e1x5= e1x5;
00328 showerShape.e2x5= e2x5;
00329 showerShape.e3x3= e3x3;
00330 showerShape.e5x5= e5x5;
00331 showerShape.maxEnergyXtal = maxXtal;
00332 showerShape.sigmaEtaEta = sigmaEtaEta;
00333 showerShape.sigmaIetaIeta = sigmaIetaIeta;
00334 showerShape.hcalDepth1OverEcal = HoE1;
00335 showerShape.hcalDepth2OverEcal = HoE2;
00336 newCandidate.setShowerShapeVariables ( showerShape );
00337
00338
00339
00340 reco::Photon::MIPVariables mipVar ;
00341 if(subdet==EcalBarrel && runMIPTagger_ )
00342 {
00343
00344 thePhotonMIPHaloTagger_-> MIPcalculate( &newCandidate,evt,es,mipVar);
00345 newCandidate.setMIPVariables(mipVar);
00346 }
00347
00348
00350 bool isLooseEM=true;
00351 if ( newCandidate.pt() < highEt_) {
00352 if ( newCandidate.hadronicOverEm() >= preselCutValues[1] ) isLooseEM=false;
00353 if ( newCandidate.ecalRecHitSumEtConeDR04() > preselCutValues[2]+ preselCutValues[3]*newCandidate.pt() ) isLooseEM=false;
00354 if ( newCandidate.hcalTowerSumEtConeDR04() > preselCutValues[4]+ preselCutValues[5]*newCandidate.pt() ) isLooseEM=false;
00355 if ( newCandidate.nTrkSolidConeDR04() > int(preselCutValues[6]) ) isLooseEM=false;
00356 if ( newCandidate.nTrkHollowConeDR04() > int(preselCutValues[7]) ) isLooseEM=false;
00357 if ( newCandidate.trkSumPtSolidConeDR04() > preselCutValues[8] ) isLooseEM=false;
00358 if ( newCandidate.trkSumPtHollowConeDR04() > preselCutValues[9] ) isLooseEM=false;
00359 if ( newCandidate.sigmaIetaIeta() > preselCutValues[10] ) isLooseEM=false;
00360 }
00361
00362
00363
00364 if ( isLooseEM)
00365 outputPhotonCollection.push_back(newCandidate);
00366
00367
00368 }
00369 }
00370