Skip to content

Commit

Permalink
Streamline HLT L3 Muon reconstruction
Browse files Browse the repository at this point in the history
- execute either Inside-Out or Outside-In reconstruction first, resorting to the second pass only for candidates that require it
- Tracks filtered by quality using some of the same criteria as HLT Muon ID
- L1/L2 objects matched with bad L3 tracks are reused to seed the second reconstruction step
- Changes implemented via 2 procModifiers for IO first (default) and OI first reconstruction
- Implemented changes in SingleMu, TTbar, and ZMM workflows with .777 and .778 subfixes for IO and OI first reconstruction, respectively
- Change 2026 to Run4 in Phase 2 workflows
  • Loading branch information
Parsifal-2045 committed Dec 10, 2024
1 parent 047b04e commit 9d7592f
Show file tree
Hide file tree
Showing 10 changed files with 484 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

# this modifier is for enabling Phase 2 L3 Tracker Muon Outside-In first reconstruction
phase2L3MuonsOIFirst = cms.Modifier()
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,70 @@ def condition(self, fragment, stepList, key, hasHarvest):
upgradeWFs['ticl_v5_superclustering_mustache_pf'].step3 = {'--procModifiers': 'ticl_v5,ticl_superclustering_mustache_pf'}
upgradeWFs['ticl_v5_superclustering_mustache_pf'].step4 = {'--procModifiers': 'ticl_v5,ticl_superclustering_mustache_pf'}

# Improved L2 seeding from L1Tk Muons and L3 Tracker Muon Inside-Out reconstruction first (Phase-2 Muon default)
class UpgradeWorkflow_phase2L2AndL3Muons(UpgradeWorkflow):
def setup_(self, step, stepName, stepDict, k, properties):
if ('Digi' in step and 'NoHLT' not in step) or ('HLTOnly' in step):
stepDict[stepName][k] = merge([self.step2, stepDict[step][k]])
if 'RecoGlobal' in step:
stepDict[stepName][k] = merge([self.step3, stepDict[step][k]])
if 'HARVESTGlobal' in step:
stepDict[stepName][k] = merge([self.step4, stepDict[step][k]])
def condition(self, fragment, stepList, key, hasHarvest):
return (fragment=="ZMM_14" or 'SingleMu' in fragment or 'TTbar_14' in fragment) and 'Run4' in key

upgradeWFs['phase2L2AndL3Muons'] = UpgradeWorkflow_phase2L2AndL3Muons(
steps = [
'HLTOnly',
'DigiTrigger',
'RecoGlobal',
'HARVESTGlobal'
],
PU = [
'HLTOnly',
'DigiTrigger',
'RecoGlobal',
'HARVESTGlobal'
],
suffix = '_phase2L2AndL3MuonsIOFirst',
offset = 0.777,
)
upgradeWFs['phase2L2AndL3Muons'].step2 = {'--procModifiers':'phase2L2AndL3Muons'}
upgradeWFs['phase2L2AndL3Muons'].step3 = {'--procModifiers':'phase2L2AndL3Muons'}
upgradeWFs['phase2L2AndL3Muons'].step4 = {'--procModifiers':'phase2L2AndL3Muons'}

# Improved L2 seeding from L1Tk Muons and L3 Tracker Muon Outside-In reconstruction first
class UpgradeWorkflow_phase2L3MuonsOIFirst(UpgradeWorkflow):
def setup_(self, step, stepName, stepDict, k, properties):
if ('Digi' in step and 'NoHLT' not in step) or ('HLTOnly' in step):
stepDict[stepName][k] = merge([self.step2, stepDict[step][k]])
if 'RecoGlobal' in step:
stepDict[stepName][k] = merge([self.step3, stepDict[step][k]])
if 'HARVESTGlobal' in step:
stepDict[stepName][k] = merge([self.step4, stepDict[step][k]])
def condition(self, fragment, stepList, key, hasHarvest):
return (fragment=="ZMM_14" or 'SingleMu' in fragment or 'TTbar_14' in fragment) and 'Run4' in key

upgradeWFs['phase2L3MuonsOIFirst'] = UpgradeWorkflow_phase2L3MuonsOIFirst(
steps = [
'HLTOnly',
'DigiTrigger',
'RecoGlobal',
'HARVESTGlobal'
],
PU = [
'HLTOnly',
'DigiTrigger',
'RecoGlobal',
'HARVESTGlobal'
],
suffix = '_phase2L2AndL3MuonsOIFirst',
offset = 0.778,
)
upgradeWFs['phase2L3MuonsOIFirst'].step2 = {'--procModifiers':'phase2L2AndL3Muons,phase2L3MuonsOIFirst'}
upgradeWFs['phase2L3MuonsOIFirst'].step3 = {'--procModifiers':'phase2L2AndL3Muons,phase2L3MuonsOIFirst'}
upgradeWFs['phase2L3MuonsOIFirst'].step4 = {'--procModifiers':'phase2L2AndL3Muons,phase2L3MuonsOIFirst'}

# Track DNN workflows
class UpgradeWorkflow_trackdnn(UpgradeWorkflow):
def setup_(self, step, stepName, stepDict, k, properties):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,10 @@
nSeedsMax_E = cms.int32(20),
src = cms.InputTag("hltIter2Phase2L3FromL1TkMuonPixelSeeds")
)

from Configuration.ProcessModifiers.phase2L2AndL3Muons_cff import phase2L2AndL3Muons
from Configuration.ProcessModifiers.phase2L3MuonsOIFirst_cff import phase2L3MuonsOIFirst
(phase2L2AndL3Muons & phase2L3MuonsOIFirst).toModify(
hltIter2Phase2L3FromL1TkMuonPixelSeedsFiltered,
L1TkMu = "hltPhase2L3MuonFilter:L1TkMuToReuse"
)
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,10 @@
zErrorVetex = cms.double(0.2)
)
)

from Configuration.ProcessModifiers.phase2L2AndL3Muons_cff import phase2L2AndL3Muons
from Configuration.ProcessModifiers.phase2L3MuonsOIFirst_cff import phase2L3MuonsOIFirst
(phase2L2AndL3Muons & phase2L3MuonsOIFirst).toModify(
hltPhase2L3FromL1TkMuonPixelTracksTrackingRegions.RegionPSet,
input = "hltPhase2L3MuonFilter:L1TkMuToReuse"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import FWCore.ParameterSet.Config as cms

hltPhase2L3MuonFilter = cms.EDProducer("phase2HLTMuonSelectorForL3",
l1TkMuons = cms.InputTag("l1tTkMuonsGmt"),
l2MuonsUpdVtx = cms.InputTag("hltL2MuonsFromL1TkMuon:UpdatedAtVtx"),
l3Tracks = cms.InputTag("hltIter2Phase2L3FromL1TkMuonMerged"),
IOFirst = cms.bool(True),
matchingDr = cms.double(0.02),
applyL3Filters = cms.bool(True),
MinNhits = cms.int32(1),
MaxNormalizedChi2 = cms.double(5.0),
MinNhitsMuons = cms.int32(0),
MinNhitsPixel = cms.int32(1),
MinNhitsTracker = cms.int32(6),
MaxPtDifference = cms.double(999.0),
)

from Configuration.ProcessModifiers.phase2L2AndL3Muons_cff import phase2L2AndL3Muons
from Configuration.ProcessModifiers.phase2L3MuonsOIFirst_cff import phase2L3MuonsOIFirst
(phase2L2AndL3Muons & phase2L3MuonsOIFirst).toModify(
hltPhase2L3MuonFilter,
l3Tracks = "hltPhase2L3OIMuonTrackSelectionHighPurity",
IOFirst = False,
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,47 @@
MinFound = cms.int32(3),
MinPT = cms.double(0.05),
ShareFrac = cms.double(0.19),
TrackProducers = cms.VInputTag("hltPhase2L3OIMuonTrackSelectionHighPurity", "hltIter2Phase2L3FromL1TkMuonMerged"),
TrackProducers = cms.VInputTag(
"hltPhase2L3OIMuonTrackSelectionHighPurity",
"hltIter2Phase2L3FromL1TkMuonMerged",
),
allowFirstHitShare = cms.bool(True),
copyExtras = cms.untracked.bool(True),
copyMVA = cms.bool(False),
hasSelector = cms.vint32(0, 0),
indivShareFrac = cms.vdouble(1.0, 1.0),
newQuality = cms.string('confirmed'),
selectedTrackQuals = cms.VInputTag("hltPhase2L3OIMuonTrackSelectionHighPurity", "hltIter2Phase2L3FromL1TkMuonMerged"),
setsToMerge = cms.VPSet(cms.PSet(
pQual = cms.bool(False),
tLists = cms.vint32(0, 1)
)),
trackAlgoPriorityOrder = cms.string('hltESPTrackAlgoPriorityOrder'),
writeOnlyTrkQuals = cms.bool(False)
newQuality = cms.string("confirmed"),
selectedTrackQuals = cms.VInputTag(
"hltPhase2L3OIMuonTrackSelectionHighPurity",
"hltIter2Phase2L3FromL1TkMuonMerged",
),
setsToMerge = cms.VPSet(cms.PSet(pQual = cms.bool(False), tLists = cms.vint32(0, 1))),
trackAlgoPriorityOrder = cms.string("hltESPTrackAlgoPriorityOrder"),
writeOnlyTrkQuals = cms.bool(False),
)

from Configuration.ProcessModifiers.phase2L2AndL3Muons_cff import phase2L2AndL3Muons
phase2L2AndL3Muons.toModify(
hltPhase2L3MuonMerged,
TrackProducers = cms.VInputTag(
"hltPhase2L3OIMuonTrackSelectionHighPurity",
"hltPhase2L3MuonFilter:L3IOTracksFiltered",
),
selectedTrackQuals = cms.VInputTag(
"hltPhase2L3OIMuonTrackSelectionHighPurity",
"hltPhase2L3MuonFilter:L3IOTracksFiltered",
),
)

from Configuration.ProcessModifiers.phase2L3MuonsOIFirst_cff import phase2L3MuonsOIFirst
(phase2L2AndL3Muons & phase2L3MuonsOIFirst).toModify(
hltPhase2L3MuonMerged,
TrackProducers = cms.VInputTag(
"hltPhase2L3MuonFilter:L3OITracksFiltered",
"hltIter2Phase2L3FromL1TkMuonMerged",
),
selectedTrackQuals = cms.VInputTag(
"hltPhase2L3MuonFilter:L3OITracksFiltered",
"hltIter2Phase2L3FromL1TkMuonMerged",
),
)
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,15 @@
tsosDiff1 = cms.double(0.2),
tsosDiff2 = cms.double(0.02)
)

from Configuration.ProcessModifiers.phase2L2AndL3Muons_cff import phase2L2AndL3Muons
phase2L2AndL3Muons.toModify(
hltPhase2L3OISeedsFromL2Muons,
src = "hltPhase2L3MuonFilter:L2MuToReuse"
)

from Configuration.ProcessModifiers.phase2L3MuonsOIFirst_cff import phase2L3MuonsOIFirst
(phase2L2AndL3Muons & phase2L3MuonsOIFirst).toModify(
hltPhase2L3OISeedsFromL2Muons,
src ="hltL2MuonsFromL1TkMuon:UpdatedAtVtx"
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,44 @@
from ..sequences.HLTPhase2L3MuonsSequence_cfi import *
from ..sequences.HLTPhase2L3OISequence_cfi import *

HLTMuonsSequence = cms.Sequence(HLTL2MuonsFromL1TkSequence+HLTPhase2L3OISequence+HLTPhase2L3FromL1TkSequence+HLTIter0Phase2L3FromL1TkSequence+HLTIter2Phase2L3FromL1TkSequence+HLTPhase2L3MuonsSequence)
HLTMuonsSequence = cms.Sequence(
HLTL2MuonsFromL1TkSequence
+ HLTPhase2L3OISequence
+ HLTPhase2L3FromL1TkSequence
+ HLTIter0Phase2L3FromL1TkSequence
+ HLTIter2Phase2L3FromL1TkSequence
+ HLTPhase2L3MuonsSequence
)

from ..modules.hltPhase2L3MuonFilter_cfi import *

# The IO first HLT Muons sequence
Phase2HLTMuonsSequenceIOFirst = cms.Sequence(
HLTL2MuonsFromL1TkSequence
+ HLTPhase2L3FromL1TkSequence
+ HLTIter0Phase2L3FromL1TkSequence
+ HLTIter2Phase2L3FromL1TkSequence
+ hltPhase2L3MuonFilter
+ HLTPhase2L3OISequence
+ HLTPhase2L3MuonsSequence
)
# The OI first HLT Muons sequence
Phase2HLTMuonsSequenceOIFirst = cms.Sequence(
HLTL2MuonsFromL1TkSequence
+ HLTPhase2L3OISequence
+ hltPhase2L3MuonFilter
+ HLTPhase2L3FromL1TkSequence
+ HLTIter0Phase2L3FromL1TkSequence
+ HLTIter2Phase2L3FromL1TkSequence
+ HLTPhase2L3MuonsSequence
)

from Configuration.ProcessModifiers.phase2L2AndL3Muons_cff import phase2L2AndL3Muons

phase2L2AndL3Muons.toReplaceWith(HLTMuonsSequence, Phase2HLTMuonsSequenceIOFirst)

from Configuration.ProcessModifiers.phase2L3MuonsOIFirst_cff import phase2L3MuonsOIFirst

(phase2L2AndL3Muons & phase2L3MuonsOIFirst).toReplaceWith(
HLTMuonsSequence, Phase2HLTMuonsSequenceOIFirst
)
81 changes: 81 additions & 0 deletions RecoMuon/L3TrackFinder/interface/phase2HLTMuonSelectorForL3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#ifndef RecoMuon_L3TrackFinder_phase2HLTMuonSelectorForL3_H
#define RecoMuon_L3TrackFinder_phase2HLTMuonSelectorForL3_H

/** \class phase2HLTMuonSelectorForL3
*
* Phase-2 L3 selector for Muons
* This module allows to choose whether to perform
* Inside-Out or Outside-In reconstruction first for L3 Muons,
* performing the second pass only on candidates that were not
* reconstructed or whose quality was not good enough. Required
* quality criteria are configurable, the default parameters
* match the requests of HLT Muon ID.
* When Inside-Out reconstruction is performed first, the resulting
* L3 Tracks are filtered and geometrically matched with L2
* Standalone Muons. If either the match is unsuccessful, or
* the L3 track is not of good-enough quality, the associated
* Standalone Muon will be re-used to seed the Outside-In step.
* The Outside-In first approach follows a similar logic by
* matching the L3 tracks directly with L1 Tracker Muons.
* Then, when either the match fails or the track is not of
* good-enough quality, the L1 Tracker Muon is re-used to seed
* the Inside-Out reconstruction.
*
* \author Luca Ferragina (INFN BO), 2024
*/

#include "FWCore/Framework/interface/stream/EDProducer.h"
#include "FWCore/Framework/interface/ESHandle.h"
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/Framework/interface/ConsumesCollector.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/Utilities/interface/ESGetToken.h"
#include "FWCore/Utilities/interface/InputTag.h"

#include "DataFormats/L1TMuonPhase2/interface/TrackerMuon.h"
#include "DataFormats/MuonReco/interface/MuonFwd.h"
#include "DataFormats/MuonSeed/interface/L2MuonTrajectorySeedCollection.h"
#include "DataFormats/TrackReco/interface/Track.h"
#include "DataFormats/TrackReco/interface/TrackFwd.h"

namespace edm {
class ParameterSet;
class Event;
class EventSetup;
} // End namespace edm

class phase2HLTMuonSelectorForL3 : public edm::stream::EDProducer<> {
public:
// Constructor
phase2HLTMuonSelectorForL3(const edm::ParameterSet&);

// Destructor
~phase2HLTMuonSelectorForL3() override = default;

// Default values
static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);

// Select objects to be reused
void produce(edm::Event&, const edm::EventSetup&) override;

private:
const edm::EDGetTokenT<l1t::TrackerMuonCollection> l1TkMuCollToken_;
const edm::EDGetTokenT<reco::TrackCollection> l2MuCollectionToken_;
const edm::EDGetTokenT<reco::TrackCollection> l3TrackCollectionToken_;

const bool IOFirst_;
const double matchingDr_;
const bool applyL3Filters_;
const double maxNormalizedChi2_, maxPtDifference_;
const int minNhits_, minNhitsMuons_, minNhitsPixel_, minNhitsTracker_;

// Check L3 inner track quality parameters
const bool rejectL3Track(l1t::TrackerMuonRef l1TkMuRef, reco::TrackRef l3TrackRef) const;
};

#endif
Loading

0 comments on commit 9d7592f

Please sign in to comment.