Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:52

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 
0190 using namespace pat;
0191 
0192 PATPhotonProducer::PATPhotonProducer(const edm::ParameterSet& iConfig)
0193     : ecalClusterToolsESGetTokens_{consumesCollector()},
0194       isolator_(iConfig.getParameter<edm::ParameterSet>("userIsolation"), consumesCollector(), false),
0195       useUserData_(iConfig.exists("userData")),
0196       ecalTopologyToken_{esConsumes()},
0197       ecalGeometryToken_{esConsumes()} {
0198   // initialize the configurables
0199   photonToken_ = consumes<edm::View<reco::Photon>>(iConfig.getParameter<edm::InputTag>("photonSource"));
0200   electronToken_ = consumes<reco::GsfElectronCollection>(iConfig.getParameter<edm::InputTag>("electronSource"));
0201   hConversionsToken_ = consumes<reco::ConversionCollection>(iConfig.getParameter<edm::InputTag>("conversionSource"));
0202   beamLineToken_ = consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("beamLineSrc"));
0203   embedSuperCluster_ = iConfig.getParameter<bool>("embedSuperCluster");
0204   embedSeedCluster_ = iConfig.getParameter<bool>("embedSeedCluster");
0205   embedBasicClusters_ = iConfig.getParameter<bool>("embedBasicClusters");
0206   embedPreshowerClusters_ = iConfig.getParameter<bool>("embedPreshowerClusters");
0207   embedRecHits_ = iConfig.getParameter<bool>("embedRecHits");
0208   reducedBarrelRecHitCollection_ = iConfig.getParameter<edm::InputTag>("reducedBarrelRecHitCollection");
0209   reducedBarrelRecHitCollectionToken_ = mayConsume<EcalRecHitCollection>(reducedBarrelRecHitCollection_);
0210   reducedEndcapRecHitCollection_ = iConfig.getParameter<edm::InputTag>("reducedEndcapRecHitCollection");
0211   reducedEndcapRecHitCollectionToken_ = mayConsume<EcalRecHitCollection>(reducedEndcapRecHitCollection_);
0212   // MC matching configurables
0213   addGenMatch_ = iConfig.getParameter<bool>("addGenMatch");
0214   if (addGenMatch_) {
0215     embedGenMatch_ = iConfig.getParameter<bool>("embedGenMatch");
0216     genMatchTokens_.push_back(consumes<edm::Association<reco::GenParticleCollection>>(
0217         iConfig.getParameter<edm::InputTag>("genParticleMatch")));
0218   }
0219   // Efficiency configurables
0220   addEfficiencies_ = iConfig.getParameter<bool>("addEfficiencies");
0221   if (addEfficiencies_) {
0222     efficiencyLoader_ =
0223         pat::helper::EfficiencyLoader(iConfig.getParameter<edm::ParameterSet>("efficiencies"), consumesCollector());
0224   }
0225   // PFCluster Isolation maps
0226   addPuppiIsolation_ = iConfig.getParameter<bool>("addPuppiIsolation");
0227   if (addPuppiIsolation_) {
0228     PUPPIIsolation_charged_hadrons_ =
0229         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationChargedHadrons"));
0230     PUPPIIsolation_neutral_hadrons_ =
0231         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationNeutralHadrons"));
0232     PUPPIIsolation_photons_ =
0233         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationPhotons"));
0234   }
0235   addPFClusterIso_ = iConfig.getParameter<bool>("addPFClusterIso");
0236   if (addPFClusterIso_) {
0237     ecalPFClusterIsoT_ = consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("ecalPFClusterIsoMap"));
0238     auto hcPFC = iConfig.getParameter<edm::InputTag>("hcalPFClusterIsoMap");
0239     if (not hcPFC.label().empty())
0240       hcalPFClusterIsoT_ = consumes<edm::ValueMap<float>>(hcPFC);
0241   }
0242 
0243   // photon ID configurables
0244   addPhotonID_ = iConfig.getParameter<bool>("addPhotonID");
0245   if (addPhotonID_) {
0246     // it might be a single photon ID
0247     if (iConfig.existsAs<edm::InputTag>("photonIDSource")) {
0248       photIDSrcs_.push_back(NameTag("", iConfig.getParameter<edm::InputTag>("photonIDSource")));
0249     }
0250     // or there might be many of them
0251     if (iConfig.existsAs<edm::ParameterSet>("photonIDSources")) {
0252       // please don't configure me twice
0253       if (!photIDSrcs_.empty()) {
0254         throw cms::Exception("Configuration")
0255             << "PATPhotonProducer: you can't specify both 'photonIDSource' and 'photonIDSources'\n";
0256       }
0257       // read the different photon ID names
0258       edm::ParameterSet idps = iConfig.getParameter<edm::ParameterSet>("photonIDSources");
0259       std::vector<std::string> names = idps.getParameterNamesForType<edm::InputTag>();
0260       for (std::vector<std::string>::const_iterator it = names.begin(), ed = names.end(); it != ed; ++it) {
0261         photIDSrcs_.push_back(NameTag(*it, idps.getParameter<edm::InputTag>(*it)));
0262       }
0263     }
0264     // but in any case at least once
0265     if (photIDSrcs_.empty())
0266       throw cms::Exception("Configuration") << "PATPhotonProducer: id addPhotonID is true, you must specify either:\n"
0267                                             << "\tInputTag photonIDSource = <someTag>\n"
0268                                             << "or\n"
0269                                             << "\tPSet photonIDSources = { \n"
0270                                             << "\t\tInputTag <someName> = <someTag>   // as many as you want \n "
0271                                             << "\t}\n";
0272   }
0273   photIDTokens_ = edm::vector_transform(
0274       photIDSrcs_, [this](NameTag const& tag) { return mayConsume<edm::ValueMap<Bool_t>>(tag.second); });
0275   // Resolution configurables
0276   addResolutions_ = iConfig.getParameter<bool>("addResolutions");
0277   if (addResolutions_) {
0278     resolutionLoader_ =
0279         pat::helper::KinResolutionsLoader(iConfig.getParameter<edm::ParameterSet>("resolutions"), consumesCollector());
0280   }
0281   // Check to see if the user wants to add user data
0282   if (useUserData_) {
0283     userDataHelper_ =
0284         PATUserDataHelper<Photon>(iConfig.getParameter<edm::ParameterSet>("userData"), consumesCollector());
0285   }
0286   // produces vector of photons
0287   produces<std::vector<Photon>>();
0288 
0289   // read isoDeposit labels, for direct embedding
0290   readIsolationLabels(iConfig, "isoDeposits", isoDepositLabels_, isoDepositTokens_);
0291   // read isolation value labels, for direct embedding
0292   readIsolationLabels(iConfig, "isolationValues", isolationValueLabels_, isolationValueTokens_);
0293 
0294   saveRegressionData_ = iConfig.getParameter<bool>("saveRegressionData");
0295 }
0296 
0297 PATPhotonProducer::~PATPhotonProducer() {}
0298 
0299 void PATPhotonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0300   // switch off embedding (in unschedules mode)
0301   if (iEvent.isRealData()) {
0302     addGenMatch_ = false;
0303     embedGenMatch_ = false;
0304   }
0305 
0306   ecalTopology_ = &iSetup.getData(ecalTopologyToken_);
0307   ecalGeometry_ = &iSetup.getData(ecalGeometryToken_);
0308 
0309   // Get the vector of Photon's from the event
0310   edm::Handle<edm::View<reco::Photon>> photons;
0311   iEvent.getByToken(photonToken_, photons);
0312 
0313   // for conversion veto selection
0314   edm::Handle<reco::ConversionCollection> hConversions;
0315   iEvent.getByToken(hConversionsToken_, hConversions);
0316 
0317   // Get the collection of electrons from the event
0318   edm::Handle<reco::GsfElectronCollection> hElectrons;
0319   iEvent.getByToken(electronToken_, hElectrons);
0320 
0321   // Get the beamspot
0322   edm::Handle<reco::BeamSpot> beamSpotHandle;
0323   iEvent.getByToken(beamLineToken_, beamSpotHandle);
0324 
0325   EcalClusterLazyTools lazyTools(iEvent,
0326                                  ecalClusterToolsESGetTokens_.get(iSetup),
0327                                  reducedBarrelRecHitCollectionToken_,
0328                                  reducedEndcapRecHitCollectionToken_);
0329 
0330   // prepare the MC matching
0331   std::vector<edm::Handle<edm::Association<reco::GenParticleCollection>>> genMatches(genMatchTokens_.size());
0332   if (addGenMatch_) {
0333     for (size_t j = 0, nd = genMatchTokens_.size(); j < nd; ++j) {
0334       iEvent.getByToken(genMatchTokens_[j], genMatches[j]);
0335     }
0336   }
0337 
0338   if (isolator_.enabled())
0339     isolator_.beginEvent(iEvent, iSetup);
0340 
0341   if (efficiencyLoader_.enabled())
0342     efficiencyLoader_.newEvent(iEvent);
0343   if (resolutionLoader_.enabled())
0344     resolutionLoader_.newEvent(iEvent, iSetup);
0345 
0346   IsoDepositMaps deposits(isoDepositTokens_.size());
0347   for (size_t j = 0, nd = isoDepositTokens_.size(); j < nd; ++j) {
0348     iEvent.getByToken(isoDepositTokens_[j], deposits[j]);
0349   }
0350 
0351   IsolationValueMaps isolationValues(isolationValueTokens_.size());
0352   for (size_t j = 0; j < isolationValueTokens_.size(); ++j) {
0353     iEvent.getByToken(isolationValueTokens_[j], isolationValues[j]);
0354   }
0355 
0356   // prepare ID extraction
0357   std::vector<edm::Handle<edm::ValueMap<Bool_t>>> idhandles;
0358   std::vector<pat::Photon::IdPair> ids;
0359   if (addPhotonID_) {
0360     idhandles.resize(photIDSrcs_.size());
0361     ids.resize(photIDSrcs_.size());
0362     for (size_t i = 0; i < photIDSrcs_.size(); ++i) {
0363       iEvent.getByToken(photIDTokens_[i], idhandles[i]);
0364       ids[i].first = photIDSrcs_[i].first;
0365     }
0366   }
0367 
0368   //value maps for puppi isolation
0369   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_charged_hadrons;
0370   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_neutral_hadrons;
0371   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_photons;
0372   if (addPuppiIsolation_) {
0373     iEvent.getByToken(PUPPIIsolation_charged_hadrons_, PUPPIIsolation_charged_hadrons);
0374     iEvent.getByToken(PUPPIIsolation_neutral_hadrons_, PUPPIIsolation_neutral_hadrons);
0375     iEvent.getByToken(PUPPIIsolation_photons_, PUPPIIsolation_photons);
0376   }
0377 
0378   // loop over photons
0379   std::vector<Photon>* PATPhotons = new std::vector<Photon>();
0380   for (edm::View<reco::Photon>::const_iterator itPhoton = photons->begin(); itPhoton != photons->end(); itPhoton++) {
0381     // construct the Photon from the ref -> save ref to original object
0382     unsigned int idx = itPhoton - photons->begin();
0383     edm::RefToBase<reco::Photon> photonRef = photons->refAt(idx);
0384     edm::Ptr<reco::Photon> photonPtr = photons->ptrAt(idx);
0385     Photon aPhoton(photonRef);
0386     auto phoPtr = photons->ptrAt(idx);
0387     if (embedSuperCluster_)
0388       aPhoton.embedSuperCluster();
0389     if (embedSeedCluster_)
0390       aPhoton.embedSeedCluster();
0391     if (embedBasicClusters_)
0392       aPhoton.embedBasicClusters();
0393     if (embedPreshowerClusters_)
0394       aPhoton.embedPreshowerClusters();
0395 
0396     std::vector<DetId> selectedCells;
0397     bool barrel = itPhoton->isEB();
0398     //loop over sub clusters
0399     if (embedBasicClusters_) {
0400       for (reco::CaloCluster_iterator clusIt = itPhoton->superCluster()->clustersBegin();
0401            clusIt != itPhoton->superCluster()->clustersEnd();
0402            ++clusIt) {
0403         //get seed (max energy xtal)
0404         DetId seed = lazyTools.getMaximum(**clusIt).first;
0405         //get all xtals in 5x5 window around the seed
0406         std::vector<DetId> dets5x5 =
0407             (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalBarrel)->getWindow(seed, 5, 5)
0408                      : ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalEndcap)->getWindow(seed, 5, 5);
0409         selectedCells.insert(selectedCells.end(), dets5x5.begin(), dets5x5.end());
0410 
0411         //get all xtals belonging to cluster
0412         for (const std::pair<DetId, float>& hit : (*clusIt)->hitsAndFractions()) {
0413           selectedCells.push_back(hit.first);
0414         }
0415       }
0416     }
0417 
0418     //remove duplicates
0419     std::sort(selectedCells.begin(), selectedCells.end());
0420     std::unique(selectedCells.begin(), selectedCells.end());
0421 
0422     // Retrieve the corresponding RecHits
0423 
0424     edm::Handle<EcalRecHitCollection> recHitsEBHandle;
0425     iEvent.getByToken(reducedBarrelRecHitCollectionToken_, recHitsEBHandle);
0426     edm::Handle<EcalRecHitCollection> recHitsEEHandle;
0427     iEvent.getByToken(reducedEndcapRecHitCollectionToken_, recHitsEEHandle);
0428 
0429     //orginal code would throw an exception via the handle not being valid but now it'll just have a null pointer error
0430     //should have little effect, if its not barrel or endcap, something very bad has happened elsewhere anyways
0431     const EcalRecHitCollection* recHits = nullptr;
0432     if (photonRef->superCluster()->seed()->hitsAndFractions().at(0).first.subdetId() == EcalBarrel)
0433       recHits = recHitsEBHandle.product();
0434     else if (photonRef->superCluster()->seed()->hitsAndFractions().at(0).first.subdetId() == EcalEndcap)
0435       recHits = recHitsEEHandle.product();
0436 
0437     EcalRecHitCollection selectedRecHits;
0438 
0439     unsigned nSelectedCells = selectedCells.size();
0440     for (unsigned icell = 0; icell < nSelectedCells; ++icell) {
0441       EcalRecHitCollection::const_iterator it = recHits->find(selectedCells[icell]);
0442       if (it != recHits->end()) {
0443         selectedRecHits.push_back(*it);
0444       }
0445     }
0446     selectedRecHits.sort();
0447     if (embedRecHits_)
0448       aPhoton.embedRecHits(&selectedRecHits);
0449 
0450     // store the match to the generated final state muons
0451     if (addGenMatch_) {
0452       for (size_t i = 0, n = genMatches.size(); i < n; ++i) {
0453         reco::GenParticleRef genPhoton = (*genMatches[i])[photonRef];
0454         aPhoton.addGenParticleRef(genPhoton);
0455       }
0456       if (embedGenMatch_)
0457         aPhoton.embedGenParticle();
0458     }
0459 
0460     if (efficiencyLoader_.enabled()) {
0461       efficiencyLoader_.setEfficiencies(aPhoton, photonRef);
0462     }
0463 
0464     if (resolutionLoader_.enabled()) {
0465       resolutionLoader_.setResolutions(aPhoton);
0466     }
0467 
0468     // here comes the extra functionality
0469     if (isolator_.enabled()) {
0470       isolator_.fill(*photons, idx, isolatorTmpStorage_);
0471       typedef pat::helper::MultiIsolator::IsolationValuePairs IsolationValuePairs;
0472       // better to loop backwards, so the vector is resized less times
0473       for (IsolationValuePairs::const_reverse_iterator it = isolatorTmpStorage_.rbegin(),
0474                                                        ed = isolatorTmpStorage_.rend();
0475            it != ed;
0476            ++it) {
0477         aPhoton.setIsolation(it->first, it->second);
0478       }
0479     }
0480 
0481     for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
0482       aPhoton.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[photonRef]);
0483     }
0484 
0485     for (size_t j = 0; j < isolationValues.size(); ++j) {
0486       aPhoton.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[photonRef]);
0487     }
0488 
0489     // add photon ID info
0490     if (addPhotonID_) {
0491       for (size_t i = 0; i < photIDSrcs_.size(); ++i) {
0492         ids[i].second = (*idhandles[i])[photonRef];
0493       }
0494       aPhoton.setPhotonIDs(ids);
0495     }
0496 
0497     if (useUserData_) {
0498       userDataHelper_.add(aPhoton, iEvent, iSetup);
0499     }
0500 
0501     // set conversion veto selection
0502     bool passelectronveto = false;
0503     if (hConversions.isValid()) {
0504       // this is recommended method
0505       passelectronveto = !ConversionTools::hasMatchedPromptElectron(
0506           photonRef->superCluster(), *hElectrons, *hConversions, beamSpotHandle->position());
0507     }
0508     aPhoton.setPassElectronVeto(passelectronveto);
0509 
0510     // set electron veto using pixel seed (not recommended but many analysis groups are still using since it is powerful method to remove electrons)
0511     aPhoton.setHasPixelSeed(photonRef->hasPixelSeed());
0512 
0513     // set seed energy
0514     aPhoton.setSeedEnergy(photonRef->superCluster()->seed()->energy());
0515 
0516     // set input variables for regression energy correction
0517     if (saveRegressionData_) {
0518       EcalRegressionData ecalRegData;
0519       ecalRegData.fill(*(photonRef->superCluster()),
0520                        recHitsEBHandle.product(),
0521                        recHitsEEHandle.product(),
0522                        ecalGeometry_,
0523                        ecalTopology_,
0524                        -1);
0525 
0526       aPhoton.setEMax(ecalRegData.eMax());
0527       aPhoton.setE2nd(ecalRegData.e2nd());
0528       aPhoton.setE3x3(ecalRegData.e3x3());
0529       aPhoton.setETop(ecalRegData.eTop());
0530       aPhoton.setEBottom(ecalRegData.eBottom());
0531       aPhoton.setELeft(ecalRegData.eLeft());
0532       aPhoton.setERight(ecalRegData.eRight());
0533       aPhoton.setSee(ecalRegData.sigmaIEtaIEta());
0534       aPhoton.setSep(
0535           ecalRegData.sigmaIEtaIPhi() * ecalRegData.sigmaIEtaIEta() *
0536           ecalRegData
0537               .sigmaIPhiIPhi());  //there is a conflict on what sigmaIEtaIPhi actually is, regression and ID have it differently, this may change in later releases
0538       aPhoton.setSpp(ecalRegData.sigmaIPhiIPhi());
0539 
0540       aPhoton.setMaxDR(ecalRegData.maxSubClusDR());
0541       aPhoton.setMaxDRDPhi(ecalRegData.maxSubClusDRDPhi());
0542       aPhoton.setMaxDRDEta(ecalRegData.maxSubClusDRDEta());
0543       aPhoton.setMaxDRRawEnergy(ecalRegData.maxSubClusDRRawEnergy());
0544       aPhoton.setSubClusRawE1(ecalRegData.subClusRawEnergy(EcalRegressionData::SubClusNr::C1));
0545       aPhoton.setSubClusRawE2(ecalRegData.subClusRawEnergy(EcalRegressionData::SubClusNr::C2));
0546       aPhoton.setSubClusRawE3(ecalRegData.subClusRawEnergy(EcalRegressionData::SubClusNr::C3));
0547       aPhoton.setSubClusDPhi1(ecalRegData.subClusDPhi(EcalRegressionData::SubClusNr::C1));
0548       aPhoton.setSubClusDPhi2(ecalRegData.subClusDPhi(EcalRegressionData::SubClusNr::C2));
0549       aPhoton.setSubClusDPhi3(ecalRegData.subClusDPhi(EcalRegressionData::SubClusNr::C3));
0550       aPhoton.setSubClusDEta1(ecalRegData.subClusDEta(EcalRegressionData::SubClusNr::C1));
0551       aPhoton.setSubClusDEta2(ecalRegData.subClusDEta(EcalRegressionData::SubClusNr::C2));
0552       aPhoton.setSubClusDEta3(ecalRegData.subClusDEta(EcalRegressionData::SubClusNr::C3));
0553 
0554       aPhoton.setCryPhi(ecalRegData.seedCrysPhiOrY());
0555       aPhoton.setCryEta(ecalRegData.seedCrysEtaOrX());
0556       aPhoton.setIEta(ecalRegData.seedCrysIEtaOrIX());
0557       aPhoton.setIPhi(ecalRegData.seedCrysIPhiOrIY());
0558     } else {
0559       aPhoton.setEMax(0);
0560       aPhoton.setE2nd(0);
0561       aPhoton.setE3x3(0);
0562       aPhoton.setETop(0);
0563       aPhoton.setEBottom(0);
0564       aPhoton.setELeft(0);
0565       aPhoton.setERight(0);
0566       aPhoton.setSee(0);
0567       aPhoton.setSep(0);
0568       aPhoton.setSpp(0);
0569 
0570       aPhoton.setMaxDR(0);
0571       aPhoton.setMaxDRDPhi(0);
0572       aPhoton.setMaxDRDEta(0);
0573       aPhoton.setMaxDRRawEnergy(0);
0574       aPhoton.setSubClusRawE1(0);
0575       aPhoton.setSubClusRawE2(0);
0576       aPhoton.setSubClusRawE3(0);
0577       aPhoton.setSubClusDPhi1(0);
0578       aPhoton.setSubClusDPhi2(0);
0579       aPhoton.setSubClusDPhi3(0);
0580       aPhoton.setSubClusDEta1(0);
0581       aPhoton.setSubClusDEta2(0);
0582       aPhoton.setSubClusDEta3(0);
0583 
0584       aPhoton.setCryPhi(0);
0585       aPhoton.setCryEta(0);
0586       aPhoton.setIEta(0);
0587       aPhoton.setIPhi(0);
0588     }
0589 
0590     if (addPuppiIsolation_)
0591       aPhoton.setIsolationPUPPI((*PUPPIIsolation_charged_hadrons)[phoPtr],
0592                                 (*PUPPIIsolation_neutral_hadrons)[phoPtr],
0593                                 (*PUPPIIsolation_photons)[phoPtr]);
0594     else
0595       aPhoton.setIsolationPUPPI(-999., -999., -999.);
0596 
0597     // Get PFCluster Isolation
0598     if (addPFClusterIso_) {
0599       reco::Photon::PflowIsolationVariables newPFIsol = aPhoton.getPflowIsolationVariables();
0600       edm::Handle<edm::ValueMap<float>> ecalPFClusterIsoMapH;
0601       iEvent.getByToken(ecalPFClusterIsoT_, ecalPFClusterIsoMapH);
0602       newPFIsol.sumEcalClusterEt = (*ecalPFClusterIsoMapH)[photonRef];
0603       edm::Handle<edm::ValueMap<float>> hcalPFClusterIsoMapH;
0604       if (not hcalPFClusterIsoT_.isUninitialized()) {
0605         iEvent.getByToken(hcalPFClusterIsoT_, hcalPFClusterIsoMapH);
0606         newPFIsol.sumHcalClusterEt = (*hcalPFClusterIsoMapH)[photonRef];
0607       } else {
0608         newPFIsol.sumHcalClusterEt = -999.;
0609       }
0610       aPhoton.setPflowIsolationVariables(newPFIsol);
0611     }
0612 
0613     // add the Photon to the vector of Photons
0614     PATPhotons->push_back(aPhoton);
0615   }
0616 
0617   // sort Photons in ET
0618   std::sort(PATPhotons->begin(), PATPhotons->end(), eTComparator_);
0619 
0620   // put genEvt object in Event
0621   std::unique_ptr<std::vector<Photon>> myPhotons(PATPhotons);
0622   iEvent.put(std::move(myPhotons));
0623   if (isolator_.enabled())
0624     isolator_.endEvent();
0625 }
0626 
0627 // ParameterSet description for module
0628 void PATPhotonProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0629   edm::ParameterSetDescription iDesc;
0630   iDesc.setComment("PAT photon producer module");
0631 
0632   // input source
0633   iDesc.add<edm::InputTag>("photonSource", edm::InputTag("no default"))->setComment("input collection");
0634   iDesc.add<edm::InputTag>("electronSource", edm::InputTag("no default"))->setComment("input collection");
0635   iDesc.add<edm::InputTag>("conversionSource", edm::InputTag("allConversions"))->setComment("input collection");
0636 
0637   iDesc.add<edm::InputTag>("reducedBarrelRecHitCollection", edm::InputTag("reducedEcalRecHitsEB"));
0638   iDesc.add<edm::InputTag>("reducedEndcapRecHitCollection", edm::InputTag("reducedEcalRecHitsEE"));
0639 
0640   iDesc.ifValue(
0641       edm::ParameterDescription<bool>("addPFClusterIso", false, true),
0642       true >> (edm::ParameterDescription<edm::InputTag>(
0643                    "ecalPFClusterIsoMap", edm::InputTag("photonEcalPFClusterIsolationProducer"), true) and
0644                edm::ParameterDescription<edm::InputTag>(
0645                    "hcalPFClusterIsoMap", edm::InputTag("photonHcalPFClusterIsolationProducer"), true)) or
0646           false >> (edm::ParameterDescription<edm::InputTag>("ecalPFClusterIsoMap", edm::InputTag(""), true) and
0647                     edm::ParameterDescription<edm::InputTag>("hcalPFClusterIsoMap", edm::InputTag(""), true)));
0648 
0649   iDesc.ifValue(
0650       edm::ParameterDescription<bool>("addPuppiIsolation", false, true),
0651       true >> (edm::ParameterDescription<edm::InputTag>(
0652                    "puppiIsolationChargedHadrons", edm::InputTag("egmPhotonPUPPIIsolation", "h+-DR030-"), true) and
0653                edm::ParameterDescription<edm::InputTag>(
0654                    "puppiIsolationNeutralHadrons", edm::InputTag("egmPhotonPUPPIIsolation", "h0-DR030-"), true) and
0655                edm::ParameterDescription<edm::InputTag>(
0656                    "puppiIsolationPhotons", edm::InputTag("egmPhotonPUPPIIsolation", "gamma-DR030-"), true)) or
0657           false >> edm::EmptyGroupDescription());
0658 
0659   iDesc.add<bool>("embedSuperCluster", true)->setComment("embed external super cluster");
0660   iDesc.add<bool>("embedSeedCluster", true)->setComment("embed external seed cluster");
0661   iDesc.add<bool>("embedBasicClusters", true)->setComment("embed external basic clusters");
0662   iDesc.add<bool>("embedPreshowerClusters", true)->setComment("embed external preshower clusters");
0663   iDesc.add<bool>("embedRecHits", true)->setComment("embed external RecHits");
0664 
0665   // MC matching configurables
0666   iDesc.add<bool>("addGenMatch", true)->setComment("add MC matching");
0667   iDesc.add<bool>("embedGenMatch", false)->setComment("embed MC matched MC information");
0668   std::vector<edm::InputTag> emptySourceVector;
0669   iDesc
0670       .addNode(edm::ParameterDescription<edm::InputTag>("genParticleMatch", edm::InputTag(), true) xor
0671                edm::ParameterDescription<std::vector<edm::InputTag>>("genParticleMatch", emptySourceVector, true))
0672       ->setComment("input with MC match information");
0673 
0674   pat::helper::KinResolutionsLoader::fillDescription(iDesc);
0675 
0676   // photon ID configurables
0677   iDesc.add<bool>("addPhotonID", true)->setComment("add photon ID variables");
0678   edm::ParameterSetDescription photonIDSourcesPSet;
0679   photonIDSourcesPSet.setAllowAnything();
0680   iDesc
0681       .addNode(edm::ParameterDescription<edm::InputTag>("photonIDSource", edm::InputTag(), true) xor
0682                edm::ParameterDescription<edm::ParameterSetDescription>("photonIDSources", photonIDSourcesPSet, true))
0683       ->setComment("input with photon ID variables");
0684 
0685   // IsoDeposit configurables
0686   edm::ParameterSetDescription isoDepositsPSet;
0687   isoDepositsPSet.addOptional<edm::InputTag>("tracker");
0688   isoDepositsPSet.addOptional<edm::InputTag>("ecal");
0689   isoDepositsPSet.addOptional<edm::InputTag>("hcal");
0690   isoDepositsPSet.addOptional<edm::InputTag>("pfAllParticles");
0691   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedHadrons");
0692   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedAll");
0693   isoDepositsPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
0694   isoDepositsPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
0695   isoDepositsPSet.addOptional<edm::InputTag>("pfPhotons");
0696   isoDepositsPSet.addOptional<std::vector<edm::InputTag>>("user");
0697   iDesc.addOptional("isoDeposits", isoDepositsPSet);
0698 
0699   // isolation values configurables
0700   edm::ParameterSetDescription isolationValuesPSet;
0701   isolationValuesPSet.addOptional<edm::InputTag>("tracker");
0702   isolationValuesPSet.addOptional<edm::InputTag>("ecal");
0703   isolationValuesPSet.addOptional<edm::InputTag>("hcal");
0704   isolationValuesPSet.addOptional<edm::InputTag>("pfAllParticles");
0705   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedHadrons");
0706   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedAll");
0707   isolationValuesPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
0708   isolationValuesPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
0709   isolationValuesPSet.addOptional<edm::InputTag>("pfPhotons");
0710   isolationValuesPSet.addOptional<std::vector<edm::InputTag>>("user");
0711   iDesc.addOptional("isolationValues", isolationValuesPSet);
0712 
0713   // Efficiency configurables
0714   edm::ParameterSetDescription efficienciesPSet;
0715   efficienciesPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
0716   iDesc.add("efficiencies", efficienciesPSet);
0717   iDesc.add<bool>("addEfficiencies", false);
0718 
0719   // Check to see if the user wants to add user data
0720   edm::ParameterSetDescription userDataPSet;
0721   PATUserDataHelper<Photon>::fillDescription(userDataPSet);
0722   iDesc.addOptional("userData", userDataPSet);
0723 
0724   edm::ParameterSetDescription isolationPSet;
0725   isolationPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
0726   iDesc.add("userIsolation", isolationPSet);
0727 
0728   iDesc.addNode(edm::ParameterDescription<edm::InputTag>("beamLineSrc", edm::InputTag(), true))
0729       ->setComment("input with high level selection");
0730 
0731   iDesc.add<bool>("saveRegressionData", true)->setComment("save regression input variables");
0732 
0733   descriptions.add("PATPhotonProducer", iDesc);
0734 }
0735 
0736 #include "FWCore/Framework/interface/MakerMacros.h"
0737 DEFINE_FWK_MODULE(PATPhotonProducer);