From b599a18e3737553f453bc073414c15ad1a4c22aa Mon Sep 17 00:00:00 2001 From: Andre Govinda Stahl Leiton Date: Tue, 6 Aug 2024 21:19:46 +0200 Subject: [PATCH] Introduce Unified Particle Transformer AK4 jet tagger --- .../interface/ChargedCandidateFeatures.h | 10 +- .../BTauReco/interface/LostTracksFeatures.h | 34 ++ .../UnifiedParticleTransformerAK4Features.h | 25 + .../UnifiedParticleTransformerAK4TagInfo.h | 15 + DataFormats/BTauReco/src/classes.h | 2 + DataFormats/BTauReco/src/classes_def.xml | 16 +- .../python/recoLayer0/bTagging_cff.py | 12 + .../PatAlgos/python/tools/jetTools.py | 36 +- RecoBTag/Configuration/python/RecoBTag_cff.py | 1 + .../interface/ChargedCandidateConverter.h | 1 + .../interface/LostTracksConverter.h | 81 +++ .../FeatureTools/interface/TrackInfoBuilder.h | 2 + ...edParticleTransformerAK4TagInfoProducer.cc | 530 ++++++++++++++++++ .../src/ChargedCandidateConverter.cc | 28 + .../FeatureTools/src/LostTracksConverter.cc | 60 ++ RecoBTag/FeatureTools/src/TrackInfoBuilder.cc | 7 +- ...rticleTransformerAK4ONNXJetTagsProducer.cc | 358 ++++++++++++ .../python/pfHiggsInteractionNet_cff.py | 2 +- .../python/pfParticleNetFromMiniAODAK4_cff.py | 8 +- .../python/pfParticleNetFromMiniAODAK8_cff.py | 2 +- ...TransformerAK4DiscriminatorsJetTags_cfi.py | 157 ++++++ .../pfUnifiedParticleTransformerAK4_cff.py | 29 + .../ONNXRuntime/test/test_deep_flavour_cfg.py | 2 +- .../test/test_unifiedpartak4_cfg.py | 88 +++ 24 files changed, 1494 insertions(+), 12 deletions(-) create mode 100644 DataFormats/BTauReco/interface/LostTracksFeatures.h create mode 100644 DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h create mode 100644 DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4TagInfo.h create mode 100644 RecoBTag/FeatureTools/interface/LostTracksConverter.h create mode 100644 RecoBTag/FeatureTools/plugins/UnifiedParticleTransformerAK4TagInfoProducer.cc create mode 100644 RecoBTag/FeatureTools/src/LostTracksConverter.cc create mode 100644 RecoBTag/ONNXRuntime/plugins/UnifiedParticleTransformerAK4ONNXJetTagsProducer.cc create mode 100644 RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4DiscriminatorsJetTags_cfi.py create mode 100644 RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4_cff.py create mode 100644 RecoBTag/ONNXRuntime/test/test_unifiedpartak4_cfg.py diff --git a/DataFormats/BTauReco/interface/ChargedCandidateFeatures.h b/DataFormats/BTauReco/interface/ChargedCandidateFeatures.h index 74a11fe2342c3..aae6c350a1a6c 100644 --- a/DataFormats/BTauReco/interface/ChargedCandidateFeatures.h +++ b/DataFormats/BTauReco/interface/ChargedCandidateFeatures.h @@ -22,7 +22,6 @@ namespace btagbtvdeep { float btagPf_trackSip3dSig; float btagPf_trackSip2dVal; float btagPf_trackSip2dSig; - float btagPf_trackJetDistVal; float drsubjet1; @@ -39,6 +38,15 @@ namespace btagbtvdeep { float drminsv; float distminsv; + float charge; + float btagPf_trackDecayLen; + float HadFrac; + float CaloFrac; + float pdgID; + float lostInnerHits; + float numberOfPixelHits; + float numberOfStripHits; + float pt; float px; float py; diff --git a/DataFormats/BTauReco/interface/LostTracksFeatures.h b/DataFormats/BTauReco/interface/LostTracksFeatures.h new file mode 100644 index 0000000000000..06368eb21bd68 --- /dev/null +++ b/DataFormats/BTauReco/interface/LostTracksFeatures.h @@ -0,0 +1,34 @@ +#ifndef DataFormats_BTauReco_LostTracksFeatures_h +#define DataFormats_BTauReco_LostTracksFeatures_h + +namespace btagbtvdeep { + + class LostTracksFeatures { + public: + float btagPf_trackEtaRel; + float btagPf_trackPtRel; + float btagPf_trackPPar; + float btagPf_trackDeltaR; + float btagPf_trackPParRatio; + float btagPf_trackSip2dVal; + float btagPf_trackSip2dSig; + float btagPf_trackSip3dVal; + float btagPf_trackSip3dSig; + float btagPf_trackJetDistVal; + float drminsv; + float charge; + float puppiw; + float chi2; + float quality; + float lostInnerHits; + float numberOfPixelHits; + float numberOfStripHits; + float pt; + float eta; + float phi; + float e; + }; + +} // namespace btagbtvdeep + +#endif //DataFormats_BTauReco_LostTracksFeatures_h diff --git a/DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h b/DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h new file mode 100644 index 0000000000000..b52b107d6e673 --- /dev/null +++ b/DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h @@ -0,0 +1,25 @@ +#ifndef DataFormats_BTauReco_UnifiedParticleTransformerAK4Features_h +#define DataFormats_BTauReco_UnifiedParticleTransformerAK4Features_h + +#include "DataFormats/BTauReco/interface/SecondaryVertexFeatures.h" +#include "DataFormats/BTauReco/interface/NeutralCandidateFeatures.h" +#include "DataFormats/BTauReco/interface/ChargedCandidateFeatures.h" +#include "DataFormats/BTauReco/interface/LostTracksFeatures.h" + +#include + +namespace btagbtvdeep { + + class UnifiedParticleTransformerAK4Features { + public: + bool is_filled = true; + std::vector sv_features; + + std::vector n_pf_features; + std::vector c_pf_features; + std::vector lt_features; + }; + +} // namespace btagbtvdeep + +#endif //DataFormats_BTauReco_UnifiedParticleTransformerAK4Features_h diff --git a/DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4TagInfo.h b/DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4TagInfo.h new file mode 100644 index 0000000000000..67c31ff91acd2 --- /dev/null +++ b/DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4TagInfo.h @@ -0,0 +1,15 @@ +#ifndef DataFormats_BTauReco_UnifiedParticleTransformerAK4TagInfo_h +#define DataFormats_BTauReco_UnifiedParticleTransformerAK4TagInfo_h + +#include "DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h" +#include "DataFormats/BTauReco/interface/FeaturesTagInfo.h" + +namespace reco { + + typedef FeaturesTagInfo UnifiedParticleTransformerAK4TagInfo; + + DECLARE_EDM_REFS(UnifiedParticleTransformerAK4TagInfo) + +} // namespace reco + +#endif // DataFormats_BTauReco_UnifiedParticleTransformerAK4TagInfo_h diff --git a/DataFormats/BTauReco/src/classes.h b/DataFormats/BTauReco/src/classes.h index 49f56a9762747..01025202de2df 100644 --- a/DataFormats/BTauReco/src/classes.h +++ b/DataFormats/BTauReco/src/classes.h @@ -65,6 +65,8 @@ #include "DataFormats/BTauReco/interface/DeepDoubleXTagInfo.h" #include "DataFormats/BTauReco/interface/ParticleTransformerAK4Features.h" #include "DataFormats/BTauReco/interface/ParticleTransformerAK4TagInfo.h" +#include "DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h" +#include "DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4TagInfo.h" #include "DataFormats/BTauReco/interface/DeepBoostedJetTagInfo.h" #include "DataFormats/BTauReco/interface/PixelClusterTagInfo.h" diff --git a/DataFormats/BTauReco/src/classes_def.xml b/DataFormats/BTauReco/src/classes_def.xml index 148a0bda78d20..f8349694c7b67 100644 --- a/DataFormats/BTauReco/src/classes_def.xml +++ b/DataFormats/BTauReco/src/classes_def.xml @@ -329,6 +329,8 @@ + + @@ -366,6 +368,8 @@ + + @@ -427,7 +431,8 @@ - + + @@ -467,6 +472,14 @@ + + + + + + + + @@ -477,6 +490,7 @@ + diff --git a/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py b/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py index 361c2fd2814ae..727d7cf99e496 100644 --- a/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py +++ b/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py @@ -43,6 +43,8 @@ , 'pfNegativeDeepFlavourTagInfos' # ParticleTransformerAK4 tag infos , 'pfParticleTransformerAK4TagInfos' + # UnifiedParticleTransformerAK4 tag infos + , 'pfUnifiedParticleTransformerAK4TagInfos' # DeepDoubleB/C tag infos , 'pfDeepDoubleXTagInfos' # DeepBoostedJet tag infos @@ -338,3 +340,13 @@ for disc in _pfParticleTransformerAK4JetTagsMetaDiscrs: supportedMetaDiscr[disc] = _pfParticleTransformerAK4JetTagsProbs # ----------------------------------- + +# ----------------------------------- +# setup UnifiedParticleTransformer AK4 +from RecoBTag.ONNXRuntime.pfUnifiedParticleTransformerAK4_cff import _pfUnifiedParticleTransformerAK4JetTagsProbs, _pfUnifiedParticleTransformerAK4JetTagsMetaDiscrs +# update supportedBtagDiscr +for disc in _pfUnifiedParticleTransformerAK4JetTagsProbs + _pfUnifiedParticleTransformerAK4JetTagsMetaDiscrs: + supportedBtagDiscr[disc] = [["pfUnifiedParticleTransformerAK4TagInfos"]] +# update supportedMetaDiscr +for disc in _pfUnifiedParticleTransformerAK4JetTagsMetaDiscrs: + supportedMetaDiscr[disc] = _pfUnifiedParticleTransformerAK4JetTagsProbs diff --git a/PhysicsTools/PatAlgos/python/tools/jetTools.py b/PhysicsTools/PatAlgos/python/tools/jetTools.py index 5854c1481c874..050258c8bea5a 100644 --- a/PhysicsTools/PatAlgos/python/tools/jetTools.py +++ b/PhysicsTools/PatAlgos/python/tools/jetTools.py @@ -681,11 +681,11 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou flip = flip), process, task) - if 'ParticleTransformerAK4TagInfos' in btagInfo: + if ('ParticleTransformerAK4TagInfos' in btagInfo) and ('UnifiedParticleTransformerAK4TagInfos' not in btagInfo): #We also have to veto UParT is we select ParT svUsed = svSource if btagInfo == 'pfNegativeParticleTransformerAK4TagInfos': svUsed = cms.InputTag(btagPrefix+'inclusiveCandidateNegativeSecondaryVertices'+labelName+postfix) - flip = True + flip = True else: flip = False # use right input tags when running with RECO PF candidates, which actually @@ -711,6 +711,38 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou is_weighted_jet = is_weighted_jet, flip = flip), process, task) + + if 'UnifiedParticleTransformerAK4TagInfos' in btagInfo: + svUsed = svSource + if btagInfo == 'pfNegativeUnifiedParticleTransformerAK4TagInfos': + svUsed = cms.InputTag(btagPrefix+'inclusiveCandidateNegativeSecondaryVertices'+labelName+postfix) + flip = True + else: + flip = False + # use right input tags when running with RECO PF candidates, which actually + # depends of whether jets use "particleFlow" + if pfCandidates.value() == 'packedPFCandidates': + puppi_value_map = setupPuppiForPackedPF(process)[0] + vertex_associator = cms.InputTag("") + else: + puppi_value_map = cms.InputTag("puppi") + vertex_associator = cms.InputTag("primaryVertexAssociation","original") + + # If this jet is a puppi jet, then set is_weighted_jet to true. + is_weighted_jet = False + if ('puppi' in jetSource.value().lower()): + is_weighted_jet = True + addToProcessAndTask(btagPrefix+btagInfo+labelName+postfix, + btag.pfUnifiedParticleTransformerAK4TagInfos.clone( + jets = jetSource, + vertices=pvSource, + secondary_vertices=svUsed, + puppi_value_map = puppi_value_map, + vertex_associator = vertex_associator, + is_weighted_jet = is_weighted_jet, + flip = flip), + process, task) + if btagInfo == 'pfDeepDoubleXTagInfos': # can only run on PAT jets, so the updater needs to be used if 'updated' not in jetSource.value().lower(): diff --git a/RecoBTag/Configuration/python/RecoBTag_cff.py b/RecoBTag/Configuration/python/RecoBTag_cff.py index fab7ac28b3475..2602b0ccb75cc 100644 --- a/RecoBTag/Configuration/python/RecoBTag_cff.py +++ b/RecoBTag/Configuration/python/RecoBTag_cff.py @@ -14,6 +14,7 @@ from RecoBTag.ONNXRuntime.pfParticleNet_cff import * from RecoBTag.ONNXRuntime.pfParticleNetAK4_cff import * from RecoBTag.ONNXRuntime.pfParticleTransformerAK4_cff import * +from RecoBTag.ONNXRuntime.pfUnifiedParticleTransformerAK4_cff import * from RecoVertex.AdaptiveVertexFinder.inclusiveVertexing_cff import * from RecoBTag.PixelCluster.pixelClusterTagInfos_cfi import * diff --git a/RecoBTag/FeatureTools/interface/ChargedCandidateConverter.h b/RecoBTag/FeatureTools/interface/ChargedCandidateConverter.h index 02dc62ce7384d..ff711d3838505 100644 --- a/RecoBTag/FeatureTools/interface/ChargedCandidateConverter.h +++ b/RecoBTag/FeatureTools/interface/ChargedCandidateConverter.h @@ -57,6 +57,7 @@ namespace btagbtvdeep { c_pf_features.btagPf_trackSip2dVal = catch_infs_and_bound(trackSip2dVal, 0, -1, 70); c_pf_features.btagPf_trackSip2dSig = catch_infs_and_bound(trackSip2dSig, 0, -1, 4e4); c_pf_features.btagPf_trackJetDistVal = catch_infs_and_bound(track_info.getTrackJetDistVal(), 0, -20, 1); + c_pf_features.btagPf_trackDecayLen = track_info.getTrackJetDecayLen(); c_pf_features.drminsv = catch_infs_and_bound(drminpfcandsv, 0, -1. * jetR, 0, -1. * jetR); c_pf_features.distminsv = distminpfcandsv; diff --git a/RecoBTag/FeatureTools/interface/LostTracksConverter.h b/RecoBTag/FeatureTools/interface/LostTracksConverter.h new file mode 100644 index 0000000000000..6c1d7283adbac --- /dev/null +++ b/RecoBTag/FeatureTools/interface/LostTracksConverter.h @@ -0,0 +1,81 @@ +#ifndef RecoBTag_FeatureTools_LostTracksConverter_h +#define RecoBTag_FeatureTools_LostTracksConverter_h + +#include "RecoBTag/FeatureTools/interface/deep_helpers.h" +#include "RecoBTag/FeatureTools/interface/TrackInfoBuilder.h" +#include "DataFormats/BTauReco/interface/LostTracksFeatures.h" + +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" +#include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h" +#include "DataFormats/PatCandidates/interface/Jet.h" + +namespace btagbtvdeep { + + template + void commonCandidateToFeatures(const CandidateType* c_pf, + const reco::Jet& jet, + const TrackInfoBuilder& track_info, + const bool& isWeightedJet, + const float& drminpfcandsv, + const float& jetR, + const float& puppiw, + LostTracksFeatures& lt_features, + const bool flip = false, + const float& distminpfcandsv = 0) { + float trackSip2dVal = track_info.getTrackSip2dVal(); + float trackSip2dSig = track_info.getTrackSip2dSig(); + float trackSip3dVal = track_info.getTrackSip3dVal(); + float trackSip3dSig = track_info.getTrackSip3dSig(); + if (flip == true) { + trackSip2dVal = -trackSip2dVal; + trackSip2dSig = -trackSip2dSig; + trackSip3dSig = -trackSip3dSig; + trackSip3dVal = -trackSip3dVal; + } + + lt_features.btagPf_trackEtaRel = catch_infs_and_bound(track_info.getTrackEtaRel(), 0, -5, 15); + lt_features.btagPf_trackPtRel = catch_infs_and_bound(track_info.getTrackPtRel(), 0, -1, 4); + lt_features.btagPf_trackPPar = catch_infs_and_bound(track_info.getTrackPPar(), 0, -1e5, 1e5); + lt_features.btagPf_trackDeltaR = catch_infs_and_bound(track_info.getTrackDeltaR(), 0, -5, 5); + lt_features.btagPf_trackPParRatio = catch_infs_and_bound(track_info.getTrackPParRatio(), 0, -10, 100); + lt_features.btagPf_trackSip3dVal = catch_infs_and_bound(trackSip3dVal, 0, -1, 1e5); + lt_features.btagPf_trackSip3dSig = catch_infs_and_bound(trackSip3dSig, 0, -1, 4e4); + lt_features.btagPf_trackSip2dVal = catch_infs_and_bound(trackSip2dVal, 0, -1, 70); + lt_features.btagPf_trackSip2dSig = catch_infs_and_bound(trackSip2dSig, 0, -1, 4e4); + lt_features.btagPf_trackJetDistVal = catch_infs_and_bound(track_info.getTrackJetDistVal(), 0, -20, 1); + + lt_features.drminsv = catch_infs_and_bound(drminpfcandsv, 0, -1. * jetR, 0, -1. * jetR); + + lt_features.pt = c_pf->pt(); + lt_features.eta = c_pf->eta(); + lt_features.phi = c_pf->phi(); + lt_features.e = c_pf->energy(); + } + + void packedCandidateToFeatures(const pat::PackedCandidate* c_pf, + const pat::Jet& jet, + const TrackInfoBuilder& track_info, + const bool isWeightedJet, + const float drminpfcandsv, + const float jetR, + const float puppiw, + LostTracksFeatures& lt_features, + const bool flip = false, + const float distminpfcandsv = 0); + + void recoCandidateToFeatures(const reco::PFCandidate* c_pf, + const reco::Jet& jet, + const TrackInfoBuilder& track_info, + const bool isWeightedJet, + const float drminpfcandsv, + const float jetR, + const float puppiw, + const int pv_ass_quality, + const reco::VertexRef& pv, + LostTracksFeatures& lt_features, + const bool flip = false, + const float distminpfcandsv = 0); + +} // namespace btagbtvdeep + +#endif //RecoBTag_FeatureTools_LostTracksConverter_h diff --git a/RecoBTag/FeatureTools/interface/TrackInfoBuilder.h b/RecoBTag/FeatureTools/interface/TrackInfoBuilder.h index c9c6cc47c500b..44bb016642079 100644 --- a/RecoBTag/FeatureTools/interface/TrackInfoBuilder.h +++ b/RecoBTag/FeatureTools/interface/TrackInfoBuilder.h @@ -31,6 +31,7 @@ namespace btagbtvdeep { const float getTrackSip2dVal() const { return trackSip2dVal_; } const float getTrackSip3dSig() const { return trackSip3dSig_; } const float getTrackSip3dVal() const { return trackSip3dVal_; } + const float getTrackJetDecayLen() const { return trackJetDecayLen_; } private: edm::ESHandle builder_; @@ -50,6 +51,7 @@ namespace btagbtvdeep { float trackJetDistVal_; float trackJetDistSig_; + float trackJetDecayLen_; }; } // namespace btagbtvdeep diff --git a/RecoBTag/FeatureTools/plugins/UnifiedParticleTransformerAK4TagInfoProducer.cc b/RecoBTag/FeatureTools/plugins/UnifiedParticleTransformerAK4TagInfoProducer.cc new file mode 100644 index 0000000000000..349da4f98f797 --- /dev/null +++ b/RecoBTag/FeatureTools/plugins/UnifiedParticleTransformerAK4TagInfoProducer.cc @@ -0,0 +1,530 @@ +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" +#include "FWCore/Utilities/interface/ESGetToken.h" + +#include "DataFormats/PatCandidates/interface/Jet.h" +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" + +#include "DataFormats/BTauReco/interface/ShallowTagInfo.h" + +#include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h" +#include "TrackingTools/Records/interface/TransientTrackRecord.h" + +#include "DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4TagInfo.h" +#include "DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h" + +#include "RecoBTag/FeatureTools/interface/JetConverter.h" +#include "RecoBTag/FeatureTools/interface/ShallowTagInfoConverter.h" +#include "RecoBTag/FeatureTools/interface/SecondaryVertexConverter.h" +#include "RecoBTag/FeatureTools/interface/NeutralCandidateConverter.h" +#include "RecoBTag/FeatureTools/interface/ChargedCandidateConverter.h" +#include "RecoBTag/FeatureTools/interface/LostTracksConverter.h" + +#include "RecoBTag/FeatureTools/interface/TrackInfoBuilder.h" +#include "RecoBTag/FeatureTools/interface/sorting_modules.h" + +#include "DataFormats/VertexReco/interface/VertexFwd.h" +#include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h" + +#include "RecoBTag/FeatureTools/interface/deep_helpers.h" + +#include "FWCore/ParameterSet/interface/Registry.h" +#include "FWCore/Common/interface/Provenance.h" +#include "DataFormats/Provenance/interface/ProductProvenance.h" + +#include "DataFormats/BTauReco/interface/SeedingTrackFeatures.h" +#include "DataFormats/BTauReco/interface/TrackPairFeatures.h" +#include "RecoBTag/FeatureTools/interface/TrackPairInfoBuilder.h" +#include "RecoBTag/FeatureTools/interface/SeedingTrackInfoBuilder.h" +#include "RecoBTag/FeatureTools/interface/SeedingTracksConverter.h" + +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "RecoBTag/TrackProbability/interface/HistogramProbabilityEstimator.h" +class HistogramProbabilityEstimator; +#include + +#include +#include "CondFormats/BTauObjects/interface/TrackProbabilityCalibration.h" +#include "CondFormats/DataRecord/interface/BTagTrackProbability2DRcd.h" +#include "CondFormats/DataRecord/interface/BTagTrackProbability3DRcd.h" +#include "FWCore/Framework/interface/EventSetupRecord.h" +#include "FWCore/Framework/interface/EventSetupRecordImplementation.h" +#include "FWCore/Framework/interface/EventSetupRecordKey.h" +#include "DataFormats/Common/interface/AssociationMap.h" + +class UnifiedParticleTransformerAK4TagInfoProducer : public edm::stream::EDProducer<> { +public: + explicit UnifiedParticleTransformerAK4TagInfoProducer(const edm::ParameterSet&); + ~UnifiedParticleTransformerAK4TagInfoProducer() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + typedef std::vector UnifiedParticleTransformerAK4TagInfoCollection; + typedef reco::VertexCompositePtrCandidateCollection SVCollection; + typedef reco::VertexCollection VertexCollection; + typedef edm::AssociationMap> JetMatchMap; + + void beginStream(edm::StreamID) override {} + void produce(edm::Event&, const edm::EventSetup&) override; + void endStream() override {} + + const double jet_radius_; + const double min_candidate_pt_; + const bool flip_; + + const edm::EDGetTokenT> jet_token_; + const edm::EDGetTokenT vtx_token_; + const edm::EDGetTokenT> lt_token_; + const edm::EDGetTokenT sv_token_; + edm::EDGetTokenT unsubjet_map_token_; + edm::EDGetTokenT> puppi_value_map_token_; + edm::EDGetTokenT> pvasq_value_map_token_; + edm::EDGetTokenT> pvas_token_; + const edm::EDGetTokenT> candidateToken_; + const edm::ESGetToken track_builder_token_; + bool use_puppi_value_map_; + bool use_pvasq_value_map_; + bool use_unsubjet_map_; + + const bool fallback_puppi_weight_; + const bool fallback_vertex_association_; + + const bool is_weighted_jet_; + + const double min_jet_pt_; + const double max_jet_eta_; +}; + +UnifiedParticleTransformerAK4TagInfoProducer::UnifiedParticleTransformerAK4TagInfoProducer( + const edm::ParameterSet& iConfig) + : jet_radius_(iConfig.getParameter("jet_radius")), + min_candidate_pt_(iConfig.getParameter("min_candidate_pt")), + flip_(iConfig.getParameter("flip")), + jet_token_(consumes>(iConfig.getParameter("jets"))), + vtx_token_(consumes(iConfig.getParameter("vertices"))), + lt_token_(consumes>(iConfig.getParameter("losttracks"))), + sv_token_(consumes(iConfig.getParameter("secondary_vertices"))), + candidateToken_(consumes>(iConfig.getParameter("candidates"))), + track_builder_token_( + esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))), + use_puppi_value_map_(false), + use_pvasq_value_map_(false), + use_unsubjet_map_(false), + fallback_puppi_weight_(iConfig.getParameter("fallback_puppi_weight")), + fallback_vertex_association_(iConfig.getParameter("fallback_vertex_association")), + is_weighted_jet_(iConfig.getParameter("is_weighted_jet")), + min_jet_pt_(iConfig.getParameter("min_jet_pt")), + max_jet_eta_(iConfig.getParameter("max_jet_eta")) { + produces(); + + const auto& puppi_value_map_tag = iConfig.getParameter("puppi_value_map"); + if (!puppi_value_map_tag.label().empty()) { + puppi_value_map_token_ = consumes>(puppi_value_map_tag); + use_puppi_value_map_ = true; + } else if (is_weighted_jet_) { + throw edm::Exception(edm::errors::Configuration, + "puppi_value_map is not set but jet is weighted. Must set puppi_value_map."); + } + + const auto& pvas_tag = iConfig.getParameter("vertex_associator"); + if (!pvas_tag.label().empty()) { + pvasq_value_map_token_ = consumes>(pvas_tag); + pvas_token_ = consumes>(pvas_tag); + use_pvasq_value_map_ = true; + } + + const auto& unsubjet_map_tag = iConfig.getParameter("unsubjet_map"); + if (!unsubjet_map_tag.label().empty()) { + unsubjet_map_token_ = consumes(unsubjet_map_tag); + use_unsubjet_map_ = true; + } +} + +void UnifiedParticleTransformerAK4TagInfoProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + // pfUnifiedParticleTransformerAK4TagInfos + edm::ParameterSetDescription desc; + desc.add("jet_radius", 0.4); + desc.add("min_candidate_pt", 0.10); + desc.add("flip", false); + desc.add("vertices", edm::InputTag("offlinePrimaryVertices")); + desc.add("losttracks", edm::InputTag("lostTracks")); + desc.add("puppi_value_map", edm::InputTag("puppi")); + desc.add("secondary_vertices", edm::InputTag("inclusiveCandidateSecondaryVertices")); + desc.add("jets", edm::InputTag("ak4PFJetsCHS")); + desc.add("unsubjet_map", {}); + desc.add("candidates", edm::InputTag("packedPFCandidates")); + desc.add("vertex_associator", edm::InputTag("primaryVertexAssociation", "original")); + desc.add("fallback_puppi_weight", false); + desc.add("fallback_vertex_association", false); + desc.add("is_weighted_jet", false); + desc.add("min_jet_pt", 15.0); + desc.add("max_jet_eta", 2.5); + descriptions.add("pfUnifiedParticleTransformerAK4TagInfos", desc); +} + +void UnifiedParticleTransformerAK4TagInfoProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + auto output_tag_infos = std::make_unique(); + edm::Handle> jets; + iEvent.getByToken(jet_token_, jets); + + edm::Handle unsubjet_map; + if (use_unsubjet_map_) + iEvent.getByToken(unsubjet_map_token_, unsubjet_map); + + edm::Handle vtxs; + iEvent.getByToken(vtx_token_, vtxs); + if (vtxs->empty()) { + // produce empty TagInfos in case no primary vertex + iEvent.put(std::move(output_tag_infos)); + return; // exit event + } + + edm::Handle> LTs; + iEvent.getByToken(lt_token_, LTs); + + // reference to primary vertex + const auto& pv = vtxs->at(0); + + edm::Handle> tracks; + iEvent.getByToken(candidateToken_, tracks); + + edm::Handle svs; + iEvent.getByToken(sv_token_, svs); + + edm::Handle> puppi_value_map; + if (use_puppi_value_map_) { + iEvent.getByToken(puppi_value_map_token_, puppi_value_map); + } + + edm::Handle> pvasq_value_map; + edm::Handle> pvas; + if (use_pvasq_value_map_) { + iEvent.getByToken(pvasq_value_map_token_, pvasq_value_map); + iEvent.getByToken(pvas_token_, pvas); + } + + edm::ESHandle track_builder = iSetup.getHandle(track_builder_token_); + + for (std::size_t jet_n = 0; jet_n < jets->size(); jet_n++) { + // create data containing structure + btagbtvdeep::UnifiedParticleTransformerAK4Features features; + + // reco jet reference (use as much as possible) + const auto& jet = jets->at(jet_n); + if (jet.pt() < 15.0) { + features.is_filled = false; + } + if (std::abs(jet.eta()) > 2.5) { + features.is_filled = false; + } + // dynamical casting to pointers, null if not possible + const auto* pf_jet = dynamic_cast(&jet); + const auto* pat_jet = dynamic_cast(&jet); + edm::RefToBase jet_ref(jets, jet_n); + const auto& unsubJet = + (use_unsubjet_map_ && (*unsubjet_map)[jet_ref].isNonnull()) ? *(*unsubjet_map)[jet_ref] : jet; + + if (features.is_filled) { + math::XYZVector jet_dir = jet.momentum().Unit(); + GlobalVector jet_ref_track_dir(jet.px(), jet.py(), jet.pz()); + + // copy which will be sorted + auto svs_sorted = *svs; + // sort by dxy + std::sort(svs_sorted.begin(), svs_sorted.end(), [&pv](const auto& sva, const auto& svb) { + return btagbtvdeep::sv_vertex_comparator(sva, svb, pv); + }); + // fill features from secondary vertices + for (const auto& sv : svs_sorted) { + if (reco::deltaR2(sv, jet_dir) > (jet_radius_ * jet_radius_)) + continue; + else { + features.sv_features.emplace_back(); + // in C++17 could just get from emplace_back output + auto& sv_features = features.sv_features.back(); + btagbtvdeep::svToFeatures(sv, pv, jet, sv_features, flip_); + } + } + + // stuff required for dealing with pf candidates and lost tracks + std::vector> c_sorted, n_sorted, lt_sorted; + // to cache the TrackInfo + std::map trackinfos; + std::map lt_trackinfos; + // unsorted reference to sv + const auto& svs_unsorted = *svs; + std::vector ltPtrs; + static constexpr size_t max_lt_ = 5; + + //Adding the lost tracks associated with the jets + for (size_t i = 0; i < LTs->size(); ++i) { + auto cand = LTs->ptrAt(i); + if ((reco::deltaR(*cand, jet) < 0.2)) { + const auto* PackedCandidate_ = dynamic_cast(&(*cand)); + if (PackedCandidate_) { + if (PackedCandidate_->pt() < 1.0) + continue; + auto& trackinfo = lt_trackinfos.emplace(i, track_builder).first->second; + trackinfo.buildTrackInfo(PackedCandidate_, jet_dir, jet_ref_track_dir, pv); + + lt_sorted.emplace_back(i, + trackinfo.getTrackSip2dSig(), + -btagbtvdeep::mindrsvpfcand(svs_unsorted, PackedCandidate_), + PackedCandidate_->pt() / jet.pt()); + + ltPtrs.push_back(cand); + } + } + } + + // sort lt collection + std::sort(lt_sorted.begin(), lt_sorted.end(), btagbtvdeep::SortingClass::compareByABCInv); + int n_ltcand_ = std::min(lt_sorted.size(), max_lt_); + + std::vector lt_sortedindices; + lt_sortedindices = btagbtvdeep::invertSortingVector(lt_sorted); + + // set right size to vectors + features.lt_features.clear(); + features.lt_features.resize(lt_sorted.size()); + + for (unsigned int i = 0; i < (unsigned int)n_ltcand_; i++) { + //auto cand = LTs->ptrAt(i); + //const auto *PackedCandidate_ = dynamic_cast(&(*cand)); + const auto* PackedCandidate_ = dynamic_cast(&(*ltPtrs.at(i))); + if (!PackedCandidate_) + continue; + if (PackedCandidate_->pt() < min_candidate_pt_) + continue; + + if (PackedCandidate_->charge() != 0) { + //auto reco_cand = dynamic_cast(cand); + float puppiw = PackedCandidate_->puppiWeight(); + + float drminpfcandsv = btagbtvdeep::mindrsvpfcand(svs_unsorted, PackedCandidate_); + float distminpfcandsv = 0; + + size_t entry = lt_sortedindices.at(i); + // get cached track info + auto& trackinfo = lt_trackinfos.emplace(i, track_builder).first->second; + trackinfo.buildTrackInfo(PackedCandidate_, jet_dir, jet_ref_track_dir, pv); + // get_ref to vector element + auto& lt_features = features.lt_features.at(entry); + + if (PackedCandidate_) { + if (PackedCandidate_->hasTrackDetails()) { + const reco::Track& PseudoTrack = PackedCandidate_->pseudoTrack(); + reco::TransientTrack transientTrack; + transientTrack = track_builder->build(PseudoTrack); + distminpfcandsv = btagbtvdeep::mindistsvpfcand(svs_unsorted, transientTrack); + } + + btagbtvdeep::packedCandidateToFeatures(PackedCandidate_, + jet, + trackinfo, + is_weighted_jet_, + drminpfcandsv, + static_cast(jet_radius_), + puppiw, + lt_features, + flip_, + distminpfcandsv); + } + } + } + + // fill collection, from DeepTNtuples plus some styling + for (unsigned int i = 0; i < unsubJet.numberOfDaughters(); i++) { + auto cand = unsubJet.daughter(i); + if (cand) { + // candidates under 100MeV (configurable) are not considered + // might change if we use also white-listing + if (cand->pt() < min_candidate_pt_) + continue; + if (cand->charge() != 0) { + auto& trackinfo = trackinfos.emplace(i, track_builder).first->second; + trackinfo.buildTrackInfo(cand, jet_dir, jet_ref_track_dir, pv); + + c_sorted.emplace_back(i, + trackinfo.getTrackSip2dSig(), + -btagbtvdeep::mindrsvpfcand(svs_unsorted, cand), + cand->pt() / jet.pt()); + } else { + n_sorted.emplace_back(i, -1, -btagbtvdeep::mindrsvpfcand(svs_unsorted, cand), cand->pt() / jet.pt()); + } + } + } + + // sort collections (open the black-box if you please) + std::sort(c_sorted.begin(), c_sorted.end(), btagbtvdeep::SortingClass::compareByABCInv); + std::sort(n_sorted.begin(), n_sorted.end(), btagbtvdeep::SortingClass::compareByABCInv); + + std::vector c_sortedindices, n_sortedindices; + + // this puts 0 everywhere and the right position in ind + c_sortedindices = btagbtvdeep::invertSortingVector(c_sorted); + n_sortedindices = btagbtvdeep::invertSortingVector(n_sorted); + + // set right size to vectors + features.c_pf_features.clear(); + features.c_pf_features.resize(c_sorted.size()); + features.n_pf_features.clear(); + features.n_pf_features.resize(n_sorted.size()); + + for (unsigned int i = 0; i < unsubJet.numberOfDaughters(); i++) { + // get pointer and check that is correct + auto cand = dynamic_cast(unsubJet.daughter(i)); + if (!cand) + continue; + // candidates under 100MeV are not considered + // might change if we use also white-listing + if (cand->pt() < 0.100) + continue; + + auto packed_cand = dynamic_cast(cand); + auto reco_cand = dynamic_cast(cand); + + // need some edm::Ptr or edm::Ref if reco candidates + reco::PFCandidatePtr reco_ptr; + if (pf_jet) { + reco_ptr = pf_jet->getPFConstituent(i); + } else if (pat_jet && reco_cand) { + reco_ptr = pat_jet->getPFConstituent(i); + } + + reco::CandidatePtr cand_ptr; + if (pat_jet) { + cand_ptr = pat_jet->sourceCandidatePtr(i); + } + + // + // Access puppi weight from ValueMap. + // + float puppiw = 1.0; // Set to fallback value + + if (reco_cand) { + if (use_puppi_value_map_) + puppiw = (*puppi_value_map)[reco_ptr]; + else if (!fallback_puppi_weight_) { + throw edm::Exception(edm::errors::InvalidReference, "PUPPI value map missing") + << "use fallback_puppi_weight option to use " << puppiw << " for reco_cand as default"; + } + } else if (packed_cand) { + if (use_puppi_value_map_) + puppiw = (*puppi_value_map)[cand_ptr]; + else if (!fallback_puppi_weight_) { + throw edm::Exception(edm::errors::InvalidReference, "PUPPI value map missing") + << "use fallback_puppi_weight option to use " << puppiw << " for packed_cand as default"; + } + } else { + throw edm::Exception(edm::errors::InvalidReference) + << "Cannot convert to either reco::PFCandidate or pat::PackedCandidate"; + } + + float drminpfcandsv = btagbtvdeep::mindrsvpfcand(svs_unsorted, cand); + float distminpfcandsv = 0; + if (cand->charge() != 0) { + // is charged candidate + auto entry = c_sortedindices.at(i); + + // get cached track info + auto& trackinfo = trackinfos.at(i); + + // get_ref to vector element + auto& c_pf_features = features.c_pf_features.at(entry); + // fill feature structure + if (packed_cand) { + if (packed_cand->hasTrackDetails()) { + const reco::Track& PseudoTrack = packed_cand->pseudoTrack(); + reco::TransientTrack transientTrack; + transientTrack = track_builder->build(PseudoTrack); + distminpfcandsv = btagbtvdeep::mindistsvpfcand(svs_unsorted, transientTrack); + } + + btagbtvdeep::packedCandidateToFeatures(packed_cand, + jet, + trackinfo, + is_weighted_jet_, + drminpfcandsv, + static_cast(jet_radius_), + puppiw, + c_pf_features, + flip_, + distminpfcandsv); + } else if (reco_cand) { + // get vertex association quality + int pv_ass_quality = 0; // fallback value + if (use_pvasq_value_map_) { + pv_ass_quality = (*pvasq_value_map)[reco_ptr]; + } else if (!fallback_vertex_association_) { + throw edm::Exception(edm::errors::InvalidReference, "vertex association missing") + << "use fallback_vertex_association option to use" << pv_ass_quality + << "as default quality and closest dz PV as criteria"; + } + // getting the PV as PackedCandidatesProducer + // but using not the slimmed but original vertices + auto ctrack = reco_cand->bestTrack(); + int pvi = -1; + float dist = 1e99; + for (size_t ii = 0; ii < vtxs->size(); ii++) { + float dz = (ctrack) ? std::abs(ctrack->dz(((*vtxs)[ii]).position())) : 0; + if (dz < dist) { + pvi = ii; + dist = dz; + } + } + auto PV = reco::VertexRef(vtxs, pvi); + if (use_pvasq_value_map_) { + const reco::VertexRef& PV_orig = (*pvas)[reco_ptr]; + if (PV_orig.isNonnull()) + PV = reco::VertexRef(vtxs, PV_orig.key()); + } + btagbtvdeep::recoCandidateToFeatures(reco_cand, + jet, + trackinfo, + is_weighted_jet_, + drminpfcandsv, + static_cast(jet_radius_), + puppiw, + pv_ass_quality, + PV, + c_pf_features, + flip_, + distminpfcandsv); + } + } else { + // is neutral candidate + auto entry = n_sortedindices.at(i); + // get_ref to vector element + auto& n_pf_features = features.n_pf_features.at(entry); + // fill feature structure + if (packed_cand) { + btagbtvdeep::packedCandidateToFeatures(packed_cand, + jet, + is_weighted_jet_, + drminpfcandsv, + static_cast(jet_radius_), + puppiw, + n_pf_features); + } else if (reco_cand) { + btagbtvdeep::recoCandidateToFeatures( + reco_cand, jet, is_weighted_jet_, drminpfcandsv, static_cast(jet_radius_), puppiw, n_pf_features); + } + } + } + } + output_tag_infos->emplace_back(features, jet_ref); + } + iEvent.put(std::move(output_tag_infos)); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(UnifiedParticleTransformerAK4TagInfoProducer); diff --git a/RecoBTag/FeatureTools/src/ChargedCandidateConverter.cc b/RecoBTag/FeatureTools/src/ChargedCandidateConverter.cc index 5209c7d2818c4..a5661a61a8739 100644 --- a/RecoBTag/FeatureTools/src/ChargedCandidateConverter.cc +++ b/RecoBTag/FeatureTools/src/ChargedCandidateConverter.cc @@ -18,6 +18,13 @@ namespace btagbtvdeep { c_pf_features.vtx_ass = c_pf->pvAssociationQuality(); c_pf_features.puppiw = puppiw; + c_pf_features.charge = c_pf->charge(); + + c_pf_features.CaloFrac = c_pf->caloFraction(); + c_pf_features.HadFrac = c_pf->hcalFraction(); + c_pf_features.lostInnerHits = catch_infs(c_pf->lostInnerHits(), 2); + c_pf_features.numberOfPixelHits = catch_infs(c_pf->numberOfPixelHits(), -1); + c_pf_features.numberOfStripHits = catch_infs(c_pf->stripLayersWithMeasurement(), -1); // if PackedCandidate does not have TrackDetails this gives an Exception // because unpackCovariance might be called for pseudoTrack/bestTrack @@ -36,6 +43,27 @@ namespace btagbtvdeep { c_pf_features.dz = catch_infs(c_pf->dz()); c_pf_features.dxysig = c_pf->bestTrack() ? catch_infs(c_pf->dxy() / c_pf->dxyError()) : 0; c_pf_features.dzsig = c_pf->bestTrack() ? catch_infs(c_pf->dz() / c_pf->dzError()) : 0; + + float pdgid_; + if (abs(c_pf->pdgId()) == 11 and c_pf->charge() != 0) { + pdgid_ = 0.0; + } else if (abs(c_pf->pdgId()) == 13 and c_pf->charge() != 0) { + pdgid_ = 1.0; + } else if (abs(c_pf->pdgId()) == 22 and c_pf->charge() == 0) { + pdgid_ = 2.0; + } else if (abs(c_pf->pdgId()) != 22 and c_pf->charge() == 0 and abs(c_pf->pdgId()) != 1 and + abs(c_pf->pdgId()) != 2) { + pdgid_ = 3.0; + } else if (abs(c_pf->pdgId()) != 11 and abs(c_pf->pdgId()) != 13 and c_pf->charge() != 0) { + pdgid_ = 4.0; + } else if (c_pf->charge() == 0 and abs(c_pf->pdgId()) == 1) { + pdgid_ = 5.0; + } else if (c_pf->charge() == 0 and abs(c_pf->pdgId()) == 2) { + pdgid_ = 6.0; + } else { + pdgid_ = 7.0; + } + c_pf_features.pdgID = pdgid_; } void recoCandidateToFeatures(const reco::PFCandidate* c_pf, diff --git a/RecoBTag/FeatureTools/src/LostTracksConverter.cc b/RecoBTag/FeatureTools/src/LostTracksConverter.cc new file mode 100644 index 0000000000000..11fc316039c90 --- /dev/null +++ b/RecoBTag/FeatureTools/src/LostTracksConverter.cc @@ -0,0 +1,60 @@ +#include "RecoBTag/FeatureTools/interface/LostTracksConverter.h" + +namespace btagbtvdeep { + + void packedCandidateToFeatures(const pat::PackedCandidate* c_pf, + const pat::Jet& jet, + const TrackInfoBuilder& track_info, + const bool isWeightedJet, + const float drminpfcandsv, + const float jetR, + const float puppiw, + LostTracksFeatures& lt_features, + const bool flip, + const float distminpfcandsv) { + commonCandidateToFeatures( + c_pf, jet, track_info, isWeightedJet, drminpfcandsv, jetR, puppiw, lt_features, flip, distminpfcandsv); + + lt_features.puppiw = puppiw; + lt_features.charge = c_pf->charge(); + + lt_features.lostInnerHits = catch_infs(c_pf->lostInnerHits(), 2); + lt_features.numberOfPixelHits = catch_infs(c_pf->numberOfPixelHits(), -1); + lt_features.numberOfStripHits = catch_infs(c_pf->stripLayersWithMeasurement(), -1); + + // if PackedCandidate does not have TrackDetails this gives an Exception + // because unpackCovariance might be called for pseudoTrack/bestTrack + if (c_pf->hasTrackDetails()) { + const auto& pseudo_track = c_pf->pseudoTrack(); + lt_features.chi2 = catch_infs_and_bound(pseudo_track.normalizedChi2(), 300, -1, 300); + // this returns the quality enum not a mask. + lt_features.quality = pseudo_track.qualityMask(); + } else { + // default negative chi2 and loose track if notTrackDetails + lt_features.chi2 = catch_infs_and_bound(-1, 300, -1, 300); + lt_features.quality = (1 << reco::TrackBase::loose); + } + } + void recoCandidateToFeatures(const reco::PFCandidate* c_pf, + const reco::Jet& jet, + const TrackInfoBuilder& track_info, + const bool isWeightedJet, + const float drminpfcandsv, + const float jetR, + const float puppiw, + const int pv_ass_quality, + const reco::VertexRef& pv, + LostTracksFeatures& lt_features, + const bool flip, + const float distminpfcandsv) { + commonCandidateToFeatures( + c_pf, jet, track_info, isWeightedJet, drminpfcandsv, jetR, puppiw, lt_features, flip, distminpfcandsv); + + lt_features.puppiw = puppiw; + + const auto& pseudo_track = (c_pf->bestTrack()) ? *c_pf->bestTrack() : reco::Track(); + lt_features.chi2 = catch_infs_and_bound(std::floor(pseudo_track.normalizedChi2()), 300, -1, 300); + lt_features.quality = quality_from_pfcand(*c_pf); + } + +} // namespace btagbtvdeep diff --git a/RecoBTag/FeatureTools/src/TrackInfoBuilder.cc b/RecoBTag/FeatureTools/src/TrackInfoBuilder.cc index 57753af18595f..f75e4ef20b2e6 100644 --- a/RecoBTag/FeatureTools/src/TrackInfoBuilder.cc +++ b/RecoBTag/FeatureTools/src/TrackInfoBuilder.cc @@ -27,7 +27,8 @@ namespace btagbtvdeep { trackSip3dVal_(0), trackSip3dSig_(0), trackJetDistVal_(0), - trackJetDistSig_(0) {} + trackJetDistSig_(0), + trackJetDecayLen_(0) {} void TrackInfoBuilder::buildTrackInfo(const reco::Candidate *candidate, const math::XYZVector &jetDir, @@ -63,6 +64,7 @@ namespace btagbtvdeep { trackSip3dSig_ = 0.; trackJetDistVal_ = 0.; trackJetDistSig_ = 0.; + trackJetDecayLen_ = 0.; return; } @@ -84,12 +86,15 @@ namespace btagbtvdeep { Measurement1D meas_ip2d = IPTools::signedTransverseImpactParameter(transientTrack, refjetdirection, pv).second; Measurement1D meas_ip3d = IPTools::signedImpactParameter3D(transientTrack, refjetdirection, pv).second; Measurement1D jetdist = IPTools::jetTrackDistance(transientTrack, refjetdirection, pv).second; + Measurement1D decayl = IPTools::signedDecayLength3D(transientTrack, refjetdirection, pv).second; trackSip2dVal_ = static_cast(meas_ip2d.value()); trackSip2dSig_ = static_cast(meas_ip2d.significance()); trackSip3dVal_ = static_cast(meas_ip3d.value()); trackSip3dSig_ = static_cast(meas_ip3d.significance()); trackJetDistVal_ = static_cast(jetdist.value()); trackJetDistSig_ = static_cast(jetdist.significance()); + + trackJetDecayLen_ = static_cast(decayl.value()); } } // namespace btagbtvdeep diff --git a/RecoBTag/ONNXRuntime/plugins/UnifiedParticleTransformerAK4ONNXJetTagsProducer.cc b/RecoBTag/ONNXRuntime/plugins/UnifiedParticleTransformerAK4ONNXJetTagsProducer.cc new file mode 100644 index 0000000000000..a6864da0c3de5 --- /dev/null +++ b/RecoBTag/ONNXRuntime/plugins/UnifiedParticleTransformerAK4ONNXJetTagsProducer.cc @@ -0,0 +1,358 @@ +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/Framework/interface/makeRefToBaseProdFrom.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" + +#include "DataFormats/BTauReco/interface/JetTag.h" + +#include "DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4TagInfo.h" +#include "DataFormats/BTauReco/interface/UnifiedParticleTransformerAK4Features.h" + +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" + +using namespace cms::Ort; + +class UnifiedParticleTransformerAK4ONNXJetTagsProducer : public edm::stream::EDProducer> { +public: + explicit UnifiedParticleTransformerAK4ONNXJetTagsProducer(const edm::ParameterSet&, const ONNXRuntime*); + ~UnifiedParticleTransformerAK4ONNXJetTagsProducer() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + + static std::unique_ptr initializeGlobalCache(const edm::ParameterSet&); + static void globalEndJob(const ONNXRuntime*); + +private: + typedef std::vector TagInfoCollection; + typedef reco::JetTagCollection JetTagCollection; + + void produce(edm::Event&, const edm::EventSetup&) override; + + void make_inputs(btagbtvdeep::UnifiedParticleTransformerAK4Features features); + void get_input_sizes(const reco::FeaturesTagInfo taginfo); + + const edm::EDGetTokenT src_; + std::vector flav_names_; + std::vector input_names_; + std::vector output_names_; + + enum InputIndexes { + kChargedCandidates = 0, + kLostTracks = 1, + kNeutralCandidates = 2, + kVertices = 3, + kChargedCandidates4Vec = 4, + kLostTracks4Vec = 5, + kNeutralCandidates4Vec = 6, + kVertices4Vec = 7 + }; + unsigned n_cpf_; + constexpr static unsigned n_features_cpf_ = 25; + constexpr static unsigned n_pairwise_features_cpf_ = 4; + unsigned n_lt_; + constexpr static unsigned n_features_lt_ = 18; + constexpr static unsigned n_pairwise_features_lt_ = 4; + unsigned n_npf_; + constexpr static unsigned n_features_npf_ = 8; + constexpr static unsigned n_pairwise_features_npf_ = 4; + unsigned n_sv_; + constexpr static unsigned n_features_sv_ = 14; + constexpr static unsigned n_pairwise_features_sv_ = 4; + std::vector input_sizes_; + std::vector> input_shapes_; // shapes of each input group (-1 for dynamic axis) + + // hold the input data + FloatArrays data_; +}; + +UnifiedParticleTransformerAK4ONNXJetTagsProducer::UnifiedParticleTransformerAK4ONNXJetTagsProducer( + const edm::ParameterSet& iConfig, const ONNXRuntime* cache) + : src_(consumes(iConfig.getParameter("src"))), + flav_names_(iConfig.getParameter>("flav_names")), + input_names_(iConfig.getParameter>("input_names")), + output_names_(iConfig.getParameter>("output_names")) { + // get output names from flav_names + for (const auto& flav_name : flav_names_) { + produces(flav_name); + } +} + +void UnifiedParticleTransformerAK4ONNXJetTagsProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + // pfUnifiedParticleTransformerAK4JetTags + edm::ParameterSetDescription desc; + desc.add("src", edm::InputTag("pfUnifiedParticleTransformerAK4TagInfos")); + desc.add>( + "input_names", {"input_1", "input_2", "input_3", "input_4", "input_5", "input_6", "input_7", "input_8"}); + desc.add("model_path", edm::FileInPath("RecoBTag/Combined/data/UParTAK4/PUPPI/V00/UParTAK4.onnx")); + desc.add>("output_names", {"softmax"}); + desc.add>( + "flav_names", + std::vector{"probb", "probbb", "problepb", "probc", "probs", + "probu", "probd", "probg", "probele", "probmu", + "probtaup1h0p", "probtaup1h1p", "probtaup1h2p", "probtaup3h0p", "probtaup3h1p", + "probtaum1h0p", "probtaum1h1p", "probtaum1h2p", "probtaum3h0p", "probtaum3h1p", + "ptcorr", "ptreshigh", "ptreslow", "ptnu", "probemudata", + "probemumc", "probdimudata", "probdimumc", "probmutaudata", "probmutaumc"}); + + descriptions.add("pfUnifiedParticleTransformerAK4JetTags", desc); +} + +std::unique_ptr UnifiedParticleTransformerAK4ONNXJetTagsProducer::initializeGlobalCache( + const edm::ParameterSet& iConfig) { + return std::make_unique(iConfig.getParameter("model_path").fullPath()); +} + +void UnifiedParticleTransformerAK4ONNXJetTagsProducer::globalEndJob(const ONNXRuntime* cache) {} + +void UnifiedParticleTransformerAK4ONNXJetTagsProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + edm::Handle tag_infos; + iEvent.getByToken(src_, tag_infos); + + // initialize output collection + std::vector> output_tags; + if (!tag_infos->empty()) { + auto jet_ref = tag_infos->begin()->jet(); + auto ref2prod = edm::makeRefToBaseProdFrom(jet_ref, iEvent); + for (std::size_t i = 0; i < flav_names_.size(); i++) { + output_tags.emplace_back(std::make_unique(ref2prod)); + } + } else { + for (std::size_t i = 0; i < flav_names_.size(); i++) { + output_tags.emplace_back(std::make_unique()); + } + } + + for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) { + const auto& taginfo = (*tag_infos)[jet_n]; + std::vector outputs(flav_names_.size(), -1.0); + if (taginfo.features().is_filled) { + get_input_sizes(taginfo); + + // run prediction with dynamic batch size per event + input_shapes_ = {{(int64_t)1, (int64_t)n_cpf_, (int64_t)n_features_cpf_}, + {(int64_t)1, (int64_t)n_lt_, (int64_t)n_features_lt_}, + {(int64_t)1, (int64_t)n_npf_, (int64_t)n_features_npf_}, + {(int64_t)1, (int64_t)n_sv_, (int64_t)n_features_sv_}, + {(int64_t)1, (int64_t)n_cpf_, (int64_t)n_pairwise_features_cpf_}, + {(int64_t)1, (int64_t)n_lt_, (int64_t)n_pairwise_features_lt_}, + {(int64_t)1, (int64_t)n_npf_, (int64_t)n_pairwise_features_npf_}, + {(int64_t)1, (int64_t)n_sv_, (int64_t)n_pairwise_features_sv_}}; + + outputs = globalCache()->run(input_names_, data_, input_shapes_, output_names_, 1)[0]; + assert(outputs.size() == flav_names_.size()); + } + + const auto& jet_ref = tag_infos->at(jet_n).jet(); + for (std::size_t flav_n = 0; flav_n < flav_names_.size(); flav_n++) { + (*(output_tags[flav_n]))[jet_ref] = outputs[flav_n]; + } + } + + // put into the event + for (std::size_t flav_n = 0; flav_n < flav_names_.size(); ++flav_n) { + iEvent.put(std::move(output_tags[flav_n]), flav_names_[flav_n]); + } +} + +void UnifiedParticleTransformerAK4ONNXJetTagsProducer::get_input_sizes( + const reco::FeaturesTagInfo taginfo) { + const auto& features = taginfo.features(); + + /// We require a fixed size due to an ONNX conversion issue (to be improved in the future ?) /// + n_cpf_ = (unsigned int)29; + n_lt_ = (unsigned int)5; + n_npf_ = (unsigned int)25; + n_sv_ = (unsigned int)5; + + input_sizes_ = { + n_cpf_ * n_features_cpf_, + n_lt_ * n_features_lt_, + n_npf_ * n_features_npf_, + n_sv_ * n_features_sv_, + n_cpf_ * n_pairwise_features_cpf_, + n_lt_ * n_pairwise_features_lt_, + n_npf_ * n_pairwise_features_npf_, + n_sv_ * n_pairwise_features_sv_, + }; + // init data storage + data_.clear(); + for (const auto& len : input_sizes_) { + data_.emplace_back(1 * len, 0); + } + + make_inputs(features); +} + +void UnifiedParticleTransformerAK4ONNXJetTagsProducer::make_inputs( + btagbtvdeep::UnifiedParticleTransformerAK4Features features) { + float* ptr = nullptr; + const float* start = nullptr; + unsigned offset = 0; + + // c_pf candidates + auto max_c_pf_n = std::min(features.c_pf_features.size(), (std::size_t)n_cpf_); + for (std::size_t c_pf_n = 0; c_pf_n < max_c_pf_n; c_pf_n++) { + const auto& c_pf_features = features.c_pf_features.at(c_pf_n); + ptr = &data_[kChargedCandidates][offset + c_pf_n * n_features_cpf_]; + start = ptr; + *ptr = c_pf_features.btagPf_trackEtaRel; + *(++ptr) = c_pf_features.btagPf_trackPtRel; + *(++ptr) = c_pf_features.btagPf_trackPPar; + *(++ptr) = c_pf_features.btagPf_trackDeltaR; + *(++ptr) = c_pf_features.btagPf_trackPParRatio; + *(++ptr) = c_pf_features.btagPf_trackSip2dVal; + *(++ptr) = c_pf_features.btagPf_trackSip2dSig; + *(++ptr) = c_pf_features.btagPf_trackSip3dVal; + *(++ptr) = c_pf_features.btagPf_trackSip3dSig; + *(++ptr) = c_pf_features.btagPf_trackJetDistVal; + *(++ptr) = c_pf_features.ptrel; + *(++ptr) = c_pf_features.drminsv; + *(++ptr) = c_pf_features.vtx_ass; + *(++ptr) = c_pf_features.puppiw; + *(++ptr) = c_pf_features.chi2; + *(++ptr) = c_pf_features.quality; + *(++ptr) = c_pf_features.charge; + *(++ptr) = c_pf_features.dz; + *(++ptr) = c_pf_features.btagPf_trackDecayLen; + *(++ptr) = c_pf_features.HadFrac; + *(++ptr) = c_pf_features.CaloFrac; + *(++ptr) = c_pf_features.pdgID; + *(++ptr) = c_pf_features.lostInnerHits; + *(++ptr) = c_pf_features.numberOfPixelHits; + *(++ptr) = c_pf_features.numberOfStripHits; + + assert(start + n_features_cpf_ - 1 == ptr); + } + + // n_lt candidates + auto max_lt_n = std::min(features.lt_features.size(), (std::size_t)n_lt_); + for (std::size_t lt_n = 0; lt_n < max_lt_n; lt_n++) { + const auto& lt_features = features.lt_features.at(lt_n); + ptr = &data_[kLostTracks][offset + lt_n * n_features_lt_]; + start = ptr; + *ptr = lt_features.btagPf_trackEtaRel; + *(++ptr) = lt_features.btagPf_trackPtRel; + *(++ptr) = lt_features.btagPf_trackPPar; + *(++ptr) = lt_features.btagPf_trackDeltaR; + *(++ptr) = lt_features.btagPf_trackPParRatio; + *(++ptr) = lt_features.btagPf_trackSip2dVal; + *(++ptr) = lt_features.btagPf_trackSip2dSig; + *(++ptr) = lt_features.btagPf_trackSip3dVal; + *(++ptr) = lt_features.btagPf_trackSip3dSig; + *(++ptr) = lt_features.btagPf_trackJetDistVal; + *(++ptr) = lt_features.drminsv; + *(++ptr) = lt_features.charge; + *(++ptr) = lt_features.puppiw; + *(++ptr) = lt_features.chi2; + *(++ptr) = lt_features.quality; + *(++ptr) = lt_features.lostInnerHits; + *(++ptr) = lt_features.numberOfPixelHits; + *(++ptr) = lt_features.numberOfStripHits; + assert(start + n_features_lt_ - 1 == ptr); + } + + // n_pf candidates + auto max_n_pf_n = std::min(features.n_pf_features.size(), (std::size_t)n_npf_); + for (std::size_t n_pf_n = 0; n_pf_n < max_n_pf_n; n_pf_n++) { + const auto& n_pf_features = features.n_pf_features.at(n_pf_n); + ptr = &data_[kNeutralCandidates][offset + n_pf_n * n_features_npf_]; + start = ptr; + *ptr = n_pf_features.ptrel; + *(++ptr) = n_pf_features.etarel; + *(++ptr) = n_pf_features.phirel; + *(++ptr) = n_pf_features.deltaR; + *(++ptr) = n_pf_features.isGamma; + *(++ptr) = n_pf_features.hadFrac; + *(++ptr) = n_pf_features.drminsv; + *(++ptr) = n_pf_features.puppiw; + assert(start + n_features_npf_ - 1 == ptr); + } + + // sv candidates + auto max_sv_n = std::min(features.sv_features.size(), (std::size_t)n_sv_); + for (std::size_t sv_n = 0; sv_n < max_sv_n; sv_n++) { + const auto& sv_features = features.sv_features.at(sv_n); + ptr = &data_[kVertices][offset + sv_n * n_features_sv_]; + start = ptr; + *ptr = sv_features.pt; + *(++ptr) = sv_features.deltaR; + *(++ptr) = sv_features.mass; + *(++ptr) = sv_features.etarel; + *(++ptr) = sv_features.phirel; + *(++ptr) = sv_features.ntracks; + *(++ptr) = sv_features.chi2; + *(++ptr) = sv_features.normchi2; + *(++ptr) = sv_features.dxy; + *(++ptr) = sv_features.dxysig; + *(++ptr) = sv_features.d3d; + *(++ptr) = sv_features.d3dsig; + *(++ptr) = sv_features.costhetasvpv; + *(++ptr) = sv_features.enratio; + assert(start + n_features_sv_ - 1 == ptr); + } + + // cpf pairwise features (4-vectors) + auto max_cpf_n = std::min(features.c_pf_features.size(), (std::size_t)n_cpf_); + for (std::size_t cpf_n = 0; cpf_n < max_cpf_n; cpf_n++) { + const auto& cpf_pairwise_features = features.c_pf_features.at(cpf_n); + ptr = &data_[kChargedCandidates4Vec][offset + cpf_n * n_pairwise_features_cpf_]; + start = ptr; + *ptr = cpf_pairwise_features.px; + *(++ptr) = cpf_pairwise_features.py; + *(++ptr) = cpf_pairwise_features.pz; + *(++ptr) = cpf_pairwise_features.e; + + assert(start + n_pairwise_features_cpf_ - 1 == ptr); + } + + // lt pairwise features (4-vectors) specific case requiring (pt,eta,phi,e) + auto max_lt_N = std::min(features.lt_features.size(), (std::size_t)n_lt_); + for (std::size_t lt_N = 0; lt_N < max_lt_N; lt_N++) { + const auto& lt_pairwise_features = features.lt_features.at(lt_N); + ptr = &data_[kLostTracks4Vec][offset + lt_N * n_pairwise_features_lt_]; + start = ptr; + *ptr = lt_pairwise_features.pt; + *(++ptr) = lt_pairwise_features.eta; + *(++ptr) = lt_pairwise_features.phi; + *(++ptr) = lt_pairwise_features.e; + + assert(start + n_pairwise_features_lt_ - 1 == ptr); + } + + // npf pairwise features (4-vectors) + auto max_npf_n = std::min(features.n_pf_features.size(), (std::size_t)n_npf_); + for (std::size_t npf_n = 0; npf_n < max_npf_n; npf_n++) { + const auto& npf_pairwise_features = features.n_pf_features.at(npf_n); + ptr = &data_[kNeutralCandidates4Vec][offset + npf_n * n_pairwise_features_npf_]; + start = ptr; + *ptr = npf_pairwise_features.px; + *(++ptr) = npf_pairwise_features.py; + *(++ptr) = npf_pairwise_features.pz; + *(++ptr) = npf_pairwise_features.e; + + assert(start + n_pairwise_features_npf_ - 1 == ptr); + } + + // sv pairwise features (4-vectors) + auto max_sv_N = std::min(features.sv_features.size(), (std::size_t)n_sv_); + for (std::size_t sv_N = 0; sv_N < max_sv_N; sv_N++) { + const auto& sv_pairwise_features = features.sv_features.at(sv_N); + ptr = &data_[kVertices4Vec][offset + sv_N * n_pairwise_features_sv_]; + start = ptr; + *ptr = sv_pairwise_features.px; + *(++ptr) = sv_pairwise_features.py; + *(++ptr) = sv_pairwise_features.pz; + *(++ptr) = sv_pairwise_features.e; + + assert(start + n_pairwise_features_sv_ - 1 == ptr); + } +} + +//define this as a plug-in +DEFINE_FWK_MODULE(UnifiedParticleTransformerAK4ONNXJetTagsProducer); diff --git a/RecoBTag/ONNXRuntime/python/pfHiggsInteractionNet_cff.py b/RecoBTag/ONNXRuntime/python/pfHiggsInteractionNet_cff.py index 85387335873f6..42df6dfb331fd 100644 --- a/RecoBTag/ONNXRuntime/python/pfHiggsInteractionNet_cff.py +++ b/RecoBTag/ONNXRuntime/python/pfHiggsInteractionNet_cff.py @@ -17,7 +17,7 @@ pfHiggsInteractionNetTags = boostedJetONNXJetTagsProducer.clone( src = 'pfHiggsInteractionNetTagInfos', preprocessParams = pfHiggsInteractionNetPreprocessParams, - model_path = 'RecoBTag/Combined/data/HiggsInteractionNet/V00/IN.onnx', + model_path = 'RecoBTag/Combined/data/HiggsInteractionNet/V00/modelfile/model.onnx', flav_names = [ 'probQCD', 'probHbb' ] ) diff --git a/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py b/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py index 82356764f3818..cd308d139c9b2 100644 --- a/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py +++ b/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py @@ -41,28 +41,28 @@ pfParticleNetFromMiniAODAK4CHSCentralJetTags = boostedJetONNXJetTagsProducer.clone( src = 'pfParticleNetFromMiniAODAK4CHSCentralTagInfos', preprocess_json = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/CHS/Central/preprocess.json', - model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/CHS/Central/particle-net.onnx', + model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/CHS/Central/modelfile/model.onnx', flav_names = ['probmu','probele','probtaup1h0p','probtaup1h1p','probtaup1h2p','probtaup3h0p','probtaup3h1p','probtaum1h0p','probtaum1h1p','probtaum1h2p','probtaum3h0p','probtaum3h1p','probb','probc','probuds','probg','ptcorr','ptreshigh','ptreslow','ptnu'], ) pfParticleNetFromMiniAODAK4CHSForwardJetTags = boostedJetONNXJetTagsProducer.clone( src = 'pfParticleNetFromMiniAODAK4CHSForwardTagInfos', preprocess_json = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/CHS/Forward/preprocess.json', - model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/CHS/Forward/particle-net.onnx', + model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/CHS/Forward/modelfile/model.onnx', flav_names = ['probq','probg','ptcorr','ptreshigh','ptreslow','ptnu'], ) pfParticleNetFromMiniAODAK4PuppiCentralJetTags = boostedJetONNXJetTagsProducer.clone( src = 'pfParticleNetFromMiniAODAK4PuppiCentralTagInfos', preprocess_json = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/PUPPI/Central/preprocess.json', - model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/PUPPI/Central/particle-net.onnx', + model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/PUPPI/Central/modelfile/model.onnx', flav_names = ['probmu','probele','probtaup1h0p','probtaup1h1p','probtaup1h2p','probtaup3h0p','probtaup3h1p','probtaum1h0p','probtaum1h1p','probtaum1h2p','probtaum3h0p','probtaum3h1p','probb','probc','probuds','probg','ptcorr','ptreshigh','ptreslow','ptnu'], ) pfParticleNetFromMiniAODAK4PuppiForwardJetTags = boostedJetONNXJetTagsProducer.clone( src = 'pfParticleNetFromMiniAODAK4PuppiForwardTagInfos', preprocess_json = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/PUPPI/Forward/preprocess.json', - model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/PUPPI/Forward/particle-net.onnx', + model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK4/PUPPI/Forward/modelfile/model.onnx', flav_names = ['probq','probg','ptcorr','ptreshigh','ptreslow','ptnu'], ) diff --git a/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK8_cff.py b/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK8_cff.py index 2c9e3c62e4c94..80d4a79f93356 100644 --- a/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK8_cff.py +++ b/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK8_cff.py @@ -17,7 +17,7 @@ pfParticleNetFromMiniAODAK8JetTags = boostedJetONNXJetTagsProducer.clone( src = 'pfParticleNetFromMiniAODAK8TagInfos', preprocess_json = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK8/preprocess.json', - model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK8/particle-net.onnx', + model_path = 'RecoBTag/Combined/data/ParticleNetFromMiniAODAK8/modelfile/model.onnx', flav_names = ['probHtt','probHtm','probHte','probHbb', 'probHcc', 'probHqq', 'probHgg','probQCD2hf','probQCD1hf','probQCD0hf','masscorr'], ) diff --git a/RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4DiscriminatorsJetTags_cfi.py b/RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4DiscriminatorsJetTags_cfi.py new file mode 100644 index 0000000000000..28064787c6fc1 --- /dev/null +++ b/RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4DiscriminatorsJetTags_cfi.py @@ -0,0 +1,157 @@ +import FWCore.ParameterSet.Config as cms + +pfUnifiedParticleTransformerAK4DiscriminatorsJetTags = cms.EDProducer( + 'BTagProbabilityToDiscriminator', + discriminators = cms.VPSet( + cms.PSet( + name = cms.string('BvsAll'), + numerator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probbb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'problepb'), + ), + denominator=cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probbb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'problepb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probc'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probs'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probu'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probd'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probg'), + ), + ), + cms.PSet( + name = cms.string('CvsL'), + numerator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probc'), + ), + denominator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probc'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probs'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probu'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probd'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probg'), + ), + ), + cms.PSet( + name = cms.string('CvsB'), + numerator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probc'), + ), + denominator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probc'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probbb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'problepb'), + ), + ), + cms.PSet( + name = cms.string('QvsG'), + numerator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probs'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probu'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probd'), + ), + denominator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probs'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probu'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probd'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probg'), + ), + ), + cms.PSet( + name = cms.string('TauVsJet'), + numerator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h1p'), + ), + denominator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probbb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'problepb'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probc'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probs'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probu'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probd'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probg'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h1p'), + ), + ), + cms.PSet( + name = cms.string('TauVsEle'), + numerator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h1p'), + ), + denominator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probele'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h1p'), + ), + ), + + cms.PSet( + name = cms.string('TauVsMu'), + numerator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h1p'), + ), + denominator = cms.VInputTag( + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probmu'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaup3h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h1p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum1h2p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h0p'), + cms.InputTag('pfUnifiedParticleTransformerAK4JetTags', 'probtaum3h1p'), + ), + ), + + ) + ) diff --git a/RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4_cff.py b/RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4_cff.py new file mode 100644 index 0000000000000..aee089f50ef68 --- /dev/null +++ b/RecoBTag/ONNXRuntime/python/pfUnifiedParticleTransformerAK4_cff.py @@ -0,0 +1,29 @@ +import FWCore.ParameterSet.Config as cms + +from RecoBTag.FeatureTools.pfUnifiedParticleTransformerAK4TagInfos_cfi import pfUnifiedParticleTransformerAK4TagInfos + +from RecoBTag.ONNXRuntime.pfUnifiedParticleTransformerAK4JetTags_cfi import pfUnifiedParticleTransformerAK4JetTags +from RecoBTag.ONNXRuntime.pfUnifiedParticleTransformerAK4DiscriminatorsJetTags_cfi import pfUnifiedParticleTransformerAK4DiscriminatorsJetTags +from CommonTools.PileupAlgos.Puppi_cff import puppi +from CommonTools.RecoAlgos.primaryVertexAssociation_cfi import primaryVertexAssociation + +# declare all the discriminators +# probs +_pfUnifiedParticleTransformerAK4JetTagsProbs = ['pfUnifiedParticleTransformerAK4JetTags:' + flav_name + for flav_name in pfUnifiedParticleTransformerAK4JetTags.flav_names] +# meta-taggers +_pfUnifiedParticleTransformerAK4JetTagsMetaDiscrs = ['pfUnifiedParticleTransformerAK4DiscriminatorsJetTags:' + disc.name.value() + for disc in pfUnifiedParticleTransformerAK4DiscriminatorsJetTags.discriminators] +_pfUnifiedParticleTransformerAK4JetTagsAll = _pfUnifiedParticleTransformerAK4JetTagsProbs + _pfUnifiedParticleTransformerAK4JetTagsMetaDiscrs + + + +# == +# This task is not used, useful only if we run it from RECO jets (RECO/AOD) +pfUnifiedParticleTransformerAK4Task = cms.Task(puppi, primaryVertexAssociation, + pfUnifiedParticleTransformerAK4TagInfos, pfUnifiedParticleTransformerAK4JetTags, + pfUnifiedParticleTransformerAK4DiscriminatorsJetTags) +# run from MiniAOD instead +pfUnifiedParticleTransformerAK4FromMiniAODTask = cms.Task(pfUnifiedParticleTransformerAK4TagInfos, + pfUnifiedParticleTransformerAK4JetTags, + pfUnifiedParticleTransformerAK4DiscriminatorsJetTags) diff --git a/RecoBTag/ONNXRuntime/test/test_deep_flavour_cfg.py b/RecoBTag/ONNXRuntime/test/test_deep_flavour_cfg.py index 3a791fbcaadf7..6ed9615811014 100644 --- a/RecoBTag/ONNXRuntime/test/test_deep_flavour_cfg.py +++ b/RecoBTag/ONNXRuntime/test/test_deep_flavour_cfg.py @@ -71,7 +71,7 @@ from PhysicsTools.PatAlgos.patInputFiles_cff import filesRelValTTbarPileUpMINIAODSIM process.source.fileNames = filesRelValTTbarPileUpMINIAODSIM -process.source.fileNames = cms.untracked.vstring('/store/mc/PhaseIFall16MiniAOD/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PhaseIFall16PUFlat20to50_PhaseIFall16_81X_upgrade2017_realistic_v26-v1/50000/08358A47-61E3-E611-8B77-001E677928AE.root') +process.source.fileNames = cms.untracked.vstring('/store/mc/Run3Summer23BPixMiniAODv4/TTtoLNu2Q_TuneCP5_13p6TeV_powheg-pythia8/MINIAODSIM/130X_mcRun3_2023_realistic_postBPix_v2-v3/2520000/00488681-4f49-4bdc-89e6-198da9e42a17.root') process.maxEvents.input = 10 diff --git a/RecoBTag/ONNXRuntime/test/test_unifiedpartak4_cfg.py b/RecoBTag/ONNXRuntime/test/test_unifiedpartak4_cfg.py new file mode 100644 index 0000000000000..4330ad8d00bea --- /dev/null +++ b/RecoBTag/ONNXRuntime/test/test_unifiedpartak4_cfg.py @@ -0,0 +1,88 @@ + +import FWCore.ParameterSet.Config as cms +from PhysicsTools.PatAlgos.tools.helpers import getPatAlgosToolsTask + +process = cms.Process("PATtest") + +## MessageLogger +process.load("FWCore.MessageLogger.MessageLogger_cfi") + +## Options and Output Report +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(True) ) + +## Source +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring() +) +## Maximal Number of Events +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(1000)) + +## Geometry and Detector Conditions (needed for a few patTuple production steps) +process.load("Configuration.Geometry.GeometryRecoDB_cff") +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:run2_mc') +process.load("Configuration.StandardSequences.MagneticField_cff") + +## Output Module Configuration (expects a path 'p') +from PhysicsTools.PatAlgos.patEventContent_cff import patEventContentNoCleaning +process.out = cms.OutputModule("PoolOutputModule", + fileName = cms.untracked.string('patTuple.root'), + outputCommands = cms.untracked.vstring('drop *', *patEventContentNoCleaning ) + ) + +patAlgosToolsTask = getPatAlgosToolsTask(process) +process.outpath = cms.EndPath(process.out, patAlgosToolsTask) + +## and add them to the event content +from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection + +updateJetCollection( + process, + jetSource = cms.InputTag('slimmedJetsPuppi'), + pvSource = cms.InputTag('offlineSlimmedPrimaryVertices'), + svSource = cms.InputTag('slimmedSecondaryVertices'), + jetCorrections = ('AK4PFchs', cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute']), 'None'), + btagDiscriminators = [ + 'pfDeepFlavourJetTags:probb', + 'pfDeepFlavourJetTags:probbb', + 'pfDeepFlavourJetTags:problepb', + 'pfDeepFlavourJetTags:probc', + 'pfDeepFlavourJetTags:probuds', + 'pfDeepFlavourJetTags:probg', + 'pfUnifiedParticleTransformerAK4JetTags:probb', + 'pfUnifiedParticleTransformerAK4JetTags:probbb', + 'pfUnifiedParticleTransformerAK4JetTags:problepb', + 'pfUnifiedParticleTransformerAK4JetTags:probc', + 'pfUnifiedParticleTransformerAK4JetTags:probs', + 'pfUnifiedParticleTransformerAK4JetTags:probu', + 'pfUnifiedParticleTransformerAK4JetTags:probd', + 'pfUnifiedParticleTransformerAK4JetTags:probg', + 'pfParticleTransformerAK4JetTags:probb', + 'pfParticleTransformerAK4JetTags:probbb', + 'pfParticleTransformerAK4JetTags:problepb', + 'pfParticleTransformerAK4JetTags:probc', + 'pfParticleTransformerAK4JetTags:probuds', + 'pfParticleTransformerAK4JetTags:probg', + 'pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probb', + 'pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probc', + 'pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds', + 'pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probg', + ] + ) + +from PhysicsTools.PatAlgos.patInputFiles_cff import filesRelValTTbarPileUpMINIAODSIM + +process.source.fileNames = filesRelValTTbarPileUpMINIAODSIM +process.source.fileNames = cms.untracked.vstring('/store/mc/Run3Summer23BPixMiniAODv4/TTtoLNu2Q_TuneCP5_13p6TeV_powheg-pythia8/MINIAODSIM/130X_mcRun3_2023_realistic_postBPix_v2-v3/2520000/00488681-4f49-4bdc-89e6-198da9e42a17.root') + +process.maxEvents.input = 1000 + +from Configuration.EventContent.EventContent_cff import MINIAODSIMEventContent +process.out.outputCommands = MINIAODSIMEventContent.outputCommands +process.out.outputCommands.append('keep *_selectedUpdatedPatJets*_*_*') +process.out.outputCommands.append('keep *_pfDeepFlavourTagInfos*_*_*') +process.out.outputCommands.append('keep *_pfDeepFlavourJetTags*_*_*') +process.out.outputCommands.append('keep *_updatedPatJets*_*_*') + +process.out.fileName = 'test_deep_unifiedpartak4_MINIAODSIM.root'