diff --git a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py index 5ad73f2f7660a..9a8656728f849 100644 --- a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py +++ b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py @@ -857,7 +857,7 @@ def setup_(self, step, stepName, stepDict, k, properties): stepDict[stepName][k] = merge([self.step4, stepDict[step][k]]) def condition(self, fragment, stepList, key, hasHarvest): selected_fragments = ["TTbar_14TeV", "CloseByP", "Eta1p7_2p7", "ZEE_14"] - return (fragment in selected_fragments) and 'Run4' in key + return any(sf in fragment for sf in selected_fragments) and 'Run4' in key upgradeWFs['ticl_v5'] = UpgradeWorkflow_ticl_v5( steps = [ diff --git a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclCandidate_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclCandidate_cfi.py index efaa81a348abd..8786b790ac7f8 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclCandidate_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclCandidate_cfi.py @@ -1,6 +1,25 @@ import FWCore.ParameterSet.Config as cms hltTiclCandidate = cms.EDProducer("TICLCandidateProducer", + inferenceAlgo = cms.string('TracksterInferenceByPFN'), + regressionAndPid = cms.bool(True), + pluginInferenceAlgoTracksterInferenceByPFN = cms.PSet( + algo_verbosity = cms.int32(0), + onnxPIDModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/PFN/linking/id_v0.onnx'), + onnxEnergyModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/PFN/linking/energy_v0.onnx'), + inputNames = cms.vstring( + 'input', + 'input_tr_features' + ), + output_en = cms.vstring('enreg_output'), + output_id = cms.vstring('pid_output'), + eid_min_cluster_energy = cms.double(1), + eid_n_layers = cms.int32(50), + eid_n_clusters = cms.int32(10), + doPID = cms.int32(1), + doRegression = cms.int32(1), + type = cms.string('TracksterInferenceByPFN') + ), cutTk = cms.string('1.48 < abs(eta) < 3.0 && pt > 1. && quality("highPurity") && hitPattern().numberOfLostHits("MISSING_OUTER_HITS") < 5'), detector = cms.string('HGCAL'), egamma_tracksterlinks_collections = cms.VInputTag("hltTiclTracksterLinks"), diff --git a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinksL1Seeded_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinksL1Seeded_cfi.py index 367706fffeddc..f94091e6fea0f 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinksL1Seeded_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinksL1Seeded_cfi.py @@ -38,7 +38,7 @@ mightGet = cms.optional.untracked.vstring, original_masks = cms.VInputTag("hltMergeLayerClustersL1Seeded:InitialLayerClustersMask"), propagator = cms.string('PropagatorWithMaterial'), - regressionAndPid = cms.bool(True), + regressionAndPid = cms.bool(False), tracksters_collections = cms.VInputTag("hltTiclTrackstersCLUE3DHighL1Seeded", "hltTiclTrackstersRecoveryL1Seeded") ) diff --git a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py index b787e3fb03f82..057c16b1c6ae3 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py @@ -38,7 +38,7 @@ mightGet = cms.optional.untracked.vstring, original_masks = cms.VInputTag("hltMergeLayerClusters:InitialLayerClustersMask"), propagator = cms.string('PropagatorWithMaterial'), - regressionAndPid = cms.bool(True), + regressionAndPid = cms.bool(False), tracksters_collections = cms.VInputTag("hltTiclTrackstersCLUE3DHigh", "hltTiclTrackstersRecovery") ) diff --git a/HLTrigger/Configuration/python/HLT_75e33/psets/hltTiclTracksterLinksPSet_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/psets/hltTiclTracksterLinksPSet_cfi.py index 78f553e3d5871..d3f73a2fb1ff7 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/psets/hltTiclTracksterLinksPSet_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/psets/hltTiclTracksterLinksPSet_cfi.py @@ -18,11 +18,11 @@ 100 ), upper_distance_projective_sqr = cms.vdouble( - 30, + 4, 60 ), lower_distance_projective_sqr = cms.vdouble( - 30, + 4, 60 ), min_distance_z = cms.vdouble( diff --git a/RecoHGCal/TICL/plugins/GeneralInterpretationAlgo.cc b/RecoHGCal/TICL/plugins/GeneralInterpretationAlgo.cc index 4db2756038072..994494cac337d 100644 --- a/RecoHGCal/TICL/plugins/GeneralInterpretationAlgo.cc +++ b/RecoHGCal/TICL/plugins/GeneralInterpretationAlgo.cc @@ -375,18 +375,15 @@ void GeneralInterpretationAlgo::makeCandidates(const Inputs &input, // in this case mergeTracksters() clears the pid probabilities and the regressed energy is not set // TODO: fix probabilities when CNN will be splitted Trackster outTrackster; - float regr_en = 0.f; bool isHadron = false; - outTrackster.mergeTracksters(input.tracksters, trackstersInTrackIndices[iTrack]); for (auto const tracksterId : trackstersInTrackIndices[iTrack]) { //maskTracksters[tracksterId] = 0; - regr_en += input.tracksters[tracksterId].regressed_energy(); + outTrackster.mergeTracksters(input.tracksters[tracksterId]); if (input.tracksters[tracksterId].isHadronic()) isHadron = true; } resultCandidate[iTrack] = resultTracksters.size(); resultTracksters.push_back(outTrackster); - resultTracksters.back().setRegressedEnergy(regr_en); // since a track has been linked it can only be electron or charged hadron if (isHadron) resultTracksters.back().setIdProbability(ticl::Trackster::ParticleType::charged_hadron, 1.f); diff --git a/RecoHGCal/TICL/plugins/TICLCandidateProducer.cc b/RecoHGCal/TICL/plugins/TICLCandidateProducer.cc index f67841c5406ab..7a49e9a67f9e9 100644 --- a/RecoHGCal/TICL/plugins/TICLCandidateProducer.cc +++ b/RecoHGCal/TICL/plugins/TICLCandidateProducer.cc @@ -1,5 +1,4 @@ -// Author: Felice Pantaleo, Wahid Redjeb, Aurora Perego (CERN) - felice.pantaleo@cern.ch, wahid.redjeb@cern.ch, aurora.perego@cern.ch -// Date: 12/2023 +// Author: Felice Pantaleo, Wahid Redjeb, Aurora Perego (CERN) - felice.pantaleo@cern.ch, wahid.redjeb@cern.ch, aurora.perego@cern.ch Date: 12/2023 #include // unique_ptr #include "DataFormats/HGCalReco/interface/MultiVectorManager.h" #include "FWCore/Framework/interface/stream/EDProducer.h" @@ -47,22 +46,28 @@ #include "MagneticField/Engine/interface/MagneticField.h" #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h" +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" + #include "Geometry/HGCalCommonData/interface/HGCalDDDConstants.h" #include "Geometry/Records/interface/IdealGeometryRecord.h" #include "Geometry/CommonDetUnit/interface/GeomDet.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h" #include "TrackstersPCA.h" using namespace ticl; +using cms::Ort::ONNXRuntime; -class TICLCandidateProducer : public edm::stream::EDProducer<> { +class TICLCandidateProducer : public edm::stream::EDProducer> { public: - explicit TICLCandidateProducer(const edm::ParameterSet &ps); + explicit TICLCandidateProducer(const edm::ParameterSet &ps, const ONNXRuntime *); ~TICLCandidateProducer() override {} void produce(edm::Event &, const edm::EventSetup &) override; static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); void beginRun(edm::Run const &iEvent, edm::EventSetup const &es) override; + static std::unique_ptr initializeGlobalCache(const edm::ParameterSet &iConfig); + static void globalEndJob(const ONNXRuntime *); private: void dumpCandidate(const TICLCandidate &) const; @@ -82,6 +87,8 @@ class TICLCandidateProducer : public edm::stream::EDProducer<> { const edm::EDGetTokenT> clusters_token_; const edm::EDGetTokenT>> clustersTime_token_; + const bool regressionAndPid_; + std::unique_ptr inferenceAlgo_; std::vector>> original_masks_tokens_; @@ -113,10 +120,11 @@ class TICLCandidateProducer : public edm::stream::EDProducer<> { static constexpr float timeRes = 0.02f; }; -TICLCandidateProducer::TICLCandidateProducer(const edm::ParameterSet &ps) +TICLCandidateProducer::TICLCandidateProducer(const edm::ParameterSet &ps, const ONNXRuntime *) : clusters_token_(consumes>(ps.getParameter("layer_clusters"))), clustersTime_token_( consumes>>(ps.getParameter("layer_clustersTime"))), + regressionAndPid_(ps.getParameter("regressionAndPid")), tracks_token_(consumes>(ps.getParameter("tracks"))), muons_token_(consumes>(ps.getParameter("muons"))), useMTDTiming_(ps.getParameter("useMTDTiming")), @@ -168,6 +176,11 @@ TICLCandidateProducer::TICLCandidateProducer(const edm::ParameterSet &ps) if (useMTDTiming_) { inputTimingToken_ = consumes(ps.getParameter("timingSoA")); } + // Initialize inference algorithm using the factory + std::string inferencePlugin = ps.getParameter("inferenceAlgo"); + edm::ParameterSet inferencePSet = ps.getParameter("pluginInferenceAlgo" + inferencePlugin); + inferenceAlgo_ = std::unique_ptr( + TracksterInferenceAlgoFactory::get()->create(inferencePlugin, inferencePSet)); produces>(); @@ -180,6 +193,12 @@ TICLCandidateProducer::TICLCandidateProducer(const edm::ParameterSet &ps) TICLGeneralInterpretationPluginFactory::get()->create(algoType, interpretationPSet, consumesCollector()); } +std::unique_ptr TICLCandidateProducer::initializeGlobalCache(const edm::ParameterSet &iConfig) { + return std::unique_ptr(nullptr); +} + +void TICLCandidateProducer::globalEndJob(const ONNXRuntime *) {} + void TICLCandidateProducer::beginRun(edm::Run const &iEvent, edm::EventSetup const &es) { edm::ESHandle hdc = es.getHandle(hdc_token_); hgcons_ = hdc.product(); @@ -311,6 +330,12 @@ void TICLCandidateProducer::produce(edm::Event &evt, const edm::EventSetup &es) rhtools_.getPositionLayer(rhtools_.lastLayerEE()).z(), rhtools_, true); + if (regressionAndPid_) { + // Run inference algorithm + inferenceAlgo_->inputData(layerClusters, *resultTracksters); + inferenceAlgo_->runInference( + *resultTracksters); //option to use "Linking" instead of "CLU3D"/"energyAndPid" instead of "PID" + } std::vector maskTracksters(resultTracksters->size(), true); edm::OrphanHandle> resultTracksters_h = evt.put(std::move(resultTracksters)); @@ -326,16 +351,16 @@ void TICLCandidateProducer::produce(edm::Event &evt, const edm::EventSetup &es) maskTracksters[tracksterId] = false; } else { //charged candidates track only - edm::Ptr tracksterPtr; - TICLCandidate chargedCandidate(trackPtr, tracksterPtr); auto trackRef = edm::Ref(tracks_h, iTrack); const int muId = PFMuonAlgo::muAssocToTrack(trackRef, *muons_h); const reco::MuonRef muonRef = reco::MuonRef(muons_h, muId); if (muonRef.isNonnull() and muonRef->isGlobalMuon()) { // create muon candidate + edm::Ptr tracksterPtr; + TICLCandidate chargedCandidate(trackPtr, tracksterPtr); chargedCandidate.setPdgId(13 * trackPtr.get()->charge()); + resultCandidates->push_back(chargedCandidate); } - resultCandidates->push_back(chargedCandidate); } } } @@ -478,6 +503,9 @@ void TICLCandidateProducer::fillDescriptions(edm::ConfigurationDescriptions &des edm::ParameterSetDescription desc; edm::ParameterSetDescription interpretationDesc; interpretationDesc.addNode(edm::PluginDescription("type", "General", true)); + edm::ParameterSetDescription inferenceDesc; + inferenceDesc.addNode(edm::PluginDescription("type", "TracksterInferenceByPFN", true)); + desc.add("pluginInferenceAlgoTracksterInferenceByPFN", inferenceDesc); desc.add("interpretationDescPSet", interpretationDesc); desc.add>("egamma_tracksters_collections", {edm::InputTag("ticlTracksterLinks")}); desc.add>("egamma_tracksterlinks_collections", {edm::InputTag("ticlTracksterLinks")}); @@ -498,6 +526,8 @@ void TICLCandidateProducer::fillDescriptions(edm::ConfigurationDescriptions &des desc.add("cutTk", "1.48 < abs(eta) < 3.0 && pt > 1. && quality(\"highPurity\") && " "hitPattern().numberOfLostHits(\"MISSING_OUTER_HITS\") < 5"); + desc.add("regressionAndPid", true); + desc.add("inferenceAlgo", "TracksterInferenceByPFN"); descriptions.add("ticlCandidateProducer", desc); } diff --git a/RecoHGCal/TICL/plugins/TracksterLinkingbySkeletons.cc b/RecoHGCal/TICL/plugins/TracksterLinkingbySkeletons.cc index bfcbad2a93e4a..0619053e48663 100644 --- a/RecoHGCal/TICL/plugins/TracksterLinkingbySkeletons.cc +++ b/RecoHGCal/TICL/plugins/TracksterLinkingbySkeletons.cc @@ -274,7 +274,7 @@ bool TracksterLinkingbySkeletons::areCompatible(const ticl::Trackster &myTrackst const ticl::Trackster &otherTrackster, const std::array &mySkeleton, const std::array &otherSkeleton) { - float zVal_interface = rhtools_.getPositionLayer(rhtools_.lastLayerEE()).z(); + float zVal_interface = std::abs(rhtools_.getPositionLayer(rhtools_.lastLayerEE()).z()); if (!isGoodTrackster(myTrackster, mySkeleton, min_num_lcs_, min_trackster_energy_, pca_quality_th_)) { LogDebug("TracksterLinkingbySkeletons") << "Inner Trackster with energy " << myTrackster.raw_energy() << " Num LCs " @@ -286,12 +286,25 @@ bool TracksterLinkingbySkeletons::areCompatible(const ticl::Trackster &myTrackst << myTrackster.vertices().size() << " IS GOOD " << std::endl; float proj_distance = projective_distance(mySkeleton[1], otherSkeleton[1]); - auto isEE = mySkeleton[1].z() <= zVal_interface ? 0 : 1; + bool isInEE = std::abs(mySkeleton[1].z()) <= zVal_interface; + bool isOutEE = std::abs(otherSkeleton[1].z()) <= zVal_interface; + bool bothEE = (isInEE && isOutEE); // only check if they are aligned + + // inEE --> !outEE --> True + // inEE --> outEE --> False + // !inEE --> outEE --> False + // !inEE --> !outEE --> True + bool isLoose = (!isOutEE); + + if (bothEE) { //just don't try to link if two objects are in the CEE part (too much occupancy) + return false; + } + auto const max_distance_proj_sqr = computeParameter(myTrackster.raw_energy(), - lower_boundary_[isEE], - lower_distance_projective_sqr_[isEE], - upper_boundary_[isEE], - upper_distance_projective_sqr_[isEE]); + lower_boundary_[isLoose], + lower_distance_projective_sqr_[isLoose], + upper_boundary_[isLoose], + upper_distance_projective_sqr_[isLoose]); bool areAlignedInProjectiveSpace = proj_distance < max_distance_proj_sqr; LogDebug("TracksterLinkingbySkeletons") @@ -310,13 +323,10 @@ bool TracksterLinkingbySkeletons::areCompatible(const ticl::Trackster &myTrackst LogDebug("TracksterLinkingbySkeletons") << "\t\t Linked! Splitted components!" << std::endl; return true; } - //if is EE do not try to link more, PU occupancy is too high in this region - if (isEE) { - return false; - } + //if instead we are in the CE-H part of the detector, we can try to link more // we measure the distance between the two closest nodes in the two skeletons - return checkClosestPoints(myTrackster, otherTrackster, mySkeleton, otherSkeleton, isEE); + return checkClosestPoints(myTrackster, otherTrackster, mySkeleton, otherSkeleton, isLoose); } } else { if (otherTrackster.vertices().size() >= 3) { @@ -327,22 +337,22 @@ bool TracksterLinkingbySkeletons::areCompatible(const ticl::Trackster &myTrackst LogDebug("TracksterLinkingbySkeletons") << "\t Not aligned in projective space, check distance between closest points in the two skeletons " << std::endl; - if (checkClosestPoints(myTrackster, otherTrackster, mySkeleton, otherSkeleton, isEE)) { + if (checkClosestPoints(myTrackster, otherTrackster, mySkeleton, otherSkeleton, isLoose)) { return true; } else { - return checkCylinderAlignment(mySkeleton, otherSkeleton, isEE); + return checkCylinderAlignment(mySkeleton, otherSkeleton, isLoose); } } } else { - return checkCylinderAlignment(mySkeleton, otherSkeleton, isEE); + return checkCylinderAlignment(mySkeleton, otherSkeleton, isLoose); } } } bool TracksterLinkingbySkeletons::checkCylinderAlignment(const std::array &mySkeleton, const std::array &otherSkeleton, - int isEE) { - bool isInCyl = isInCylinder(mySkeleton, otherSkeleton, cylinder_radius_sqr_[isEE]); + int isLoose) { + bool isInCyl = isInCylinder(mySkeleton, otherSkeleton, cylinder_radius_sqr_[isLoose]); if (isInCyl) { LogDebug("TracksterLinkingbySkeletons") << "Two Points are in Cylinder " << isInCyl << " Linked! " << std::endl; } @@ -369,7 +379,7 @@ bool TracksterLinkingbySkeletons::checkClosestPoints(const ticl::Trackster &myTr const ticl::Trackster &otherTrackster, const std::array &mySkeleton, const std::array &otherSkeleton, - int isEE) { + int isLoose) { int myClosestPoint = -1; int otherClosestPoint = -1; float minDistance_z = std::numeric_limits::max(); @@ -387,24 +397,24 @@ bool TracksterLinkingbySkeletons::checkClosestPoints(const ticl::Trackster &myTr float d = projective_distance(mySkeleton[myClosestPoint], otherSkeleton[otherClosestPoint]); auto const max_distance_proj_sqr_closest = computeParameter(myTrackster.raw_energy(), - lower_boundary_[isEE], - lower_distance_projective_sqr_closest_points_[isEE], - upper_boundary_[isEE], - upper_distance_projective_sqr_closest_points_[isEE]); + lower_boundary_[isLoose], + lower_distance_projective_sqr_closest_points_[isLoose], + upper_boundary_[isLoose], + upper_distance_projective_sqr_closest_points_[isLoose]); LogDebug("TracksterLinkingbySkeletons") << "\t\t Distance between closest points " << d << " TH " << 10.f << " Z Distance " << minDistance_z << " TH " << max_distance_proj_sqr_closest << std::endl; - if (d < max_distance_proj_sqr_closest && minDistance_z < max_z_distance_closest_points_[isEE]) { + if (d < max_distance_proj_sqr_closest && minDistance_z < max_z_distance_closest_points_[isLoose]) { LogDebug("TracksterLinkingbySkeletons") << "\t\t\t Linked! " << d << std::endl; return true; } LogDebug("TracksterLinkingbySkeletons") << "Distance between closest point " << d << " Distance in z " - << max_z_distance_closest_points_[isEE] << std::endl; + << max_z_distance_closest_points_[isLoose] << std::endl; - return checkCylinderAlignment(mySkeleton, otherSkeleton, isEE); + return checkCylinderAlignment(mySkeleton, otherSkeleton, isLoose); } void TracksterLinkingbySkeletons::linkTracksters( diff --git a/RecoHGCal/TICL/python/iterativeTICL_cff.py b/RecoHGCal/TICL/python/iterativeTICL_cff.py index fceb6915f4b59..a1ca1de9928bd 100644 --- a/RecoHGCal/TICL/python/iterativeTICL_cff.py +++ b/RecoHGCal/TICL/python/iterativeTICL_cff.py @@ -52,11 +52,11 @@ 100 ), upper_distance_projective_sqr = cms.vdouble( - 30, + 4, 60 ), lower_distance_projective_sqr = cms.vdouble( - 30, + 4, 60 ), min_distance_z = cms.vdouble( @@ -84,7 +84,7 @@ type = cms.string('Skeletons') ), - regressionAndPid = cms.bool(True), + regressionAndPid = cms.bool(False), inferenceAlgo = cms.string('TracksterInferenceByPFN'), pluginInferenceAlgoTracksterInferenceByDNN = cms.PSet( algo_verbosity = cms.int32(0), @@ -115,7 +115,31 @@ type = cms.string('TracksterInferenceByPFN') ) ) -ticlCandidate = _ticlCandidateProducer.clone() + +ticlCandidate = _ticlCandidateProducer.clone( + inferenceAlgo=cms.string('TracksterInferenceByPFN'), + regressionAndPid = cms.bool(True), + pluginInferenceAlgoTracksterInferenceByPFN=cms.PSet( + algo_verbosity=cms.int32(0), + onnxPIDModelPath=cms.FileInPath( + 'RecoHGCal/TICL/data/ticlv5/onnx_models/PFN/linking/id_v0.onnx'), + onnxEnergyModelPath=cms.FileInPath( + 'RecoHGCal/TICL/data/ticlv5/onnx_models/PFN/linking/energy_v0.onnx'), + inputNames=cms.vstring( + 'input', + 'input_tr_features' + ), + output_en=cms.vstring('enreg_output'), + output_id=cms.vstring('pid_output'), + eid_min_cluster_energy=cms.double(1), + eid_n_layers=cms.int32(50), + eid_n_clusters=cms.int32(10), + doPID=cms.int32(1), + doRegression=cms.int32(1), + type=cms.string('TracksterInferenceByPFN') + ) +) + mtdSoA = _mtdSoAProducer.clone() pfTICL = _pfTICLProducer.clone()