diff --git a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/python/JetParticleAssociationAlgConfig.py b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/python/JetParticleAssociationAlgConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..4cca2d37fdd26951784f68e4c198575c4f1a4072 --- /dev/null +++ b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/python/JetParticleAssociationAlgConfig.py @@ -0,0 +1,40 @@ +# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + +JetParticleShrinkingConeAssociation=CompFactory.JetParticleShrinkingConeAssociation + +# this function is only used below +def JetParticleAssociationCfg(ConfigFlags, jetCollName, partcollname, assocname, **options): + + acc=ComponentAccumulator() + + options["coneSizeFitPar1"] = +0.239 + options["coneSizeFitPar2"] = -1.220 + options["coneSizeFitPar3"] = -1.64e-5 + options["InputParticleContainer"] = partcollname + options["OutputDecoration"] = assocname + + # -- create the association tool + acc.setPrivateTools(JetParticleShrinkingConeAssociation(JetContainer=jetCollName, **options)) + + return acc + +def JetParticleAssociationAlgCfg(ConfigFlags, JetCollection="", InputParticleCollection="", OutputParticleDecoration="", **options): + + + acc=ComponentAccumulator() + jetcol = JetCollection.replace("Track", "PV0Track") + + # setup the associator + if not jetcol.endswith('Jets'): + jetcol += 'Jets' + options['JetContainer'] = jetcol + options['Decorators'] = [acc.popToolsAndMerge(JetParticleAssociationCfg(ConfigFlags, jetcol, InputParticleCollection, OutputParticleDecoration))] + options['name'] = (jetcol + "_" + OutputParticleDecoration + "_assoc").lower() + + # -- create the association algorithm + acc.addEventAlgo(CompFactory.JetDecorationAlg(**options)) + + return acc diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/CMakeLists.txt b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/CMakeLists.txt index eb9f3bca1209c84405baf9376a9878fd6d3ce88d..9a66f5e702afb44961c2a7f5a9b309b2beebad51 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/CMakeLists.txt +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/CMakeLists.txt @@ -48,6 +48,7 @@ if (NOT XAOD_STANDALONE) src/JetToBTagLinkerAlg.cxx src/BTagTrackLinkCopyAlg.cxx src/BTaggingBuilderAlg.cxx + src/PoorMansIpAugmenterAlg.cxx src/components/FlavorTagDiscriminants_entries.cxx LINK_LIBRARIES FlavorTagDiscriminants ) diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/BTagTrackIpAccessor.h b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/BTagTrackIpAccessor.h index d93afc1a2c6e5247e20a466a4b9ac6dca355b453..519aad816fbd69ecaba1427c65e3bf017847e347 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/BTagTrackIpAccessor.h +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/BTagTrackIpAccessor.h @@ -28,7 +28,8 @@ struct BTagSignedIP { class BTagTrackIpAccessor { public: - BTagTrackIpAccessor(const std::string& prefix = "btagIp_" ); + // used to have "btagIp_" as a default argument + BTagTrackIpAccessor(const std::string& prefix); void augment(const xAOD::TrackParticle &track, const xAOD::Jet &jet); // NOTE: this should be called in the derivations if possible, diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2.h b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2.h index fc1478e772d5b3947ec1851709b8c9dcb6bb4dd3..a909a404f7582a42a825f0d8006b4f79caabd7f1 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2.h +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2.h @@ -37,26 +37,6 @@ namespace FlavorTagDiscriminants { enum class SortOrder { ABS_D0_SIGNIFICANCE_DESCENDING, D0_SIGNIFICANCE_DESCENDING, PT_DESCENDING}; enum class TrackSelection {ALL, IP3D_2018, DIPS_LOOSE_202102}; - enum class OutputType {FLOAT, DOUBLE}; - - // classes to deal with typedefs - // - template - struct EDMTypeEnum; - template <> struct EDMTypeEnum { - const static EDMType type = EDMType::FLOAT; - }; - template <> struct EDMTypeEnum { - const static EDMType type = EDMType::DOUBLE; - }; - template - struct OutputTypeEnum; - template<> struct OutputTypeEnum { - const static OutputType type = OutputType::FLOAT; - }; - template<> struct OutputTypeEnum { - const static OutputType type = OutputType::DOUBLE; - }; // Structures to define DL2 input. @@ -80,6 +60,16 @@ namespace FlavorTagDiscriminants { std::vector inputs; }; + // other DL2 options + struct DL2Options { + DL2Options(); + std::string track_prefix; + FlipTagConfig flip; + std::string track_link_name; + std::map remap_scalar; + }; + + // _____________________________________________________________________ // Internal code @@ -167,8 +157,7 @@ namespace FlavorTagDiscriminants { class TracksFromJet { public: - TracksFromJet(SortOrder, TrackSelection, - const std::string& track_link_name); + TracksFromJet(SortOrder, TrackSelection, const DL2Options&); Tracks operator()(const xAOD::Jet& jet, const xAOD::BTagging& btag) const; private: @@ -208,9 +197,7 @@ namespace FlavorTagDiscriminants { DL2(const lwt::GraphConfig&, const std::vector&, const std::vector& = {}, - FlipTagConfig = FlipTagConfig::STANDARD, - std::map remap = {}, - OutputType = OutputType::DOUBLE); + const DL2Options& = DL2Options()); void decorate(const xAOD::BTagging& btag) const; // functions to report data depdedencies @@ -220,14 +207,13 @@ namespace FlavorTagDiscriminants { struct TrackSequenceBuilder { TrackSequenceBuilder(SortOrder, TrackSelection, - FlipTagConfig, - const std::string& trackLinkName); + const DL2Options&); std::string name; internal::TracksFromJet tracksFromJet; internal::TrackSequenceFilter flipFilter; std::vector sequencesFromTracks; }; - typedef std::function OutputSetter; + typedef SG::AuxElement::Decorator OutputSetter; typedef std::vector > OutNode; SG::AuxElement::ConstAccessor> m_jetLink; std::string m_input_node_name; @@ -248,15 +234,15 @@ namespace FlavorTagDiscriminants { // factory functions to produce callable objects that build inputs namespace get { VarFromBTag varFromBTag(const std::string& name, - EDMType, - const std::string& defaultflag); - TrackSortVar trackSortVar(SortOrder); + EDMType, + const std::string& defaultflag); + TrackSortVar trackSortVar(SortOrder, const DL2Options&); std::pair> trackFilter( - TrackSelection); + TrackSelection, const DL2Options&); std::pair> seqFromTracks( - const DL2TrackInputConfig&); + const DL2TrackInputConfig&, const DL2Options&); std::pair> flipFilter( - FlipTagConfig); + const DL2Options&); } } } diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2HighLevel.h b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2HighLevel.h index 7bb8fa6b2f4af3241a95b2761a114c4205d0be1c..38534e72fb72128c4955537061cdb9cb04fd51cd 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2HighLevel.h +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/DL2HighLevel.h @@ -24,7 +24,7 @@ namespace FlavorTagDiscriminants { public: DL2HighLevel(const std::string& nn_file_name, FlipTagConfig = FlipTagConfig::STANDARD, - std::map var_remap = {}); + std::map remap_scalar = {}); DL2HighLevel(DL2HighLevel&&); ~DL2HighLevel(); void decorate(const xAOD::BTagging& btag) const; diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/PoorMansIpAugmenterAlg.h b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/PoorMansIpAugmenterAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..34107a83422655550075cbef1962f59ce1a17a15 --- /dev/null +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/PoorMansIpAugmenterAlg.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef POOR_MANS_TRACK_AUGMENTER_ALG_HH +#define POOR_MANS_TRACK_AUGMENTER_ALG_HH + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "GaudiKernel/ToolHandle.h" +#include "AthContainers/AuxElement.h" +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODTracking/VertexContainer.h" +#include "xAODTracking/VertexAuxContainer.h" +#include "StoreGate/WriteDecorHandle.h" + +namespace FlavorTagDiscriminants { + + + class PoorMansIpAugmenterAlg: public AthReentrantAlgorithm { + public: + PoorMansIpAugmenterAlg(const std::string& name, + ISvcLocator* pSvcLocator ); + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ) const override; + virtual StatusCode finalize() override; + + + private: + const xAOD::Vertex* getPrimaryVertex( const xAOD::VertexContainer& ) const; + + private: + + // Input Containers + SG::ReadHandleKey< xAOD::TrackParticleContainer > m_TrackContainerKey { + this,"TrackContainer","InDetTrackParticles", + "Key for the input track collection"}; + SG::ReadHandleKey< xAOD::VertexContainer > m_VertexContainerKey { + this,"PrimaryVertexContainer","PrimaryVertices", + "Key for the input vertex collection"}; + + // Decorators for tracks + Gaudi::Property< std::string > m_prefix{this,"prefix","poboyIp_",""}; + + SG::WriteDecorHandleKey< xAOD::TrackParticleContainer > m_dec_d0_sigma { + this, "d0Uncertainty", "d0Uncertainty", "d0Uncertainty of tracks"}; + SG::WriteDecorHandleKey< xAOD::TrackParticleContainer > m_dec_z0_sigma { + this, "z0SinThetaUncertainty", "z0SinThetaUncertainty", + "z0SinThetaUncertainty of tracks"}; + + SG::WriteDecorHandleKey< xAOD::TrackParticleContainer > m_dec_track_pos { + this, "trackDisplacement","trackDisplacement", + "trackDisplacement of tracks" }; + SG::WriteDecorHandleKey< xAOD::TrackParticleContainer > m_dec_track_mom { + this, "trackMomentum","trackMomentum","trackMomentum of tracks" }; + }; + +} + +#endif diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/customGetter.h b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/customGetter.h index 1d87420303845949052258692076e912fc7abc15..7b2c1dcf80a3e7a04170ad5b202400cdbdd2d4f5 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/customGetter.h +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/FlavorTagDiscriminants/customGetter.h @@ -9,12 +9,13 @@ // EDM includes -#include "xAODJet/Jet.h" -#include "xAODTracking/TrackParticle.h" -#include "xAODBTagging/BTagging.h" +#include "xAODJet/JetFwd.h" +#include "xAODTracking/TrackParticleFwd.h" +#include "xAODBTagging/BTaggingFwd.h" #include #include +#include #ifndef CUSTOM_GETTER_H #define CUSTOM_GETTER_H @@ -40,20 +41,27 @@ namespace FlavorTagDiscriminants { /// /// NOTE: This function is for experts only, don't expect support. /// - std::function( + + using SequenceFromTracks = std::function( const xAOD::Jet&, - const std::vector&)> - customSequenceGetter(const std::string& name); + const std::vector&)>; + + std::pair> + customSequenceGetterWithDeps( + const std::string& name, // name of the getter + const std::string& prefix // prefix for track accessor + ); // internal functions namespace internal { std::function(const xAOD::BTagging&)> customGetterAndName(const std::string&); - std::function>( + std::pair>( const xAOD::Jet&, - const std::vector&)> - customNamedSeqGetter(const std::string&); + const std::vector&)>, + std::set> + customNamedSeqGetterWithDeps(const std::string&, const std::string&); } } diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/BTagMuonAugmenter.cxx b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/BTagMuonAugmenter.cxx index 63e767c63c2a2e4b24069d00c0cb8a872b18f93f..9b31bebac78eb1e10f4d38e9c6852e7071163a55 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/BTagMuonAugmenter.cxx +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/BTagMuonAugmenter.cxx @@ -14,6 +14,7 @@ namespace FlavorTagDiscriminants { float muonMinDR, float muonMinpT, FlipTagConfig flipConfig ): + m_btag_track_aug("btagIp_"), m_jetLink("jetLink"), m_dec_muon_isDefaults("softMuon_isDefaults"), m_dec_muon_pt("softMuon_pt"), @@ -34,7 +35,6 @@ namespace FlavorTagDiscriminants { { // you probably have to initialize something here using namespace FlavorTagDiscriminants; - m_btag_track_aug = BTagTrackIpAccessor(); m_muonAssociationName = muonAssociationName; m_muonMinDR = muonMinDR; m_muonMinpT = muonMinpT; diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2.cxx b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2.cxx index f128ba4bd2cdbe8b591ca87877b36def4e0b058e..7db20461070dff4624c3e0842fd2d02366bf2995 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2.cxx +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2.cxx @@ -11,28 +11,31 @@ namespace { const std::string jetLinkName = "jetLink"; - const std::string defaultTrackLinkName = "BTagTrackToJetAssociator"; - } namespace FlavorTagDiscriminants { + DL2Options::DL2Options() { + track_prefix = "btagIp_"; + flip = FlipTagConfig::STANDARD; + track_link_name = "BTagTrackToJetAssociator"; + } + // DL2 // // TODO: make this work with more input nodes DL2::DL2(const lwt::GraphConfig& graph_config, const std::vector& inputs, const std::vector& track_sequences, - FlipTagConfig flipConfig, - std::map remap, - OutputType output_type): + const DL2Options& options): m_jetLink(jetLinkName), m_input_node_name(""), m_graph(new lwt::LightweightGraph(graph_config,graph_config.outputs.begin()->first)), m_variable_cleaner(nullptr) { using namespace internal; + std::map remap = options.remap_scalar; // set up inputs if (graph_config.inputs.size() > 1) { throw std::logic_error("We don't currently support graphs with " @@ -55,30 +58,25 @@ namespace FlavorTagDiscriminants { m_varsFromBTag.push_back(filler); } - // remap track link name - auto tlh = remap.extract(defaultTrackLinkName); - std::string trackLinkName = tlh ? tlh.mapped() : defaultTrackLinkName; - // set up sequence inputs - for (const DL2TrackSequenceConfig& track_cfg: track_sequences) { - TrackSequenceBuilder track_getter(track_cfg.order, - track_cfg.selection, - flipConfig, - trackLinkName); + for (const DL2TrackSequenceConfig& cfg: track_sequences) { + TrackSequenceBuilder track_getter(cfg.order, + cfg.selection, + options); // add the tracking data dependencies - auto track_data_deps = get::trackFilter(track_cfg.selection).second; - track_data_deps.merge(get::flipFilter(flipConfig).second); + auto track_data_deps = get::trackFilter(cfg.selection, options).second; + track_data_deps.merge(get::flipFilter(options).second); - track_getter.name = track_cfg.name; - for (const DL2TrackInputConfig& input_cfg: track_cfg.inputs) { - auto [seqGetter, deps] = get::seqFromTracks(input_cfg); + track_getter.name = cfg.name; + for (const DL2TrackInputConfig& input_cfg: cfg.inputs) { + auto [seqGetter, deps] = get::seqFromTracks(input_cfg, options); track_getter.sequencesFromTracks.push_back(seqGetter); track_data_deps.merge(deps); } m_trackSequenceBuilders.push_back(track_getter); m_dataDependencyNames.trackInputs.merge(track_data_deps); m_dataDependencyNames.bTagInputs.insert(jetLinkName); - m_dataDependencyNames.bTagInputs.insert(trackLinkName); + m_dataDependencyNames.bTagInputs.insert(options.track_link_name); } // set up outputs @@ -90,24 +88,11 @@ namespace FlavorTagDiscriminants { std::string name = node_name + "_" + element; // let user rename the output - auto replacement_handle = remap.extract(name); - if (replacement_handle) name = replacement_handle.mapped(); + if (auto h = remap.extract(name)) name = h.mapped(); m_dataDependencyNames.bTagOutputs.insert(name); - // for the spring 2019 retraining campaign we're stuck with - // doubles. Hopefully at some point we can move to using - // floats. - if (output_type == OutputType::DOUBLE) { - SG::AuxElement::Decorator d(name); - node.emplace_back( - element, [d](const SG::AuxElement& e, double v){ d(e) = v;}); - } else if (output_type == OutputType::FLOAT) { - SG::AuxElement::Decorator f(name); - node.emplace_back( - element, [f](const SG::AuxElement& e, double v){ f(e) = v;}); - } else { - throw std::logic_error("Unknown output type"); - } + SG::AuxElement::Decorator f(name); + node.emplace_back(element, f); } m_decorators[node_name] = node; } @@ -161,7 +146,7 @@ namespace FlavorTagDiscriminants { // the second argument to compute(...) is for sequences auto out_vals = m_graph->compute(nodes, seqs, dec.first); for (const auto& node: dec.second) { - node.second(btag, out_vals.at(node.first)); + node.second(btag) = out_vals.at(node.first); } } } @@ -171,12 +156,11 @@ namespace FlavorTagDiscriminants { } DL2::TrackSequenceBuilder::TrackSequenceBuilder( - SortOrder order, + SortOrder sort, TrackSelection selection, - FlipTagConfig flipcfg, - const std::string& trackLink): - tracksFromJet(order, selection, trackLink), - flipFilter(internal::get::flipFilter(flipcfg).first) + const DL2Options& options): + tracksFromJet(sort, selection, options), + flipFilter(internal::get::flipFilter(options).first) { } @@ -189,10 +173,10 @@ namespace FlavorTagDiscriminants { // Track Getter Class TracksFromJet::TracksFromJet(SortOrder order, TrackSelection selection, - const std::string& track_link_name): - m_trackAssociator(track_link_name), - m_trackSortVar(get::trackSortVar(order)), - m_trackFilter(get::trackFilter(selection).first) + const DL2Options& options): + m_trackAssociator(options.track_link_name), + m_trackSortVar(get::trackSortVar(order, options)), + m_trackFilter(get::trackFilter(selection, options).first) { } Tracks TracksFromJet::operator()(const xAOD::Jet& jet, @@ -254,11 +238,12 @@ namespace FlavorTagDiscriminants { // factory for functions which return the sort variable we // use to order tracks - TrackSortVar trackSortVar(SortOrder order) { + TrackSortVar trackSortVar(SortOrder config, const DL2Options& options) + { typedef xAOD::TrackParticle Tp; typedef xAOD::Jet Jet; - BTagTrackIpAccessor aug; - switch(order) { + BTagTrackIpAccessor aug(options.track_prefix); + switch(config) { case SortOrder::ABS_D0_SIGNIFICANCE_DESCENDING: return [aug](const Tp* tp, const Jet&) { return std::abs(aug.d0(*tp) / aug.d0Uncertainty(*tp)); @@ -278,11 +263,11 @@ namespace FlavorTagDiscriminants { // factory for functions that return true for tracks we want to // use, false for those we don't want std::pair> trackFilter( - TrackSelection selection) { + TrackSelection config, const DL2Options& options) { typedef xAOD::TrackParticle Tp; typedef SG::AuxElement AE; - BTagTrackIpAccessor aug; + BTagTrackIpAccessor aug(options.track_prefix); auto data_deps = aug.getTrackIpDataDependencyNames(); // make sure we record accessors as data dependencies @@ -300,7 +285,7 @@ namespace FlavorTagDiscriminants { auto sct_shared = addAccessor("numberOfSCTSharedHits"); auto sct_dead = addAccessor("numberOfSCTDeadSensors"); - switch (selection) { + switch (config) { case TrackSelection::ALL: return {[](const Tp*) {return true;}, {} }; // the following numbers come from Nicole, Dec 2018: // pt > 1 GeV @@ -360,8 +345,9 @@ namespace FlavorTagDiscriminants { // factory for functions that build std::vector objects from // track sequences std::pair> seqFromTracks( - const DL2TrackInputConfig& cfg) + const DL2TrackInputConfig& cfg, const DL2Options& options) { + const std::string prefix = options.track_prefix; switch (cfg.type) { case EDMType::FLOAT: return { SequenceGetter(cfg.name), {cfg.name} @@ -369,10 +355,10 @@ namespace FlavorTagDiscriminants { case EDMType::UCHAR: return { SequenceGetter(cfg.name), {cfg.name} }; - case EDMType::CUSTOM_GETTER: return { - customNamedSeqGetter(cfg.name), - BTagTrackIpAccessor().getTrackIpDataDependencyNames() - }; + case EDMType::CUSTOM_GETTER: { + return customNamedSeqGetterWithDeps( + cfg.name, options.track_prefix); + } default: { throw std::logic_error("Unknown EDM type"); } @@ -400,11 +386,11 @@ namespace FlavorTagDiscriminants { // factory function std::pair> flipFilter( - FlipTagConfig cfg) + const DL2Options& options) { namespace ph = std::placeholders; // for _1, _2, _3 - BTagTrackIpAccessor aug; - switch(cfg) { + BTagTrackIpAccessor aug(options.track_prefix); + switch(options.flip) { case FlipTagConfig::NEGATIVE_IP_ONLY: // flips order and removes tracks with negative IP return { diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2HighLevel.cxx b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2HighLevel.cxx index 183d1f54d4e433a8b4da45aa93be47e258f29985..8d91ba9cef88f9417f29dd57ed8c456354162d8b 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2HighLevel.cxx +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/DL2HighLevel.cxx @@ -31,7 +31,7 @@ namespace FlavorTagDiscriminants { DL2HighLevel::DL2HighLevel(const std::string& nn_file_name, FlipTagConfig flip_config, - std::map var_map): + std::map remap_scalar): m_dl2(nullptr) { // get the graph @@ -69,22 +69,19 @@ namespace FlavorTagDiscriminants { // build the standard inputs // - // the ftagfloat_t is defined in this library (in ftagfloat_t.h) - EDMType floattype = EDMTypeEnum::type; - // type and default value-finding regexes are hardcoded for now TypeRegexes type_regexes = { {".*_isDefaults"_r, EDMType::UCHAR}, // TODO: in the future we should migrate RNN and IPxD // variables to floats. This is outside the scope of the // current flavor tagging developments and AFT-438. - {"IP[23]D(Neg)?_[pbc](b|c|u|tau)"_r, floattype}, - {"SV1(Flip)?_[pbc](b|c|u|tau)"_r, floattype}, - {"(rnnip|iprnn|dips[^_]*)(flip)?_p(b|c|u|tau)"_r, floattype}, + {"IP[23]D(Neg)?_[pbc](b|c|u|tau)"_r, EDMType::FLOAT}, + {"SV1(Flip)?_[pbc](b|c|u|tau)"_r, EDMType::FLOAT}, + {"(rnnip|iprnn|dips[^_]*)(flip)?_p(b|c|u|tau)"_r, EDMType::FLOAT}, {"(JetFitter|SV1|JetFitterSecondaryVertex)(Flip)?_[Nn].*"_r, EDMType::INT}, {"(JetFitter|SV1|JetFitterSecondaryVertex).*"_r, EDMType::FLOAT}, {"pt|abs_eta|eta"_r, EDMType::CUSTOM_GETTER}, - {"softMuon_p[bcu]"_r, floattype}, + {"softMuon_p[bcu]"_r, EDMType::FLOAT}, {"softMuon_.*"_r, EDMType::FLOAT}, }; @@ -111,7 +108,7 @@ namespace FlavorTagDiscriminants { if (config.inputs.size() == 1) { // allow the user to remape some of the inputs - remap_inputs(config.inputs.at(0).variables, var_map, + remap_inputs(config.inputs.at(0).variables, remap_scalar, config.inputs.at(0).defaults); std::vector input_names; @@ -139,7 +136,7 @@ namespace FlavorTagDiscriminants { TypeRegexes trk_type_regexes { {"numberOf.*"_r, EDMType::UCHAR}, - {"btagIp_(d|z)0.*"_r, EDMType::FLOAT}, + {"btagIp_(d0|z0SinTheta)Uncertainty"_r, EDMType::FLOAT}, {".*_(d|z)0.*"_r, EDMType::CUSTOM_GETTER}, {"(log_)?(ptfrac|dr).*"_r, EDMType::CUSTOM_GETTER} }; @@ -161,15 +158,23 @@ namespace FlavorTagDiscriminants { std::vector trk_config = get_track_input_config( trk_names, trk_type_regexes, trk_sort_regexes, trk_select_regexes); - OutputType outtype = OutputTypeEnum::type; + // some additional options + DL2Options options; + if (auto h = remap_scalar.extract(options.track_prefix)) { + options.track_prefix = h.mapped(); + } + if (auto h = remap_scalar.extract(options.track_link_name)) { + options.track_link_name = h.mapped(); + } + options.flip = flip_config; + options.remap_scalar = remap_scalar; + m_dl2.reset( new DL2( config, // lwtnn config input_config, // EDM input config trk_config, // edm track input config - flip_config, // flip tagger configuration - var_map, // variable remapping - outtype // output type + options )); } diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/customGetter.cxx b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/customGetter.cxx index 3d8aa0da5083d85c1f4d0f700a58e7fc8ba1ae36..6c01e1a7dbeb41e011813b140c4f72c4db3aea62 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/customGetter.cxx +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/Root/customGetter.cxx @@ -4,6 +4,12 @@ #include "FlavorTagDiscriminants/customGetter.h" #include "FlavorTagDiscriminants/BTagTrackIpAccessor.h" +#include "xAODJet/Jet.h" +#include "xAODTracking/TrackParticle.h" +#include "xAODBTagging/BTagging.h" + +#include + namespace { // ______________________________________________________________________ // Custom getters for jet-wise quantities @@ -56,79 +62,64 @@ namespace { } }; -} - -namespace FlavorTagDiscriminants { - namespace internal { - - // ________________________________________________________________ - // Interface functions - // - // As long as we're giving lwtnn pair objects, we - // can't use the raw getter functions above (which only return a - // double). Instead we'll wrap those functions in another function, - // which returns the pair we wanted. - // - // Case for jet variables - std::function(const xAOD::BTagging&)> - customGetterAndName(const std::string& name) { - auto getter = customGetter(name); - return [name, getter](const xAOD::BTagging& j) { - return std::make_pair(name, getter(j)); - }; - } + std::optional + sequenceWithIpDep( + const std::string& name, + const std::string& prefix) + { - // Case for track variables - std::function>( - const xAOD::Jet&, - const std::vector&)> - customNamedSeqGetter(const std::string& name) { - auto getter = customSequenceGetter(name); - return [name, getter](const xAOD::Jet& j, - const std::vector& t) { - return std::make_pair(name, getter(j, t)); - }; - } - } - // ________________________________________________________________________ - // Master track getter list - // - // These functions are wrapped by the customNamedSeqGetter function - // below to become the ones that are actually used in DL2. - // - std::function( - const xAOD::Jet&, - const std::vector&)> - customSequenceGetter(const std::string& name) { - using Ac = BTagTrackIpAccessor; using Tp = xAOD::TrackParticle; using Jet = xAOD::Jet; typedef std::vector Tracks; + + BTagTrackIpAccessor a(prefix); if (name == "IP3D_signed_d0_significance") { - return TJGetter([a=Ac()](const Tp& t, const Jet& j){ - return a.getSignedIp(t, j).ip3d_signed_d0_significance; + return TJGetter([a](const Tp& t, const Jet& j){ + return a.getSignedIp(t, j).ip3d_signed_d0_significance; }); } if (name == "IP3D_signed_z0_significance") { - return TJGetter([a=Ac()](const Tp& t, const Jet& j){ + return TJGetter([a](const Tp& t, const Jet& j){ return a.getSignedIp(t, j).ip3d_signed_z0_significance; }); } if (name == "IP2D_signed_d0") { - return TJGetter([a=Ac()](const Tp& t, const Jet& j){ + return TJGetter([a](const Tp& t, const Jet& j){ return a.getSignedIp(t, j).ip2d_signed_d0; }); } if (name == "IP3D_signed_d0") { - return TJGetter([a=Ac()](const Tp& t, const Jet& j){ + return TJGetter([a](const Tp& t, const Jet& j){ return a.getSignedIp(t, j).ip3d_signed_d0; }); } if (name == "IP3D_signed_z0") { - return TJGetter([a=Ac()](const Tp& t, const Jet& j){ + return TJGetter([a](const Tp& t, const Jet& j){ return a.getSignedIp(t, j).ip3d_signed_z0; }); } + if (name == "d0" || name == "btagIp_d0") { + return TJGetter([a](const Tp& t, const Jet&){ + return a.d0(t); + }); + } + if (name == "z0SinTheta" || name == "btagIp_z0SinTheta") { + return TJGetter([a](const Tp& t, const Jet&){ + return a.z0SinTheta(t); + }); + } + return std::nullopt; + + } + + std::optional + sequenceNoDep(const std::string& name) + { + + using Tp = xAOD::TrackParticle; + using Jet = xAOD::Jet; + typedef std::vector Tracks; + if (name == "log_ptfrac") { return TJGetter([](const Tp& t, const Jet& j) { return std::log(t.pt() / j.pt()); @@ -156,18 +147,78 @@ namespace FlavorTagDiscriminants { } if (name == "pt") { return [](const Jet&, const Tracks& t) { - std::vector tracks; - for (auto* trk: t) tracks.push_back(trk->pt()); - return tracks; - }; + std::vector tracks; + for (auto* trk: t) tracks.push_back(trk->pt()); + return tracks; + }; } if (name == "eta") { return [](const Jet&, const Tracks& t) { - std::vector tracks; - for (auto* trk: t) tracks.push_back(trk->eta()); - return tracks; + std::vector tracks; + for (auto* trk: t) tracks.push_back(trk->eta()); + return tracks; + }; + } + return std::nullopt; + } + +} + +namespace FlavorTagDiscriminants { + namespace internal { + + // ________________________________________________________________ + // Interface functions + // + // As long as we're giving lwtnn pair objects, we + // can't use the raw getter functions above (which only return a + // double). Instead we'll wrap those functions in another function, + // which returns the pair we wanted. + // + // Case for jet variables + std::function(const xAOD::BTagging&)> + customGetterAndName(const std::string& name) { + auto getter = customGetter(name); + return [name, getter](const xAOD::BTagging& j) { + return std::make_pair(name, getter(j)); }; } + + // Case for track variables + std::pair>( + const xAOD::Jet&, + const std::vector&)>, + std::set> + customNamedSeqGetterWithDeps(const std::string& name, + const std::string& prefix) { + auto [getter, deps] = customSequenceGetterWithDeps(name, prefix); + return { + [name, getter](const xAOD::Jet& j, + const std::vector& t) { + return std::make_pair(name, getter(j, t)); + }, + deps + }; + } + } + // ________________________________________________________________________ + // Master track getter list + // + // These functions are wrapped by the customNamedSeqGetter function + // below to become the ones that are actually used in DL2. + // + std::pair> + customSequenceGetterWithDeps(const std::string& name, + const std::string& prefix) { + + if (auto getter = sequenceWithIpDep(name, prefix)) { + auto deps = BTagTrackIpAccessor(prefix).getTrackIpDataDependencyNames(); + return {*getter, deps}; + } + + if (auto getter = sequenceNoDep(name)) { + return {*getter, {}}; + } throw std::logic_error("no match for custom getter " + name); } diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/src/PoorMansIpAugmenterAlg.cxx b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/src/PoorMansIpAugmenterAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..26b70993a752cd921c085c516282dcca6087d7f5 --- /dev/null +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/src/PoorMansIpAugmenterAlg.cxx @@ -0,0 +1,219 @@ +/* + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "FlavorTagDiscriminants/PoorMansIpAugmenterAlg.h" + +#include "xAODTracking/VertexContainer.h" +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODTracking/TrackParticleAuxContainer.h" + +// NOTE: would be nice to include this to access track parameters, but +// it's not in all builds. +// +// #include "TrkEventPrimitives/ParamDefs.h" + +namespace Pmt { + // copied from + // https://acode-browser1.usatlas.bnl.gov/lxr/source/athena/Tracking/TrkEvent/TrkEventPrimitives/TrkEventPrimitives/ParamDefs.h, + // which isn't included in some builds. + enum ParamDefs { + // Track defining parameters + d0 = 0, + z0 = 1, + phi0 = 2, + theta = 3, + qOverP = 4, + // Cartesian + x = 0, + y = 1, + z = 2, + }; + + // I'm pretty sure I can get x, y, z, beamspot perigee points from + // x = -sin(phi) * d0 + // y = cos(phi) * d0 + // z = z0 + Eigen::Vector3d getPosition( + const xAOD::TrackParticle& trk) { + double d0 = trk.d0(); + double phi = trk.phi(); + return Amg::Vector3D( + d0 * -std::sin(phi), + d0 * std::cos(phi), + trk.z0()); + } + + // this one is going to be harder, there's some lead here: + // https://acode-browser1.usatlas.bnl.gov/lxr/source/athena/Tracking/TrkVertexFitter/TrkVertexFitterUtils/src/TrackToVertexIPEstimator.cxx + double getSigmaD0(const xAOD::TrackParticle& trk, + const xAOD::Vertex& vtx) { + + // start with the track part + double trackComponent = trk.definingParametersCovMatrixDiagVec().at( + Pmt::d0); + + // now do the vertex part + // first two elements of the vertex covariance is xy + Eigen::Matrix2d vtxCov = vtx.covariancePosition().block<2,2>(0,0); + double phi = trk.phi(); + // The sign seems inverted below, but maybe that doesn't + // matter. I'm just following TrackToVertexIPEstimator... + Eigen::Vector2d vtxJacobian(-std::sin(phi), std::cos(phi)); + double vertexComponent = vtxJacobian.transpose()*vtxCov*vtxJacobian; + + return std::sqrt(trackComponent + vertexComponent); + + } + + + double getSigmaZ0SinTheta(const xAOD::TrackParticle& trk, + const xAOD::Vertex& vtx) { + + // first do the track part + const auto& fullCov = trk.definingParametersCovMatrix(); + Eigen::Matrix2d trkCov; + trkCov(0,0)=fullCov(Pmt::z0, Pmt::z0); + trkCov(0,1)=fullCov(Pmt::z0, Pmt::theta); + trkCov(1,0)=fullCov(Pmt::theta, Pmt::z0); + trkCov(1,1)=fullCov(Pmt::theta, Pmt::theta); + double theta = trk.theta(); + Eigen::Vector2d trkJacobian( + std::sin(theta), + trk.z0()*std::cos(theta)); + double trackComponent = trkJacobian.transpose()*trkCov*trkJacobian; + + // now do the vertex part + double vxZCov = vtx.covariancePosition()(Pmt::z,Pmt::z); + double vertexComponent = std::sin(theta)*vxZCov*std::sin(theta); + + return std::sqrt(trackComponent + vertexComponent); + + } + +} + +namespace FlavorTagDiscriminants { + + PoorMansIpAugmenterAlg::PoorMansIpAugmenterAlg( + const std::string& name, ISvcLocator* loc ) + : AthReentrantAlgorithm(name, loc) {} + + StatusCode PoorMansIpAugmenterAlg::initialize() { + ATH_MSG_INFO( "Inizializing " << name() << "... " ); + + // Initialize Container keys + ATH_MSG_DEBUG( "Inizializing containers:" ); + ATH_MSG_DEBUG( " ** " << m_TrackContainerKey ); + ATH_MSG_DEBUG( " ** " << m_VertexContainerKey ); + + ATH_CHECK( m_TrackContainerKey.initialize() ); + ATH_CHECK( m_VertexContainerKey.initialize() ); + + // Prepare decorators + m_dec_d0_sigma = m_TrackContainerKey.key() + "." + m_prefix.value() + m_dec_d0_sigma.key(); + m_dec_z0_sigma = m_TrackContainerKey.key() + "." + m_prefix.value() + m_dec_z0_sigma.key(); + + m_dec_track_pos = m_TrackContainerKey.key() + "." + m_prefix.value() + m_dec_track_pos.key(); + m_dec_track_mom = m_TrackContainerKey.key() + "." + m_prefix.value() + m_dec_track_mom.key(); + + // Initialize decorators + ATH_MSG_DEBUG( "Inizializing decorators:" ); + ATH_MSG_DEBUG( " ** " << m_dec_d0_sigma ); + ATH_MSG_DEBUG( " ** " << m_dec_z0_sigma ); + ATH_MSG_DEBUG( " ** " << m_dec_track_pos ); + ATH_MSG_DEBUG( " ** " << m_dec_track_mom ); + + CHECK( m_dec_d0_sigma.initialize() ); + CHECK( m_dec_z0_sigma.initialize() ); + CHECK( m_dec_track_pos.initialize() ); + CHECK( m_dec_track_mom.initialize() ); + + return StatusCode::SUCCESS; + } + + StatusCode PoorMansIpAugmenterAlg::execute(const EventContext& ctx) const { + ATH_MSG_DEBUG( "Executing " << name() << "... " ); + + SG::ReadHandle verteces( + m_VertexContainerKey,ctx ); + CHECK( verteces.isValid() ); + + const xAOD::Vertex* primary = getPrimaryVertex( *verteces ); + if ( primary == nullptr ) { + ATH_MSG_FATAL("No primary vertex found"); + return StatusCode::FAILURE; + } + + SG::ReadHandle tracks( + m_TrackContainerKey,ctx); + CHECK( tracks.isValid() ); + ATH_MSG_DEBUG( "Retrieved " << tracks->size() << " input tracks..." ); + + using TPC = xAOD::TrackParticleContainer; + + SG::WriteDecorHandle decor_d0_sigma(m_dec_d0_sigma, ctx); + SG::WriteDecorHandle decor_z0_sigma(m_dec_z0_sigma, ctx); + + SG::WriteDecorHandle> decor_track_pos( + m_dec_track_pos, ctx); + SG::WriteDecorHandle> decor_track_mom( + m_dec_track_mom, ctx); + + // now decorate the tracks + for (const xAOD::TrackParticle *trk: *tracks) { + decor_d0_sigma(*trk) = Pmt::getSigmaD0(*trk, *primary); + decor_z0_sigma(*trk) = Pmt::getSigmaZ0SinTheta(*trk, *primary); + + const Amg::Vector3D position = ( + Pmt::getPosition(*trk) - primary->position()); + auto trkp4 = trk->p4(); + const Amg::Vector3D momentum(trkp4.Px(), trkp4.Py(), trkp4.Pz()); + + ATH_MSG_DEBUG( + "track_displacement (x,y,z)= (" + << position.x() << ", " << position.y() << ", " << position.z() + << ")"); + ATH_MSG_DEBUG( + "track_momentum (x,y,z)= (" + << momentum.x() << ", " << momentum.y() << ", " << momentum.z() + << ")"); + + std::vector out_vec_pos( + position.data(), position.data() + position.size()); + std::vector out_vec_mom( + momentum.data(), momentum.data() + momentum.size()); + + decor_track_pos (*trk) = out_vec_pos; + decor_track_mom (*trk) = out_vec_mom; + } + + return StatusCode::SUCCESS; + } + + StatusCode PoorMansIpAugmenterAlg::finalize() { + return StatusCode::SUCCESS; + } + + const xAOD::Vertex* PoorMansIpAugmenterAlg::getPrimaryVertex( + const xAOD::VertexContainer& vertexCollection ) const { + if ( vertexCollection.size() == 0 ) { + ATH_MSG_DEBUG( "Input vertex collection has size 0!" ); + return nullptr; + } + + for ( const xAOD::Vertex *vertex : vertexCollection ) { + if ( vertex->vertexType() == xAOD::VxType::PriVtx ) { + return vertex; + } + } + + // this is taken from BTagTool, should be the beam spot if nothing + // else exists. + return vertexCollection.front(); + } + +} + + diff --git a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/src/components/FlavorTagDiscriminants_entries.cxx b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/src/components/FlavorTagDiscriminants_entries.cxx index fdd2393b0ded8bd41bd79120a5a6d6cdce54fe0c..0b0bf7d336c0ee924cead3d414da3256c6fefaee 100644 --- a/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/src/components/FlavorTagDiscriminants_entries.cxx +++ b/PhysicsAnalysis/JetTagging/FlavorTagDiscriminants/src/components/FlavorTagDiscriminants_entries.cxx @@ -12,6 +12,7 @@ #include "FlavorTagDiscriminants/JetToBTagLinkerAlg.h" #include "FlavorTagDiscriminants/BTagTrackLinkCopyAlg.h" #include "FlavorTagDiscriminants/BTaggingBuilderAlg.h" +#include "FlavorTagDiscriminants/PoorMansIpAugmenterAlg.h" using namespace FlavorTagDiscriminants; @@ -25,3 +26,4 @@ DECLARE_COMPONENT(BTagToJetLinkerAlg) DECLARE_COMPONENT(JetToBTagLinkerAlg) DECLARE_COMPONENT(BTagTrackLinkCopyAlg) DECLARE_COMPONENT(BTaggingBuilderAlg) +DECLARE_COMPONENT(PoorMansIpAugmenterAlg) diff --git a/PhysicsAnalysis/JetTagging/FlavourTaggingTests/src/PhysicsVariablePlots.cxx b/PhysicsAnalysis/JetTagging/FlavourTaggingTests/src/PhysicsVariablePlots.cxx index 35bb16eb1a62e87aff4515926d7e9fc5181360d4..cf8cab88a73396d6ee0e6432646b5ee8fdd6aef1 100644 --- a/PhysicsAnalysis/JetTagging/FlavourTaggingTests/src/PhysicsVariablePlots.cxx +++ b/PhysicsAnalysis/JetTagging/FlavourTaggingTests/src/PhysicsVariablePlots.cxx @@ -357,7 +357,7 @@ namespace FTAGValidation { if (trackType == "bTag" || trackType == "") { if (chain != "") { - BTagTrackIpAccessor accessor; + BTagTrackIpAccessor accessor("btagIp_"); float d0_signed_sig = accessor.getSignedIp(*trackParticle, *jet).ip3d_signed_d0_significance; float z0_signed_sig = accessor.getSignedIp(*trackParticle, *jet).ip3d_signed_z0_significance; ATH_CHECK( fillHistogram( chain+flavour+"track_sigd0_signed", d0_signed_sig) ); diff --git a/PhysicsAnalysis/JetTagging/JetTagAlgs/BTagging/python/JetParticleAssociationAlgConfig.py b/PhysicsAnalysis/JetTagging/JetTagAlgs/BTagging/python/JetParticleAssociationAlgConfig.py index 3c8d32d20653b867980e39a188a1b4f1d0e7dbe3..e9cfd446fffc92f07bd5b49f02ef996de3b4591d 100644 --- a/PhysicsAnalysis/JetTagging/JetTagAlgs/BTagging/python/JetParticleAssociationAlgConfig.py +++ b/PhysicsAnalysis/JetTagging/JetTagAlgs/BTagging/python/JetParticleAssociationAlgConfig.py @@ -1,21 +1,9 @@ -# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration -from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator -from AthenaConfiguration.ComponentFactory import CompFactory -from BTagging.JetParticleAssociationConfig import JetParticleAssociationCfg +# this is just a thin wrapper on ParticleJetTools, I want to +# keep the scope of the MR where we moved this limited. Eventually I +# should move the things that point to this to point to the library +# below. -def JetParticleAssociationAlgCfg(ConfigFlags, JetCollection="", InputParticleCollection="", OutputParticleDecoration="", **options): - - - acc=ComponentAccumulator() - jetcol = JetCollection.replace("Track", "PV0Track") - - # setup the associator - options['JetContainer'] = jetcol + 'Jets' - options['Decorators'] = [acc.popToolsAndMerge(JetParticleAssociationCfg(ConfigFlags, jetcol+'Jets', InputParticleCollection, OutputParticleDecoration))] - options['name'] = (jetcol + "_" + OutputParticleDecoration + "_assoc").lower() - - # -- create the association algorithm - acc.addEventAlgo(CompFactory.JetDecorationAlg(**options)) - - return acc \ No newline at end of file +from ParticleJetTools.JetParticleAssociationAlgConfig import ( # noqa: F401 + JetParticleAssociationAlgCfg) # noqa: F401 diff --git a/PhysicsAnalysis/JetTagging/JetTagAlgs/BTagging/python/JetParticleAssociationConfig.py b/PhysicsAnalysis/JetTagging/JetTagAlgs/BTagging/python/JetParticleAssociationConfig.py deleted file mode 100644 index 154333d7a0e4282fc717a2bc1dd44f094da64c24..0000000000000000000000000000000000000000 --- a/PhysicsAnalysis/JetTagging/JetTagAlgs/BTagging/python/JetParticleAssociationConfig.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration - -from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator -from AthenaConfiguration.ComponentFactory import CompFactory - -# import the JetParticleAssociation configurable (first try - only -JetParticleShrinkingConeAssociation=CompFactory.JetParticleShrinkingConeAssociation - -def JetParticleAssociationCfg(ConfigFlags, jetCollName, partcollname, assocname, **options): - - acc=ComponentAccumulator() - - options["coneSizeFitPar1"] = +0.239 - options["coneSizeFitPar2"] = -1.220 - options["coneSizeFitPar3"] = -1.64e-5 - options["InputParticleContainer"] = partcollname - options["OutputDecoration"] = assocname - - # -- create the association tool - acc.setPrivateTools(JetParticleShrinkingConeAssociation(JetContainer=jetCollName, **options)) - - return acc \ No newline at end of file