Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:25:01

0001 /** \class ReducedEGProducer
0002  **  
0003  **  Select subset of electrons and photons from input collections and
0004  **  produced consistently relinked output collections including
0005  **  associated SuperClusters, CaloClusters and ecal RecHits
0006  **
0007  **  \author J.Bendavid (CERN)
0008  **  \edited: K. McDermott(Cornell) : refactored code + out of time photons
0009  ***/
0010 
0011 #include "CommonTools/Egamma/interface/ConversionTools.h"
0012 #include "CommonTools/UtilAlgos/interface/StringCutObjectSelector.h"
0013 #include "CommonTools/Utils/interface/StringToEnumValue.h"
0014 #include "CondFormats/EcalObjects/interface/EcalFunctionParameters.h"
0015 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
0016 #include "DataFormats/Common/interface/Handle.h"
0017 #include "DataFormats/Common/interface/ValueMap.h"
0018 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
0019 #include "DataFormats/EgammaCandidates/interface/HIPhotonIsolation.h"
0020 #include "DataFormats/EgammaCandidates/interface/Photon.h"
0021 #include "DataFormats/EgammaCandidates/interface/PhotonFwd.h"
0022 #include "DataFormats/EgammaCandidates/interface/PhotonCore.h"
0023 #include "DataFormats/EgammaReco/interface/BasicCluster.h"
0024 #include "DataFormats/EgammaReco/interface/BasicClusterShapeAssociation.h"
0025 #include "DataFormats/EgammaReco/interface/ClusterShape.h"
0026 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
0027 #include "DataFormats/HcalRecHit/interface/HcalRecHitCollections.h"
0028 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
0029 #include "FWCore/Framework/interface/ESHandle.h"
0030 #include "FWCore/Framework/interface/Event.h"
0031 #include "FWCore/Framework/interface/EventSetup.h"
0032 #include "FWCore/Framework/interface/stream/EDProducer.h"
0033 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0034 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0035 #include "FWCore/Utilities/interface/Exception.h"
0036 #include "Geometry/Records/interface/CaloTopologyRecord.h"
0037 #include "Geometry/CaloTopology/interface/CaloTopology.h"
0038 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterTools.h"
0039 #include "RecoEgamma/EgammaIsolationAlgos/interface/EGHcalRecHitSelector.h"
0040 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalSeverityLevelAlgo.h"
0041 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalSeverityLevelAlgoRcd.h"
0042 
0043 #include <memory>
0044 #include <unordered_set>
0045 #include <vector>
0046 
0047 class ReducedEGProducer : public edm::stream::EDProducer<> {
0048 public:
0049   ReducedEGProducer(const edm::ParameterSet& ps);
0050 
0051   void beginRun(edm::Run const&, const edm::EventSetup&) final;
0052   void produce(edm::Event& evt, const edm::EventSetup& es) final;
0053 
0054 private:
0055   template <class T>
0056   std::vector<edm::EDPutTokenT<T>> vproduces(std::vector<std::string> const& labels) {
0057     std::vector<edm::EDPutTokenT<T>> putTokens{};
0058     putTokens.reserve(labels.size());
0059     for (const auto& label : labels) {
0060       putTokens.push_back(produces<T>(label));
0061     }
0062     return putTokens;
0063   }
0064 
0065   template <typename T, typename U>
0066   void linkCore(const T& core, U& cores, std::map<T, unsigned int>& coreMap);
0067 
0068   void linkSuperCluster(const reco::SuperClusterRef& superCluster,
0069                         std::map<reco::SuperClusterRef, unsigned int>& superClusterMap,
0070                         reco::SuperClusterCollection& superClusters,
0071                         const bool relink,
0072                         std::unordered_set<unsigned int>& superClusterFullRelinkMap);
0073 
0074   void linkConversions(const reco::ConversionRefVector& convrefs,
0075                        reco::ConversionCollection& conversions,
0076                        std::map<reco::ConversionRef, unsigned int>& conversionMap);
0077 
0078   void linkConversionsByTrackRef(const edm::Handle<reco::ConversionCollection>& conversionHandle,
0079                                  const reco::GsfElectron& gsfElectron,
0080                                  reco::ConversionCollection& conversions,
0081                                  std::map<reco::ConversionRef, unsigned int>& conversionMap);
0082 
0083   void linkConversionsByTrackRef(const edm::Handle<reco::ConversionCollection>& conversionHandle,
0084                                  const reco::SuperCluster& superCluster,
0085                                  reco::ConversionCollection& conversions,
0086                                  std::map<reco::ConversionRef, unsigned int>& conversionMap);
0087 
0088   void linkConversion(const reco::ConversionRef& convref,
0089                       reco::ConversionCollection& conversions,
0090                       std::map<reco::ConversionRef, unsigned int>& conversionMap);
0091 
0092   void linkCaloCluster(const reco::CaloClusterPtr& caloCluster,
0093                        reco::CaloClusterCollection& caloClusters,
0094                        std::map<reco::CaloClusterPtr, unsigned int>& caloClusterMap);
0095 
0096   void linkCaloClusters(const reco::SuperCluster& superCluster,
0097                         reco::CaloClusterCollection& ebeeClusters,
0098                         std::map<reco::CaloClusterPtr, unsigned int>& ebeeClusterMap,
0099                         std::unordered_set<DetId>& rechitMap,
0100                         const edm::Handle<EcalRecHitCollection>& barrelHitHandle,
0101                         const edm::Handle<EcalRecHitCollection>& endcapHitHandle,
0102                         CaloTopology const& caloTopology,
0103                         reco::CaloClusterCollection& esClusters,
0104                         std::map<reco::CaloClusterPtr, unsigned int>& esClusterMap);
0105 
0106   void linkHcalHits(const reco::SuperCluster& superClus,
0107                     const HBHERecHitCollection& recHits,
0108                     std::unordered_set<DetId>& hcalDetIds);
0109 
0110   void relinkCaloClusters(reco::SuperCluster& superCluster,
0111                           const std::map<reco::CaloClusterPtr, unsigned int>& ebeeClusterMap,
0112                           const std::map<reco::CaloClusterPtr, unsigned int>& esClusterMap,
0113                           const edm::OrphanHandle<reco::CaloClusterCollection>& outEBEEClusterHandle,
0114                           const edm::OrphanHandle<reco::CaloClusterCollection>& outESClusterHandle);
0115 
0116   template <typename T>
0117   void relinkSuperCluster(T& core,
0118                           const std::map<reco::SuperClusterRef, unsigned int>& superClusterMap,
0119                           const edm::OrphanHandle<reco::SuperClusterCollection>& outSuperClusterHandle);
0120 
0121   void relinkGsfTrack(reco::GsfElectronCore& electroncore,
0122                       const std::map<reco::GsfTrackRef, unsigned int>& gsfTrackMap,
0123                       const edm::OrphanHandle<reco::GsfTrackCollection>& outGsfTrackHandle);
0124 
0125   void relinkConversions(reco::PhotonCore& photonCore,
0126                          const reco::ConversionRefVector& convrefs,
0127                          const std::map<reco::ConversionRef, unsigned int>& conversionMap,
0128                          const edm::OrphanHandle<reco::ConversionCollection>& outConversionHandle);
0129 
0130   void relinkPhotonCore(reco::Photon& photon,
0131                         const std::map<reco::PhotonCoreRef, unsigned int>& photonCoreMap,
0132                         const edm::OrphanHandle<reco::PhotonCoreCollection>& outPhotonCoreHandle);
0133 
0134   void relinkGsfElectronCore(reco::GsfElectron& gsfElectron,
0135                              const std::map<reco::GsfElectronCoreRef, unsigned int>& gsfElectronCoreMap,
0136                              const edm::OrphanHandle<reco::GsfElectronCoreCollection>& outGsfElectronCoreHandle);
0137 
0138   static void calibratePhoton(reco::Photon& photon,
0139                               const reco::PhotonRef& oldPhoRef,
0140                               const edm::ValueMap<float>& energyMap,
0141                               const edm::ValueMap<float>& energyErrMap);
0142 
0143   static void calibrateElectron(reco::GsfElectron& gsfElectron,
0144                                 const reco::GsfElectronRef& oldEleRef,
0145                                 const edm::ValueMap<float>& energyMap,
0146                                 const edm::ValueMap<float>& energyErrMap,
0147                                 const edm::ValueMap<float>& ecalEnergyMap,
0148                                 const edm::ValueMap<float>& ecalEnergyErrMap);
0149 
0150   template <typename T>
0151   void setToken(edm::EDGetTokenT<T>& token, const edm::ParameterSet& config, const std::string& name) {
0152     token = consumes<T>(config.getParameter<edm::InputTag>(name));
0153   }
0154 
0155   //tokens for input collections
0156   const edm::EDGetTokenT<reco::PhotonCollection> photonT_;
0157   edm::EDGetTokenT<reco::PhotonCollection> ootPhotonT_;
0158   const edm::EDGetTokenT<reco::GsfElectronCollection> gsfElectronT_;
0159   const edm::EDGetTokenT<reco::ConversionCollection> conversionT_;
0160   const edm::EDGetTokenT<reco::ConversionCollection> singleConversionT_;
0161 
0162   const edm::EDGetTokenT<EcalRecHitCollection> barrelEcalHits_;
0163   const edm::EDGetTokenT<EcalRecHitCollection> endcapEcalHits_;
0164   const bool doPreshowerEcalHits_;
0165   const edm::EDGetTokenT<EcalRecHitCollection> preshowerEcalHits_;
0166   const edm::EDGetTokenT<HBHERecHitCollection> hbheHits_;
0167 
0168   const edm::EDGetTokenT<edm::ValueMap<std::vector<reco::PFCandidateRef>>> photonPfCandMapT_;
0169   const edm::EDGetTokenT<edm::ValueMap<std::vector<reco::PFCandidateRef>>> gsfElectronPfCandMapT_;
0170 
0171   std::vector<edm::EDGetTokenT<edm::ValueMap<bool>>> photonIdTs_;
0172   std::vector<edm::EDGetTokenT<edm::ValueMap<float>>> gsfElectronIdTs_;
0173 
0174   std::vector<edm::EDGetTokenT<edm::ValueMap<float>>> photonFloatValueMapTs_;
0175   std::vector<edm::EDGetTokenT<edm::ValueMap<float>>> ootPhotonFloatValueMapTs_;
0176   std::vector<edm::EDGetTokenT<edm::ValueMap<float>>> gsfElectronFloatValueMapTs_;
0177 
0178   const edm::EDGetTokenT<reco::HIPhotonIsolationMap> recoHIPhotonIsolationMapInputToken_;
0179   edm::EDPutTokenT<reco::HIPhotonIsolationMap> recoHIPhotonIsolationMapOutputName_;
0180 
0181   const bool applyPhotonCalibOnData_;
0182   const bool applyPhotonCalibOnMC_;
0183   const bool applyGsfElectronCalibOnData_;
0184   const bool applyGsfElectronCalibOnMC_;
0185   edm::EDGetTokenT<edm::ValueMap<float>> photonCalibEnergyT_;
0186   edm::EDGetTokenT<edm::ValueMap<float>> photonCalibEnergyErrT_;
0187   edm::EDGetTokenT<edm::ValueMap<float>> gsfElectronCalibEnergyT_;
0188   edm::EDGetTokenT<edm::ValueMap<float>> gsfElectronCalibEnergyErrT_;
0189   edm::EDGetTokenT<edm::ValueMap<float>> gsfElectronCalibEcalEnergyT_;
0190   edm::EDGetTokenT<edm::ValueMap<float>> gsfElectronCalibEcalEnergyErrT_;
0191 
0192   edm::ESGetToken<CaloTopology, CaloTopologyRecord> caloTopology_;
0193   //names for output collections
0194   const edm::EDPutTokenT<reco::PhotonCollection> outPhotons_;
0195   const edm::EDPutTokenT<reco::PhotonCoreCollection> outPhotonCores_;
0196   edm::EDPutTokenT<reco::PhotonCollection> outOOTPhotons_;
0197   edm::EDPutTokenT<reco::PhotonCoreCollection> outOOTPhotonCores_;
0198   const edm::EDPutTokenT<reco::GsfElectronCollection> outGsfElectrons_;
0199   const edm::EDPutTokenT<reco::GsfElectronCoreCollection> outGsfElectronCores_;
0200   const edm::EDPutTokenT<reco::GsfTrackCollection> outGsfTracks_;
0201   const edm::EDPutTokenT<reco::ConversionCollection> outConversions_;
0202   const edm::EDPutTokenT<reco::ConversionCollection> outSingleConversions_;
0203   const edm::EDPutTokenT<reco::SuperClusterCollection> outSuperClusters_;
0204   const edm::EDPutTokenT<reco::CaloClusterCollection> outEBEEClusters_;
0205   const edm::EDPutTokenT<reco::CaloClusterCollection> outESClusters_;
0206   edm::EDPutTokenT<reco::SuperClusterCollection> outOOTSuperClusters_;
0207   edm::EDPutTokenT<reco::CaloClusterCollection> outOOTEBEEClusters_;
0208   edm::EDPutTokenT<reco::CaloClusterCollection> outOOTESClusters_;
0209   const edm::EDPutTokenT<EcalRecHitCollection> outEBRecHits_;
0210   const edm::EDPutTokenT<EcalRecHitCollection> outEERecHits_;
0211   edm::EDPutTokenT<EcalRecHitCollection> outESRecHits_;
0212   const edm::EDPutTokenT<HBHERecHitCollection> outHBHERecHits_;
0213   const edm::EDPutTokenT<edm::ValueMap<std::vector<reco::PFCandidateRef>>> outPhotonPfCandMap_;
0214   const edm::EDPutTokenT<edm::ValueMap<std::vector<reco::PFCandidateRef>>> outGsfElectronPfCandMap_;
0215   const std::vector<edm::EDPutTokenT<edm::ValueMap<bool>>> outPhotonIds_;
0216   const std::vector<edm::EDPutTokenT<edm::ValueMap<float>>> outGsfElectronIds_;
0217   const std::vector<edm::EDPutTokenT<edm::ValueMap<float>>> outPhotonFloatValueMaps_;
0218   std::vector<edm::EDPutTokenT<edm::ValueMap<float>>> outOOTPhotonFloatValueMaps_;
0219   const std::vector<edm::EDPutTokenT<edm::ValueMap<float>>> outGsfElectronFloatValueMaps_;
0220 
0221   const StringCutObjectSelector<reco::Photon> keepPhotonSel_;
0222   const StringCutObjectSelector<reco::Photon> slimRelinkPhotonSel_;
0223   const StringCutObjectSelector<reco::Photon> relinkPhotonSel_;
0224   const StringCutObjectSelector<reco::Photon> keepOOTPhotonSel_;
0225   const StringCutObjectSelector<reco::Photon> slimRelinkOOTPhotonSel_;
0226   const StringCutObjectSelector<reco::Photon> relinkOOTPhotonSel_;
0227   const StringCutObjectSelector<reco::GsfElectron> keepGsfElectronSel_;
0228   const StringCutObjectSelector<reco::GsfElectron> slimRelinkGsfElectronSel_;
0229   const StringCutObjectSelector<reco::GsfElectron> relinkGsfElectronSel_;
0230 
0231   EGHcalRecHitSelector hcalHitSel_;
0232 };
0233 
0234 #include "FWCore/Framework/interface/MakerMacros.h"
0235 DEFINE_FWK_MODULE(ReducedEGProducer);
0236 
0237 namespace {
0238 
0239   template <class T>
0240   auto getHandles(edm::Event const& event, std::vector<edm::EDGetTokenT<T>> const& tokens) {
0241     std::vector<edm::Handle<T>> handles(tokens.size());
0242     int index = 0;
0243     for (const auto& token : tokens) {
0244       event.getByToken(token, handles[index++]);
0245     }
0246     return handles;
0247   }
0248 
0249   template <class Handle, class T>
0250   auto emplaceValueMap(Handle const& handle,
0251                        std::vector<T> const& values,
0252                        edm::Event& ev,
0253                        edm::EDPutTokenT<edm::ValueMap<T>> const& putToken) {
0254     using MapType = edm::ValueMap<T>;
0255     MapType oMap{};
0256     {
0257       typename MapType::Filler filler(oMap);
0258       filler.insert(handle, values.begin(), values.end());
0259       filler.fill();
0260     }
0261     ev.emplace(putToken, std::move(oMap));
0262   };
0263 }  // namespace
0264 
0265 ReducedEGProducer::ReducedEGProducer(const edm::ParameterSet& config)
0266     : photonT_(consumes(config.getParameter<edm::InputTag>("photons"))),
0267       gsfElectronT_(consumes(config.getParameter<edm::InputTag>("gsfElectrons"))),
0268       conversionT_(consumes(config.getParameter<edm::InputTag>("conversions"))),
0269       singleConversionT_(consumes(config.getParameter<edm::InputTag>("singleConversions"))),
0270       barrelEcalHits_(consumes(config.getParameter<edm::InputTag>("barrelEcalHits"))),
0271       endcapEcalHits_(consumes(config.getParameter<edm::InputTag>("endcapEcalHits"))),
0272       doPreshowerEcalHits_(!config.getParameter<edm::InputTag>("preshowerEcalHits").label().empty()),
0273       preshowerEcalHits_(doPreshowerEcalHits_
0274                              ? consumes<EcalRecHitCollection>(config.getParameter<edm::InputTag>("preshowerEcalHits"))
0275                              : edm::EDGetTokenT<EcalRecHitCollection>()),
0276       hbheHits_(consumes<HBHERecHitCollection>(config.getParameter<edm::InputTag>("hbheHits"))),
0277       photonPfCandMapT_(consumes(config.getParameter<edm::InputTag>("photonsPFValMap"))),
0278       gsfElectronPfCandMapT_(consumes(config.getParameter<edm::InputTag>("gsfElectronsPFValMap"))),
0279       recoHIPhotonIsolationMapInputToken_{
0280           !config.getParameter<edm::InputTag>("hiPhotonIsolationMapInput").label().empty()
0281               ? consumes<reco::HIPhotonIsolationMap>(config.getParameter<edm::InputTag>("hiPhotonIsolationMapInput"))
0282               : edm::EDGetTokenT<reco::HIPhotonIsolationMap>{}},
0283       //calibration flags
0284       applyPhotonCalibOnData_(config.getParameter<bool>("applyPhotonCalibOnData")),
0285       applyPhotonCalibOnMC_(config.getParameter<bool>("applyPhotonCalibOnMC")),
0286       applyGsfElectronCalibOnData_(config.getParameter<bool>("applyGsfElectronCalibOnData")),
0287       applyGsfElectronCalibOnMC_(config.getParameter<bool>("applyGsfElectronCalibOnMC")),
0288       //output collections
0289       outPhotons_{produces<reco::PhotonCollection>("reducedGedPhotons")},
0290       outPhotonCores_{produces<reco::PhotonCoreCollection>("reducedGedPhotonCores")},
0291       outGsfElectrons_{produces<reco::GsfElectronCollection>("reducedGedGsfElectrons")},
0292       outGsfElectronCores_{produces<reco::GsfElectronCoreCollection>("reducedGedGsfElectronCores")},
0293       outGsfTracks_{produces<reco::GsfTrackCollection>("reducedGsfTracks")},
0294       outConversions_{produces<reco::ConversionCollection>("reducedConversions")},
0295       outSingleConversions_{produces<reco::ConversionCollection>("reducedSingleLegConversions")},
0296       outSuperClusters_{produces<reco::SuperClusterCollection>("reducedSuperClusters")},
0297       outEBEEClusters_{produces<reco::CaloClusterCollection>("reducedEBEEClusters")},
0298       outESClusters_{produces<reco::CaloClusterCollection>("reducedESClusters")},
0299       outEBRecHits_{produces<EcalRecHitCollection>("reducedEBRecHits")},
0300       outEERecHits_{produces<EcalRecHitCollection>("reducedEERecHits")},
0301       outHBHERecHits_{produces<HBHERecHitCollection>("reducedHBHEHits")},
0302       outPhotonPfCandMap_{produces<edm::ValueMap<std::vector<reco::PFCandidateRef>>>("reducedPhotonPfCandMap")},
0303       outGsfElectronPfCandMap_{
0304           produces<edm::ValueMap<std::vector<reco::PFCandidateRef>>>("reducedGsfElectronPfCandMap")},
0305       outPhotonIds_{vproduces<edm::ValueMap<bool>>(config.getParameter<std::vector<std::string>>("photonIDOutput"))},
0306       outGsfElectronIds_{
0307           vproduces<edm::ValueMap<float>>(config.getParameter<std::vector<std::string>>("gsfElectronIDOutput"))},
0308       outPhotonFloatValueMaps_{
0309           vproduces<edm::ValueMap<float>>(config.getParameter<std::vector<std::string>>("photonFloatValueMapOutput"))},
0310       outGsfElectronFloatValueMaps_{vproduces<edm::ValueMap<float>>(
0311           config.getParameter<std::vector<std::string>>("gsfElectronFloatValueMapOutput"))},
0312       keepPhotonSel_(config.getParameter<std::string>("keepPhotons")),
0313       slimRelinkPhotonSel_(config.getParameter<std::string>("slimRelinkPhotons")),
0314       relinkPhotonSel_(config.getParameter<std::string>("relinkPhotons")),
0315       keepOOTPhotonSel_(config.getParameter<std::string>("keepOOTPhotons")),
0316       slimRelinkOOTPhotonSel_(config.getParameter<std::string>("slimRelinkOOTPhotons")),
0317       relinkOOTPhotonSel_(config.getParameter<std::string>("relinkOOTPhotons")),
0318       keepGsfElectronSel_(config.getParameter<std::string>("keepGsfElectrons")),
0319       slimRelinkGsfElectronSel_(config.getParameter<std::string>("slimRelinkGsfElectrons")),
0320       relinkGsfElectronSel_(config.getParameter<std::string>("relinkGsfElectrons")),
0321       hcalHitSel_(config.getParameter<edm::ParameterSet>("hcalHitSel"), consumesCollector()) {
0322   const auto& aTag = config.getParameter<edm::InputTag>("ootPhotons");
0323   caloTopology_ = esConsumes();
0324   if (not aTag.label().empty())
0325     ootPhotonT_ = consumes<reco::PhotonCollection>(aTag);
0326 
0327   for (const edm::InputTag& tag : config.getParameter<std::vector<edm::InputTag>>("photonIDSources")) {
0328     photonIdTs_.emplace_back(consumes<edm::ValueMap<bool>>(tag));
0329   }
0330 
0331   for (const edm::InputTag& tag : config.getParameter<std::vector<edm::InputTag>>("gsfElectronIDSources")) {
0332     gsfElectronIdTs_.emplace_back(consumes<edm::ValueMap<float>>(tag));
0333   }
0334 
0335   for (const edm::InputTag& tag : config.getParameter<std::vector<edm::InputTag>>("photonFloatValueMapSources")) {
0336     photonFloatValueMapTs_.emplace_back(consumes<edm::ValueMap<float>>(tag));
0337   }
0338 
0339   for (const edm::InputTag& tag : config.getParameter<std::vector<edm::InputTag>>("ootPhotonFloatValueMapSources")) {
0340     ootPhotonFloatValueMapTs_.emplace_back(consumes<edm::ValueMap<float>>(tag));
0341   }
0342 
0343   for (const edm::InputTag& tag : config.getParameter<std::vector<edm::InputTag>>("gsfElectronFloatValueMapSources")) {
0344     gsfElectronFloatValueMapTs_.emplace_back(consumes<edm::ValueMap<float>>(tag));
0345   }
0346 
0347   if (applyPhotonCalibOnData_ || applyPhotonCalibOnMC_) {
0348     setToken(photonCalibEnergyT_, config, "photonCalibEnergySource");
0349     setToken(photonCalibEnergyErrT_, config, "photonCalibEnergyErrSource");
0350   }
0351   if (applyGsfElectronCalibOnData_ || applyGsfElectronCalibOnMC_) {
0352     setToken(gsfElectronCalibEnergyT_, config, "gsfElectronCalibEnergySource");
0353     setToken(gsfElectronCalibEnergyErrT_, config, "gsfElectronCalibEnergyErrSource");
0354     setToken(gsfElectronCalibEcalEnergyT_, config, "gsfElectronCalibEcalEnergySource");
0355     setToken(gsfElectronCalibEcalEnergyErrT_, config, "gsfElectronCalibEcalEnergyErrSource");
0356   }
0357 
0358   if (!ootPhotonT_.isUninitialized()) {
0359     outOOTPhotons_ = produces<reco::PhotonCollection>("reducedOOTPhotons");
0360     outOOTPhotonCores_ = produces<reco::PhotonCoreCollection>("reducedOOTPhotonCores");
0361     outOOTSuperClusters_ = produces<reco::SuperClusterCollection>("reducedOOTSuperClusters");
0362     outOOTEBEEClusters_ = produces<reco::CaloClusterCollection>("reducedOOTEBEEClusters");
0363     outOOTESClusters_ = produces<reco::CaloClusterCollection>("reducedOOTESClusters");
0364   }
0365   if (doPreshowerEcalHits_) {
0366     outESRecHits_ = produces<EcalRecHitCollection>("reducedESRecHits");
0367   }
0368   if (!ootPhotonT_.isUninitialized()) {
0369     outOOTPhotonFloatValueMaps_ =
0370         vproduces<edm::ValueMap<float>>(config.getParameter<std::vector<std::string>>("ootPhotonFloatValueMapOutput"));
0371   }
0372   if (!recoHIPhotonIsolationMapInputToken_.isUninitialized()) {
0373     recoHIPhotonIsolationMapOutputName_ =
0374         produces<reco::HIPhotonIsolationMap>(config.getParameter<std::string>("hiPhotonIsolationMapOutput"));
0375   }
0376 }
0377 
0378 void ReducedEGProducer::beginRun(edm::Run const& run, const edm::EventSetup& iSetup) { hcalHitSel_.setup(iSetup); }
0379 
0380 void ReducedEGProducer::produce(edm::Event& event, const edm::EventSetup& eventSetup) {
0381   //get input collections
0382 
0383   auto photonHandle = event.getHandle(photonT_);
0384 
0385   auto ootPhotonHandle =
0386       !ootPhotonT_.isUninitialized() ? event.getHandle(ootPhotonT_) : edm::Handle<reco::PhotonCollection>{};
0387 
0388   auto gsfElectronHandle = event.getHandle(gsfElectronT_);
0389   auto conversionHandle = event.getHandle(conversionT_);
0390   auto singleConversionHandle = event.getHandle(singleConversionT_);
0391   auto barrelHitHandle = event.getHandle(barrelEcalHits_);
0392   auto endcapHitHandle = event.getHandle(endcapEcalHits_);
0393 
0394   auto preshowerHitHandle =
0395       doPreshowerEcalHits_ ? event.getHandle(preshowerEcalHits_) : edm::Handle<EcalRecHitCollection>{};
0396 
0397   auto hbheHitHandle = event.getHandle(hbheHits_);
0398   auto photonPfCandMapHandle = event.getHandle(photonPfCandMapT_);
0399   auto gsfElectronPfCandMapHandle = event.getHandle(gsfElectronPfCandMapT_);
0400 
0401   auto photonIdHandles = getHandles(event, photonIdTs_);
0402   auto gsfElectronIdHandles = getHandles(event, gsfElectronIdTs_);
0403   auto photonFloatValueMapHandles = getHandles(event, photonFloatValueMapTs_);
0404 
0405   auto ootPhotonFloatValueMapHandles = !ootPhotonT_.isUninitialized()
0406                                            ? getHandles(event, ootPhotonFloatValueMapTs_)
0407                                            : std::vector<edm::Handle<edm::ValueMap<float>>>{};
0408 
0409   auto gsfElectronFloatValueMapHandles = getHandles(event, gsfElectronFloatValueMapTs_);
0410 
0411   edm::Handle<edm::ValueMap<float>> gsfElectronCalibEnergyHandle;
0412   edm::Handle<edm::ValueMap<float>> gsfElectronCalibEnergyErrHandle;
0413   edm::Handle<edm::ValueMap<float>> gsfElectronCalibEcalEnergyHandle;
0414   edm::Handle<edm::ValueMap<float>> gsfElectronCalibEcalEnergyErrHandle;
0415   if (applyGsfElectronCalibOnData_ || applyGsfElectronCalibOnMC_) {
0416     event.getByToken(gsfElectronCalibEnergyT_, gsfElectronCalibEnergyHandle);
0417     event.getByToken(gsfElectronCalibEnergyErrT_, gsfElectronCalibEnergyErrHandle);
0418     event.getByToken(gsfElectronCalibEcalEnergyT_, gsfElectronCalibEcalEnergyHandle);
0419     event.getByToken(gsfElectronCalibEcalEnergyErrT_, gsfElectronCalibEcalEnergyErrHandle);
0420   }
0421   edm::Handle<edm::ValueMap<float>> photonCalibEnergyHandle;
0422   edm::Handle<edm::ValueMap<float>> photonCalibEnergyErrHandle;
0423   if (applyPhotonCalibOnData_ || applyPhotonCalibOnMC_) {
0424     event.getByToken(photonCalibEnergyT_, photonCalibEnergyHandle);
0425     event.getByToken(photonCalibEnergyErrT_, photonCalibEnergyErrHandle);
0426   }
0427 
0428   auto const& caloTopology = eventSetup.getData(caloTopology_);
0429 
0430   //initialize output collections
0431   reco::PhotonCollection photons;
0432   reco::PhotonCoreCollection photonCores;
0433   reco::PhotonCollection ootPhotons;
0434   reco::PhotonCoreCollection ootPhotonCores;
0435   reco::GsfElectronCollection gsfElectrons;
0436   reco::GsfElectronCoreCollection gsfElectronCores;
0437   reco::GsfTrackCollection gsfTracks;
0438   reco::ConversionCollection conversions;
0439   reco::ConversionCollection singleConversions;
0440   reco::SuperClusterCollection superClusters;
0441   reco::CaloClusterCollection ebeeClusters;
0442   reco::CaloClusterCollection esClusters;
0443   reco::SuperClusterCollection ootSuperClusters;
0444   reco::CaloClusterCollection ootEbeeClusters;
0445   reco::CaloClusterCollection ootEsClusters;
0446   EcalRecHitCollection ebRecHits;
0447   EcalRecHitCollection eeRecHits;
0448   EcalRecHitCollection esRecHits;
0449   HBHERecHitCollection hbheRecHits;
0450   edm::ValueMap<std::vector<reco::PFCandidateRef>> photonPfCandMap;
0451   edm::ValueMap<std::vector<reco::PFCandidateRef>> gsfElectronPfCandMap;
0452 
0453   //maps to collection indices of output objects
0454   std::map<reco::PhotonCoreRef, unsigned int> photonCoreMap;
0455   std::map<reco::PhotonCoreRef, unsigned int> ootPhotonCoreMap;
0456   std::map<reco::GsfElectronCoreRef, unsigned int> gsfElectronCoreMap;
0457   std::map<reco::GsfTrackRef, unsigned int> gsfTrackMap;
0458   std::map<reco::ConversionRef, unsigned int> conversionMap;
0459   std::map<reco::ConversionRef, unsigned int> singleConversionMap;
0460   std::map<reco::SuperClusterRef, unsigned int> superClusterMap;
0461   std::map<reco::CaloClusterPtr, unsigned int> ebeeClusterMap;
0462   std::map<reco::CaloClusterPtr, unsigned int> esClusterMap;
0463   std::map<reco::SuperClusterRef, unsigned int> ootSuperClusterMap;
0464   std::map<reco::CaloClusterPtr, unsigned int> ootEbeeClusterMap;
0465   std::map<reco::CaloClusterPtr, unsigned int> ootEsClusterMap;
0466   std::unordered_set<DetId> rechitMap;
0467   std::unordered_set<DetId> hcalRechitMap;
0468 
0469   std::unordered_set<unsigned int> superClusterFullRelinkMap;
0470   std::unordered_set<unsigned int> ootSuperClusterFullRelinkMap;
0471 
0472   //vectors for pfcandidate valuemaps
0473   std::vector<std::vector<reco::PFCandidateRef>> pfCandIsoPairVecPho;
0474   std::vector<std::vector<reco::PFCandidateRef>> pfCandIsoPairVecEle;
0475 
0476   //vectors for id valuemaps
0477   std::vector<std::vector<bool>> photonIdVals(photonIdHandles.size());
0478   std::vector<std::vector<float>> gsfElectronIdVals(gsfElectronIdHandles.size());
0479   std::vector<std::vector<float>> photonFloatValueMapVals(photonFloatValueMapHandles.size());
0480   std::vector<std::vector<float>> ootPhotonFloatValueMapVals(ootPhotonFloatValueMapHandles.size());
0481   std::vector<std::vector<float>> gsfElectronFloatValueMapVals(gsfElectronFloatValueMapHandles.size());
0482 
0483   // HI photon iso value maps
0484   reco::HIPhotonIsolationMap const* recoHIPhotonIsolationMapInputValueMap =
0485       !recoHIPhotonIsolationMapInputToken_.isUninitialized() ? &event.get(recoHIPhotonIsolationMapInputToken_)
0486                                                              : nullptr;
0487   std::vector<reco::HIPhotonIsolation> recoHIPhotonIsolationMapInputVals;
0488 
0489   //loop over photons and fill maps
0490   int index = -1;
0491   for (const auto& photon : *photonHandle) {
0492     index++;
0493 
0494     reco::PhotonRef photonref(photonHandle, index);
0495     photons.push_back(photon);
0496     auto& newPhoton = photons.back();
0497 
0498     if ((applyPhotonCalibOnData_ && event.isRealData()) || (applyPhotonCalibOnMC_ && !event.isRealData())) {
0499       calibratePhoton(newPhoton, photonref, *photonCalibEnergyHandle, *photonCalibEnergyErrHandle);
0500     }
0501 
0502     //we do this after calibration
0503     bool keep = keepPhotonSel_(newPhoton);
0504     if (!keep) {
0505       photons.pop_back();
0506       continue;
0507     }
0508 
0509     //fill pf candidate value map vector
0510     pfCandIsoPairVecPho.push_back((*photonPfCandMapHandle)[photonref]);
0511 
0512     //fill photon id valuemap vectors
0513     int subindex = 0;
0514     for (const auto& photonIdHandle : photonIdHandles) {
0515       photonIdVals[subindex++].push_back((*photonIdHandle)[photonref]);
0516     }
0517 
0518     subindex = 0;
0519     for (const auto& photonFloatValueMapHandle : photonFloatValueMapHandles) {
0520       photonFloatValueMapVals[subindex++].push_back((*photonFloatValueMapHandle)[photonref]);
0521     }
0522 
0523     // HI photon isolation
0524     if (!recoHIPhotonIsolationMapInputToken_.isUninitialized()) {
0525       recoHIPhotonIsolationMapInputVals.push_back((*recoHIPhotonIsolationMapInputValueMap)[photonref]);
0526     }
0527 
0528     //link photon core
0529     const reco::PhotonCoreRef& photonCore = photon.photonCore();
0530     linkCore(photonCore, photonCores, photonCoreMap);
0531 
0532     bool slimRelink = slimRelinkPhotonSel_(newPhoton);
0533     //no supercluster relinking unless slimRelink selection is satisfied
0534     if (!slimRelink)
0535       continue;
0536 
0537     bool relink = relinkPhotonSel_(newPhoton);
0538 
0539     //link supercluster
0540     const reco::SuperClusterRef& superCluster = photon.superCluster();
0541     linkSuperCluster(superCluster, superClusterMap, superClusters, relink, superClusterFullRelinkMap);
0542 
0543     //conversions only for full relinking
0544     if (!relink)
0545       continue;
0546 
0547     const reco::ConversionRefVector& convrefs = photon.conversions();
0548     linkConversions(convrefs, conversions, conversionMap);
0549 
0550     //explicitly references conversions
0551     const reco::ConversionRefVector& singleconvrefs = photon.conversionsOneLeg();
0552     linkConversions(singleconvrefs, singleConversions, singleConversionMap);
0553 
0554     //hcal hits
0555     linkHcalHits(*photon.superCluster(), *hbheHitHandle, hcalRechitMap);
0556   }
0557 
0558   //loop over oot photons and fill maps
0559   //special note1: since not PFCand --> no PF isolation, IDs (but we do have FloatValueMap!)
0560   //special note2: conversion sequence not run over bcs from oot phos, so skip relinking of oot phos
0561   //special note3: clusters and superclusters in own collections!
0562   if (!ootPhotonT_.isUninitialized()) {
0563     index = -1;
0564     for (const auto& ootPhoton : *ootPhotonHandle) {
0565       index++;
0566 
0567       bool keep = keepOOTPhotonSel_(ootPhoton);
0568       if (!keep)
0569         continue;
0570 
0571       reco::PhotonRef ootPhotonref(ootPhotonHandle, index);
0572 
0573       ootPhotons.push_back(ootPhoton);
0574 
0575       //fill photon pfclusteriso valuemap vectors
0576       int subindex = 0;
0577       for (const auto& ootPhotonFloatValueMapHandle : ootPhotonFloatValueMapHandles) {
0578         ootPhotonFloatValueMapVals[subindex++].push_back((*ootPhotonFloatValueMapHandle)[ootPhotonref]);
0579       }
0580 
0581       //link photon core
0582       const reco::PhotonCoreRef& ootPhotonCore = ootPhoton.photonCore();
0583       linkCore(ootPhotonCore, ootPhotonCores, ootPhotonCoreMap);
0584 
0585       bool slimRelink = slimRelinkOOTPhotonSel_(ootPhoton);
0586       //no supercluster relinking unless slimRelink selection is satisfied
0587       if (!slimRelink)
0588         continue;
0589 
0590       bool relink = relinkOOTPhotonSel_(ootPhoton);
0591 
0592       const reco::SuperClusterRef& ootSuperCluster = ootPhoton.superCluster();
0593       linkSuperCluster(ootSuperCluster, ootSuperClusterMap, ootSuperClusters, relink, ootSuperClusterFullRelinkMap);
0594       //hcal hits
0595       linkHcalHits(*ootPhoton.superCluster(), *hbheHitHandle, hcalRechitMap);
0596     }
0597   }
0598 
0599   //loop over electrons and fill maps
0600   index = -1;
0601   for (const auto& gsfElectron : *gsfElectronHandle) {
0602     index++;
0603 
0604     reco::GsfElectronRef gsfElectronref(gsfElectronHandle, index);
0605     gsfElectrons.push_back(gsfElectron);
0606     auto& newGsfElectron = gsfElectrons.back();
0607     if ((applyGsfElectronCalibOnData_ && event.isRealData()) || (applyGsfElectronCalibOnMC_ && !event.isRealData())) {
0608       calibrateElectron(newGsfElectron,
0609                         gsfElectronref,
0610                         *gsfElectronCalibEnergyHandle,
0611                         *gsfElectronCalibEnergyErrHandle,
0612                         *gsfElectronCalibEcalEnergyHandle,
0613                         *gsfElectronCalibEcalEnergyErrHandle);
0614     }
0615 
0616     bool keep = keepGsfElectronSel_(newGsfElectron);
0617     if (!keep) {
0618       gsfElectrons.pop_back();
0619       continue;
0620     }
0621 
0622     pfCandIsoPairVecEle.push_back((*gsfElectronPfCandMapHandle)[gsfElectronref]);
0623 
0624     //fill electron id valuemap vectors
0625     int subindex = 0;
0626     for (const auto& gsfElectronIdHandle : gsfElectronIdHandles) {
0627       gsfElectronIdVals[subindex++].push_back((*gsfElectronIdHandle)[gsfElectronref]);
0628     }
0629 
0630     subindex = 0;
0631     for (const auto& gsfElectronFloatValueMapHandle : gsfElectronFloatValueMapHandles) {
0632       gsfElectronFloatValueMapVals[subindex++].push_back((*gsfElectronFloatValueMapHandle)[gsfElectronref]);
0633     }
0634 
0635     const reco::GsfElectronCoreRef& gsfElectronCore = gsfElectron.core();
0636     linkCore(gsfElectronCore, gsfElectronCores, gsfElectronCoreMap);
0637 
0638     const reco::GsfTrackRef& gsfTrack = gsfElectron.gsfTrack();
0639 
0640     // Save the main gsfTrack
0641     if (!gsfTrackMap.count(gsfTrack)) {
0642       gsfTracks.push_back(*gsfTrack);
0643       gsfTrackMap[gsfTrack] = gsfTracks.size() - 1;
0644     }
0645 
0646     // Save additional ambiguous gsf tracks in a map:
0647     for (auto const& ambigGsfTrack : gsfElectron.ambiguousGsfTracks()) {
0648       if (!gsfTrackMap.count(ambigGsfTrack)) {
0649         gsfTracks.push_back(*ambigGsfTrack);
0650         gsfTrackMap[ambigGsfTrack] = gsfTracks.size() - 1;
0651       }
0652     }
0653 
0654     bool slimRelink = slimRelinkGsfElectronSel_(newGsfElectron);
0655     //no supercluster relinking unless slimRelink selection is satisfied
0656     if (!slimRelink)
0657       continue;
0658 
0659     bool relink = relinkGsfElectronSel_(newGsfElectron);
0660 
0661     const reco::SuperClusterRef& superCluster = gsfElectron.superCluster();
0662     linkSuperCluster(superCluster, superClusterMap, superClusters, relink, superClusterFullRelinkMap);
0663 
0664     //conversions only for full relinking
0665     if (!relink)
0666       continue;
0667 
0668     const reco::ConversionRefVector& convrefs = gsfElectron.core()->conversions();
0669     linkConversions(convrefs, conversions, conversionMap);
0670 
0671     //explicitly references conversions
0672     const reco::ConversionRefVector& singleconvrefs = gsfElectron.core()->conversionsOneLeg();
0673     linkConversions(singleconvrefs, singleConversions, singleConversionMap);
0674 
0675     //conversions matched by trackrefs
0676     linkConversionsByTrackRef(conversionHandle, gsfElectron, conversions, conversionMap);
0677 
0678     //single leg conversions matched by trackrefs
0679     linkConversionsByTrackRef(singleConversionHandle, gsfElectron, singleConversions, singleConversionMap);
0680 
0681     //hcal hits
0682     linkHcalHits(*gsfElectron.superCluster(), *hbheHitHandle, hcalRechitMap);
0683   }
0684 
0685   //loop over output SuperClusters and fill maps
0686   index = 0;
0687   for (auto& superCluster : superClusters) {
0688     //link seed cluster no matter what
0689     const reco::CaloClusterPtr& seedCluster = superCluster.seed();
0690     linkCaloCluster(seedCluster, ebeeClusters, ebeeClusterMap);
0691 
0692     //only proceed if superCluster is marked for full relinking
0693     bool fullrelink = superClusterFullRelinkMap.count(index++);
0694     if (!fullrelink) {
0695       //zero detid vector which is anyways not useful without stored rechits
0696       superCluster.clearHitsAndFractions();
0697       continue;
0698     }
0699 
0700     // link calo clusters
0701     linkCaloClusters(superCluster,
0702                      ebeeClusters,
0703                      ebeeClusterMap,
0704                      rechitMap,
0705                      barrelHitHandle,
0706                      endcapHitHandle,
0707                      caloTopology,
0708                      esClusters,
0709                      esClusterMap);
0710 
0711     //conversions matched geometrically
0712     linkConversionsByTrackRef(conversionHandle, superCluster, conversions, conversionMap);
0713 
0714     //single leg conversions matched by trackrefs
0715     linkConversionsByTrackRef(singleConversionHandle, superCluster, singleConversions, singleConversionMap);
0716   }
0717 
0718   //loop over output OOTSuperClusters and fill maps
0719   if (!ootPhotonT_.isUninitialized()) {
0720     index = 0;
0721     for (auto& ootSuperCluster : ootSuperClusters) {
0722       //link seed cluster no matter what
0723       const reco::CaloClusterPtr& ootSeedCluster = ootSuperCluster.seed();
0724       linkCaloCluster(ootSeedCluster, ootEbeeClusters, ootEbeeClusterMap);
0725 
0726       //only proceed if ootSuperCluster is marked for full relinking
0727       bool fullrelink = ootSuperClusterFullRelinkMap.count(index++);
0728       if (!fullrelink) {
0729         //zero detid vector which is anyways not useful without stored rechits
0730         ootSuperCluster.clearHitsAndFractions();
0731         continue;
0732       }
0733 
0734       // link calo clusters
0735       linkCaloClusters(ootSuperCluster,
0736                        ootEbeeClusters,
0737                        ootEbeeClusterMap,
0738                        rechitMap,
0739                        barrelHitHandle,
0740                        endcapHitHandle,
0741                        caloTopology,
0742                        ootEsClusters,
0743                        ootEsClusterMap);
0744     }
0745   }
0746   //now finalize and add to the event collections in "reverse" order
0747 
0748   //rechits (fill output collections of rechits to be stored)
0749   for (const EcalRecHit& rechit : *barrelHitHandle) {
0750     if (rechitMap.count(rechit.detid())) {
0751       ebRecHits.push_back(rechit);
0752     }
0753   }
0754 
0755   for (const EcalRecHit& rechit : *endcapHitHandle) {
0756     if (rechitMap.count(rechit.detid())) {
0757       eeRecHits.push_back(rechit);
0758     }
0759   }
0760 
0761   event.emplace(outEBRecHits_, std::move(ebRecHits));
0762   event.emplace(outEERecHits_, std::move(eeRecHits));
0763 
0764   if (doPreshowerEcalHits_) {
0765     for (const EcalRecHit& rechit : *preshowerHitHandle) {
0766       if (rechitMap.count(rechit.detid())) {
0767         esRecHits.push_back(rechit);
0768       }
0769     }
0770     event.emplace(outESRecHits_, std::move(esRecHits));
0771   }
0772 
0773   for (const HBHERecHit& rechit : *hbheHitHandle) {
0774     if (hcalRechitMap.count(rechit.detid())) {
0775       hbheRecHits.push_back(rechit);
0776     }
0777   }
0778   event.emplace(outHBHERecHits_, std::move(hbheRecHits));
0779 
0780   //CaloClusters
0781   //put calocluster output collections in event and get orphan handles to create ptrs
0782   const auto& outEBEEClusterHandle = event.emplace(outEBEEClusters_, std::move(ebeeClusters));
0783   const auto& outESClusterHandle = event.emplace(outESClusters_, std::move(esClusters));
0784   ;
0785 
0786   //Loop over SuperClusters and relink GEDPhoton + GSFElectron CaloClusters
0787   for (reco::SuperCluster& superCluster : superClusters) {
0788     relinkCaloClusters(superCluster, ebeeClusterMap, esClusterMap, outEBEEClusterHandle, outESClusterHandle);
0789   }
0790 
0791   //OOTCaloClusters
0792   //put ootcalocluster output collections in event and get orphan handles to create ptrs
0793   edm::OrphanHandle<reco::CaloClusterCollection> outOOTEBEEClusterHandle;
0794   edm::OrphanHandle<reco::CaloClusterCollection> outOOTESClusterHandle;
0795   //Loop over OOTSuperClusters and relink OOTPhoton CaloClusters
0796   if (!ootPhotonT_.isUninitialized()) {
0797     outOOTEBEEClusterHandle = event.emplace(outOOTEBEEClusters_, std::move(ootEbeeClusters));
0798     outOOTESClusterHandle = event.emplace(outOOTESClusters_, std::move(ootEsClusters));
0799     for (reco::SuperCluster& ootSuperCluster : ootSuperClusters) {
0800       relinkCaloClusters(
0801           ootSuperCluster, ootEbeeClusterMap, ootEsClusterMap, outOOTEBEEClusterHandle, outOOTESClusterHandle);
0802     }
0803   }
0804   //put superclusters and conversions in the event
0805   const auto& outSuperClusterHandle = event.emplace(outSuperClusters_, std::move(superClusters));
0806   const auto& outConversionHandle = event.emplace(outConversions_, std::move(conversions));
0807   const auto& outSingleConversionHandle = event.emplace(outSingleConversions_, std::move(singleConversions));
0808   const auto& outGsfTrackHandle = event.emplace(outGsfTracks_, std::move(gsfTracks));
0809 
0810   //Loop over PhotonCores and relink GEDPhoton SuperClusters (and conversions)
0811   for (reco::PhotonCore& photonCore : photonCores) {
0812     // superclusters
0813     relinkSuperCluster(photonCore, superClusterMap, outSuperClusterHandle);
0814 
0815     //conversions
0816     const reco::ConversionRefVector& convrefs = photonCore.conversions();
0817     relinkConversions(photonCore, convrefs, conversionMap, outConversionHandle);
0818 
0819     //single leg conversions
0820     const reco::ConversionRefVector& singleconvrefs = photonCore.conversionsOneLeg();
0821     relinkConversions(photonCore, singleconvrefs, singleConversionMap, outSingleConversionHandle);
0822   }
0823 
0824   //Relink GSFElectron SuperClusters and main GSF Tracks
0825   for (reco::GsfElectronCore& gsfElectronCore : gsfElectronCores) {
0826     relinkSuperCluster(gsfElectronCore, superClusterMap, outSuperClusterHandle);
0827     relinkGsfTrack(gsfElectronCore, gsfTrackMap, outGsfTrackHandle);
0828   }
0829 
0830   //put ootsuperclusters in the event
0831   edm::OrphanHandle<reco::SuperClusterCollection> outOOTSuperClusterHandle;
0832   if (!ootPhotonT_.isUninitialized())
0833     outOOTSuperClusterHandle = event.emplace(outOOTSuperClusters_, std::move(ootSuperClusters));
0834 
0835   //Relink OOTPhoton SuperClusters
0836   for (reco::PhotonCore& ootPhotonCore : ootPhotonCores) {
0837     relinkSuperCluster(ootPhotonCore, ootSuperClusterMap, outOOTSuperClusterHandle);
0838   }
0839 
0840   //put photoncores and gsfelectroncores into the event
0841   const auto& outPhotonCoreHandle = event.emplace(outPhotonCores_, std::move(photonCores));
0842   edm::OrphanHandle<reco::PhotonCoreCollection> outOOTPhotonCoreHandle;
0843   if (!ootPhotonT_.isUninitialized())
0844     outOOTPhotonCoreHandle = event.emplace(outOOTPhotonCores_, std::move(ootPhotonCores));
0845   const auto& outgsfElectronCoreHandle = event.emplace(outGsfElectronCores_, std::move(gsfElectronCores));
0846 
0847   //loop over photons, oot photons, and electrons and relink the cores
0848   for (reco::Photon& photon : photons) {
0849     relinkPhotonCore(photon, photonCoreMap, outPhotonCoreHandle);
0850   }
0851 
0852   if (!ootPhotonT_.isUninitialized()) {
0853     for (reco::Photon& ootPhoton : ootPhotons) {
0854       relinkPhotonCore(ootPhoton, ootPhotonCoreMap, outOOTPhotonCoreHandle);
0855     }
0856   }
0857 
0858   for (reco::GsfElectron& gsfElectron : gsfElectrons) {
0859     relinkGsfElectronCore(gsfElectron, gsfElectronCoreMap, outgsfElectronCoreHandle);
0860 
0861     // -----
0862     // Also in this loop let's relink ambiguous tracks
0863     std::vector<reco::GsfTrackRef> ambigTracksInThisElectron;
0864     // Here we loop over the ambiguous tracks and save them in a vector
0865     for (auto const& igsf : gsfElectron.ambiguousGsfTracks()) {
0866       ambigTracksInThisElectron.push_back(igsf);
0867     }
0868 
0869     // Now we need to clear them (they are the refs to original collection):
0870     gsfElectron.clearAmbiguousGsfTracks();
0871 
0872     // And here we add them back, now from a new reduced collection:
0873     for (const auto& it : ambigTracksInThisElectron) {
0874       const auto& gsftkmapped = gsfTrackMap.find(it);
0875 
0876       if (gsftkmapped != gsfTrackMap.end()) {
0877         reco::GsfTrackRef gsftkref(outGsfTrackHandle, gsftkmapped->second);
0878         gsfElectron.addAmbiguousGsfTrack(gsftkref);
0879       } else
0880         throw cms::Exception("There must be a problem with linking and mapping of ambiguous gsf tracks...");
0881     }
0882 
0883     if (gsfElectron.ambiguousGsfTracksSize() > 0)
0884       gsfElectron.setAmbiguous(true);  // Set the flag
0885 
0886     ambigTracksInThisElectron.clear();
0887   }
0888 
0889   //(finally) store the output photon and electron collections
0890   const auto& outPhotonHandle = event.emplace(outPhotons_, std::move(photons));
0891   edm::OrphanHandle<reco::PhotonCollection> outOOTPhotonHandle;
0892   if (!ootPhotonT_.isUninitialized())
0893     outOOTPhotonHandle = event.emplace(outOOTPhotons_, std::move(ootPhotons));
0894   const auto& outGsfElectronHandle = event.emplace(outGsfElectrons_, std::move(gsfElectrons));
0895 
0896   //still need to output relinked valuemaps
0897 
0898   //photon pfcand isolation valuemap
0899   edm::ValueMap<std::vector<reco::PFCandidateRef>>::Filler fillerPhotons(photonPfCandMap);
0900   fillerPhotons.insert(outPhotonHandle, pfCandIsoPairVecPho.begin(), pfCandIsoPairVecPho.end());
0901   fillerPhotons.fill();
0902 
0903   //electron pfcand isolation valuemap
0904   edm::ValueMap<std::vector<reco::PFCandidateRef>>::Filler fillerGsfElectrons(gsfElectronPfCandMap);
0905   fillerGsfElectrons.insert(outGsfElectronHandle, pfCandIsoPairVecEle.begin(), pfCandIsoPairVecEle.end());
0906   fillerGsfElectrons.fill();
0907 
0908   event.emplace(outPhotonPfCandMap_, std::move(photonPfCandMap));
0909   event.emplace(outGsfElectronPfCandMap_, std::move(gsfElectronPfCandMap));
0910 
0911   //photon id value maps
0912   index = 0;
0913   for (auto const& vals : photonIdVals) {
0914     emplaceValueMap(outPhotonHandle, vals, event, outPhotonIds_[index++]);
0915   }
0916 
0917   //electron id value maps
0918   index = 0;
0919   for (auto const& vals : gsfElectronIdVals) {
0920     emplaceValueMap(outGsfElectronHandle, vals, event, outGsfElectronIds_[index++]);
0921   }
0922 
0923   // photon iso value maps
0924   index = 0;
0925   for (auto const& vals : photonFloatValueMapVals) {
0926     emplaceValueMap(outPhotonHandle, vals, event, outPhotonFloatValueMaps_[index++]);
0927   }
0928 
0929   if (!ootPhotonT_.isUninitialized()) {
0930     //oot photon iso value maps
0931     index = 0;
0932     for (auto const& vals : ootPhotonFloatValueMapVals) {
0933       emplaceValueMap(outOOTPhotonHandle, vals, event, outOOTPhotonFloatValueMaps_[index++]);
0934     }
0935   }
0936 
0937   // HI photon iso value maps
0938   if (!recoHIPhotonIsolationMapInputToken_.isUninitialized()) {
0939     emplaceValueMap(outPhotonHandle, recoHIPhotonIsolationMapInputVals, event, recoHIPhotonIsolationMapOutputName_);
0940   }
0941 
0942   //electron iso value maps
0943   index = 0;
0944   for (auto const& vals : gsfElectronFloatValueMapVals) {
0945     emplaceValueMap(outGsfElectronHandle, vals, event, outGsfElectronFloatValueMaps_[index++]);
0946   }
0947 }
0948 
0949 template <typename T, typename U>
0950 void ReducedEGProducer::linkCore(const T& core, U& cores, std::map<T, unsigned int>& coreMap) {
0951   if (!coreMap.count(core)) {
0952     cores.push_back(*core);
0953     coreMap[core] = cores.size() - 1;
0954   }
0955 }
0956 
0957 void ReducedEGProducer::linkSuperCluster(const reco::SuperClusterRef& superCluster,
0958                                          std::map<reco::SuperClusterRef, unsigned int>& superClusterMap,
0959                                          reco::SuperClusterCollection& superClusters,
0960                                          const bool relink,
0961                                          std::unordered_set<unsigned int>& superClusterFullRelinkMap) {
0962   const auto& mappedsc = superClusterMap.find(superCluster);
0963   //get index in output collection in order to keep track whether superCluster
0964   //will be subject to full relinking
0965   unsigned int mappedscidx = 0;
0966   if (mappedsc == superClusterMap.end()) {
0967     superClusters.push_back(*superCluster);
0968     mappedscidx = superClusters.size() - 1;
0969     superClusterMap[superCluster] = mappedscidx;
0970   } else {
0971     mappedscidx = mappedsc->second;
0972   }
0973 
0974   //additionally mark supercluster for full relinking
0975   if (relink)
0976     superClusterFullRelinkMap.insert(mappedscidx);
0977 }
0978 
0979 void ReducedEGProducer::linkConversions(const reco::ConversionRefVector& convrefs,
0980                                         reco::ConversionCollection& conversions,
0981                                         std::map<reco::ConversionRef, unsigned int>& conversionMap) {
0982   for (const auto& convref : convrefs) {
0983     linkConversion(convref, conversions, conversionMap);
0984   }
0985 }
0986 
0987 void ReducedEGProducer::linkConversionsByTrackRef(const edm::Handle<reco::ConversionCollection>& conversionHandle,
0988                                                   const reco::GsfElectron& gsfElectron,
0989                                                   reco::ConversionCollection& conversions,
0990                                                   std::map<reco::ConversionRef, unsigned int>& conversionMap) {
0991   int index = 0;
0992   for (const auto& conversion : *conversionHandle) {
0993     reco::ConversionRef convref(conversionHandle, index++);
0994 
0995     bool matched = ConversionTools::matchesConversion(gsfElectron, conversion, true, true);
0996     if (!matched)
0997       continue;
0998 
0999     linkConversion(convref, conversions, conversionMap);
1000   }
1001 }
1002 
1003 void ReducedEGProducer::linkConversionsByTrackRef(const edm::Handle<reco::ConversionCollection>& conversionHandle,
1004                                                   const reco::SuperCluster& superCluster,
1005                                                   reco::ConversionCollection& conversions,
1006                                                   std::map<reco::ConversionRef, unsigned int>& conversionMap) {
1007   int index = 0;
1008   for (const auto& conversion : *conversionHandle) {
1009     reco::ConversionRef convref(conversionHandle, index++);
1010 
1011     bool matched = ConversionTools::matchesConversion(superCluster, conversion, 0.2);
1012     if (!matched)
1013       continue;
1014 
1015     linkConversion(convref, conversions, conversionMap);
1016   }
1017 }
1018 
1019 void ReducedEGProducer::linkConversion(const reco::ConversionRef& convref,
1020                                        reco::ConversionCollection& conversions,
1021                                        std::map<reco::ConversionRef, unsigned int>& conversionMap) {
1022   if (!conversionMap.count(convref)) {
1023     conversions.push_back(*convref);
1024     conversionMap[convref] = conversions.size() - 1;
1025   }
1026 }
1027 
1028 void ReducedEGProducer::linkCaloCluster(const reco::CaloClusterPtr& caloCluster,
1029                                         reco::CaloClusterCollection& caloClusters,
1030                                         std::map<reco::CaloClusterPtr, unsigned int>& caloClusterMap) {
1031   if (!caloClusterMap.count(caloCluster)) {
1032     caloClusters.push_back(*caloCluster);
1033     caloClusterMap[caloCluster] = caloClusters.size() - 1;
1034   }
1035 }
1036 
1037 void ReducedEGProducer::linkCaloClusters(const reco::SuperCluster& superCluster,
1038                                          reco::CaloClusterCollection& ebeeClusters,
1039                                          std::map<reco::CaloClusterPtr, unsigned int>& ebeeClusterMap,
1040                                          std::unordered_set<DetId>& rechitMap,
1041                                          const edm::Handle<EcalRecHitCollection>& barrelHitHandle,
1042                                          const edm::Handle<EcalRecHitCollection>& endcapHitHandle,
1043                                          CaloTopology const& caloTopology,
1044                                          reco::CaloClusterCollection& esClusters,
1045                                          std::map<reco::CaloClusterPtr, unsigned int>& esClusterMap) {
1046   for (const auto& cluster : superCluster.clusters()) {
1047     linkCaloCluster(cluster, ebeeClusters, ebeeClusterMap);
1048 
1049     for (const auto& hitfrac : cluster->hitsAndFractions()) {
1050       rechitMap.insert(hitfrac.first);
1051     }
1052     //make sure to also take all hits in the 5x5 around the max energy xtal
1053     bool barrel = cluster->hitsAndFractions().front().first.subdetId() == EcalBarrel;
1054     const EcalRecHitCollection* rhcol = barrel ? barrelHitHandle.product() : endcapHitHandle.product();
1055     DetId seed = EcalClusterTools::getMaximum(*cluster, rhcol).first;
1056 
1057     std::vector<DetId> dets5x5 =
1058         caloTopology.getSubdetectorTopology(DetId::Ecal, barrel ? EcalBarrel : EcalEndcap)->getWindow(seed, 5, 5);
1059     for (const auto& detid : dets5x5) {
1060       rechitMap.insert(detid);
1061     }
1062   }
1063   for (const auto& cluster : superCluster.preshowerClusters()) {
1064     linkCaloCluster(cluster, esClusters, esClusterMap);
1065 
1066     for (const auto& hitfrac : cluster->hitsAndFractions()) {
1067       rechitMap.insert(hitfrac.first);
1068     }
1069   }
1070 }
1071 
1072 void ReducedEGProducer::linkHcalHits(const reco::SuperCluster& superClus,
1073                                      const HBHERecHitCollection& recHits,
1074                                      std::unordered_set<DetId>& hcalDetIds) {
1075   hcalHitSel_.addDetIds(superClus, recHits, hcalDetIds);
1076 }
1077 
1078 void ReducedEGProducer::relinkCaloClusters(reco::SuperCluster& superCluster,
1079                                            const std::map<reco::CaloClusterPtr, unsigned int>& ebeeClusterMap,
1080                                            const std::map<reco::CaloClusterPtr, unsigned int>& esClusterMap,
1081                                            const edm::OrphanHandle<reco::CaloClusterCollection>& outEBEEClusterHandle,
1082                                            const edm::OrphanHandle<reco::CaloClusterCollection>& outESClusterHandle) {
1083   //remap seed cluster
1084   const auto& seedmapped = ebeeClusterMap.find(superCluster.seed());
1085   if (seedmapped != ebeeClusterMap.end()) {
1086     //make new ptr
1087     reco::CaloClusterPtr clusptr(outEBEEClusterHandle, seedmapped->second);
1088     superCluster.setSeed(clusptr);
1089   }
1090 
1091   //remap all clusters
1092   reco::CaloClusterPtrVector clusters;
1093   for (const auto& cluster : superCluster.clusters()) {
1094     const auto& clustermapped = ebeeClusterMap.find(cluster);
1095     if (clustermapped != ebeeClusterMap.end()) {
1096       //make new ptr
1097       reco::CaloClusterPtr clusptr(outEBEEClusterHandle, clustermapped->second);
1098       clusters.push_back(clusptr);
1099     } else {
1100       //can only relink if all clusters are being relinked, so if one is missing, then skip the relinking completely
1101       clusters.clear();
1102       break;
1103     }
1104   }
1105   if (!clusters.empty()) {
1106     superCluster.setClusters(clusters);
1107   }
1108 
1109   //remap preshower clusters
1110   reco::CaloClusterPtrVector esclusters;
1111   for (const auto& cluster : superCluster.preshowerClusters()) {
1112     const auto& clustermapped = esClusterMap.find(cluster);
1113     if (clustermapped != esClusterMap.end()) {
1114       //make new ptr
1115       reco::CaloClusterPtr clusptr(outESClusterHandle, clustermapped->second);
1116       esclusters.push_back(clusptr);
1117     } else {
1118       //can only relink if all clusters are being relinked, so if one is missing, then skip the relinking completely
1119       esclusters.clear();
1120       break;
1121     }
1122   }
1123   if (!esclusters.empty()) {
1124     superCluster.setPreshowerClusters(esclusters);
1125   }
1126 }
1127 
1128 template <typename T>
1129 void ReducedEGProducer::relinkSuperCluster(
1130     T& core,
1131     const std::map<reco::SuperClusterRef, unsigned int>& superClusterMap,
1132     const edm::OrphanHandle<reco::SuperClusterCollection>& outSuperClusterHandle) {
1133   const auto& scmapped = superClusterMap.find(core.superCluster());
1134   if (scmapped != superClusterMap.end()) {
1135     //make new ref
1136     reco::SuperClusterRef scref(outSuperClusterHandle, scmapped->second);
1137     core.setSuperCluster(scref);
1138   }
1139 }
1140 
1141 void ReducedEGProducer::relinkGsfTrack(reco::GsfElectronCore& gsfElectronCore,
1142                                        const std::map<reco::GsfTrackRef, unsigned int>& gsfTrackMap,
1143                                        const edm::OrphanHandle<reco::GsfTrackCollection>& outGsfTrackHandle) {
1144   const auto& gsftkmapped = gsfTrackMap.find(gsfElectronCore.gsfTrack());
1145   if (gsftkmapped != gsfTrackMap.end()) {
1146     reco::GsfTrackRef gsftkref(outGsfTrackHandle, gsftkmapped->second);
1147     gsfElectronCore.setGsfTrack(gsftkref);
1148   }
1149 }
1150 
1151 void ReducedEGProducer::relinkConversions(reco::PhotonCore& photonCore,
1152                                           const reco::ConversionRefVector& convrefs,
1153                                           const std::map<reco::ConversionRef, unsigned int>& conversionMap,
1154                                           const edm::OrphanHandle<reco::ConversionCollection>& outConversionHandle) {
1155   reco::ConversionRefVector outconvrefs;
1156   for (const auto& convref : convrefs) {
1157     const auto& convmapped = conversionMap.find(convref);
1158     if (convmapped != conversionMap.end()) {
1159       //make new ref
1160       reco::ConversionRef outref(outConversionHandle, convmapped->second);
1161     } else {
1162       //can only relink if all conversions are being relinked, so if one is missing, then skip the relinking completely
1163       outconvrefs.clear();
1164       break;
1165     }
1166   }
1167   if (!outconvrefs.empty()) {
1168     photonCore.setConversions(outconvrefs);
1169   }
1170 }
1171 
1172 void ReducedEGProducer::relinkPhotonCore(reco::Photon& photon,
1173                                          const std::map<reco::PhotonCoreRef, unsigned int>& photonCoreMap,
1174                                          const edm::OrphanHandle<reco::PhotonCoreCollection>& outPhotonCoreHandle) {
1175   const auto& coremapped = photonCoreMap.find(photon.photonCore());
1176   if (coremapped != photonCoreMap.end()) {
1177     //make new ref
1178     reco::PhotonCoreRef coreref(outPhotonCoreHandle, coremapped->second);
1179     photon.setPhotonCore(coreref);
1180   }
1181 }
1182 
1183 void ReducedEGProducer::relinkGsfElectronCore(
1184     reco::GsfElectron& gsfElectron,
1185     const std::map<reco::GsfElectronCoreRef, unsigned int>& gsfElectronCoreMap,
1186     const edm::OrphanHandle<reco::GsfElectronCoreCollection>& outgsfElectronCoreHandle) {
1187   const auto& coremapped = gsfElectronCoreMap.find(gsfElectron.core());
1188   if (coremapped != gsfElectronCoreMap.end()) {
1189     //make new ref
1190     reco::GsfElectronCoreRef coreref(outgsfElectronCoreHandle, coremapped->second);
1191     gsfElectron.setCore(coreref);
1192   }
1193 }
1194 
1195 void ReducedEGProducer::calibratePhoton(reco::Photon& photon,
1196                                         const reco::PhotonRef& oldPhoRef,
1197                                         const edm::ValueMap<float>& energyMap,
1198                                         const edm::ValueMap<float>& energyErrMap) {
1199   float newEnergy = energyMap[oldPhoRef];
1200   float newEnergyErr = energyErrMap[oldPhoRef];
1201   photon.setCorrectedEnergy(reco::Photon::P4type::regression2, newEnergy, newEnergyErr, true);
1202 }
1203 
1204 void ReducedEGProducer::calibrateElectron(reco::GsfElectron& electron,
1205                                           const reco::GsfElectronRef& oldEleRef,
1206                                           const edm::ValueMap<float>& energyMap,
1207                                           const edm::ValueMap<float>& energyErrMap,
1208                                           const edm::ValueMap<float>& ecalEnergyMap,
1209                                           const edm::ValueMap<float>& ecalEnergyErrMap) {
1210   const float newEnergy = energyMap[oldEleRef];
1211   const float newEnergyErr = energyErrMap[oldEleRef];
1212   const float newEcalEnergy = ecalEnergyMap[oldEleRef];
1213   const float newEcalEnergyErr = ecalEnergyErrMap[oldEleRef];
1214 
1215   //make a copy of this as the setCorrectedEcalEnergy call with modifiy the electrons p4
1216   const math::XYZTLorentzVector oldP4 = electron.p4();
1217   const float corr = newEnergy / oldP4.E();
1218 
1219   electron.setCorrectedEcalEnergy(newEcalEnergy);
1220   electron.setCorrectedEcalEnergyError(newEcalEnergyErr);
1221 
1222   math::XYZTLorentzVector newP4{oldP4.x() * corr, oldP4.y() * corr, oldP4.z() * corr, newEnergy};
1223   electron.correctMomentum(newP4, electron.trackMomentumError(), newEnergyErr);
1224 }