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