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