Skip to content

Commit 859386e

Browse files
authored
Merge pull request #48811 from gsokmen/151_DNN_v3_timing_withSCSmod
Updated SuperclusterDNN v3 for superclustering in TICLv5
2 parents 7205705 + f70dfb5 commit 859386e

File tree

7 files changed

+152
-46
lines changed

7 files changed

+152
-46
lines changed

HLTrigger/Configuration/python/HLT_75e33/sequences/HLTHgcalTiclPFClusteringForEgammaL1SeededSequence_cfi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@
4848
linkingPSet = cms.PSet(
4949
type=cms.string("SuperClusteringDNN"),
5050
algo_verbosity=cms.int32(0),
51-
onnxModelPath = cms.FileInPath("RecoHGCal/TICL/data/superclustering/supercls_v2p1.onnx"),
52-
nnWorkingPoint=cms.double(0.3),
51+
onnxModelPath = cms.FileInPath("RecoHGCal/TICL/data/superclustering/supercls_v3.onnx"),
52+
nnWorkingPoint=cms.double(0.57247),
5353
),
5454
tracksters_collections = [cms.InputTag("hltTiclTrackstersCLUE3DHighL1Seeded")], # to be changed to ticlTrackstersCLUE3DEM once separate CLUE3D iterations are introduced
5555
)

HLTrigger/Configuration/python/HLT_75e33/sequences/HLTHgcalTiclPFClusteringForEgammaUnseededSequence_cfi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
linkingPSet = cms.PSet(
6262
type=cms.string("SuperClusteringDNN"),
6363
algo_verbosity=cms.int32(0),
64-
onnxModelPath = cms.FileInPath("RecoHGCal/TICL/data/superclustering/supercls_v2p1.onnx"),
65-
nnWorkingPoint=cms.double(0.3),
64+
onnxModelPath = cms.FileInPath("RecoHGCal/TICL/data/superclustering/supercls_v3.onnx"),
65+
nnWorkingPoint=cms.double(0.57247),
6666
),
6767
tracksters_collections = [cms.InputTag("hltTiclTrackstersCLUE3DHigh")], # to be changed to ticlTrackstersCLUE3DEM once separate CLUE3D iterations are introduced
6868
)

RecoHGCal/TICL/interface/SuperclusteringDNNInputs.h

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
// Author: Theo Cuisset - [email protected]
33
// Date: 11/2023
44

5+
// Modified by Gamze Sokmen - [email protected]
6+
// Changes: Implementation of the delta time feature under a new DNN input version (v3) for the superclustering DNN and correcting the seed pT calculation.
7+
// Date: 07/2025
8+
59
#ifndef __RecoHGCal_TICL_SuperclusteringDNNInputs_H__
610
#define __RecoHGCal_TICL_SuperclusteringDNNInputs_H__
711

@@ -10,6 +14,11 @@
1014
#include <memory>
1115

1216
namespace ticl {
17+
18+
// any raw_dt outside +/- kDeltaTimeDefault is considered bad
19+
static constexpr float kDeltaTimeDefault = 50.f;
20+
static constexpr float kBadDeltaTime = -5.f;
21+
1322
class Trackster;
1423

1524
// Abstract base class for DNN input preparation.
@@ -87,7 +96,39 @@ namespace ticl {
8796
}
8897
};
8998

99+
/* Third version of DNN by Gamze Sokmen and Shamik Ghosh, making use of time information as new variables.
100+
Uses features : ['DeltaEta', 'DeltaPhi', 'multi_en', 'multi_eta', 'multi_pt', 'seedEta','seedPhi','seedEn', 'seedPt', theta', 'theta_xz_seedFrame', 'theta_yz_seedFrame', 'theta_xy_cmsFrame', 'theta_yz_cmsFrame', 'theta_xz_cmsFrame', 'explVar', 'explVarRatio', 'mod_deltaTime']
101+
*/
102+
103+
class SuperclusteringDNNInputV3 : public AbstractSuperclusteringDNNInput {
104+
public:
105+
unsigned int featureCount() const override { return 18; }
106+
107+
std::vector<float> computeVector(ticl::Trackster const& ts_base, ticl::Trackster const& ts_toCluster) override;
108+
109+
std::vector<std::string> featureNames() const override {
110+
return {"DeltaEtaBaryc",
111+
"DeltaPhiBaryc",
112+
"multi_en",
113+
"multi_eta",
114+
"multi_pt",
115+
"seedEta",
116+
"seedPhi",
117+
"seedEn",
118+
"seedPt",
119+
"theta",
120+
"theta_xz_seedFrame",
121+
"theta_yz_seedFrame",
122+
"theta_xy_cmsFrame",
123+
"theta_yz_cmsFrame",
124+
"theta_xz_cmsFrame",
125+
"explVar",
126+
"explVarRatio",
127+
"mod_deltaTime"};
128+
}
129+
};
130+
90131
std::unique_ptr<AbstractSuperclusteringDNNInput> makeSuperclusteringDNNInputFromString(std::string dnnVersion);
91132
} // namespace ticl
92133

93-
#endif
134+
#endif

RecoHGCal/TICL/plugins/SuperclusteringSampleDumper.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,8 @@ void SuperclusteringSampleDumper::fillDescriptions(edm::ConfigurationDescription
265265
->setComment("Input trackster collection, same as what is used for superclustering inference.");
266266
desc.add<edm::InputTag>("recoToSimAssociatorCP",
267267
edm::InputTag("tracksterSimTracksterAssociationLinkingbyCLUE3D", "recoToSim"));
268-
desc.ifValue(edm::ParameterDescription<std::string>("dnnInputsVersion", "v2", true),
269-
edm::allowedValues<std::string>("v1", "v2"))
268+
desc.ifValue(edm::ParameterDescription<std::string>("dnnInputsVersion", "v3", true),
269+
edm::allowedValues<std::string>("v1", "v2", "v3"))
270270
->setComment(
271271
"DNN inputs version tag. Defines which set of features is fed to the DNN. Must match with the actual DNN.");
272272
// Cuts are intentionally looser than those used for inference in TracksterLinkingBySuperClustering.cpp

RecoHGCal/TICL/plugins/TracksterLinkingbySuperClusteringDNN.cc

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
TICL plugin for electron superclustering in HGCAL using a DNN.
3-
DNN designed by Alessandro Tarabini.
3+
DNN designed by Alessandro Tarabini, Florian Beaudette, Gamze Sokmen, Shamik Ghosh, Theo Cuisset.
44
55
Inputs are CLUE3D EM tracksters. Outputs are superclusters (as vectors of IDs of trackster)
66
"Seed trackster" : seed of supercluster, always highest pT trackster of supercluster, normally should be an electron
@@ -18,6 +18,9 @@ The loop is first on candidate, then on seeds as it is more efficient for step 4
1818
1919
Authors : Theo Cuisset <[email protected]>, Shamik Ghosh <[email protected]>
2020
Date : 11/2023
21+
22+
Updates : Logic works as it should and switching to v3 (Shamik)
23+
Date: 07/2025
2124
*/
2225

2326
#include <string>
@@ -146,7 +149,8 @@ void TracksterLinkingbySuperClusteringDNN::linkTracksters(
146149
Trackster const& ts_cand = inputTracksters[trackstersIndicesPt[ts_cand_idx_pt]];
147150

148151
if (ts_cand.raw_energy() < candidateEnergyThreshold_ ||
149-
!checkExplainedVarianceRatioCut(ts_cand)) // || !trackstersPassesPIDCut(ts_cand)
152+
// !checkExplainedVarianceRatioCut(ts_cand)) // || !trackstersPassesPIDCut(ts_cand)
153+
!checkExplainedVarianceRatioCut(ts_cand)) // || !trackstersPassesPIDCut(ts_cand))
150154
continue;
151155

152156
auto& tracksterTiles = tracksterTilesBothEndcaps_pt[ts_cand.barycenter().eta() > 0];
@@ -245,37 +249,37 @@ void TracksterLinkingbySuperClusteringDNN::linkTracksters(
245249
Also mask seeds (only needed to add tracksters not in a supercluster to the output). */
246250
std::vector<bool> tracksterMask(tracksterCount, false);
247251

248-
/* Index of the seed trackster of the previous iteration
249-
Initialized with an id that cannot be obtained in input */
252+
/////////////////////////////////////////////////////////////////////////TRKBUILDINGMOD
253+
250254
unsigned int previousCandTrackster_idx = std::numeric_limits<unsigned int>::max();
251255
unsigned int bestSeedForCurrentCandidate_idx = std::numeric_limits<unsigned int>::max();
252256
float bestSeedForCurrentCandidate_dnnScore = nnWorkingPoint_;
253257

254-
// Lambda to be called when there is a transition from one candidate to the next (as well as after the last iteration)
255-
// Does the actual supercluster creation
258+
// Track which tracksters were ever used as candidates
259+
std::vector<bool> usedAsCandidate(tracksterCount, false);
260+
256261
auto onCandidateTransition = [&](unsigned ts_cand_idx) {
257-
if (bestSeedForCurrentCandidate_idx <
258-
std::numeric_limits<unsigned int>::max()) { // At least one seed can be superclustered with the candidate
259-
tracksterMask[ts_cand_idx] = true; // Mask the candidate so it is not considered as seed in later iterations
260-
261-
// Look for a supercluster of the seed
262-
std::vector<std::vector<unsigned int>>::iterator seed_supercluster_it =
263-
std::find_if(outputSuperclusters.begin(),
264-
outputSuperclusters.end(),
265-
[bestSeedForCurrentCandidate_idx](std::vector<unsigned int> const& sc) {
266-
return sc[0] == bestSeedForCurrentCandidate_idx;
267-
});
268-
269-
if (seed_supercluster_it == outputSuperclusters.end()) { // No supercluster exists yet for the seed. Create one.
262+
if (bestSeedForCurrentCandidate_idx < std::numeric_limits<unsigned int>::max()) {
263+
tracksterMask[ts_cand_idx] = true; // Mask the candidate so it’s not reused as a seed
264+
usedAsCandidate[ts_cand_idx] = true;
265+
266+
// Find the supercluster the seed belongs to (even if it's already used in another supercluster)
267+
// Find existing supercluster for the seed
268+
auto seed_supercluster_it = std::find_if(outputSuperclusters.begin(),
269+
outputSuperclusters.end(),
270+
[bestSeedForCurrentCandidate_idx](const std::vector<unsigned int>& sc) {
271+
return sc[0] == bestSeedForCurrentCandidate_idx;
272+
});
273+
if (seed_supercluster_it == outputSuperclusters.end()) {
274+
// No supercluster exists for this seed, create one
270275
outputSuperclusters.emplace_back(std::initializer_list<unsigned int>{bestSeedForCurrentCandidate_idx});
271276
resultTracksters.emplace_back(inputTracksters[bestSeedForCurrentCandidate_idx]);
272277
linkedTracksterIdToInputTracksterId.emplace_back(
273278
std::initializer_list<unsigned int>{bestSeedForCurrentCandidate_idx});
274279
seed_supercluster_it = outputSuperclusters.end() - 1;
275-
tracksterMask[bestSeedForCurrentCandidate_idx] =
276-
true; // mask the seed as well (needed to find tracksters not in any supercluster)
280+
tracksterMask[bestSeedForCurrentCandidate_idx] = true;
277281
}
278-
// Index of the supercluster into resultTracksters, outputSuperclusters and linkedTracksterIdToInputTracksterId collections (the indices are the same)
282+
279283
unsigned int indexIntoOutputTracksters = seed_supercluster_it - outputSuperclusters.begin();
280284
seed_supercluster_it->push_back(ts_cand_idx);
281285
resultTracksters[indexIntoOutputTracksters].mergeTracksters(inputTracksters[ts_cand_idx]);
@@ -290,10 +294,10 @@ void TracksterLinkingbySuperClusteringDNN::linkTracksters(
290294
}
291295
};
292296

293-
//Iterate over minibatches
297+
// Iterate over minibatches
294298
for (unsigned int batchIndex = 0; batchIndex < batchOutputs.size(); batchIndex++) {
295-
std::vector<float> const& currentBatchOutputs = batchOutputs[batchIndex]; // DNN score outputs
296-
// Iterate over seed-candidate pairs inside current minibatch
299+
std::vector<float> const& currentBatchOutputs = batchOutputs[batchIndex];
300+
297301
for (unsigned int indexInBatch = 0; indexInBatch < tracksterIndicesUsedInDNN[batchIndex].size(); indexInBatch++) {
298302
assert(indexInBatch < static_cast<unsigned int>(batchOutputs[batchIndex].size()));
299303

@@ -303,21 +307,21 @@ void TracksterLinkingbySuperClusteringDNN::linkTracksters(
303307

304308
if (previousCandTrackster_idx != std::numeric_limits<unsigned int>::max() &&
305309
ts_cand_idx != previousCandTrackster_idx) {
306-
// There is a transition from one seed to the next (don't make a transition for the first iteration)
307310
onCandidateTransition(previousCandTrackster_idx);
308311
}
309312

310-
if (currentDnnScore > bestSeedForCurrentCandidate_dnnScore && !tracksterMask[ts_seed_idx]) {
311-
// Check that the DNN suggests superclustering, that this seed-candidate assoc is better than previous ones, and that the seed is not already in a supercluster as candidate
313+
// Ignore seed if it was previously used as a candidate
314+
if (currentDnnScore > bestSeedForCurrentCandidate_dnnScore && !usedAsCandidate[ts_seed_idx]) {
312315
bestSeedForCurrentCandidate_idx = ts_seed_idx;
313316
bestSeedForCurrentCandidate_dnnScore = currentDnnScore;
314317
}
318+
315319
previousCandTrackster_idx = ts_cand_idx;
316320
}
317321
}
318322
onCandidateTransition(previousCandTrackster_idx);
319323

320-
// Adding one-trackster superclusters for all tracksters not in a supercluster already that pass the seed threshold
324+
// Create singleton superclusters for unused tracksters with enough pt
321325
for (unsigned int ts_id = 0; ts_id < tracksterCount; ts_id++) {
322326
if (!tracksterMask[ts_id] && inputTracksters[ts_id].raw_pt() >= seedPtThreshold_) {
323327
outputSuperclusters.emplace_back(std::initializer_list<unsigned int>{ts_id});
@@ -326,6 +330,8 @@ void TracksterLinkingbySuperClusteringDNN::linkTracksters(
326330
}
327331
}
328332

333+
/////////////////////////////////////////////////////////////////////////TRKBUILDINGMOD
334+
329335
#ifdef EDM_ML_DEBUG
330336
for (std::vector<unsigned int> const& sc : outputSuperclusters) {
331337
std::ostringstream s;
@@ -340,8 +346,8 @@ void TracksterLinkingbySuperClusteringDNN::linkTracksters(
340346
void TracksterLinkingbySuperClusteringDNN::fillPSetDescription(edm::ParameterSetDescription& desc) {
341347
TracksterLinkingAlgoBase::fillPSetDescription(desc); // adds algo_verbosity
342348
desc.add<edm::FileInPath>("onnxModelPath")->setComment("Path to DNN (as ONNX model)");
343-
desc.ifValue(edm::ParameterDescription<std::string>("dnnInputsVersion", "v2", true),
344-
edm::allowedValues<std::string>("v1", "v2"))
349+
desc.ifValue(edm::ParameterDescription<std::string>("dnnInputsVersion", "v3", true),
350+
edm::allowedValues<std::string>("v1", "v2", "v3"))
345351
->setComment(
346352
"DNN inputs version tag. Defines which set of features is fed to the DNN. Must match with the actual DNN.");
347353
desc.add<unsigned int>("inferenceBatchSize", 1e5)
@@ -379,4 +385,4 @@ void TracksterLinkingbySuperClusteringDNN::fillPSetDescription(edm::ParameterSet
379385
{static_cast<int>(Trackster::ParticleType::photon), static_cast<int>(Trackster::ParticleType::electron)})
380386
->setComment("List of PID particle types (ticl::Trackster::ParticleType enum) to consider for PID filtering");
381387
desc.add<double>("PIDThreshold", 0.8)->setComment("PID score threshold");
382-
}
388+
}

RecoHGCal/TICL/python/superclustering_cff.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
linkingPSet = cms.PSet(
1414
type=cms.string("SuperClusteringDNN"),
1515
algo_verbosity=cms.int32(0),
16-
onnxModelPath = cms.FileInPath("RecoHGCal/TICL/data/superclustering/supercls_v2p1.onnx"),
17-
nnWorkingPoint=cms.double(0.3),
16+
onnxModelPath = cms.FileInPath("RecoHGCal/TICL/data/superclustering/supercls_v3.onnx"),
17+
nnWorkingPoint=cms.double(0.57247),
1818
),
1919
tracksters_collections = [cms.InputTag("ticlTrackstersCLUE3DHigh")], # to be changed to ticlTrackstersCLUE3DEM once separate CLUE3D iterations are introduced
2020
)

0 commit comments

Comments
 (0)