diff --git a/Configuration/ProcessModifiers/python/trackingIters01_cff.py b/Configuration/ProcessModifiers/python/trackingIters01_cff.py
new file mode 100644
index 0000000000000..9f7506d27b51c
--- /dev/null
+++ b/Configuration/ProcessModifiers/python/trackingIters01_cff.py
@@ -0,0 +1,4 @@
+import FWCore.ParameterSet.Config as cms
+
+# This modifier sets the iterative tracking to use a minimal set of iterations, first two
+trackingIters01 = cms.Modifier()
diff --git a/Configuration/ProcessModifiers/python/trackingLST_cff.py b/Configuration/ProcessModifiers/python/trackingLST_cff.py
new file mode 100644
index 0000000000000..ae1dd83e20b0b
--- /dev/null
+++ b/Configuration/ProcessModifiers/python/trackingLST_cff.py
@@ -0,0 +1,5 @@
+import FWCore.ParameterSet.Config as cms
+
+# This modifier sets the LST (Phase-2 line segment tracking) used for track building
+trackingLST = cms.Modifier()
+
diff --git a/Configuration/PyReleaseValidation/README.md b/Configuration/PyReleaseValidation/README.md
index a3c4177c0fcb8..a114e81d7146c 100644
--- a/Configuration/PyReleaseValidation/README.md
+++ b/Configuration/PyReleaseValidation/README.md
@@ -65,6 +65,8 @@ The offsets currently in use are:
* 0.7: trackingMkFit modifier
* 0.701: DisplacedRegionalStep tracking iteration for Run-3
* 0.702: trackingMkFit modifier for Phase-2 (initialStep only)
+* 0.703: LST tracking (Phase-2 only), initialStep+HighPtTripletStep only, on CPU
+* 0.704: LST tracking (Phase-2 only), initialStep+HighPtTripletStep only, on GPU
* 0.75: HLT phase-2 timing menu
* 0.751: HLT phase-2 timing menu Alpaka variant
* 0.752: HLT phase-2 timing menu ticl_v5 variant
diff --git a/Configuration/PyReleaseValidation/python/relval_Run4.py b/Configuration/PyReleaseValidation/python/relval_Run4.py
index 3b866ca55c000..95f75dcee7a6a 100644
--- a/Configuration/PyReleaseValidation/python/relval_Run4.py
+++ b/Configuration/PyReleaseValidation/python/relval_Run4.py
@@ -36,6 +36,9 @@
numWFIB.extend([31234.0]) #Run4D114
numWFIB.extend([32034.0]) #Run4D115
+# Temporary placement for LST workflow to workaround PR conflicts - to be formatted and placed in an upcoming PR
+numWFIB.extend([24834.703]) #Run4D98 LST tracking (initialStep+HighPtTripletStep only)
+
#Additional sample for short matrix and IB
#Default Phase-2 Det NoPU
numWFIB.extend([prefixDet+34.911]) #DD4hep XML
diff --git a/Configuration/PyReleaseValidation/python/relval_gpu.py b/Configuration/PyReleaseValidation/python/relval_gpu.py
index f71ade3f646f1..e70d877c1daaa 100644
--- a/Configuration/PyReleaseValidation/python/relval_gpu.py
+++ b/Configuration/PyReleaseValidation/python/relval_gpu.py
@@ -72,6 +72,8 @@
# Run4, Alpaka-based noPU
29634.402, 29634.403, 29634.404, 29634.406,
29661.402,
+ # Run4, Alpaka-based noPU GPU LST tracking D98
+ 24834.704,
# Run4, Alpaka-based PU
29834.402, 29834.403, 29834.404
diff --git a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py
index fbfd6b28801aa..31543ebd3b380 100644
--- a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py
+++ b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py
@@ -490,6 +490,56 @@ def condition_(self, fragment, stepList, key, hasHarvest):
'--procModifiers': 'trackingMkFitCommon,trackingMkFitInitialStep'
}
+# LST on CPU, initialStep+highPtTripletStep-only tracking-only
+class UpgradeWorkflow_lstOnCPUIters01TrackingOnly(UpgradeWorkflowTracking):
+ def setup__(self, step, stepName, stepDict, k, properties):
+ if 'Reco' in step: stepDict[stepName][k] = merge([self.step3, stepDict[step][k]])
+ elif 'HARVEST' in step: stepDict[stepName][k] = merge([{'-s': 'HARVESTING:@trackingOnlyValidation+@trackingOnlyDQM'}, stepDict[step][k]])
+ elif 'ALCA' in step: stepDict[stepName][k] = None
+ def condition_(self, fragment, stepList, key, hasHarvest):
+ return ('Run4' in key)
+upgradeWFs['lstOnCPUIters01TrackingOnly'] = UpgradeWorkflow_lstOnCPUIters01TrackingOnly(
+ steps = [
+ 'RecoGlobal',
+ 'HARVESTGlobal',
+ # Add ALCA steps explicitly, so that they can be properly removed
+ 'ALCA',
+ 'ALCAPhase2'
+ ],
+ PU = [],
+ suffix = '_lstOnCPUIters01TrackingOnly',
+ offset = 0.703,
+)
+upgradeWFs['lstOnCPUIters01TrackingOnly'].step3 = upgradeWFs['trackingOnly'].step3 | {
+ '--procModifiers': 'trackingIters01,trackingLST',
+ '--accelerators' : 'cpu'
+}
+
+# LST on GPU, initialStep+highPtTripletStep-only tracking-only
+class UpgradeWorkflow_lstOnGPUIters01TrackingOnly(UpgradeWorkflowTracking):
+ def setup__(self, step, stepName, stepDict, k, properties):
+ if 'Reco' in step: stepDict[stepName][k] = merge([self.step3, stepDict[step][k]])
+ elif 'HARVEST' in step: stepDict[stepName][k] = merge([{'-s': 'HARVESTING:@trackingOnlyValidation+@trackingOnlyDQM'}, stepDict[step][k]])
+ elif 'ALCA' in step: stepDict[stepName][k] = None
+ def condition_(self, fragment, stepList, key, hasHarvest):
+ return ('Run4' in key)
+upgradeWFs['lstOnGPUIters01TrackingOnly'] = UpgradeWorkflow_lstOnGPUIters01TrackingOnly(
+ steps = [
+ 'RecoGlobal',
+ 'HARVESTGlobal',
+ # Add ALCA steps explicitly, so that they can be properly removed
+ 'ALCA',
+ 'ALCAPhase2'
+ ],
+ PU = [],
+ suffix = '_lstOnGPUIters01TrackingOnly',
+ offset = 0.704,
+)
+upgradeWFs['lstOnGPUIters01TrackingOnly'].step3 = upgradeWFs['trackingOnly'].step3 | {
+ '--procModifiers': 'trackingIters01,trackingLST',
+ '--accelerators' : 'gpu-*'
+}
+
#DeepCore seeding for JetCore iteration workflow
class UpgradeWorkflow_seedingDeepCore(UpgradeWorkflow):
def setup_(self, step, stepName, stepDict, k, properties):
diff --git a/RecoTracker/ConversionSeedGenerators/python/ConversionStep_cff.py b/RecoTracker/ConversionSeedGenerators/python/ConversionStep_cff.py
index 256432c1180c8..6d44990855324 100644
--- a/RecoTracker/ConversionSeedGenerators/python/ConversionStep_cff.py
+++ b/RecoTracker/ConversionSeedGenerators/python/ConversionStep_cff.py
@@ -33,6 +33,16 @@
oldClusterRemovalInfo = 'detachedQuadStepClusters',
overrideTrkQuals = 'detachedQuadStepSelector:detachedQuadStepTrk'
))
+from Configuration.ProcessModifiers.trackingIters01_cff import trackingIters01
+trackingIters01.toModify(convClusters,
+ trajectories = "highPtTripletStepTracks",
+ oldClusterRemovalInfo = "highPtTripletStepClusters",
+ overrideTrkQuals = "highPtTripletStepSelector:highPtTripletStep"
+)
+from Configuration.ProcessModifiers.trackingLST_cff import trackingLST
+(trackingIters01 & trackingPhase2PU140 & trackingLST).toModify(convClusters,
+ overrideTrkQuals = ""
+)
_convLayerPairsStripOnlyLayers = ['TIB1+TID1_pos',
'TIB1+TID1_neg',
diff --git a/RecoTracker/FinalTrackSelectors/python/MergeTrackCollections_cff.py b/RecoTracker/FinalTrackSelectors/python/MergeTrackCollections_cff.py
index 907e3126a5cd7..d5256c19a1756 100644
--- a/RecoTracker/FinalTrackSelectors/python/MergeTrackCollections_cff.py
+++ b/RecoTracker/FinalTrackSelectors/python/MergeTrackCollections_cff.py
@@ -17,6 +17,8 @@
ttrhBuilderName = "WithAngleAndTemplate",
chi2EstimatorName = "duplicateTrackCandidatesChi2Est"
)
+from Configuration.ProcessModifiers.trackingIters01_cff import trackingIters01
+trackingIters01.toModify(duplicateTrackCandidates, source = "earlyGeneralTracks")
import RecoTracker.TrackProducer.TrackProducer_cfi
mergedDuplicateTracks = RecoTracker.TrackProducer.TrackProducer_cfi.TrackProducer.clone(
@@ -44,6 +46,10 @@
candidateSource = "duplicateTrackCandidates:candidates",
candidateComponents = "duplicateTrackCandidates:candidateMap"
)
+trackingIters01.toModify(generalTracks,
+ originalSource = "earlyGeneralTracks",
+ originalMVAVals = "earlyGeneralTracks:MVAValues"
+)
generalTracksTask = cms.Task(
duplicateTrackCandidates,
diff --git a/RecoTracker/FinalTrackSelectors/python/earlyGeneralTracks_cfi.py b/RecoTracker/FinalTrackSelectors/python/earlyGeneralTracks_cfi.py
index 525640861f3ea..d03744c8bdfe5 100644
--- a/RecoTracker/FinalTrackSelectors/python/earlyGeneralTracks_cfi.py
+++ b/RecoTracker/FinalTrackSelectors/python/earlyGeneralTracks_cfi.py
@@ -109,6 +109,16 @@ def _extend_displacedGeneral(x):
makeReKeyedSeeds = cms.untracked.bool(False)
)
)
+from Configuration.ProcessModifiers.trackingIters01_cff import trackingIters01
+trackingIters01.toModify(earlyGeneralTracks,
+ TrackProducers = ['initialStepTracks', 'highPtTripletStepTracks'],
+ hasSelector = [1,1],
+ indivShareFrac = [1,0.16],
+ selectedTrackQuals = ['initialStepSelector:initialStep',
+ 'highPtTripletStepSelector:highPtTripletStep'
+ ],
+ setsToMerge = {0: dict(tLists = [0,1])}
+)
from Configuration.ProcessModifiers.vectorHits_cff import vectorHits
def _extend_pixelLess(x):
x.TrackProducers += ['pixelLessStepTracks']
@@ -118,3 +128,13 @@ def _extend_pixelLess(x):
x.setsToMerge[0].tLists += [6]
(trackingPhase2PU140 & vectorHits).toModify(earlyGeneralTracks, _extend_pixelLess)
+from Configuration.ProcessModifiers.trackingLST_cff import trackingLST
+(trackingPhase2PU140 & trackingLST).toModify(earlyGeneralTracks,
+ TrackProducers = ['highPtTripletStepLSTpTracks', 'highPtTripletStepLSTT5Tracks'],
+ hasSelector = [1,0],
+ indivShareFrac = [0.1,0.1],
+ selectedTrackQuals = ['highPtTripletStepSelector:highPtTripletStep',
+ 'highPtTripletStepSelectorLSTT5:highPtTripletStepLSTT5'
+ ],
+ setsToMerge = {0: dict(tLists = [0,1])}
+)
diff --git a/RecoTracker/IterativeTracking/python/HighPtTripletStep_cff.py b/RecoTracker/IterativeTracking/python/HighPtTripletStep_cff.py
index 8f35832cc75d5..7c1dab22afd58 100644
--- a/RecoTracker/IterativeTracking/python/HighPtTripletStep_cff.py
+++ b/RecoTracker/IterativeTracking/python/HighPtTripletStep_cff.py
@@ -259,6 +259,10 @@
phase2clustersToSkip = 'highPtTripletStepClusters'
)
+from Configuration.ProcessModifiers.trackingLST_cff import trackingLST
+from RecoTracker.LST.lstOutputConverter_cfi import lstOutputConverter as _lstOutputConverter
+(trackingPhase2PU140 & trackingLST).toReplaceWith(highPtTripletStepTrackCandidates, _lstOutputConverter.clone())
+
#For FastSim phase1 tracking
import FastSimulation.Tracking.TrackCandidateProducer_cfi
_fastSim_highPtTripletStepTrackCandidates = FastSimulation.Tracking.TrackCandidateProducer_cfi.trackCandidateProducer.clone(
@@ -280,6 +284,25 @@
from Configuration.Eras.Modifier_phase2_timing_layer_cff import phase2_timing_layer
phase2_timing_layer.toModify(highPtTripletStepTracks, TrajectoryInEvent = True)
+highPtTripletStepLSTpTracks = highPtTripletStepTracks.clone(
+ src = 'highPtTripletStepTrackCandidates:pTCsLST'
+)
+highPtTripletStepLSTT5Tracks = highPtTripletStepTracks.clone(
+ src = 'highPtTripletStepTrackCandidates:t5TCsLST'
+)
+_highPtTripletStepTracks_LST = RecoTracker.FinalTrackSelectors.trackListMerger_cfi.trackListMerger.clone(
+ TrackProducers = ['highPtTripletStepLSTpTracks',
+ 'highPtTripletStepLSTT5Tracks'],
+ hasSelector = [1,0],
+ indivShareFrac = [0.1,0.1],
+ selectedTrackQuals = ['highPtTripletStepSelector:highPtTripletStep',
+ 'highPtTripletStepSelectorLSTT5:highPtTripletStepLSTT5'],
+ copyExtras = True,
+ copyMVA = False,
+ setsToMerge = [cms.PSet( tLists=cms.vint32(0,1), pQual=cms.bool(True) )]
+)
+(trackingPhase2PU140 & trackingLST).toReplaceWith(highPtTripletStepTracks, _highPtTripletStepTracks_LST)
+
# Final selection
from RecoTracker.FinalTrackSelectors.TrackMVAClassifierPrompt_cfi import *
highPtTripletStep = TrackMVAClassifierPrompt.clone(
@@ -357,6 +380,28 @@
from Configuration.ProcessModifiers.vectorHits_cff import vectorHits
vectorHits.toModify(highPtTripletStepSelector.trackSelectors[2], minNumberLayers = 3, minNumber3DLayers = 3, d0_par1 = ( 0.5, 4.0 ), dz_par1 = ( 0.6, 4.0 ))
+(trackingPhase2PU140 & trackingLST).toModify(highPtTripletStepSelector, src = 'highPtTripletStepLSTpTracks')
+# Passthrough selector to satisfy the TrackListMerger requirement for selector values
+highPtTripletStepSelectorLSTT5 = RecoTracker.FinalTrackSelectors.multiTrackSelector_cfi.multiTrackSelector.clone(
+ src = 'highPtTripletStepLSTT5Tracks',
+ trackSelectors = [
+ RecoTracker.FinalTrackSelectors.multiTrackSelector_cfi.looseMTS.clone(
+ name = 'highPtTripletStepLSTT5Loose',
+ minHitsToBypassChecks = 0
+ ), #end of pset
+ RecoTracker.FinalTrackSelectors.multiTrackSelector_cfi.tightMTS.clone(
+ name = 'highPtTripletStepLSTT5Tight',
+ preFilterName = 'highPtTripletStepLSTT5Loose',
+ minHitsToBypassChecks = 0
+ ),
+ RecoTracker.FinalTrackSelectors.multiTrackSelector_cfi.highpurityMTS.clone(
+ name = 'highPtTripletStepLSTT5',
+ preFilterName = 'highPtTripletStepLSTT5Tight',
+ minHitsToBypassChecks = 0
+ ),
+ ] #end of vpset
+) #end of clone
+
# Final sequence
HighPtTripletStepTask = cms.Task(highPtTripletStepClusters,
highPtTripletStepSeedLayers,
@@ -378,6 +423,17 @@
_HighPtTripletStep_Phase2PU140 = cms.Sequence(_HighPtTripletStepTask_Phase2PU140)
trackingPhase2PU140.toReplaceWith(HighPtTripletStepTask, _HighPtTripletStepTask_Phase2PU140)
+_HighPtTripletStepTask_LST = HighPtTripletStepTask.copy()
+from RecoLocalTracker.Phase2TrackerRecHits.Phase2TrackerRecHits_cfi import siPhase2RecHits
+from RecoTracker.LST.lstSeedTracks_cff import lstInitialStepSeedTracks,lstHighPtTripletStepSeedTracks
+from RecoTracker.LST.lstPixelSeedInputProducer_cfi import lstPixelSeedInputProducer
+from RecoTracker.LST.lstPhase2OTHitsInputProducer_cfi import lstPhase2OTHitsInputProducer
+from RecoTracker.LST.lstProducerTask_cff import *
+
+_HighPtTripletStepTask_LST.add(siPhase2RecHits, lstInitialStepSeedTracks, lstHighPtTripletStepSeedTracks, lstPixelSeedInputProducer, lstPhase2OTHitsInputProducer,
+ lstProducerTask, highPtTripletStepLSTpTracks, highPtTripletStepLSTT5Tracks, highPtTripletStepSelectorLSTT5)
+(trackingPhase2PU140 & trackingLST).toReplaceWith(HighPtTripletStepTask, _HighPtTripletStepTask_LST)
+
# fast tracking mask producer
from FastSimulation.Tracking.FastTrackerRecHitMaskProducer_cfi import maskProducerFromClusterRemover
highPtTripletStepMasks = maskProducerFromClusterRemover(highPtTripletStepClusters)
diff --git a/RecoTracker/IterativeTracking/python/LowPtQuadStep_cff.py b/RecoTracker/IterativeTracking/python/LowPtQuadStep_cff.py
index 84d87c18c883a..40a1161b15f13 100644
--- a/RecoTracker/IterativeTracking/python/LowPtQuadStep_cff.py
+++ b/RecoTracker/IterativeTracking/python/LowPtQuadStep_cff.py
@@ -14,6 +14,9 @@
for _eraName, _postfix, _era in _cfg.nonDefaultEras():
_era.toReplaceWith(lowPtQuadStepClusters, _cfg.clusterRemoverForIter('LowPtQuadStep', _eraName, _postfix))
+from Configuration.ProcessModifiers.trackingLST_cff import trackingLST
+# with LST, this is the first iteration with proper cluster masking
+trackingLST.toModify(lowPtQuadStepClusters, oldClusterRemovalInfo = "")
# SEEDING LAYERS
import RecoTracker.TkSeedingLayers.PixelLayerQuadruplets_cfi
diff --git a/RecoTracker/IterativeTracking/python/iterativeTkConfig.py b/RecoTracker/IterativeTracking/python/iterativeTkConfig.py
index d409cae8d3340..8d9fd5fb45824 100644
--- a/RecoTracker/IterativeTracking/python/iterativeTkConfig.py
+++ b/RecoTracker/IterativeTracking/python/iterativeTkConfig.py
@@ -53,16 +53,20 @@
_iterations_trackingPhase1.append('JetCoreRegionalStep')
-_iterations_trackingPhase2PU140 = [
+_iterations_trackingPhase2PU140_VS = cms.PSet(names = cms.vstring(
"InitialStep",
"HighPtTripletStep",
"LowPtQuadStep",
"LowPtTripletStep",
"DetachedQuadStep",
"PixelPairStep",
-]
+))
from Configuration.ProcessModifiers.vectorHits_cff import vectorHits
-vectorHits.toModify(_iterations_trackingPhase2PU140, func=lambda x: x.append('PixelLessStep'))
+vectorHits.toModify(_iterations_trackingPhase2PU140_VS.names, func=lambda x: x.append('PixelLessStep'))
+from Configuration.ProcessModifiers.trackingIters01_cff import trackingIters01
+trackingIters01.toModify(_iterations_trackingPhase2PU140_VS, names = ["InitialStep", "HighPtTripletStep"])
+# apply all procModifiers before this
+_iterations_trackingPhase2PU140 = _iterations_trackingPhase2PU140_VS.names.value()
from Configuration.ProcessModifiers.jetCoreInPhase2_cff import jetCoreInPhase2
jetCoreInPhase2.toModify(_iterations_trackingPhase2PU140, func=lambda x: x.append('JetCoreRegionalStep'))
@@ -76,10 +80,13 @@
"MuonSeededStepOutIn",
]
#Phase2
-_iterations_muonSeeded_trackingPhase2PU140 = [
+_iterations_muonSeeded_trackingPhase2PU140_VS = cms.PSet(names = cms.vstring(
"MuonSeededStepInOut",
"MuonSeededStepOutIn",
-]
+))
+trackingIters01.toModify(_iterations_muonSeeded_trackingPhase2PU140_VS, names = [])
+_iterations_muonSeeded_trackingPhase2PU140 = _iterations_muonSeeded_trackingPhase2PU140_VS.names.value()
+
_multipleSeedProducers = {
"MixedTripletStep": ["A", "B"],
"TobTecStep": ["Pair", "Tripl"],
diff --git a/RecoTracker/LST/BuildFile.xml b/RecoTracker/LST/BuildFile.xml
new file mode 100644
index 0000000000000..07a6ae1d26eaf
--- /dev/null
+++ b/RecoTracker/LST/BuildFile.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/RecoTracker/LST/interface/LSTOutput.h b/RecoTracker/LST/interface/LSTOutput.h
new file mode 100644
index 0000000000000..f50000b83cf21
--- /dev/null
+++ b/RecoTracker/LST/interface/LSTOutput.h
@@ -0,0 +1,40 @@
+#ifndef RecoTracker_LST_interface_LSTOutput_h
+#define RecoTracker_LST_interface_LSTOutput_h
+
+#include
+#include
+
+#include "RecoTracker/LSTCore/interface/Common.h"
+
+class LSTOutput {
+public:
+ LSTOutput() = default;
+ LSTOutput(std::vector> const hitIdx,
+ std::vector const len,
+ std::vector const seedIdx,
+ std::vector const trackCandidateType)
+ : hitIdx_(std::move(hitIdx)),
+ len_(std::move(len)),
+ seedIdx_(std::move(seedIdx)),
+ trackCandidateType_(std::move(trackCandidateType)) {}
+
+ using LSTTCType = lst::LSTObjType;
+
+ // Hit indices of each of the LST track candidates.
+ std::vector> const& hitIdx() const { return hitIdx_; }
+ // Number of hits of each of the LST track candidates.
+ std::vector const& len() const { return len_; }
+ // Index of the pixel track associated to each of the LST track candidates.
+ // If not associated to a pixel track, which is the case for T5s, it defaults to -1.
+ std::vector const& seedIdx() const { return seedIdx_; }
+ // LSTTCType from RecoTracker/LSTCore/interface/Common.h
+ std::vector const& trackCandidateType() const { return trackCandidateType_; }
+
+private:
+ std::vector> hitIdx_;
+ std::vector len_;
+ std::vector seedIdx_;
+ std::vector trackCandidateType_;
+};
+
+#endif
diff --git a/RecoTracker/LST/interface/LSTPhase2OTHitsInput.h b/RecoTracker/LST/interface/LSTPhase2OTHitsInput.h
new file mode 100644
index 0000000000000..00fd77846c4c3
--- /dev/null
+++ b/RecoTracker/LST/interface/LSTPhase2OTHitsInput.h
@@ -0,0 +1,33 @@
+#ifndef RecoTracker_LST_interface_LSTPhase2OTHitsInput_h
+#define RecoTracker_LST_interface_LSTPhase2OTHitsInput_h
+
+#include
+#include
+
+#include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h"
+
+class LSTPhase2OTHitsInput {
+public:
+ LSTPhase2OTHitsInput() = default;
+ LSTPhase2OTHitsInput(std::vector const detId,
+ std::vector const x,
+ std::vector const y,
+ std::vector const z,
+ std::vector const hits)
+ : detId_(std::move(detId)), x_(std::move(x)), y_(std::move(y)), z_(std::move(z)), hits_(std::move(hits)) {}
+
+ std::vector const& detId() const { return detId_; }
+ std::vector const& x() const { return x_; }
+ std::vector const& y() const { return y_; }
+ std::vector const& z() const { return z_; }
+ std::vector const& hits() const { return hits_; }
+
+private:
+ std::vector detId_;
+ std::vector x_;
+ std::vector y_;
+ std::vector z_;
+ std::vector hits_;
+};
+
+#endif
diff --git a/RecoTracker/LST/interface/LSTPixelSeedInput.h b/RecoTracker/LST/interface/LSTPixelSeedInput.h
new file mode 100644
index 0000000000000..18d3768b2e0fc
--- /dev/null
+++ b/RecoTracker/LST/interface/LSTPixelSeedInput.h
@@ -0,0 +1,75 @@
+#ifndef RecoTracker_LST_interface_LSTPixelSeedInput_h
+#define RecoTracker_LST_interface_LSTPixelSeedInput_h
+
+#include
+#include
+
+class LSTPixelSeedInput {
+public:
+ LSTPixelSeedInput() = default;
+ LSTPixelSeedInput(std::vector const px,
+ std::vector const py,
+ std::vector const pz,
+ std::vector const dxy,
+ std::vector const dz,
+ std::vector const ptErr,
+ std::vector const etaErr,
+ std::vector const stateTrajGlbX,
+ std::vector const stateTrajGlbY,
+ std::vector const stateTrajGlbZ,
+ std::vector const stateTrajGlbPx,
+ std::vector const stateTrajGlbPy,
+ std::vector const stateTrajGlbPz,
+ std::vector const q,
+ std::vector> const hitIdx)
+ : px_(std::move(px)),
+ py_(std::move(py)),
+ pz_(std::move(pz)),
+ dxy_(std::move(dxy)),
+ dz_(std::move(dz)),
+ ptErr_(std::move(ptErr)),
+ etaErr_(std::move(etaErr)),
+ stateTrajGlbX_(std::move(stateTrajGlbX)),
+ stateTrajGlbY_(std::move(stateTrajGlbY)),
+ stateTrajGlbZ_(std::move(stateTrajGlbZ)),
+ stateTrajGlbPx_(std::move(stateTrajGlbPx)),
+ stateTrajGlbPy_(std::move(stateTrajGlbPy)),
+ stateTrajGlbPz_(std::move(stateTrajGlbPz)),
+ q_(std::move(q)),
+ hitIdx_(std::move(hitIdx)) {}
+
+ std::vector const& px() const { return px_; }
+ std::vector const& py() const { return py_; }
+ std::vector const& pz() const { return pz_; }
+ std::vector const& dxy() const { return dxy_; }
+ std::vector const& dz() const { return dz_; }
+ std::vector const& ptErr() const { return ptErr_; }
+ std::vector const& etaErr() const { return etaErr_; }
+ std::vector const& stateTrajGlbX() const { return stateTrajGlbX_; }
+ std::vector const& stateTrajGlbY() const { return stateTrajGlbY_; }
+ std::vector const& stateTrajGlbZ() const { return stateTrajGlbZ_; }
+ std::vector const& stateTrajGlbPx() const { return stateTrajGlbPx_; }
+ std::vector const& stateTrajGlbPy() const { return stateTrajGlbPy_; }
+ std::vector const& stateTrajGlbPz() const { return stateTrajGlbPz_; }
+ std::vector const& q() const { return q_; }
+ std::vector> const& hitIdx() const { return hitIdx_; }
+
+private:
+ std::vector px_;
+ std::vector py_;
+ std::vector pz_;
+ std::vector dxy_;
+ std::vector dz_;
+ std::vector ptErr_;
+ std::vector etaErr_;
+ std::vector stateTrajGlbX_;
+ std::vector stateTrajGlbY_;
+ std::vector stateTrajGlbZ_;
+ std::vector stateTrajGlbPx_;
+ std::vector stateTrajGlbPy_;
+ std::vector stateTrajGlbPz_;
+ std::vector q_;
+ std::vector> hitIdx_;
+};
+
+#endif
diff --git a/RecoTracker/LST/plugins/BuildFile.xml b/RecoTracker/LST/plugins/BuildFile.xml
new file mode 100644
index 0000000000000..49e9ee77f5a3b
--- /dev/null
+++ b/RecoTracker/LST/plugins/BuildFile.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RecoTracker/LST/plugins/LSTOutputConverter.cc b/RecoTracker/LST/plugins/LSTOutputConverter.cc
new file mode 100644
index 0000000000000..0bbdd68051b87
--- /dev/null
+++ b/RecoTracker/LST/plugins/LSTOutputConverter.cc
@@ -0,0 +1,273 @@
+#include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h"
+#include "DataFormats/TrackerRecHit2D/interface/SiPixelRecHitCollection.h"
+#include "DataFormats/TrackCandidate/interface/TrackCandidateCollection.h"
+#include "DataFormats/TrackReco/interface/SeedStopInfo.h"
+#include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/Exception.h"
+#include "Geometry/CommonDetUnit/interface/GeomDet.h"
+#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
+#include "MagneticField/Engine/interface/MagneticField.h"
+#include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
+#include "RecoTracker/LST/interface/LSTPhase2OTHitsInput.h"
+#include "RecoTracker/LST/interface/LSTOutput.h"
+#include "RecoTracker/TkSeedingLayers/interface/SeedingHitSet.h"
+
+#include "RecoTracker/TkSeedGenerator/interface/SeedCreator.h"
+#include "RecoTracker/TkSeedGenerator/interface/SeedCreatorFactory.h"
+
+#include "RecoTracker/TkTrackingRegions/interface/GlobalTrackingRegion.h"
+#include "TrackingTools/GeomPropagators/interface/Propagator.h"
+#include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
+#include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
+
+class LSTOutputConverter : public edm::stream::EDProducer<> {
+public:
+ explicit LSTOutputConverter(edm::ParameterSet const& iConfig);
+ ~LSTOutputConverter() override = default;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+
+ const edm::EDGetTokenT lstOutputToken_;
+ const edm::EDGetTokenT lstPhase2OTHitsInputToken_;
+ const edm::EDGetTokenT lstPixelSeedToken_;
+ const bool includeT5s_;
+ const bool includeNonpLSTSs_;
+ const edm::ESGetToken mfToken_;
+ const edm::ESGetToken propagatorAlongToken_;
+ const edm::ESGetToken propagatorOppositeToken_;
+ const edm::ESGetToken tGeomToken_;
+ std::unique_ptr seedCreator_;
+ const edm::EDPutTokenT trajectorySeedPutToken_;
+ const edm::EDPutTokenT trajectorySeedpLSPutToken_;
+ const edm::EDPutTokenT trackCandidatePutToken_;
+ const edm::EDPutTokenT trackCandidatepTCPutToken_;
+ const edm::EDPutTokenT trackCandidateT5TCPutToken_;
+ const edm::EDPutTokenT trackCandidateNopLSTCPutToken_;
+ const edm::EDPutTokenT trackCandidatepTTCPutToken_;
+ const edm::EDPutTokenT trackCandidatepLSTCPutToken_;
+ const edm::EDPutTokenT> seedStopInfoPutToken_;
+};
+
+LSTOutputConverter::LSTOutputConverter(edm::ParameterSet const& iConfig)
+ : lstOutputToken_(consumes(iConfig.getParameter("lstOutput"))),
+ lstPhase2OTHitsInputToken_{consumes(iConfig.getParameter("phase2OTHits"))},
+ lstPixelSeedToken_{consumes(iConfig.getParameter("lstPixelSeeds"))},
+ includeT5s_(iConfig.getParameter("includeT5s")),
+ includeNonpLSTSs_(iConfig.getParameter("includeNonpLSTSs")),
+ mfToken_(esConsumes()),
+ propagatorAlongToken_{esConsumes(iConfig.getParameter("propagatorAlong"))},
+ propagatorOppositeToken_{esConsumes(iConfig.getParameter("propagatorOpposite"))},
+ tGeomToken_(esConsumes()),
+ seedCreator_(SeedCreatorFactory::get()->create("SeedFromConsecutiveHitsCreator",
+ iConfig.getParameter("SeedCreatorPSet"),
+ consumesCollector())),
+ // FIXME: need to make creation configurable:
+ // - A toggle to not produce TSs at all could be useful to save memory;
+ // it won't affect speed though
+ // - The minimal set for TCs is t5TCsLST, pTTCsLST and pLSTCsLST.
+ // That would complicate the handling of collections though,
+ // so it is deferred to when we have a clearer picture of what's needed.
+ trajectorySeedPutToken_(produces("")),
+ trajectorySeedpLSPutToken_(produces("pLSTSsLST")),
+ trackCandidatePutToken_(produces("")),
+ trackCandidatepTCPutToken_(produces("pTCsLST")),
+ trackCandidateT5TCPutToken_(produces("t5TCsLST")),
+ trackCandidateNopLSTCPutToken_(produces("nopLSTCsLST")),
+ trackCandidatepTTCPutToken_(produces("pTTCsLST")),
+ trackCandidatepLSTCPutToken_(produces("pLSTCsLST")),
+ seedStopInfoPutToken_(produces()) {}
+
+void LSTOutputConverter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+
+ desc.add("lstOutput", edm::InputTag("lstProducer"));
+ desc.add("phase2OTHits", edm::InputTag("lstPhase2OTHitsInputProducer"));
+ desc.add("lstPixelSeeds", edm::InputTag("lstPixelSeedInputProducer"));
+ desc.add("includeT5s", true);
+ desc.add("includeNonpLSTSs", false);
+ desc.add("propagatorAlong", edm::ESInputTag{"", "PropagatorWithMaterial"});
+ desc.add("propagatorOpposite", edm::ESInputTag{"", "PropagatorWithMaterialOpposite"});
+
+ edm::ParameterSetDescription psd0;
+ psd0.add("ComponentName", std::string("SeedFromConsecutiveHitsCreator"));
+ psd0.add("propagator", std::string("PropagatorWithMaterial"));
+ psd0.add("SeedMomentumForBOFF", 5.0);
+ psd0.add("OriginTransverseErrorMultiplier", 1.0);
+ psd0.add("MinOneOverPtError", 1.0);
+ psd0.add("magneticField", std::string(""));
+ psd0.add("TTRHBuilder", std::string("WithTrackAngle"));
+ psd0.add("forceKinematicWithRegionDirection", false);
+ desc.add("SeedCreatorPSet", psd0);
+
+ descriptions.addWithDefaultLabel(desc);
+}
+
+void LSTOutputConverter::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ // Setup
+ auto const& lstOutput = iEvent.get(lstOutputToken_);
+ auto const& phase2OTRecHits = iEvent.get(lstPhase2OTHitsInputToken_);
+ auto const& pixelSeeds = iEvent.get(lstPixelSeedToken_);
+ auto const& mf = iSetup.getData(mfToken_);
+ auto const& propAlo = iSetup.getData(propagatorAlongToken_);
+ auto const& propOppo = iSetup.getData(propagatorOppositeToken_);
+ auto const& tracker = iSetup.getData(tGeomToken_);
+
+ // Vector definitions
+ std::vector> const& lstTC_hitIdx = lstOutput.hitIdx();
+ std::vector const& lstTC_len = lstOutput.len();
+ std::vector const& lstTC_seedIdx = lstOutput.seedIdx();
+ std::vector const& lstTC_trackCandidateType = lstOutput.trackCandidateType();
+
+ TrajectorySeedCollection outputTS, outputpLSTS;
+ outputTS.reserve(lstTC_len.size());
+ outputpLSTS.reserve(lstTC_len.size());
+ TrackCandidateCollection outputTC, outputpTC, outputT5TC, outputNopLSTC, outputpTTC, outputpLSTC;
+ outputTC.reserve(lstTC_len.size());
+ outputpTC.reserve(lstTC_len.size());
+ outputT5TC.reserve(lstTC_len.size());
+ outputNopLSTC.reserve(lstTC_len.size());
+ outputpTTC.reserve(lstTC_len.size());
+ outputpLSTC.reserve(lstTC_len.size());
+
+ auto const& OTHits = phase2OTRecHits.hits();
+
+ LogDebug("LSTOutputConverter") << "lstTC size " << lstTC_len.size();
+ for (unsigned int i = 0; i < lstTC_len.size(); i++) {
+ LogDebug("LSTOutputConverter") << " cand " << i << " " << lstTC_len[i] << " " << lstTC_seedIdx[i];
+ TrajectorySeed seed;
+ if (lstTC_trackCandidateType[i] != LSTOutput::LSTTCType::T5)
+ seed = pixelSeeds[lstTC_seedIdx[i]];
+
+ edm::OwnVector recHits;
+ if (lstTC_trackCandidateType[i] != LSTOutput::LSTTCType::T5) {
+ for (auto const& hit : seed.recHits())
+ recHits.push_back(hit.clone());
+ }
+
+ unsigned int const nPixelHits = lstTC_trackCandidateType[i] == LSTOutput::LSTTCType::T5 ? 0 : recHits.size();
+ for (unsigned int j = nPixelHits; j < lstTC_hitIdx[i].size(); j++)
+ recHits.push_back(OTHits[lstTC_hitIdx[i][j]]->clone());
+
+ recHits.sort([](const auto& a, const auto& b) {
+ const auto asub = a.det()->subDetector();
+ const auto bsub = b.det()->subDetector();
+ if (GeomDetEnumerators::isInnerTracker(asub) && GeomDetEnumerators::isOuterTracker(bsub)) {
+ return true;
+ } else if (GeomDetEnumerators::isOuterTracker(asub) && GeomDetEnumerators::isInnerTracker(bsub)) {
+ return false;
+ } else if (asub != bsub) {
+ return asub < bsub;
+ } else {
+ const auto& apos = a.surface();
+ const auto& bpos = b.surface();
+ if (GeomDetEnumerators::isBarrel(asub)) {
+ return apos->rSpan().first < bpos->rSpan().first;
+ } else {
+ return std::abs(apos->zSpan().first) < std::abs(bpos->zSpan().first);
+ }
+ }
+ });
+
+ TrajectorySeedCollection seeds;
+ if (lstTC_trackCandidateType[i] != LSTOutput::LSTTCType::pLS) {
+ // Construct a full-length TrajectorySeed always for T5s,
+ // only when required by a flag for other pT objects.
+ if (includeNonpLSTSs_ || lstTC_trackCandidateType[i] == LSTOutput::LSTTCType::T5) {
+ using Hit = SeedingHitSet::ConstRecHitPointer;
+ std::vector hitsForSeed;
+ hitsForSeed.reserve(lstTC_len[i]);
+ int nHits = 0;
+ for (auto const& hit : recHits) {
+ if (lstTC_trackCandidateType[i] == LSTOutput::LSTTCType::T5) {
+ auto hType = tracker.getDetectorType(hit.geographicalId());
+ if (hType != TrackerGeometry::ModuleType::Ph2PSP && nHits < 2)
+ continue; // the first two should be P
+ }
+ hitsForSeed.emplace_back(dynamic_cast(&hit));
+ nHits++;
+ }
+
+ seedCreator_->init(GlobalTrackingRegion(), iSetup, nullptr);
+ seedCreator_->makeSeed(seeds, hitsForSeed);
+ if (seeds.empty()) {
+ edm::LogInfo("LSTOutputConverter")
+ << "failed to convert a LST object to a seed" << i << " " << lstTC_len[i] << " " << lstTC_seedIdx[i];
+ if (lstTC_trackCandidateType[i] == LSTOutput::LSTTCType::T5)
+ continue;
+ }
+ if (lstTC_trackCandidateType[i] == LSTOutput::LSTTCType::T5)
+ seed = seeds[0];
+
+ auto trajectorySeed = (seeds.empty() ? seed : seeds[0]);
+ outputTS.emplace_back(trajectorySeed);
+ auto const& ss = trajectorySeed.startingState();
+ LogDebug("LSTOutputConverter") << "Created a seed with " << seed.nHits() << " " << ss.detId() << " " << ss.pt()
+ << " " << ss.parameters().vector() << " " << ss.error(0);
+ }
+ } else {
+ outputTS.emplace_back(seed);
+ outputpLSTS.emplace_back(seed);
+ }
+
+ TrajectoryStateOnSurface tsos =
+ trajectoryStateTransform::transientState(seed.startingState(), (seed.recHits().end() - 1)->surface(), &mf);
+ tsos.rescaleError(100.);
+ auto tsosPair = propOppo.propagateWithPath(tsos, *recHits[0].surface());
+ if (!tsosPair.first.isValid()) {
+ LogDebug("LSTOutputConverter") << "Propagating to startingState opposite to momentum failed, trying along next";
+ tsosPair = propAlo.propagateWithPath(tsos, *recHits[0].surface());
+ }
+ if (tsosPair.first.isValid()) {
+ PTrajectoryStateOnDet st =
+ trajectoryStateTransform::persistentState(tsosPair.first, recHits[0].det()->geographicalId().rawId());
+
+ if (lstTC_trackCandidateType[i] == LSTOutput::LSTTCType::T5) {
+ if (!includeT5s_) {
+ continue;
+ } else {
+ auto tc = TrackCandidate(recHits, seed, st);
+ outputTC.emplace_back(tc);
+ outputT5TC.emplace_back(tc);
+ outputNopLSTC.emplace_back(tc);
+ }
+ } else {
+ auto tc = TrackCandidate(recHits, seed, st);
+ outputTC.emplace_back(tc);
+ outputpTC.emplace_back(tc);
+ if (lstTC_trackCandidateType[i] != LSTOutput::LSTTCType::pLS) {
+ outputNopLSTC.emplace_back(tc);
+ outputpTTC.emplace_back(tc);
+ } else {
+ outputpLSTC.emplace_back(tc);
+ }
+ }
+ } else {
+ edm::LogInfo("LSTOutputConverter") << "Failed to make a candidate initial state. Seed state is " << tsos
+ << " TC cand " << i << " " << lstTC_len[i] << " " << lstTC_seedIdx[i]
+ << " first hit " << recHits.front().globalPosition() << " last hit "
+ << recHits.back().globalPosition();
+ }
+ }
+
+ LogDebug("LSTOutputConverter") << "done with conversion: Track candidate output size = " << outputpTC.size()
+ << " (p* objects) + " << outputT5TC.size() << " (T5 objects)";
+ iEvent.emplace(trajectorySeedPutToken_, std::move(outputTS));
+ iEvent.emplace(trajectorySeedpLSPutToken_, std::move(outputpLSTS));
+ iEvent.emplace(trackCandidatePutToken_, std::move(outputTC));
+ iEvent.emplace(trackCandidatepTCPutToken_, std::move(outputpTC));
+ iEvent.emplace(trackCandidateT5TCPutToken_, std::move(outputT5TC));
+ iEvent.emplace(trackCandidateNopLSTCPutToken_, std::move(outputNopLSTC));
+ iEvent.emplace(trackCandidatepTTCPutToken_, std::move(outputpTTC));
+ iEvent.emplace(trackCandidatepLSTCPutToken_, std::move(outputpLSTC));
+ iEvent.emplace(seedStopInfoPutToken_, 0U); //dummy stop info
+}
+
+DEFINE_FWK_MODULE(LSTOutputConverter);
diff --git a/RecoTracker/LST/plugins/LSTPhase2OTHitsInputProducer.cc b/RecoTracker/LST/plugins/LSTPhase2OTHitsInputProducer.cc
new file mode 100644
index 0000000000000..a0fcc72f598b6
--- /dev/null
+++ b/RecoTracker/LST/plugins/LSTPhase2OTHitsInputProducer.cc
@@ -0,0 +1,67 @@
+#include "FWCore/Framework/interface/global/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+
+#include "RecoTracker/LST/interface/LSTPhase2OTHitsInput.h"
+
+class LSTPhase2OTHitsInputProducer : public edm::global::EDProducer<> {
+public:
+ explicit LSTPhase2OTHitsInputProducer(edm::ParameterSet const& iConfig);
+ ~LSTPhase2OTHitsInputProducer() override = default;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ void produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const override;
+
+ const edm::EDGetTokenT phase2OTRecHitToken_;
+ const edm::EDPutTokenT lstPhase2OTHitsInputPutToken_;
+};
+
+LSTPhase2OTHitsInputProducer::LSTPhase2OTHitsInputProducer(edm::ParameterSet const& iConfig)
+ : phase2OTRecHitToken_(consumes(iConfig.getParameter("phase2OTRecHits"))),
+ lstPhase2OTHitsInputPutToken_(produces()) {}
+
+void LSTPhase2OTHitsInputProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+
+ desc.add("phase2OTRecHits", edm::InputTag("siPhase2RecHits"));
+
+ descriptions.addWithDefaultLabel(desc);
+}
+
+void LSTPhase2OTHitsInputProducer::produce(edm::StreamID iID, edm::Event& iEvent, const edm::EventSetup& iSetup) const {
+ // Setup
+ auto const& phase2OTHits = iEvent.get(phase2OTRecHitToken_);
+
+ // Vector definitions
+ std::vector ph2_detId;
+ ph2_detId.reserve(phase2OTHits.dataSize());
+ std::vector ph2_x;
+ ph2_x.reserve(phase2OTHits.dataSize());
+ std::vector ph2_y;
+ ph2_y.reserve(phase2OTHits.dataSize());
+ std::vector ph2_z;
+ ph2_z.reserve(phase2OTHits.dataSize());
+ std::vector ph2_hits;
+ ph2_hits.reserve(phase2OTHits.dataSize());
+
+ for (auto const& it : phase2OTHits) {
+ const DetId hitId = it.detId();
+ for (auto const& hit : it) {
+ ph2_detId.push_back(hitId.rawId());
+ ph2_x.push_back(hit.globalPosition().x());
+ ph2_y.push_back(hit.globalPosition().y());
+ ph2_z.push_back(hit.globalPosition().z());
+ ph2_hits.push_back(&hit);
+ }
+ }
+
+ LSTPhase2OTHitsInput phase2OTHitsInput(
+ std::move(ph2_detId), std::move(ph2_x), std::move(ph2_y), std::move(ph2_z), std::move(ph2_hits));
+ iEvent.emplace(lstPhase2OTHitsInputPutToken_, std::move(phase2OTHitsInput));
+}
+
+DEFINE_FWK_MODULE(LSTPhase2OTHitsInputProducer);
diff --git a/RecoTracker/LST/plugins/LSTPixelSeedInputProducer.cc b/RecoTracker/LST/plugins/LSTPixelSeedInputProducer.cc
new file mode 100644
index 0000000000000..819baf78c6aa4
--- /dev/null
+++ b/RecoTracker/LST/plugins/LSTPixelSeedInputProducer.cc
@@ -0,0 +1,171 @@
+#include "FWCore/Framework/interface/global/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+
+#include "FWCore/Utilities/interface/transform.h"
+
+#include "MagneticField/Engine/interface/MagneticField.h"
+#include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
+
+#include "DataFormats/TrackerRecHit2D/interface/SiStripMatchedRecHit2DCollection.h"
+#include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
+
+#include "Validation/RecoTrack/interface/trackFromSeedFitFailed.h"
+
+#include "TrackingTools/Records/interface/TransientRecHitRecord.h"
+#include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
+#include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHitBuilder.h"
+
+#include "RecoTracker/LST/interface/LSTPixelSeedInput.h"
+
+class LSTPixelSeedInputProducer : public edm::global::EDProducer<> {
+public:
+ explicit LSTPixelSeedInputProducer(edm::ParameterSet const& iConfig);
+ ~LSTPixelSeedInputProducer() override = default;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ void produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const override;
+
+ const edm::ESGetToken mfToken_;
+ const edm::EDGetTokenT beamSpotToken_;
+ std::vector>> seedTokens_;
+ const edm::EDPutTokenT lstPixelSeedInputPutToken_;
+ const edm::EDPutTokenT lstPixelSeedsPutToken_;
+};
+
+LSTPixelSeedInputProducer::LSTPixelSeedInputProducer(edm::ParameterSet const& iConfig)
+ : mfToken_(esConsumes()),
+ beamSpotToken_(consumes(iConfig.getParameter("beamSpot"))),
+ lstPixelSeedInputPutToken_(produces()),
+ lstPixelSeedsPutToken_(produces()) {
+ seedTokens_ = edm::vector_transform(iConfig.getParameter>("seedTracks"),
+ [&](const edm::InputTag& tag) { return consumes>(tag); });
+}
+
+void LSTPixelSeedInputProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+
+ desc.add("beamSpot", edm::InputTag("offlineBeamSpot"));
+
+ desc.add>("seedTracks",
+ std::vector{edm::InputTag("lstInitialStepSeedTracks"),
+ edm::InputTag("lstHighPtTripletStepSeedTracks")});
+
+ descriptions.addWithDefaultLabel(desc);
+}
+
+void LSTPixelSeedInputProducer::produce(edm::StreamID iID, edm::Event& iEvent, const edm::EventSetup& iSetup) const {
+ // Setup
+ auto const& mf = iSetup.getData(mfToken_);
+ auto const& bs = iEvent.get(beamSpotToken_);
+
+ // Vector definitions
+ std::vector see_px;
+ std::vector see_py;
+ std::vector see_pz;
+ std::vector see_dxy;
+ std::vector see_dz;
+ std::vector see_ptErr;
+ std::vector see_etaErr;
+ std::vector see_stateTrajGlbX;
+ std::vector see_stateTrajGlbY;
+ std::vector see_stateTrajGlbZ;
+ std::vector see_stateTrajGlbPx;
+ std::vector see_stateTrajGlbPy;
+ std::vector see_stateTrajGlbPz;
+ std::vector see_q;
+ std::vector> see_hitIdx;
+ TrajectorySeedCollection see_seeds;
+
+ for (size_t iColl = 0; iColl < seedTokens_.size(); ++iColl) {
+ // Get seed tokens
+ auto const& seedToken = seedTokens_[iColl];
+ auto const& seedTracks = iEvent.get(seedToken);
+
+ if (seedTracks.empty())
+ continue;
+
+ // Get seed track refs
+ edm::RefToBaseVector seedTrackRefs;
+ for (edm::View::size_type i = 0; i < seedTracks.size(); ++i) {
+ seedTrackRefs.push_back(seedTracks.refAt(i));
+ }
+
+ edm::ProductID id = seedTracks[0].seedRef().id();
+
+ for (size_t iSeed = 0; iSeed < seedTrackRefs.size(); ++iSeed) {
+ auto const& seedTrackRef = seedTrackRefs[iSeed];
+ auto const& seedTrack = *seedTrackRef;
+ auto const& seedRef = seedTrack.seedRef();
+ auto const& seed = *seedRef;
+
+ if (seedRef.id() != id)
+ throw cms::Exception("LogicError")
+ << "All tracks in 'TracksFromSeeds' collection should point to seeds in the same collection. Now the "
+ "element 0 had ProductID "
+ << id << " while the element " << seedTrackRef.key() << " had " << seedTrackRef.id() << ".";
+
+ const bool seedFitOk = !trackFromSeedFitFailed(seedTrack);
+
+ const TrackingRecHit* lastRecHit = &*(seed.recHits().end() - 1);
+ TrajectoryStateOnSurface tsos =
+ trajectoryStateTransform::transientState(seed.startingState(), lastRecHit->surface(), &mf);
+ auto const& stateGlobal = tsos.globalParameters();
+
+ std::vector hitIdx;
+ for (auto const& hit : seed.recHits()) {
+ int subid = hit.geographicalId().subdetId();
+ if (subid == (int)PixelSubdetector::PixelBarrel || subid == (int)PixelSubdetector::PixelEndcap) {
+ const BaseTrackerRecHit* bhit = dynamic_cast(&hit);
+ const auto& clusterRef = bhit->firstClusterRef();
+ const auto clusterKey = clusterRef.cluster_pixel().key();
+ hitIdx.push_back(clusterKey);
+ } else {
+ throw cms::Exception("LSTPixelSeedInputProducer") << "Not pixel hits found!";
+ }
+ }
+
+ // Fill output
+ see_px.push_back(seedFitOk ? seedTrack.px() : 0);
+ see_py.push_back(seedFitOk ? seedTrack.py() : 0);
+ see_pz.push_back(seedFitOk ? seedTrack.pz() : 0);
+ see_dxy.push_back(seedFitOk ? seedTrack.dxy(bs.position()) : 0);
+ see_dz.push_back(seedFitOk ? seedTrack.dz(bs.position()) : 0);
+ see_ptErr.push_back(seedFitOk ? seedTrack.ptError() : 0);
+ see_etaErr.push_back(seedFitOk ? seedTrack.etaError() : 0);
+ see_stateTrajGlbX.push_back(stateGlobal.position().x());
+ see_stateTrajGlbY.push_back(stateGlobal.position().y());
+ see_stateTrajGlbZ.push_back(stateGlobal.position().z());
+ see_stateTrajGlbPx.push_back(stateGlobal.momentum().x());
+ see_stateTrajGlbPy.push_back(stateGlobal.momentum().y());
+ see_stateTrajGlbPz.push_back(stateGlobal.momentum().z());
+ see_q.push_back(seedTrack.charge());
+ see_hitIdx.push_back(hitIdx);
+ see_seeds.push_back(seed);
+ }
+ }
+
+ LSTPixelSeedInput pixelSeedInput(std::move(see_px),
+ std::move(see_py),
+ std::move(see_pz),
+ std::move(see_dxy),
+ std::move(see_dz),
+ std::move(see_ptErr),
+ std::move(see_etaErr),
+ std::move(see_stateTrajGlbX),
+ std::move(see_stateTrajGlbY),
+ std::move(see_stateTrajGlbZ),
+ std::move(see_stateTrajGlbPx),
+ std::move(see_stateTrajGlbPy),
+ std::move(see_stateTrajGlbPz),
+ std::move(see_q),
+ std::move(see_hitIdx));
+ iEvent.emplace(lstPixelSeedInputPutToken_, std::move(pixelSeedInput));
+ iEvent.emplace(lstPixelSeedsPutToken_, std::move(see_seeds));
+}
+
+DEFINE_FWK_MODULE(LSTPixelSeedInputProducer);
diff --git a/RecoTracker/LST/plugins/alpaka/LSTModulesDevESProducer.cc b/RecoTracker/LST/plugins/alpaka/LSTModulesDevESProducer.cc
new file mode 100644
index 0000000000000..d0e103b1e315b
--- /dev/null
+++ b/RecoTracker/LST/plugins/alpaka/LSTModulesDevESProducer.cc
@@ -0,0 +1,31 @@
+// LST includes
+#include "RecoTracker/LSTCore/interface/alpaka/LST.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/ESProducer.h"
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/ModuleFactory.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
+
+#include "RecoTracker/Record/interface/TrackerRecoGeometryRecord.h"
+
+namespace ALPAKA_ACCELERATOR_NAMESPACE {
+
+ class LSTModulesDevESProducer : public ESProducer {
+ public:
+ LSTModulesDevESProducer(edm::ParameterSet const& iConfig) : ESProducer(iConfig) { setWhatProduced(this); }
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ descriptions.addWithDefaultLabel(desc);
+ }
+
+ std::unique_ptr> produce(TrackerRecoGeometryRecord const& iRecord) {
+ return lst::loadAndFillESHost();
+ }
+ };
+
+} // namespace ALPAKA_ACCELERATOR_NAMESPACE
+
+DEFINE_FWK_EVENTSETUP_ALPAKA_MODULE(LSTModulesDevESProducer);
diff --git a/RecoTracker/LST/plugins/alpaka/LSTProducer.cc b/RecoTracker/LST/plugins/alpaka/LSTProducer.cc
new file mode 100644
index 0000000000000..7eb6c57ade05c
--- /dev/null
+++ b/RecoTracker/LST/plugins/alpaka/LSTProducer.cc
@@ -0,0 +1,99 @@
+#include
+
+#include "RecoTracker/LSTCore/interface/alpaka/LST.h"
+
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDGetToken.h"
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDPutToken.h"
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/Event.h"
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EventSetup.h"
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/stream/SynchronizingEDProducer.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+
+#include "RecoTracker/LST/interface/LSTOutput.h"
+#include "RecoTracker/LST/interface/LSTPhase2OTHitsInput.h"
+#include "RecoTracker/LST/interface/LSTPixelSeedInput.h"
+
+#include "RecoTracker/Record/interface/TrackerRecoGeometryRecord.h"
+
+namespace ALPAKA_ACCELERATOR_NAMESPACE {
+
+ class LSTProducer : public stream::SynchronizingEDProducer<> {
+ public:
+ LSTProducer(edm::ParameterSet const& config)
+ : lstPixelSeedInputToken_{consumes(config.getParameter("pixelSeedInput"))},
+ lstPhase2OTHitsInputToken_{consumes(config.getParameter("phase2OTHitsInput"))},
+ lstESToken_{esConsumes()},
+ verbose_(config.getParameter("verbose")),
+ nopLSDupClean_(config.getParameter("nopLSDupClean")),
+ tcpLSTriplets_(config.getParameter("tcpLSTriplets")),
+ lstOutputToken_{produces()} {}
+
+ void acquire(device::Event const& event, device::EventSetup const& setup) override {
+ // Inputs
+ auto const& pixelSeeds = event.get(lstPixelSeedInputToken_);
+ auto const& phase2OTHits = event.get(lstPhase2OTHitsInputToken_);
+
+ auto const& lstESDeviceData = setup.getData(lstESToken_);
+
+ lst_.run(event.queue(),
+ verbose_,
+ &lstESDeviceData,
+ pixelSeeds.px(),
+ pixelSeeds.py(),
+ pixelSeeds.pz(),
+ pixelSeeds.dxy(),
+ pixelSeeds.dz(),
+ pixelSeeds.ptErr(),
+ pixelSeeds.etaErr(),
+ pixelSeeds.stateTrajGlbX(),
+ pixelSeeds.stateTrajGlbY(),
+ pixelSeeds.stateTrajGlbZ(),
+ pixelSeeds.stateTrajGlbPx(),
+ pixelSeeds.stateTrajGlbPy(),
+ pixelSeeds.stateTrajGlbPz(),
+ pixelSeeds.q(),
+ pixelSeeds.hitIdx(),
+ phase2OTHits.detId(),
+ phase2OTHits.x(),
+ phase2OTHits.y(),
+ phase2OTHits.z(),
+ nopLSDupClean_,
+ tcpLSTriplets_);
+ }
+
+ void produce(device::Event& event, device::EventSetup const&) override {
+ // Output
+ LSTOutput lstOutput(lst_.hits(), lst_.len(), lst_.seedIdx(), lst_.trackCandidateType());
+ event.emplace(lstOutputToken_, std::move(lstOutput));
+ }
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("pixelSeedInput", edm::InputTag{"lstPixelSeedInputProducer"});
+ desc.add("phase2OTHitsInput", edm::InputTag{"lstPhase2OTHitsInputProducer"});
+ desc.add("verbose", false);
+ desc.add("nopLSDupClean", false);
+ desc.add("tcpLSTriplets", false);
+ descriptions.addWithDefaultLabel(desc);
+ }
+
+ private:
+ edm::EDGetTokenT lstPixelSeedInputToken_;
+ edm::EDGetTokenT lstPhase2OTHitsInputToken_;
+ device::ESGetToken, TrackerRecoGeometryRecord> lstESToken_;
+ const bool verbose_, nopLSDupClean_, tcpLSTriplets_;
+ edm::EDPutTokenT lstOutputToken_;
+
+ lst::LST lst_;
+ };
+
+} // namespace ALPAKA_ACCELERATOR_NAMESPACE
+
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/MakerMacros.h"
+DEFINE_FWK_ALPAKA_MODULE(LSTProducer);
diff --git a/RecoTracker/LST/python/lstProducerTask_cff.py b/RecoTracker/LST/python/lstProducerTask_cff.py
new file mode 100644
index 0000000000000..588b354788635
--- /dev/null
+++ b/RecoTracker/LST/python/lstProducerTask_cff.py
@@ -0,0 +1,7 @@
+import FWCore.ParameterSet.Config as cms
+
+from RecoTracker.LST.lstProducer_cfi import lstProducer
+
+from RecoTracker.LST.lstModulesDevESProducer_cfi import lstModulesDevESProducer
+
+lstProducerTask = cms.Task(lstModulesDevESProducer, lstProducer)
diff --git a/RecoTracker/LST/python/lstSeedTracks_cff.py b/RecoTracker/LST/python/lstSeedTracks_cff.py
new file mode 100644
index 0000000000000..7046c616b0054
--- /dev/null
+++ b/RecoTracker/LST/python/lstSeedTracks_cff.py
@@ -0,0 +1,15 @@
+import FWCore.ParameterSet.Config as cms
+
+lstInitialStepSeedTracks = cms.EDProducer(
+ "TrackFromSeedProducer",
+ src = cms.InputTag("initialStepSeeds"),
+ beamSpot = cms.InputTag("offlineBeamSpot"),
+ TTRHBuilder = cms.string("WithoutRefit")
+)
+
+lstHighPtTripletStepSeedTracks = cms.EDProducer(
+ "TrackFromSeedProducer",
+ src = cms.InputTag("highPtTripletStepSeeds"),
+ beamSpot = cms.InputTag("offlineBeamSpot"),
+ TTRHBuilder = cms.string("WithoutRefit")
+)
diff --git a/RecoTracker/LST/python/lst_cff.py b/RecoTracker/LST/python/lst_cff.py
new file mode 100644
index 0000000000000..af3a80ae77e18
--- /dev/null
+++ b/RecoTracker/LST/python/lst_cff.py
@@ -0,0 +1,6 @@
+import FWCore.ParameterSet.Config as cms
+
+from RecoTracker.LST.lstSeedTracks_cff import *
+from RecoTracker.LST.lstPixelSeedInputProducer_cfi import *
+from RecoTracker.LST.lstPhase2OTHitsInputProducer_cfi import *
+from RecoTracker.LST.lstOutputConverter_cfi import *
diff --git a/RecoTracker/LST/src/ES_ModulesDev.cc b/RecoTracker/LST/src/ES_ModulesDev.cc
new file mode 100644
index 0000000000000..06a357860a7d5
--- /dev/null
+++ b/RecoTracker/LST/src/ES_ModulesDev.cc
@@ -0,0 +1,5 @@
+#include "RecoTracker/LSTCore/interface/LSTESData.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+#include "FWCore/Utilities/interface/typelookup.h"
+
+TYPELOOKUP_DATA_REG(lst::LSTESData);
diff --git a/RecoTracker/LST/src/alpaka/ES_ModulesDev.cc b/RecoTracker/LST/src/alpaka/ES_ModulesDev.cc
new file mode 100644
index 0000000000000..54ded5e7a7c98
--- /dev/null
+++ b/RecoTracker/LST/src/alpaka/ES_ModulesDev.cc
@@ -0,0 +1,4 @@
+#include "RecoTracker/LSTCore/interface/LSTESData.h"
+#include "HeterogeneousCore/AlpakaCore/interface/alpaka/typelookup.h"
+
+TYPELOOKUP_ALPAKA_TEMPLATED_DATA_REG(lst::LSTESData);
diff --git a/RecoTracker/LST/src/classes.h b/RecoTracker/LST/src/classes.h
new file mode 100644
index 0000000000000..6a6817d9b538e
--- /dev/null
+++ b/RecoTracker/LST/src/classes.h
@@ -0,0 +1,9 @@
+#ifndef RecoTracker_LST_classes_h
+#define RecoTracker_LST_classes_h
+
+#include "DataFormats/Common/interface/Wrapper.h"
+#include "RecoTracker/LST/interface/LSTPixelSeedInput.h"
+#include "RecoTracker/LST/interface/LSTPhase2OTHitsInput.h"
+#include "RecoTracker/LST/interface/LSTOutput.h"
+
+#endif
diff --git a/RecoTracker/LST/src/classes_def.xml b/RecoTracker/LST/src/classes_def.xml
new file mode 100644
index 0000000000000..d386e7b92a215
--- /dev/null
+++ b/RecoTracker/LST/src/classes_def.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/RecoTracker/LSTCore/BuildFile.xml b/RecoTracker/LSTCore/BuildFile.xml
new file mode 100644
index 0000000000000..a58a1898046ae
--- /dev/null
+++ b/RecoTracker/LSTCore/BuildFile.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/RecoTracker/LSTCore/interface/Common.h b/RecoTracker/LSTCore/interface/Common.h
new file mode 100644
index 0000000000000..f65ca7a50d867
--- /dev/null
+++ b/RecoTracker/LSTCore/interface/Common.h
@@ -0,0 +1,107 @@
+#ifndef RecoTracker_LSTCore_interface_Common_h
+#define RecoTracker_LSTCore_interface_Common_h
+
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+#include "DataFormats/Common/interface/StdArray.h"
+
+#if defined(FP16_Base)
+#if defined ALPAKA_ACC_GPU_CUDA_ENABLED
+#include
+#elif defined ALPAKA_ACC_GPU_HIP_ENABLED
+#include
+#endif
+#endif
+
+namespace lst {
+
+ // Named constants for pixelTypes
+ enum PixelType : int8_t { kInvalid = -1, kHighPt = 0, kLowPtPosCurv = 1, kLowPtNegCurv = 2 };
+
+ // Named types for LST objects
+ enum LSTObjType { T5 = 4, pT3 = 5, pT5 = 7, pLS = 8 };
+
+// If a compile time flag does not define PT_CUT, default to 0.8 (GeV)
+#ifndef PT_CUT
+ constexpr float PT_CUT = 0.8f;
+#endif
+
+ constexpr unsigned int max_blocks = 80;
+ constexpr unsigned int max_connected_modules = 40;
+
+ constexpr unsigned int n_max_pixel_segments_per_module = 50000;
+
+ constexpr unsigned int n_max_pixel_md_per_modules = 2 * n_max_pixel_segments_per_module;
+
+ constexpr unsigned int n_max_pixel_triplets = 5000;
+ constexpr unsigned int n_max_pixel_quintuplets = 15000;
+
+ constexpr unsigned int n_max_pixel_track_candidates = 30000;
+ constexpr unsigned int n_max_nonpixel_track_candidates = 1000;
+
+ constexpr unsigned int size_superbins = 45000;
+
+// Half precision wrapper functions.
+#if defined(FP16_Base)
+#define __F2H __float2half
+#define __H2F __half2float
+ typedef __half FPX;
+#else
+#define __F2H
+#define __H2F
+ typedef float FPX;
+#endif
+
+// Needed for files that are compiled by g++ to not throw an error.
+// uint4 is defined only for CUDA, so we will have to revisit this soon when running on other backends.
+#if !defined(ALPAKA_ACC_GPU_CUDA_ENABLED) && !defined(ALPAKA_ACC_GPU_HIP_ENABLED)
+ struct uint4 {
+ unsigned int x;
+ unsigned int y;
+ unsigned int z;
+ unsigned int w;
+ };
+#endif
+
+ // Defining the constant host device variables right up here
+ // Currently pixel tracks treated as LSs with 2 double layers (IT layers 1+2 and 3+4) and 4 hits. To be potentially handled better in the future.
+ struct Params_Modules {
+ using ArrayU16xMaxConnected = edm::StdArray;
+ };
+ struct Params_pLS {
+ static constexpr int kLayers = 2, kHits = 4;
+ };
+ struct Params_LS {
+ static constexpr int kLayers = 2, kHits = 4;
+ using ArrayUxLayers = edm::StdArray;
+ };
+ struct Params_T3 {
+ static constexpr int kLayers = 3, kHits = 6;
+ using ArrayU8xLayers = edm::StdArray;
+ using ArrayU16xLayers = edm::StdArray;
+ using ArrayUxHits = edm::StdArray;
+ };
+ struct Params_pT3 {
+ static constexpr int kLayers = 5, kHits = 10;
+ using ArrayU8xLayers = edm::StdArray;
+ using ArrayU16xLayers = edm::StdArray;
+ using ArrayUxHits = edm::StdArray;
+ };
+ struct Params_T5 {
+ static constexpr int kLayers = 5, kHits = 10;
+ using ArrayU8xLayers = edm::StdArray;
+ using ArrayU16xLayers = edm::StdArray;
+ using ArrayUxHits = edm::StdArray;
+ };
+ struct Params_pT5 {
+ static constexpr int kLayers = 7, kHits = 14;
+ using ArrayU8xLayers = edm::StdArray;
+ using ArrayU16xLayers = edm::StdArray;
+ using ArrayUxHits = edm::StdArray;
+ };
+
+ using ArrayIx2 = edm::StdArray;
+ using ArrayUx2 = edm::StdArray;
+
+} //namespace lst
+
+#endif
diff --git a/RecoTracker/LSTCore/interface/EndcapGeometry.h b/RecoTracker/LSTCore/interface/EndcapGeometry.h
new file mode 100644
index 0000000000000..b8c44c14fb143
--- /dev/null
+++ b/RecoTracker/LSTCore/interface/EndcapGeometry.h
@@ -0,0 +1,29 @@
+#ifndef RecoTracker_LSTCore_interface_EndcapGeometry_h
+#define RecoTracker_LSTCore_interface_EndcapGeometry_h
+
+#include