diff --git a/Reconstruction/DiTauRec/CMakeLists.txt b/Reconstruction/DiTauRec/CMakeLists.txt index 25d37f5a223315a39ae5e7b0a193793f3c8106d8..c578623878067c97d784ec21df9647d68307bdeb 100644 --- a/Reconstruction/DiTauRec/CMakeLists.txt +++ b/Reconstruction/DiTauRec/CMakeLists.txt @@ -11,7 +11,7 @@ atlas_add_component( DiTauRec src/*.cxx src/components/*.cxx INCLUDE_DIRS ${FASTJET_INCLUDE_DIRS} - LINK_LIBRARIES ${FASTJET_LIBRARIES} AthenaBaseComps xAODEgamma xAODJet xAODMuon xAODTau GaudiKernel JetEDM TrkToolInterfaces CaloEvent xAODTracking RecoToolInterfaces StoreGateLib tauRecToolsLib TrkParametersIdentificationHelpers ) + LINK_LIBRARIES ${FASTJET_LIBRARIES} AthenaBaseComps xAODEgamma xAODJet xAODMuon xAODTau GaudiKernel JetEDM TrkToolInterfaces CaloEvent xAODTracking RecoToolInterfaces StoreGateLib tauRecToolsLib TrkParametersIdentificationHelpers PathResolver) # Install files from the package: atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} ) diff --git a/Reconstruction/DiTauRec/DiTauRec/DiTauOnnxDiscriminantTool.h b/Reconstruction/DiTauRec/DiTauRec/DiTauOnnxDiscriminantTool.h index 204e62f1297c729facaab6eda32cfb9562e53deb..87fb2181e310c61d8740a0e3e998aefb83823c2a 100644 --- a/Reconstruction/DiTauRec/DiTauRec/DiTauOnnxDiscriminantTool.h +++ b/Reconstruction/DiTauRec/DiTauRec/DiTauOnnxDiscriminantTool.h @@ -11,7 +11,7 @@ #include "xAODTau/DiTauJet.h" #include "DiTauToolBase.h" #include "GaudiKernel/ToolHandle.h" -#include "GaudiKernel/PathResolver.h" +#include "PathResolver/PathResolver.h" #include "AthContainers/Accessor.h" #include "AthContainers/ConstAccessor.h" diff --git a/Reconstruction/DiTauRec/src/DiTauOnnxDiscriminantTool.cxx b/Reconstruction/DiTauRec/src/DiTauOnnxDiscriminantTool.cxx index 0a32e9e89ca1e6e22cafa85add0cbfa4c11fe7bc..eeb8551aa11079784b07e6b7371ef4137d667dad 100644 --- a/Reconstruction/DiTauRec/src/DiTauOnnxDiscriminantTool.cxx +++ b/Reconstruction/DiTauRec/src/DiTauOnnxDiscriminantTool.cxx @@ -35,7 +35,7 @@ StatusCode DiTauOnnxDiscriminantTool::initialize() { ATH_MSG_INFO( "Initializing DiTauOnnxDiscriminantTool" ); ATH_MSG_INFO( "onnxModelPath: " << m_onnxModelPath ); - auto model_path = System::PathResolver::find_file (m_onnxModelPath, "DATAPATH"); + auto model_path = PathResolverFindCalibFile (m_onnxModelPath); if (model_path.empty()) { ATH_MSG_ERROR("Could not find model file: " << m_onnxModelPath); return StatusCode::FAILURE; diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/ATLAS_CHECK_THREAD_SAFETY b/Trigger/TrigHypothesis/TrigDitauHypo/ATLAS_CHECK_THREAD_SAFETY new file mode 100644 index 0000000000000000000000000000000000000000..77271e1ef846a24878a37bfe7c1c663cdc0c7b7e --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/ATLAS_CHECK_THREAD_SAFETY @@ -0,0 +1 @@ +Trigger/TrigHypothesis/TrigDitauHypo diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/CMakeLists.txt b/Trigger/TrigHypothesis/TrigDitauHypo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fd0414881ab1c8a317dfe88379d555b6898d9f9b --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +# Declare the package name: +atlas_subdir( TrigDitauHypo ) + +# External dependencies: +find_package( ROOT COMPONENTS Core MathCore ) + +# Component(s) in the package: +atlas_add_component( TrigDitauHypo + src/*.cxx src/components/*.cxx + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} AthViews AthenaBaseComps AthenaMonitoringKernelLib CxxUtils DecisionHandlingLib GaudiKernel TrigCompositeUtilsLib TrigSteeringEvent TrkTrack TrkTrackSummary xAODBase xAODCaloEvent xAODTau xAODTracking xAODTrigger ) + +# Install files from the package: +atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} --extend-extensions=ATL900,ATL901 ) diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/python/TrigDiTauHypoTool.py b/Trigger/TrigHypothesis/TrigDitauHypo/python/TrigDiTauHypoTool.py new file mode 100644 index 0000000000000000000000000000000000000000..0631c0d9740594bf13bede264544bc0eb566d80b --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/python/TrigDiTauHypoTool.py @@ -0,0 +1,36 @@ +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +import re +from AthenaCommon.SystemOfUnits import GeV + +from AthenaCommon.Logging import logging +log = logging.getLogger('TrigHLTDiTauHypoTool') + + +def TrigDiTauHypoToolFromDict(flags, chainDict): + name = chainDict['chainName'] + chainPart = chainDict['chainParts'][0] + cut_pt = float(chainPart['threshold']) * GeV + ditau_tag_str = chainPart['ditauTag'] + pattern = r"ditauOmni([0-9])Trk([0-9]{2})" + match = re.match(pattern, ditau_tag_str) + if match is None: + log.error(f"Invalid ditau tag: {ditau_tag_str}") + raise ValueError(f"Invalid ditau tag: {ditau_tag_str}") + id_cut = float(match.group(1))/10 + n_trk_lead = int(match.group(2)[0]) + n_trk_subl = int(match.group(2)[1]) + if n_trk_lead < 3 or n_trk_subl < 3: + log.error(f"Invalid ditau tag: {ditau_tag_str}") + log.error("it doesn't make sense to require less than 3 tracks in a ditau subjet") + raise ValueError(f"Invalid ditau tag: {ditau_tag_str}") + + from AthenaConfiguration.ComponentFactory import CompFactory + currentHypo = CompFactory.TrigDiTauHypoTool( + name, + ditau_pt_threshold=cut_pt, + ditau_id_score=id_cut, + ditau_lead_max_trk=n_trk_lead, + ditau_subl_max_trk=n_trk_subl, + ) + + return currentHypo \ No newline at end of file diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/src/ITrigDiTauHypoTool.h b/Trigger/TrigHypothesis/TrigDitauHypo/src/ITrigDiTauHypoTool.h new file mode 100644 index 0000000000000000000000000000000000000000..a4801be8e2c95d520be853d500816f2f72f95c21 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/src/ITrigDiTauHypoTool.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +*/ +#pragma once + +#include "AsgTools/IAsgTool.h" +#include "xAODTau/DiTauJetContainer.h" +#include "TrigCompositeUtils/TrigCompositeUtils.h" +#include "TrigCompositeUtils/HLTIdentifier.h" + + +class ITrigDiTauHypoTool : virtual public::IAlgTool { + +public: + DeclareInterfaceID(ITrigDiTauHypoTool, 1, 0); + + + virtual ~ITrigDiTauHypoTool(){}; + struct ToolInfo { + TrigCompositeUtils::Decision* decision; + const TrigRoiDescriptor* roi; + const xAOD::DiTauJetContainer* diTauContainer; + const TrigCompositeUtils::DecisionIDContainer previousDecisionIDs; + ToolInfo(TrigCompositeUtils::Decision* d, const TrigRoiDescriptor* r, const xAOD::DiTauJetContainer *c, const TrigCompositeUtils::Decision* previousDecision) + : previousDecisionIDs(TrigCompositeUtils::decisionIDs(previousDecision).begin(), TrigCompositeUtils::decisionIDs(previousDecision).end()) + { + decision = d; + roi = r; + diTauContainer = c; + } +}; + virtual StatusCode decide(std::vector<ToolInfo>& input) const = 0; + virtual bool decide(const ToolInfo& i) const = 0; +}; diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoAlg.cxx b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b19fbf023a1a3a7970114482e50e76479a313ba6 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoAlg.cxx @@ -0,0 +1,103 @@ +/* + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigSteeringEvent/TrigRoiDescriptorCollection.h" +#include "AthViews/ViewHelper.h" +#include "TrigCompositeUtils/TrigCompositeUtils.h" + +#include "TrigDiTauHypoAlg.h" + + +using namespace TrigCompositeUtils; + +TrigDiTauHypoAlg::TrigDiTauHypoAlg(const std::string& name, ISvcLocator* pSvcLocator) + : ::HypoBase(name, pSvcLocator) +{} + + +StatusCode TrigDiTauHypoAlg::initialize() { + ATH_CHECK(m_hypoTools.retrieve()); + ATH_CHECK(m_DiTauJets_key.initialize()); + + // TauJet are made in views, so they are not in the EvtStore: hide them + renounce(m_DiTauJets_key); + + return StatusCode::SUCCESS; +} + + +StatusCode TrigDiTauHypoAlg::execute(const EventContext& context) const +{ + ATH_MSG_DEBUG("Executing " << name()); + + // Retrieve previous decisions from the previous step + SG::ReadHandle<DecisionContainer> previousDecisionsHandle = SG::makeHandle(decisionInput(), context); + if(!previousDecisionsHandle.isValid()) { + ATH_MSG_DEBUG("No implicit RH for previous decisions " << decisionInput().key() << ": is this expected?"); + return StatusCode::SUCCESS; + } + + ATH_MSG_DEBUG("Running with " << previousDecisionsHandle->size() << " previous decisions"); + + + // Create output decision handle + SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context); + + + // Prepare inputs for the decision tools + std::vector<ITrigDiTauHypoTool::ToolInfo> toolInput; + int counter = -1; + for(const xAOD::TrigComposite* previousDecision : *previousDecisionsHandle) { + counter++; + + // Get View + const ElementLink<ViewContainer> viewEL = previousDecision->objectLink<ViewContainer>(viewString()); + ATH_CHECK(viewEL.isValid()); + + // Get RoI + LinkInfo<TrigRoiDescriptorCollection> roiEL = findLink<TrigRoiDescriptorCollection>(previousDecision, roiString()); + ATH_CHECK(roiEL.isValid()); + const TrigRoiDescriptor* roi = *roiEL.link; + + // Get TauJet + SG::ReadHandle<xAOD::DiTauJetContainer> diTauHandle = ViewHelper::makeHandle(*viewEL, m_DiTauJets_key, context); + if(!diTauHandle.isValid()) { + ATH_MSG_WARNING("Something is wrong, missing TauJet container! Continuing anyways skipping view"); + continue; + } + ATH_MSG_DEBUG("Tau handle size: " << diTauHandle->size()); + if(diTauHandle->size() != 1) { + ATH_MSG_DEBUG("Something is wrong, an unexpected number of taus was found (expected 1), continuing anyways skipping view"); + continue; + } + + + // Create new decision + Decision* newDecision = newDecisionIn(outputHandle.ptr(), hypoAlgNodeName()); + TrigCompositeUtils::linkToPrevious(newDecision, decisionInput().key(), counter); + newDecision->setObjectLink(roiString(), roiEL.link); + + ElementLink<xAOD::DiTauJetContainer> newDiTauEL = ViewHelper::makeLink(*viewEL, diTauHandle, 0); + ATH_CHECK(newDiTauEL.isValid()); + newDecision->setObjectLink(featureString(), newDiTauEL); + + // Create tool input + toolInput.emplace_back(newDecision, roi, diTauHandle.cptr(), previousDecision); + + ATH_MSG_DEBUG("Added view, roi, tau, previous decision to new decision (" << counter << ") for view " << (*viewEL)->name()); + } + + ATH_MSG_DEBUG("Found " << toolInput.size() << " inputs to tools"); + + + // Execute decisions from all tools + for(auto& tool : m_hypoTools) { + ATH_CHECK(tool->decide(toolInput)); + } + + + ATH_CHECK(hypoBaseOutputProcessing(outputHandle)); + + return StatusCode::SUCCESS; +} diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoAlg.h b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..edc618edafdefc78ad43cb2b37c59d1d7f2d8745 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoAlg.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +*/ + +#pragma once + +#include "DecisionHandling/HypoBase.h" +#include "xAODTau/DiTauJetContainer.h" + +#include "ITrigDiTauHypoTool.h" + + +/** + * @class TrigDiTauHypoAlg + * @brief HLT Precision step TauJet selection hypothesis algorithm + **/ +class TrigDiTauHypoAlg : public ::HypoBase +{ +public: + TrigDiTauHypoAlg(const std::string& name, ISvcLocator* pSvcLocator); + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& context) const override; + +private: + ToolHandleArray<ITrigDiTauHypoTool> m_hypoTools {this, "HypoTools", {}, "Hypo tools"}; + SG::ReadHandleKey<xAOD::DiTauJetContainer> m_DiTauJets_key {this, "DiTauJets_key", "", "DiTauJets in view" }; +}; diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoTool.cxx b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..485f69d476202c52a6c5b1ad70b3565ea4628651 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoTool.cxx @@ -0,0 +1,70 @@ +/* + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +*/ + +#include "AthenaMonitoringKernel/Monitored.h" +#include "TrigCompositeUtils/TrigCompositeUtils.h" +#include "xAODTau/TauJetContainer.h" +#include "GaudiKernel/SystemOfUnits.h" + +#include "TrigDiTauHypoTool.h" + + +using namespace TrigCompositeUtils; + +TrigDiTauHypoTool::TrigDiTauHypoTool(const std::string& type, const std::string& name, const IInterface* parent) + : base_class(type, name, parent), + m_decisionId(HLT::Identifier::fromToolName(name)) +{} + + +TrigDiTauHypoTool::~TrigDiTauHypoTool() +{} + + +StatusCode TrigDiTauHypoTool::initialize() +{ + ATH_MSG_DEBUG(name() << ": in initialize()"); + + ATH_MSG_DEBUG("TrigDiTauHypoTool will cut on:"); + ATH_MSG_DEBUG(" - PtMin : " << m_ditau_pt_threshold.value()); + ATH_MSG_DEBUG(" - ID Score : " << m_ditau_omni_score.value()); + ATH_MSG_DEBUG(" - Max Lead Trk: " << m_ditau_lead_max_trk.value()); + ATH_MSG_DEBUG(" - Max Subl Trk: " << m_ditau_subl_max_trk.value()); + return StatusCode::SUCCESS; +} + + +bool TrigDiTauHypoTool::decide(const ITrigDiTauHypoTool::ToolInfo& input) const +{ + static const SG::ConstAccessor< int > n_tracks_leadAcc("n_tracks_lead"); + static const SG::ConstAccessor< int > n_tracks_sublAcc("n_tracks_subl"); + static const SG::ConstAccessor< float > ditau_ptAcc ("ditau_pt"); + static const SG::ConstAccessor< float > omni_scoreAcc ("omni_score"); + ATH_MSG_DEBUG(name() << ": in execute()"); + // Tau pass flag + bool pass = false; + for(const xAOD::DiTauJet* diTau : *(input.diTauContainer)) { + if(ditau_ptAcc(*diTau) < m_ditau_pt_threshold.value()) continue; + if(omni_scoreAcc(*diTau) < m_ditau_omni_score.value()) continue; + if(n_tracks_leadAcc(*diTau) > m_ditau_lead_max_trk.value() || n_tracks_leadAcc(*diTau) < 0) continue; + if(n_tracks_sublAcc(*diTau) > m_ditau_subl_max_trk.value() || n_tracks_sublAcc(*diTau) < 0) continue; + pass = true; + } + ATH_MSG_DEBUG(" Pass hypo tool: " << pass); + return pass; +} + + +StatusCode TrigDiTauHypoTool::decide(std::vector<ITrigDiTauHypoTool::ToolInfo>& input) const { + for(auto& i : input) { + if(passed(m_decisionId.numeric(), i.previousDecisionIDs)) { + if(decide(i)) { + addDecisionID(m_decisionId, i.decision); + } + } + } + + return StatusCode::SUCCESS; +} + diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoTool.h b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoTool.h new file mode 100644 index 0000000000000000000000000000000000000000..2591bc486ed46895870ff00899781ab08ec1dcf0 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/src/TrigDiTauHypoTool.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration +*/ + +#pragma once + +#include "TrigCompositeUtils/HLTIdentifier.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "TrigCompositeUtils/TrigCompositeUtils.h" +#include "AthenaMonitoringKernel/GenericMonitoringTool.h" + +#include "xAODTau/DiTauJetContainer.h" +#include "ITrigDiTauHypoTool.h" + +class TrigDiTauHypoTool: public extends<AthAlgTool, ITrigDiTauHypoTool> { + public: + TrigDiTauHypoTool(const std::string& type, const std::string& name, const IInterface* parent); + virtual ~TrigDiTauHypoTool(); + virtual StatusCode initialize() override; + virtual StatusCode decide(std::vector<ITrigDiTauHypoTool::ToolInfo>& input) const override; + virtual bool decide(const ITrigDiTauHypoTool::ToolInfo& i) const override; + private: + HLT::Identifier m_decisionId; + Gaudi::Property<float> m_ditau_pt_threshold {this, "ditau_pt_threshold", 200, "ditau pT threshold [GeV]" }; + Gaudi::Property<float> m_ditau_omni_score {this, "ditau_id_score", 0.0, "ditau omni id score" }; + Gaudi::Property<int> m_ditau_lead_max_trk {this, "ditau_lead_max_trk", 3, "ditau lead track multiplicity" }; + Gaudi::Property<int> m_ditau_subl_max_trk {this, "ditau_subl_max_trk", 3, "ditau sublead track multiplicity" }; +}; + diff --git a/Trigger/TrigHypothesis/TrigDitauHypo/src/components/TrigDiTauHypo_entries.cxx b/Trigger/TrigHypothesis/TrigDitauHypo/src/components/TrigDiTauHypo_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..006da9d72774ced22dfe1ca1ec8c36172f84f63d --- /dev/null +++ b/Trigger/TrigHypothesis/TrigDitauHypo/src/components/TrigDiTauHypo_entries.cxx @@ -0,0 +1,6 @@ +#include "../TrigDiTauHypoAlg.h" +#include "../TrigDiTauHypoTool.h" + +DECLARE_COMPONENT( TrigDiTauHypoAlg ) +DECLARE_COMPONENT( TrigDiTauHypoTool ) + diff --git a/Trigger/TrigSteer/TrigOutputHandling/TrigOutputHandling/TriggerEDMAuxAccessors.h b/Trigger/TrigSteer/TrigOutputHandling/TrigOutputHandling/TriggerEDMAuxAccessors.h index 2743222d96c941b9a1f1b0fb54c65849c52f41d4..bae16cae3b941bf93d7afcdfd0758f07fd99e15f 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/TrigOutputHandling/TriggerEDMAuxAccessors.h +++ b/Trigger/TrigSteer/TrigOutputHandling/TrigOutputHandling/TriggerEDMAuxAccessors.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration */ #include "xAODBase/IParticleContainer.h" @@ -52,7 +52,12 @@ auto intAccessors = initAccessors<int>( "dEdxTrk_id","dEdxTrk_dedx_n_usedhits", "dEdxTrk_n_hits_innermost","dEdxTrk_n_hits_inner","dEdxTrk_n_hits_pix","dEdxTrk_n_hits_sct", "dEdxHit_trkid","dEdxHit_iblovfl","dEdxHit_loc","dEdxHit_layer","NumPV", "nRoIs", - "l1a_type", "other_type", "beforeafterflag","pass"); + "l1a_type", "other_type", "beforeafterflag","pass", + "n_isotrack", + "n_track", + "n_tracks_lead", + "n_tracks_subl" + ); auto int16Accessors = initAccessors<int16_t>("view", "HPtdEdxTrk_n_hdedx_hits_1p45","HPtdEdxTrk_n_hdedx_hits_1p50","HPtdEdxTrk_n_hdedx_hits_1p55","HPtdEdxTrk_n_hdedx_hits_1p60", @@ -187,7 +192,40 @@ auto floatAccessors = initAccessors<float>( "ClusterEta", "ClusterPhi", "d0TJVA", "d0SigTJVA", "z0sinthetaTJVA", "z0sinthetaSigTJVA", "GNTau_Score", "GNTau_ScoreSigTrans", - "pixQ2mod" + "pixQ2mod", + "E_frac_subl", + "E_frac_subsubl", + "R_core_lead", + "R_core_subl", + "R_isotrack", + "R_max_lead", + "R_max_subl", + "R_subjets_subl", + "R_subjets_subsubl", + "R_track", + "R_track_all", + "R_track_core", + "R_tracks_lead", + "R_tracks_subl", + "d0_leadtrack_lead", + "d0_leadtrack_subl", + "ditau_pt", + "f_core_lead", + "f_core_subl", + "f_isotracks", + "f_subjet_lead", + "f_subjet_subl", + "f_subjets", + "f_track_lead", + "f_track_subl", + "m_core_lead", + "m_core_subl", + "m_track", + "m_track_all", + "m_track_core", + "m_tracks_lead", + "m_tracks_subl", + "omni_score" ); auto doubleAccessors = initAccessors<double>("ptcone02", "ptcone03", "JetDensityEMPFlow", diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx index 8c10a3990c7056317fde6e63aaacee7e21dc808a..bb6c8847b89ceb801bd11cd828f0cef0c6d794bf 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx +++ b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx @@ -28,6 +28,7 @@ #include "xAODTrigMuon/L2IsoMuonAuxContainer.h" #include "xAODMuon/MuonAuxContainer.h" #include "xAODTau/TauJetAuxContainer.h" +#include "xAODTau/DiTauJetAuxContainer.h" #include "xAODTau/TauTrackAuxContainer.h" #include "xAODJet/JetAuxContainer.h" #include "xAODTracking/VertexAuxContainer.h" @@ -154,6 +155,7 @@ StatusCode HLTEDMCreator::initialize() INIT_XAOD( L2IsoMuonContainer, L2IsoMuonAuxContainer ); INIT_XAOD( MuonContainer, MuonAuxContainer ); INIT_XAOD( TauJetContainer, TauJetAuxContainer ); + INIT_XAOD( DiTauJetContainer, DiTauJetAuxContainer ); INIT_XAOD( TauTrackContainer, TauTrackAuxContainer ); INIT_XAOD( JetContainer, JetAuxContainer ); INIT_XAOD( VertexContainer, VertexAuxContainer ); @@ -496,6 +498,7 @@ StatusCode HLTEDMCreator::createOutput(const EventContext& context) const { CREATE_XAOD( L2IsoMuonContainer, L2IsoMuonAuxContainer ); CREATE_XAOD( MuonContainer, MuonAuxContainer ); CREATE_XAOD( TauJetContainer, TauJetAuxContainer ); + CREATE_XAOD( DiTauJetContainer, DiTauJetAuxContainer ); CREATE_XAOD( TauTrackContainer, TauTrackAuxContainer ); CREATE_XAOD( CaloClusterContainer, CaloClusterTrigAuxContainer ); // NOTE: Difference in interface and aux CREATE_XAOD( JetContainer, JetAuxContainer ); diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h index 3d4b6740b3ac4ab5408d1aacd9e29f9ed4491a91..5be32de2a4d04747213ace1625cfdb16e6fd8ebd 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h +++ b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h @@ -35,6 +35,7 @@ #include "xAODTrigMuon/L2IsoMuonContainer.h" #include "xAODMuon/MuonContainer.h" #include "xAODTau/TauJetContainer.h" +#include "xAODTau/DiTauJetContainer.h" #include "xAODTau/TauTrackContainer.h" #include "xAODJet/JetContainer.h" #include "xAODTracking/VertexContainer.h" @@ -136,6 +137,7 @@ class HLTEDMCreator: public extends<AthAlgTool, IHLTOutputTool> { DEF_XAOD_KEY( L2IsoMuonContainer ); DEF_XAOD_KEY( MuonContainer ); DEF_XAOD_KEY( TauJetContainer ); + DEF_XAOD_KEY( DiTauJetContainer ); DEF_XAOD_KEY( TauTrackContainer ); DEF_XAOD_KEY( CaloClusterContainer ); DEF_XAOD_KEY( JetContainer ); diff --git a/Trigger/TrigTools/TrigInDetConfig/python/BuildSignatureFlags.py b/Trigger/TrigTools/TrigInDetConfig/python/BuildSignatureFlags.py index 69683e2213e4bdacee2fe22c1e539faf53746ab5..7352347a3b8dbef4375004659f095b9d323c59b2 100644 --- a/Trigger/TrigTools/TrigInDetConfig/python/BuildSignatureFlags.py +++ b/Trigger/TrigTools/TrigInDetConfig/python/BuildSignatureFlags.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration from AthenaConfiguration.AthConfigFlags import AthConfigFlags from TrkConfig.TrackingPassFlags import createTrackingPassFlags,createITkTrackingPassFlags @@ -170,6 +170,8 @@ def signatureTrigTrackingFlags(mode : str) -> AthConfigFlags: "tauCore" : tauCore, "tauIso" : tauIso, + "ditau" : ditau, + "bjet" : bjet, "fullScan" : fullScan, @@ -331,6 +333,24 @@ def tauIso(flags: AthConfigFlags, instanceName: str, recoMode: str) -> AthConfig flags.minPT = tsetter(flags.minPT, flags.pTmin) return flags +@signatureActions +def ditau(flags: AthConfigFlags, instanceName: str, recoMode: str) -> AthConfigFlags: + + flags.input_name = instanceName + flags.name = "ditau" + flags.suffix = "ditau" + flags.roi = "HLT_DitauRoI" + flags.etaHalfWidth = 1.0 + flags.phiHalfWidth = 1.0 + flags.zedHalfWidth = 7.0 + flags.adaptiveVertex = True + flags.addSingleTrackVertices = True + flags.vertex = "HLT_IDVertex_ditau" + flags.electronPID = False + flags.pTmin = 0.8*Units.GeV + flags.minPT = tsetter(flags.minPT, flags.pTmin) + return flags + @signatureActions def bjet(flags: AthConfigFlags, instanceName: str, recoMode: str) -> AthConfigFlags: diff --git a/Trigger/TrigValidation/TriggerTest/test/test_trig_data_v1Dev_slice_ditau_build.py b/Trigger/TrigValidation/TriggerTest/test/test_trig_data_v1Dev_slice_ditau_build.py new file mode 100755 index 0000000000000000000000000000000000000000..b78b5c420b988ac6668f55f43fb92565250ffe22 --- /dev/null +++ b/Trigger/TrigValidation/TriggerTest/test/test_trig_data_v1Dev_slice_ditau_build.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +# art-description: Trigger RDO->RDO_TRIG athena test of the b-jet slice in Dev_pp_run3_v1 menu, data input +# art-type: build +# art-include: main/Athena +# art-include: 24.0/Athena +# Skipping art-output which has no effect for build tests. +# If you create a grid version, check art-output in existing grid tests. + +from TrigValTools.TrigValSteering import Test, ExecStep, CheckSteps + +ex = ExecStep.ExecStep() +ex.type = 'athena' +ex.job_options = 'TriggerJobOpts/runHLT.py' +ex.input = 'data_Main' +ex.max_events = 150 +ex.threads = 1 +ex.flags = ['Trigger.triggerMenuSetup="Dev_pp_run3_v1"', + 'Trigger.enabledSignatures=[\\\"Ditau\\\"]', + 'Trigger.doLVL1=True'] + +test = Test.Test() +test.art_type = 'build' +test.exec_steps = [ex] +test.check_steps = CheckSteps.default_check_steps(test) + +import sys +sys.exit(test.run()) diff --git a/Trigger/TrigValidation/TriggerTest/test/test_trig_mc_v1Dev_slice_ditau_build.py b/Trigger/TrigValidation/TriggerTest/test/test_trig_mc_v1Dev_slice_ditau_build.py new file mode 100755 index 0000000000000000000000000000000000000000..75e69871320a61d196c54d6504ebb021fc0c235a --- /dev/null +++ b/Trigger/TrigValidation/TriggerTest/test/test_trig_mc_v1Dev_slice_ditau_build.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +# art-description: Trigger RDO->RDO_TRIG athena test of the tau slice in Dev_pp_run3_v1 menu +# art-type: build +# art-include: main/Athena +# art-include: 24.0/Athena +# Skipping art-output which has no effect for build tests. +# If you create a grid version, check art-output in existing grid tests. + +from TrigValTools.TrigValSteering import Test, ExecStep, CheckSteps + +from AthenaConfiguration.TestDefaults import defaultConditionsTags +conditions = defaultConditionsTags.RUN3_MC + +ex = ExecStep.ExecStep() +ex.type = 'athena' +ex.job_options = 'TriggerJobOpts/runHLT.py' +ex.input = 'ttbar' +ex.threads = 1 +ex.flags = ['Trigger.triggerMenuSetup="Dev_pp_run3_v1"', + 'IOVDb.GlobalTag="' + conditions + '"', + 'Trigger.enabledSignatures=[\\\"Ditau\\\"]'] + +test = Test.Test() +test.art_type = 'build' +test.exec_steps = [ex] +test.check_steps = CheckSteps.default_check_steps(test) + +import sys +sys.exit(test.run()) diff --git a/Trigger/TrigValidation/TriggerTest/test/test_trig_mc_v1Dev_slice_ditau_grid.py b/Trigger/TrigValidation/TriggerTest/test/test_trig_mc_v1Dev_slice_ditau_grid.py new file mode 100755 index 0000000000000000000000000000000000000000..0627b5f925c03572eaab64db53265500c0062c29 --- /dev/null +++ b/Trigger/TrigValidation/TriggerTest/test/test_trig_mc_v1Dev_slice_ditau_grid.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +# art-description: Trigger RDO->RDO_TRIG athena test of the egamma slice in Dev_pp_run3_v1 menu +# art-type: grid +# art-include: main/Athena +# art-include: 24.0/Athena +# art-athena-mt: 8 +# art-output: *.txt +# art-output: *.log +# art-output: log.* +# art-output: *.out +# art-output: *.err +# art-output: *.log.tar.gz +# art-output: *.new +# art-output: *.json +# art-output: *.root +# art-output: *.pmon.gz +# art-output: *perfmon* +# art-output: prmon* +# art-output: *.check* + +from TrigValTools.TrigValSteering import Test, ExecStep, CheckSteps + +from AthenaConfiguration.TestDefaults import defaultConditionsTags +conditions = defaultConditionsTags.RUN3_MC + +ex = ExecStep.ExecStep() +ex.type = 'athena' +ex.job_options = 'TriggerJobOpts/runHLT.py' +ex.input = 'ttbar' +ex.threads = 8 +ex.concurrent_events = 8 +ex.flags = ['Trigger.triggerMenuSetup="Dev_pp_run3_v1"', + 'IOVDb.GlobalTag="' + conditions + '"', + 'Trigger.enabledSignatures=[\\\"Ditau\\\"]'] + +test = Test.Test() +test.art_type = 'grid' +test.exec_steps = [ex] +test.check_steps = CheckSteps.default_check_steps(test) + +import sys +sys.exit(test.run()) diff --git a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py index 9e64d0f6fada67bb21254ea93e674ab103d13a56..28e8b229c947a4ce0e50972fd3c71722498414eb 100644 --- a/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py +++ b/Trigger/TriggerCommon/TrigEDMConfig/python/TriggerEDMRun3.py @@ -228,6 +228,12 @@ TauJet_vars_str = '.'.join(TauJet_vars) TauTrack_vars = ['pt', 'eta', 'phi', 'flagSet', 'trackLinks', 'd0TJVA', 'd0SigTJVA', 'z0sinthetaTJVA', 'z0sinthetaSigTJVA'] TauTrack_vars_str = '.'.join(TauTrack_vars) +# =========== +# == ditau == +DiTauJet_vars = ['pt', 'eta', 'phi', 'm', 'TauJetVtxFraction', 'subjet_pt', 'subjet_phi', 'subjet_e', 'subjet_f_core', 'subjet_eta', 'isoTrackLinks', 'jetLink', 'vertexLink', 'trackLinks'] +DiTauJet_vars += ["ditau_pt", "f_core_lead", "f_core_subl", "f_subjet_lead", "f_subjet_subl", "f_subjets", "f_track_lead", "f_track_subl", "R_max_lead", "R_max_subl", "n_track", "n_tracks_lead", "n_tracks_subl", "n_isotrack", "R_track", "R_track_core", "R_track_all", "R_isotrack", "R_core_lead", "R_core_subl", "R_tracks_lead", "R_tracks_subl", "m_track", "m_track_core", "m_core_lead", "m_core_subl", "m_track_all", "m_tracks_lead", "m_tracks_subl", "E_frac_subl", "E_frac_subsubl", "R_subjets_subl", "R_subjets_subsubl", "d0_leadtrack_lead", "d0_leadtrack_subl", "f_isotracks", "omni_score"] +DiTauJet_vars_str = '.'.join(DiTauJet_vars) + # =========== # === LLP === MuRoiToKeep = ['ClusterEta','ClusterPhi','nRoIs'] @@ -288,6 +294,7 @@ TriggerHLTListRun3 = [ ('TrigRoiDescriptorCollection#HLT_METRoI', 'BS ESD AODFULL AODSLIM', 'Steer'), ('TrigRoiDescriptorCollection#HLT_JETRoI', 'BS ESD AODFULL AODSLIM', 'Steer'), ('TrigRoiDescriptorCollection#HLT_TAURoI', 'BS ESD AODFULL AODSLIM', 'Steer'), + ('TrigRoiDescriptorCollection#HLT_DitauRoI', 'BS ESD AODFULL AODSLIM', 'Steer'), # xAOD::TrigCompositeContainer#HLTNav_Summary is now transient-only ('xAOD::TrigCompositeContainer#HLTNav_Summary_OnlineSlimmed', 'BS ESD', 'Steer'), @@ -708,6 +715,12 @@ TriggerHLTListRun3 = [ ('xAOD::JetContainer#HLT_jet_seed', '', 'Tau', [InViews('tauCaloMVAViews')]), ('xAOD::JetAuxContainer#HLT_jet_seedAux.', '', 'Tau'), + #ditau + ('xAOD::TrackParticleContainer#HLT_IDTrack_ditau_FTF', 'BS ESD AODFULL AODSLIM', 'Ditau', [InViews('DitauViews')]), + ('xAOD::TrackParticleAuxContainer#HLT_IDTrack_ditau_FTFAux.', 'BS ESD AODFULL AODSLIM', 'Ditau'), + ('xAOD::TrackParticleContainer#HLT_IDTrack_ditau_IDTrig', 'BS ESD AODFULL AODSLIM', 'Ditau', [InViews('DitauViews')]), + ('xAOD::TrackParticleAuxContainer#HLT_IDTrack_ditau_IDTrigAux.', 'BS ESD AODFULL AODSLIM', 'Ditau'), + # Jet ('xAOD::JetContainer#HLT_AntiKt4EMTopoJets_subjesIS', 'BS ESD AODFULL AODSLIM', 'Jet', [Alias('JetContainerShallowCopy')]), ('xAOD::ShallowAuxContainer#HLT_AntiKt4EMTopoJets_subjesISAux.'+JetCopyVars, 'BS ESD AODFULL AODSLIM', 'Jet'), @@ -814,6 +827,9 @@ TriggerHLTListRun3 = [ ('xAOD::JetContainer#HLT_AntiKt4EMPFlowCSSKJets_nojcalib_ftf', '', 'Jet'), ('xAOD::JetAuxContainer#HLT_AntiKt4EMPFlowCSSKJets_nojcalib_ftfAux.'+JetVars, '', 'Jet'), + ('xAOD::JetContainer#HLT_AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10Jets_jes_ftf_Ditau_jets', 'BS ESD AODFULL', 'Jet'), + ('xAOD::JetAuxContainer#HLT_AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10Jets_jes_ftf_Ditau_jetsAux.'+JetVars, 'BS ESD AODFULL', 'Jet'), + ## event info ('xAOD::TrigCompositeContainer#HLT_TCEventInfo_jet', 'BS ESD AODFULL', 'Jet' ), ('xAOD::TrigCompositeAuxContainer#HLT_TCEventInfo_jetAux.JetDensityEMPFlow.AvgMu.NumPV', 'BS ESD AODFULL', 'Jet' ), @@ -996,6 +1012,10 @@ TriggerHLTListRun3 = [ ('xAOD::TauTrackContainer#HLT_tautrack_LRT', 'BS ESD AODFULL AODSLIM', 'Tau', [InViews('precLRTTauViews'), InViews('tauPrecisionReco_LRTViews')]), ('xAOD::TauTrackAuxContainer#HLT_tautrack_LRTAux.'+TauTrack_vars_str, 'BS ESD AODFULL AODSLIM', 'Tau'), + # ditau + ('xAOD::DiTauJetContainer#HLT_DiTauJets', 'BS ESD AODFULL AODSLIM', 'Ditau', [InViews('DitauViews')]), + ('xAOD::DiTauJetAuxContainer#HLT_DiTauJetsAux.'+DiTauJet_vars_str, 'BS ESD AODFULL AODSLIM', 'Ditau'), + # bjet RoI Descriptor used for EventView creation ('TrigRoiDescriptorCollection#HLT_Roi_Bjet', 'BS ESD AODFULL', 'Bjet'), diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/GenerateMenuMT.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/GenerateMenuMT.py index a6e397fe9d2e1d95e5891570134eaa27374bcf97..fd40a2add1d1ff40cff0b7ee1b8938853a32c751 100755 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/GenerateMenuMT.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/GenerateMenuMT.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration from typing import Optional import importlib, re, string @@ -15,7 +15,7 @@ def calibCosmicMonSignatures(): return ['Streaming','Monitor','Beamspot','Cosmic', 'Calib', 'EnhancedBias'] def combinedSignatures(): - return ['MinBias','Electron','Photon','Muon','Tau','Jet', 'Bjet','MET','UnconventionalTracking','HeavyIon'] + return ['MinBias','Electron','Photon','Muon','Tau', 'Ditau','Jet', 'Bjet','MET','UnconventionalTracking','HeavyIon'] def jointSignatures(): return ['Bjet', 'Egamma', 'Combined'] @@ -93,6 +93,7 @@ class GenerateMenuMT(metaclass=Singleton): signatureDeps.update({ # Bjet always requires jet 'Bjet': ['Bjet','Jet'], + 'Ditau' : ['Ditau','Jet'], # Egamma contains two signatures 'Egamma': ['Electron','Photon'], 'Combined': combinedSignatures(), @@ -403,7 +404,7 @@ class GenerateMenuMT(metaclass=Singleton): if currentSig in self.availableSignatures: try: log.debug("[__generateChainConfigs] Trying to get chain config for %s", currentSig) - if currentSig in ['Electron', 'Photon', 'Muon', 'Tau', 'Bphysics'] : + if currentSig in ['Electron', 'Photon', 'Muon', 'Tau', 'Bphysics', 'Ditau'] : chainPartConfig, perSig_lengthOfChainConfigs = self.chainDefModule[currentSig].generateChainConfigs(flags, chainPartDict, perSig_lengthOfChainConfigs) else: chainPartConfig = self.chainDefModule[currentSig].generateChainConfigs(flags, chainPartDict) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/Utility/DictFromChainName.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/Utility/DictFromChainName.py index a75ccfc87d01620a6e8562f85e1f221d16eeeef8..05eeb632b0aebb484d6c323075e9af0fb0fb678c 100755 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/Utility/DictFromChainName.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/Utility/DictFromChainName.py @@ -1,5 +1,5 @@ #! /bin/env python -# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration """ Class to obtain the chain configuration dictionary from the short or long name @@ -175,7 +175,7 @@ def unifyJetRecoParts(chainParts): jetDefaults, _ = getSignatureInformation('Jet') # Extract the jet chainParts, and get the reco specs from the last one _jetRecoKeys = JetRecoKeys - jetChainParts = [cPart for cPart in chainParts if cPart['signature'] in ['Jet','Bjet']] + jetChainParts = [cPart for cPart in chainParts if cPart['signature'] in ['Jet','Bjet', 'Ditau']] jetRecoDict = {k:jetChainParts[-1][k] for k in _jetRecoKeys} # Check consistency of the preceding jet parts @@ -191,7 +191,7 @@ def unifyJetRecoParts(chainParts): newChainParts = [] for cPart in chainParts: newCPart = deepcopy(cPart) - if newCPart['signature'] in ['Jet','Bjet']: + if newCPart['signature'] in ['Jet','Bjet', 'Ditau']: for k in _jetRecoKeys: newCPart[k] = jetRecoDict[k] newChainParts.append(newCPart) @@ -519,6 +519,23 @@ def analyseChainName(chainName, L1thresholds, L1item): if propSet is False: log.debug('Changing %s from %s to %s', prop, str(chainProperties[prop]), str(bJetDefaultValues[prop])) chainProperties[prop] = bJetDefaultValues[prop] + + + if chainProperties['ditauTag'] != '': + log.debug('Setting Ditau chain defaults') + # b-jet chain, so we now use the bJet defaults if they have not already been overriden + ditauJetDefaultValues, allowedDitauJetPropertiesAndValues = getSignatureInformation('Ditau') + for prop, value in ditauJetDefaultValues.items(): + propSet=False + for value in allowedDitauJetPropertiesAndValues[prop]: + if value in matchedparts: + propSet=True + break + + # if the property was not set already, then set if according to the ditau-jet defaults + if propSet is False: + log.debug('Changing %s from %s to %s', prop, str(chainProperties[prop]), str(ditauJetDefaultValues[prop])) + chainProperties[prop] = ditauJetDefaultValues[prop] if chainProperties['signature'] == 'Jet' and chainProperties['beamspotChain'] != '': @@ -600,13 +617,19 @@ def analyseChainName(chainName, L1thresholds, L1item): cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Bjet', cPart['tnpInfo']) else: cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Bjet', cPart['extra']) + if cPart['signature'] == 'Jet' and cPart['ditauTag'] != '': + cPart['signature'] = 'Ditau' + if 'tnpInfo' in cPart.keys() and cPart['tnpInfo'] != "": + cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Ditau', cPart['tnpInfo']) + else: + cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Ditau', cPart['extra']) genchainDict['signatures'] += [cPart['signature']] genchainDict['alignmentGroups'] += [cPart['alignmentGroup']] # Postprocess chains with multiple jet chainParts # to set them consistently from only one specification if len(genchainDict['chainParts'])>1: - if 'Jet' in genchainDict['signatures'] or 'Bjet' in genchainDict['signatures']: + if 'Jet' in genchainDict['signatures'] or 'Bjet' in genchainDict['signatures'] or 'Ditau' in genchainDict['signatures']: genchainDict['chainParts'] = unifyJetRecoParts(genchainDict['chainParts']) #genchainDict['signature'] = allChainProperties[0]['signature'] @@ -682,7 +705,7 @@ def dictFromChainName(flags, chainInfo): chainDict['sigDicts'][sf].extend(chainPart['subSigs']) else: chainDict['sigDicts'].update({sf:chainPart['subSigs']}) - if sf == 'Bjet': + if sf in ['Bjet', 'Ditau']: chainDict['sigDicts'].update({'Jet':['Jet']}) @@ -711,7 +734,7 @@ def dictFromChainName(flags, chainInfo): log.error("Standard tau chains should be seeded from L1_TAU. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature) #incorrectL1=True - if thisSignature in ['Jet','Bjet','MET','UnconventionalTracking']: + if thisSignature in ['Jet','Bjet', 'Ditau','MET','UnconventionalTracking']: if 'FSNOSEED' not in thisL1: log.error("Jet, b-jet, MET chains should be seeded from FSNOSEED. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature) #incorrectL1=True diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauChainConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauChainConfiguration.py new file mode 100644 index 0000000000000000000000000000000000000000..ea934310fef6283a5e48d2eb323a7497abb376b2 --- /dev/null +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauChainConfiguration.py @@ -0,0 +1,35 @@ +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.Logging import logging +logging.getLogger().info("Importing %s",__name__) +log = logging.getLogger(__name__) + +from ..Config.ChainConfigurationBase import ChainConfigurationBase +from .DitauMenuSequences import ditauSequenceGenCfg + + +#---------------------------------------------------------------- +# Class to configure chain +#---------------------------------------------------------------- +class DitauChainConfiguration(ChainConfigurationBase): + + def __init__(self, chainDict, jet_name): + self.jetName = jet_name + ChainConfigurationBase.__init__(self, chainDict) + + # ---------------------- + # Assemble the chain depending on information from chainName + # ---------------------- + def assembleChainImpl(self, flags): + log.debug("Assembling chain for %s", self.chainName) + chainStep = self.getStep( + flags, + 'ditau_step', + [ditauSequenceGenCfg], + seq_name = 'ditau', + jet_name = self.jetName + ) + + myChain = self.buildChain([chainStep]) + return myChain + diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauConfigFlagsHLT.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauConfigFlagsHLT.py new file mode 100644 index 0000000000000000000000000000000000000000..3f5c35aae103a2f34443d606776cfe549a6ded1e --- /dev/null +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauConfigFlagsHLT.py @@ -0,0 +1,26 @@ +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +import unittest +from AthenaConfiguration.AthConfigFlags import AthConfigFlags + +def createDiTauConfigFlags(): + ditau_cfg = AthConfigFlags() + ditau_cfg.addFlag("DiTau.DiTauContainer", ["HLT_DiTauJets"]) + ditau_cfg.addFlag("DiTau.JetSeedPt", 200000) + ditau_cfg.addFlag("DiTau.MaxEta", 2.5) + ditau_cfg.addFlag("DiTau.Rjet", 1.0) + ditau_cfg.addFlag("DiTau.Rsubjet", 0.2) + ditau_cfg.addFlag("DiTau.Rcore", 0.1) + ditau_cfg.addFlag("DiTau.CalibFolder", 'TrigTauRec/00-11-02/') + ditau_cfg.addFlag("DiTau.DiTauIDModel", "dev/boosted_ditau_omni_model.onnx") + return ditau_cfg + +class DiTestTauRecConfigFlags(unittest.TestCase): + def runTest(self): + createDiTauConfigFlags() + + +if __name__ == "__main__": + unittest.main() + + diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauMenuSequences.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauMenuSequences.py new file mode 100644 index 0000000000000000000000000000000000000000..8c2546f6f6805560450c02e479c047454ca1fcb1 --- /dev/null +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/DitauMenuSequences.py @@ -0,0 +1,181 @@ +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from TriggerMenuMT.HLT.Config.MenuComponents import MenuSequence, SelectionCA, InViewRecoCA +from DiTauRec.DiTauToolsConfig import ( + SeedJetBuilderCfg, SubjetBuilderCfg, + VertexFinderCfg, + DiTauTrackFinderCfg, + DiTauConstituentFinderCfg, + IDVarCalculatorCfg, + TVAToolCfg, + DiTauIDVarDecoratorCfg, + DiTauOnnxScoreCalculatorCfg, +) + + +from TrigEDMConfig.TriggerEDM import recordable + +from AthenaCommon.Logging import logging +log = logging.getLogger(__name__) + + +def ditauTrackingCfg(flags, inputRoI: str, inputVertex: str, inputJets: str) -> ComponentAccumulator: + #safety measure to ensure we get the right instance of flags + from TrigInDetConfig.utils import getFlagsForActiveConfig + trkflags = getFlagsForActiveConfig(flags, "ditau", log) + + from TrigInDetConfig.InnerTrackingTrigSequence import InnerTrackingTrigSequence + seq = InnerTrackingTrigSequence.create(trkflags, + trkflags.Tracking.ActiveConfig.input_name, + rois = inputRoI, + inView = "VDVInDetFTF") + acc = seq.sequence("FastTrackFinder") + acc.merge(seq.sequenceAfterPattern()) + + verifier = CompFactory.AthViews.ViewDataVerifier(name = 'VDVsecondStageDitauTracking', + DataObjects = {('xAOD::VertexContainer', f'StoreGateSvc+{inputVertex}'), + ('xAOD::JetContainer', f'StoreGateSvc+{inputJets}')} ) + acc.addEventAlgo(verifier) + + return acc + +def JetTVAAlgCfg(flags, inputTracks, inputVertex, name="HLT_DiTauRec_JetAlgorithm"): # Name changed wrt legacy config DiTauRec_TVATool + """Configure the JetAlgorithm""" + acc = ComponentAccumulator() + + tools = [acc.popToolsAndMerge( + TVAToolCfg( + flags, + TrackParticleContainer = inputTracks, + VertexContainer = inputVertex, + TrackVertexAssociation = "HLT_JetTrackVtxAssoc_forDiTaus" + ) + )] + tools = tools + + acc.addEventAlgo(CompFactory.JetAlgorithm(name, Tools = tools)) + return acc + +def ditauRecoCfg(flags, inputJets: str, inputVertex: str, inputFSTracks: str, inputTracks: str, inputCells: str, inputClusters: str) -> ComponentAccumulator: + from .DitauConfigFlagsHLT import createDiTauConfigFlags + flags_ditau = createDiTauConfigFlags() + + acc = ComponentAccumulator() + acc.merge(JetTVAAlgCfg( + flags, + inputTracks=inputFSTracks, + inputVertex=inputVertex, + )) + tools = [ + acc.popToolsAndMerge(SeedJetBuilderCfg(flags, JetCollection=inputJets)), + acc.popToolsAndMerge(SubjetBuilderCfg(flags)), + acc.popToolsAndMerge(VertexFinderCfg( + flags, + TrackVertexAssociation = "HLT_JetTrackVtxAssoc_forDiTaus", + PrimVtxContainerName = inputVertex, + AssociatedTracks = "GhostTrack_ftf" + )), + acc.popToolsAndMerge(DiTauTrackFinderCfg( + flags, + TrackParticleContainer=inputTracks + )), + acc.popToolsAndMerge(DiTauConstituentFinderCfg( + flags, + )), + # acc.popToolsAndMerge(CellFinderCfg( + # flags, + # ClusterContainer = inputClusters, + # CellContainer = inputCells + # )), + acc.popToolsAndMerge(IDVarCalculatorCfg(flags, useCells=False)), + acc.popToolsAndMerge(DiTauIDVarDecoratorCfg(flags)), + acc.popToolsAndMerge(DiTauOnnxScoreCalculatorCfg( + flags, + onnxModelPath=f"{flags_ditau.DiTau.CalibFolder}{flags_ditau.DiTau.DiTauIDModel}", + )), + ] + + acc.addEventAlgo(CompFactory.DiTauBuilder( + "HLT_DiTauBuilder", + DiTauContainer = recordable("HLT_DiTauJets"), + Tools = tools, + SeedJetName = inputJets, + minPt = flags_ditau.DiTau.JetSeedPt, + maxEta = flags_ditau.DiTau.MaxEta, + Rjet = flags_ditau.DiTau.Rjet, + Rsubjet = flags_ditau.DiTau.Rsubjet, + Rcore = flags_ditau.DiTau.Rcore, + )) + return acc + +def ditauSequenceGenCfg(flags, seq_name, jet_name): + # input maker and ROI tool + prmVtxKey = flags.Trigger.InDetTracking.fullScan.vertex + roiTool = CompFactory.ViewCreatorCentredOnJetWithPVConstraintROITool( + RoisWriteHandleKey = recordable( 'HLT_DitauRoI' ), + VertexReadHandleKey = prmVtxKey, + PrmVtxLink = prmVtxKey.replace( "HLT_","" ), + RoIEtaWidth = 1.0, + RoIPhiWidth = 1.0, + RoIZWidth = 7.0, + ) + ditauAcc = InViewRecoCA("Ditau", RoITool = roiTool, + InViewRoIs = "InViewRoIs", + mergeUsingFeature = True, + RequireParentView = False, + ViewFallThrough = True, + InViewJets = recordable( f'{jet_name}_Ditau_jets' ), + PlaceJetInView = True) + InputMakerAlg = ditauAcc.inputMaker() + # Tracking + trackingAcc = ditauTrackingCfg( + flags, + inputRoI=InputMakerAlg.InViewRoIs, + inputVertex=prmVtxKey, + inputJets=InputMakerAlg.InViewJets + ) + ditauAcc.mergeReco(trackingAcc) + + # ditau reconstruction + inputJets = InputMakerAlg.InViewJets + inputVertex = prmVtxKey + inputFSTracks = flags.Trigger.InDetTracking.fullScan.tracks_FTF + inputIDTracks = flags.Trigger.InDetTracking.ditau.tracks_IDTrig + inputCells = "CaloCellsFS" + inputClusters = "HLT_TopoCaloClustersFS" + + recoAcc = ditauRecoCfg( + flags, + inputJets=inputJets, + inputVertex=inputVertex, + inputFSTracks=inputFSTracks, + inputTracks=inputIDTracks, + inputCells=inputCells, + inputClusters=inputClusters + ) + + ditauAcc.mergeReco(recoAcc) + + ditauAcc.addRecoAlgo(CompFactory.AthViews.ViewDataVerifier( + name=f'{ditauAcc.name}RecoVDV', + DataObjects={ + ('CaloCellContainer', f'StoreGateSvc+{inputCells}'), + ('xAOD::CaloClusterContainer', f'StoreGateSvc+{inputClusters}'), + ('CaloClusterCellLinkContainer', f'StoreGateSvc+{inputClusters}_links'), + ('xAOD::TrackParticleContainer' , f'StoreGateSvc+{inputFSTracks}'), + } + )) + + selAcc = SelectionCA(f'Trig_DitauReco_{seq_name}') + selAcc.mergeReco(ditauAcc) + selAcc.addHypoAlgo(CompFactory.TrigDiTauHypoAlg( + f'DiTauHypoAlg_{seq_name}', + DiTauJets_key='HLT_DiTauJets', + )) + + from TrigDitauHypo.TrigDiTauHypoTool import TrigDiTauHypoToolFromDict + menuSeq = MenuSequence(flags, selAcc, HypoToolGen=TrigDiTauHypoToolFromDict) + + return menuSeq \ No newline at end of file diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/GenerateDitauChainDefs.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/GenerateDitauChainDefs.py new file mode 100644 index 0000000000000000000000000000000000000000..f8d9210750d4be10d362d9f6568ac17dab419ee7 --- /dev/null +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/GenerateDitauChainDefs.py @@ -0,0 +1,35 @@ +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration + +from TriggerMenuMT.HLT.Config.Utility.ChainDictTools import splitChainDict +from .DitauChainConfiguration import DitauChainConfiguration +from ..Jet.JetChainConfiguration import JetChainConfiguration + +import pprint +from AthenaCommon.Logging import logging +log = logging.getLogger(__name__) +log.debug("Importing %s",__name__) + + +def generateJetChainConfigs(flags, subChainDict): + jet_cfg = JetChainConfiguration(subChainDict) + jet_cfg.prepareDataDependencies(flags) + jet = jet_cfg.assembleChain(flags) + jet_name = jet_cfg.jetName + return jet, jet_name + + +def generateChainConfigs(flags, chainDict, perSig_lengthOfChainConfigs): + + log.debug('full dictionary is: %s\n', pprint.pformat(chainDict)) + listOfChainDicts = splitChainDict(chainDict) + + for subChainDict in listOfChainDicts: + log.debug('Assembling subChainsDict for chain %s', subChainDict['chainName'] ) + Jet, jet_name = generateJetChainConfigs(flags, subChainDict) + Ditau = DitauChainConfiguration(subChainDict, jet_name).assembleChain(flags) + Jet.append_step_to_jet(Ditau.steps) + theChainDef = Jet + + log.debug("theChainDef: %s" , theChainDef) + return theChainDef, perSig_lengthOfChainConfigs + diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/__init__.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Ditau/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Dev_pp_run3_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Dev_pp_run3_v1.py index c88ff28f1902a7614cb8fff2d9eab8c841073b00..88d8b4e620f830872fc5a642e9b99b37e16a689d 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Dev_pp_run3_v1.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Dev_pp_run3_v1.py @@ -19,6 +19,7 @@ from .Physics_pp_run3_v1 import (PhysicsStream, SingleBjetGroup, MultiBjetGroup, SingleTauGroup, + DiTauGroup, MultiTauGroup, MultiPhotonGroup, TauBJetGroup, @@ -614,6 +615,37 @@ def getDevSignatures(): ChainProp(name="HLT_tau160_mediumRNN_trackLRT_L1eTAU140", groups=DevGroup, monGroups=['tauMon:t0']), ] + + chains['Ditau'] = [ + # no id chains + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni0Trk99_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni0Trk55_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni0Trk33_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + # id chain at 0.5 + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni5Trk55_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni5Trk44_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni5Trk33_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + # varias id chain with ntrk 5, 5 cuts + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni6Trk55_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni7Trk55_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni8Trk55_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni9Trk55_pf_jes_ftf_preselj200_L1jJ160', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + #alt L1 seed + # no id chains + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni0Trk99_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni0Trk55_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni0Trk33_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + # id chain at 0.5 + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni5Trk55_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni5Trk44_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni5Trk33_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + # varias id chain with ntrk 5, 5 cuts + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni6Trk55_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni7Trk55_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni8Trk55_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ChainProp(name='HLT_j250_a10sd_cssk_ditauOmni9Trk55_pf_jes_ftf_preselj200_L1gLJ140p0ETA25', l1SeedThresholds=['FSNOSEED'], groups=DiTauGroup+DevGroup), + ] + chains['Bphysics'] = [ #ATR-21003; default dimuon and Bmumux chains from Run2; l2io validation; should not be moved to Physics ChainProp(name='HLT_2mu4_noL2Comb_bJpsimumu_L12MU3V', stream=["BphysDelayed"], groups=BphysicsGroup+DevGroup), diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Physics_pp_run3_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Physics_pp_run3_v1.py index ec9c4aec8e25f1d2bc81e5be68aaaea716a47d8d..984842a36c1e56f90027f74824d9312157c234ba 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Physics_pp_run3_v1.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/Physics_pp_run3_v1.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration #------------------------------------------------------------------------# # Physics_pp_run3_v1.py menu -- contains physics chains for MC and data @@ -24,6 +24,7 @@ EgammaBjetGroup = ['RATE:EgammaBjet', 'BW:BJet'] MuonBjetGroup = ['RATE:MuonBjet', 'BW:BJet'] BjetMETGroup = ['RATE:BjetMET', 'BW:BJet'] SingleTauGroup = ['RATE:SingleTau', 'BW:Tau'] +DiTauGroup = ['RATE:Ditau', 'BW:Tau'] MultiTauGroup = ['RATE:MultiTau', 'BW:Tau'] BphysicsGroup = ['RATE:Bphysics', 'BW:Bphysics'] BphysElectronGroup = ['RATE:BphysicsElectron', 'BW:BphysicsElectron'] diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/SignatureDicts.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/SignatureDicts.py index 6674c10f1cf72fbd6125b255a79379e75cd43117..d06a1cbabea17bf1020411618711d706b5917130 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/SignatureDicts.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/SignatureDicts.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration from AthenaCommon.Logging import logging log = logging.getLogger( __name__ ) log.debug("Importing %s",__name__) @@ -23,6 +23,7 @@ SignatureDict = OrderedDict({ 'Tau' : ('tau','AllTag'), 'Jet' : ('j', 'JetMET'), 'Bjet' : ('', 'JetMET'), + 'Ditau' : ('', 'JetMET'), 'MET' : ('xe', 'JetMET'), 'XS' : ('xs', 'JetMET'), 'TE' : ('te', 'JetMET'), @@ -71,7 +72,7 @@ def getListOfSignatures(): class ChainStore(dict): """Class to hold list of chains for each signature (dictionary with fixed set of keys)""" - _allowedSignatures = ['Egamma', 'Muon', 'Jet', 'Bjet', 'Bphysics', 'MET', 'Tau', + _allowedSignatures = ['Egamma', 'Muon', 'Jet', 'Bjet', 'Bphysics', 'MET', 'Tau', 'Ditau', 'HeavyIon', 'Beamspot', 'Cosmic', 'EnhancedBias', 'Monitor', 'Calib', 'Streaming', 'Combined', 'MinBias', 'UnconventionalTracking', 'Test'] @@ -86,6 +87,15 @@ class ChainStore(dict): else: dict.__setitem__(self, key, value) +# Helper functions +def getAllDitauTags(): + # Create a list of all possible ditau tags + ditau_tags = [] + for id_cut in range(0, 10): + for n_trk_lead in range(3, 10): + for n_trk_subl in range(3, 10): + ditau_tags.append(f'ditauOmni{id_cut}Trk{n_trk_lead}{n_trk_subl}') + return ditau_tags #========================================================== # ---- Generic Template for all chains ---- @@ -476,6 +486,7 @@ JetChainParts = { 'bgn260', 'bgn265', 'bgn270', 'bgn272', 'bgn275', 'bgn277', 'bgn280', 'bgn282', 'bgn285', ], + 'ditauTag' : getAllDitauTags(), 'bTracking' : [], 'bConfig' : ['split',], 'bMatching' : ['antimatchdr05mu'], @@ -526,6 +537,7 @@ JetChainParts_Default = { 'smc' : 'nosmc', # 'bTag' : '', + 'ditauTag' : '', 'bTracking' : '', 'bConfig' : [], 'bMatching' : [], @@ -543,6 +555,10 @@ bJetChainParts_Default = { 'subSigs' : ['Bjet'], } +ditauJetChainParts_Default = { + 'sigFolder' : ['Ditau'], + 'subSigs' : ['Ditau'], +} # ---- Beamspot Dictionary for chains confiugred through jets BeamspotJetChainParts_Default = { 'signature' : 'Beamspot', @@ -1420,6 +1436,8 @@ def getSignatureInformation(signature): return [BeamspotJetChainParts_Default, JetChainParts] if signature == "Tau": return [TauChainParts_Default, TauChainParts] + if signature == "Ditau": + return [ditauJetChainParts_Default, JetChainParts] if (signature == "Muon"): return [MuonChainParts_Default, MuonChainParts] if (signature == "Bphysics"):