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 7f7f5ecc4e7a9e95150fc5b0838336049b853e2b..2db34009a4895403ce4e59f9afc81e3d88840cd0 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 251007ac133f7f78f60259eb21e9ee90e8e7e345..59a4e00a129da2cfa0c2aa1352d36b82b6892c4a 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/dilepton_persist_leptons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py new file mode 100644 index 0000000000000000000000000000000000000000..95d9dda56b2190a18fa794d5dbc13c98f09a2ad6 --- /dev/null +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/dilepton_persist_leptons.py @@ -0,0 +1,547 @@ +############################################################################### +# (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 GeV, MeV, 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_ismuon_long_muon, + make_long_electrons_no_brem, + make_long_electrons_with_brem, + make_prompt_dielectron_with_brem, +) + +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/drellyan.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/drellyan.py index dff1de5bdf78ce0030007d8bcae6c3c4ef96a0bf..696bd6670b113627f29d1d578d1082b000eeb37c 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( diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/hlt2_qee.py index 38d4f9eb5489706d38891b9e1efd17a033e39094..3c951e4f623da316358cf674f740dc0c0964c5ea 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) diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/qee/qee_builders.py index 42d3a0be9411df4862ab040e08936292308276ed..dd9f46f97229570f1660f496451dfecac4f005df 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, @@ -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-" ) 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 8cc398e8ff54401648f3fd869b66cebaeb8a60a3..d55da7ce8d17fc45ad93b337cb9362e0c8fca884 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"], )