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/PhotonFwd.h"
00019 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
00020
00021 #include "DataFormats/EgammaReco/interface/ElectronPixelSeed.h"
00022 #include "RecoCaloTools/Selectors/interface/CaloConeSelector.h"
00023 #include "RecoEgamma/EgammaPhotonProducers/interface/PhotonProducer.h"
00024
00025
00026
00027 PhotonProducer::PhotonProducer(const edm::ParameterSet& config) :
00028 conf_(config),
00029 theLikelihoodCalc_(0)
00030
00031 {
00032
00033
00034 scHybridBarrelProducer_ = conf_.getParameter<edm::InputTag>("scHybridBarrelProducer");
00035 scIslandEndcapProducer_ = conf_.getParameter<edm::InputTag>("scIslandEndcapProducer");
00036 barrelEcalHits_ = conf_.getParameter<edm::InputTag>("barrelEcalHits");
00037 endcapEcalHits_ = conf_.getParameter<edm::InputTag>("endcapEcalHits");
00038
00039 conversionProducer_ = conf_.getParameter<std::string>("conversionProducer");
00040 conversionCollection_ = conf_.getParameter<std::string>("conversionCollection");
00041 vertexProducer_ = conf_.getParameter<std::string>("primaryVertexProducer");
00042 PhotonCollection_ = conf_.getParameter<std::string>("photonCollection");
00043 pixelSeedProducer_ = conf_.getParameter<std::string>("pixelSeedProducer");
00044
00045 hbheLabel_ = conf_.getParameter<std::string>("hbheModule");
00046 hbheInstanceName_ = conf_.getParameter<std::string>("hbheInstance");
00047 hOverEConeSize_ = conf_.getParameter<double>("hOverEConeSize");
00048 maxHOverE_ = conf_.getParameter<double>("maxHOverE");
00049 minSCEt_ = conf_.getParameter<double>("minSCEt");
00050 minR9_ = conf_.getParameter<double>("minR9");
00051 likelihoodWeights_= conf_.getParameter<std::string>("MVA_weights_location");
00052
00053 usePrimaryVertex_ = conf_.getParameter<bool>("usePrimaryVertex");
00054 risolveAmbiguity_ = conf_.getParameter<bool>("risolveConversionAmbiguity");
00055
00056
00057
00058 std::map<std::string,double> providedParameters;
00059 providedParameters.insert(std::make_pair("LogWeighted",conf_.getParameter<bool>("posCalc_logweight")));
00060 providedParameters.insert(std::make_pair("T0_barl",conf_.getParameter<double>("posCalc_t0_barl")));
00061 providedParameters.insert(std::make_pair("T0_endc",conf_.getParameter<double>("posCalc_t0_endc")));
00062 providedParameters.insert(std::make_pair("T0_endcPresh",conf_.getParameter<double>("posCalc_t0_endcPresh")));
00063 providedParameters.insert(std::make_pair("W0",conf_.getParameter<double>("posCalc_w0")));
00064 providedParameters.insert(std::make_pair("X0",conf_.getParameter<double>("posCalc_x0")));
00065 posCalculator_ = PositionCalc(providedParameters);
00066
00067
00068 produces< reco::PhotonCollection >(PhotonCollection_);
00069
00070 }
00071
00072 PhotonProducer::~PhotonProducer() {
00073
00074 delete theLikelihoodCalc_;
00075
00076 }
00077
00078
00079 void PhotonProducer::beginJob (edm::EventSetup const & theEventSetup) {
00080 theLikelihoodCalc_ = new ConversionLikelihoodCalculator();
00081 edm::FileInPath path_mvaWeightFile(likelihoodWeights_.c_str() );
00082 theLikelihoodCalc_->setWeightsFile(path_mvaWeightFile.fullPath().c_str());
00083
00084
00085 }
00086
00087
00088 void PhotonProducer::produce(edm::Event& theEvent, const edm::EventSetup& theEventSetup) {
00089
00090 using namespace edm;
00091
00092
00093 reco::PhotonCollection outputPhotonCollection;
00094 std::auto_ptr< reco::PhotonCollection > outputPhotonCollection_p(new reco::PhotonCollection);
00095
00096
00097 bool validBarrelSCHandle=true;
00098 Handle<reco::SuperClusterCollection> scBarrelHandle;
00099 theEvent.getByLabel(scHybridBarrelProducer_,scBarrelHandle);
00100 if (!scBarrelHandle.isValid()) {
00101 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<scHybridBarrelProducer_.label();
00102 bool validBarrelSCHandle=false;
00103 }
00104
00105
00106
00107 bool validEndcapSCHandle=true;
00108 Handle<reco::SuperClusterCollection> scEndcapHandle;
00109 theEvent.getByLabel(scIslandEndcapProducer_,scEndcapHandle);
00110 if (!scEndcapHandle.isValid()) {
00111 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<scIslandEndcapProducer_.label();
00112 validEndcapSCHandle=false;
00113 }
00114
00115
00116
00117 bool validEcalRecHits=true;
00118 Handle<EcalRecHitCollection> barrelHitHandle;
00119 EcalRecHitCollection barrelRecHits;
00120 theEvent.getByLabel(barrelEcalHits_, barrelHitHandle);
00121 if (!barrelHitHandle.isValid()) {
00122 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<barrelEcalHits_.label();
00123 validEcalRecHits=false;
00124 }
00125 if ( validEcalRecHits) barrelRecHits = *(barrelHitHandle.product());
00126
00127
00128 Handle<EcalRecHitCollection> endcapHitHandle;
00129 theEvent.getByLabel(endcapEcalHits_, endcapHitHandle);
00130 EcalRecHitCollection endcapRecHits;
00131 if (!endcapHitHandle.isValid()) {
00132 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<endcapEcalHits_.label();
00133 validEcalRecHits=false;
00134 }
00135 if( validEcalRecHits) endcapRecHits = *(endcapHitHandle.product());
00136
00137
00138
00139 theEventSetup.get<CaloGeometryRecord>().get(theCaloGeom_);
00140 const CaloSubdetectorGeometry *barrelGeometry = theCaloGeom_->getSubdetectorGeometry(DetId::Ecal, EcalBarrel);
00141 const CaloSubdetectorGeometry *endcapGeometry = theCaloGeom_->getSubdetectorGeometry(DetId::Ecal, EcalEndcap);
00142 const CaloSubdetectorGeometry *preshowerGeometry = theCaloGeom_->getSubdetectorGeometry(DetId::Ecal, EcalPreshower);
00143
00144 edm::ESHandle<CaloTopology> pTopology;
00145 theEventSetup.get<CaloTopologyRecord>().get(theCaloTopo_);
00146 const CaloTopology *topology = theCaloTopo_.product();
00147
00148
00150 validConversions_=true;
00151 edm::Handle<reco::ConversionCollection> conversionHandle;
00152 theEvent.getByLabel(conversionProducer_, conversionCollection_ , conversionHandle);
00153 if (!conversionHandle.isValid()) {
00154
00155 validConversions_=false;
00156 }
00157
00158
00159
00160
00161 bool validHcalRecHits=true;
00162 Handle<HBHERecHitCollection> hbhe;
00163 std::auto_ptr<HBHERecHitMetaCollection> mhbhe;
00164 theEvent.getByLabel(hbheLabel_,hbheInstanceName_,hbhe);
00165 if (!hbhe.isValid()) {
00166 edm::LogError("PhotonProducer") << "Error! Can't get the product "<<hbheInstanceName_.c_str();
00167 validHcalRecHits=false;
00168 }
00169
00170 if ( hOverEConeSize_ > 0.) {
00171 if ( validHcalRecHits ) mhbhe= std::auto_ptr<HBHERecHitMetaCollection>(new HBHERecHitMetaCollection(*hbhe));
00172 }
00173
00174
00175 theHoverEcalc_=HoECalculator(theCaloGeom_);
00176
00177
00178 validPixelSeeds_=true;
00179 Handle<reco::ElectronPixelSeedCollection> pixelSeedHandle;
00180 reco::ElectronPixelSeedCollection pixelSeeds;
00181 theEvent.getByLabel(pixelSeedProducer_, pixelSeedHandle);
00182 if (!pixelSeedHandle.isValid()) {
00183
00184 validPixelSeeds_=false;
00185 }
00186 if ( validPixelSeeds_) pixelSeeds = *(pixelSeedHandle.product());
00187
00188
00189
00190
00191 Handle<reco::VertexCollection> vertexHandle;
00192 reco::VertexCollection vertexCollection;
00193 bool validVertex=true;
00194 if ( usePrimaryVertex_ ) {
00195 theEvent.getByLabel(vertexProducer_, vertexHandle);
00196 if (!vertexHandle.isValid()) {
00197 edm::LogError("PhotonProducer") << "Error! Can't get the product primary Vertex Collection "<< "\n";
00198 validVertex=false;
00199 }
00200 if (validVertex) vertexCollection = *(vertexHandle.product());
00201 }
00202 math::XYZPoint vtx(0.,0.,0.);
00203 if (vertexCollection.size()>0) vtx = vertexCollection.begin()->position();
00204
00205 edm::LogInfo("PhotonProducer") << "Constructing Photon 4-vectors assuming primary vertex position: " << vtx << std::endl;
00206
00207 int iSC=0;
00208
00209 if ( validBarrelSCHandle) fillPhotonCollection(scBarrelHandle,barrelGeometry,preshowerGeometry,topology,&barrelRecHits,mhbhe.get(),conversionHandle,pixelSeeds,vtx,outputPhotonCollection,iSC);
00210 if ( validEndcapSCHandle) fillPhotonCollection(scEndcapHandle,endcapGeometry,preshowerGeometry,topology,&endcapRecHits,mhbhe.get(),conversionHandle,pixelSeeds,vtx,outputPhotonCollection,iSC);
00211
00212
00213 edm::LogInfo("PhotonProducer") << " Put in the event " << iSC << " Photon Candidates \n";
00214 outputPhotonCollection_p->assign(outputPhotonCollection.begin(),outputPhotonCollection.end());
00215 theEvent.put( outputPhotonCollection_p, PhotonCollection_);
00216
00217 }
00218
00219 void PhotonProducer::fillPhotonCollection(
00220 const edm::Handle<reco::SuperClusterCollection> & scHandle,
00221 const CaloSubdetectorGeometry *geometry,
00222 const CaloSubdetectorGeometry *geometryES,
00223 const CaloTopology *topology,
00224 const EcalRecHitCollection* hits,
00225 HBHERecHitMetaCollection *mhbhe,
00226 const edm::Handle<reco::ConversionCollection> & conversionHandle,
00227 const reco::ElectronPixelSeedCollection& pixelSeeds,
00228 math::XYZPoint & vtx,
00229 reco::PhotonCollection & outputPhotonCollection, int& iSC) {
00230
00231
00232 reco::ElectronPixelSeedCollection::const_iterator pixelSeedItr;
00233 for(unsigned int lSC=0; lSC < scHandle->size(); lSC++) {
00234
00235
00236 reco::SuperClusterRef scRef(reco::SuperClusterRef(scHandle, lSC));
00237 iSC++;
00238 const reco::SuperCluster* pClus=&(*scRef);
00239
00240
00241 if (scRef->energy()/cosh(scRef->eta()) <= minSCEt_) continue;
00242
00243 double HoE=theHoverEcalc_(pClus,mhbhe);
00244 if (HoE>=maxHOverE_) continue;
00245
00246
00247
00248
00249 math::XYZPoint unconvPos = posCalculator_.Calculate_Location(scRef->seed()->getHitsByDetId(),hits,geometry,geometryES);
00250
00251
00252 float e3x3= EcalClusterTools::e3x3( *(scRef->seed()), &(*hits), &(*topology));
00253 float r9 =e3x3/(scRef->rawEnergy());
00254 float e5x5= EcalClusterTools::e5x5( *(scRef->seed()), &(*hits), &(*topology));
00255
00256 math::XYZPoint caloPosition;
00257 double photonEnergy=0;
00258 if (r9>minR9_) {
00259 caloPosition = unconvPos;
00260 photonEnergy=e5x5;
00261 } else {
00262 caloPosition = scRef->position();
00263 photonEnergy=scRef->energy();
00264 }
00265
00266
00267 bool hasSeed = false;
00268 if ( validPixelSeeds_) {
00269 for(pixelSeedItr = pixelSeeds.begin(); pixelSeedItr != pixelSeeds.end(); pixelSeedItr++) {
00270 if (fabs(pixelSeedItr->superCluster()->eta() - scRef->eta()) < 0.0001 &&
00271 fabs(pixelSeedItr->superCluster()->phi() - scRef->phi()) < 0.0001) {
00272 hasSeed=true;
00273 break;
00274 }
00275 }
00276 }
00277
00278
00279 math::XYZVector direction = caloPosition - vtx;
00280 math::XYZVector momentum = direction.unit() * photonEnergy ;
00281
00282 const reco::Particle::LorentzVector p4(momentum.x(), momentum.y(), momentum.z(), photonEnergy );
00283
00284
00285 reco::Photon newCandidate(p4, caloPosition, scRef, HoE, hasSeed, vtx);
00286
00287 if ( validConversions_) {
00288
00289 if ( risolveAmbiguity_ ) {
00290
00291 reco::ConversionRef bestRef=solveAmbiguity( conversionHandle , scRef);
00292
00293 if (bestRef.isNonnull() ) newCandidate.addConversion(bestRef);
00294
00295
00296 } else {
00297
00298
00299 for( unsigned int icp = 0; icp < conversionHandle->size(); icp++) {
00300
00301 reco::ConversionRef cpRef(reco::ConversionRef(conversionHandle,icp));
00302
00303 if (!( scRef.id() == cpRef->caloCluster()[0].id() && scRef.key() == cpRef->caloCluster()[0].key() )) continue;
00304 if ( !cpRef->isConverted() ) continue;
00305 newCandidate.addConversion(cpRef);
00306
00307 }
00308
00309 }
00310
00311 }
00312
00313
00314 outputPhotonCollection.push_back(newCandidate);
00315
00316
00317 }
00318
00319 }
00320
00321
00322
00323 reco::ConversionRef PhotonProducer::solveAmbiguity(const edm::Handle<reco::ConversionCollection> & conversionHandle, reco::SuperClusterRef& scRef) {
00324
00325 std::multimap<reco::ConversionRef, double > convMap;
00326
00327
00328 for ( unsigned int icp=0; icp< conversionHandle->size(); icp++) {
00329 reco::ConversionRef cpRef(reco::ConversionRef(conversionHandle,icp));
00330
00331
00332 if (!( scRef.id() == cpRef->caloCluster()[0].id() && scRef.key() == cpRef->caloCluster()[0].key() )) continue;
00333 if ( !cpRef->isConverted() ) continue;
00334
00335 double like = theLikelihoodCalc_->calculateLikelihood(cpRef);
00336
00337 convMap.insert ( std::make_pair(cpRef,like) ) ;
00338 }
00339
00340
00341
00342 std::multimap<reco::ConversionRef, double >::iterator iMap;
00343 double max_lh = -1.;
00344 reco::ConversionRef bestRef;
00345
00346 for (iMap=convMap.begin(); iMap!=convMap.end(); iMap++) {
00347 double like = iMap->second;
00348 if (like > max_lh) {
00349 max_lh = like;
00350 bestRef=iMap->first;
00351 }
00352 }
00353
00354
00355
00356 float ep=0;
00357 if ( max_lh <0 ) {
00358
00360 float epMin=999;
00361
00362 for (iMap=convMap.begin(); iMap!=convMap.end(); iMap++) {
00363 reco::ConversionRef convRef=iMap->first;
00364 std::vector<reco::TrackRef> tracks = convRef->tracks();
00365 float px=tracks[0]->innerMomentum().x();
00366 float py=tracks[0]->innerMomentum().y();
00367 float pz=tracks[0]->innerMomentum().z();
00368 float p=sqrt(px*px+py*py+pz*pz);
00369 ep=fabs(1.-convRef->caloCluster()[0]->energy()/p);
00370
00371 if ( ep<epMin) {
00372 epMin=ep;
00373 bestRef=iMap->first;
00374 }
00375 }
00376
00377
00378 }
00379
00380
00381 return bestRef;
00382
00383
00384 }
00385
00386 double PhotonProducer::hOverE(const reco::SuperClusterRef & scRef,
00387 HBHERecHitMetaCollection *mhbhe){
00388
00390 double HoE=0;
00391 if (mhbhe) {
00392 CaloConeSelector sel(hOverEConeSize_, theCaloGeom_.product(), DetId::Hcal);
00393 GlobalPoint pclu((*scRef).x(),(*scRef).y(),(*scRef).z());
00394 double hcalEnergy = 0.;
00395 std::auto_ptr<CaloRecHitMetaCollectionV> chosen=sel.select(pclu,*mhbhe);
00396 for (CaloRecHitMetaCollectionV::const_iterator i=chosen->begin(); i!=chosen->end(); i++) {
00397 hcalEnergy += i->energy();
00398 }
00399 HoE= hcalEnergy/(*scRef).energy();
00400 LogDebug("") << "H/E : " << HoE;
00401 }
00402 return HoE;
00403 }