diff --git a/PhysicsTools/PatAlgos/python/tools/helpers.py b/PhysicsTools/PatAlgos/python/tools/helpers.py index a1d4a7851a63d..0f9dbd0d181e6 100644 --- a/PhysicsTools/PatAlgos/python/tools/helpers.py +++ b/PhysicsTools/PatAlgos/python/tools/helpers.py @@ -433,3 +433,65 @@ def testListModules(self): self.assertEqual([p.a,p.b,p.c], listModules(p.s)) unittest.main() + +class CloneTaskVisitor(object): + """Visitor that travels within a cms.Task, and returns a cloned version of the Task. + All modules are cloned and a postfix is added""" + def __init__(self, process, label, postfix, removePostfix="", noClones = [], verbose = False): + self._process = process + self._postfix = postfix + self._removePostfix = removePostfix + self._noClones = noClones + self._verbose = verbose + self._moduleLabels = [] + self._clonedTask = cms.Task() + setattr(process, self._newLabel(label), self._clonedTask) + + def enter(self, visitee): + if isinstance(visitee, cms._Module): + label = visitee.label() + newModule = None + if label in self._noClones: #keep unchanged + newModule = getattr(self._process, label) + elif label in self._moduleLabels: # has the module already been cloned ? + newModule = getattr(self._process, self._newLabel(label)) + else: + self._moduleLabels.append(label) + newModule = visitee.clone() + setattr(self._process, self._newLabel(label), newModule) + self.__appendToTopTask(newModule) + + def leave(self, visitee): + pass + + def clonedTask(self):#FIXME: can the following be used for Task? + for label in self._moduleLabels: + massSearchReplaceAnyInputTag(self._clonedTask, label, self._newLabel(label), moduleLabelOnly=True, verbose=self._verbose) + self._moduleLabels = [] # prevent the InputTag replacement next time the 'clonedTask' function is called. + return self._clonedTask + + def _newLabel(self, label): + if self._removePostfix != "": + if label[-len(self._removePostfix):] == self._removePostfix: + label = label[0:-len(self._removePostfix)] + else: + raise Exception("Tried to remove postfix %s from label %s, but it wasn't there" % (self._removePostfix, label)) + return label + self._postfix + + def __appendToTopTask(self, visitee): + self._clonedTask.add(visitee) + +def cloneProcessingSnippetTask(process, task, postfix, removePostfix="", noClones = [], verbose = False): + """ + ------------------------------------------------------------------ + copy a task plus the modules therein (including modules in subtasks) + both are renamed by getting a postfix + input tags are automatically adjusted + ------------------------------------------------------------------ + """ + result = task + if not postfix == "": + visitor = CloneTaskVisitor(process, task.label(), postfix, removePostfix, noClones, verbose) + task.visit(visitor) + result = visitor.clonedTask() + return result diff --git a/RecoJets/JetProducers/plugins/BoostedTauSeedsProducer.cc b/RecoJets/JetProducers/plugins/BoostedTauSeedsProducer.cc index 832c0ab5aac00..93e32da07585f 100644 --- a/RecoJets/JetProducers/plugins/BoostedTauSeedsProducer.cc +++ b/RecoJets/JetProducers/plugins/BoostedTauSeedsProducer.cc @@ -28,6 +28,8 @@ #include "DataFormats/JetReco/interface/PFJetCollection.h" #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h" #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h" +#include "DataFormats/PatCandidates/interface/Jet.h" +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" #include "DataFormats/Common/interface/AssociationMap.h" #include "DataFormats/Common/interface/Ref.h" #include "DataFormats/Common/interface/RefProd.h" @@ -40,41 +42,46 @@ #include #include -class BoostedTauSeedsProducer : public edm::stream::EDProducer<> { +template +class GenericBoostedTauSeedsProducer : public edm::stream::EDProducer<> { public: - explicit BoostedTauSeedsProducer(const edm::ParameterSet&); - ~BoostedTauSeedsProducer() override {} + explicit GenericBoostedTauSeedsProducer(const edm::ParameterSet&); + ~GenericBoostedTauSeedsProducer() override {} void produce(edm::Event&, const edm::EventSetup&) override; private: - typedef edm::AssociationMap, std::vector, unsigned int> > + typedef edm::AssociationMap, std::vector, unsigned int>> JetToPFCandidateAssociation; + typedef std::vector JetTypeCollection; + typedef std::vector CandTypeCollection; std::string moduleLabel_; typedef edm::View JetView; edm::EDGetTokenT srcSubjets_; - edm::EDGetTokenT srcPFCandidates_; + edm::EDGetTokenT srcPFCandidates_; int verbosity_; }; -BoostedTauSeedsProducer::BoostedTauSeedsProducer(const edm::ParameterSet& cfg) +template +GenericBoostedTauSeedsProducer::GenericBoostedTauSeedsProducer(const edm::ParameterSet& cfg) : moduleLabel_(cfg.getParameter("@module_label")) { srcSubjets_ = consumes(cfg.getParameter("subjetSrc")); - srcPFCandidates_ = consumes(cfg.getParameter("pfCandidateSrc")); + srcPFCandidates_ = consumes(cfg.getParameter("pfCandidateSrc")); verbosity_ = (cfg.exists("verbosity")) ? cfg.getParameter("verbosity") : 0; - produces(); + produces(); produces("pfCandAssocMapForIsolation"); //produces("pfCandAssocMapForIsoDepositVetos"); } namespace { - typedef std::vector > JetToConstitMap; + typedef std::vector> JetToConstitMap; - reco::PFJet convertToPFJet(const reco::Jet& jet, const reco::Jet::Constituents& jetConstituents) { + template + JetType convertToPFJet(const reco::Jet& jet, const reco::Jet::Constituents& jetConstituents) { // CV: code for filling pfJetSpecific objects taken from // RecoParticleFlow/PFRootEvent/src/JetMaker.cc double chargedHadronEnergy = 0.; @@ -86,37 +93,36 @@ namespace { int neutralMultiplicity = 0; int muonMultiplicity = 0; for (auto const& jetConstituent : jetConstituents) { - const reco::PFCandidate* pfCandidate = dynamic_cast(jetConstituent.get()); + const CandType* pfCandidate = dynamic_cast(jetConstituent.get()); if (pfCandidate) { - switch (pfCandidate->particleId()) { - case reco::PFCandidate::h: // charged hadron + switch (std::abs(pfCandidate->pdgId())) { + case 211: // charged hadron chargedHadronEnergy += pfCandidate->energy(); ++chargedMultiplicity; break; - case reco::PFCandidate::e: // electron + case 11: // electron chargedEmEnergy += pfCandidate->energy(); ++chargedMultiplicity; break; - case reco::PFCandidate::mu: // muon + case 13: // muon chargedMuEnergy += pfCandidate->energy(); ++chargedMultiplicity; ++muonMultiplicity; break; - case reco::PFCandidate::gamma: // photon - case reco::PFCandidate::egamma_HF: // electromagnetic in HF + case 22: // photon + case 2: // electromagnetic in HF neutralEmEnergy += pfCandidate->energy(); ++neutralMultiplicity; break; - case reco::PFCandidate::h0: // neutral hadron - case reco::PFCandidate::h_HF: // hadron in HF + case 130: // neutral hadron + case 1: // hadron in HF neutralHadronEnergy += pfCandidate->energy(); ++neutralMultiplicity; break; default: - edm::LogWarning("convertToPFJet") - << "PFCandidate: Pt = " << pfCandidate->pt() << ", eta = " << pfCandidate->eta() - << ", phi = " << pfCandidate->phi() << " has invalid particleID = " << pfCandidate->particleId() - << " !!" << std::endl; + edm::LogWarning("convertToPFJet") << "PFCandidate: Pt = " << pfCandidate->pt() + << ", eta = " << pfCandidate->eta() << ", phi = " << pfCandidate->phi() + << " has invalid pdgID = " << pfCandidate->pdgId() << " !!" << std::endl; break; } } else { @@ -138,7 +144,7 @@ namespace { reco::PFJet pfJet(jet.p4(), jet.vertex(), pfJetSpecific, jetConstituents); pfJet.setJetArea(jet.jetArea()); - return pfJet; + return JetType(pfJet); } void getJetConstituents(const reco::Jet& jet, reco::Jet::Constituents& jet_and_subjetConstituents) { @@ -153,20 +159,21 @@ namespace { } } - std::vector getPFCandidates_exclJetConstituents( + template + std::vector>> getPFCandidates_exclJetConstituents( const reco::Jet& jet, - const edm::Handle& pfCandidates, + const edm::Handle>& pfCandidates, const JetToConstitMap::value_type& constitmap, bool invert) { auto const& collection_cand = (*pfCandidates); - std::vector pfCandidates_exclJetConstituents; + std::vector>> pfCandidates_exclJetConstituents; size_t numPFCandidates = pfCandidates->size(); for (size_t pfCandidateIdx = 0; pfCandidateIdx < numPFCandidates; ++pfCandidateIdx) { if (!(deltaR2(collection_cand[pfCandidateIdx], jet) < 1.0)) continue; bool isJetConstituent = constitmap.count(pfCandidateIdx); if (!(isJetConstituent ^ invert)) { - reco::PFCandidateRef pfCandidate(pfCandidates, pfCandidateIdx); + edm::Ref> pfCandidate(pfCandidates, pfCandidateIdx); pfCandidates_exclJetConstituents.push_back(pfCandidate); } } @@ -184,7 +191,8 @@ namespace { } } // namespace -void BoostedTauSeedsProducer::produce(edm::Event& evt, const edm::EventSetup& es) { +template +void GenericBoostedTauSeedsProducer::produce(edm::Event& evt, const edm::EventSetup& es) { if (verbosity_ >= 1) { std::cout << ":" << std::endl; } @@ -196,14 +204,14 @@ void BoostedTauSeedsProducer::produce(edm::Event& evt, const edm::EventSetup& es } assert((subjets->size() % 2) == 0); // CV: ensure that subjets come in pairs - edm::Handle pfCandidates; + edm::Handle pfCandidates; evt.getByToken(srcPFCandidates_, pfCandidates); if (verbosity_ >= 1) { std::cout << "#pfCandidates = " << pfCandidates->size() << std::endl; } - auto selectedSubjets = std::make_unique(); - edm::RefProd selectedSubjetRefProd = evt.getRefBeforePut(); + auto selectedSubjets = std::make_unique(); + edm::RefProd selectedSubjetRefProd = evt.getRefBeforePut(); auto selectedSubjetPFCandidateAssociationForIsolation = std::make_unique(&evt.productGetter()); @@ -247,16 +255,16 @@ void BoostedTauSeedsProducer::produce(edm::Event& evt, const edm::EventSetup& es printJetConstituents("subjetConstituents2", subjetConstituents2); } - selectedSubjets->push_back(convertToPFJet(*subjet1, subjetConstituents1)); - edm::Ref subjetRef1(selectedSubjetRefProd, selectedSubjets->size() - 1); - selectedSubjets->push_back(convertToPFJet(*subjet2, subjetConstituents2)); - edm::Ref subjetRef2(selectedSubjetRefProd, selectedSubjets->size() - 1); + selectedSubjets->push_back(convertToPFJet(*subjet1, subjetConstituents1)); + edm::Ref subjetRef1(selectedSubjetRefProd, selectedSubjets->size() - 1); + selectedSubjets->push_back(convertToPFJet(*subjet2, subjetConstituents2)); + edm::Ref subjetRef2(selectedSubjetRefProd, selectedSubjets->size() - 1); // find all PFCandidates that are not constituents of the **other** subjet - std::vector pfCandidatesNotInSubjet1 = - getPFCandidates_exclJetConstituents(*subjet1, pfCandidates, constitmap[2 * idx + 1], false); - std::vector pfCandidatesNotInSubjet2 = - getPFCandidates_exclJetConstituents(*subjet2, pfCandidates, constitmap[2 * idx], false); + std::vector>> pfCandidatesNotInSubjet1 = + getPFCandidates_exclJetConstituents(*subjet1, pfCandidates, constitmap[2 * idx + 1], false); + std::vector>> pfCandidatesNotInSubjet2 = + getPFCandidates_exclJetConstituents(*subjet2, pfCandidates, constitmap[2 * idx], false); if (verbosity_ >= 1) { std::cout << "#pfCandidatesNotInSubjet1 = " << pfCandidatesNotInSubjet1.size() << std::endl; std::cout << "#pfCandidatesNotInSubjet2 = " << pfCandidatesNotInSubjet2.size() << std::endl; @@ -276,5 +284,9 @@ void BoostedTauSeedsProducer::produce(edm::Event& evt, const edm::EventSetup& es evt.put(std::move(selectedSubjetPFCandidateAssociationForIsolation), "pfCandAssocMapForIsolation"); } +typedef GenericBoostedTauSeedsProducer BoostedTauSeedsProducer; +typedef GenericBoostedTauSeedsProducer PATBoostedTauSeedsProducer; + #include "FWCore/Framework/interface/MakerMacros.h" DEFINE_FWK_MODULE(BoostedTauSeedsProducer); +DEFINE_FWK_MODULE(PATBoostedTauSeedsProducer); diff --git a/RecoTauTag/Configuration/python/tools/adaptToRunAtMiniAOD.py b/RecoTauTag/Configuration/python/tools/adaptToRunAtMiniAOD.py index e19ab6c984573..7487b9c5675ab 100644 --- a/RecoTauTag/Configuration/python/tools/adaptToRunAtMiniAOD.py +++ b/RecoTauTag/Configuration/python/tools/adaptToRunAtMiniAOD.py @@ -7,241 +7,300 @@ # Created: 9 Nov. 2017 ###### +import PhysicsTools.PatAlgos.tools.helpers as configtools ##### -def addTauReReco(process): - #PAT - process.load('PhysicsTools.PatAlgos.producersLayer1.tauProducer_cff') - process.load('PhysicsTools.PatAlgos.selectionLayer1.tauSelector_cfi') - process.selectedPatTaus.cut="pt > 18. && tauID(\'decayModeFindingNewDMs\')> 0.5" #Cut as in MiniAOD - #Tau RECO - process.load("RecoTauTag.Configuration.RecoPFTauTag_cff") - #Task/Sequence for tau rereco - process.miniAODTausTask = cms.Task( - process.PFTauTask, - process.makePatTausTask, - process.selectedPatTaus - ) - process.miniAODTausSequence = cms.Sequence(process.miniAODTausTask) - #Path with tau rereco (Needed?) - process.TauReco = cms.Path(process.miniAODTausSequence) +class adaptToRunAtMiniAOD(object): + def __init__(self, process, runBoosted=False, postfix=""): + self.process = process + self.runBoosted = runBoosted + self.postfix = postfix + if runBoosted: + self.postfix = 'Boosted'+postfix + #print("Adapting boosted tau reconstruction to run at miniAOD; postfix = \"%s\"" % self.postfix) + #else: + # print("Adapting tau reconstruction to run at miniAOD; postfix = \"%s\"" % self.postfix) -##### -def convertModuleToMiniAODInput(process, name): - module = getattr(process, name) - if hasattr(module, 'particleFlowSrc'): - module.particleFlowSrc = cms.InputTag("packedPFCandidates", "", "") - if hasattr(module, 'vertexSrc'): - module.vertexSrc = cms.InputTag('offlineSlimmedPrimaryVertices') - if hasattr(module, 'qualityCuts') and hasattr(module.qualityCuts, 'primaryVertexSrc'): - module.qualityCuts.primaryVertexSrc = cms.InputTag('offlineSlimmedPrimaryVertices') + ##### + def addTauReReco(self): + #PAT + self.process.load('PhysicsTools.PatAlgos.producersLayer1.tauProducer_cff') + self.process.load('PhysicsTools.PatAlgos.selectionLayer1.tauSelector_cfi') + self.process.selectedPatTaus.cut="pt > 18. && tauID(\'decayModeFindingNewDMs\')> 0.5" #Cut as in MiniAOD + #Tau RECO + self.process.load("RecoTauTag.Configuration.RecoPFTauTag_cff") + #Task/Sequence for tau rereco + self.process.miniAODTausTask = cms.Task( + self.process.PFTauTask, + self.process.makePatTausTask, + self.process.selectedPatTaus + ) + self.miniAODTausTask = configtools.cloneProcessingSnippetTask( + self.process,self.process.miniAODTausTask,postfix=self.postfix) + setattr(self.process,'miniAODTausSequence'+self.postfix,cms.Sequence(self.miniAODTausTask)) + if not self.postfix=="": + del self.process.miniAODTausTask -##### -def adaptTauToMiniAODReReco(process, reclusterJets=True): + ##### + def convertModuleToMiniAODInput(self,name): + module = getattr(self.process, name) + if hasattr(module, 'particleFlowSrc'): + module.particleFlowSrc = cms.InputTag("packedPFCandidates", "", "") + if hasattr(module, 'vertexSrc'): + module.vertexSrc = cms.InputTag('offlineSlimmedPrimaryVertices') + if hasattr(module, 'qualityCuts') and hasattr(module.qualityCuts, 'primaryVertexSrc'): + module.qualityCuts.primaryVertexSrc = cms.InputTag('offlineSlimmedPrimaryVertices') + + ##### + def adaptTauToMiniAODReReco(self,reclusterJets=True): # TRYING TO MAKE THINGS MINIAOD COMPATIBLE, FROM THE START, TO THE END, 1 BY 1 - #print '[adaptTauToMiniAODReReco]: Start' - - jetCollection = 'slimmedJets' - # Add new jet collections if reclustering is demanded - if reclusterJets: - jetCollection = 'patJetsPAT' - from RecoJets.JetProducers.ak4PFJets_cfi import ak4PFJets - process.ak4PFJetsPAT = ak4PFJets.clone( - src=cms.InputTag("packedPFCandidates") - ) - # trivial PATJets - from PhysicsTools.PatAlgos.producersLayer1.jetProducer_cfi import _patJets - process.patJetsPAT = _patJets.clone( - jetSource = cms.InputTag("ak4PFJetsPAT"), - addJetCorrFactors = cms.bool(False), - jetCorrFactorsSource = cms.VInputTag(), - addBTagInfo = cms.bool(False), - addDiscriminators = cms.bool(False), - discriminatorSources = cms.VInputTag(), - addAssociatedTracks = cms.bool(False), - addJetCharge = cms.bool(False), - addGenPartonMatch = cms.bool(False), - embedGenPartonMatch = cms.bool(False), - addGenJetMatch = cms.bool(False), - getJetMCFlavour = cms.bool(False), - addJetFlavourInfo = cms.bool(False), - ) - process.miniAODTausTask.add(process.ak4PFJetsPAT) - process.miniAODTausTask.add(process.patJetsPAT) + #print '[adaptTauToMiniAODReReco]: Start' + jetCollection = 'slimmedJets' + # Add new jet collections if reclustering is demanded + if self.runBoosted: + jetCollection = 'boostedTauSeedsPAT'+self.postfix + from RecoTauTag.Configuration.boostedHPSPFTaus_cff import ca8PFJetsCHSprunedForBoostedTaus + setattr(self.process,'ca8PFJetsCHSprunedForBoostedTausPAT'+self.postfix,ca8PFJetsCHSprunedForBoostedTaus.clone( + src = 'packedPFCandidates', + jetCollInstanceName = 'subJetsForSeedingBoostedTausPAT' + )) + setattr(self.process,'boostedTauSeedsPAT'+self.postfix, + cms.EDProducer("PATBoostedTauSeedsProducer", + subjetSrc = cms.InputTag('ca8PFJetsCHSprunedForBoostedTausPAT'+self.postfix,'subJetsForSeedingBoostedTausPAT'), + pfCandidateSrc = cms.InputTag('packedPFCandidates'), + verbosity = cms.int32(0) + )) + self.miniAODTausTask.add(getattr(self.process,'ca8PFJetsCHSprunedForBoostedTausPAT'+self.postfix)) + self.miniAODTausTask.add(getattr(self.process,'boostedTauSeedsPAT'+self.postfix)) + elif reclusterJets: + jetCollection = 'patJetsPAT'+self.postfix + from RecoJets.JetProducers.ak4PFJets_cfi import ak4PFJets + setattr(self.process,'ak4PFJetsPAT'+self.postfix,ak4PFJets.clone( + src = "packedPFCandidates" + )) + # trivial PATJets + from PhysicsTools.PatAlgos.producersLayer1.jetProducer_cfi import _patJets + setattr(self.process,'patJetsPAT'+self.postfix,_patJets.clone( + jetSource = "ak4PFJetsPAT"+self.postfix, + addJetCorrFactors = False, + jetCorrFactorsSource = [], + addBTagInfo = False, + addDiscriminators = False, + discriminatorSources = [], + addAssociatedTracks = False, + addJetCharge = False, + addGenPartonMatch = False, + embedGenPartonMatch = False, + addGenJetMatch = False, + getJetMCFlavour = False, + addJetFlavourInfo = False, + )) + self.miniAODTausTask.add(getattr(self.process,'ak4PFJetsPAT'+self.postfix)) + self.miniAODTausTask.add(getattr(self.process,'patJetsPAT'+self.postfix)) - # so this adds all tracks to jet in some deltaR region. we don't have tracks so don't need it :D - # process.ak4PFJetTracksAssociatorAtVertex.jets = cms.InputTag(jetCollection) + # so this adds all tracks to jet in some deltaR region. we don't have tracks so don't need it :D + # self.process.ak4PFJetTracksAssociatorAtVertex.jets = cms.InputTag(jetCollection) - # Remove ak4PFJetTracksAssociatorAtVertex from recoTauCommonSequence - # Remove pfRecoTauTagInfoProducer from recoTauCommonSequence since it uses the jet-track association - # HOWEVER, may use https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookMiniAOD2017#Isolated_Tracks - # probably needs recovery of the two modules above - - process.recoTauAK4Jets08RegionPAT = cms.EDProducer("RecoTauPatJetRegionProducer", - deltaR = process.recoTauAK4PFJets08Region.deltaR, - maxJetAbsEta = process.recoTauAK4PFJets08Region.maxJetAbsEta, - minJetPt = process.recoTauAK4PFJets08Region.minJetPt, - pfCandAssocMapSrc = cms.InputTag(""), - pfCandSrc = cms.InputTag("packedPFCandidates"), - src = cms.InputTag(jetCollection) - ) - - process.recoTauPileUpVertices.src = cms.InputTag("offlineSlimmedPrimaryVertices") - # Redefine recoTauCommonTask - # with redefined region and PU vertices, and w/o track-to-vertex associator and tauTagInfo (the two latter are probably obsolete and not needed at all) - process.recoTauCommonTask = cms.Task( - process.recoTauAK4Jets08RegionPAT, - process.recoTauPileUpVertices - ) - - for moduleName in process.TauReco.moduleNames(): - convertModuleToMiniAODInput(process, moduleName) - - - # Adapt TauPiZeros producer - process.ak4PFJetsLegacyHPSPiZeros.builders[0].qualityCuts.primaryVertexSrc = cms.InputTag("offlineSlimmedPrimaryVertices") - process.ak4PFJetsLegacyHPSPiZeros.jetSrc = cms.InputTag(jetCollection) - - # Adapt TauChargedHadrons producer - for builder in process.ak4PFJetsRecoTauChargedHadrons.builders: - builder.qualityCuts.primaryVertexSrc = cms.InputTag("offlineSlimmedPrimaryVertices") - if builder.name.value() == 'tracks': #replace plugin based on generalTracks by one based on lostTracks - builder.name = 'lostTracks' - builder.plugin = 'PFRecoTauChargedHadronFromLostTrackPlugin' - builder.srcTracks = cms.InputTag("lostTracks") - process.ak4PFJetsRecoTauChargedHadrons.jetSrc = cms.InputTag(jetCollection) - - # Adapt combinatoricRecoTau producer - process.combinatoricRecoTaus.jetRegionSrc = 'recoTauAK4Jets08RegionPAT' - process.combinatoricRecoTaus.jetSrc = jetCollection - # Adapt builders - for builder in process.combinatoricRecoTaus.builders: - for name,value in builder.parameters_().items(): - if name == 'qualityCuts': - builder.qualityCuts.primaryVertexSrc = 'offlineSlimmedPrimaryVertices' - elif name == 'pfCandSrc': - builder.pfCandSrc = 'packedPFCandidates' - # Adapt supported modifiers and remove unsupported ones - modifiersToRemove_ = cms.VPSet() - for mod in process.combinatoricRecoTaus.modifiers: - if mod.name.value() == 'elec_rej': - modifiersToRemove_.append(mod) - continue - elif mod.name.value() == 'TTIworkaround': - modifiersToRemove_.append(mod) - continue - for name,value in mod.parameters_().items(): - if name == 'qualityCuts': - mod.qualityCuts.primaryVertexSrc = 'offlineSlimmedPrimaryVertices' - for mod in modifiersToRemove_: - process.combinatoricRecoTaus.modifiers.remove(mod) - #print "\t\t Removing '%s' modifier from 'combinatoricRecoTaus'" %mod.name.value() - - # Redefine tau PV producer - process.hpsPFTauPrimaryVertexProducer.__dict__['_TypedParameterizable__type'] = 'PFTauMiniAODPrimaryVertexProducer' - process.hpsPFTauPrimaryVertexProducer.PVTag = 'offlineSlimmedPrimaryVertices' - process.hpsPFTauPrimaryVertexProducer.packedCandidatesTag = cms.InputTag("packedPFCandidates") - process.hpsPFTauPrimaryVertexProducer.lostCandidatesTag = cms.InputTag("lostTracks") - - # Redefine tau SV producer - process.hpsPFTauSecondaryVertexProducer = cms.EDProducer("PFTauSecondaryVertexProducer", - PFTauTag = cms.InputTag("hpsPFTauProducer") - ) + # Remove ak4PFJetTracksAssociatorAtVertex from recoTauCommonSequence + # Remove pfRecoTauTagInfoProducer from recoTauCommonSequence since it uses the jet-track association + # HOWEVER, may use https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookMiniAOD2017#Isolated_Tracks + # probably needs recovery of the two modules above + self.miniAODTausTask.remove(getattr(self.process,'ak4PFJetTracksAssociatorAtVertex'+self.postfix)) + self.miniAODTausTask.remove(getattr(self.process,'pfRecoTauTagInfoProducer'+self.postfix)) + + self.miniAODTausTask.remove(getattr(self.process,'recoTauAK4PFJets08Region'+self.postfix)) + setattr(self.process,'recoTauAK4Jets08RegionPAT'+self.postfix, + cms.EDProducer("RecoTauPatJetRegionProducer", + deltaR = self.process.recoTauAK4PFJets08Region.deltaR, + maxJetAbsEta = self.process.recoTauAK4PFJets08Region.maxJetAbsEta, + minJetPt = self.process.recoTauAK4PFJets08Region.minJetPt, + pfCandAssocMapSrc = cms.InputTag(""), + pfCandSrc = cms.InputTag("packedPFCandidates"), + src = cms.InputTag(jetCollection) + )) + _jetRegionProducer = getattr(self.process,'recoTauAK4Jets08RegionPAT'+self.postfix) + self.miniAODTausTask.add(_jetRegionProducer) + if self.runBoosted: + _jetRegionProducer.pfCandAssocMapSrc = cms.InputTag(jetCollection, 'pfCandAssocMapForIsolation') + + getattr(self.process,'recoTauPileUpVertices'+self.postfix).src = "offlineSlimmedPrimaryVertices" + + for moduleName in self.miniAODTausTask.moduleNames(): + self.convertModuleToMiniAODInput(moduleName) + + + # Adapt TauPiZeros producer + _piZeroProducer = getattr(self.process,'ak4PFJetsLegacyHPSPiZeros'+self.postfix) + for builder in _piZeroProducer.builders: + builder.qualityCuts.primaryVertexSrc = "offlineSlimmedPrimaryVertices" + _piZeroProducer.jetSrc = jetCollection + + # Adapt TauChargedHadrons producer + _chargedHadronProducer = getattr(self.process,'ak4PFJetsRecoTauChargedHadrons'+self.postfix) + for builder in _chargedHadronProducer.builders: + builder.qualityCuts.primaryVertexSrc = "offlineSlimmedPrimaryVertices" + if builder.name.value() == 'tracks': #replace plugin based on generalTracks by one based on lostTracks + builder.name = 'lostTracks' + builder.plugin = 'PFRecoTauChargedHadronFromLostTrackPlugin' + builder.srcTracks = "lostTracks" + if self.runBoosted: + builder.dRcone = 0.3 + builder.dRconeLimitedToJetArea = True + _chargedHadronProducer.jetSrc = jetCollection + + # Adapt combinatoricRecoTau producer + _combinatoricRecoTauProducer = getattr(self.process,'combinatoricRecoTaus'+self.postfix) + _combinatoricRecoTauProducer.jetRegionSrc = 'recoTauAK4Jets08RegionPAT'+self.postfix + _combinatoricRecoTauProducer.jetSrc = jetCollection + # Adapt builders + for builder in _combinatoricRecoTauProducer.builders: + for name,value in builder.parameters_().items(): + if name == 'qualityCuts': + builder.qualityCuts.primaryVertexSrc = 'offlineSlimmedPrimaryVertices' + elif name == 'pfCandSrc': + builder.pfCandSrc = 'packedPFCandidates' + # Adapt supported modifiers and remove unsupported ones + _modifiersToRemove = cms.VPSet() + for mod in _combinatoricRecoTauProducer.modifiers: + if mod.name.value() == 'elec_rej': + _modifiersToRemove.append(mod) + continue + elif mod.name.value() == 'TTIworkaround': + _modifiersToRemove.append(mod) + continue + for name,value in mod.parameters_().items(): + if name == 'qualityCuts': + mod.qualityCuts.primaryVertexSrc = 'offlineSlimmedPrimaryVertices' + for mod in _modifiersToRemove: + _combinatoricRecoTauProducer.modifiers.remove(mod) + #print "\t\t Removing '%s' modifier from 'combinatoricRecoTaus'" %mod.name.value() + + # Redefine tau PV producer + _tauPVProducer = getattr(self.process,'hpsPFTauPrimaryVertexProducer'+self.postfix) + _tauPVProducer.__dict__['_TypedParameterizable__type'] = 'PFTauMiniAODPrimaryVertexProducer' + _tauPVProducer.PVTag = 'offlineSlimmedPrimaryVertices' + _tauPVProducer.packedCandidatesTag = cms.InputTag("packedPFCandidates") + _tauPVProducer.lostCandidatesTag = cms.InputTag("lostTracks") + + # Redefine tau SV producer + setattr(self.process,'hpsPFTauSecondaryVertexProducer'+self.postfix, + cms.EDProducer("PFTauSecondaryVertexProducer", + PFTauTag = cms.InputTag("hpsPFTauProducer"+self.postfix) + )) - # Remove RecoTau producers which are not supported (yet?), i.e. against-e/mu discriminats - for moduleName in process.TauReco.moduleNames(): - if 'ElectronRejection' in moduleName or 'MuonRejection' in moduleName: - if 'ByDeadECALElectronRejection' in moduleName: continue - process.miniAODTausTask.remove(getattr(process, moduleName)) - - # Instead add against-mu discriminants which are MiniAOD compatible - from RecoTauTag.RecoTau.hpsPFTauDiscriminationByMuonRejectionSimple_cff import hpsPFTauDiscriminationByMuonRejectionSimple + # Remove RecoTau producers which are not supported (yet?), i.e. against-e/mu discriminats + for moduleName in self.miniAODTausTask.moduleNames(): + if 'ElectronRejection' in moduleName or 'MuonRejection' in moduleName: + if 'ByDeadECALElectronRejection' in moduleName: continue + self.miniAODTausTask.remove(getattr(self.process, moduleName)) + + # Instead add against-mu discriminants which are MiniAOD compatible + from RecoTauTag.RecoTau.hpsPFTauDiscriminationByMuonRejectionSimple_cff import hpsPFTauDiscriminationByMuonRejectionSimple - process.hpsPFTauDiscriminationByMuonRejectionSimple = hpsPFTauDiscriminationByMuonRejectionSimple - process.miniAODTausTask.add(process.hpsPFTauDiscriminationByMuonRejectionSimple) + setattr(self.process,'hpsPFTauDiscriminationByMuonRejectionSimple'+self.postfix, + hpsPFTauDiscriminationByMuonRejectionSimple.clone( + PFTauProducer = "hpsPFTauProducer"+self.postfix)) + _tauIDAntiMuSimple = getattr(self.process,'hpsPFTauDiscriminationByMuonRejectionSimple'+self.postfix) + if self.runBoosted: + _tauIDAntiMuSimple.dRmuonMatch = 0.1 + self.miniAODTausTask.add(_tauIDAntiMuSimple) - ##### - # PAT part in the following - - process.tauGenJets.GenParticles = cms.InputTag("prunedGenParticles") - process.tauMatch.matched = cms.InputTag("prunedGenParticles") - - # Remove unsupported tauIDs - for name, src in process.patTaus.tauIDSources.parameters_().items(): - if name.find('againstElectron') > -1 or name.find('againstMuon') > -1: - if name.find('againstElectronDeadECAL') > -1: continue - delattr(process.patTaus.tauIDSources,name) - # Add MiniAOD specific ones - setattr(process.patTaus.tauIDSources,'againstMuonLooseSimple', - cms.PSet(inputTag = cms.InputTag('hpsPFTauDiscriminationByMuonRejectionSimple'), - provenanceConfigLabel = cms.string('IDWPdefinitions'), - idLabel = cms.string('ByLooseMuonRejectionSimple') + ##### + # PAT part in the following + + getattr(self.process,'tauGenJets'+self.postfix).GenParticles = "prunedGenParticles" + getattr(self.process,'tauMatch'+self.postfix).matched = "prunedGenParticles" + + # Remove unsupported tauIDs + _patTauProducer = getattr(self.process,'patTaus'+self.postfix) + for name,src in _patTauProducer.tauIDSources.parameters_().items(): + if name.find('againstElectron') > -1 or name.find('againstMuon') > -1: + if name.find('againstElectronDeadECAL') > -1: continue + delattr(_patTauProducer.tauIDSources,name) + # Add MiniAOD specific ones + setattr(_patTauProducer.tauIDSources,'againstMuonLooseSimple', + cms.PSet(inputTag = cms.InputTag('hpsPFTauDiscriminationByMuonRejectionSimple'+self.postfix), + provenanceConfigLabel = cms.string('IDWPdefinitions'), + idLabel = cms.string('ByLooseMuonRejectionSimple') )) - setattr(process.patTaus.tauIDSources,'againstMuonTightSimple', - cms.PSet(inputTag = cms.InputTag('hpsPFTauDiscriminationByMuonRejectionSimple'), - provenanceConfigLabel = cms.string('IDWPdefinitions'), - idLabel = cms.string('ByTightMuonRejectionSimple') + setattr(_patTauProducer.tauIDSources,'againstMuonTightSimple', + cms.PSet(inputTag = cms.InputTag('hpsPFTauDiscriminationByMuonRejectionSimple'+self.postfix), + provenanceConfigLabel = cms.string('IDWPdefinitions'), + idLabel = cms.string('ByTightMuonRejectionSimple') )) - # Run TauIDs (anti-e && deepTau) on top of selectedPatTaus - _updatedTauName = 'selectedPatTausNewIDs' - _noUpdatedTauName = 'selectedPatTausNoNewIDs' - import RecoTauTag.RecoTau.tools.runTauIdMVA as tauIdConfig - tauIdEmbedder = tauIdConfig.TauIDEmbedder( - process, debug = False, - updatedTauName = _updatedTauName, - toKeep = ['againstEle2018','deepTau2017v2p1'] - ) - tauIdEmbedder.runTauID() - setattr(process, _noUpdatedTauName, process.selectedPatTaus.clone()) - process.miniAODTausTask.add(getattr(process,_noUpdatedTauName)) - delattr(process, 'selectedPatTaus') - process.deepTau2017v2p1.taus = _noUpdatedTauName - process.patTauDiscriminationByElectronRejectionMVA62018Raw.PATTauProducer = _noUpdatedTauName - process.patTauDiscriminationByElectronRejectionMVA62018.PATTauProducer = _noUpdatedTauName - process.selectedPatTaus = getattr(process, _updatedTauName).clone( - src = _noUpdatedTauName - ) - process.newTauIDsTask = cms.Task( - process.rerunMvaIsolationTask, - process.selectedPatTaus - ) - process.miniAODTausTask.add(process.newTauIDsTask) - - #print '[adaptTauToMiniAODReReco]: Done!' + # Run TauIDs (anti-e && deepTau) on top of selectedPatTaus + _updatedTauName = 'selectedPatTausNewIDs'+self.postfix + _noUpdatedTauName = 'selectedPatTausNoNewIDs'+self.postfix + toKeep = ['againstEle2018'] + if not self.runBoosted: + toKeep.append('deepTau2017v2p1') + import RecoTauTag.RecoTau.tools.runTauIdMVA as tauIdConfig + tauIdEmbedder = tauIdConfig.TauIDEmbedder( + self.process, debug = False, + originalTauName = _noUpdatedTauName, + updatedTauName = _updatedTauName, + postfix = "MiniAODTaus"+self.postfix, + toKeep = toKeep + ) + tauIdEmbedder.runTauID() + setattr(self.process, _noUpdatedTauName, getattr(self.process,'selectedPatTaus'+self.postfix).clone()) + self.miniAODTausTask.add(getattr(self.process,_noUpdatedTauName)) + delattr(self.process, 'selectedPatTaus'+self.postfix) + setattr(self.process,'selectedPatTaus'+self.postfix,getattr(self.process, _updatedTauName).clone()) + delattr(self.process, _updatedTauName) + setattr(self.process,'newTauIDsTask'+self.postfix,cms.Task( + getattr(self.process,'rerunMvaIsolationTaskMiniAODTaus'+self.postfix), + getattr(self.process,'selectedPatTaus'+self.postfix) + )) + self.miniAODTausTask.add(getattr(self.process,'newTauIDsTask'+self.postfix)) + + #print '[adaptTauToMiniAODReReco]: Done!' -##### -def setOutputModule(mode=0): + ##### + def setOutputModule(self,mode=0): #mode = 0: store original MiniAOD and new selectedPatTaus #mode = 1: store original MiniAOD, new selectedPatTaus, and all PFTau products as in AOD (except of unsuported ones), plus a few additional collections (charged hadrons, pi zeros, combinatoric reco taus) - import Configuration.EventContent.EventContent_cff as evtContent - output = cms.OutputModule( - 'PoolOutputModule', - fileName=cms.untracked.string('miniAOD_TauReco.root'), - fastCloning=cms.untracked.bool(False), - dataset=cms.untracked.PSet( - dataTier=cms.untracked.string('MINIAODSIM'), - filterName=cms.untracked.string('') - ), - outputCommands = evtContent.MINIAODSIMEventContent.outputCommands, - SelectEvents=cms.untracked.PSet( - SelectEvents=cms.vstring('*',) + import Configuration.EventContent.EventContent_cff as evtContent + output = cms.OutputModule( + 'PoolOutputModule', + fileName=cms.untracked.string('miniAOD_TauReco.root'), + fastCloning=cms.untracked.bool(False), + dataset=cms.untracked.PSet( + dataTier=cms.untracked.string('MINIAODSIM'), + filterName=cms.untracked.string('') + ), + outputCommands = evtContent.MINIAODSIMEventContent.outputCommands, + SelectEvents=cms.untracked.PSet( + SelectEvents=cms.vstring('*',) ) - ) - output.outputCommands.append('keep *_selectedPatTaus_*_*') - if mode==1: - for prod in evtContent.RecoTauTagAOD.outputCommands: - if prod.find('ElectronRejection') > -1 and prod.find('DeadECAL') == -1: - continue - if prod.find('MuonRejection') > -1: - continue - output.outputCommands.append(prod) - output.outputCommands.append('keep *_hpsPFTauDiscriminationByMuonRejectionSimple_*_*') - output.outputCommands.append('keep *_combinatoricReco*_*_*') - output.outputCommands.append('keep *_ak4PFJetsRecoTauChargedHadrons_*_*') - output.outputCommands.append('keep *_ak4PFJetsLegacyHPSPiZeros_*_*') - output.outputCommands.append('keep *_patJetsPAT_*_*') - - return output + ) + output.outputCommands.append('keep *_selectedPatTaus'+self.postfix+'_*_*') + if mode==1: + import re + for prod in evtContent.RecoTauTagAOD.outputCommands: + if prod.find('ElectronRejection') > -1 and prod.find('DeadECAL') == -1: + continue + if prod.find('MuonRejection') > -1: + continue + if prod.find("_*_*")>-1: # products w/o instance + output.outputCommands.append(prod.replace("_*_*",self.postfix+"_*_*")) + else: # check if there are prods with instance + m = re.search(r'_[A-Za-z0-9]+_\*', prod) + if m!=None: + inst = m.group(0) + output.outputCommands.append(prod.replace(inst,self.postfix+inst)) + else: + print("Warning: \"%s\" do not match known name patterns; trying to keep w/o postfix" % prod) + output.outputCommands.append(prod) + + output.outputCommands.append('keep *_hpsPFTauDiscriminationByMuonRejectionSimple'+self.postfix+'_*_*') + output.outputCommands.append('keep *_combinatoricReco*_*_*') + output.outputCommands.append('keep *_ak4PFJetsRecoTauChargedHadrons'+self.postfix+'_*_*') + output.outputCommands.append('keep *_ak4PFJetsLegacyHPSPiZeros'+self.postfix+'_*_*') + output.outputCommands.append('keep *_patJetsPAT'+self.postfix+'_*_*') + output.outputCommands.append('keep *_boostedTauSeedsPAT'+self.postfix+'_*_*') + + return output ##### diff --git a/RecoTauTag/RecoTau/test/rerunTauRecoOnMiniAOD.py b/RecoTauTag/RecoTau/test/rerunTauRecoOnMiniAOD.py index eb75eb61aa3a9..70458aeea2662 100644 --- a/RecoTauTag/RecoTau/test/rerunTauRecoOnMiniAOD.py +++ b/RecoTauTag/RecoTau/test/rerunTauRecoOnMiniAOD.py @@ -13,9 +13,16 @@ maxEvents = 100 # maxEvents = -1 +# Set 'runBoosted' true to run boosted tau reconstuction +runBoosted = False + +# Add postfix to production sequences and modules; +# In case of boosted tau recostuction actual postfix is 'Boosted'+postfix +postfix = '' # If 'reclusterJets' set true a new collection of uncorrected ak4PFJets is # built to seed taus (as at RECO), otherwise standard slimmedJets are used +# Irrelavant in case of boosted tau reco reclusterJets = True # reclusterJets = False @@ -33,8 +40,11 @@ print('Running Tau reco&id with MiniAOD inputs:') print('\t Run type:', runType) print('\t Recluster jets:', reclusterJets) +print('\t Boosted tau reco:', runBoosted) print('\t Use Phase2 settings:', phase2) print('\t Output mode:', outMode) +if not postfix=="": + print('\t Postfix:', postfix) ##### from Configuration.Eras.Era_Run2_2018_cff import Run2_2018 @@ -80,10 +90,11 @@ exit(1) ##### -import RecoTauTag.Configuration.tools.adaptToRunAtMiniAOD as tauAtMiniTools +from RecoTauTag.Configuration.tools.adaptToRunAtMiniAOD import adaptToRunAtMiniAOD ##### -tauAtMiniTools.addTauReReco(process) +tauAtMiniTools = adaptToRunAtMiniAOD(process,runBoosted,postfix=postfix) +tauAtMiniTools.addTauReReco() ##### process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') @@ -115,11 +126,14 @@ process.out = cms.EndPath(process.output) ##### -tauAtMiniTools.adaptTauToMiniAODReReco(process, reclusterJets) +tauAtMiniTools.adaptTauToMiniAODReReco(reclusterJets) +process.p = cms.Path( + getattr(process,("miniAODTausSequence"+postfix if not runBoosted else "miniAODTausSequenceBoosted"+postfix)) +) if runType == 'data': from PhysicsTools.PatAlgos.tools.coreTools import runOnData - runOnData(process, names = ['Taus'], outputModules = []) + runOnData(process, names = ['Taus'], outputModules = [], postfix = (postfix if not runBoosted else 'Boosted'+postfix)) ##### process.load('FWCore.MessageService.MessageLogger_cfi')