Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-14 02:53:33

0001 /**
0002   \class    pat::PATPhotonProducer PATPhotonProducer.h "PhysicsTools/PatAlgos/interface/PATPhotonProducer.h"
0003   \brief    Produces the pat::Photon
0004 
0005    The PATPhotonProducer produces the analysis-level pat::Photon starting from
0006    a collection of objects of PhotonType.
0007 
0008   \author   Steven Lowette
0009   \version  $Id: PATPhotonProducer.h,v 1.19 2009/06/25 23:49:35 gpetrucc Exp $
0010 */
0011 
0012 #include "CommonTools/Egamma/interface/ConversionTools.h"
0013 #include "CommonTools/Utils/interface/EtComparator.h"
0014 #include "DataFormats/Common/interface/View.h"
0015 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
0016 #include "DataFormats/EcalRecHit/interface/EcalRecHit.h"
0017 #include "DataFormats/EcalRecHit/interface/EcalRecHitCollections.h"
0018 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0019 #include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
0020 #include "DataFormats/PatCandidates/interface/Electron.h"
0021 #include "DataFormats/PatCandidates/interface/Photon.h"
0022 #include "DataFormats/PatCandidates/interface/UserData.h"
0023 #include "FWCore/Framework/interface/ConsumesCollector.h"
0024 #include "FWCore/Framework/interface/ESHandle.h"
0025 #include "FWCore/Framework/interface/Event.h"
0026 #include "FWCore/Framework/interface/EventSetup.h"
0027 #include "FWCore/Framework/interface/stream/EDProducer.h"
0028 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0029 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0030 #include "FWCore/ParameterSet/interface/EmptyGroupDescription.h"
0031 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0032 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0033 #include "FWCore/Utilities/interface/InputTag.h"
0034 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
0035 #include "Geometry/CaloTopology/interface/CaloSubdetectorTopology.h"
0036 #include "Geometry/CaloTopology/interface/CaloTopology.h"
0037 #include "Geometry/Records/interface/CaloGeometryRecord.h"
0038 #include "Geometry/Records/interface/CaloTopologyRecord.h"
0039 #include "PhysicsTools/PatAlgos/interface/EfficiencyLoader.h"
0040 #include "PhysicsTools/PatAlgos/interface/KinResolutionsLoader.h"
0041 #include "PhysicsTools/PatAlgos/interface/MultiIsolator.h"
0042 #include "PhysicsTools/PatAlgos/interface/PATUserDataHelper.h"
0043 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterLazyTools.h"
0044 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterTools.h"
0045 #include "RecoEgamma/EgammaTools/interface/EcalRegressionData.h"
0046 
0047 namespace pat {
0048 
0049   class PATPhotonProducer : public edm::stream::EDProducer<> {
0050   public:
0051     explicit PATPhotonProducer(const edm::ParameterSet& iConfig);
0052     ~PATPhotonProducer() override;
0053 
0054     void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
0055 
0056     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0057 
0058   private:
0059     // configurables
0060     edm::EDGetTokenT<edm::View<reco::Photon>> photonToken_;
0061     edm::EDGetTokenT<reco::GsfElectronCollection> electronToken_;
0062     edm::EDGetTokenT<reco::ConversionCollection> hConversionsToken_;
0063     edm::EDGetTokenT<reco::BeamSpot> beamLineToken_;
0064 
0065     bool embedSuperCluster_;
0066     bool embedSeedCluster_;
0067     bool embedBasicClusters_;
0068     bool embedPreshowerClusters_;
0069     bool embedRecHits_;
0070 
0071     edm::InputTag reducedBarrelRecHitCollection_;
0072     edm::EDGetTokenT<EcalRecHitCollection> reducedBarrelRecHitCollectionToken_;
0073     edm::InputTag reducedEndcapRecHitCollection_;
0074     edm::EDGetTokenT<EcalRecHitCollection> reducedEndcapRecHitCollectionToken_;
0075 
0076     const EcalClusterLazyTools::ESGetTokens ecalClusterToolsESGetTokens_;
0077 
0078     bool addPFClusterIso_;
0079     bool addPuppiIsolation_;
0080     edm::EDGetTokenT<edm::ValueMap<float>> ecalPFClusterIsoT_;
0081     edm::EDGetTokenT<edm::ValueMap<float>> hcalPFClusterIsoT_;
0082 
0083     bool addGenMatch_;
0084     bool embedGenMatch_;
0085     std::vector<edm::EDGetTokenT<edm::Association<reco::GenParticleCollection>>> genMatchTokens_;
0086 
0087     // tools
0088     GreaterByEt<Photon> eTComparator_;
0089 
0090     typedef std::vector<edm::Handle<edm::ValueMap<IsoDeposit>>> IsoDepositMaps;
0091     typedef std::vector<edm::Handle<edm::ValueMap<double>>> IsolationValueMaps;
0092     typedef std::pair<pat::IsolationKeys, edm::InputTag> IsolationLabel;
0093     typedef std::vector<IsolationLabel> IsolationLabels;
0094 
0095     pat::helper::MultiIsolator isolator_;
0096     pat::helper::MultiIsolator::IsolationValuePairs isolatorTmpStorage_;  // better here than recreate at each event
0097     std::vector<edm::EDGetTokenT<edm::ValueMap<IsoDeposit>>> isoDepositTokens_;
0098     std::vector<edm::EDGetTokenT<edm::ValueMap<double>>> isolationValueTokens_;
0099 
0100     IsolationLabels isoDepositLabels_;
0101     IsolationLabels isolationValueLabels_;
0102 
0103     /// fill the labels vector from the contents of the parameter set,
0104     /// for the isodeposit or isolation values embedding
0105     template <typename T>
0106     void readIsolationLabels(const edm::ParameterSet& iConfig,
0107                              const char* psetName,
0108                              IsolationLabels& labels,
0109                              std::vector<edm::EDGetTokenT<edm::ValueMap<T>>>& tokens);
0110 
0111     bool addEfficiencies_;
0112     pat::helper::EfficiencyLoader efficiencyLoader_;
0113 
0114     bool addResolutions_;
0115     pat::helper::KinResolutionsLoader resolutionLoader_;
0116 
0117     bool addPhotonID_;
0118     typedef std::pair<std::string, edm::InputTag> NameTag;
0119     std::vector<NameTag> photIDSrcs_;
0120     std::vector<edm::EDGetTokenT<edm::ValueMap<Bool_t>>> photIDTokens_;
0121 
0122     bool useUserData_;
0123     //PUPPI isolation tokens
0124     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_charged_hadrons_;
0125     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_neutral_hadrons_;
0126     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_photons_;
0127     pat::PATUserDataHelper<pat::Photon> userDataHelper_;
0128 
0129     const CaloTopology* ecalTopology_;
0130     const CaloGeometry* ecalGeometry_;
0131 
0132     bool saveRegressionData_;
0133 
0134     const edm::ESGetToken<CaloTopology, CaloTopologyRecord> ecalTopologyToken_;
0135     const edm::ESGetToken<CaloGeometry, CaloGeometryRecord> ecalGeometryToken_;
0136   };
0137 
0138 }  // namespace pat
0139 
0140 template <typename T>
0141 void pat::PATPhotonProducer::readIsolationLabels(const edm::ParameterSet& iConfig,
0142                                                  const char* psetName,
0143                                                  pat::PATPhotonProducer::IsolationLabels& labels,
0144                                                  std::vector<edm::EDGetTokenT<edm::ValueMap<T>>>& tokens) {
0145   labels.clear();
0146 
0147   if (iConfig.exists(psetName)) {
0148     edm::ParameterSet depconf = iConfig.getParameter<edm::ParameterSet>(psetName);
0149 
0150     if (depconf.exists("tracker"))
0151       labels.push_back(std::make_pair(pat::TrackIso, depconf.getParameter<edm::InputTag>("tracker")));
0152     if (depconf.exists("ecal"))
0153       labels.push_back(std::make_pair(pat::EcalIso, depconf.getParameter<edm::InputTag>("ecal")));
0154     if (depconf.exists("hcal"))
0155       labels.push_back(std::make_pair(pat::HcalIso, depconf.getParameter<edm::InputTag>("hcal")));
0156     if (depconf.exists("pfAllParticles")) {
0157       labels.push_back(std::make_pair(pat::PfAllParticleIso, depconf.getParameter<edm::InputTag>("pfAllParticles")));
0158     }
0159     if (depconf.exists("pfChargedHadrons")) {
0160       labels.push_back(
0161           std::make_pair(pat::PfChargedHadronIso, depconf.getParameter<edm::InputTag>("pfChargedHadrons")));
0162     }
0163     if (depconf.exists("pfChargedAll")) {
0164       labels.push_back(std::make_pair(pat::PfChargedAllIso, depconf.getParameter<edm::InputTag>("pfChargedAll")));
0165     }
0166     if (depconf.exists("pfPUChargedHadrons")) {
0167       labels.push_back(
0168           std::make_pair(pat::PfPUChargedHadronIso, depconf.getParameter<edm::InputTag>("pfPUChargedHadrons")));
0169     }
0170     if (depconf.exists("pfNeutralHadrons")) {
0171       labels.push_back(
0172           std::make_pair(pat::PfNeutralHadronIso, depconf.getParameter<edm::InputTag>("pfNeutralHadrons")));
0173     }
0174     if (depconf.exists("pfPhotons")) {
0175       labels.push_back(std::make_pair(pat::PfGammaIso, depconf.getParameter<edm::InputTag>("pfPhotons")));
0176     }
0177     if (depconf.exists("user")) {
0178       std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag>>("user");
0179       std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
0180       int key = pat::IsolationKeys::UserBaseIso;
0181       for (; it != ed; ++it, ++key) {
0182         labels.push_back(std::make_pair(pat::IsolationKeys(key), *it));
0183       }
0184     }
0185 
0186     tokens = edm::vector_transform(
0187         labels, [this](IsolationLabel const& label) { return consumes<edm::ValueMap<T>>(label.second); });
0188   }
0189   tokens = edm::vector_transform(
0190       labels, [this](IsolationLabel const& label) { return consumes<edm::ValueMap<T>>(label.second); });
0191 }
0192 
0193 using namespace pat;
0194 
0195 PATPhotonProducer::PATPhotonProducer(const edm::ParameterSet& iConfig)
0196     : ecalClusterToolsESGetTokens_{consumesCollector()},
0197       isolator_(iConfig.getParameter<edm::ParameterSet>("userIsolation"), consumesCollector(), false),
0198       useUserData_(iConfig.exists("userData")),
0199       ecalTopologyToken_{esConsumes()},
0200       ecalGeometryToken_{esConsumes()} {
0201   // initialize the configurables
0202   photonToken_ = consumes<edm::View<reco::Photon>>(iConfig.getParameter<edm::InputTag>("photonSource"));
0203   electronToken_ = consumes<reco::GsfElectronCollection>(iConfig.getParameter<edm::InputTag>("electronSource"));
0204   hConversionsToken_ = consumes<reco::ConversionCollection>(iConfig.getParameter<edm::InputTag>("conversionSource"));
0205   beamLineToken_ = consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("beamLineSrc"));
0206   embedSuperCluster_ = iConfig.getParameter<bool>("embedSuperCluster");
0207   embedSeedCluster_ = iConfig.getParameter<bool>("embedSeedCluster");
0208   embedBasicClusters_ = iConfig.getParameter<bool>("embedBasicClusters");
0209   embedPreshowerClusters_ = iConfig.getParameter<bool>("embedPreshowerClusters");
0210   embedRecHits_ = iConfig.getParameter<bool>("embedRecHits");
0211   reducedBarrelRecHitCollection_ = iConfig.getParameter<edm::InputTag>("reducedBarrelRecHitCollection");
0212   reducedBarrelRecHitCollectionToken_ = mayConsume<EcalRecHitCollection>(reducedBarrelRecHitCollection_);
0213   reducedEndcapRecHitCollection_ = iConfig.getParameter<edm::InputTag>("reducedEndcapRecHitCollection");
0214   reducedEndcapRecHitCollectionToken_ = mayConsume<EcalRecHitCollection>(reducedEndcapRecHitCollection_);
0215   // MC matching configurables
0216   addGenMatch_ = iConfig.getParameter<bool>("addGenMatch");
0217   if (addGenMatch_) {
0218     embedGenMatch_ = iConfig.getParameter<bool>("embedGenMatch");
0219     genMatchTokens_.push_back(consumes<edm::Association<reco::GenParticleCollection>>(
0220         iConfig.getParameter<edm::InputTag>("genParticleMatch")));
0221   }
0222   // Efficiency configurables
0223   addEfficiencies_ = iConfig.getParameter<bool>("addEfficiencies");
0224   if (addEfficiencies_) {
0225     efficiencyLoader_ =
0226         pat::helper::EfficiencyLoader(iConfig.getParameter<edm::ParameterSet>("efficiencies"), consumesCollector());
0227   }
0228   // PFCluster Isolation maps
0229   addPuppiIsolation_ = iConfig.getParameter<bool>("addPuppiIsolation");
0230   if (addPuppiIsolation_) {
0231     PUPPIIsolation_charged_hadrons_ =
0232         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationChargedHadrons"));
0233     PUPPIIsolation_neutral_hadrons_ =
0234         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationNeutralHadrons"));
0235     PUPPIIsolation_photons_ =
0236         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationPhotons"));
0237   }
0238   addPFClusterIso_ = iConfig.getParameter<bool>("addPFClusterIso");
0239   if (addPFClusterIso_) {
0240     ecalPFClusterIsoT_ = consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("ecalPFClusterIsoMap"));
0241     auto hcPFC = iConfig.getParameter<edm::InputTag>("hcalPFClusterIsoMap");
0242     if (not hcPFC.label().empty())
0243       hcalPFClusterIsoT_ = consumes<edm::ValueMap<float>>(hcPFC);
0244   }
0245 
0246   // photon ID configurables
0247   addPhotonID_ = iConfig.getParameter<bool>("addPhotonID");
0248   if (addPhotonID_) {
0249     // it might be a single photon ID
0250     if (iConfig.existsAs<edm::InputTag>("photonIDSource")) {
0251       photIDSrcs_.push_back(NameTag("", iConfig.getParameter<edm::InputTag>("photonIDSource")));
0252     }
0253     // or there might be many of them
0254     if (iConfig.existsAs<edm::ParameterSet>("photonIDSources")) {
0255       // please don't configure me twice
0256       if (!photIDSrcs_.empty()) {
0257         throw cms::Exception("Configuration")
0258             << "PATPhotonProducer: you can't specify both 'photonIDSource' and 'photonIDSources'\n";
0259       }
0260       // read the different photon ID names
0261       edm::ParameterSet idps = iConfig.getParameter<edm::ParameterSet>("photonIDSources");
0262       std::vector<std::string> names = idps.getParameterNamesForType<edm::InputTag>();
0263       for (std::vector<std::string>::const_iterator it = names.begin(), ed = names.end(); it != ed; ++it) {
0264         photIDSrcs_.push_back(NameTag(*it, idps.getParameter<edm::InputTag>(*it)));
0265       }
0266     }
0267     // but in any case at least once
0268     if (photIDSrcs_.empty())
0269       throw cms::Exception("Configuration") << "PATPhotonProducer: id addPhotonID is true, you must specify either:\n"
0270                                             << "\tInputTag photonIDSource = <someTag>\n"
0271                                             << "or\n"
0272                                             << "\tPSet photonIDSources = { \n"
0273                                             << "\t\tInputTag <someName> = <someTag>   // as many as you want \n "
0274                                             << "\t}\n";
0275   }
0276   photIDTokens_ = edm::vector_transform(
0277       photIDSrcs_, [this](NameTag const& tag) { return mayConsume<edm::ValueMap<Bool_t>>(tag.second); });
0278   // Resolution configurables
0279   addResolutions_ = iConfig.getParameter<bool>("addResolutions");
0280   if (addResolutions_) {
0281     resolutionLoader_ =
0282         pat::helper::KinResolutionsLoader(iConfig.getParameter<edm::ParameterSet>("resolutions"), consumesCollector());
0283   }
0284   // Check to see if the user wants to add user data
0285   if (useUserData_) {
0286     userDataHelper_ =
0287         PATUserDataHelper<Photon>(iConfig.getParameter<edm::ParameterSet>("userData"), consumesCollector());
0288   }
0289   // produces vector of photons
0290   produces<std::vector<Photon>>();
0291 
0292   // read isoDeposit labels, for direct embedding
0293   readIsolationLabels(iConfig, "isoDeposits", isoDepositLabels_, isoDepositTokens_);
0294   // read isolation value labels, for direct embedding
0295   readIsolationLabels(iConfig, "isolationValues", isolationValueLabels_, isolationValueTokens_);
0296 
0297   saveRegressionData_ = iConfig.getParameter<bool>("saveRegressionData");
0298 }
0299 
0300 PATPhotonProducer::~PATPhotonProducer() {}
0301 
0302 void PATPhotonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0303   // switch off embedding (in unschedules mode)
0304   if (iEvent.isRealData()) {
0305     addGenMatch_ = false;
0306     embedGenMatch_ = false;
0307   }
0308 
0309   ecalTopology_ = &iSetup.getData(ecalTopologyToken_);
0310   ecalGeometry_ = &iSetup.getData(ecalGeometryToken_);
0311 
0312   // Get the vector of Photon's from the event
0313   edm::Handle<edm::View<reco::Photon>> photons;
0314   iEvent.getByToken(photonToken_, photons);
0315 
0316   // for conversion veto selection
0317   edm::Handle<reco::ConversionCollection> hConversions;
0318   iEvent.getByToken(hConversionsToken_, hConversions);
0319 
0320   // Get the collection of electrons from the event
0321   edm::Handle<reco::GsfElectronCollection> hElectrons;
0322   iEvent.getByToken(electronToken_, hElectrons);
0323 
0324   // Get the beamspot
0325   edm::Handle<reco::BeamSpot> beamSpotHandle;
0326   iEvent.getByToken(beamLineToken_, beamSpotHandle);
0327 
0328   EcalClusterLazyTools lazyTools(iEvent,
0329                                  ecalClusterToolsESGetTokens_.get(iSetup),
0330                                  reducedBarrelRecHitCollectionToken_,
0331                                  reducedEndcapRecHitCollectionToken_);
0332 
0333   // prepare the MC matching
0334   std::vector<edm::Handle<edm::Association<reco::GenParticleCollection>>> genMatches(genMatchTokens_.size());
0335   if (addGenMatch_) {
0336     for (size_t j = 0, nd = genMatchTokens_.size(); j < nd; ++j) {
0337       iEvent.getByToken(genMatchTokens_[j], genMatches[j]);
0338     }
0339   }
0340 
0341   if (isolator_.enabled())
0342     isolator_.beginEvent(iEvent, iSetup);
0343 
0344   if (efficiencyLoader_.enabled())
0345     efficiencyLoader_.newEvent(iEvent);
0346   if (resolutionLoader_.enabled())
0347     resolutionLoader_.newEvent(iEvent, iSetup);
0348 
0349   IsoDepositMaps deposits(isoDepositTokens_.size());
0350   for (size_t j = 0, nd = isoDepositTokens_.size(); j < nd; ++j) {
0351     iEvent.getByToken(isoDepositTokens_[j], deposits[j]);
0352   }
0353 
0354   IsolationValueMaps isolationValues(isolationValueTokens_.size());
0355   for (size_t j = 0; j < isolationValueTokens_.size(); ++j) {
0356     iEvent.getByToken(isolationValueTokens_[j], isolationValues[j]);
0357   }
0358 
0359   // prepare ID extraction
0360   std::vector<edm::Handle<edm::ValueMap<Bool_t>>> idhandles;
0361   std::vector<pat::Photon::IdPair> ids;
0362   if (addPhotonID_) {
0363     idhandles.resize(photIDSrcs_.size());
0364     ids.resize(photIDSrcs_.size());
0365     for (size_t i = 0; i < photIDSrcs_.size(); ++i) {
0366       iEvent.getByToken(photIDTokens_[i], idhandles[i]);
0367       ids[i].first = photIDSrcs_[i].first;
0368     }
0369   }
0370 
0371   //value maps for puppi isolation
0372   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_charged_hadrons;
0373   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_neutral_hadrons;
0374   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_photons;
0375   if (addPuppiIsolation_) {
0376     iEvent.getByToken(PUPPIIsolation_charged_hadrons_, PUPPIIsolation_charged_hadrons);
0377     iEvent.getByToken(PUPPIIsolation_neutral_hadrons_, PUPPIIsolation_neutral_hadrons);
0378     iEvent.getByToken(PUPPIIsolation_photons_, PUPPIIsolation_photons);
0379   }
0380 
0381   // loop over photons
0382   std::vector<Photon>* PATPhotons = new std::vector<Photon>();
0383   for (edm::View<reco::Photon>::const_iterator itPhoton = photons->begin(); itPhoton != photons->end(); itPhoton++) {
0384     // construct the Photon from the ref -> save ref to original object
0385     unsigned int idx = itPhoton - photons->begin();
0386     edm::RefToBase<reco::Photon> photonRef = photons->refAt(idx);
0387     edm::Ptr<reco::Photon> photonPtr = photons->ptrAt(idx);
0388     Photon aPhoton(photonRef);
0389     auto phoPtr = photons->ptrAt(idx);
0390     if (embedSuperCluster_)
0391       aPhoton.embedSuperCluster();
0392     if (embedSeedCluster_)
0393       aPhoton.embedSeedCluster();
0394     if (embedBasicClusters_)
0395       aPhoton.embedBasicClusters();
0396     if (embedPreshowerClusters_)
0397       aPhoton.embedPreshowerClusters();
0398 
0399     std::vector<DetId> selectedCells;
0400     bool barrel = itPhoton->isEB();
0401     //loop over sub clusters
0402     if (embedBasicClusters_) {
0403       for (reco::CaloCluster_iterator clusIt = itPhoton->superCluster()->clustersBegin();
0404            clusIt != itPhoton->superCluster()->clustersEnd();
0405            ++clusIt) {
0406         //get seed (max energy xtal)
0407         DetId seed = lazyTools.getMaximum(**clusIt).first;
0408         //get all xtals in 5x5 window around the seed
0409         std::vector<DetId> dets5x5 =
0410             (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalBarrel)->getWindow(seed, 5, 5)
0411                      : ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalEndcap)->getWindow(seed, 5, 5);
0412         selectedCells.insert(selectedCells.end(), dets5x5.begin(), dets5x5.end());
0413 
0414         //get all xtals belonging to cluster
0415         for (const std::pair<DetId, float>& hit : (*clusIt)->hitsAndFractions()) {
0416           selectedCells.push_back(hit.first);
0417         }
0418       }
0419     }
0420 
0421     //remove duplicates
0422     std::sort(selectedCells.begin(), selectedCells.end());
0423     std::unique(selectedCells.begin(), selectedCells.end());
0424 
0425     // Retrieve the corresponding RecHits
0426 
0427     edm::Handle<EcalRecHitCollection> recHitsEBHandle;
0428     iEvent.getByToken(reducedBarrelRecHitCollectionToken_, recHitsEBHandle);
0429     edm::Handle<EcalRecHitCollection> recHitsEEHandle;
0430     iEvent.getByToken(reducedEndcapRecHitCollectionToken_, recHitsEEHandle);
0431 
0432     //orginal code would throw an exception via the handle not being valid but now it'll just have a null pointer error
0433     //should have little effect, if its not barrel or endcap, something very bad has happened elsewhere anyways
0434     const EcalRecHitCollection* recHits = nullptr;
0435     if (photonRef->superCluster()->seed()->hitsAndFractions().at(0).first.subdetId() == EcalBarrel)
0436       recHits = recHitsEBHandle.product();
0437     else if (photonRef->superCluster()->seed()->hitsAndFractions().at(0).first.subdetId() == EcalEndcap)
0438       recHits = recHitsEEHandle.product();
0439 
0440     EcalRecHitCollection selectedRecHits;
0441 
0442     unsigned nSelectedCells = selectedCells.size();
0443     for (unsigned icell = 0; icell < nSelectedCells; ++icell) {
0444       EcalRecHitCollection::const_iterator it = recHits->find(selectedCells[icell]);
0445       if (it != recHits->end()) {
0446         selectedRecHits.push_back(*it);
0447       }
0448     }
0449     selectedRecHits.sort();
0450     if (embedRecHits_)
0451       aPhoton.embedRecHits(&selectedRecHits);
0452 
0453     // store the match to the generated final state muons
0454     if (addGenMatch_) {
0455       for (size_t i = 0, n = genMatches.size(); i < n; ++i) {
0456         reco::GenParticleRef genPhoton = (*genMatches[i])[photonRef];
0457         aPhoton.addGenParticleRef(genPhoton);
0458       }
0459       if (embedGenMatch_)
0460         aPhoton.embedGenParticle();
0461     }
0462 
0463     if (efficiencyLoader_.enabled()) {
0464       efficiencyLoader_.setEfficiencies(aPhoton, photonRef);
0465     }
0466 
0467     if (resolutionLoader_.enabled()) {
0468       resolutionLoader_.setResolutions(aPhoton);
0469     }
0470 
0471     // here comes the extra functionality
0472     if (isolator_.enabled()) {
0473       isolator_.fill(*photons, idx, isolatorTmpStorage_);
0474       typedef pat::helper::MultiIsolator::IsolationValuePairs IsolationValuePairs;
0475       // better to loop backwards, so the vector is resized less times
0476       for (IsolationValuePairs::const_reverse_iterator it = isolatorTmpStorage_.rbegin(),
0477                                                        ed = isolatorTmpStorage_.rend();
0478            it != ed;
0479            ++it) {
0480         aPhoton.setIsolation(it->first, it->second);
0481       }
0482     }
0483 
0484     for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
0485       aPhoton.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[photonRef]);
0486     }
0487 
0488     for (size_t j = 0; j < isolationValues.size(); ++j) {
0489       aPhoton.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[photonRef]);
0490     }
0491 
0492     // add photon ID info
0493     if (addPhotonID_) {
0494       for (size_t i = 0; i < photIDSrcs_.size(); ++i) {
0495         ids[i].second = (*idhandles[i])[photonRef];
0496       }
0497       aPhoton.setPhotonIDs(ids);
0498     }
0499 
0500     if (useUserData_) {
0501       userDataHelper_.add(aPhoton, iEvent, iSetup);
0502     }
0503 
0504     // set conversion veto selection
0505     bool passelectronveto = false;
0506     if (hConversions.isValid()) {
0507       // this is recommended method
0508       passelectronveto = !ConversionTools::hasMatchedPromptElectron(
0509           photonRef->superCluster(), *hElectrons, *hConversions, beamSpotHandle->position());
0510     }
0511     aPhoton.setPassElectronVeto(passelectronveto);
0512 
0513     // set electron veto using pixel seed (not recommended but many analysis groups are still using since it is powerful method to remove electrons)
0514     aPhoton.setHasPixelSeed(photonRef->hasPixelSeed());
0515 
0516     // set seed energy
0517     aPhoton.setSeedEnergy(photonRef->superCluster()->seed()->energy());
0518 
0519     // set input variables for regression energy correction
0520     if (saveRegressionData_) {
0521       EcalRegressionData ecalRegData;
0522       ecalRegData.fill(*(photonRef->superCluster()),
0523                        recHitsEBHandle.product(),
0524                        recHitsEEHandle.product(),
0525                        ecalGeometry_,
0526                        ecalTopology_,
0527                        -1);
0528 
0529       aPhoton.setEMax(ecalRegData.eMax());
0530       aPhoton.setE2nd(ecalRegData.e2nd());
0531       aPhoton.setE3x3(ecalRegData.e3x3());
0532       aPhoton.setETop(ecalRegData.eTop());
0533       aPhoton.setEBottom(ecalRegData.eBottom());
0534       aPhoton.setELeft(ecalRegData.eLeft());
0535       aPhoton.setERight(ecalRegData.eRight());
0536       aPhoton.setSee(ecalRegData.sigmaIEtaIEta());
0537       aPhoton.setSep(
0538           ecalRegData.sigmaIEtaIPhi() * ecalRegData.sigmaIEtaIEta() *
0539           ecalRegData
0540               .sigmaIPhiIPhi());  //there is a conflict on what sigmaIEtaIPhi actually is, regression and ID have it differently, this may change in later releases
0541       aPhoton.setSpp(ecalRegData.sigmaIPhiIPhi());
0542 
0543       aPhoton.setMaxDR(ecalRegData.maxSubClusDR());
0544       aPhoton.setMaxDRDPhi(ecalRegData.maxSubClusDRDPhi());
0545       aPhoton.setMaxDRDEta(ecalRegData.maxSubClusDRDEta());
0546       aPhoton.setMaxDRRawEnergy(ecalRegData.maxSubClusDRRawEnergy());
0547       aPhoton.setSubClusRawE1(ecalRegData.subClusRawEnergy(EcalRegressionData::SubClusNr::C1));
0548       aPhoton.setSubClusRawE2(ecalRegData.subClusRawEnergy(EcalRegressionData::SubClusNr::C2));
0549       aPhoton.setSubClusRawE3(ecalRegData.subClusRawEnergy(EcalRegressionData::SubClusNr::C3));
0550       aPhoton.setSubClusDPhi1(ecalRegData.subClusDPhi(EcalRegressionData::SubClusNr::C1));
0551       aPhoton.setSubClusDPhi2(ecalRegData.subClusDPhi(EcalRegressionData::SubClusNr::C2));
0552       aPhoton.setSubClusDPhi3(ecalRegData.subClusDPhi(EcalRegressionData::SubClusNr::C3));
0553       aPhoton.setSubClusDEta1(ecalRegData.subClusDEta(EcalRegressionData::SubClusNr::C1));
0554       aPhoton.setSubClusDEta2(ecalRegData.subClusDEta(EcalRegressionData::SubClusNr::C2));
0555       aPhoton.setSubClusDEta3(ecalRegData.subClusDEta(EcalRegressionData::SubClusNr::C3));
0556 
0557       aPhoton.setCryPhi(ecalRegData.seedCrysPhiOrY());
0558       aPhoton.setCryEta(ecalRegData.seedCrysEtaOrX());
0559       aPhoton.setIEta(ecalRegData.seedCrysIEtaOrIX());
0560       aPhoton.setIPhi(ecalRegData.seedCrysIPhiOrIY());
0561     } else {
0562       aPhoton.setEMax(0);
0563       aPhoton.setE2nd(0);
0564       aPhoton.setE3x3(0);
0565       aPhoton.setETop(0);
0566       aPhoton.setEBottom(0);
0567       aPhoton.setELeft(0);
0568       aPhoton.setERight(0);
0569       aPhoton.setSee(0);
0570       aPhoton.setSep(0);
0571       aPhoton.setSpp(0);
0572 
0573       aPhoton.setMaxDR(0);
0574       aPhoton.setMaxDRDPhi(0);
0575       aPhoton.setMaxDRDEta(0);
0576       aPhoton.setMaxDRRawEnergy(0);
0577       aPhoton.setSubClusRawE1(0);
0578       aPhoton.setSubClusRawE2(0);
0579       aPhoton.setSubClusRawE3(0);
0580       aPhoton.setSubClusDPhi1(0);
0581       aPhoton.setSubClusDPhi2(0);
0582       aPhoton.setSubClusDPhi3(0);
0583       aPhoton.setSubClusDEta1(0);
0584       aPhoton.setSubClusDEta2(0);
0585       aPhoton.setSubClusDEta3(0);
0586 
0587       aPhoton.setCryPhi(0);
0588       aPhoton.setCryEta(0);
0589       aPhoton.setIEta(0);
0590       aPhoton.setIPhi(0);
0591     }
0592 
0593     if (addPuppiIsolation_)
0594       aPhoton.setIsolationPUPPI((*PUPPIIsolation_charged_hadrons)[phoPtr],
0595                                 (*PUPPIIsolation_neutral_hadrons)[phoPtr],
0596                                 (*PUPPIIsolation_photons)[phoPtr]);
0597     else
0598       aPhoton.setIsolationPUPPI(-999., -999., -999.);
0599 
0600     // Get PFCluster Isolation
0601     if (addPFClusterIso_) {
0602       reco::Photon::PflowIsolationVariables newPFIsol = aPhoton.getPflowIsolationVariables();
0603       edm::Handle<edm::ValueMap<float>> ecalPFClusterIsoMapH;
0604       iEvent.getByToken(ecalPFClusterIsoT_, ecalPFClusterIsoMapH);
0605       newPFIsol.sumEcalClusterEt = (*ecalPFClusterIsoMapH)[photonRef];
0606       edm::Handle<edm::ValueMap<float>> hcalPFClusterIsoMapH;
0607       if (not hcalPFClusterIsoT_.isUninitialized()) {
0608         iEvent.getByToken(hcalPFClusterIsoT_, hcalPFClusterIsoMapH);
0609         newPFIsol.sumHcalClusterEt = (*hcalPFClusterIsoMapH)[photonRef];
0610       } else {
0611         newPFIsol.sumHcalClusterEt = -999.;
0612       }
0613       aPhoton.setPflowIsolationVariables(newPFIsol);
0614     }
0615 
0616     // add the Photon to the vector of Photons
0617     PATPhotons->push_back(aPhoton);
0618   }
0619 
0620   // sort Photons in ET
0621   std::sort(PATPhotons->begin(), PATPhotons->end(), eTComparator_);
0622 
0623   // put genEvt object in Event
0624   std::unique_ptr<std::vector<Photon>> myPhotons(PATPhotons);
0625   iEvent.put(std::move(myPhotons));
0626   if (isolator_.enabled())
0627     isolator_.endEvent();
0628 }
0629 
0630 // ParameterSet description for module
0631 void PATPhotonProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0632   edm::ParameterSetDescription iDesc;
0633   iDesc.setComment("PAT photon producer module");
0634 
0635   // input source
0636   iDesc.add<edm::InputTag>("photonSource", edm::InputTag("no default"))->setComment("input collection");
0637   iDesc.add<edm::InputTag>("electronSource", edm::InputTag("no default"))->setComment("input collection");
0638   iDesc.add<edm::InputTag>("conversionSource", edm::InputTag("allConversions"))->setComment("input collection");
0639 
0640   iDesc.add<edm::InputTag>("reducedBarrelRecHitCollection", edm::InputTag("reducedEcalRecHitsEB"));
0641   iDesc.add<edm::InputTag>("reducedEndcapRecHitCollection", edm::InputTag("reducedEcalRecHitsEE"));
0642 
0643   iDesc.ifValue(
0644       edm::ParameterDescription<bool>("addPFClusterIso", false, true),
0645       true >> (edm::ParameterDescription<edm::InputTag>(
0646                    "ecalPFClusterIsoMap", edm::InputTag("photonEcalPFClusterIsolationProducer"), true) and
0647                edm::ParameterDescription<edm::InputTag>(
0648                    "hcalPFClusterIsoMap", edm::InputTag("photonHcalPFClusterIsolationProducer"), true)) or
0649           false >> (edm::ParameterDescription<edm::InputTag>("ecalPFClusterIsoMap", edm::InputTag(""), true) and
0650                     edm::ParameterDescription<edm::InputTag>("hcalPFClusterIsoMap", edm::InputTag(""), true)));
0651 
0652   iDesc.ifValue(
0653       edm::ParameterDescription<bool>("addPuppiIsolation", false, true),
0654       true >> (edm::ParameterDescription<edm::InputTag>(
0655                    "puppiIsolationChargedHadrons", edm::InputTag("egmPhotonPUPPIIsolation", "h+-DR030-"), true) and
0656                edm::ParameterDescription<edm::InputTag>(
0657                    "puppiIsolationNeutralHadrons", edm::InputTag("egmPhotonPUPPIIsolation", "h0-DR030-"), true) and
0658                edm::ParameterDescription<edm::InputTag>(
0659                    "puppiIsolationPhotons", edm::InputTag("egmPhotonPUPPIIsolation", "gamma-DR030-"), true)) or
0660           false >> edm::EmptyGroupDescription());
0661 
0662   iDesc.add<bool>("embedSuperCluster", true)->setComment("embed external super cluster");
0663   iDesc.add<bool>("embedSeedCluster", true)->setComment("embed external seed cluster");
0664   iDesc.add<bool>("embedBasicClusters", true)->setComment("embed external basic clusters");
0665   iDesc.add<bool>("embedPreshowerClusters", true)->setComment("embed external preshower clusters");
0666   iDesc.add<bool>("embedRecHits", true)->setComment("embed external RecHits");
0667 
0668   // MC matching configurables
0669   iDesc.add<bool>("addGenMatch", true)->setComment("add MC matching");
0670   iDesc.add<bool>("embedGenMatch", false)->setComment("embed MC matched MC information");
0671   std::vector<edm::InputTag> emptySourceVector;
0672   iDesc
0673       .addNode(edm::ParameterDescription<edm::InputTag>("genParticleMatch", edm::InputTag(), true) xor
0674                edm::ParameterDescription<std::vector<edm::InputTag>>("genParticleMatch", emptySourceVector, true))
0675       ->setComment("input with MC match information");
0676 
0677   pat::helper::KinResolutionsLoader::fillDescription(iDesc);
0678 
0679   // photon ID configurables
0680   iDesc.add<bool>("addPhotonID", true)->setComment("add photon ID variables");
0681   edm::ParameterSetDescription photonIDSourcesPSet;
0682   photonIDSourcesPSet.setAllowAnything();
0683   iDesc
0684       .addNode(edm::ParameterDescription<edm::InputTag>("photonIDSource", edm::InputTag(), true) xor
0685                edm::ParameterDescription<edm::ParameterSetDescription>("photonIDSources", photonIDSourcesPSet, true))
0686       ->setComment("input with photon ID variables");
0687 
0688   // IsoDeposit configurables
0689   edm::ParameterSetDescription isoDepositsPSet;
0690   isoDepositsPSet.addOptional<edm::InputTag>("tracker");
0691   isoDepositsPSet.addOptional<edm::InputTag>("ecal");
0692   isoDepositsPSet.addOptional<edm::InputTag>("hcal");
0693   isoDepositsPSet.addOptional<edm::InputTag>("pfAllParticles");
0694   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedHadrons");
0695   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedAll");
0696   isoDepositsPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
0697   isoDepositsPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
0698   isoDepositsPSet.addOptional<edm::InputTag>("pfPhotons");
0699   isoDepositsPSet.addOptional<std::vector<edm::InputTag>>("user");
0700   iDesc.addOptional("isoDeposits", isoDepositsPSet);
0701 
0702   // isolation values configurables
0703   edm::ParameterSetDescription isolationValuesPSet;
0704   isolationValuesPSet.addOptional<edm::InputTag>("tracker");
0705   isolationValuesPSet.addOptional<edm::InputTag>("ecal");
0706   isolationValuesPSet.addOptional<edm::InputTag>("hcal");
0707   isolationValuesPSet.addOptional<edm::InputTag>("pfAllParticles");
0708   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedHadrons");
0709   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedAll");
0710   isolationValuesPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
0711   isolationValuesPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
0712   isolationValuesPSet.addOptional<edm::InputTag>("pfPhotons");
0713   isolationValuesPSet.addOptional<std::vector<edm::InputTag>>("user");
0714   iDesc.addOptional("isolationValues", isolationValuesPSet);
0715 
0716   // Efficiency configurables
0717   edm::ParameterSetDescription efficienciesPSet;
0718   efficienciesPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
0719   iDesc.add("efficiencies", efficienciesPSet);
0720   iDesc.add<bool>("addEfficiencies", false);
0721 
0722   // Check to see if the user wants to add user data
0723   edm::ParameterSetDescription userDataPSet;
0724   PATUserDataHelper<Photon>::fillDescription(userDataPSet);
0725   iDesc.addOptional("userData", userDataPSet);
0726 
0727   edm::ParameterSetDescription isolationPSet;
0728   isolationPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
0729   iDesc.add("userIsolation", isolationPSet);
0730 
0731   iDesc.addNode(edm::ParameterDescription<edm::InputTag>("beamLineSrc", edm::InputTag(), true))
0732       ->setComment("input with high level selection");
0733 
0734   iDesc.add<bool>("saveRegressionData", true)->setComment("save regression input variables");
0735 
0736   descriptions.add("PATPhotonProducer", iDesc);
0737 }
0738 
0739 #include "FWCore/Framework/interface/MakerMacros.h"
0740 DEFINE_FWK_MODULE(PATPhotonProducer);