diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/__init__.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/__init__.py index c0d7dc099d3f4bcce2c217c08bb4fd9fb5c10d39..319fced6f11bf13b224f81f360845f5ef219485c 100644 --- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/__init__.py +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/__init__.py @@ -60,3 +60,4 @@ def hlt2_line_builder(name): # Import each module so that the lines are registered from . import D02HH from . import Bs2JpsiPhi +from . import psi2MuMu_detached diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/psi2MuMu_detached.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/psi2MuMu_detached.py new file mode 100644 index 0000000000000000000000000000000000000000..1374db870b98d76e66a16eef3b6a23aaf425baf4 --- /dev/null +++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/psi2MuMu_detached.py @@ -0,0 +1,166 @@ +############################################################################### +# (c) Copyright 2019 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 D0 -> h- h+ HLT2 lines. + +Final states built are: + +1. D0 -> K- pi+ and it's charge conjugate +2. D*+ -> (D0 -> K- pi+) pi+ and it's charge conjugate +3. D0 -> K- K+ +4. D0 -> pi- pi+ + +The D0 -> h- h+, with identical h species, do not create the charge conjugate +D~0 objects because it would have identical properties and hence would be +a waste of CPU (duplicating the selection and vertexing). This is annoying when +D* tagging is eventually added, however, and one cannot create the 'physical' +charge combinations of `D*+ -> D0 pi+` and `D*- D~0 pi-`. It can be considered +a flaw in the selection framework that we cannot currently express these sorts +of combinations cleanly. +""" +from __future__ import absolute_import, division, print_function +import math + +from GaudiKernel.SystemOfUnits import GeV, MeV, mm, mrad + +from RecoConf.hlt1_tracking import require_pvs, require_gec +from RecoConf.reco_objects_from_file import make_pvs + +from ..algorithms import require_all, ParticleCombinerWithPVs, ParticleFilterWithPVs +from ..framework import configurable +from ..standard_particles import make_has_rich_long_pions, make_has_rich_long_kaons, make_ismuon_long_muon +from . import hlt2_line_builder + +# Charged pion mass in MeV + + +@configurable +def make_selected_muons(make_particles=make_ismuon_long_muon, + make_pvs=make_pvs, + trchi2_max=3, + mipchi2_min=4, + pt_min=500 * MeV, + p_min=1 * GeV, + pid_cut="PIDmu>0.0"): + """Return maker for particles filtered by thresholds common to charm decay product selections. + + Parameters + ---------- + make_particles + Particle maker function. + make_pvs : callable + Primary vertex maker function. + + Remaining parameters define thresholds for the selection. + """ + code = require_all( + 'PT > {pt_min}', + 'P > {p_min}', + # TODO(AP): Cut value is reasonable for Run 2, but removes basically + # everything in the upgrade sample + # 'TRCHI2 < {trchi2_max}', + 'MIPCHI2DV(PRIMARY) > {mipchi2_min}').format( + pt_min=pt_min, + p_min=p_min, + trchi2_max=trchi2_max, + mipchi2_min=mipchi2_min) + if pid_cut is not None: + code += ' & ({})'.format(pid_cut) + return ParticleFilterWithPVs(make_particles(), make_pvs(), Code=code) + + +@configurable +def make_dimuon_detached(particles, + descriptors, + pvs, + am_min=2896.9 * MeV, + am_max=3886.1 * MeV, + amaxchild_pt_min=1500 * MeV, + apt_min=2000 * MeV, + amindoca_max=0.1 * mm, + vchi2pdof_max=10, + bpvvdchi2_min=25, + acos_bpvdira_min=0 * mrad): + """Return D0 maker with selection tailored for two-body hadronic final states. + + Parameters + ---------- + particles : list + Input particles used in the combination. + descriptors : list + Decay descriptors to be reconstructed. + pvs + Primary vertices used for computing PV-related information. + + Remaining parameters define thresholds for the selection. + """ + combination_code = require_all("in_range({am_min}, AM, {am_max})", + "AMAXCHILD(PT) > {amaxchild_pt_min}", + "APT > {apt_min}", + "AMINDOCA('') < {amindoca_max}").format( + am_min=am_min, + am_max=am_max, + amaxchild_pt_min=amaxchild_pt_min, + apt_min=apt_min, + amindoca_max=amindoca_max) + + cos_bpvdira_max = math.cos(acos_bpvdira_min) + vertex_code = require_all("CHI2VXNDOF < {vchi2pdof_max}", "BPVVALID()", + "BPVVDCHI2() > {bpvvdchi2_min}", + "BPVDIRA() < {cos_bpvdira_max}").format( + vchi2pdof_max=vchi2pdof_max, + bpvvdchi2_min=bpvvdchi2_min, + cos_bpvdira_max=cos_bpvdira_max) + + return ParticleCombinerWithPVs( + particles=particles, + pvs=pvs, + DecayDescriptors=descriptors, + CombinationCut=combination_code, + MotherCut=vertex_code) + + +@configurable +def make_Jpsi_detached(particle, pvs, m_min=2996.9 * MeV, m_max=3196.9 * MeV): + vertex_code = require_all("in_range({m_min}, M, {m_max})").format( + m_min=m_min, m_max=m_max) + return ParticleFilterWithPVs(particle, pvs, Code=vertex_code) + + +@configurable +def make_psi2S_detached(particle, pvs, m_min=3566.1 * MeV, m_max=3786.1 * MeV): + vertex_code = require_all("in_range({m_min}, M, {m_max})").format( + m_min=m_min, m_max=m_max) + return ParticleFilterWithPVs(particle, pvs, Code=vertex_code) + + +def charm_prefilters(): + """Return a list of prefilters common to charm HLT2 lines.""" + return [require_gec(), require_pvs(make_pvs())] + + +@hlt2_line_builder('Hlt2Jpsi2MuMuDetachedLine') +def Jpsi2MuMudetached_line(): + muons = make_selected_muons() + pvs = make_pvs() + dimuon = make_dimuon_detached( + particles=[muons], descriptors=['J/psi(1S) -> mu+ mu-'], pvs=pvs) + Jpsi = make_Jpsi_detached(dimuon, pvs) + return charm_prefilters() + [Jpsi] + + +@hlt2_line_builder('Hlt2psi2S2MuMuDetachedLine') +def psi2S2MuMudetached_line(): + muons = make_selected_muons() + pvs = make_pvs() + dimuon = make_dimuon_detached( + particles=[muons], descriptors=['J/psi(1S) -> mu+ mu-'], pvs=pvs) + Jpsi = make_psi2S_detached(dimuon, pvs) + return charm_prefilters() + [Jpsi]