From 75268fe3f92cf164105e4d03cef99341cf70952b Mon Sep 17 00:00:00 2001 From: Imanol Corredoira Fernandez <imanol.corredoira.fernandez@cern.ch> Date: Tue, 11 Mar 2025 08:24:51 +0000 Subject: [PATCH 1/8] Reducing the momentum cut in the DY HLT2 line --- Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/drellyan.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/drellyan.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/drellyan.py index dff1de5bdf7..696bd6670b1 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/drellyan.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/drellyan.py @@ -161,11 +161,11 @@ for is_ss in [True, False]: ): pvs = make_pvs() + muon_min_p = 6 * GeV + if use_soft_muons: - muon_min_p = 10.0 * GeV muon_min_pt = 1.0 * GeV else: - muon_min_p = 17.5 * GeV muon_min_pt = 1.3 * GeV dimuons = make_dimuon_candidates( -- GitLab From 981611c9e4f192bb4b6d18ddcdb7b96845cc6455 Mon Sep 17 00:00:00 2001 From: Izaac Sanderswood <izaac.sanderswood@cern.ch> Date: Wed, 12 Mar 2025 12:29:36 +0000 Subject: [PATCH 2/8] Remove unnecessary charge conjugates from decay descriptors --- Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py index 42d3a0be941..b51288d6298 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py @@ -629,7 +629,7 @@ def make_XtoTT_muons(pvs, mass_min=2000.0): filtered_TT_muons, filtered_TT_muons, pvs, - "[KS0 -> mu+ mu-]cc", + "KS0 -> mu+ mu-", mass_min=mass_min, ) @@ -638,7 +638,7 @@ def make_XtoTT_muons(pvs, mass_min=2000.0): def make_XtoTT_kaons(pvs): filtered_TT_kaons = filter_ttrack_kaons_for_high_mass(pvs) return qee_ttrack_combiner_highmass( - filtered_TT_kaons, filtered_TT_kaons, pvs, "[KS0 -> K+ K-]cc" + filtered_TT_kaons, filtered_TT_kaons, pvs, "KS0 -> K+ K-" ) -- GitLab From 4bbea6c67187b3c7cb65b4a881ce7eb84af30641 Mon Sep 17 00:00:00 2001 From: Ross John Hunter <ross.john.hunter@cern.ch> Date: Thu, 13 Mar 2025 11:56:49 +0000 Subject: [PATCH 3/8] Add a HLT1 filter to the Hlt2SingleHighPtMuon lines --- .../python/Hlt2Conf/lines/qee/single_high_pt_muon.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/single_high_pt_muon.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/single_high_pt_muon.py index 8cc398e8ff5..d55da7ce8d1 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/single_high_pt_muon.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/single_high_pt_muon.py @@ -1,5 +1,5 @@ ############################################################################### -# (c) Copyright 2019-2023 CERN for the benefit of the LHCb Collaboration # +# (c) Copyright 2019-2025 CERN for the benefit of the LHCb Collaboration # # # # This software is distributed under the terms of the GNU General Public # # Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # @@ -82,6 +82,7 @@ def single_muon_highpt_line( prescale=prescale, persistreco=persistreco, monitoring_variables=("pt", "eta", "n_candidates"), + hlt1_filter_code=["Hlt1SingleHighPtMuonDecision"], ) @@ -100,6 +101,7 @@ def single_muon_highpt_prescale_line( prescale=prescale, persistreco=persistreco, monitoring_variables=("pt", "eta", "n_candidates"), + hlt1_filter_code=["Hlt1SingleHighPtMuonDecision"], ) @@ -120,6 +122,7 @@ def single_muon_highpt_iso_line( prescale=prescale, persistreco=persistreco, monitoring_variables=("pt", "eta", "n_candidates"), + hlt1_filter_code=["Hlt1SingleHighPtMuonDecision"], ) -- GitLab From bd4bae6e520891de421d47923c3e24be98920941 Mon Sep 17 00:00:00 2001 From: Spencer Collaviti <spencer.edward.collaviti@cern.ch> Date: Mon, 17 Mar 2025 10:53:06 +0000 Subject: [PATCH 4/8] Retune LL and DD HNL Lines --- .../lines/qee/b_to_majolep_majo_to_leplep.py | 44 +++---- .../lines/qee/b_to_majolep_majo_to_leppi.py | 123 ++++++++++++++++-- .../python/Hlt2Conf/lines/qee/qee_builders.py | 4 +- 3 files changed, 137 insertions(+), 34 deletions(-) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leplep.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leplep.py index 7f7f5ecc4e7..2db34009a48 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leplep.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leplep.py @@ -1,5 +1,5 @@ ############################################################################### -# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration # +# (c) Copyright 2025 CERN for the benefit of the LHCb Collaboration # # # # This software is distributed under the terms of the GNU General Public # # Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # @@ -31,8 +31,11 @@ Hlt2QEE_BpToMajoE_MajoToMuE_SS_DD_Tight: tight PID cut line for the B(_c)+ -> e Hlt2QEE_BpToMajoE_MajoToMuE_OS_LL_Tight: tight PID cut line for the B(_c)+ -> e HNL(-> mu- e, LL) Hlt2QEE_BpToMajoE_MajoToMuE_OS_DD_Tight: tight PID cut line for the B(_c)+ -> e HNL(-> mu- e, DD) -Contact: Louis Henry, louis.henry@cern.ch - +Contact: +- Spencer Collaviti, spencer.collaviti@cern.ch +- Andrea Merli, andrea.merli@cern.ch +- Lisa Fantini, lisa.fantini@cern.ch +- Viacheslav Duk, viacheslav.duk@cern.ch """ import Functors as F @@ -93,20 +96,20 @@ def _custom_monitoring_params(pvs, ptName): defaultCutDict = { "LL": { - "AllTracks": {"P": 2000.0 * MeV}, + "AllTracks": {"P": 2000.0 * MeV, "TRCHI2NDOFMAX": 3.0, "GHOSTPROBMAX": 0.4}, "Children": {"MINIPCHI2PV": 200}, "Bachelor": {}, "Child1": {}, "Child2": {}, "Majo": { "FDCHI2MIN": 2000, - "MASS": [0.2 * GeV, 6.0 * GeV], + "MASS": [1.0 * GeV, 6.5 * GeV], "MINIPCHI2PV": 20, }, "B": {"MASS": [4.0 * GeV, 7.0 * GeV]}, }, "DD": { - "AllTracks": {"P": 2000.0 * MeV}, + "AllTracks": {"P": 2000.0 * MeV, "TRCHI2NDOFMAX": 3.0, "GHOSTPROBMAX": 0.4}, "Children": {}, "Bachelor": {}, "Child1": {}, @@ -117,7 +120,7 @@ defaultCutDict = { } child_muon_pidCut = [F.ISMUON, F.PID_MU > 0.0] -bach_muon_pidCut = [F.PID_MU > 2] +bach_muon_pidCut = [F.ISMUON, F.PID_MU > 2] electron_pidCut = [F.PID_E > -2] @@ -136,13 +139,16 @@ def buildFromList(cutList): # Build a cut from a dictionnary -def build_cut_on_track(cutDict, pvs): +def build_cut_on_track(cutDict, pvs, corrm=False): listOfFunctors = [] for cut, cutVal in cutDict.items(): if cut == "PIDCuts": listOfFunctors += cutVal elif cut == "MASS": - listOfFunctors.append(in_range(cutVal[0], F.MASS, cutVal[1])) + if corrm: + listOfFunctors.append(in_range(cutVal[0], F.OWNPVCORRM(), cutVal[1])) + else: + listOfFunctors.append(in_range(cutVal[0], F.MASS, cutVal[1])) else: functors = { "P": F.P, @@ -151,6 +157,8 @@ def build_cut_on_track(cutDict, pvs): "FDCHI2MIN": F.OWNPVFDCHI2, "FDCHI2MAX": F.OWNPVFDCHI2, "MAXDOCA": F.MAXDOCA(), + "TRCHI2NDOFMAX": F.CHI2DOF, + "GHOSTPROBMAX": F.GHOSTPROB, } if "MAX" in cut: listOfFunctors.append(functors[cut] < cutVal) @@ -161,18 +169,12 @@ def build_cut_on_track(cutDict, pvs): return buildFromList(listOfFunctors) -def build_combination_cut(cutDict, pvs): - listOfFunctors = [] - for cut, cutVal in cutDict.items(): - if cut == "MASS": - listOfFunctors.append(in_range(cutVal[0], F.MASS, cutVal[1])) - # Build the cut - return buildFromList(listOfFunctors) - - def builder_BToMajoL_line( - name, bachelorName, children, cutDict={}, prescale=1, persistreco=True + name, bachelorName, children, cutDict=None, prescale=1, persistreco=True ): + if cutDict is None: + cutDict = {} + pvs = make_pvs # Interpret name into a B decay majoDecayDescr = "KS0 -> " + children[0] + "+ " + children[1] + "-" @@ -221,8 +223,7 @@ def builder_BToMajoL_line( [firstChild, secondChild], name="Majo2" + children[0] + children[1] + "_" + recoMode + "_{hash}", DecayDescriptor=majoDecayDescr, - CombinationCut=build_combination_cut(cutDict["Majo"], pvs), - CompositeCut=build_cut_on_track(cutDict["Majo"], pvs), + CompositeCut=build_cut_on_track(cutDict["Majo"], pvs, corrm=True), ) # Bachelor bachelor = make_filter_tracks( @@ -235,7 +236,6 @@ def builder_BToMajoL_line( [majo, bachelor], name=name + "_{hash}", DecayDescriptor="[B+ -> KS0 " + bachelorName + "+]cc", - CombinationCut=build_combination_cut(cutDict["B"], pvs), CompositeCut=build_cut_on_track(cutDict["B"], pvs), ) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leppi.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leppi.py index 251007ac133..59a4e00a129 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leppi.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/b_to_majolep_majo_to_leppi.py @@ -1,5 +1,5 @@ ############################################################################### -# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration # +# (c) Copyright 2025 CERN for the benefit of the LHCb Collaboration # # # # This software is distributed under the terms of the GNU General Public # # Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # @@ -21,6 +21,8 @@ List of lines (LL - Long, DD - downstream): Hlt2QEE_BpToMajoMu_MajoToEPi_LL_Tight: tight PID cut line for the B(_c)+ -> mu HNL(-> epi, LL) Hlt2QEE_BpToMajoE_MajoToMuPi_LL_Tight: tight PID cut line for the B(_c)+ -> e HNL(-> mupi, LL) +Hlt2QEE_BpToMajoMu_MajoToMuPi_LL_Tight: tight PID cut line for the B(_c)+ -> mu HNL(-> mupi, LL) +Hlt2QEE_BpToMajoE_MajoToEPi_LL_Tight: tight PID cut line for the B(_c)+ -> e HNL(-> epi, LL) Hlt2QEE_BpToMajoMu_MajoToEPi_DD_Tight: tight PID cut line for the B(_c)+ -> mu HNL(-> epi, DD) Hlt2QEE_BpToMajoE_MajoToMuPi_DD_Tight: tight PID cut line for the B(_c)+ -> e HNL(-> mupi, DD) @@ -33,9 +35,11 @@ Hlt2QEE_BuToKs0Pi_Ks0ToPiPi_LL: B+ -> pi KS0 (->pipi) LL line Hlt2QEE_BuToKs0Pi_Ks0ToPiPi_DD: B+ -> pi KS0 (->pipi) DD line -Contact: Lera Lukashenko, valeriia.lukashenko@cern.ch -Contact: Louis Henry, louis.henry@cern.ch - +Contact: +- Spencer Collaviti, spencer.collaviti@cern.ch +- Andrea Merli, andrea.merli@cern.ch +- Lisa Fantini, lisa.fantini@cern.ch +- Viacheslav Duk, viacheslav.duk@cern.ch """ import Functors as F @@ -74,7 +78,7 @@ def BpToMajoMu_MajoToEPi_LL_Tight_line( muons = make_majorana_lepton( leptons=make_long_muons, - name="majo_long_muons_{hash}", + name="majo_B_long_muons_{hash}", pvs=pvs, pt_min=700 * MeV, pid=F.ISMUON, @@ -124,7 +128,7 @@ def BpToMajoE_MajoToMuPi_LL_Tight_line( pvs = make_pvs muons = make_majorana_lepton( - leptons=make_long_muons, name="majo_long_muons_{hash}", pvs=pvs, pid=F.ISMUON + leptons=make_long_muons, name="majo_N_long_muons_{hash}", pvs=pvs, pid=F.ISMUON ) electrons_with_brem = make_majorana_lepton( @@ -165,6 +169,105 @@ def BpToMajoE_MajoToMuPi_LL_Tight_line( ) +@register_line_builder(all_lines) +def BpToMajoMu_MajoToMuPi_LL_Tight_line( + name="Hlt2QEE_BpToMajoMu_MajoToMuPi_LL_Tight", prescale=1 +): + pvs = make_pvs + + b_muons = make_majorana_lepton( + leptons=make_long_muons, + name="majo_B_long_muons_{hash}", + pvs=pvs, + pt_min=700 * MeV, + pid=F.ISMUON, + ) + + muons = make_majorana_lepton( + leptons=make_long_muons, name="majo_N_long_muons_{hash}", pvs=pvs, pid=F.ISMUON + ) + + pions = make_majorana_lepton( + leptons=make_long_pions, + name="majo_long_pions_{hash}", + pvs=pvs, + pid=(F.PID_E <= 0.0), + ) + + majoranas2piMu = make_majorana( + name="Majo2mupi_{hash}", + child1=pions, + child2=muons, + descriptor="[KS0 -> mu- pi+]cc", + ) + + b2MuN = make_bhadron_majorana( + name="B2MajoMu_{hash}", + majoranas=majoranas2piMu, + bachelor=b_muons, + pvs=pvs, + descriptor="[B+ -> KS0 mu+]cc", + ) + + return Hlt2Line( + name=name, + algs=hnl_prefilter() + [majoranas2piMu, b2MuN], + prescale=prescale, + monitoring_variables=_HNL_MONITORING_VARIABLES, + ) + + +@register_line_builder(all_lines) +def BpToMajoE_MajoToEPi_LL_Tight_line( + name="Hlt2QEE_BpToMajoE_MajoToEPi_LL_Tight", prescale=1 +): + pvs = make_pvs + + b_electrons_with_brem = make_majorana_lepton( + leptons=make_long_electrons_with_brem, + name="majo_long_electrons_with_brem_{hash}", + pvs=pvs, + pt_min=700 * MeV, + pid=(F.PID_E > 1.0), + ) + + electrons_with_brem = make_majorana_lepton( + leptons=make_long_electrons_with_brem, + name="majo_long_electrons_with_brem_{hash}", + pvs=pvs, + pid=(F.PID_E > 1.0), + ) + + pions = make_majorana_lepton( + leptons=make_long_pions, + name="majo_long_pions_{hash}", + pvs=pvs, + pid=(F.PID_E <= 0.0), + ) + + majoranas2piE = make_majorana( + name="Majo2epi_{hash}", + child1=pions, + child2=electrons_with_brem, + descriptor="[KS0 -> e- pi+]cc", + ) + + b2EN = make_bhadron_majorana( + name="B2MajoE_{hash}", + majoranas=majoranas2piE, + bachelor=b_electrons_with_brem, + pvs=pvs, + descriptor="[B+ -> KS0 e+]cc", + ) + + return Hlt2Line( + name=name, + algs=hnl_prefilter() + [majoranas2piE, b2EN], + prescale=prescale, + monitoring_variables=_HNL_MONITORING_VARIABLES, + ) + + @register_line_builder(all_lines) def BpToMajoMu_MajoToEPi_DD_Tight_line( name="Hlt2QEE_BpToMajoMu_MajoToEPi_DD_Tight", prescale=1 @@ -173,7 +276,7 @@ def BpToMajoMu_MajoToEPi_DD_Tight_line( muons = make_majorana_lepton( leptons=make_long_muons, - name="majo_long_muons_{hash}", + name="majo_B_long_muons_{hash}", pvs=pvs, pt_min=700 * MeV, pid=F.ISMUON, @@ -282,7 +385,7 @@ def BpToMajoMu_MajoToEPi_LL_Loose_line( muons = make_majorana_lepton( leptons=make_long_muons, - name="majo_long_muons_{hash}", + name="majo_B_long_muons_{hash}", pvs=pvs, pt_min=700 * MeV, pid=F.ISMUON, @@ -332,7 +435,7 @@ def BpToMajoE_MajoToMuPi_LL_Loose_line( pvs = make_pvs muons = make_majorana_lepton( - leptons=make_long_muons, name="majo_long_muons_{hash}", pvs=pvs, pid=F.ISMUON + leptons=make_long_muons, name="majo_N_long_muons_{hash}", pvs=pvs, pid=F.ISMUON ) electrons_with_brem = make_majorana_lepton( @@ -381,7 +484,7 @@ def BpToMajoMu_MajoToEPi_DD_Loose_line( muons = make_majorana_lepton( leptons=make_long_muons, - name="majo_long_muons_{hash}", + name="majo_B_long_muons_{hash}", pvs=pvs, pt_min=700 * MeV, pid=F.ISMUON, diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py index b51288d6298..dd9f46f9722 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py @@ -290,8 +290,8 @@ def make_majorana( child2, name="Generic_Majorana", descriptor="", - am_min=0.2 * GeV, - am_max=7.0 * GeV, + am_min=1.0 * GeV, + am_max=6.5 * GeV, adocachi2=16.0, pt_min=0.7 * GeV, vtxchi2_max=9.0, -- GitLab From 61c0a2d573342a5a9ad599e740f130b34d72756f Mon Sep 17 00:00:00 2001 From: Lorenzo Sestini <lorenzo.sestini@cern.ch> Date: Wed, 19 Mar 2025 09:35:35 +0100 Subject: [PATCH 5/8] New lines for multilepton searches --- .../lines/qee/dilepton_persist_leptons.py | 534 ++++++++++++++++++ .../python/Hlt2Conf/lines/qee/hlt2_qee.py | 2 + 2 files changed, 536 insertions(+) create mode 100644 Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py new file mode 100644 index 00000000000..e491bae1a43 --- /dev/null +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py @@ -0,0 +1,534 @@ +############################################################################### +# (c) Copyright 2019-2024 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +""" +Definition of an HLT2 line to preserve dilepton candidates (dimuons or dielectrons) and any other lepton in the event (muon or electron). +Aim for new dark photon searches +Contact: Lorenzo Sestini lorenzo.sestini@cern.ch +""" + +import Functors as F +from Functors.math import in_range +from GaudiKernel.SystemOfUnits import MeV, GeV, mm +from Moore.config import register_line_builder +from Moore.lines import Hlt2Line +from PyConf import configurable +from PyConf.Algorithms import SelectionFromRelationTable, WeightedRelTableAlg +from RecoConf.algorithms_thor import ParticleCombiner, ParticleFilter +from RecoConf.event_filters import require_pvs +from RecoConf.reconstruction_objects import make_pvs, upfront_reconstruction +from RecoConf.standard_particles import ( + make_detached_dielectron_with_brem, + make_long_electrons_no_brem, + make_long_electrons_with_brem, + make_prompt_dielectron_with_brem, + make_ismuon_long_muon +) + +full_lines = {} +turbo_lines = {} + +#Mass limits now accepts all possible dilepton+lepton combination. May be reduced in the future. +comb_mass_limits = (0.0 * GeV, 14000.0 * GeV) +# NOTE: No dielectron mass monitors allowed (custom or default) to avoid potential unblinding. +_default_monitoring_variables = ("pt", "eta", "n_candidates", "ipchi2", "vchi2") + + +@configurable +def muon_filter(pvs, make_particles=make_ismuon_long_muon, min_ipchi2=0, pid_mu=-10, p_min=5 * GeV, pt_min=0.0 * GeV): + muon_requirements = F.require_all( + F.P >= p_min, + F.PT >= pt_min, + F.MINIPCHI2CUT(IPChi2Cut=min_ipchi2, Vertices=pvs), + ) + if pid_mu: + muon_requirements = (F.PID_MU > pid_mu) & muon_requirements + return ParticleFilter(make_particles(), F.FILTER(muon_requirements)) + +@configurable +def electron_filter(make_particles=make_long_electrons_with_brem, p_min=5 * GeV, pid_e=0.0, pt_min=0.0 * GeV): + electron_requirements = F.require_all( + F.P >= p_min, + F.PT >= pt_min, + F.PID_E >= pid_e, + ) + + return ParticleFilter(make_particles(), F.FILTER(electron_requirements)) + +@configurable +def dimuon_maker( + pvs, + comb_maxdoca=0.1 * mm, + vchi2pdof_max=9, + min_pt_prod=1 * GeV * GeV, + min_ipchi2=0, + min_mass=2 * F.PDG_MASS("mu+"), + max_mass=110 * GeV, + isOS=True, + pid_mu=-10, + ownpvvdchi2_min=0, +): + muons = make_ismuon_long_muon + filtered_muons = muon_filter(pvs, muons, min_ipchi2, pid_mu) + combination_code = F.require_all( + F.MAXSDOCACUT(comb_maxdoca), + F.CHILD(1, F.PT) * F.CHILD(2, F.PT) > min_pt_prod, + in_range(min_mass, F.MASS, max_mass), + ) + vertex_code = F.require_all( + F.CHI2DOF < vchi2pdof_max, F.OWNPVFDCHI2 > ownpvvdchi2_min + ) + if isOS: + DecayDescriptor = "J/psi(1S) -> mu+ mu-" + else: + DecayDescriptor = "[J/psi(1S) -> mu+ mu+]cc" + return ParticleCombiner( + Inputs=[filtered_muons, filtered_muons], + DecayDescriptor=DecayDescriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code, + ) + + +@configurable +def dielectron_maker_prompt(e_minpt, isOS): + return make_prompt_dielectron_with_brem( + electron_maker=make_long_electrons_no_brem, + opposite_sign=isOS, + PIDe_min=0.0, + pt_e=e_minpt, + maxipchi2=2.0, + trghostprob=0.25, + dielectron_ID="J/psi(1S)", + pt_diE=0 * MeV, + m_diE_min=5 * MeV, + m_diE_max=300 * MeV, + adocachi2cut=30, + bpvvdchi2=None, + vfaspfchi2ndof=10, + ) + + +@configurable +def dielectron_maker_displaced(e_minpt, isOS): + return make_detached_dielectron_with_brem( + electron_maker=make_long_electrons_no_brem, + opposite_sign=isOS, + PIDe_min=0.0, + pt_e=e_minpt, + minipchi2=2.0, + trghostprob=0.25, + dielectron_ID="J/psi(1S)", + pt_diE=0 * MeV, + m_diE_min=5 * MeV, + m_diE_max=300 * MeV, + adocachi2cut=30, + bpvvdchi2=0, + vfaspfchi2ndof=10, + ) + + +# OS Prompt lines +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_prompt_line( + name="Hlt2QEE_DiMuonPrompt_PersistMuEl", + prescale=1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in prompt mu+mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_prompt = dimuon_maker(pvs) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIPDecision"], + ) + + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_prompt_line( + name="Hlt2QEE_DiElectronPrompt_PersistMuEl", + prescale=1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in prompt e+e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=True) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_promptDecision"], + ) + +# OS displaced lines +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_displaced_line( + name="Hlt2QEE_DiMuonDisplaced_PersistMuEl", + prescale=1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in prompt mu+mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_displaced = dimuon_maker(pvs, min_ipchi2=16, ownpvvdchi2_min=30) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIPDecision"], + ) + + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_displaced_line( + name="Hlt2QEE_DiElectronDisplaced_PersistMuEl", + prescale=1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in prompt e+e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_displaced = dielectron_maker_displaced(e_minpt, isOS=True) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronDisplaced_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronDisplaced_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_displacedDecision"], + ) + +#SS lines +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_prompt_same_sign_line( + name="Hlt2QEE_DiMuonPrompt_PersistMuElSS", + prescale=0.1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in prompt mu+mu+/mu-mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_prompt = dimuon_maker(pvs,isOS=False) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], + ) + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_prompt_same_sign_line( + name="Hlt2QEE_DiElectronPrompt_PersistMuElSS", + prescale=0.1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in prompt e+e+/e-e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=False) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_ss_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_ss_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_SS_massSlice.*_promptDecision"], + ) + + +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_displaced_same_sign_line( + name="Hlt2QEE_DiMuonDisplaced_PersistMuElSS", + prescale=0.1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in displaced mu+mu+/mu-mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_displaced = dimuon_maker(pvs, min_ipchi2=16, ownpvvdchi2_min=30, isOS=False) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], + ) + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_displaced_same_sign_line( + name="Hlt2QEE_DiElectronDisplaced_PersistElSS", + prescale=0.1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in displaced e+e+/e-e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_displaced = dielectron_maker_displaced(e_minpt, isOS=False) + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronDisplaced_ss_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronDisplaced_ss_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_SS_massSlice.*_displacedDecision"], + ) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py index 38d4f9eb548..3c951e4f623 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py @@ -17,6 +17,7 @@ from Hlt2Conf.lines.qee import ( b_to_majolep_majo_to_leppi, busca, dielectron_persist_photons, + dilepton_persist_leptons, dimuon_no_ip, diphoton, drellyan, @@ -50,6 +51,7 @@ turbo_lines.update(diphoton.all_lines) turbo_lines.update(dimuon_no_ip.turbo_lines) turbo_lines.update(drellyan.all_lines) turbo_lines.update(dielectron_persist_photons.turbo_lines) +turbo_lines.update(dilepton_persist_leptons.turbo_lines) turbo_lines.update(wz_boson_rare_decays.all_lines) turbo_lines.update(ttrack_llps.turbo_lines) turbo_lines.update(muon_detector_showers.all_lines) -- GitLab From 661bbd8bf14ce7a7346edb88ba949d005d30d2de Mon Sep 17 00:00:00 2001 From: Lorenzo Sestini <lorenzo.sestini@cern.ch> Date: Wed, 19 Mar 2025 09:41:24 +0100 Subject: [PATCH 6/8] Reverting to previous version --- .../lines/qee/dilepton_persist_leptons.py | 534 ------------------ .../python/Hlt2Conf/lines/qee/hlt2_qee.py | 2 - 2 files changed, 536 deletions(-) delete mode 100644 Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py deleted file mode 100644 index e491bae1a43..00000000000 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py +++ /dev/null @@ -1,534 +0,0 @@ -############################################################################### -# (c) Copyright 2019-2024 CERN for the benefit of the LHCb Collaboration # -# # -# This software is distributed under the terms of the GNU General Public # -# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # -# # -# In applying this licence, CERN does not waive the privileges and immunities # -# granted to it by virtue of its status as an Intergovernmental Organization # -# or submit itself to any jurisdiction. # -############################################################################### -""" -Definition of an HLT2 line to preserve dilepton candidates (dimuons or dielectrons) and any other lepton in the event (muon or electron). -Aim for new dark photon searches -Contact: Lorenzo Sestini lorenzo.sestini@cern.ch -""" - -import Functors as F -from Functors.math import in_range -from GaudiKernel.SystemOfUnits import MeV, GeV, mm -from Moore.config import register_line_builder -from Moore.lines import Hlt2Line -from PyConf import configurable -from PyConf.Algorithms import SelectionFromRelationTable, WeightedRelTableAlg -from RecoConf.algorithms_thor import ParticleCombiner, ParticleFilter -from RecoConf.event_filters import require_pvs -from RecoConf.reconstruction_objects import make_pvs, upfront_reconstruction -from RecoConf.standard_particles import ( - make_detached_dielectron_with_brem, - make_long_electrons_no_brem, - make_long_electrons_with_brem, - make_prompt_dielectron_with_brem, - make_ismuon_long_muon -) - -full_lines = {} -turbo_lines = {} - -#Mass limits now accepts all possible dilepton+lepton combination. May be reduced in the future. -comb_mass_limits = (0.0 * GeV, 14000.0 * GeV) -# NOTE: No dielectron mass monitors allowed (custom or default) to avoid potential unblinding. -_default_monitoring_variables = ("pt", "eta", "n_candidates", "ipchi2", "vchi2") - - -@configurable -def muon_filter(pvs, make_particles=make_ismuon_long_muon, min_ipchi2=0, pid_mu=-10, p_min=5 * GeV, pt_min=0.0 * GeV): - muon_requirements = F.require_all( - F.P >= p_min, - F.PT >= pt_min, - F.MINIPCHI2CUT(IPChi2Cut=min_ipchi2, Vertices=pvs), - ) - if pid_mu: - muon_requirements = (F.PID_MU > pid_mu) & muon_requirements - return ParticleFilter(make_particles(), F.FILTER(muon_requirements)) - -@configurable -def electron_filter(make_particles=make_long_electrons_with_brem, p_min=5 * GeV, pid_e=0.0, pt_min=0.0 * GeV): - electron_requirements = F.require_all( - F.P >= p_min, - F.PT >= pt_min, - F.PID_E >= pid_e, - ) - - return ParticleFilter(make_particles(), F.FILTER(electron_requirements)) - -@configurable -def dimuon_maker( - pvs, - comb_maxdoca=0.1 * mm, - vchi2pdof_max=9, - min_pt_prod=1 * GeV * GeV, - min_ipchi2=0, - min_mass=2 * F.PDG_MASS("mu+"), - max_mass=110 * GeV, - isOS=True, - pid_mu=-10, - ownpvvdchi2_min=0, -): - muons = make_ismuon_long_muon - filtered_muons = muon_filter(pvs, muons, min_ipchi2, pid_mu) - combination_code = F.require_all( - F.MAXSDOCACUT(comb_maxdoca), - F.CHILD(1, F.PT) * F.CHILD(2, F.PT) > min_pt_prod, - in_range(min_mass, F.MASS, max_mass), - ) - vertex_code = F.require_all( - F.CHI2DOF < vchi2pdof_max, F.OWNPVFDCHI2 > ownpvvdchi2_min - ) - if isOS: - DecayDescriptor = "J/psi(1S) -> mu+ mu-" - else: - DecayDescriptor = "[J/psi(1S) -> mu+ mu+]cc" - return ParticleCombiner( - Inputs=[filtered_muons, filtered_muons], - DecayDescriptor=DecayDescriptor, - CombinationCut=combination_code, - CompositeCut=vertex_code, - ) - - -@configurable -def dielectron_maker_prompt(e_minpt, isOS): - return make_prompt_dielectron_with_brem( - electron_maker=make_long_electrons_no_brem, - opposite_sign=isOS, - PIDe_min=0.0, - pt_e=e_minpt, - maxipchi2=2.0, - trghostprob=0.25, - dielectron_ID="J/psi(1S)", - pt_diE=0 * MeV, - m_diE_min=5 * MeV, - m_diE_max=300 * MeV, - adocachi2cut=30, - bpvvdchi2=None, - vfaspfchi2ndof=10, - ) - - -@configurable -def dielectron_maker_displaced(e_minpt, isOS): - return make_detached_dielectron_with_brem( - electron_maker=make_long_electrons_no_brem, - opposite_sign=isOS, - PIDe_min=0.0, - pt_e=e_minpt, - minipchi2=2.0, - trghostprob=0.25, - dielectron_ID="J/psi(1S)", - pt_diE=0 * MeV, - m_diE_min=5 * MeV, - m_diE_max=300 * MeV, - adocachi2cut=30, - bpvvdchi2=0, - vfaspfchi2ndof=10, - ) - - -# OS Prompt lines -@register_line_builder(turbo_lines) -@configurable -def dimuon_mu_el_prompt_line( - name="Hlt2QEE_DiMuonPrompt_PersistMuEl", - prescale=1, - persistreco=False, - make_pvs=make_pvs, -): - """This line save muons in prompt mu+mu- events and any other muon/electron""" - pvs = make_pvs() - - dimuons_prompt = dimuon_maker(pvs) - - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs, pt_min=5 * GeV), - ReferenceParticles=dimuons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dimuons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_prompt], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronPrompt_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronPrompt_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiMuonNoIPDecision"], - ) - - -@register_line_builder(turbo_lines) -@configurable -def dielectron_mu_el_prompt_line( - name="Hlt2QEE_DiElectronPrompt_PersistMuEl", - prescale=1, - persistreco=False, - e_minpt=0.0, - make_pvs=make_pvs, -): - """This line save electrons in prompt e+e- events and any other muon/electron""" - pvs = make_pvs() - - dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=True) - - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs,pt_min=5 * GeV), - ReferenceParticles=dielectrons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dielectrons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_prompt], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronPrompt_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronPrompt_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_promptDecision"], - ) - -# OS displaced lines -@register_line_builder(turbo_lines) -@configurable -def dimuon_mu_el_displaced_line( - name="Hlt2QEE_DiMuonDisplaced_PersistMuEl", - prescale=1, - persistreco=False, - make_pvs=make_pvs, -): - """This line save muons in prompt mu+mu- events and any other muon/electron""" - pvs = make_pvs() - - dimuons_displaced = dimuon_maker(pvs, min_ipchi2=16, ownpvvdchi2_min=30) - - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs, pt_min=5 * GeV), - ReferenceParticles=dimuons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dimuons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_displaced], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronPrompt_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronPrompt_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiMuonNoIPDecision"], - ) - - -@register_line_builder(turbo_lines) -@configurable -def dielectron_mu_el_displaced_line( - name="Hlt2QEE_DiElectronDisplaced_PersistMuEl", - prescale=1, - persistreco=False, - e_minpt=0.0, - make_pvs=make_pvs, -): - """This line save electrons in prompt e+e- events and any other muon/electron""" - pvs = make_pvs() - - dielectrons_displaced = dielectron_maker_displaced(e_minpt, isOS=True) - - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs, pt_min=5 * GeV), - ReferenceParticles=dielectrons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dielectrons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_displaced], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronDisplaced_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronDisplaced_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_displacedDecision"], - ) - -#SS lines -@register_line_builder(turbo_lines) -@configurable -def dimuon_mu_el_prompt_same_sign_line( - name="Hlt2QEE_DiMuonPrompt_PersistMuElSS", - prescale=0.1, - persistreco=False, - make_pvs=make_pvs, -): - """This line save muons in prompt mu+mu+/mu-mu- events and any other muon/electron""" - pvs = make_pvs() - - dimuons_prompt = dimuon_maker(pvs,isOS=False) - - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs,pt_min=5 * GeV), - ReferenceParticles=dimuons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dimuons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_prompt], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronPrompt_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronPrompt_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], - ) - -@register_line_builder(turbo_lines) -@configurable -def dielectron_mu_el_prompt_same_sign_line( - name="Hlt2QEE_DiElectronPrompt_PersistMuElSS", - prescale=0.1, - persistreco=False, - e_minpt=0.0, - make_pvs=make_pvs, -): - """This line save electrons in prompt e+e+/e-e- events and any other muon/electron""" - pvs = make_pvs() - - dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=False) - - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs,pt_min=5 * GeV), - ReferenceParticles=dielectrons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dielectrons_prompt, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_prompt], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronPrompt_ss_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronPrompt_ss_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiElectronLowMass_SS_massSlice.*_promptDecision"], - ) - - -@register_line_builder(turbo_lines) -@configurable -def dimuon_mu_el_displaced_same_sign_line( - name="Hlt2QEE_DiMuonDisplaced_PersistMuElSS", - prescale=0.1, - persistreco=False, - make_pvs=make_pvs, -): - """This line save muons in displaced mu+mu+/mu-mu- events and any other muon/electron""" - pvs = make_pvs() - - dimuons_displaced = dimuon_maker(pvs, min_ipchi2=16, ownpvvdchi2_min=30, isOS=False) - - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs, pt_min=5 * GeV), - ReferenceParticles=dimuons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dimuons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_displaced], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronPrompt_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronPrompt_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], - ) - -@register_line_builder(turbo_lines) -@configurable -def dielectron_mu_el_displaced_same_sign_line( - name="Hlt2QEE_DiElectronDisplaced_PersistElSS", - prescale=0.1, - persistreco=False, - e_minpt=0.0, - make_pvs=make_pvs, -): - """This line save electrons in displaced e+e+/e-e- events and any other muon/electron""" - pvs = make_pvs() - - dielectrons_displaced = dielectron_maker_displaced(e_minpt, isOS=False) - muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs, pt_min=5 * GeV), - ReferenceParticles=dielectrons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - electrons_table = WeightedRelTableAlg( - InputCandidates=electron_filter(pt_min=5 * GeV), - ReferenceParticles=dielectrons_displaced, - Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), - ) - - return Hlt2Line( - name=name, - algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_displaced], - persistreco=persistreco, - extra_outputs=[ - ( - "DiElectronDisplaced_ss_Muons", - SelectionFromRelationTable( - InputRelations=muons_table.OutputRelations - ).OutputLocation, - ), - ( - "DiElectronDisplaced_ss_Electrons", - SelectionFromRelationTable( - InputRelations=electrons_table.OutputRelations - ).OutputLocation, - ) - ], - prescale=prescale, - monitoring_variables=_default_monitoring_variables, - hlt1_filter_code=["Hlt1DiElectronLowMass_SS_massSlice.*_displacedDecision"], - ) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py index 3c951e4f623..38d4f9eb548 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py @@ -17,7 +17,6 @@ from Hlt2Conf.lines.qee import ( b_to_majolep_majo_to_leppi, busca, dielectron_persist_photons, - dilepton_persist_leptons, dimuon_no_ip, diphoton, drellyan, @@ -51,7 +50,6 @@ turbo_lines.update(diphoton.all_lines) turbo_lines.update(dimuon_no_ip.turbo_lines) turbo_lines.update(drellyan.all_lines) turbo_lines.update(dielectron_persist_photons.turbo_lines) -turbo_lines.update(dilepton_persist_leptons.turbo_lines) turbo_lines.update(wz_boson_rare_decays.all_lines) turbo_lines.update(ttrack_llps.turbo_lines) turbo_lines.update(muon_detector_showers.all_lines) -- GitLab From bbcd19dbbbe7a0b5cdee6a3527c2645ab1a56ae0 Mon Sep 17 00:00:00 2001 From: Lorenzo Sestini <lorenzo.sestini@cern.ch> Date: Wed, 19 Mar 2025 10:13:54 +0100 Subject: [PATCH 7/8] New multilepton lines saved --- .../lines/qee/dilepton_persist_leptons.py | 534 ++++++++++++++++++ .../python/Hlt2Conf/lines/qee/hlt2_qee.py | 2 + 2 files changed, 536 insertions(+) create mode 100644 Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py new file mode 100644 index 00000000000..e491bae1a43 --- /dev/null +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py @@ -0,0 +1,534 @@ +############################################################################### +# (c) Copyright 2019-2024 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +""" +Definition of an HLT2 line to preserve dilepton candidates (dimuons or dielectrons) and any other lepton in the event (muon or electron). +Aim for new dark photon searches +Contact: Lorenzo Sestini lorenzo.sestini@cern.ch +""" + +import Functors as F +from Functors.math import in_range +from GaudiKernel.SystemOfUnits import MeV, GeV, mm +from Moore.config import register_line_builder +from Moore.lines import Hlt2Line +from PyConf import configurable +from PyConf.Algorithms import SelectionFromRelationTable, WeightedRelTableAlg +from RecoConf.algorithms_thor import ParticleCombiner, ParticleFilter +from RecoConf.event_filters import require_pvs +from RecoConf.reconstruction_objects import make_pvs, upfront_reconstruction +from RecoConf.standard_particles import ( + make_detached_dielectron_with_brem, + make_long_electrons_no_brem, + make_long_electrons_with_brem, + make_prompt_dielectron_with_brem, + make_ismuon_long_muon +) + +full_lines = {} +turbo_lines = {} + +#Mass limits now accepts all possible dilepton+lepton combination. May be reduced in the future. +comb_mass_limits = (0.0 * GeV, 14000.0 * GeV) +# NOTE: No dielectron mass monitors allowed (custom or default) to avoid potential unblinding. +_default_monitoring_variables = ("pt", "eta", "n_candidates", "ipchi2", "vchi2") + + +@configurable +def muon_filter(pvs, make_particles=make_ismuon_long_muon, min_ipchi2=0, pid_mu=-10, p_min=5 * GeV, pt_min=0.0 * GeV): + muon_requirements = F.require_all( + F.P >= p_min, + F.PT >= pt_min, + F.MINIPCHI2CUT(IPChi2Cut=min_ipchi2, Vertices=pvs), + ) + if pid_mu: + muon_requirements = (F.PID_MU > pid_mu) & muon_requirements + return ParticleFilter(make_particles(), F.FILTER(muon_requirements)) + +@configurable +def electron_filter(make_particles=make_long_electrons_with_brem, p_min=5 * GeV, pid_e=0.0, pt_min=0.0 * GeV): + electron_requirements = F.require_all( + F.P >= p_min, + F.PT >= pt_min, + F.PID_E >= pid_e, + ) + + return ParticleFilter(make_particles(), F.FILTER(electron_requirements)) + +@configurable +def dimuon_maker( + pvs, + comb_maxdoca=0.1 * mm, + vchi2pdof_max=9, + min_pt_prod=1 * GeV * GeV, + min_ipchi2=0, + min_mass=2 * F.PDG_MASS("mu+"), + max_mass=110 * GeV, + isOS=True, + pid_mu=-10, + ownpvvdchi2_min=0, +): + muons = make_ismuon_long_muon + filtered_muons = muon_filter(pvs, muons, min_ipchi2, pid_mu) + combination_code = F.require_all( + F.MAXSDOCACUT(comb_maxdoca), + F.CHILD(1, F.PT) * F.CHILD(2, F.PT) > min_pt_prod, + in_range(min_mass, F.MASS, max_mass), + ) + vertex_code = F.require_all( + F.CHI2DOF < vchi2pdof_max, F.OWNPVFDCHI2 > ownpvvdchi2_min + ) + if isOS: + DecayDescriptor = "J/psi(1S) -> mu+ mu-" + else: + DecayDescriptor = "[J/psi(1S) -> mu+ mu+]cc" + return ParticleCombiner( + Inputs=[filtered_muons, filtered_muons], + DecayDescriptor=DecayDescriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code, + ) + + +@configurable +def dielectron_maker_prompt(e_minpt, isOS): + return make_prompt_dielectron_with_brem( + electron_maker=make_long_electrons_no_brem, + opposite_sign=isOS, + PIDe_min=0.0, + pt_e=e_minpt, + maxipchi2=2.0, + trghostprob=0.25, + dielectron_ID="J/psi(1S)", + pt_diE=0 * MeV, + m_diE_min=5 * MeV, + m_diE_max=300 * MeV, + adocachi2cut=30, + bpvvdchi2=None, + vfaspfchi2ndof=10, + ) + + +@configurable +def dielectron_maker_displaced(e_minpt, isOS): + return make_detached_dielectron_with_brem( + electron_maker=make_long_electrons_no_brem, + opposite_sign=isOS, + PIDe_min=0.0, + pt_e=e_minpt, + minipchi2=2.0, + trghostprob=0.25, + dielectron_ID="J/psi(1S)", + pt_diE=0 * MeV, + m_diE_min=5 * MeV, + m_diE_max=300 * MeV, + adocachi2cut=30, + bpvvdchi2=0, + vfaspfchi2ndof=10, + ) + + +# OS Prompt lines +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_prompt_line( + name="Hlt2QEE_DiMuonPrompt_PersistMuEl", + prescale=1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in prompt mu+mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_prompt = dimuon_maker(pvs) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIPDecision"], + ) + + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_prompt_line( + name="Hlt2QEE_DiElectronPrompt_PersistMuEl", + prescale=1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in prompt e+e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=True) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_promptDecision"], + ) + +# OS displaced lines +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_displaced_line( + name="Hlt2QEE_DiMuonDisplaced_PersistMuEl", + prescale=1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in prompt mu+mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_displaced = dimuon_maker(pvs, min_ipchi2=16, ownpvvdchi2_min=30) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIPDecision"], + ) + + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_displaced_line( + name="Hlt2QEE_DiElectronDisplaced_PersistMuEl", + prescale=1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in prompt e+e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_displaced = dielectron_maker_displaced(e_minpt, isOS=True) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronDisplaced_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronDisplaced_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_displacedDecision"], + ) + +#SS lines +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_prompt_same_sign_line( + name="Hlt2QEE_DiMuonPrompt_PersistMuElSS", + prescale=0.1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in prompt mu+mu+/mu-mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_prompt = dimuon_maker(pvs,isOS=False) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], + ) + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_prompt_same_sign_line( + name="Hlt2QEE_DiElectronPrompt_PersistMuElSS", + prescale=0.1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in prompt e+e+/e-e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=False) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_prompt, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_prompt], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_ss_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_ss_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_SS_massSlice.*_promptDecision"], + ) + + +@register_line_builder(turbo_lines) +@configurable +def dimuon_mu_el_displaced_same_sign_line( + name="Hlt2QEE_DiMuonDisplaced_PersistMuElSS", + prescale=0.1, + persistreco=False, + make_pvs=make_pvs, +): + """This line save muons in displaced mu+mu+/mu-mu- events and any other muon/electron""" + pvs = make_pvs() + + dimuons_displaced = dimuon_maker(pvs, min_ipchi2=16, ownpvvdchi2_min=30, isOS=False) + + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dimuons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronPrompt_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronPrompt_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], + ) + +@register_line_builder(turbo_lines) +@configurable +def dielectron_mu_el_displaced_same_sign_line( + name="Hlt2QEE_DiElectronDisplaced_PersistElSS", + prescale=0.1, + persistreco=False, + e_minpt=0.0, + make_pvs=make_pvs, +): + """This line save electrons in displaced e+e+/e-e- events and any other muon/electron""" + pvs = make_pvs() + + dielectrons_displaced = dielectron_maker_displaced(e_minpt, isOS=False) + muons_table = WeightedRelTableAlg( + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + electrons_table = WeightedRelTableAlg( + InputCandidates=electron_filter(pt_min=5 * GeV), + ReferenceParticles=dielectrons_displaced, + Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), + ) + + return Hlt2Line( + name=name, + algs=upfront_reconstruction() + [require_pvs(pvs), dielectrons_displaced], + persistreco=persistreco, + extra_outputs=[ + ( + "DiElectronDisplaced_ss_Muons", + SelectionFromRelationTable( + InputRelations=muons_table.OutputRelations + ).OutputLocation, + ), + ( + "DiElectronDisplaced_ss_Electrons", + SelectionFromRelationTable( + InputRelations=electrons_table.OutputRelations + ).OutputLocation, + ) + ], + prescale=prescale, + monitoring_variables=_default_monitoring_variables, + hlt1_filter_code=["Hlt1DiElectronLowMass_SS_massSlice.*_displacedDecision"], + ) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py index 38d4f9eb548..3c951e4f623 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py @@ -17,6 +17,7 @@ from Hlt2Conf.lines.qee import ( b_to_majolep_majo_to_leppi, busca, dielectron_persist_photons, + dilepton_persist_leptons, dimuon_no_ip, diphoton, drellyan, @@ -50,6 +51,7 @@ turbo_lines.update(diphoton.all_lines) turbo_lines.update(dimuon_no_ip.turbo_lines) turbo_lines.update(drellyan.all_lines) turbo_lines.update(dielectron_persist_photons.turbo_lines) +turbo_lines.update(dilepton_persist_leptons.turbo_lines) turbo_lines.update(wz_boson_rare_decays.all_lines) turbo_lines.update(ttrack_llps.turbo_lines) turbo_lines.update(muon_detector_showers.all_lines) -- GitLab From 494840b5c0799d2ed9aaae66fedf7ed6f2bbb57c Mon Sep 17 00:00:00 2001 From: Gitlab CI <noreply@cern.ch> Date: Wed, 19 Mar 2025 09:14:56 +0000 Subject: [PATCH 8/8] pre-commit fixes patch generated by https://gitlab.cern.ch/lhcb/Moore/-/jobs/52958354 --- .../lines/qee/dilepton_persist_leptons.py | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py index e491bae1a43..95d9dda56b2 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py @@ -16,7 +16,7 @@ Contact: Lorenzo Sestini lorenzo.sestini@cern.ch import Functors as F from Functors.math import in_range -from GaudiKernel.SystemOfUnits import MeV, GeV, mm +from GaudiKernel.SystemOfUnits import GeV, MeV, mm from Moore.config import register_line_builder from Moore.lines import Hlt2Line from PyConf import configurable @@ -26,23 +26,30 @@ from RecoConf.event_filters import require_pvs from RecoConf.reconstruction_objects import make_pvs, upfront_reconstruction from RecoConf.standard_particles import ( make_detached_dielectron_with_brem, + make_ismuon_long_muon, make_long_electrons_no_brem, make_long_electrons_with_brem, make_prompt_dielectron_with_brem, - make_ismuon_long_muon ) full_lines = {} turbo_lines = {} -#Mass limits now accepts all possible dilepton+lepton combination. May be reduced in the future. +# Mass limits now accepts all possible dilepton+lepton combination. May be reduced in the future. comb_mass_limits = (0.0 * GeV, 14000.0 * GeV) # NOTE: No dielectron mass monitors allowed (custom or default) to avoid potential unblinding. _default_monitoring_variables = ("pt", "eta", "n_candidates", "ipchi2", "vchi2") @configurable -def muon_filter(pvs, make_particles=make_ismuon_long_muon, min_ipchi2=0, pid_mu=-10, p_min=5 * GeV, pt_min=0.0 * GeV): +def muon_filter( + pvs, + make_particles=make_ismuon_long_muon, + min_ipchi2=0, + pid_mu=-10, + p_min=5 * GeV, + pt_min=0.0 * GeV, +): muon_requirements = F.require_all( F.P >= p_min, F.PT >= pt_min, @@ -52,8 +59,14 @@ def muon_filter(pvs, make_particles=make_ismuon_long_muon, min_ipchi2=0, pid_mu= muon_requirements = (F.PID_MU > pid_mu) & muon_requirements return ParticleFilter(make_particles(), F.FILTER(muon_requirements)) + @configurable -def electron_filter(make_particles=make_long_electrons_with_brem, p_min=5 * GeV, pid_e=0.0, pt_min=0.0 * GeV): +def electron_filter( + make_particles=make_long_electrons_with_brem, + p_min=5 * GeV, + pid_e=0.0, + pt_min=0.0 * GeV, +): electron_requirements = F.require_all( F.P >= p_min, F.PT >= pt_min, @@ -62,6 +75,7 @@ def electron_filter(make_particles=make_long_electrons_with_brem, p_min=5 * GeV, return ParticleFilter(make_particles(), F.FILTER(electron_requirements)) + @configurable def dimuon_maker( pvs, @@ -177,8 +191,7 @@ def dimuon_mu_el_prompt_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) - + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, @@ -201,7 +214,7 @@ def dielectron_mu_el_prompt_line( dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=True) muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), ReferenceParticles=dielectrons_prompt, Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), ) @@ -228,14 +241,14 @@ def dielectron_mu_el_prompt_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) - + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_promptDecision"], ) + # OS displaced lines @register_line_builder(turbo_lines) @configurable @@ -278,8 +291,7 @@ def dimuon_mu_el_displaced_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) - + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, @@ -329,14 +341,15 @@ def dielectron_mu_el_displaced_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, hlt1_filter_code=["Hlt1DiElectronLowMass_massSlice.*_displacedDecision"], ) -#SS lines + +# SS lines @register_line_builder(turbo_lines) @configurable def dimuon_mu_el_prompt_same_sign_line( @@ -348,10 +361,10 @@ def dimuon_mu_el_prompt_same_sign_line( """This line save muons in prompt mu+mu+/mu-mu- events and any other muon/electron""" pvs = make_pvs() - dimuons_prompt = dimuon_maker(pvs,isOS=False) + dimuons_prompt = dimuon_maker(pvs, isOS=False) muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), ReferenceParticles=dimuons_prompt, Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), ) @@ -378,14 +391,14 @@ def dimuon_mu_el_prompt_same_sign_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) - + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], ) + @register_line_builder(turbo_lines) @configurable def dielectron_mu_el_prompt_same_sign_line( @@ -401,7 +414,7 @@ def dielectron_mu_el_prompt_same_sign_line( dielectrons_prompt = dielectron_maker_prompt(e_minpt, isOS=False) muons_table = WeightedRelTableAlg( - InputCandidates=muon_filter(pvs,pt_min=5 * GeV), + InputCandidates=muon_filter(pvs, pt_min=5 * GeV), ReferenceParticles=dielectrons_prompt, Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), ) @@ -428,7 +441,7 @@ def dielectron_mu_el_prompt_same_sign_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, @@ -460,7 +473,7 @@ def dimuon_mu_el_displaced_same_sign_line( ReferenceParticles=dimuons_displaced, Cut=in_range(comb_mass_limits[0], F.COMB_MASS(), comb_mass_limits[1]), ) - + return Hlt2Line( name=name, algs=upfront_reconstruction() + [require_pvs(pvs), dimuons_displaced], @@ -477,14 +490,14 @@ def dimuon_mu_el_displaced_same_sign_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) - + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, hlt1_filter_code=["Hlt1DiMuonNoIP_SSDecision"], ) + @register_line_builder(turbo_lines) @configurable def dielectron_mu_el_displaced_same_sign_line( @@ -526,7 +539,7 @@ def dielectron_mu_el_displaced_same_sign_line( SelectionFromRelationTable( InputRelations=electrons_table.OutputRelations ).OutputLocation, - ) + ), ], prescale=prescale, monitoring_variables=_default_monitoring_variables, -- GitLab