diff --git a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py index 568d8e70d88ce..396c3d3c8f11f 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTracksterLinks_cfi.py @@ -2,14 +2,9 @@ hltTiclTracksterLinks = cms.EDProducer("TracksterLinksProducer", detector = cms.string('HGCAL'), - eid_input_name = cms.string('input'), - eid_min_cluster_energy = cms.double(2.5), - eid_n_clusters = cms.int32(10), - eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), layer_clusters = cms.InputTag("hltHgcalMergeLayerClusters"), layer_clustersTime = cms.InputTag("hltHgcalMergeLayerClusters","timeLayerCluster"), + inferenceAlgo = cms.string('TracksterInferenceByDNN'), linkingPSet = cms.PSet( algo_verbosity = cms.int32(0), cylinder_radius_sqr = cms.vdouble(9, 9), @@ -25,10 +20,25 @@ type = cms.string('Skeletons'), wind = cms.double(0.036) ), + pluginInferenceAlgoTracksterInferenceByDNN = cms.PSet( + algo_verbosity = cms.int32(0), + onnxPIDModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/linking/id_v0.onnx'), + onnxEnergyModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/linking/energy_v0.onnx'), + inputNames = cms.vstring('input'), + 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('TracksterInferenceByDNN') + ), mightGet = cms.optional.untracked.vstring, original_masks = cms.VInputTag("hltHgcalMergeLayerClusters:InitialLayerClustersMask"), propagator = cms.string('PropagatorWithMaterial'), regressionAndPid = cms.bool(True), - tfDnnLabel = cms.string('tracksterSelectionTf'), tracksters_collections = cms.VInputTag("hltTiclTrackstersCLUE3DHigh", "hltTiclTrackstersPassthrough") ) + + diff --git a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHighL1Seeded_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHighL1Seeded_cfi.py index 673f0d83e7d1d..4a5bd170978a7 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHighL1Seeded_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHighL1Seeded_cfi.py @@ -10,14 +10,9 @@ mightGet = cms.optional.untracked.vstring, original_mask = cms.InputTag("hltHgcalMergeLayerClustersL1Seeded","InitialLayerClustersMask"), patternRecognitionBy = cms.string('CLUE3D'), + inferenceAlgo = cms.string('TracksterInferenceByCNNv4'), pluginPatternRecognitionByCA = cms.PSet( algo_verbosity = cms.int32(0), - eid_input_name = cms.string('input'), - eid_min_cluster_energy = cms.double(1), - eid_n_clusters = cms.int32(10), - eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), energy_em_over_total_threshold = cms.double(-1), etaLimitIncreaseWindow = cms.double(2.1), filter_on_categories = cms.vint32(0), @@ -100,34 +95,51 @@ 2, 2 ), - eid_input_name = cms.string('input'), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), - eid_min_cluster_energy = cms.double(1), - eid_n_layers = cms.int32(50), - eid_n_clusters = cms.int32(10), computeLocalTime = cms.bool(False), doPidCut = cms.bool(True), cutHadProb = cms.double(999.), type = cms.string('CLUE3D') - ), pluginPatternRecognitionByFastJet = cms.PSet( algo_verbosity = cms.int32(0), antikt_radius = cms.double(0.09), - eid_input_name = cms.string('input'), + minNumLayerCluster = cms.int32(5), + type = cms.string('FastJet') + ), + pluginInferenceAlgoTracksterInferenceByCNNv4 = cms.PSet( + algo_verbosity = cms.int32(0), + onnxModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv4/onnx_models/energy_id_v0.onnx'), + inputNames = cms.vstring('input:0'), + outputNames = cms.vstring("output/regressed_energy:0", "output/id_probabilities:0"), 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(0), + type = cms.string('TracksterInferenceByCNNv4') + ), + pluginInferenceAlgoTracksterInferenceByDNN = cms.PSet( + algo_verbosity = cms.int32(0), + onnxPIDModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/id_v0.onnx'), + onnxEnergyModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/energy_v0.onnx'), + inputNames = cms.vstring('input'), + output_en = cms.vstring('enreg_output'), + output_id = cms.vstring('pid_output'), eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), - minNumLayerCluster = cms.int32(5), - type = cms.string('FastJet') + eid_n_clusters = cms.int32(10), + doPID = cms.int32(1), + doRegression = cms.int32(0), + type = cms.string('TracksterInferenceByDNN') + ), + pluginInferenceAlgoTracksterInferenceByANN = cms.PSet( + algo_verbosity = cms.int32(0), + type = cms.string('TracksterInferenceByANN') + ), seeding_regions = cms.InputTag("hltTiclSeedingL1"), - tfDnnLabel = cms.string('tracksterSelectionTf'), - time_layerclusters = cms.InputTag("hltHgcalMergeLayerClustersL1Seeded","timeLayerCluster") + time_layerclusters = cms.InputTag("hltHgcalMergeLayerClustersL1Seeded","timeLayerCluster"), ) from Configuration.ProcessModifiers.ticl_v5_cff import ticl_v5 ticl_v5.toModify(hltTiclTrackstersCLUE3DHighL1Seeded.pluginPatternRecognitionByCLUE3D, computeLocalTime = cms.bool(True), doPidCut = cms.bool(False)) +ticl_v5.toModify(hltTiclTrackstersCLUE3DHighL1Seeded.inferenceAlgo, type = cms.string('TracksterInferenceByDNN')) diff --git a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHigh_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHigh_cfi.py index 57436cfbfbd87..88b4cd7b7ab84 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHigh_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersCLUE3DHigh_cfi.py @@ -10,14 +10,9 @@ mightGet = cms.optional.untracked.vstring, original_mask = cms.InputTag("hltHgcalMergeLayerClusters","InitialLayerClustersMask"), patternRecognitionBy = cms.string('CLUE3D'), + inferenceAlgo = cms.string('TracksterInferenceByCNNv4'), pluginPatternRecognitionByCA = cms.PSet( algo_verbosity = cms.int32(0), - eid_input_name = cms.string('input'), - eid_min_cluster_energy = cms.double(1), - eid_n_clusters = cms.int32(10), - eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), energy_em_over_total_threshold = cms.double(-1), etaLimitIncreaseWindow = cms.double(2.1), filter_on_categories = cms.vint32(0), @@ -100,12 +95,6 @@ 2, 2 ), - eid_input_name = cms.string('input'), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), - eid_min_cluster_energy = cms.double(1), - eid_n_layers = cms.int32(50), - eid_n_clusters = cms.int32(10), computeLocalTime = cms.bool(False), doPidCut = cms.bool(True), cutHadProb = cms.double(999.), @@ -115,19 +104,43 @@ pluginPatternRecognitionByFastJet = cms.PSet( algo_verbosity = cms.int32(0), antikt_radius = cms.double(0.09), - eid_input_name = cms.string('input'), + minNumLayerCluster = cms.int32(5), + type = cms.string('FastJet') + ), + pluginInferenceAlgoTracksterInferenceByCNNv4 = cms.PSet( + algo_verbosity = cms.int32(0), + onnxModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv4/onnx_models/energy_id_v0.onnx'), + inputNames = cms.vstring('input:0'), + outputNames = cms.vstring("output/regressed_energy:0", "output/id_probabilities:0"), 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(0), + type = cms.string('TracksterInferenceByCNNv4') + ), + pluginInferenceAlgoTracksterInferenceByDNN = cms.PSet( + algo_verbosity = cms.int32(0), + onnxPIDModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/id_v0.onnx'), + onnxEnergyModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/energy_v0.onnx'), + inputNames = cms.vstring('input'), + output_en = cms.vstring('enreg_output'), + output_id = cms.vstring('pid_output'), eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), - minNumLayerCluster = cms.int32(5), - type = cms.string('FastJet') + eid_n_clusters = cms.int32(10), + doPID = cms.int32(1), + doRegression = cms.int32(0), + type = cms.string('TracksterInferenceByDNN') + ), + pluginInferenceAlgoTracksterInferenceByANN = cms.PSet( + algo_verbosity = cms.int32(0), + type = cms.string('TracksterInferenceByANN') + ), seeding_regions = cms.InputTag("hltTiclSeedingGlobal"), - tfDnnLabel = cms.string('tracksterSelectionTf'), time_layerclusters = cms.InputTag("hltHgcalMergeLayerClusters","timeLayerCluster") -) - + ) + from Configuration.ProcessModifiers.ticl_v5_cff import ticl_v5 ticl_v5.toModify(hltTiclTrackstersCLUE3DHigh.pluginPatternRecognitionByCLUE3D, computeLocalTime = cms.bool(True), doPidCut = cms.bool(False)) +ticl_v5.toModify(hltTiclTrackstersCLUE3DHigh.inferenceAlgo, type = cms.string('TracksterInferenceByDNN')) diff --git a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersPassthrough_cfi.py b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersPassthrough_cfi.py index 4fedc0e0b1d41..aa34abef3f2f4 100644 --- a/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersPassthrough_cfi.py +++ b/HLTrigger/Configuration/python/HLT_75e33/modules/hltTiclTrackstersPassthrough_cfi.py @@ -10,15 +10,10 @@ mightGet = cms.optional.untracked.vstring, original_mask = cms.InputTag("hltTiclTrackstersCLUE3DHigh"), patternRecognitionBy = cms.string('Passthrough'), + inferenceAlgo = cms.string('TracksterInferenceByDNN'), pluginPatternRecognitionByCA = cms.PSet( algo_verbosity = cms.int32(0), computeLocalTime = cms.bool(True), - eid_input_name = cms.string('input'), - eid_min_cluster_energy = cms.double(1), - eid_n_clusters = cms.int32(10), - eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), energy_em_over_total_threshold = cms.double(-1), etaLimitIncreaseWindow = cms.double(2.1), filter_on_categories = cms.vint32(0), @@ -53,12 +48,6 @@ densitySiblingLayers = cms.vint32(3, 3, 3), densityXYDistanceSqr = cms.vdouble(3.24, 3.24, 3.24), doPidCut = cms.bool(False), - eid_input_name = cms.string('input'), - eid_min_cluster_energy = cms.double(1), - eid_n_clusters = cms.int32(10), - eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), kernelDensityFactor = cms.vdouble(0.2, 0.2, 0.2), minNumLayerCluster = cms.vint32(2, 2, 2), nearestHigherOnSameLayer = cms.bool(False), @@ -72,12 +61,6 @@ algo_verbosity = cms.int32(0), antikt_radius = cms.double(0.09), computeLocalTime = cms.bool(True), - eid_input_name = cms.string('input'), - eid_min_cluster_energy = cms.double(1), - eid_n_clusters = cms.int32(10), - eid_n_layers = cms.int32(50), - eid_output_name_energy = cms.string('output/regressed_energy'), - eid_output_name_id = cms.string('output/id_probabilities'), minNumLayerCluster = cms.int32(5), type = cms.string('FastJet') ), @@ -85,7 +68,26 @@ algo_verbosity = cms.int32(0), type = cms.string('Passthrough') ), + + pluginInferenceAlgoTracksterInferenceByDNN = cms.PSet( + algo_verbosity = cms.int32(0), + onnxPIDModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/id_v0.onnx'), + onnxEnergyModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/energy_v0.onnx'), + inputNames = cms.vstring('input'), + 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(0), + doRegression = cms.int32(0), + type = cms.string('TracksterInferenceByDNN') + ), + pluginInferenceAlgoTracksterInferenceByANN = cms.PSet( + algo_verbosity = cms.int32(0), + type = cms.string('TracksterInferenceByANN') + + ), seeding_regions = cms.InputTag("hltTiclSeedingGlobal"), - tfDnnLabel = cms.string('tracksterSelectionTf'), time_layerclusters = cms.InputTag("hltHgcalMergeLayerClusters","timeLayerCluster") ) diff --git a/RecoHGCal/TICL/BuildFile.xml b/RecoHGCal/TICL/BuildFile.xml index fc31796e1bd74..75a12c12c5e41 100644 --- a/RecoHGCal/TICL/BuildFile.xml +++ b/RecoHGCal/TICL/BuildFile.xml @@ -4,6 +4,7 @@ + diff --git a/RecoHGCal/TICL/interface/PatternRecognitionAlgoBase.h b/RecoHGCal/TICL/interface/PatternRecognitionAlgoBase.h index 2658443104721..fd337ed71df29 100644 --- a/RecoHGCal/TICL/interface/PatternRecognitionAlgoBase.h +++ b/RecoHGCal/TICL/interface/PatternRecognitionAlgoBase.h @@ -6,6 +6,8 @@ #include #include +#include +#include #include "DataFormats/CaloRecHit/interface/CaloCluster.h" #include "DataFormats/HGCalReco/interface/Trackster.h" #include "DataFormats/HGCalReco/interface/TICLLayerTile.h" @@ -28,7 +30,7 @@ namespace ticl { public: PatternRecognitionAlgoBaseT(const edm::ParameterSet& conf, edm::ConsumesCollector) : algo_verbosity_(conf.getParameter("algo_verbosity")) {} - virtual ~PatternRecognitionAlgoBaseT(){}; + virtual ~PatternRecognitionAlgoBaseT() {}; struct Inputs { const edm::Event& ev; @@ -38,23 +40,25 @@ namespace ticl { const edm::ValueMap>& layerClustersTime; const TILES& tiles; const std::vector& regions; - const tensorflow::Session* tfSession; - Inputs(const edm::Event& eV, const edm::EventSetup& eS, const std::vector& lC, const std::vector& mS, const edm::ValueMap>& lT, const TILES& tL, - const std::vector& rG, - const tensorflow::Session* tS) - : ev(eV), es(eS), layerClusters(lC), mask(mS), layerClustersTime(lT), tiles(tL), regions(rG), tfSession(tS) {} + const std::vector& rG) + : ev(eV), es(eS), layerClusters(lC), mask(mS), layerClustersTime(lT), tiles(tL), regions(rG) {} }; virtual void makeTracksters(const Inputs& input, std::vector& result, std::unordered_map>& seedToTracksterAssociation) = 0; + virtual void filter(std::vector& output, + const std::vector& inTracksters, + const Inputs& input, + std::unordered_map>& seedToTracksterAssociation) = 0; + protected: int algo_verbosity_; }; diff --git a/RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h b/RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h new file mode 100644 index 0000000000000..f4ec06b87f11b --- /dev/null +++ b/RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h @@ -0,0 +1,38 @@ +// Author: Felice Pantaleo - felice.pantaleo@cern.ch +// Date: 07/2024 + +#ifndef RecoHGCal_TICL_TracksterInferenceAlgo_H__ +#define RecoHGCal_TICL_TracksterInferenceAlgo_H__ + +#include +#include "DataFormats/HGCalReco/interface/Trackster.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" + +#include "DataFormats/Candidate/interface/Candidate.h" +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "DataFormats/CaloRecHit/interface/CaloCluster.h" +#include "DataFormats/HGCalReco/interface/TICLCandidate.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" +#include "FWCore/PluginManager/interface/PluginFactory.h" + +namespace ticl { + class TracksterInferenceAlgoBase { + public: + explicit TracksterInferenceAlgoBase(const edm::ParameterSet& conf) + : algo_verbosity_(conf.getParameter("algo_verbosity")) {} + virtual ~TracksterInferenceAlgoBase() {} + + virtual void inputData(const std::vector& layerClusters, std::vector& tracksters) = 0; + virtual void runInference(std::vector& tracksters) = 0; + static void fillPSetDescription(edm::ParameterSetDescription& desc) { desc.add("algo_verbosity", 0); }; + + protected: + int algo_verbosity_; + }; +} // namespace ticl + +#endif diff --git a/RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h b/RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h new file mode 100644 index 0000000000000..9ad204ce647b3 --- /dev/null +++ b/RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h @@ -0,0 +1,15 @@ +// Author: Felice Pantaleo - felice.pantaleo@cern.ch +// Date: 07/2024 + +#ifndef RecoHGCal_TICL_TracksterInferenceAlgoFactory_H__ +#define RecoHGCal_TICL_TracksterInferenceAlgoFactory_H__ + +#include "FWCore/PluginManager/interface/PluginFactory.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h" + +typedef edmplugin::PluginFactory + TracksterInferenceAlgoFactory; + +#endif diff --git a/RecoHGCal/TICL/interface/TracksterInferenceByANN.h b/RecoHGCal/TICL/interface/TracksterInferenceByANN.h new file mode 100644 index 0000000000000..e323d5f3d35c5 --- /dev/null +++ b/RecoHGCal/TICL/interface/TracksterInferenceByANN.h @@ -0,0 +1,19 @@ +#ifndef RecoHGCal_TICL_TracksterInferenceByANN_H__ +#define RecoHGCal_TICL_TracksterInferenceByANN_H__ + +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h" + +namespace ticl { + class TracksterInferenceByANN : public TracksterInferenceAlgoBase { + public: + explicit TracksterInferenceByANN(const edm::ParameterSet& conf); + void inputData(const std::vector& layerClusters, std::vector& tracksters) override; + void runInference(std::vector& tracksters) override; + + private: + const cms::Ort::ONNXRuntime* onnxPIDSession_; + const cms::Ort::ONNXRuntime* onnxEnergySession_; + }; +} // namespace ticl + +#endif diff --git a/RecoHGCal/TICL/interface/TracksterInferenceByCNNv4.h b/RecoHGCal/TICL/interface/TracksterInferenceByCNNv4.h new file mode 100644 index 0000000000000..db12d1006af4b --- /dev/null +++ b/RecoHGCal/TICL/interface/TracksterInferenceByCNNv4.h @@ -0,0 +1,38 @@ +#ifndef RecoHGCal_TICL_TracksterInferenceByCNNv4_H__ +#define RecoHGCal_TICL_TracksterInferenceByCNNv4_H__ + +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h" +#include "RecoLocalCalo/HGCalRecAlgos/interface/RecHitTools.h" + +namespace ticl { + + class TracksterInferenceByCNNv4 : public TracksterInferenceAlgoBase { + public: + explicit TracksterInferenceByCNNv4(const edm::ParameterSet& conf); + void inputData(const std::vector& layerClusters, std::vector& tracksters) override; + void runInference(std::vector& tracksters) override; + + static void fillPSetDescription(edm::ParameterSetDescription& iDesc); + + private: + const cms::Ort::ONNXRuntime* onnxSession_; + + const std::string modelPath_; + const std::vector inputNames_; + const std::vector outputNames_; + const float eidMinClusterEnergy_; + const int eidNLayers_; + const int eidNClusters_; + static constexpr int eidNFeatures_ = 3; + int doPID_; + int doRegression_; + + hgcal::RecHitTools rhtools_; + std::vector> input_shapes_; + std::vector tracksterIndices_; + std::vector> input_Data_; + int batchSize_; + }; +} // namespace ticl + +#endif // RecoHGCal_TICL_TracksterInferenceByDNN_H__ diff --git a/RecoHGCal/TICL/interface/TracksterInferenceByDNN.h b/RecoHGCal/TICL/interface/TracksterInferenceByDNN.h new file mode 100644 index 0000000000000..9a1723b37bdb5 --- /dev/null +++ b/RecoHGCal/TICL/interface/TracksterInferenceByDNN.h @@ -0,0 +1,41 @@ +#ifndef RecoHGCal_TICL_TracksterInferenceByDNN_H__ +#define RecoHGCal_TICL_TracksterInferenceByDNN_H__ + +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h" +#include "RecoLocalCalo/HGCalRecAlgos/interface/RecHitTools.h" + +namespace ticl { + + class TracksterInferenceByDNN : public TracksterInferenceAlgoBase { + public: + explicit TracksterInferenceByDNN(const edm::ParameterSet& conf); + void inputData(const std::vector& layerClusters, std::vector& tracksters) override; + void runInference(std::vector& tracksters) override; + + static void fillPSetDescription(edm::ParameterSetDescription& iDesc); + + private: + const cms::Ort::ONNXRuntime* onnxPIDSession_; + const cms::Ort::ONNXRuntime* onnxEnergySession_; + + const std::string id_modelPath_; + const std::string en_modelPath_; + const std::vector inputNames_; + const std::vector output_en_; + const std::vector output_id_; + const float eidMinClusterEnergy_; + const int eidNLayers_; + const int eidNClusters_; + static constexpr int eidNFeatures_ = 3; + int doPID_; + int doRegression_; + + hgcal::RecHitTools rhtools_; + std::vector> input_shapes_; + std::vector tracksterIndices_; + std::vector> input_Data_; + int batchSize_; + }; +} // namespace ticl + +#endif // RecoHGCal_TICL_TracksterInferenceByDNN_H__ diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.cc b/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.cc index 11500c7597a29..83b0a98ef4b00 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.cc +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.cc @@ -40,12 +40,6 @@ PatternRecognitionbyCA::PatternRecognitionbyCA(const edm::ParameterSet &c max_longitudinal_sigmaPCA_(conf.getParameter("max_longitudinal_sigmaPCA")), min_clusters_per_ntuplet_(min_layers_per_trackster_), max_delta_time_(conf.getParameter("max_delta_time")), - eidInputName_(conf.getParameter("eid_input_name")), - eidOutputNameEnergy_(conf.getParameter("eid_output_name_energy")), - eidOutputNameId_(conf.getParameter("eid_output_name_id")), - eidMinClusterEnergy_(conf.getParameter("eid_min_cluster_energy")), - eidNLayers_(conf.getParameter("eid_n_layers")), - eidNClusters_(conf.getParameter("eid_n_clusters")), computeLocalTime_(conf.getParameter("computeLocalTime")), siblings_maxRSquared_(conf.getParameter>("siblings_maxRSquared")){}; @@ -75,7 +69,6 @@ void PatternRecognitionbyCA::makeTracksters( constexpr int nEtaBin = TILES::constants_type_t::nEtaBins; constexpr int nPhiBin = TILES::constants_type_t::nPhiBins; - bool isRegionalIter = (input.regions[0].index != -1); std::vector foundNtuplets; std::vector seedIndices; std::vector layer_cluster_usage(input.layerClusters.size(), 0); @@ -105,8 +98,7 @@ void PatternRecognitionbyCA::makeTracksters( int tracksterId = -1; // container for holding tracksters before selection - std::vector tmpTracksters; - tmpTracksters.reserve(foundNtuplets.size()); + result.reserve(foundNtuplets.size()); for (auto const &ntuplet : foundNtuplets) { tracksterId++; @@ -177,25 +169,25 @@ void PatternRecognitionbyCA::makeTracksters( tmp.setSeed(input.regions[0].collectionID, seedIndices[tracksterId]); std::copy(std::begin(effective_cluster_idx), std::end(effective_cluster_idx), std::back_inserter(tmp.vertices())); - tmpTracksters.push_back(tmp); + result.push_back(tmp); } } - ticl::assignPCAtoTracksters(tmpTracksters, + ticl::assignPCAtoTracksters(result, input.layerClusters, input.layerClustersTime, rhtools_.getPositionLayer(rhtools_.lastLayerEE(isHFnose), isHFnose).z(), rhtools_, computeLocalTime_); - // run energy regression and ID - energyRegressionAndID(input.layerClusters, input.tfSession, tmpTracksters); - // Filter results based on PID criteria or EM/Total energy ratio. - // We want to **keep** tracksters whose cumulative - // probability summed up over the selected categories - // is greater than the chosen threshold. Therefore - // the filtering function should **discard** all - // tracksters **below** the threshold. - auto filter_on_pids = [&](Trackster &t) -> bool { + theGraph_->clear(); +} + +template +void PatternRecognitionbyCA::filter(std::vector &output, + const std::vector &inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs &input, + std::unordered_map> &seedToTracksterAssociation) { + auto filter_on_pids = [&](const ticl::Trackster &t) -> bool { auto cumulative_prob = 0.; for (auto index : filter_on_categories_) { cumulative_prob += t.id_probabilities(index); @@ -205,62 +197,37 @@ void PatternRecognitionbyCA::makeTracksters( }; std::vector selectedTrackstersIds; - for (unsigned i = 0; i < tmpTracksters.size(); ++i) { - if (!filter_on_pids(tmpTracksters[i]) and tmpTracksters[i].sigmasPCA()[0] < max_longitudinal_sigmaPCA_) { + for (unsigned i = 0; i < inTracksters.size(); ++i) { + auto &t = inTracksters[i]; + if (!filter_on_pids(t) and t.sigmasPCA()[0] < max_longitudinal_sigmaPCA_) { selectedTrackstersIds.push_back(i); } } - - result.reserve(selectedTrackstersIds.size()); - + output.reserve(selectedTrackstersIds.size()); + bool isRegionalIter = (input.regions[0].index != -1); for (unsigned i = 0; i < selectedTrackstersIds.size(); ++i) { - const auto &t = tmpTracksters[selectedTrackstersIds[i]]; - for (auto const lcId : t.vertices()) { - layer_cluster_usage[lcId]++; - if (PatternRecognitionAlgoBaseT::algo_verbosity_ > VerbosityLevel::Basic) - LogDebug("HGCPatternRecoByCA") << "LayerID: " << lcId << " count: " << (int)layer_cluster_usage[lcId] - << std::endl; - } + const auto &t = inTracksters[selectedTrackstersIds[i]]; if (isRegionalIter) { seedToTracksterAssociation[t.seedIndex()].push_back(i); } - result.push_back(t); + output.push_back(t); } - for (auto &trackster : result) { - assert(trackster.vertices().size() <= trackster.vertex_multiplicity().size()); - for (size_t i = 0; i < trackster.vertices().size(); ++i) { - trackster.vertex_multiplicity()[i] = layer_cluster_usage[trackster.vertices(i)]; - if (PatternRecognitionAlgoBaseT::algo_verbosity_ > VerbosityLevel::Basic) - LogDebug("HGCPatternRecoByCA") << "LayerID: " << trackster.vertices(i) - << " count: " << (int)trackster.vertex_multiplicity(i) << std::endl; - } - } // Now decide if the tracksters from the track-based iterations have to be merged if (oneTracksterPerTrackSeed_) { std::vector tmp; - mergeTrackstersTRK(result, input.layerClusters, tmp, seedToTracksterAssociation); - tmp.swap(result); + mergeTrackstersTRK(output, input.layerClusters, tmp, seedToTracksterAssociation); + tmp.swap(output); } - ticl::assignPCAtoTracksters(result, - input.layerClusters, - input.layerClustersTime, - rhtools_.getPositionLayer(rhtools_.lastLayerEE(isHFnose), isHFnose).z(), - rhtools_, - computeLocalTime_); - - // run energy regression and ID - energyRegressionAndID(input.layerClusters, input.tfSession, result); - // now adding dummy tracksters from seeds not connected to any shower in the result collection // these are marked as charged hadrons with probability 1. if (promoteEmptyRegionToTrackster_) { - emptyTrackstersFromSeedsTRK(result, seedToTracksterAssociation, input.regions[0].collectionID); + emptyTrackstersFromSeedsTRK(output, seedToTracksterAssociation, input.regions[0].collectionID); } if (PatternRecognitionAlgoBaseT::algo_verbosity_ > VerbosityLevel::Advanced) { - for (auto &trackster : result) { + for (auto &trackster : output) { LogDebug("HGCPatternRecoByCA") << "Trackster characteristics: " << std::endl; LogDebug("HGCPatternRecoByCA") << "Size: " << trackster.vertices().size() << std::endl; auto counter = 0; @@ -269,9 +236,7 @@ void PatternRecognitionbyCA::makeTracksters( } } } - theGraph_->clear(); } - template void PatternRecognitionbyCA::mergeTrackstersTRK( const std::vector &input, @@ -347,146 +312,6 @@ void PatternRecognitionbyCA::emptyTrackstersFromSeedsTRK( } } -template -void PatternRecognitionbyCA::energyRegressionAndID(const std::vector &layerClusters, - const tensorflow::Session *eidSession, - std::vector &tracksters) { - // Energy regression and particle identification strategy: - // - // 1. Set default values for regressed energy and particle id for each trackster. - // 2. Store indices of tracksters whose total sum of cluster energies is above the - // eidMinClusterEnergy_ (GeV) threshold. Inference is not applied for soft tracksters. - // 3. When no trackster passes the selection, return. - // 4. Create input and output tensors. The batch dimension is determined by the number of - // selected tracksters. - // 5. Fill input tensors with layer cluster features. Per layer, clusters are ordered descending - // by energy. Given that tensor data is contiguous in memory, we can use pointer arithmetic to - // fill values, even with batching. - // 6. Zero-fill features for empty clusters in each layer. - // 7. Batched inference. - // 8. Assign the regressed energy and id probabilities to each trackster. - // - // Indices used throughout this method: - // i -> batch element / trackster - // j -> layer - // k -> cluster - // l -> feature - - // set default values per trackster, determine if the cluster energy threshold is passed, - // and store indices of hard tracksters - std::vector tracksterIndices; - for (int i = 0; i < (int)tracksters.size(); i++) { - // calculate the cluster energy sum (2) - // note: after the loop, sumClusterEnergy might be just above the threshold which is enough to - // decide whether to run inference for the trackster or not - float sumClusterEnergy = 0.; - for (const unsigned int &vertex : tracksters[i].vertices()) { - sumClusterEnergy += (float)layerClusters[vertex].energy(); - // there might be many clusters, so try to stop early - if (sumClusterEnergy >= eidMinClusterEnergy_) { - // set default values (1) - tracksters[i].setRegressedEnergy(0.f); - tracksters[i].zeroProbabilities(); - tracksterIndices.push_back(i); - break; - } - } - } - - // do nothing when no trackster passes the selection (3) - int batchSize = (int)tracksterIndices.size(); - if (batchSize == 0) { - return; - } - - // create input and output tensors (4) - tensorflow::TensorShape shape({batchSize, eidNLayers_, eidNClusters_, eidNFeatures_}); - tensorflow::Tensor input(tensorflow::DT_FLOAT, shape); - tensorflow::NamedTensorList inputList = {{eidInputName_, input}}; - - std::vector outputs; - std::vector outputNames; - if (!eidOutputNameEnergy_.empty()) { - outputNames.push_back(eidOutputNameEnergy_); - } - if (!eidOutputNameId_.empty()) { - outputNames.push_back(eidOutputNameId_); - } - - // fill input tensor (5) - for (int i = 0; i < batchSize; i++) { - const Trackster &trackster = tracksters[tracksterIndices[i]]; - - // per layer, we only consider the first eidNClusters_ clusters in terms of energy, so in order - // to avoid creating large / nested structures to do the sorting for an unknown number of total - // clusters, create a sorted list of layer cluster indices to keep track of the filled clusters - std::vector clusterIndices(trackster.vertices().size()); - for (int k = 0; k < (int)trackster.vertices().size(); k++) { - clusterIndices[k] = k; - } - sort(clusterIndices.begin(), clusterIndices.end(), [&layerClusters, &trackster](const int &a, const int &b) { - return layerClusters[trackster.vertices(a)].energy() > layerClusters[trackster.vertices(b)].energy(); - }); - - // keep track of the number of seen clusters per layer - std::vector seenClusters(eidNLayers_); - - // loop through clusters by descending energy - for (const int &k : clusterIndices) { - // get features per layer and cluster and store the values directly in the input tensor - const reco::CaloCluster &cluster = layerClusters[trackster.vertices(k)]; - int j = rhtools_.getLayerWithOffset(cluster.hitsAndFractions()[0].first) - 1; - if (j < eidNLayers_ && seenClusters[j] < eidNClusters_) { - // get the pointer to the first feature value for the current batch, layer and cluster - float *features = &input.tensor()(i, j, seenClusters[j], 0); - - // fill features - *(features++) = float(cluster.energy() / float(trackster.vertex_multiplicity(k))); - *(features++) = float(std::abs(cluster.eta())); - *(features) = float(cluster.phi()); - - // increment seen clusters - seenClusters[j]++; - } - } - - // zero-fill features of empty clusters in each layer (6) - for (int j = 0; j < eidNLayers_; j++) { - for (int k = seenClusters[j]; k < eidNClusters_; k++) { - float *features = &input.tensor()(i, j, k, 0); - for (int l = 0; l < eidNFeatures_; l++) { - *(features++) = 0.f; - } - } - } - } - - // run the inference (7) - tensorflow::run(eidSession, inputList, outputNames, &outputs); - - // store regressed energy per trackster (8) - if (!eidOutputNameEnergy_.empty()) { - // get the pointer to the energy tensor, dimension is batch x 1 - float *energy = outputs[0].flat().data(); - - for (const int &i : tracksterIndices) { - tracksters[i].setRegressedEnergy(*(energy++)); - } - } - - // store id probabilities per trackster (8) - if (!eidOutputNameId_.empty()) { - // get the pointer to the id probability tensor, dimension is batch x id_probabilities.size() - int probsIdx = eidOutputNameEnergy_.empty() ? 0 : 1; - float *probs = outputs[probsIdx].flat().data(); - - for (const int &i : tracksterIndices) { - tracksters[i].setProbabilities(probs); - probs += tracksters[i].id_probabilities().size(); - } - } -} - template void PatternRecognitionbyCA::fillPSetDescription(edm::ParameterSetDescription &iDesc) { iDesc.add("algo_verbosity", 0); @@ -508,12 +333,6 @@ void PatternRecognitionbyCA::fillPSetDescription(edm::ParameterSetDescrip ->setComment("make default such that no filtering is applied"); iDesc.add("max_longitudinal_sigmaPCA", 9999); iDesc.add("max_delta_time", 3.)->setComment("nsigma"); - iDesc.add("eid_input_name", "input"); - iDesc.add("eid_output_name_energy", "output/regressed_energy"); - iDesc.add("eid_output_name_id", "output/id_probabilities"); - iDesc.add("eid_min_cluster_energy", 1.); - iDesc.add("eid_n_layers", 50); - iDesc.add("eid_n_clusters", 10); iDesc.add("computeLocalTime", false); iDesc.add>("siblings_maxRSquared", {6e-4, 6e-4, 6e-4}); } diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.h b/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.h index 90bcddf06eabf..0a4eed44f0680 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.h +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyCA.h @@ -20,6 +20,11 @@ namespace ticl { std::vector& result, std::unordered_map>& seedToTracksterAssociation) override; + void filter(std::vector& output, + const std::vector& inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs& input, + std::unordered_map>& seedToTracksterAssociation) override; + void energyRegressionAndID(const std::vector& layerClusters, const tensorflow::Session*, std::vector& result); @@ -58,16 +63,10 @@ namespace ticl { const std::string eidInputName_; const std::string eidOutputNameEnergy_; const std::string eidOutputNameId_; - const float eidMinClusterEnergy_; - const int eidNLayers_; - const int eidNClusters_; const bool computeLocalTime_; hgcal::RecHitTools rhtools_; - tensorflow::Session* eidSession_; const std::vector siblings_maxRSquared_; - - static const int eidNFeatures_ = 3; }; } // namespace ticl diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.cc b/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.cc index ec809b813e6a6..e55e463129cd4 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.cc +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.cc @@ -39,15 +39,8 @@ PatternRecognitionbyCLUE3D::PatternRecognitionbyCLUE3D(const edm::Paramet minNumLayerCluster_(conf.getParameter>("minNumLayerCluster")), doPidCut_(conf.getParameter("doPidCut")), cutHadProb_(conf.getParameter("cutHadProb")), - eidInputName_(conf.getParameter("eid_input_name")), - eidOutputNameEnergy_(conf.getParameter("eid_output_name_energy")), - eidOutputNameId_(conf.getParameter("eid_output_name_id")), - eidMinClusterEnergy_(conf.getParameter("eid_min_cluster_energy")), - eidNLayers_(conf.getParameter("eid_n_layers")), - eidNClusters_(conf.getParameter("eid_n_clusters")), computeLocalTime_(conf.getParameter("computeLocalTime")), usePCACleaning_(conf.getParameter("usePCACleaning")){}; - template void PatternRecognitionbyCLUE3D::dumpTiles(const TILES &tiles) const { constexpr int nEtaBin = TILES::constants_type_t::nEtaBins; @@ -330,18 +323,7 @@ void PatternRecognitionbyCLUE3D::makeTracksters( minNumLayerCluster_[tracksterSeedAlgoId_[tracksterIndex++]]; }), result.end()); - if (doPidCut_) { - energyRegressionAndID(input.layerClusters, input.tfSession, result); - result.erase(std::remove_if(std::begin(result), - std::end(result), - [&](auto const &v) { - auto const &hadProb = - v.id_probability(ticl::Trackster::ParticleType::charged_hadron) + - v.id_probability(ticl::Trackster::ParticleType::neutral_hadron); - return hadProb >= cutHadProb_; - }), - result.end()); - } + result.shrink_to_fit(); ticl::assignPCAtoTracksters(result, @@ -373,144 +355,25 @@ void PatternRecognitionbyCLUE3D::makeTracksters( edm::LogVerbatim("PatternRecognitionbyCLUE3D") << std::endl; } } - template -void PatternRecognitionbyCLUE3D::energyRegressionAndID(const std::vector &layerClusters, - const tensorflow::Session *eidSession, - std::vector &tracksters) { - // Energy regression and particle identification strategy: - // - // 1. Set default values for regressed energy and particle id for each trackster. - // 2. Store indices of tracksters whose total sum of cluster energies is above the - // eidMinClusterEnergy_ (GeV) threshold. Inference is not applied for soft tracksters. - // 3. When no trackster passes the selection, return. - // 4. Create input and output tensors. The batch dimension is determined by the number of - // selected tracksters. - // 5. Fill input tensors with layer cluster features. Per layer, clusters are ordered descending - // by energy. Given that tensor data is contiguous in memory, we can use pointer arithmetic to - // fill values, even with batching. - // 6. Zero-fill features for empty clusters in each layer. - // 7. Batched inference. - // 8. Assign the regressed energy and id probabilities to each trackster. - // - // Indices used throughout this method: - // i -> batch element / trackster - // j -> layer - // k -> cluster - // l -> feature - - // set default values per trackster, determine if the cluster energy threshold is passed, - // and store indices of hard tracksters - std::vector tracksterIndices; - for (int i = 0; i < static_cast(tracksters.size()); i++) { - // calculate the cluster energy sum (2) - // note: after the loop, sumClusterEnergy might be just above the threshold which is enough to - // decide whether to run inference for the trackster or not - float sumClusterEnergy = 0.; - for (const unsigned int &vertex : tracksters[i].vertices()) { - sumClusterEnergy += static_cast(layerClusters[vertex].energy()); - // there might be many clusters, so try to stop early - if (sumClusterEnergy >= eidMinClusterEnergy_) { - // set default values (1) - tracksters[i].setRegressedEnergy(0.f); - tracksters[i].zeroProbabilities(); - tracksterIndices.push_back(i); - break; - } - } - } - - // do nothing when no trackster passes the selection (3) - int batchSize = static_cast(tracksterIndices.size()); - if (batchSize == 0) { - return; - } - - // create input and output tensors (4) - tensorflow::TensorShape shape({batchSize, eidNLayers_, eidNClusters_, eidNFeatures_}); - tensorflow::Tensor input(tensorflow::DT_FLOAT, shape); - tensorflow::NamedTensorList inputList = {{eidInputName_, input}}; - - std::vector outputs; - std::vector outputNames; - if (!eidOutputNameEnergy_.empty()) { - outputNames.push_back(eidOutputNameEnergy_); - } - if (!eidOutputNameId_.empty()) { - outputNames.push_back(eidOutputNameId_); - } - - // fill input tensor (5) - for (int i = 0; i < batchSize; i++) { - const Trackster &trackster = tracksters[tracksterIndices[i]]; - - // per layer, we only consider the first eidNClusters_ clusters in terms of energy, so in order - // to avoid creating large / nested structures to do the sorting for an unknown number of total - // clusters, create a sorted list of layer cluster indices to keep track of the filled clusters - std::vector clusterIndices(trackster.vertices().size()); - for (int k = 0; k < (int)trackster.vertices().size(); k++) { - clusterIndices[k] = k; - } - sort(clusterIndices.begin(), clusterIndices.end(), [&layerClusters, &trackster](const int &a, const int &b) { - return layerClusters[trackster.vertices(a)].energy() > layerClusters[trackster.vertices(b)].energy(); - }); - - // keep track of the number of seen clusters per layer - std::vector seenClusters(eidNLayers_); - - // loop through clusters by descending energy - for (const int &k : clusterIndices) { - // get features per layer and cluster and store the values directly in the input tensor - const reco::CaloCluster &cluster = layerClusters[trackster.vertices(k)]; - int j = rhtools_.getLayerWithOffset(cluster.hitsAndFractions()[0].first) - 1; - if (j < eidNLayers_ && seenClusters[j] < eidNClusters_) { - // get the pointer to the first feature value for the current batch, layer and cluster - float *features = &input.tensor()(i, j, seenClusters[j], 0); - - // fill features - *(features++) = float(cluster.energy() / float(trackster.vertex_multiplicity(k))); - *(features++) = float(std::abs(cluster.eta())); - *(features) = float(cluster.phi()); - - // increment seen clusters - seenClusters[j]++; - } - } +void PatternRecognitionbyCLUE3D::filter(std::vector &output, + const std::vector &inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs &input, + std::unordered_map> &seedToTracksterAssociation) { + auto isHAD = [this](const Trackster &t) -> bool { + auto const hadProb = t.id_probability(ticl::Trackster::ParticleType::charged_hadron) + + t.id_probability(ticl::Trackster::ParticleType::neutral_hadron); + return hadProb >= cutHadProb_; + }; - // zero-fill features of empty clusters in each layer (6) - for (int j = 0; j < eidNLayers_; j++) { - for (int k = seenClusters[j]; k < eidNClusters_; k++) { - float *features = &input.tensor()(i, j, k, 0); - for (int l = 0; l < eidNFeatures_; l++) { - *(features++) = 0.f; - } + if (doPidCut_) { + for (auto const &t : inTracksters) { + if (!isHAD(t)) { + output.push_back(t); } } - } - - // run the inference (7) - tensorflow::run(eidSession, inputList, outputNames, &outputs); - - // store regressed energy per trackster (8) - if (!eidOutputNameEnergy_.empty()) { - // get the pointer to the energy tensor, dimension is batch x 1 - float *energy = outputs[0].flat().data(); - - for (const int &i : tracksterIndices) { - tracksters[i].setRegressedEnergy(*(energy++)); - } - } - - // store id probabilities per trackster (8) - if (!eidOutputNameId_.empty()) { - // get the pointer to the id probability tensor, dimension is batch x id_probabilities.size() - int probsIdx = eidOutputNameEnergy_.empty() ? 0 : 1; - float *probs = outputs[probsIdx].flat().data(); - - for (const int &i : tracksterIndices) { - tracksters[i].setProbabilities(probs); - probs += tracksters[i].id_probabilities().size(); - } + } else { + output = inTracksters; } } @@ -666,9 +529,9 @@ void PatternRecognitionbyCLUE3D::calculateLocalDensity( } } } // end of loop on possible compatible clusters - } // end of loop over phi-bin region - } // end of loop over eta-bin region - } // end of loop on the sibling layers + } // end of loop over phi-bin region + } // end of loop over eta-bin region + } // end of loop on the sibling layers if (rescaleDensityByZ_) { if (PatternRecognitionAlgoBaseT::algo_verbosity_ > VerbosityLevel::Advanced) { edm::LogVerbatim("PatternRecognitionbyCLUE3D") @@ -777,9 +640,9 @@ void PatternRecognitionbyCLUE3D::calculateDistanceToHigher( i_nearestHigher = layerandSoa; } } // End of loop on clusters - } // End of loop on phi bins - } // End of loop on eta bins - } // End of loop on layers + } // End of loop on phi bins + } // End of loop on eta bins + } // End of loop on layers clustersOnLayer.delta[i] = nearest_distances; clustersOnLayer.nearestHigher[i] = i_nearestHigher; @@ -898,12 +761,6 @@ void PatternRecognitionbyCLUE3D::fillPSetDescription(edm::ParameterSetDes iDesc.add>("minNumLayerCluster", {2, 2, 2})->setComment("Not Inclusive"); iDesc.add("doPidCut", false); iDesc.add("cutHadProb", 0.5); - iDesc.add("eid_input_name", "input"); - iDesc.add("eid_output_name_energy", "output/regressed_energy"); - iDesc.add("eid_output_name_id", "output/id_probabilities"); - iDesc.add("eid_min_cluster_energy", 1.); - iDesc.add("eid_n_layers", 50); - iDesc.add("eid_n_clusters", 10); iDesc.add("computeLocalTime", false); iDesc.add("usePCACleaning", false)->setComment("Enable PCA cleaning alorithm"); } diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.h b/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.h index b3139e2402501..fa907ad6a6eef 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.h +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyCLUE3D.h @@ -18,6 +18,11 @@ namespace ticl { std::vector& result, std::unordered_map>& seedToTracksterAssociation) override; + void filter(std::vector& output, + const std::vector& inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs& input, + std::unordered_map>& seedToTracksterAssociation) override; + void energyRegressionAndID(const std::vector& layerClusters, const tensorflow::Session*, std::vector& result); @@ -134,19 +139,10 @@ namespace ticl { const bool doPidCut_; const float cutHadProb_; const std::vector filter_on_categories_; - const std::string eidInputName_; - const std::string eidOutputNameEnergy_; - const std::string eidOutputNameId_; - const float eidMinClusterEnergy_; - const int eidNLayers_; - const int eidNClusters_; const bool computeLocalTime_; const bool usePCACleaning_; hgcal::RecHitTools rhtools_; - tensorflow::Session* eidSession_; - - static const int eidNFeatures_ = 3; }; } // namespace ticl diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.cc b/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.cc index b8e8bf99f4a6f..957abb847c0cb 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.cc +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.cc @@ -32,12 +32,6 @@ PatternRecognitionbyFastJet::PatternRecognitionbyFastJet(const edm::Param caloGeomToken_(iC.esConsumes()), antikt_radius_(conf.getParameter("antikt_radius")), minNumLayerCluster_(conf.getParameter("minNumLayerCluster")), - eidInputName_(conf.getParameter("eid_input_name")), - eidOutputNameEnergy_(conf.getParameter("eid_output_name_energy")), - eidOutputNameId_(conf.getParameter("eid_output_name_id")), - eidMinClusterEnergy_(conf.getParameter("eid_min_cluster_energy")), - eidNLayers_(conf.getParameter("eid_n_layers")), - eidNClusters_(conf.getParameter("eid_n_clusters")), computeLocalTime_(conf.getParameter("computeLocalTime")){}; template @@ -135,9 +129,9 @@ void PatternRecognitionbyFastJet::makeTracksters( fpj.set_user_index(clusterIdx); fjInputs.push_back(fpj); } // End of loop on the clusters on currentLayer - } // End of loop over phi-bin region - } // End of loop over eta-bin region - } // End of loop over layers + } // End of loop over phi-bin region + } // End of loop over eta-bin region + } // End of loop over layers // Collect the jet from the other side wrt to the one taken care of inside the main loop above. buildJetAndTracksters(fjInputs, result); @@ -150,7 +144,6 @@ void PatternRecognitionbyFastJet::makeTracksters( computeLocalTime_); // run energy regression and ID - energyRegressionAndID(input.layerClusters, input.tfSession, result); if (PatternRecognitionAlgoBaseT::algo_verbosity_ > VerbosityLevel::Basic) { for (auto const &t : result) { edm::LogVerbatim("PatternRecogntionbyFastJet") << "Barycenter: " << t.barycenter(); @@ -162,143 +155,11 @@ void PatternRecognitionbyFastJet::makeTracksters( } template -void PatternRecognitionbyFastJet::energyRegressionAndID(const std::vector &layerClusters, - const tensorflow::Session *eidSession, - std::vector &tracksters) { - // Energy regression and particle identification strategy: - // - // 1. Set default values for regressed energy and particle id for each trackster. - // 2. Store indices of tracksters whose total sum of cluster energies is above the - // eidMinClusterEnergy_ (GeV) threshold. Inference is not applied for soft tracksters. - // 3. When no trackster passes the selection, return. - // 4. Create input and output tensors. The batch dimension is determined by the number of - // selected tracksters. - // 5. Fill input tensors with layer cluster features. Per layer, clusters are ordered descending - // by energy. Given that tensor data is contiguous in memory, we can use pointer arithmetic to - // fill values, even with batching. - // 6. Zero-fill features for empty clusters in each layer. - // 7. Batched inference. - // 8. Assign the regressed energy and id probabilities to each trackster. - // - // Indices used throughout this method: - // i -> batch element / trackster - // j -> layer - // k -> cluster - // l -> feature - - // set default values per trackster, determine if the cluster energy threshold is passed, - // and store indices of hard tracksters - std::vector tracksterIndices; - for (int i = 0; i < static_cast(tracksters.size()); i++) { - // calculate the cluster energy sum (2) - // note: after the loop, sumClusterEnergy might be just above the threshold which is enough to - // decide whether to run inference for the trackster or not - float sumClusterEnergy = 0.; - for (const unsigned int &vertex : tracksters[i].vertices()) { - sumClusterEnergy += static_cast(layerClusters[vertex].energy()); - // there might be many clusters, so try to stop early - if (sumClusterEnergy >= eidMinClusterEnergy_) { - // set default values (1) - tracksters[i].setRegressedEnergy(0.f); - tracksters[i].zeroProbabilities(); - tracksterIndices.push_back(i); - break; - } - } - } - - // do nothing when no trackster passes the selection (3) - int batchSize = static_cast(tracksterIndices.size()); - if (batchSize == 0) { - return; - } - - // create input and output tensors (4) - tensorflow::TensorShape shape({batchSize, eidNLayers_, eidNClusters_, eidNFeatures_}); - tensorflow::Tensor input(tensorflow::DT_FLOAT, shape); - tensorflow::NamedTensorList inputList = {{eidInputName_, input}}; - - std::vector outputs; - std::vector outputNames; - if (!eidOutputNameEnergy_.empty()) { - outputNames.push_back(eidOutputNameEnergy_); - } - if (!eidOutputNameId_.empty()) { - outputNames.push_back(eidOutputNameId_); - } - - // fill input tensor (5) - for (int i = 0; i < batchSize; i++) { - const Trackster &trackster = tracksters[tracksterIndices[i]]; - - // per layer, we only consider the first eidNClusters_ clusters in terms of energy, so in order - // to avoid creating large / nested structures to do the sorting for an unknown number of total - // clusters, create a sorted list of layer cluster indices to keep track of the filled clusters - std::vector clusterIndices(trackster.vertices().size()); - for (int k = 0; k < (int)trackster.vertices().size(); k++) { - clusterIndices[k] = k; - } - sort(clusterIndices.begin(), clusterIndices.end(), [&layerClusters, &trackster](const int &a, const int &b) { - return layerClusters[trackster.vertices(a)].energy() > layerClusters[trackster.vertices(b)].energy(); - }); - - // keep track of the number of seen clusters per layer - std::vector seenClusters(eidNLayers_); - - // loop through clusters by descending energy - for (const int &k : clusterIndices) { - // get features per layer and cluster and store the values directly in the input tensor - const reco::CaloCluster &cluster = layerClusters[trackster.vertices(k)]; - int j = rhtools_.getLayerWithOffset(cluster.hitsAndFractions()[0].first) - 1; - if (j < eidNLayers_ && seenClusters[j] < eidNClusters_) { - // get the pointer to the first feature value for the current batch, layer and cluster - float *features = &input.tensor()(i, j, seenClusters[j], 0); - - // fill features - *(features++) = float(cluster.energy() / float(trackster.vertex_multiplicity(k))); - *(features++) = float(std::abs(cluster.eta())); - *(features) = float(cluster.phi()); - - // increment seen clusters - seenClusters[j]++; - } - } - - // zero-fill features of empty clusters in each layer (6) - for (int j = 0; j < eidNLayers_; j++) { - for (int k = seenClusters[j]; k < eidNClusters_; k++) { - float *features = &input.tensor()(i, j, k, 0); - for (int l = 0; l < eidNFeatures_; l++) { - *(features++) = 0.f; - } - } - } - } - - // run the inference (7) - tensorflow::run(eidSession, inputList, outputNames, &outputs); - - // store regressed energy per trackster (8) - if (!eidOutputNameEnergy_.empty()) { - // get the pointer to the energy tensor, dimension is batch x 1 - float *energy = outputs[0].flat().data(); - - for (const int &i : tracksterIndices) { - tracksters[i].setRegressedEnergy(*(energy++)); - } - } - - // store id probabilities per trackster (8) - if (!eidOutputNameId_.empty()) { - // get the pointer to the id probability tensor, dimension is batch x id_probabilities.size() - int probsIdx = eidOutputNameEnergy_.empty() ? 0 : 1; - float *probs = outputs[probsIdx].flat().data(); - - for (const int &i : tracksterIndices) { - tracksters[i].setProbabilities(probs); - probs += tracksters[i].id_probabilities().size(); - } - } +void PatternRecognitionbyFastJet::filter(std::vector &output, + const std::vector &inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs &input, + std::unordered_map> &seedToTracksterAssociation) { + output = inTracksters; } template @@ -306,12 +167,6 @@ void PatternRecognitionbyFastJet::fillPSetDescription(edm::ParameterSetDe iDesc.add("algo_verbosity", 0); iDesc.add("antikt_radius", 0.09)->setComment("Radius to be used while running the Anti-kt clustering"); iDesc.add("minNumLayerCluster", 5)->setComment("Not Inclusive"); - iDesc.add("eid_input_name", "input"); - iDesc.add("eid_output_name_energy", "output/regressed_energy"); - iDesc.add("eid_output_name_id", "output/id_probabilities"); - iDesc.add("eid_min_cluster_energy", 1.); - iDesc.add("eid_n_layers", 50); - iDesc.add("eid_n_clusters", 10); iDesc.add("computeLocalTime", false); } diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.h b/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.h index 2811b54c8e6e4..bfc10ea26e9d3 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.h +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyFastJet.h @@ -24,6 +24,11 @@ namespace ticl { std::vector& result, std::unordered_map>& seedToTracksterAssociation) override; + void filter(std::vector& output, + const std::vector& inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs& input, + std::unordered_map>& seedToTracksterAssociation) override; + void energyRegressionAndID(const std::vector& layerClusters, const tensorflow::Session*, std::vector& result); @@ -34,18 +39,9 @@ namespace ticl { edm::ESGetToken caloGeomToken_; const double antikt_radius_; const int minNumLayerCluster_; - const std::string eidInputName_; - const std::string eidOutputNameEnergy_; - const std::string eidOutputNameId_; - const float eidMinClusterEnergy_; - const int eidNLayers_; - const int eidNClusters_; const bool computeLocalTime_; hgcal::RecHitTools rhtools_; - tensorflow::Session* eidSession_; - - static const int eidNFeatures_ = 3; void buildJetAndTracksters(std::vector&, std::vector&); }; diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.cc b/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.cc index ccca28ea82bd5..de40f9fd5d298 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.cc +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.cc @@ -62,6 +62,15 @@ void PatternRecognitionbyPassthrough::makeTracksters( } } +template +void PatternRecognitionbyPassthrough::filter( + std::vector &output, + const std::vector &inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs &input, + std::unordered_map> &seedToTracksterAssociation) { + output = inTracksters; +} + template void PatternRecognitionbyPassthrough::fillPSetDescription(edm::ParameterSetDescription &iDesc) { iDesc.add("algo_verbosity", 0); diff --git a/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.h b/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.h index 8ef9a76824be0..22f818b8ed958 100644 --- a/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.h +++ b/RecoHGCal/TICL/plugins/PatternRecognitionbyPassthrough.h @@ -18,6 +18,11 @@ namespace ticl { std::vector& result, std::unordered_map>& seedToTracksterAssociation) override; + void filter(std::vector& output, + const std::vector& inTracksters, + const typename PatternRecognitionAlgoBaseT::Inputs& input, + std::unordered_map>& seedToTracksterAssociation) override; + static void fillPSetDescription(edm::ParameterSetDescription& iDesc); private: diff --git a/RecoHGCal/TICL/plugins/TracksterInferenceAlgoFactory.cc b/RecoHGCal/TICL/plugins/TracksterInferenceAlgoFactory.cc new file mode 100644 index 0000000000000..b3580ab956cb4 --- /dev/null +++ b/RecoHGCal/TICL/plugins/TracksterInferenceAlgoFactory.cc @@ -0,0 +1,13 @@ +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceByDNN.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceByANN.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceByCNNv4.h" +#include "FWCore/ParameterSet/interface/ValidatedPluginFactoryMacros.h" +#include "FWCore/ParameterSet/interface/ValidatedPluginMacros.h" + +EDM_REGISTER_VALIDATED_PLUGINFACTORY(TracksterInferenceAlgoFactory, "TracksterInferenceAlgoFactory"); +DEFINE_EDM_VALIDATED_PLUGIN(TracksterInferenceAlgoFactory, ticl::TracksterInferenceByDNN, "TracksterInferenceByDNN"); +DEFINE_EDM_VALIDATED_PLUGIN(TracksterInferenceAlgoFactory, ticl::TracksterInferenceByANN, "TracksterInferenceByANN"); +DEFINE_EDM_VALIDATED_PLUGIN(TracksterInferenceAlgoFactory, + ticl::TracksterInferenceByCNNv4, + "TracksterInferenceByCNNv4"); diff --git a/RecoHGCal/TICL/plugins/TracksterInferenceByANN.cc b/RecoHGCal/TICL/plugins/TracksterInferenceByANN.cc new file mode 100644 index 0000000000000..d57b9ca3bfd0b --- /dev/null +++ b/RecoHGCal/TICL/plugins/TracksterInferenceByANN.cc @@ -0,0 +1,24 @@ +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceByANN.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" + +namespace ticl { + + TracksterInferenceByANN::TracksterInferenceByANN(const edm::ParameterSet& conf) : TracksterInferenceAlgoBase(conf) { + // Load ANN model + } + + void TracksterInferenceByANN::inputData(const std::vector& layerClusters, + std::vector& tracksters) { + // Prepare data for inference + } + + void TracksterInferenceByANN::runInference(std::vector& tracksters) { + // Run inference using ANN + } +} // namespace ticl + +// Define this as a plug-in +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_EDM_PLUGIN(TracksterInferenceAlgoFactory, ticl::TracksterInferenceByANN, "TracksterInferenceByANN"); diff --git a/RecoHGCal/TICL/plugins/TracksterInferenceByCNNv4.cc b/RecoHGCal/TICL/plugins/TracksterInferenceByCNNv4.cc new file mode 100644 index 0000000000000..fb27c17310b4d --- /dev/null +++ b/RecoHGCal/TICL/plugins/TracksterInferenceByCNNv4.cc @@ -0,0 +1,136 @@ +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceByCNNv4.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "RecoHGCal/TICL/interface/PatternRecognitionAlgoBase.h" +#include "RecoLocalCalo/HGCalRecAlgos/interface/RecHitTools.h" +#include "TrackstersPCA.h" + +namespace ticl { + using namespace cms::Ort; // Use ONNXRuntime namespace + + // Constructor for TracksterInferenceByCNNv4 + TracksterInferenceByCNNv4::TracksterInferenceByCNNv4(const edm::ParameterSet& conf) + : TracksterInferenceAlgoBase(conf), + modelPath_(conf.getParameter("onnxModelPath").fullPath()), // Path to the PID model CLU3D + inputNames_(conf.getParameter>("inputNames")), // Define input names for inference + outputNames_(conf.getParameter>("outputNames")), // Define output names for inference + eidMinClusterEnergy_(conf.getParameter("eid_min_cluster_energy")), // Minimum cluster energy + eidNLayers_(conf.getParameter("eid_n_layers")), // Number of layers + eidNClusters_(conf.getParameter("eid_n_clusters")), // Number of clusters + doPID_(conf.getParameter("doPID")), // Number of clusters + doRegression_(conf.getParameter("doRegression")) // Number of clusters + { + // Initialize ONNX Runtime sessions for PID and Energy models + static std::unique_ptr onnxRuntimeInstance = + std::make_unique(modelPath_.c_str()); + onnxSession_ = onnxRuntimeInstance.get(); + } + + // Method to process input data and prepare it for inference + void TracksterInferenceByCNNv4::inputData(const std::vector& layerClusters, + std::vector& tracksters) { + tracksterIndices_.clear(); // Clear previous indices + for (int i = 0; i < static_cast(tracksters.size()); i++) { + float sumClusterEnergy = 0.; + for (const unsigned int& vertex : tracksters[i].vertices()) { + sumClusterEnergy += static_cast(layerClusters[vertex].energy()); + if (sumClusterEnergy >= eidMinClusterEnergy_) { + tracksters[i].setRegressedEnergy(0.f); // Set regressed energy to 0 + tracksters[i].zeroProbabilities(); // Zero out probabilities + tracksterIndices_.push_back(i); // Add index to the list + break; + } + } + } + + // Prepare input shapes and data for inference + batchSize_ = static_cast(tracksterIndices_.size()); + if (batchSize_ == 0) + return; // Exit if no tracksters + + std::vector inputShape = {batchSize_, eidNLayers_, eidNClusters_, eidNFeatures_}; + input_shapes_ = {inputShape}; + + input_Data_.clear(); + input_Data_.emplace_back(batchSize_ * eidNLayers_ * eidNClusters_ * eidNFeatures_, 0); + + for (int i = 0; i < batchSize_; i++) { + const Trackster& trackster = tracksters[tracksterIndices_[i]]; + + // Prepare indices and sort clusters based on energy + std::vector clusterIndices(trackster.vertices().size()); + for (int k = 0; k < static_cast(trackster.vertices().size()); k++) { + clusterIndices[k] = k; + } + + std::sort(clusterIndices.begin(), clusterIndices.end(), [&layerClusters, &trackster](const int& a, const int& b) { + return layerClusters[trackster.vertices(a)].energy() > layerClusters[trackster.vertices(b)].energy(); + }); + + std::vector seenClusters(eidNLayers_, 0); + + // Fill input data with cluster information + for (const int& k : clusterIndices) { + const reco::CaloCluster& cluster = layerClusters[trackster.vertices(k)]; + int j = rhtools_.getLayerWithOffset(cluster.hitsAndFractions()[0].first) - 1; + if (j < eidNLayers_ && seenClusters[j] < eidNClusters_) { + auto index = (i * eidNLayers_ + j) * eidNFeatures_ * eidNClusters_ + seenClusters[j] * eidNFeatures_; + input_Data_[0][index] = + static_cast(cluster.energy() / static_cast(trackster.vertex_multiplicity(k))); + input_Data_[0][index + 1] = static_cast(std::abs(cluster.eta())); + input_Data_[0][index + 2] = static_cast(cluster.phi()); + seenClusters[j]++; + } + } + } + } + + // Method to run inference and update tracksters + void TracksterInferenceByCNNv4::runInference(std::vector& tracksters) { + if (batchSize_ == 0) + return; // Exit if no batch + + std::vector> outputTensors; + outputTensors = onnxSession_->run(inputNames_, input_Data_, input_shapes_, outputNames_, batchSize_); + if (doPID_ and doRegression_) { + // Run energy model inference + if (!outputNames_.empty()) { + for (int i = 0; i < static_cast(batchSize_); i++) { + const float energy = outputTensors[0][i]; + tracksters[tracksterIndices_[i]].setRegressedEnergy(energy); // Update energy + } + } + } + + if (doPID_) { + // Run PID model inference + if (!outputNames_.empty()) { + int probsIdx = outputNames_.empty() ? 0 : 1; + std::vector vec = outputTensors[probsIdx]; + float* probs = vec.data(); + for (int i = 0; i < batchSize_; i++) { + tracksters[tracksterIndices_[i]].setProbabilities(probs); // Update probabilities + probs += tracksters[tracksterIndices_[i]].id_probabilities().size(); // Move to next set of probabilities + } + } + } + } + + // Method to fill parameter set description for configuration + void TracksterInferenceByCNNv4::fillPSetDescription(edm::ParameterSetDescription& iDesc) { + iDesc.add("algo_verbosity", 0); + iDesc + .add("onnxModelPath", + edm::FileInPath("RecoHGCal/TICL/data/ticlv4/onnx_models/energy_id_v0.onnx")) + ->setComment("Path to ONNX PID model CLU3D"); + iDesc.add>("inputNames", {"input:0"}); + iDesc.add>("outputNames", {"output/regressed_energy:0", "output/id_probabilities:0"}); + iDesc.add("eid_min_cluster_energy", 1.0); + iDesc.add("eid_n_layers", 50); + iDesc.add("eid_n_clusters", 10); + iDesc.add("doPID", 1); + iDesc.add("doRegression", 0); + } +} // namespace ticl diff --git a/RecoHGCal/TICL/plugins/TracksterInferenceByDNN.cc b/RecoHGCal/TICL/plugins/TracksterInferenceByDNN.cc new file mode 100644 index 0000000000000..d9195f2811685 --- /dev/null +++ b/RecoHGCal/TICL/plugins/TracksterInferenceByDNN.cc @@ -0,0 +1,148 @@ +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceByDNN.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "RecoHGCal/TICL/interface/PatternRecognitionAlgoBase.h" +#include "RecoLocalCalo/HGCalRecAlgos/interface/RecHitTools.h" +#include "TrackstersPCA.h" + +namespace ticl { + using namespace cms::Ort; // Use ONNXRuntime namespace + + // Constructor for TracksterInferenceByDNN + TracksterInferenceByDNN::TracksterInferenceByDNN(const edm::ParameterSet& conf) + : TracksterInferenceAlgoBase(conf), + id_modelPath_( + conf.getParameter("onnxPIDModelPath").fullPath()), // Path to the PID model CLU3D + en_modelPath_( + conf.getParameter("onnxEnergyModelPath").fullPath()), // Path to the Energy model CLU3D + inputNames_(conf.getParameter>("inputNames")), // Define input names for inference + output_en_(conf.getParameter>("output_en")), // Define output energy for inference + output_id_(conf.getParameter>("output_id")), // Define output PID for inference + eidMinClusterEnergy_(conf.getParameter("eid_min_cluster_energy")), // Minimum cluster energy + eidNLayers_(conf.getParameter("eid_n_layers")), // Number of layers + eidNClusters_(conf.getParameter("eid_n_clusters")), // Number of clusters + doPID_(conf.getParameter("doPID")), // Number of clusters + doRegression_(conf.getParameter("doRegression")) // Number of clusters + { + // Initialize ONNX Runtime sessions for PID and Energy models + static std::unique_ptr onnxPIDRuntimeInstance = + std::make_unique(id_modelPath_.c_str()); + onnxPIDSession_ = onnxPIDRuntimeInstance.get(); + static std::unique_ptr onnxEnergyRuntimeInstance = + std::make_unique(en_modelPath_.c_str()); + onnxEnergySession_ = onnxEnergyRuntimeInstance.get(); + } + + // Method to process input data and prepare it for inference + void TracksterInferenceByDNN::inputData(const std::vector& layerClusters, + std::vector& tracksters) { + tracksterIndices_.clear(); // Clear previous indices + for (int i = 0; i < static_cast(tracksters.size()); i++) { + float sumClusterEnergy = 0.; + for (const unsigned int& vertex : tracksters[i].vertices()) { + sumClusterEnergy += static_cast(layerClusters[vertex].energy()); + if (sumClusterEnergy >= eidMinClusterEnergy_) { + tracksters[i].setRegressedEnergy(0.f); // Set regressed energy to 0 + tracksters[i].zeroProbabilities(); // Zero out probabilities + tracksterIndices_.push_back(i); // Add index to the list + break; + } + } + } + + // Prepare input shapes and data for inference + batchSize_ = static_cast(tracksterIndices_.size()); + if (batchSize_ == 0) + return; // Exit if no tracksters + + std::vector inputShape = {batchSize_, eidNLayers_, eidNClusters_, eidNFeatures_}; + input_shapes_ = {inputShape}; + + input_Data_.clear(); + input_Data_.emplace_back(batchSize_ * eidNLayers_ * eidNClusters_ * eidNFeatures_, 0); + + for (int i = 0; i < batchSize_; i++) { + const Trackster& trackster = tracksters[tracksterIndices_[i]]; + + // Prepare indices and sort clusters based on energy + std::vector clusterIndices(trackster.vertices().size()); + for (int k = 0; k < static_cast(trackster.vertices().size()); k++) { + clusterIndices[k] = k; + } + + std::sort(clusterIndices.begin(), clusterIndices.end(), [&layerClusters, &trackster](const int& a, const int& b) { + return layerClusters[trackster.vertices(a)].energy() > layerClusters[trackster.vertices(b)].energy(); + }); + + std::vector seenClusters(eidNLayers_, 0); + + // Fill input data with cluster information + for (const int& k : clusterIndices) { + const reco::CaloCluster& cluster = layerClusters[trackster.vertices(k)]; + int j = rhtools_.getLayerWithOffset(cluster.hitsAndFractions()[0].first) - 1; + if (j < eidNLayers_ && seenClusters[j] < eidNClusters_) { + auto index = (i * eidNLayers_ + j) * eidNFeatures_ * eidNClusters_ + seenClusters[j] * eidNFeatures_; + input_Data_[0][index] = + static_cast(cluster.energy() / static_cast(trackster.vertex_multiplicity(k))); + input_Data_[0][index + 1] = static_cast(std::abs(cluster.eta())); + input_Data_[0][index + 2] = static_cast(cluster.phi()); + seenClusters[j]++; + } + } + } + } + + // Method to run inference and update tracksters + void TracksterInferenceByDNN::runInference(std::vector& tracksters) { + if (batchSize_ == 0) + return; // Exit if no batch + + if (doPID_ and doRegression_) { + // Run energy model inference + auto result = onnxEnergySession_->run(inputNames_, input_Data_, input_shapes_, output_en_, batchSize_); + auto& energyOutputTensor = result[0]; + if (!output_en_.empty()) { + for (int i = 0; i < static_cast(batchSize_); i++) { + const float energy = energyOutputTensor[i]; + tracksters[tracksterIndices_[i]].setRegressedEnergy(energy); // Update energy + } + } + } + + if (doPID_) { + // Run PID model inference + auto pidOutput = onnxPIDSession_->run(inputNames_, input_Data_, input_shapes_, output_id_, batchSize_); + auto pidOutputTensor = pidOutput[0]; + float* probs = pidOutputTensor.data(); + if (!output_id_.empty()) { + for (int i = 0; i < batchSize_; i++) { + tracksters[tracksterIndices_[i]].setProbabilities(probs); // Update probabilities + probs += tracksters[tracksterIndices_[i]].id_probabilities().size(); // Move to next set of probabilities + } + } + } + } + // Method to fill parameter set description for configuration + void TracksterInferenceByDNN::fillPSetDescription(edm::ParameterSetDescription& iDesc) { + iDesc.add("algo_verbosity", 0); + iDesc + .add("onnxPIDModelPath", + edm::FileInPath("RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/id_v0.onnx")) + ->setComment("Path to ONNX PID model CLU3D"); + iDesc + .add( + "onnxEnergyModelPath", + edm::FileInPath("RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/energy_v0.onnx")) + ->setComment("Path to ONNX Energy model CLU3D"); + iDesc.add>("inputNames", {"input"}); + iDesc.add>("output_en", {"enreg_output"}); + iDesc.add>("output_id", {"pid_output"}); + iDesc.add("eid_min_cluster_energy", 1.0); + iDesc.add("eid_n_layers", 50); + iDesc.add("eid_n_clusters", 10); + iDesc.add("doPID", 1); + iDesc.add("doRegression", 1); + } +} // namespace ticl diff --git a/RecoHGCal/TICL/plugins/TracksterLinksProducer.cc b/RecoHGCal/TICL/plugins/TracksterLinksProducer.cc index 7cc7f58e46585..4901d0de3bc65 100644 --- a/RecoHGCal/TICL/plugins/TracksterLinksProducer.cc +++ b/RecoHGCal/TICL/plugins/TracksterLinksProducer.cc @@ -42,6 +42,7 @@ #include "Geometry/CommonDetUnit/interface/GeomDet.h" #include "RecoLocalCalo/HGCalRecAlgos/interface/RecHitTools.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h" #include "TrackstersPCA.h" @@ -51,7 +52,7 @@ using cms::Ort::ONNXRuntime; class TracksterLinksProducer : public edm::stream::EDProducer> { public: explicit TracksterLinksProducer(const edm::ParameterSet &ps, const ONNXRuntime *); - ~TracksterLinksProducer() override{}; + ~TracksterLinksProducer() override {}; void produce(edm::Event &, const edm::EventSetup &) override; static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); @@ -62,9 +63,6 @@ class TracksterLinksProducer : public edm::stream::EDProducer &, const char *label) const; void dumpTrackster(const Trackster &) const; - void energyRegressionAndID(const std::vector &layerClusters, - const tensorflow::Session *, - std::vector &result) const; std::unique_ptr linkingAlgo_; std::string algoType_; @@ -74,17 +72,7 @@ class TracksterLinksProducer : public edm::stream::EDProducer>> clustersTime_token_; const bool regressionAndPid_; - const std::string tfDnnLabel_; - const edm::ESGetToken tfDnnToken_; - const tensorflow::Session *tfSession_; - const std::string eidInputName_; - const std::string eidOutputNameEnergy_; - const std::string eidOutputNameId_; - const float eidMinClusterEnergy_; - const int eidNLayers_; - const int eidNClusters_; - static constexpr int eidNFeatures_ = 3; - tensorflow::Session *eidSession_; + std::unique_ptr inferenceAlgo_; std::vector>> original_masks_tokens_; @@ -105,16 +93,6 @@ TracksterLinksProducer::TracksterLinksProducer(const edm::ParameterSet &ps, cons clustersTime_token_( consumes>>(ps.getParameter("layer_clustersTime"))), regressionAndPid_(ps.getParameter("regressionAndPid")), - tfDnnLabel_(ps.getParameter("tfDnnLabel")), - tfDnnToken_(esConsumes(edm::ESInputTag("", tfDnnLabel_))), - tfSession_(nullptr), - eidInputName_(ps.getParameter("eid_input_name")), - eidOutputNameEnergy_(ps.getParameter("eid_output_name_energy")), - eidOutputNameId_(ps.getParameter("eid_output_name_id")), - eidMinClusterEnergy_(ps.getParameter("eid_min_cluster_energy")), - eidNLayers_(ps.getParameter("eid_n_layers")), - eidNClusters_(ps.getParameter("eid_n_clusters")), - eidSession_(nullptr), geometry_token_(esConsumes()), detector_(ps.getParameter("detector")), propName_(ps.getParameter("propagator")), @@ -129,6 +107,11 @@ TracksterLinksProducer::TracksterLinksProducer(const edm::ParameterSet &ps, cons for (auto const &tag : ps.getParameter>("original_masks")) { original_masks_tokens_.emplace_back(consumes>(tag)); } + // 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)); // New trackster collection after linking produces>(); @@ -197,132 +180,6 @@ void TracksterLinksProducer::dumpTrackster(const Trackster &t) const { LogDebug("TracksterLinksProducer") << std::endl; } -void TracksterLinksProducer::energyRegressionAndID(const std::vector &layerClusters, - const tensorflow::Session *eidSession, - std::vector &tracksters) const { - // Energy regression and particle identification strategy: - // - // 1. Set default values for regressed energy and particle id for each trackster. - // 2. Store indices of tracksters whose total sum of cluster energies is above the - // eidMinClusterEnergy_ (GeV) threshold. Inference is not applied for soft tracksters. - // 3. When no trackster passes the selection, return. - // 4. Create input and output tensors. The batch dimension is determined by the number of - // selected tracksters. - // 5. Fill input tensors with layer cluster features. Per layer, clusters are ordered descending - // by energy. Given that tensor data is contiguous in memory, we can use pointer arithmetic to - // fill values, even with batching. - // 6. Zero-fill features for empty clusters in each layer. - // 7. Batched inference. - // 8. Assign the regressed energy and id probabilities to each trackster. - // - // Indices used throughout this method: - // i -> batch element / trackster - // j -> layer - // k -> cluster - // l -> feature - - // do nothing when no trackster passes the selection (3) - int batchSize = (int)tracksters.size(); - if (batchSize == 0) { - return; - } - - for (auto &t : tracksters) { - t.setRegressedEnergy(0.f); - t.zeroProbabilities(); - } - - // create input and output tensors (4) - tensorflow::TensorShape shape({batchSize, eidNLayers_, eidNClusters_, eidNFeatures_}); - tensorflow::Tensor input(tensorflow::DT_FLOAT, shape); - tensorflow::NamedTensorList inputList = {{eidInputName_, input}}; - static constexpr int inputDimension = 4; - - std::vector outputs; - std::vector outputNames; - if (!eidOutputNameEnergy_.empty()) { - outputNames.push_back(eidOutputNameEnergy_); - } - if (!eidOutputNameId_.empty()) { - outputNames.push_back(eidOutputNameId_); - } - - // fill input tensor (5) - for (int i = 0; i < batchSize; i++) { - const Trackster &trackster = tracksters[i]; - - // per layer, we only consider the first eidNClusters_ clusters in terms of - // energy, so in order to avoid creating large / nested structures to do - // the sorting for an unknown number of total clusters, create a sorted - // list of layer cluster indices to keep track of the filled clusters - std::vector clusterIndices(trackster.vertices().size()); - for (int k = 0; k < (int)trackster.vertices().size(); k++) { - clusterIndices[k] = k; - } - sort(clusterIndices.begin(), clusterIndices.end(), [&layerClusters, &trackster](const int &a, const int &b) { - return layerClusters[trackster.vertices(a)].energy() > layerClusters[trackster.vertices(b)].energy(); - }); - - // keep track of the number of seen clusters per layer - std::vector seenClusters(eidNLayers_); - - // loop through clusters by descending energy - for (const int &k : clusterIndices) { - // get features per layer and cluster and store the values directly in the input tensor - const reco::CaloCluster &cluster = layerClusters[trackster.vertices(k)]; - int j = rhtools_.getLayerWithOffset(cluster.hitsAndFractions()[0].first) - 1; - if (j < eidNLayers_ && seenClusters[j] < eidNClusters_) { - // get the pointer to the first feature value for the current batch, layer and cluster - float *features = &input.tensor()(i, j, seenClusters[j], 0); - - // fill features - *(features++) = float(cluster.energy() / float(trackster.vertex_multiplicity(k))); - *(features++) = float(std::abs(cluster.eta())); - *(features) = float(cluster.phi()); - - // increment seen clusters - seenClusters[j]++; - } - } - - // zero-fill features of empty clusters in each layer (6) - for (int j = 0; j < eidNLayers_; j++) { - for (int k = seenClusters[j]; k < eidNClusters_; k++) { - float *features = &input.tensor()(i, j, k, 0); - for (int l = 0; l < eidNFeatures_; l++) { - *(features++) = 0.f; - } - } - } - } - - // run the inference (7) - tensorflow::run(eidSession, inputList, outputNames, &outputs); - - // store regressed energy per trackster (8) - if (!eidOutputNameEnergy_.empty()) { - // get the pointer to the energy tensor, dimension is batch x 1 - float *energy = outputs[0].flat().data(); - - for (int i = 0; i < batchSize; ++i) { - float regressedEnergy = - tracksters[i].raw_energy() > eidMinClusterEnergy_ ? energy[i] : tracksters[i].raw_energy(); - tracksters[i].setRegressedEnergy(regressedEnergy); - } - } - - // store id probabilities per trackster (8) - if (!eidOutputNameId_.empty()) { - // get the pointer to the id probability tensor, dimension is batch x id_probabilities.size() - int probsIdx = !eidOutputNameEnergy_.empty(); - float *probs = outputs[probsIdx].flat().data(); - int probsNumber = tracksters[0].id_probabilities().size(); - for (int i = 0; i < batchSize; ++i) { - tracksters[i].setProbabilities(&probs[i * probsNumber]); - } - } -} - void TracksterLinksProducer::produce(edm::Event &evt, const edm::EventSetup &es) { linkingAlgo_->setEvent(evt, es); @@ -333,7 +190,6 @@ void TracksterLinksProducer::produce(edm::Event &evt, const edm::EventSetup &es) const auto &layerClusters = evt.get(clusters_token_); const auto &layerClustersTimes = evt.get(clustersTime_token_); - tfSession_ = es.getData(tfDnnToken_).getSession(); // loop over the original_masks_tokens_ and get the original masks collections and multiply them // to get the global mask std::vector original_global_mask(layerClusters.size(), 1.f); @@ -374,8 +230,12 @@ void TracksterLinksProducer::produce(edm::Event &evt, const edm::EventSetup &es) } } - if (regressionAndPid_) - energyRegressionAndID(layerClusters, tfSession_, *resultTracksters); + if (regressionAndPid_) { + // Run inference algorithm + inferenceAlgo_->inputData(layerClusters, *resultTracksters); + inferenceAlgo_->runInference( + *resultTracksters); //option to use "Linking" instead of "CLU3D"/"energyAndPid" instead of "PID" + } assignPCAtoTracksters(*resultTracksters, layerClusters, @@ -419,6 +279,15 @@ void TracksterLinksProducer::fillDescriptions(edm::ConfigurationDescriptions &de edm::ParameterSetDescription desc; edm::ParameterSetDescription linkingDesc; linkingDesc.addNode(edm::PluginDescription("type", "Skeletons", true)); + // Inference Plugins + edm::ParameterSetDescription inferenceDesc; + inferenceDesc.addNode(edm::PluginDescription("type", "TracksterInferenceByDNN", true)); + desc.add("pluginInferenceAlgoTracksterInferenceByDNN", inferenceDesc); + + edm::ParameterSetDescription inferenceDescCNNv4; + inferenceDescCNNv4.addNode( + edm::PluginDescription("type", "TracksterInferenceByCNNv4", true)); + desc.add("pluginInferenceAlgoTracksterInferenceByCNNv4", inferenceDescCNNv4); desc.add("linkingPSet", linkingDesc); desc.add>("tracksters_collections", {edm::InputTag("ticlTrackstersCLUE3DHigh")}); @@ -427,15 +296,9 @@ void TracksterLinksProducer::fillDescriptions(edm::ConfigurationDescriptions &de desc.add("layer_clusters", edm::InputTag("hgcalMergeLayerClusters")); desc.add("layer_clustersTime", edm::InputTag("hgcalMergeLayerClusters", "timeLayerCluster")); desc.add("regressionAndPid", false); - desc.add("tfDnnLabel", "tracksterSelectionTf"); - desc.add("eid_input_name", "input"); - desc.add("eid_output_name_energy", "output/regressed_energy"); - desc.add("eid_output_name_id", "output/id_probabilities"); - desc.add("eid_min_cluster_energy", 2.5); - desc.add("eid_n_layers", 50); - desc.add("eid_n_clusters", 10); desc.add("detector", "HGCAL"); desc.add("propagator", "PropagatorWithMaterial"); + desc.add("inferenceAlgo", "TracksterInferenceByDNN"); descriptions.add("tracksterLinksProducer", desc); } diff --git a/RecoHGCal/TICL/plugins/TrackstersProducer.cc b/RecoHGCal/TICL/plugins/TrackstersProducer.cc index d3fbb3a91e67e..cadb0805e18c5 100644 --- a/RecoHGCal/TICL/plugins/TrackstersProducer.cc +++ b/RecoHGCal/TICL/plugins/TrackstersProducer.cc @@ -20,14 +20,16 @@ #include "DataFormats/HGCalReco/interface/Trackster.h" #include "DataFormats/HGCalReco/interface/TICLLayerTile.h" #include "DataFormats/HGCalReco/interface/TICLSeedingRegion.h" +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" #include "RecoHGCal/TICL/plugins/PatternRecognitionPluginFactory.h" -#include "PhysicsTools/TensorFlow/interface/TfGraphRecord.h" -#include "PhysicsTools/TensorFlow/interface/TensorFlow.h" -#include "PhysicsTools/TensorFlow/interface/TfGraphDefWrapper.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoBase.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "RecoHGCal/TICL/interface/TracksterInferenceAlgoFactory.h" using namespace ticl; +using namespace cms::Ort; class TrackstersProducer : public edm::stream::EDProducer<> { public: @@ -44,12 +46,9 @@ class TrackstersProducer : public edm::stream::EDProducer<> { private: std::string detector_; bool doNose_; - const std::string tfDnnLabel_; - const edm::ESGetToken tfDnnToken_; - const tensorflow::Session* tfSession_; std::unique_ptr> myAlgo_; std::unique_ptr> myAlgoHFNose_; - + std::unique_ptr inferenceAlgo_; const edm::EDGetTokenT> clusters_token_; const edm::EDGetTokenT> filtered_layerclusters_mask_token_; const edm::EDGetTokenT> original_layerclusters_mask_token_; @@ -65,9 +64,6 @@ DEFINE_FWK_MODULE(TrackstersProducer); TrackstersProducer::TrackstersProducer(const edm::ParameterSet& ps) : detector_(ps.getParameter("detector")), doNose_(detector_ == "HFNose"), - tfDnnLabel_(ps.getParameter("tfDnnLabel")), - tfDnnToken_(esConsumes(edm::ESInputTag("", tfDnnLabel_))), - tfSession_(nullptr), clusters_token_(consumes>(ps.getParameter("layer_clusters"))), filtered_layerclusters_mask_token_(consumes>(ps.getParameter("filtered_mask"))), original_layerclusters_mask_token_(consumes>(ps.getParameter("original_mask"))), @@ -89,6 +85,12 @@ TrackstersProducer::TrackstersProducer(const edm::ParameterSet& ps) layer_clusters_tiles_token_ = consumes(ps.getParameter("layer_clusters_tiles")); } + // 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)); + if (itername_ == "TrkEM") iterIndex_ = ticl::Trackster::TRKEM; else if (itername_ == "EM") @@ -117,7 +119,7 @@ void TrackstersProducer::fillDescriptions(edm::ConfigurationDescriptions& descri desc.add("seeding_regions", edm::InputTag("ticlSeedingRegionProducer")); desc.add("patternRecognitionBy", "CA"); desc.add("itername", "unknown"); - desc.add("tfDnnLabel", "tracksterSelectionTf"); + desc.add("inferenceAlgo", "TracksterInferenceByDNN"); // CA Plugin edm::ParameterSetDescription pluginDesc; @@ -139,11 +141,27 @@ void TrackstersProducer::fillDescriptions(edm::ConfigurationDescriptions& descri pluginDescPassThrough.addNode(edm::PluginDescription("type", "Passthrough", true)); desc.add("pluginPatternRecognitionByPassthrough", pluginDescPassThrough); + // Inference Plugins + edm::ParameterSetDescription inferenceDesc; + inferenceDesc.addNode(edm::PluginDescription("type", "TracksterInferenceByDNN", true)); + desc.add("pluginInferenceAlgoTracksterInferenceByDNN", inferenceDesc); + + edm::ParameterSetDescription inferenceDescANN; + inferenceDescANN.addNode( + edm::PluginDescription("type", "TracksterInferenceByANN", true)); + desc.add("pluginInferenceAlgoTracksterInferenceByANN", inferenceDescANN); + + edm::ParameterSetDescription inferenceDescCNNv4; + inferenceDescCNNv4.addNode( + edm::PluginDescription("type", "TracksterInferenceByCNNv4", true)); + desc.add("pluginInferenceAlgoTracksterInferenceByCNNv4", inferenceDescCNNv4); + descriptions.add("trackstersProducer", desc); } void TrackstersProducer::produce(edm::Event& evt, const edm::EventSetup& es) { auto result = std::make_unique>(); + auto initialResult = std::make_unique>(); auto output_mask = std::make_unique>(); const std::vector& original_layerclusters_mask = evt.get(original_layerclusters_mask_token_); @@ -152,8 +170,6 @@ void TrackstersProducer::produce(edm::Event& evt, const edm::EventSetup& es) { const auto& layerClustersTimes = evt.get(clustersTime_token_); const auto& seeding_regions = evt.get(seeding_regions_token_); - tfSession_ = es.getData(tfDnnToken_).getSession(); - std::unordered_map> seedToTrackstersAssociation; // if it's regional iteration and there are seeding regions if (!seeding_regions.empty() and seeding_regions[0].index != -1) { @@ -165,23 +181,25 @@ void TrackstersProducer::produce(edm::Event& evt, const edm::EventSetup& es) { if (doNose_) { const auto& layer_clusters_hfnose_tiles = evt.get(layer_clusters_tiles_hfnose_token_); - const typename PatternRecognitionAlgoBaseT::Inputs inputHFNose(evt, - es, - layerClusters, - inputClusterMask, - layerClustersTimes, - layer_clusters_hfnose_tiles, - seeding_regions, - tfSession_); + const typename PatternRecognitionAlgoBaseT::Inputs inputHFNose( + evt, es, layerClusters, inputClusterMask, layerClustersTimes, layer_clusters_hfnose_tiles, seeding_regions); - myAlgoHFNose_->makeTracksters(inputHFNose, *result, seedToTrackstersAssociation); + myAlgoHFNose_->makeTracksters(inputHFNose, *initialResult, seedToTrackstersAssociation); + // Run inference algorithm + inferenceAlgo_->inputData(layerClusters, *initialResult); + inferenceAlgo_->runInference(*initialResult); + myAlgoHFNose_->filter(*result, *initialResult, inputHFNose, seedToTrackstersAssociation); } else { const auto& layer_clusters_tiles = evt.get(layer_clusters_tiles_token_); const typename PatternRecognitionAlgoBaseT::Inputs input( - evt, es, layerClusters, inputClusterMask, layerClustersTimes, layer_clusters_tiles, seeding_regions, tfSession_); + evt, es, layerClusters, inputClusterMask, layerClustersTimes, layer_clusters_tiles, seeding_regions); - myAlgo_->makeTracksters(input, *result, seedToTrackstersAssociation); + myAlgo_->makeTracksters(input, *initialResult, seedToTrackstersAssociation); + // Run inference algorithm + inferenceAlgo_->inputData(layerClusters, *initialResult); + inferenceAlgo_->runInference(*initialResult); + myAlgo_->filter(*result, *initialResult, input, seedToTrackstersAssociation); } // Now update the global mask and put it into the event output_mask->reserve(original_layerclusters_mask.size()); diff --git a/RecoHGCal/TICL/python/CLUE3DHighStep_cff.py b/RecoHGCal/TICL/python/CLUE3DHighStep_cff.py index 177dc76cf7a86..67e21faf6272b 100644 --- a/RecoHGCal/TICL/python/CLUE3DHighStep_cff.py +++ b/RecoHGCal/TICL/python/CLUE3DHighStep_cff.py @@ -26,13 +26,46 @@ algo_verbosity = 0, doPidCut = True, cutHadProb = 999 - ) + ), + inferenceAlgo = cms.string('TracksterInferenceByCNNv4'), + pluginInferenceAlgoTracksterInferenceByCNNv4 = cms.PSet( + algo_verbosity = cms.int32(0), + onnxModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv4/onnx_models/energy_id_v0.onnx'), + inputNames = cms.vstring('input:0'), + outputNames = cms.vstring("output/regressed_energy:0", "output/id_probabilities:0"), + 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(0), + type = cms.string('TracksterInferenceByCNNv4') + ), + pluginInferenceAlgoTracksterInferenceByDNN = cms.PSet( + algo_verbosity = cms.int32(0), + onnxPIDModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/id_v0.onnx'), + onnxEnergyModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/patternrecognition/energy_v0.onnx'), + inputNames = cms.vstring('input'), + 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(0), + type = cms.string('TracksterInferenceByDNN') + ), + pluginInferenceAlgoTracksterInferenceByANN = cms.PSet( + algo_verbosity = cms.int32(0), + type = cms.string('TracksterInferenceByANN') + + ), + ) from Configuration.ProcessModifiers.ticl_v5_cff import ticl_v5 ticl_v5.toModify(ticlTrackstersCLUE3DHigh.pluginPatternRecognitionByCLUE3D, computeLocalTime = cms.bool(True)) -ticl_v5.toModify(ticlTrackstersCLUE3DHigh.pluginPatternRecognitionByCLUE3D, usePCACleaning = cms.bool(True)) +ticl_v5.toModify(ticlTrackstersCLUE3DHigh.inferenceAlgo, type = cms.string('TracksterInferenceByDNN')) ticlCLUE3DHighStepTask = cms.Task(ticlSeedingGlobal ,filteredLayerClustersCLUE3DHigh diff --git a/RecoHGCal/TICL/python/iterativeTICL_cff.py b/RecoHGCal/TICL/python/iterativeTICL_cff.py index d967520046494..9737020823e94 100644 --- a/RecoHGCal/TICL/python/iterativeTICL_cff.py +++ b/RecoHGCal/TICL/python/iterativeTICL_cff.py @@ -32,8 +32,24 @@ 'ticlTrackstersCLUE3DHigh', 'ticlTrackstersPassthrough' ), - regressionAndPid = cms.bool(True) + regressionAndPid = cms.bool(True), + inferenceAlgo = cms.string('TracksterInferenceByDNN'), + pluginInferenceAlgoTracksterInferenceByDNN = cms.PSet( + algo_verbosity = cms.int32(0), + doPID = cms.int32(1), + doRegression = cms.int32(1), + inputNames = cms.vstring('input'), + output_en = cms.vstring('enreg_output'), + output_id = cms.vstring('pid_output'), + eid_min_cluster_energy = cms.double(1), + eid_n_clusters = cms.int32(10), + eid_n_layers = cms.int32(50), + onnxEnergyModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/linking/energy_v0.onnx'), + onnxPIDModelPath = cms.FileInPath('RecoHGCal/TICL/data/ticlv5/onnx_models/linking/id_v0.onnx'), + type = cms.string('TracksterInferenceByDNN') + ) ) + ticlCandidate = _ticlCandidateProducer.clone() mtdSoA = _mtdSoAProducer.clone() diff --git a/RecoHGCal/TICL/python/tracksterSelectionTf_cfi.py b/RecoHGCal/TICL/python/tracksterSelectionTf_cfi.py index c57e372622cdc..52a83d14a3d29 100644 --- a/RecoHGCal/TICL/python/tracksterSelectionTf_cfi.py +++ b/RecoHGCal/TICL/python/tracksterSelectionTf_cfi.py @@ -1,5 +1,5 @@ from PhysicsTools.TensorFlow.tfGraphDefProducer_cfi import tfGraphDefProducer as _tfGraphDefProducer tracksterSelectionTf = _tfGraphDefProducer.clone( ComponentName = "tracksterSelectionTf", - FileName = "RecoHGCal/TICL/data/tf_models/energy_id_v0.pb" + FileName = "RecoHGCal/TICL/data/ticlv4/tf_models/energy_id_v0.pb" )