diff --git a/Control/AthenaConfiguration/python/AllConfigFlags.py b/Control/AthenaConfiguration/python/AllConfigFlags.py index 89cfa2833b86440ec8d4a6331742b92ed4c696ae..49b4594f5ee89604fd444dedb72a85bb942c2122 100644 --- a/Control/AthenaConfiguration/python/AllConfigFlags.py +++ b/Control/AthenaConfiguration/python/AllConfigFlags.py @@ -39,7 +39,7 @@ def _createCfgFlags(): return [] rawCollections = [type_key[1] for type_key in GetFileMD(inputFile).get("itemList",[])] - collections = filter(lambda col: not col.endswith('Aux.'), rawCollections) + collections = [col for col in rawCollections if not col.endswith('Aux.') ] return collections acf.addFlag('Input.Collections', lambda prevFlags : _inputCollections(prevFlags.Input.Files) ) diff --git a/Reconstruction/Jet/JetRec/JetRec/JetGroomer.h b/Reconstruction/Jet/JetRec/JetRec/JetGroomer.h index 666bb45ff75369d989f0628a4e5e7f6959ef34ce..1804e52b4ecc0cb1ead91e584603a6190eb64fb6 100644 --- a/Reconstruction/Jet/JetRec/JetRec/JetGroomer.h +++ b/Reconstruction/Jet/JetRec/JetRec/JetGroomer.h @@ -29,13 +29,15 @@ #include "xAODJet/JetContainer.h" #include "xAODJet/JetAuxContainer.h" -class JetGroomer - : public asg::AsgTool, - virtual public JetProvider<xAOD::JetAuxContainer> -{ - ASG_TOOL_CLASS(JetGroomer, IJetProvider) - public: +namespace JetGrooming { + class JetGroomer + : public asg::AsgTool, + virtual public JetProvider<xAOD::JetAuxContainer> + { + ASG_TOOL_CLASS(JetGroomer, IJetProvider) + + public: using asg::AsgTool::AsgTool; virtual StatusCode initialize() override; @@ -46,17 +48,18 @@ class JetGroomer // Implementation of grooming goes here // The jet is inserted into the output container, which is necessary for speed // in the xAOD container paradigm - virtual void insertGroomedJet(const xAOD::Jet&, const PseudoJetContainer&, xAOD::JetContainer&, PseudoJetVector&) const = 0; + virtual void insertGroomedJet(const xAOD::Jet&, const PseudoJetContainer&, xAOD::JetContainer&, PseudoJetVector&) const = 0; protected: - /// Handle Input JetContainer (this contains the parent ungroomed jets to be trimmed) - SG::ReadHandleKey<xAOD::JetContainer> m_inputJetContainer {this, "UngroomedJets", "ungroomedinput", "Input ungroomed jet container"}; + /// Handle Input JetContainer (this contains the parent ungroomed jets to be trimmed) + SG::ReadHandleKey<xAOD::JetContainer> m_inputJetContainer {this, "UngroomedJets", "ungroomedinput", "Input ungroomed jet container"}; - /// This is the input to the parent JetContainer. It is needed in order to re-assign the ghost constituents from the final groomed PJ to the xAOD::Jet - SG::ReadHandleKey<PseudoJetContainer> m_inputPseudoJets {this, "ParentPseudoJets", "inputpseudojet", "input constituents of parent JetContainer"}; + /// This is the input to the parent JetContainer. It is needed in order to re-assign the ghost constituents from the final groomed PJ to the xAOD::Jet + SG::ReadHandleKey<PseudoJetContainer> m_inputPseudoJets {this, "ParentPseudoJets", "inputpseudojet", "input constituents of parent JetContainer"}; - SG::WriteHandleKey<PseudoJetVector> m_finalPseudoJets {this, "FinalPseudoJets_DONOTSET", "", "output pseudojets -- autoconfigured name"}; + SG::WriteHandleKey<PseudoJetVector> m_finalPseudoJets {this, "FinalPseudoJets_DONOTSET", "", "output pseudojets -- autoconfigured name"}; -}; + }; +} #endif diff --git a/Reconstruction/Jet/JetRec/Root/JetGroomer.cxx b/Reconstruction/Jet/JetRec/Root/JetGroomer.cxx index a54de07cdb9763f74dbe82e9beb8b747ea04eb21..a88efae8bf8dcc4cfe3b90e00121ae287e20bffd 100644 --- a/Reconstruction/Jet/JetRec/Root/JetGroomer.cxx +++ b/Reconstruction/Jet/JetRec/Root/JetGroomer.cxx @@ -10,11 +10,14 @@ using xAOD::JetContainer; -StatusCode JetGroomer::initialize() { +using namespace JetGrooming; + +StatusCode JetGroomer::initialize() { + ATH_MSG_DEBUG("Initializing..."); - if(m_inputJetContainer.empty()){ + if(m_inputJetContainer.empty()){ ATH_MSG_ERROR("Jet grooming requested with no input ungroomed jets"); return StatusCode::FAILURE; } else if(m_inputPseudoJets.empty()){ diff --git a/Reconstruction/Jet/JetRec/Root/JetRecursiveSoftDrop.cxx b/Reconstruction/Jet/JetRec/Root/JetRecursiveSoftDrop.cxx index 8cdefda0e2807bb64c9325d2a17366c27d42b129..f2b765dfd780b1a3c9889265d36aea625fada519 100644 --- a/Reconstruction/Jet/JetRec/Root/JetRecursiveSoftDrop.cxx +++ b/Reconstruction/Jet/JetRec/Root/JetRecursiveSoftDrop.cxx @@ -3,7 +3,6 @@ */ // JetRecursiveSoftDrop.cxx - #include "JetRec/JetRecursiveSoftDrop.h" #include <iomanip> #include "fastjet/PseudoJet.hh" diff --git a/Reconstruction/Jet/JetRec/Root/PseudoJetTranslator.cxx b/Reconstruction/Jet/JetRec/Root/PseudoJetTranslator.cxx index d5ae49d2096e4c0845a69add3e71b138fc58114f..99e9992994ff1c01fcdf8acfe80d03e719fe34c3 100644 --- a/Reconstruction/Jet/JetRec/Root/PseudoJetTranslator.cxx +++ b/Reconstruction/Jet/JetRec/Root/PseudoJetTranslator.cxx @@ -18,7 +18,7 @@ xAOD::Jet& PseudoJetTranslator::translate(const fastjet::PseudoJet& pj, // Record the jet-finding momentum, i.e. the one used to find/groom the jet. jet.setJetP4(xAOD::JetConstitScaleMomentum, jet.jetP4()); - + // save area if needed --------- if( pj.has_area() ){ @@ -45,13 +45,16 @@ xAOD::Jet& PseudoJetTranslator::translate(const fastjet::PseudoJet& pj, if ( parentCont == 0 ) { return jet ;} // can this happen? if so THIS IS an ERROR ! should do something ElementLink<xAOD::JetContainer> el(*parentCont, parent.index()); - jet.setAttribute("Parent", el); + static const SG::AuxElement::Accessor<ElementLink<xAOD::JetContainer> > parentELacc("Parent"); + parentELacc(jet) =el; jet.setInputType(parent.getInputType()); jet.setAlgorithmType(parent.getAlgorithmType()); jet.setSizeParameter(parent.getSizeParameter()); jet.setConstituentsSignalState(parent.getConstituentsSignalState()); - jet.setAttribute(xAOD::JetAttribute::JetGhostArea, parent.getAttribute<float>(xAOD::JetAttribute::JetGhostArea)); + float area=0; + if(parent.getAttribute(xAOD::JetAttribute::JetGhostArea, area)) jet.setAttribute(xAOD::JetAttribute::JetGhostArea, area); + return jet; } diff --git a/Reconstruction/Jet/JetRec/share/JetRecAlgTestCfg.py b/Reconstruction/Jet/JetRec/share/JetRecAlgTestCfg.py index 13c4c42a69c36b4ae4072b962577500eb63a017f..e34159e43cdbfdd052adae4455dd5deb665ef0da 100755 --- a/Reconstruction/Jet/JetRec/share/JetRecAlgTestCfg.py +++ b/Reconstruction/Jet/JetRec/share/JetRecAlgTestCfg.py @@ -162,7 +162,7 @@ def JetGroomAlgCfg(ConfigFlags,buildjetsname,groomjetsname): groomcfg.addSequence( CompFactory.AthSequencer(sequencename) ) # Create the JetGroomer, provide it with a JetTrimmer - jtrim = CompFactory.JetTrimming("trimSmallR2Frac5",RClus=0.2,PtFrac=0.05) + jtrim = CompFactory.getComp("JetGrooming::JetTrimming")("trimSmallR2Frac5",RClus=0.2,PtFrac=0.05) jtrim.UngroomedJets = buildjetsname jtrim.ParentPseudoJets = "PseudoJetMerged_"+buildjetsname diff --git a/Reconstruction/Jet/JetRec/src/JetSoftDropTools.cxx b/Reconstruction/Jet/JetRec/src/JetSoftDropTools.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6f6722ef86e5973168251dfc741e998a7ad2b03d --- /dev/null +++ b/Reconstruction/Jet/JetRec/src/JetSoftDropTools.cxx @@ -0,0 +1,140 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "JetSoftDropTools.h" + +#include "fastjet/PseudoJet.hh" +#include "fastjet/tools/Filter.hh" +#include "fastjet/contrib/SoftDrop.hh" +#include "fastjet/contrib/RecursiveSoftDrop.hh" +#include "fastjet/contrib/BottomUpSoftDrop.hh" +#include "fastjet/Selector.hh" + +#include "JetEDM/PseudoJetVector.h" + +#include "JetRec/PseudoJetTranslator.h" + +using namespace JetGrooming; + +namespace { + // tool implementing the operations to convert fastjet::PseudoJet -> xAOD::Jet + const static PseudoJetTranslator s_pjTranslator(false, false); // false => do not save jet areas + + + + /// A common helper to perform the creation and insertion of a groomed jet given a SoftDrop algorithm + template<typename SDHELPER> + xAOD::Jet & buildAndInsertSDJet(SDHELPER& sdhelper, const xAOD::Jet& parentjet, const PseudoJetContainer& inpjcont, xAOD::JetContainer& outcont, PseudoJetVector& groomedpjvec ){ + + const static SG::AuxElement::Accessor<const fastjet::PseudoJet*> s_pjAcc("PseudoJet"); + const static SG::AuxElement::ConstAccessor<const fastjet::PseudoJet*> s_pjConstAcc("PseudoJet"); + + // retrieve the PseudoJet from the parent : + const fastjet::PseudoJet& parentPJ = *s_pjConstAcc(parentjet); + + // call the sdhelper to build the groomed PSeudoJet + fastjet::PseudoJet groomedPJ = sdhelper(parentPJ); + + // build the xAOD::Jet from the PseudoJet, and put it in the container + xAOD::Jet& jet = s_pjTranslator.translate(groomedPJ, inpjcont, outcont, parentjet); + + // now assign the groomedPJ to its vector + // Note: the caller (JetGroomer) guarantees groomedpjvec has the correct size, + // however, it is not 100% sure (?) that parentjet.index()==jet.index(), so we can't assign before + groomedpjvec[jet.index()] = groomedPJ; + + // decorate with the pointer to the PJ we keep in the evt store. + // (the decoration is done in the PseudoJetTranslator but we have to redo-it here since we must point to + // the instance instance inside groomedpjvec) + s_pjAcc(jet) = & groomedpjvec[jet.index()]; + + return jet; + } +} + +// a shortcut to check variable range with a 1-liner (We can't use CheckedProperty...) +#define CHECK_VAR_RANGE( name, var, expr ) \ + if( ! ( expr ) ) { \ + ATH_MSG_ERROR("Property "<< name << " = "<< var << " out of range"); \ + return StatusCode::SUCCESS; } + +//********************************************************************** + +StatusCode SoftDrop::initialize() { + ATH_CHECK( JetGroomer::initialize() ); + + CHECK_VAR_RANGE("ZCut", m_zcut, (m_zcut>=0)&&(m_zcut<=10.) ); + CHECK_VAR_RANGE("beta", m_beta, (m_beta>=0)&&(m_beta<=10.) ); + CHECK_VAR_RANGE("R0", m_R0, (m_R0>=0)&&(m_R0<=10.) ); + + return StatusCode::SUCCESS; +} + + +//********************************************************************** +StatusCode RecSoftDrop::initialize() { + ATH_CHECK( SoftDrop::initialize() ); + CHECK_VAR_RANGE("N", m_N, (m_zcut>-1) ); + return StatusCode::SUCCESS; +} + + +void SoftDrop::insertGroomedJet(const xAOD::Jet& parentjet, const PseudoJetContainer& inpjcont, xAOD::JetContainer& outcont, PseudoJetVector& groomedpjvec) const { + + //configure soft drop tool + // see http://fastjet.hepforge.org/svn/contrib/contribs/RecursiveTools/tags/1.0.0/SoftDrop.hh + fastjet::contrib::SoftDrop softdropper(m_beta, m_zcut, m_R0); + + xAOD::Jet & jet = buildAndInsertSDJet(softdropper, + parentjet, inpjcont, outcont, groomedpjvec); + + if(m_saveSDatt) { + setSoftDropAttributes(jet, groomedpjvec[jet.index()].pieces().size() ); + } +} + +void SoftDrop::setSoftDropAttributes(xAOD::Jet& groomedjet, int nsdsubjets) const { + groomedjet.setAttribute<float>("ZCut", m_zcut); + groomedjet.setAttribute<float>("SoftDropBeta", m_beta); + groomedjet.setAttribute<float>("SoftDropR0", m_R0); + groomedjet.setAttribute<int>("NSoftDropSubjets", nsdsubjets); +} + + + + +//********************************************************************** + +void RecSoftDrop::insertGroomedJet(const xAOD::Jet& parentjet, const PseudoJetContainer& inpjcont, xAOD::JetContainer& outcont, PseudoJetVector& groomedpjvec) const { + + //configure recursive soft drop tool + //https://fastjet.hepforge.org/trac/browser/contrib/contribs/RecursiveTools/tags/2.0.0-beta1 + fastjet::contrib::RecursiveSoftDrop softdropper(m_beta, m_zcut, m_N, m_R0); + + xAOD::Jet & jet = buildAndInsertSDJet(softdropper, + parentjet, inpjcont, outcont, groomedpjvec); + + if(m_saveSDatt) { + setSoftDropAttributes(jet, groomedpjvec[jet.index()].pieces().size() ); + jet.setAttribute<int>("RSoftDropN", m_N); + } +} + + + +//********************************************************************** +void BottomUpSoftDrop::insertGroomedJet(const xAOD::Jet& parentjet, const PseudoJetContainer& inpjcont, xAOD::JetContainer& outcont, PseudoJetVector& groomedpjvec) const { + + //configure recursive soft drop tool + //https://fastjet.hepforge.org/trac/browser/contrib/contribs/RecursiveTools/tags/2.0.0-beta1 + fastjet::contrib::BottomUpSoftDrop softdropper(m_beta, m_zcut, m_R0); + + xAOD::Jet & jet = buildAndInsertSDJet(softdropper, + parentjet, inpjcont, outcont, groomedpjvec); + + if(m_saveSDatt) { + setSoftDropAttributes(jet, groomedpjvec[jet.index()].pieces().size() ); + } +} + diff --git a/Reconstruction/Jet/JetRec/src/JetSoftDropTools.h b/Reconstruction/Jet/JetRec/src/JetSoftDropTools.h new file mode 100644 index 0000000000000000000000000000000000000000..f3d600e40d4471a0442515bbca8ae3ebfa5238db --- /dev/null +++ b/Reconstruction/Jet/JetRec/src/JetSoftDropTools.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef JETREC_JETSOFDROPTOOLS_H +#define JETREC_JETSOFDROPTOOLS_H +///*********************************************** +/// +/// \file JetSoftDropTools +/// +/// Define jet grooming tools implementing variants of the soft drop algorithm +/// +/// These tools implement the IJetProvider interface via the JetGroomer base class. +/// The JetContainer thet returns is build by +/// running the trimming procedure on each jet of the parent JetContainer the tool is acting on. +/// Obviously the parent JetContainer must be present in the evt store, but also the input PseudoJetContainer from which it has been built. + +#include "fastjet/PseudoJet.hh" +#include "fastjet/tools/Filter.hh" + +#include "xAODJet/JetContainer.h" + +#include "JetInterface/IJetProvider.h" +#include "JetRec/JetGroomer.h" +#include "JetRec/PseudoJetContainer.h" + +namespace JetGrooming { + + /// \class SoftDrop + /// + /// A grooming tool implementing the SoftDrop method by wrapping fastjet::contrib::SoftDrop + /// Also serves as a base class for other SoftDrop variant. + class SoftDrop + : virtual public JetGroomer { + ASG_TOOL_CLASS(SoftDrop, IJetProvider) + + public: + using JetGroomer::JetGroomer; + + StatusCode initialize() override ; + + virtual void insertGroomedJet(const xAOD::Jet&, const PseudoJetContainer&, xAOD::JetContainer&, PseudoJetVector&) const override ; + + protected: + + void setSoftDropAttributes(xAOD::Jet& groomedjet, int nsdsubjets) const ; + + Gaudi::Property<float> m_zcut {this, "ZCut", 0.1 , "pT fraction for retaining subjets"}; + Gaudi::Property<float> m_beta {this, "Beta", 0.0, "How much to consider angular dependence"}; + Gaudi::Property<float> m_R0 {this, "R0", 1.0, "Normalization of angular distance, usually the characteristic jet radius (default R0 = 1)"}; + + Gaudi::Property<bool> m_saveSDatt {this, "SaveSoftDropAttributes",false, ""}; + + }; + + + + /// \class RecSoftDrop + /// + /// A specialized SoftDrop tool wrapping fastjet::contrib::RecursiveSoftDrop + class RecSoftDrop: public SoftDrop { + ASG_TOOL_CLASS0( RecSoftDrop ) + public: + using SoftDrop::SoftDrop;// + + StatusCode initialize() override final ; + + virtual void insertGroomedJet(const xAOD::Jet&, const PseudoJetContainer&, xAOD::JetContainer&, PseudoJetVector&) const override final ; + + private: + Gaudi::Property<int> m_N {this, "N", 0.1 , "Number of layers (-1 <> infinite)"}; + }; + + + + + + /// \class BottomUpSoftDrop + /// + /// A specialized SoftDrop tool wrapping fastjet::contrib::BottomUpSoftDrop + class BottomUpSoftDrop: virtual public SoftDrop { + ASG_TOOL_CLASS0(BottomUpSoftDrop) + public: + using SoftDrop::SoftDrop; + + virtual void insertGroomedJet(const xAOD::Jet&, const PseudoJetContainer&, xAOD::JetContainer&, PseudoJetVector&) const override final ; + }; + + + +} + + +#endif diff --git a/Reconstruction/Jet/JetRec/src/JetTrimming.cxx b/Reconstruction/Jet/JetRec/src/JetTrimming.cxx index 6379a4d8d0f6e41b49d2b966542f669eda932e13..7334813384db0aeb8d428f9b9b35868036b72a91 100644 --- a/Reconstruction/Jet/JetRec/src/JetTrimming.cxx +++ b/Reconstruction/Jet/JetRec/src/JetTrimming.cxx @@ -11,9 +11,12 @@ #include "JetRec/PseudoJetTranslator.h" +using namespace JetGrooming; +namespace { // tool implementing the operations to convert fastjet::PseudoJet -> xAOD::Jet -const static PseudoJetTranslator s_pjTranslator(false, false); // false => do not save jet areas + const static PseudoJetTranslator s_pjTranslator(false, false); // false => do not save jet areas +} //********************************************************************** @@ -49,7 +52,7 @@ StatusCode JetTrimming::initialize() { //********************************************************************** void JetTrimming::insertGroomedJet(const xAOD::Jet& parentjet, const PseudoJetContainer& inpjcont, xAOD::JetContainer& outcont, PseudoJetVector& trimpjvec) const { - + const static SG::AuxElement::Accessor<const fastjet::PseudoJet*> s_pjAcc("PseudoJet"); const static SG::AuxElement::ConstAccessor<const fastjet::PseudoJet*> s_pjConstAcc("PseudoJet"); @@ -69,7 +72,7 @@ void JetTrimming::insertGroomedJet(const xAOD::Jet& parentjet, const PseudoJetCo // decorate with the pointer to the PJ we keep in the evt store. s_pjAcc(jet) = & trimpjvec[jet.index()]; - + int nptrim = trimmedPJ.pieces().size(); jet.setAttribute<int>(xAOD::JetAttribute::TransformType, xAOD::JetTransform::Trim); jet.setAttribute<int>(xAOD::JetAttribute::NTrimSubjets, nptrim); diff --git a/Reconstruction/Jet/JetRec/src/JetTrimming.h b/Reconstruction/Jet/JetRec/src/JetTrimming.h index 4302969abe17fc70af7f247b3efafc6493f26855..2953fdb3d861d4923340d512ee3b488fec4ece75 100644 --- a/Reconstruction/Jet/JetRec/src/JetTrimming.h +++ b/Reconstruction/Jet/JetRec/src/JetTrimming.h @@ -24,27 +24,28 @@ #include "JetRec/JetGroomer.h" #include "JetRec/PseudoJetContainer.h" -class JetTrimming -: virtual public JetGroomer { - ASG_TOOL_CLASS(JetTrimming, IJetProvider) +namespace JetGrooming { + class JetTrimming + : virtual public JetGroomer { + ASG_TOOL_CLASS(JetTrimming, IJetProvider) -public: + public: - using JetGroomer::JetGroomer; + using JetGroomer::JetGroomer; - StatusCode initialize() override final; + StatusCode initialize() override final; - virtual void insertGroomedJet(const xAOD::Jet&, const PseudoJetContainer&, xAOD::JetContainer&, PseudoJetVector&) const override final; + virtual void insertGroomedJet(const xAOD::Jet&, const PseudoJetContainer&, xAOD::JetContainer&, PseudoJetVector&) const override final; -private: + private: - // The filter object that will apply the grooming - std::unique_ptr<fastjet::Filter> m_trimmer; + // The filter object that will apply the grooming + std::unique_ptr<fastjet::Filter> m_trimmer; - // Job options. - Gaudi::Property<float> m_rclus {this, "RClus", 0.3 , "R for reclustering (0 for none)"}; - Gaudi::Property<float> m_ptfrac {this, "PtFrac", 0.03, "pT fraction for retaining subjets"}; - -}; + // Job options. + Gaudi::Property<float> m_rclus {this, "RClus", 0.3 , "R for reclustering (0 for none)"}; + Gaudi::Property<float> m_ptfrac {this, "PtFrac", 0.03, "pT fraction for retaining subjets"}; + }; +} #endif diff --git a/Reconstruction/Jet/JetRec/src/components/JetRec_entries.cxx b/Reconstruction/Jet/JetRec/src/components/JetRec_entries.cxx index ace4fc6f397d107f577d71c9fad87e3b8ee104e6..5a6d67f97048dc883d1928fba859165d9e9844d7 100644 --- a/Reconstruction/Jet/JetRec/src/components/JetRec_entries.cxx +++ b/Reconstruction/Jet/JetRec/src/components/JetRec_entries.cxx @@ -2,6 +2,7 @@ #include "../JetRecAlg.h" #include "../JetViewAlg.h" #include "../JetTrimming.h" +#include "../JetSoftDropTools.h" #include "../PseudoJetMerger.h" #include "../PseudoJetAlgorithm.h" @@ -61,4 +62,7 @@ DECLARE_COMPONENT( JetViewAlg ) DECLARE_COMPONENT( PseudoJetAlgorithm ) DECLARE_COMPONENT( MuonSegmentPseudoJetAlgorithm ) -DECLARE_COMPONENT( JetTrimming ) +DECLARE_COMPONENT( JetGrooming::JetTrimming ) +DECLARE_COMPONENT( JetGrooming::SoftDrop ) +DECLARE_COMPONENT( JetGrooming::RecSoftDrop ) +DECLARE_COMPONENT( JetGrooming::BottomUpSoftDrop ) diff --git a/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py b/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py index 51d695fa1619661287c81a3139e6b4e542a43582..b822f2737b9b2d455b18a52e31ae97fecdd64b16 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py @@ -105,6 +105,7 @@ class JetDefinition(object): # used internally to resolve dependencies self._prereqDic = {} self._prereqOrder = [] + self._internalAtt = {} self._locked = lock @@ -147,19 +148,9 @@ class JetDefinition(object): @make_lproperty def prefix(self): pass - @prefix.lsetter - def prefix(self,p): - self._prefix = p - self._defineName() - @make_lproperty def suffix(self): pass - @suffix.lsetter - def suffix(self,p): - self._suffix = p - self._defineName() - @make_lproperty def basename(self): pass @@ -367,11 +358,6 @@ class JetInputDef(object): # make outputname an alias of name so JetInputDef shares an interface with JetConstitSeq. outputname = make_alias("name") - # @make_lproperty - # def outputname(self): pass - # @outputname.setter - # def outputname(self,v): - # raise Exception("Can not set the 'outputname' attribute of a JetInputDef, set its 'name' instead") ######################################################################## diff --git a/Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py index b12202360b7bc2ec715635f66874f1b7303c79d9..f0b136b329ae07ec36d1ff104c267d34cf7a8321 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py @@ -1,22 +1,19 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +""" +JetGroomConfig: A helper module for configuring jet grooming +Author: TJ Khoo, P-A Delsart +""" -######################################################################## -# # -# JetGroomConfig: A helper module for configuring jet grooming # -# Author: TJ Khoo # -# # ######################################################################## from AthenaCommon import Logging jetlog = Logging.logging.getLogger('JetGroomConfig') -from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory import JetRecConfig.JetModConfig as modH -from JetRecConfig.JetRecConfig import instantiateAliases, buildJetModifierList +from JetRecConfig.JetRecConfig import buildJetModifierList, addJetClusteringToComponent, JetRecCfg -import six def instantiateGroomingAliases( groomdef ): @@ -27,85 +24,111 @@ def instantiateGroomingAliases( groomdef ): * assumes jetdef is not 'locked' * implies calls to recursives function constH.aliasToInputDef and modH.aliasToModDef """ - - instantiateAliases(groomdef.ungroomeddef) for mod in groomdef.modifiers: modInstance = modH.aliasToModDef(mod, groomdef) groomdef._prereqDic['mod:'+mod] = modInstance groomdef._prereqOrder.append('mod:'+mod) - + ######################################################################## -# Get a jet groomer class given a tool name and the grooming definition object -# The pjsin argument is for forwards compatibility when we switch to -# using JetRecAlg # -def getJetGroomer(groomdef,pjsin): - tooltype = groomdef.groomspec["ToolType"] - toolprops = {key:val for key,val in six.iteritems (groomdef.groomspec) if key not in ["groomalg","ToolType"]} - return tooltype(groomdef.basename,**toolprops) +def getJetGroomAlg(groomdef,monTool=None): + """Returns a configured JetRecAlg set-up to perform the grooming defined by 'groomdef' + ('monTool' is a temporary placeholder, it is expected to be used in the trigger in the future) + """ + jetlog.debug("Configuring grooming alg \"jetalg_{0}\"".format(groomdef.fullname())) -######################################################################## -# Function for configuring the jet algorithm and groomers, given the -# set of dependencies -# -def getJetGroomAlg(jetname,groomdef,pjsin,monTool=None): - jetlog.debug("Configuring JetAlgorithm \"jetalg_{0}\"".format(jetname)) + # the grooming tool (a IJetProvider instance) + groomClass = CompFactory.getComp(groomdef.tooltype) + groomer = groomClass(groomdef.groomalg, + UngroomedJets = groomdef.ungroomeddef.fullname(), + ParentPseudoJets = groomdef.ungroomeddef._internalAtt['finalPJContainer'], + **groomdef.properties) + # get JetModifier list + mods = buildJetModifierList(groomdef) + # put everything together in a JetRecAlg + jetname = groomdef.fullname() + jra = CompFactory.JetRecAlg( + "jetrecalg_"+jetname, + Provider = groomer, + Modifiers = mods, + OutputContainer = jetname) + + + from JetRecConfig.JetRecConfig import autoconfigureModifiers + autoconfigureModifiers(jra.Modifiers, jetname) + + return jra + +def getJetGroomAlg_jetAlg(groomdef,pjsin,monTool=None): + """Returns a configured grooming algs based on the old JetAlgorithm + + We keep this function for compatibility with trigger config. When the trigger switches to JetRecAlg, this can be removed. + """ + jetname = groomdef.fullname() + jetlog.debug("Configuring JetAlgorithm \"jetalg_{0}\"".format(jetname)) + from . import JetRecConfig builder = JetRecConfig.getJetBuilder() - groomer = getJetGroomer(groomdef,pjsin) - groomer.JetBuilder = builder + groomClass = CompFactory.getComp(groomdef.tooltype) + groomer = groomClass(groomdef.groomalg, + JetBuilder = builder, + **groomdef.properties) + + mods = buildJetModifierList(groomdef) - + rectool = CompFactory.JetRecTool(jetname, JetGroomer=groomer, InputContainer=groomdef.ungroomeddef.fullname(), OutputContainer=jetname, JetPseudojetRetriever=CompFactory.JetPseudojetRetriever("jpjretriever"), JetModifiers=mods) - + if monTool: rectool.MonTool = monTool - + jetalg = CompFactory.JetAlgorithm("jetalg_"+jetname) jetalg.Tools = [rectool] - return jetalg -######################################################################## -# Top-level function for running jet grooming -# Will first run the jet finder, unless the input jets are -# found in the input file -def JetGroomCfg(groomdef, configFlags, jetnameprefix="",jetnamesuffix=""): - jetsfullname = jetnameprefix+groomdef.basename+jetnamesuffix+"Jets" - jetlog.info("Setting up to find {0}".format(jetsfullname)) - - sequencename = jetsfullname - - components = ComponentAccumulator() - from AthenaCommon.AlgSequence import AthSequencer - components.addSequence( AthSequencer(sequencename) ) - - # Check if the ungroomed jets exist in the input file. - # If not, we need to configure their reconstruction. - filecontents = configFlags.Input.Collections - if groomdef.ungroomedname not in filecontents: - from . import JetRecCfg - components.merge(JetRecCfg(groomdef.ungroomeddef, configFlags, - jetnameoverride=groomdef.ungroomedname)) - else: - # FIXME: Need to schedule rebuilding of pseudojets - pass - - # FIXME: Add calls to JetModConfig.getFinalModifierListAndPrereqs - components.addEventAlgo(getJetGroomAlg(jetsfullname,groomdef,groomdef.modifiers)) +def addGroomToComponent(components,groomdef, configFlags, ): + """Instantiate and schedule all the algorithms needed to run the grooming alg 'groomdef' and + add them in the ComponentAccumulator 'components' + + This function is meant to be called from the top-level JetRecConfig.JetRecCfg + (groomdef is expected to be non locked and will be modified). + """ + sequenceName = groomdef.fullname() + + # Translate modifier aliases into JetModifier config instances. + # ( This also detects input dependencies, see below) + instantiateGroomingAliases(groomdef) + + # Transfer the input & ghost dependencies onto the parent jet alg, + # so they are handled when instatiating the parent jet algs + groomdef.ungroomeddef.ghostdefs += [ g.split(':')[1] for g in groomdef._prereqOrder if g.startswith('ghost:')] + groomdef.ungroomeddef.extrainputs += [ g.split(':')[1] for g in groomdef._prereqOrder if g.startswith('input:')] + + jetlog.info("Scheduling parent alg {} for {} ".format(groomdef.ungroomeddef.fullname(), groomdef.fullname())) + # now instantiate the parent jet alg. + # (we always want it even if the parent jets are already in the input file because + # we need to rebuild the pseudoJet) + addJetClusteringToComponent(components, groomdef.ungroomeddef, configFlags, sequenceName) + + groomalg = getJetGroomAlg(groomdef) + + components.addEventAlgo(groomalg, sequenceName) + + jetlog.info("Scheduled JetAlgorithm instance \"jetalg_{0}\"".format(groomdef.fullname())) return components + if __name__=="__main__": # Setting needed for the ComponentAccumulator to do its thing @@ -132,7 +155,7 @@ if __name__=="__main__": from JetGrooming import JetTrimming AntiKt10LCTopo.ptminfilter = 100e3 AntiKt10LCTopoTrimmedPtFrac5SmallR20 = JetTrimming(AntiKt10LCTopo,"AntiKt10LCTopoJets",smallR=0.2,ptfrac=0.05) - cfg.merge(JetGroomCfg(AntiKt10LCTopoTrimmedPtFrac5SmallR20,ConfigFlags)) + cfg.merge(JetRecCfg(AntiKt10LCTopoTrimmedPtFrac5SmallR20,ConfigFlags)) cfg.printConfig(withDetails=False,summariseProps=True) diff --git a/Reconstruction/Jet/JetRecConfig/python/JetGrooming.py b/Reconstruction/Jet/JetRecConfig/python/JetGrooming.py index 2d5aa6bdd27811a8fd06a2edd9ca5470f32421a1..1fcf23fcc4d13b736afcf14b11a90a6a57d21b03 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetGrooming.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetGrooming.py @@ -1,43 +1,45 @@ -# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration - -######################################################################## -# # -# JetGrooming: A module for classes encoding definitions of objects # -# for configuring jet grooming # -# Author: TJ Khoo # -# # -######################################################################## +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +""" +JetGrooming: A module for classes encoding definitions of objects +for configuring jet grooming +Author: TJ Khoo. P-A Delsart +""" __all__ = ["GroomingDefinition","JetTrimming","JetSoftDrop"] from AthenaCommon import Logging -from .Utilities import make_lproperty, onlyAttributesAreProperties, clonable +from .Utilities import make_lproperty, onlyAttributesAreProperties, clonable, ldict jetlog = Logging.logging.getLogger('JetGrooming') @clonable @onlyAttributesAreProperties class GroomingDefinition(object): + """ Base class to define grooming procedure. + Concrete classes will have to define the tooltype & groomalg class members + and aslo a groomSpecAsStr() function. + + """ + tooltype = None + groomalg = None def __init__(self, ungroomeddef, # Ungroomed JetDefinition - #ungroomedname, # Input collection name (cannot be determined uniquely from inputdef) - groomspec, # Dict describing the grooming settings modifiers=[], # JetModifiers to run after grooming - lock=False, + suffix = '', # allows to tune the full JetContainer name + lock=False, # lock the properties of this instance to avoid accidental overwrite after __init__ + **properties # any other argument is expected a grooming tool property ): - #self.ungroomedname = ungroomedname + self._ungroomeddef = ungroomeddef.clone() # clone to avoid messing with external jetdef - # Dedicated setter/getter - self._ungroomeddef = ungroomeddef.clone() # to avoid messing with external jetdef - self._groomspec = groomspec - - self._checkGroomSpec(groomspec) - self._groomspec = groomspec + if lock: properties = ldict(properties) # ldict to freeze the properties + self.properties = properties + self.suffix = suffix self._defineName() - self.modifiers = modifiers # Tools to modify the jet - + self.modifiers = modifiers + + # used internally to resolve dependencies self._prereqDic = {} self._prereqOrder = [] @@ -64,42 +66,21 @@ class GroomingDefinition(object): self._defineName() + @make_lproperty + def properties(self): pass @make_lproperty def modifiers(self): pass - @make_lproperty - def groomspec(self): - return self.__groomspec - @groomspec.lsetter - def groomspec(self,groomspec): - self._checkGroomSpec(groomspec) - self._groomspec = groomspec - self._defineName() - - # To override in derived classes + def suffix(self): pass + + # To be overriden in derived classes def groomSpecAsStr(self): - return "Groomed" + raise Exception("Can not use a GroomingDefinition instance : use a derived class") def fullname(self): - return self.ungroomeddef.prefix+self.basename+"Jets" + return self.ungroomeddef.prefix+self.basename+"Jets"+self.suffix - def _checkGroomSpec(self,groomspec): - # Check if options are supported (implemented) - groomalg = groomspec["groomalg"] - supportedGrooming = ["Trim","SoftDrop"] - if not groomspec["groomalg"] in supportedGrooming: - jetlog.error("Unsupported grooming algorithm specification \"{}\"! Allowable options:") - for groomalg in supportedGrooming: - jetlog.error(groomalg) - raise KeyError("Invalid grooming algorithm choice: {0}".format(groomalg)) - # @property - # def inputdef(self): - # return self.__inputdef - # @inputdef.setter - # def inputdef(self,inputdef): - # self.__inputdef = inputdef - # self._defineName() def _defineName(self): @@ -114,76 +95,34 @@ class GroomingDefinition(object): __repr__ = __str__ -@clonable -@onlyAttributesAreProperties class JetTrimming(GroomingDefinition): - def __init__(self, - ungroomeddef, # Ungroomed JetDefinition - #ungroomedname, # Input collection name (cannot be determined uniquely from inputdef) - smallR, # Subjet radius - ptfrac, # Minimum subjet pt fraction - modifiers=[], # JetModifiers to run after grooming - lock=False, - ): - - # Apart from groomalg and ToolType, these correspond to the - # grooming tool property values - #from JetRec.JetRecConf import JetTrimmer - from AthenaConfiguration.ComponentFactory import CompFactory - JetTrimmer = CompFactory.JetTrimmer - groomspec = { - # Type of groomer - "groomalg": "Trim", - # Configurable class - "ToolType": JetTrimmer, - # Tool properties to set - "RClus": smallR, - "PtFrac": ptfrac, - } - - super(JetTrimming,self).__init__(ungroomeddef,groomspec,modifiers,lock=lock,finalinit=False) + groomalg = "Trim" + tooltype = "JetGrooming::JetTrimming" def groomSpecAsStr(self): - ptfrac = self.groomspec["PtFrac"] - ptfracstr = int(ptfrac*100) # Not usually smaller than % - smallR = self.groomspec["RClus"] + ptfrac = int( self.properties["PtFrac"] *100 ) # Not usually smaller than % from .JetDefinition import formatRvalue - smallRstr = formatRvalue(smallR*10) + smallR = formatRvalue(self.properties["RClus"]*10) - groomstr = "TrimmedPtFrac{}SmallR{}".format(ptfracstr,smallRstr) + groomstr = "TrimmedPtFrac{}SmallR{}".format(ptfrac,smallR) return groomstr -@clonable -@onlyAttributesAreProperties +class JetTrimmingTrig(JetTrimming): + """Temporary class for trigger (to be removed when jet trigger use JetRecAlg)""" + tooltype = "JetTrimmer" + + class JetSoftDrop(GroomingDefinition): - def __init__(self, - ungroomeddef, # Ungroomed JetDefinition - #ungroomedname, # Input collection name (cannot be determined uniquely from inputdef) - zcut, # ZCut - beta, # Beta - modifiers=[], # JetModifiers to run after grooming - lock=False): - - # Apart from groomalg and ToolType, these correspond to the - # grooming tool property values - from AthenaConfiguration.ComponentFactory import CompFactory - JetSD = CompFactory.JetSoftDrop - groomspec = { - # Type of groomer - "groomalg": "SoftDrop", - # Configurable class - "ToolType": JetSD, - # Tool properties to set - "ZCut": zcut, - "Beta": beta, - } - - super(JetSoftDrop,self).__init__(ungroomeddef,groomspec,modifiers, lock=lock, finalinit=False) + groomalg = "SoftDrop" + tooltype = "JetGrooming::SoftDrop" def groomSpecAsStr(self): - beta = self.groomspec["Beta"] - betastr = int(beta*100) - zcut = self.groomspec["ZCut"] - zcutstr = int(zcut*100) - groomstr = "SoftDropBeta{}Zcut{}".format(betastr,zcutstr) + beta = int( self.properties["Beta"] *100) + zcut = int( self.properties["ZCut"] *100) + groomstr = "SoftDropBeta{}Zcut{}".format(beta,zcut) return groomstr + +class JetSoftDropTrig(JetSoftDrop): + """Temporary class for trigger (to be removed when jet trigger use JetRecAlg)""" + tooltype = "JetSoftDrop" + diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py index 29dc80eced2ed8e188ea207134ee96bae0ebc839..e71c285f072130f3f6215480118aff09814ff11e 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py @@ -18,6 +18,9 @@ from AthenaConfiguration.ComponentFactory import CompFactory import JetRecConfig.ConstModHelpers as constH import JetRecConfig.JetModConfig as modH +from JetRecConfig.JetDefinition import JetDefinition +from JetRecConfig.JetGrooming import GroomingDefinition + @@ -26,78 +29,96 @@ __all__ = ["JetRecCfg", "JetInputCfg"] ######################################################################## + + +def JetRecCfg(jetdef, configFlags): + """Top-level function for running jet finding or grooming. -def JetRecCfg(jetdef0, configFlags): - """Top-level function for running jet finding - (i.e. clustering from inputs) This returns a ComponentAccumulator that can be merged with others from elsewhere in the job, but will provide everything needed to reconstruct one jet collection. - This could still be modularised further into the subcomponents of the - jet reconstruction job. - Receives the jet definition and input flags, mainly for input file + Receives the jet or grooming definition (jetdef) and input flags (configFlags), mainly for input file peeking such that we don't attempt to reproduce stuff that's already - in the input file + in the input file. + """ # we clone the jetdef, so we're sure we're not using a 'locked' one - jetdef = jetdef0.clone() + jetdef_i = jetdef.clone() - jetsfullname = jetdef.fullname() - jetlog.info("Setting up to find {0}".format(jetsfullname)) - - sequenceName = jetsfullname + sequenceName = jetdef_i.fullname() + jetlog.info("******************") + jetlog.info("Setting up to find {0}".format(sequenceName)) components = ComponentAccumulator() from AthenaCommon.CFElements import parOR components.addSequence( parOR(sequenceName) ) - # create proper config instances for each input and ghost aliases in this jetdef + # call the relevant function according to jetdef_i type + if isinstance(jetdef_i, JetDefinition): + addJetClusteringToComponent(components, jetdef_i, configFlags) + + elif isinstance(jetdef_i, GroomingDefinition): + from JetRecConfig.JetGroomConfig import addGroomToComponent + addGroomToComponent(components, jetdef_i, configFlags) + + return components + +def addJetClusteringToComponent(components, jetdef_i, configFlags, sequenceName=None): + """internal function which instantiates the JetRecAlg defined by the JetDefinition 'jetdef_i' + into the ComponentAccumulator 'components' + """ + sequenceName = sequenceName or jetdef_i.fullname() + # create proper config instances for each input and ghost aliases in this jetdef_i # this implicitely calculates and adds the dependencies. - instantiateAliases(jetdef) + instantiateAliases(jetdef_i) - # check if the conditions are compatible with the inputs & modifiers of this jetdef. + # check if the conditions are compatible with the inputs & modifiers of this jetdef_i. # if in standardRecoMode we will remove whatever is incompatible and still try to run # if not, we raise an exception - removeComponentFailingConditions(jetdef, configFlags, raiseOnFailure= not jetdef.standardRecoMode) + removeComponentFailingConditions(jetdef_i, configFlags, raiseOnFailure= not jetdef_i.standardRecoMode) # Schedule the various input collections. # We don't have to worry about ordering, as the scheduler # will handle the details. Just merge the components. - inputcomps = JetInputCfg(jetdef, configFlags, sequenceName) + inputcomps = JetInputCfg(jetdef_i, configFlags, sequenceName) components.merge(inputcomps) # schedule the algs to create fastjet::PseudoJet objects out of the inputs - pjCompo, pjContainer = PseudoJetCfg(jetdef, configFlags, sequenceName) + pjCompo= PseudoJetCfg(jetdef_i, configFlags, sequenceName) components.merge(pjCompo) # Generate a JetRecAlg to run the jet finding and modifiers - jetrecalg = getJetRecAlg( jetdef, pjContainer) + jetrecalg = getJetRecAlg( jetdef_i) components.addEventAlgo(jetrecalg, sequenceName) - jetlog.info("Scheduled JetAlgorithm instance \"jetalg_{0}\"".format(jetsfullname)) + jetlog.info("Scheduled JetAlgorithm instance \"jetalg_{0}\"".format(jetdef_i.fullname())) + return components -def PseudoJetCfg(jetdef, configFlags, sequenceName): - """Builds a ComponentAccumulator for creating PseudoJetContainer needed by jetdef. - IMPORTANT returns a tuple : (components, finalPJContainerName) """ + +def buildPseudoJetAlgs(jetdef): + """ Builds the list of configured PseudoJetAlgorithm needed for this jetdef. + THIS updates jetdef._internalAtt['finalPJContainer'] + (this function is factorized out of PseudoJetCfg so it can be used standalone in the trigger config) + """ - components = ComponentAccumulator(sequenceName) - # Schedule the constituent PseudoJetAlg constitpjalg = getConstitPJGAlg( jetdef.inputdef ) - components.addEventAlgo( constitpjalg, sequenceName ) finalPJContainer = constitpjalg.OutputContainer + pjalglist = [constitpjalg] # Schedule the ghost PseudoJetAlgs ghostlist = [ key for key in jetdef._prereqOrder if key.startswith('ghost:')] if ghostlist != []: + # then we need to schedule a PseudoJetAlg for each ghost collections... pjContNames = [finalPJContainer] for ghostkey in sorted(ghostlist): ghostdef = jetdef._prereqDic[ghostkey] ghostpjalg = getGhostPJGAlg( ghostdef ) - components.addEventAlgo( ghostpjalg, sequenceName ) + pjalglist.append(ghostpjalg) pjContNames.append( ghostpjalg.OutputContainer ) + # .. and merge them together with the input constituents mergeId = mergedPJId( pjContNames ) finalPJContainer = constitpjalg.OutputContainer+"_merged"+mergeId mergerName = "PJMerger_id"+mergeId @@ -106,12 +127,25 @@ def PseudoJetCfg(jetdef, configFlags, sequenceName): InputPJContainers = pjContNames, OutputContainer = finalPJContainer, ) - components.addEventAlgo( mergeAlg, sequenceName) - - return components, finalPJContainer + pjalglist.append(mergeAlg) + + # set the name of the complete,merged input PseudoJets, so it can be re-used downstream + jetdef._internalAtt['finalPJContainer'] = finalPJContainer + return pjalglist + +def PseudoJetCfg(jetdef, configFlags, sequenceName): + """Builds a ComponentAccumulator for creating PseudoJetContainer needed by jetdef. + THIS updates jetdef._internalAtt['finalPJContainer'] + """ + components = ComponentAccumulator(sequenceName) + pjalglist = buildPseudoJetAlgs( jetdef ) + for pjalg in pjalglist: + components.addEventAlgo( pjalg, sequenceName ) + return components _mergedPJContainers = dict() def mergedPJId(pjList): + """returns a simple unique ID for the list of PseudoJet container in pjList""" t = tuple(pjList) currentSize = len(_mergedPJContainers) return str(_mergedPJContainers.setdefault(t, currentSize)) @@ -129,12 +163,12 @@ def JetInputCfg(jetOrConstitdef, configFlags, sequenceName='AthAlgSeq'): * a JetConstitSource : to allow scheduling the corresponding constituents algs independently of any jet alg. """ - jetlog.info("Setting up jet inputs.") components = ComponentAccumulator(sequenceName) from .JetDefinition import JetConstitSource, JetDefinition if isinstance(jetOrConstitdef, JetConstitSource): + jetlog.info("Setting up jet inputs from JetConstitSource : "+jetOrConstitdef.name) jetdef = JetDefinition('Kt', 0., jetOrConstitdef.clone()) instantiateAliases(jetdef) removeComponentFailingConditions(jetdef, configFlags, raiseOnFailure= not jetdef.standardRecoMode) @@ -142,7 +176,7 @@ def JetInputCfg(jetOrConstitdef, configFlags, sequenceName='AthAlgSeq'): jetdef = jetOrConstitdef jetlog.info("Inspecting input file contents") - filecontents = [coll for coll in configFlags.Input.Collections] + filecontents = configFlags.Input.Collections inputdeps = [ inputkey for inputkey in jetdef._prereqOrder if inputkey.startswith('input:')] @@ -162,7 +196,7 @@ def JetInputCfg(jetOrConstitdef, configFlags, sequenceName='AthAlgSeq'): if constitalg: components.addEventAlgo(constitalg, primary=isprimary) else: # it must be a JetInputDef - cname = inputInstance.containername(jetdef,inputInstance.specs) + cname = inputInstance.containername(jetdef,inputInstance.specs) # (by defaults this is just inputInstance.name) if cname in filecontents: jetlog.debug("Input container {0} for prereq {1} already in input file.".format(cname, inputInstance.name)) else: @@ -257,15 +291,16 @@ def getJetAlgorithm(jetname, jetdef, pjContNames, monTool = None): ######################################################################## # Function that substitues JetRecTool + JetAlgorithm # -def getJetRecAlg( jetdef, pjContNames): +def getJetRecAlg( jetdef): """ """ + pjContNames = jetdef._internalAtt['finalPJContainer'] jclust = CompFactory.JetClusterer( "builder", JetAlgorithm = jetdef.algorithm, JetRadius = jetdef.radius, PtMin = jetdef.ptmin, InputPseudoJets = pjContNames, - GhostArea = 0.01, # In which cases do we not want areas? + GhostArea = 0.01 if (jetdef.radius < 0.6) else 0. , JetInputType = jetdef.inputdef.jetinputtype, ) @@ -389,7 +424,6 @@ def removeComponentFailingConditions(jetdef, configflags, raiseOnFailure=True): The compatibility is ultimately tested using the component 'filterfn' attributes. Internally calls the function isComponentPassingConditions() (see below) """ - jetlog.info("******************") jetlog.info("Standard Reco mode : filtering components in "+str(jetdef)) diff --git a/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py b/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py index c2ec26f1a0212a0d18d1363e3167c86a8e1f5fe6..8d5b473b6506259abc029bccc54abdb636fe4a2a 100644 --- a/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py +++ b/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py @@ -116,5 +116,40 @@ particlejetmods = { } jetmoddict.update(particlejetmods) -# Todo: jet substructure moment tools +# Substructure tools + +substrmods = dict( + nsubjettiness = JetModifier( "NSubjettinessTool", "nsubjettiness",Alpha = 1.0), + nsubjettinessR = JetModifier( "NSubjettinessRatiosTool", "nsubjettinessR",), + + + ktdr = JetModifier("KtDeltaRTool", "ktdr", JetRadius = 0.4), + + ktsplitter = JetModifier( "KTSplittingScaleTool", "ktsplitter"), + + angularity = JetModifier( "AngularityTool", "angularity"), + + dipolarity = JetModifier( "DipolarityTool", "dipolarity",SubJetRadius = 0.3), + + planarflow = JetModifier( "PlanarFlowTool", "planarflow"), + + ktmassdrop = JetModifier( "KtMassDropTool", "ktmassdrop"), + + ecorr = JetModifier( "EnergyCorrelatorTool", "ecorr", Beta = 1.0), + ecorrR = JetModifier( "EnergyCorrelatorRatiosTool", "ecorrR", ), + + ecorrgeneral = JetModifier( "EnergyCorrelatorGeneralizedTool", "ecorrgeneral"), + + ecorrgeneralratios = JetModifier( "EnergyCorrelatorGeneralizedRatiosTool", "ecorrgeneralratios"), + + comshapes = JetModifier( "CenterOfMassShapesTool","comshapes"), + + pull = JetModifier("JetPullTool", "pull", UseEtaInsteadOfY = False, IncludeTensorMoments = True ), + + charge = JetModifier( "JetChargeTool", "charge", K=1.0), + + qw = JetModifier( "QwTool", "qw"), + #showerdec = JetModifier( " ShowerDeconstructionTool"), +) +jetmoddict.update(substrmods) diff --git a/Reconstruction/Jet/JetRecConfig/python/StandardLargeRJets.py b/Reconstruction/Jet/JetRecConfig/python/StandardLargeRJets.py new file mode 100644 index 0000000000000000000000000000000000000000..8b8549d6d66d2c27a4ec51e07a3ae23a5500c141 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/StandardLargeRJets.py @@ -0,0 +1,91 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +from JetRecConfig.StandardJetConstits import jetconstitdic as cst +from .JetDefinition import JetDefinition +from .JetGrooming import JetTrimming, JetSoftDrop + + + +# ********************************************************* +# Ghost-associated particles for the standard large R jets +# ********************************************************* +standardghosts = ["Track","MuonSegment","Truth"] + + +flavourghosts = [ + "WBosons", "ZBosons", "HBosons", "TQuarksFinal", + "Partons",] + + + + + +# ********************************************************* +# Modifiers for the standard large R jets +# ********************************************************* +# (use tuples rather than lists to prevent accidental modification) +standardrecomods = ( + "Sort", + "Width", + "TrackMoments", +) +clustermods = ("ECPSFrac","ClusterMoments",) +truthmods = ("PartonTruthLabel","TruthPartonDR", ) +pflowmods = () + +substrmods = ("nsubjettiness", "nsubjettinessR", "ktsplitter", + "ecorr", "ecorrR", "qw", + # ... others ? +) + + +# ********************************************************* +# Standard large R jets definitions +# ********************************************************* + + +AntiKt10LCTopo = JetDefinition("AntiKt",1.0,cst.LCTopoOrigin, + ghostdefs = standardghosts+flavourghosts , + modifiers = ("Sort", "Filter:50000"), + standardRecoMode = True, + lock = True +) + + +AntiKt10LCTopoTrimmed = JetTrimming(AntiKt10LCTopo, + modifiers = standardrecomods+substrmods, + PtFrac = 0.05, RClus = 0.2, + ) + +AntiKt10LCTopoSoftDrop = JetSoftDrop(AntiKt10LCTopo, + modifiers = standardrecomods+substrmods, + Beta = 1., ZCut= 0.1, + ) + + + + +AntiKt10Truth = JetDefinition("AntiKt",1.0,cst.Truth, + ghostdefs = flavourghosts , + modifiers = ("Sort", "Filter:50000"), + standardRecoMode = True, + lock = True +) + + +AntiKt10TruthTrimmed = JetTrimming(AntiKt10Truth, + modifiers = standardrecomods+substrmods+truthmods, + PtFrac = 0.05, RClus = 0.2, + ) + +AntiKt10TruthSoftDrop = JetSoftDrop(AntiKt10Truth, + modifiers = standardrecomods+substrmods+truthmods, + Beta = 1., ZCut= 0.1, + ) + + + + + + + diff --git a/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py b/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py index af23c0a965e81e4c9ad39da9700229f979028fbd..52750d138d5c5aa7a75ed376efceff5dfdb1195d 100644 --- a/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py +++ b/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py @@ -12,7 +12,6 @@ from xAODBase.xAODType import xAODType standardghosts = ["Track","MuonSegment","Truth"] -#flavourghosts = ["TruthLabel"+ghosttype for ghosttype in [ flavourghosts = [ "BHadronsInitial", "BHadronsFinal", "BQuarksFinal", "CHadronsInitial", "CHadronsFinal", "CQuarksFinal", "TausFinal", @@ -47,7 +46,7 @@ pflowmods = () AntiKt4EMPFlow = JetDefinition("AntiKt",0.4,cst.EMPFlow, - ghostdefs = standardghosts+flavourghosts , # not working well yet : flavourghosts, + ghostdefs = standardghosts+flavourghosts , modifiers = standardrecomods+truthmods, standardRecoMode = True, lock = True @@ -90,6 +89,7 @@ AntiKt4TruthWZ = JetDefinition("AntiKt",0.4, cst.TruthWZ, def StandardSmallRJetCfg(configFlags): + """Top-level function to schedule the smallR jets in standard reconstruction """ from JetRecConfig.JetRecConfig import JetRecCfg standarSmallRList = [ diff --git a/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py b/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py index 518ea15ad8d1114ddbe2974af350051dfaf3afe8..1322fcf541350c158fd50ca8b0ad3a720714751d 100755 --- a/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py +++ b/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py @@ -12,6 +12,7 @@ def DefineJetCollections(configFlags): ######################################################################## # import the standard definitions from JetRecConfig.StandardSmallRJets import AntiKt4EMPFlow, AntiKt4EMTopo, AntiKt4Truth, AntiKt4TruthWZ + from JetRecConfig.StandardLargeRJets import AntiKt10LCTopoSoftDrop # Example for defining a custom definition from JetRecConfig.JetDefinition import JetConstitSeq, JetDefinition, xAODType @@ -38,6 +39,7 @@ def DefineJetCollections(configFlags): AntiKt4EMPFlow.clone(prefix="New"), AntiKt4EMTopoCSSK, AntiKt4EMPFlowCSSK, + AntiKt10LCTopoSoftDrop, ] if configFlags.Input.isMC: jetdefs += [AntiKt4Truth.clone(prefix="New"), diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py index 6c5b54bb1b81e081d4201670da7bb5f3389d4799..df72ad99fc2bf6364009904ac03bf6857f7737aa 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py @@ -174,11 +174,15 @@ def defineReclusteredJets(jetRecoDict,smallRjets): return rcJetDef def defineGroomedJets(jetRecoDict,ungroomedDef):#,ungroomedJetsName): - from JetRecConfig.JetGrooming import JetTrimming, JetSoftDrop + from JetRecConfig.JetGrooming import JetTrimmingTrig, JetSoftDropTrig groomAlg = jetRecoDict["recoAlg"][3:] if 'sd' in jetRecoDict["recoAlg"] else jetRecoDict["recoAlg"][-1] + suffix = "_"+ jetRecoDict["jetCalib"] + if jetRecoDict["trkopt"]!="notrk": + suffix += "_"+jetRecoDict["trkopt"] + groomDef = { - "sd":JetSoftDrop(ungroomedDef,zcut=0.1,beta=1.0), - "t" :JetTrimming(ungroomedDef,smallR=0.2,ptfrac=0.04), + "sd":JetSoftDropTrig(ungroomedDef,ZCut=0.1,Beta=1.0, suffix=suffix), + "t" :JetTrimmingTrig(ungroomedDef,RClus=0.2,PtFrac=0.04, suffix=suffix), }[groomAlg] return groomDef diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py index 10c99e949b1d27acdd11a21c22c4c830574eb0f7..3ff27580630c7028523bcae9c8235c71e04c3398 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py @@ -149,7 +149,7 @@ def standardJetRecoSequence( configFlags, dataSource, clustersKey, **jetRecoDict # make sure all our JetModifier have their track inputs set up according to trkopt from JetRecConfig.JetModConfig import jetModWithAlternateTrk jetModWithAlternateTrk(jetDef, jetRecoDict['trkopt'] ) - + # Generate a JetAlgorithm to run the jet finding and modifiers # (via a JetRecTool instance). jetRecAlg = JetRecConfig.getJetAlgorithm(jetsFullName, jetDef, pjs, monTool) @@ -177,10 +177,7 @@ def groomedJetRecoSequence( configFlags, dataSource, clustersKey, **jetRecoDict parentpjs = getattr(ungroomedJetRecoSequence,"jetalg_{}".format(ungroomedJetsName)).Tools[0].InputPseudoJets groomDef = JetRecoConfiguration.defineGroomedJets(jetRecoDict,ungroomedDef) - groomedJetsFullName = groomDef.fullname()+"_"+jetRecoDict["jetCalib"] - if jetRecoDict["trkopt"]!="notrk": - groomedJetsFullName += "_"+jetRecoDict["trkopt"] - + groomedJetsFullName = groomDef.fullname() groomDef.modifiers = JetRecoConfiguration.defineCalibFilterMods(jetRecoDict,dataSource) # Can add substructure mods here @@ -188,9 +185,9 @@ def groomedJetRecoSequence( configFlags, dataSource, clustersKey, **jetRecoDict from JetRec import JetOnlineMon monTool = JetOnlineMon.getMonTool_TrigJetAlgorithm("HLTJets/"+groomedJetsFullName+"/") - from JetRecConfig.JetGroomConfig import getJetGroomAlg, instantiateGroomingAliases + from JetRecConfig.JetGroomConfig import getJetGroomAlg_jetAlg, instantiateGroomingAliases instantiateGroomingAliases(groomDef) - groomalg = getJetGroomAlg(groomedJetsFullName,groomDef,parentpjs,monTool) + groomalg = getJetGroomAlg_jetAlg(groomDef,parentpjs,monTool) recoSeq += conf2toConfigurable( groomalg ) jetsOut = recordable(groomedJetsFullName)