Skip to content
Snippets Groups Projects

Draft : Upsilon -> ll

Closed Raja Nandakumar requested to merge nraja_rd_upsilon2ll into master
Files
5
##############################################################################
# (c) Copyright 2022 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. #
###############################################################################
"""
Definiton of dedicated prompt builders for LFV lines of qqbar -> emu (detached lines are using standard make_rd_detached_mue)
- Phi(1020) -> E Mu + SS prompt
- J/Psi(1S) -> E Mu + SS prompt
- Upsilon(1S) -> E Mu + SS
author: Miroslav Saur
date: 27.12.2021
"""
import Functors as F
from Functors.math import in_range
from GaudiKernel.SystemOfUnits import MeV, GeV
from RecoConf.reconstruction_objects import make_pvs_v2 as make_pvs
from Hlt2Conf.algorithms_thor import require_all, ParticleFilter
from PyConf import configurable
from Hlt2Conf.algorithms import ParticleCombinerWithPVs
from Hlt2Conf.lines.rd.builders.rdbuilder_thor import make_rd_tauons_hadronic_decay
from Hlt2Conf.standard_particles import (
make_detached_mue_with_brem,
make_detached_dielectron_with_brem,
make_detached_mumu,
make_long_electrons_with_brem,
make_ismuon_long_muon,
)
# filter based on the rd_detached_mue / make_detached_mue_with_brem with zero cuts on IP and added combination cuts
@configurable
def make_prompt_mue(
name="prompt_mue_builder",
min_dilepton_mass=0.0 * MeV,
max_dilepton_mass=6000.0 * MeV,
min_dilepton_pt=1.0 * GeV,
max_ipchi2_mue=50,
parent_id="J/psi(1S)",
min_probnn_mu=0.0,
min_PIDmu=0.0,
IsMuon=True,
min_PIDe=2.0,
min_pt_e=0.5 * GeV,
min_pt_mu=0.5 * GeV,
minipchi2=0, # must be 0 for a prompt builder
min_bpvvdchi2=0.0, # must be 0 for a prompt builder
max_vchi2ndof=10.0,
max_trghostprob=0.2,
same_sign=False,
):
"""
Make the detached muon-electron pair, opposite-sign or same-sign.
"""
pvs = make_pvs()
dileptons = make_detached_mue_with_brem(
dilepton_ID=parent_id,
min_probnn_mu=min_probnn_mu,
min_PIDmu=0.0,
IsMuon=IsMuon,
min_PIDe=min_PIDe,
same_sign=same_sign,
min_pt_e=min_pt_e,
min_pt_mu=min_pt_mu,
minipchi2_track=minipchi2,
min_bpvvdchi2=min_bpvvdchi2,
max_vchi2ndof=max_vchi2ndof,
max_trghostprob=max_trghostprob,
)
code = require_all(
in_range(min_dilepton_mass, F.MASS, max_dilepton_mass),
F.PT > min_dilepton_pt,
F.BPVIPCHI2(pvs) < max_ipchi2_mue,
)
return ParticleFilter(dileptons, F.FILTER(code), name=name)
@configurable
def make_prompt_etau(
name="prompt_mue_builder",
min_dilepton_mass=7000.0 * MeV,
max_dilepton_mass=13000.0 * MeV,
min_dilepton_pt=1.0 * GeV,
max_ipchi2_etau=50,
parent_id="Upsilon(1S)",
min_PIDe=2.0,
max_adocachi2=30.0,
min_pt_e=0.5 * GeV,
min_pt_tau=0.3 * GeV,
minipchi2=0, # must be 0 for a prompt builder
min_bpvvdchi2=0.0, # must be 0 for a prompt builder
max_vchi2ndof=10.0,
):
"""
Make the detached electron-tau pair, opposite-sign for now.
"""
pvs = make_pvs()
descriptor = "[{} -> e+ tau-]cc".format(parent_id)
taus = make_rd_tauons_hadronic_decay(
best_pi_ipchi2_min=minipchi2
) # Make them prompt(?)
    • Comment on lines +112 to +113

      prompt pions will probably dominate the rate. As the tau's have a small but significant lifetime, any requirement on the pi minipchi2 might be crucial to achieve manageable rates

Please register or sign in to reply
electrons = make_long_electrons_with_brem()
daughters_code = {
    • you are apparently using LoKi for combining the particles and then some ThOr filters on top. This is unnecessarily complicated and slows down the process. Have a look at rdbuilder_thor to see how to use ThOr combiners with a selection instead.

Please register or sign in to reply
"tau+": f"(PT > {min_pt_tau}) & (MIPCHI2DV(PRIMARY) > {minipchi2})", # Do we need to add a minipchi2 to the taus also for promptness?
"tau-": f"(PT > {min_pt_tau}) & (MIPCHI2DV(PRIMARY) > {minipchi2})",
"e+": f"(PIDe > {min_PIDe}) & (PT > {min_pt_e}) & (MIPCHI2DV(PRIMARY) > {minipchi2})",
"e-": f"(PIDe > {min_PIDe}) & (PT > {min_pt_e}) & (MIPCHI2DV(PRIMARY) > {minipchi2})",
}
combination_code = f"ADOCACHI2CUT({max_adocachi2}, '')"
vertex_code = (
f"(VFASPF(VCHI2/VDOF) < {max_vchi2ndof}) & (BPVVDCHI2() > {min_bpvvdchi2})"
)
etau = ParticleCombinerWithPVs(
particles=[electrons, taus],
pvs=pvs,
DaughtersCuts=daughters_code,
DecayDescriptor=descriptor,
CombinationCut=combination_code,
MotherCut=vertex_code,
)
code = require_all(
in_range(min_dilepton_mass, F.MASS, max_dilepton_mass),
F.PT > min_dilepton_pt,
F.BPVIPCHI2(pvs) < max_ipchi2_etau,
)
return ParticleFilter(etau, F.FILTER(code), name=name)
@configurable
def make_prompt_mutau(
name="prompt_mue_builder",
min_dilepton_mass=7000.0 * MeV,
max_dilepton_mass=13000.0 * MeV,
min_dilepton_pt=1.0 * GeV,
max_ipchi2_mutau=50,
parent_id="Upsilon(1S)",
min_probnn_mu=0.2,
min_PIDmu=0.0,
IsMuon=False,
min_pt_mu=0.0 * GeV,
max_adocachi2=30.0,
min_pt_tau=0.3 * GeV,
minipchi2=0, # must be 0 for a prompt builder
min_bpvvdchi2=0.0, # must be 0 for a prompt builder
max_vchi2ndof=10.0,
):
"""
Make the detached electron-tau pair, opposite-sign for now.
"""
pvs = make_pvs()
descriptor = "[{} -> mu+ tau-]cc".format(parent_id)
taus = make_rd_tauons_hadronic_decay(
best_pi_ipchi2_min=minipchi2
) # Make them prompt(?)
muons = make_ismuon_long_muon()
daughters_code = {
"tau+": f"(PT > {min_pt_tau}) & (MIPCHI2DV(PRIMARY) > {minipchi2})", # Do we need to add a minipchi2 to the taus also for promptness?
"tau-": f"(PT > {min_pt_tau}) & (MIPCHI2DV(PRIMARY) > {minipchi2})",
"mu+": f"(PROBNNmu > {min_probnn_mu}) & (PIDmu > {min_PIDmu}) & (PT > {min_pt_mu}) & (MIPCHI2DV(PRIMARY) > {minipchi2})",
"mu-": f"(PROBNNmu > {min_probnn_mu}) & (PIDmu > {min_PIDmu}) & (PT > {min_pt_mu}) & (MIPCHI2DV(PRIMARY) > {minipchi2})",
}
if IsMuon:
daughters_code["mu+"] = daughters_code["mu+"] + " & ISMUON"
daughters_code["mu-"] = daughters_code["mu-"] + " & ISMUON"
combination_code = f"ADOCACHI2CUT({max_adocachi2}, '')"
vertex_code = (
f"(VFASPF(VCHI2/VDOF) < {max_vchi2ndof}) & (BPVVDCHI2() > {min_bpvvdchi2})"
)
mutau = ParticleCombinerWithPVs(
particles=[muons, taus],
pvs=pvs,
DaughtersCuts=daughters_code,
DecayDescriptor=descriptor,
CombinationCut=combination_code,
MotherCut=vertex_code,
)
code = require_all(
in_range(min_dilepton_mass, F.MASS, max_dilepton_mass),
F.PT > min_dilepton_pt,
F.BPVIPCHI2(pvs) < max_ipchi2_mutau,
)
return ParticleFilter(mutau, F.FILTER(code), name=name)
@configurable
def make_prompt_tautau(
name="prompt_tautau_builder",
min_dilepton_mass=7000.0 * MeV,
max_dilepton_mass=13000.0 * MeV,
min_dilepton_pt=1.0 * GeV,
max_ipchi2_tautau=50,
max_adocachi2=30.0,
parent_id="Upsilon(1S)",
min_pt_tau=0.3 * GeV,
minipchi2=0, # must be 0 for a prompt builder
min_bpvvdchi2=0.0, # must be 0 for a prompt builder
max_vchi2ndof=10.0,
):
"""
Make the detached muon-electron pair, opposite-sign or same-sign.
"""
pvs = make_pvs()
taus = make_rd_tauons_hadronic_decay(
best_pi_ipchi2_min=minipchi2
) # Make them prompt(?)
descriptor = "{} -> tau+ tau-".format(parent_id)
combination_code = f"ADOCACHI2CUT({max_adocachi2}, '')"
vertex_code = (
f"(VFASPF(VCHI2/VDOF) < {max_vchi2ndof}) & (BPVVDCHI2() > {min_bpvvdchi2})"
)
daughters_code = {
"tau+": f"(PT > {min_pt_tau})", # Do we need to add a minipchi2 to the taus also for promptness?
"tau-": f"(PT > {min_pt_tau})",
}
tautau = ParticleCombinerWithPVs(
particles=[taus, taus],
pvs=pvs,
DaughtersCuts=daughters_code,
DecayDescriptor=descriptor,
CombinationCut=combination_code,
MotherCut=vertex_code,
)
code = require_all(
in_range(min_dilepton_mass, F.MASS, max_dilepton_mass),
F.PT > min_dilepton_pt,
F.BPVIPCHI2(pvs) < max_ipchi2_tautau,
)
return ParticleFilter(tautau, F.FILTER(code), name=name)
# filter based on the rd_detached_mue / make_detached_mue_with_brem with zero cuts on IP and added combination cuts
@configurable
def make_prompt_mumu(
name="prompt_mumu_builder",
min_dilepton_mass=0.0 * MeV,
max_dilepton_mass=6000.0 * MeV,
min_dilepton_pt=1.0 * GeV,
max_ipchi2_mumu=50,
parent_id="J/psi(1S)",
min_probnn_mu=0.0,
IsMuon=True,
min_pt_mu=0.5 * GeV,
minipchi2=0, # must be 0 for a prompt builder
min_bpvvdchi2=0.0, # must be 0 for a prompt builder
max_trghostprob=0.2,
Please register or sign in to reply
):
"""
Make the detached muon-electron pair, opposite-sign or same-sign.
"""
pvs = make_pvs()
dileptons = make_detached_mumu(
adocachi2cut=30,
vfaspfchi2ndof=10,
probnn_mu=min_probnn_mu,
pt_mu=min_pt_mu,
minipchi2=minipchi2,
bpvvdchi2=min_bpvvdchi2,
trghostprob=max_trghostprob,
)
code = require_all(
in_range(min_dilepton_mass, F.MASS, max_dilepton_mass),
F.PT > min_dilepton_pt,
F.BPVIPCHI2(pvs) < max_ipchi2_mumu,
)
return ParticleFilter(dileptons, F.FILTER(code), name=name)
@configurable
def make_prompt_ee(
name="prompt_ee_builder",
opposite_sign=True,
PIDe_min=2.0,
pt_e=0.5 * GeV,
minipchi2=0, # must be 0 for a prompt builder
max_ipchi2_ee=50,
trghostprob=0.2,
parent_id="J/psi(1S)",
min_dilepton_pt=0 * GeV,
min_dilepton_mass=0 * MeV,
max_dilepton_mass=6000 * MeV,
adocachi2cut=30,
max_vchi2ndof=7.5,
):
"""
Make the detached muon-electron pair, opposite-sign or same-sign.
"""
pvs = make_pvs()
dileptons = make_detached_dielectron_with_brem(
opposite_sign=opposite_sign,
PIDe_min=PIDe_min,
pt_e=pt_e,
minipchi2=minipchi2,
trghostprob=trghostprob,
dielectron_ID=parent_id,
pt_diE=min_dilepton_pt,
m_diE_min=min_dilepton_mass,
m_diE_max=max_dilepton_mass,
adocachi2cut=adocachi2cut,
vfaspfchi2ndof=max_vchi2ndof,
)
code = require_all(
in_range(min_dilepton_mass, F.MASS, max_dilepton_mass),
F.PT > min_dilepton_pt,
F.BPVIPCHI2(pvs) < max_ipchi2_ee,
)
return ParticleFilter(dileptons, F.FILTER(code), name=name)
"""
### dedicated filters and builders for making up everything from the basic particles; keeping it now for posible revison but to be removed before merging into master
@configurable
def make_prompt_long_electrons(pvs,
make_particles=make_long_electrons_with_brem,
name="prompt_long_electrons",
min_pt_e=0. * MeV,
min_p_e=0. * GeV,
min_ipchi2_electron=0,
min_ip_electron=0,
min_pid_electron=-5,
max_ghostprob_electron=0.7,
max_trackchi2_electron=None,
max_ipchi2_electron=None):
#pvs = make_pvs()
code = require_all(F.PT > min_pt_e, F.P > min_p_e,
F.MINIPCHI2(pvs) > min_ipchi2_electron,
F.MINIP(pvs) > min_ip_electron,
F.PID_MU > min_pid_electron,
F.GHOSTPROB < max_ghostprob_electron)
if max_trackchi2_electron is not None:
code &= (F.CHI2 < max_trackchi2_electron)
if max_ipchi2_electron is not None:
code &= (F.MINIPCHI2(pvs) < max_ipchi2_electron)
return ParticleFilter(make_particles(), name=name, Cut=F.FILTER())
@configurable
def make_prompt_long_muons(pvs,
make_particles=make_long_muons,
name="prompt_long_muons",
min_pt_mu=0. * MeV,
min_p_mu=0. * GeV,
min_ipchi2_muon=0,
min_ip_muon=0,
min_pid_muon=-5,
max_ghostprob_muon=0.7,
max_trackchi2_muon=None,
max_ipchi2_muon=None):
#pvs = make_pvs()
code = require_all(F.PT > min_pt_mu, F.ISMUON, F.P > min_p_mu,
F.MINIPCHI2(pvs) > min_ipchi2_muon,
F.MINIP(pvs) > min_ip_muon, F.PID_MU > min_pid_muon,
F.GHOSTPROB < max_ghostprob_muon)
if max_trackchi2_muon is not None:
code &= (F.CHI2 < max_trackchi2_muon)
if max_ipchi2_muon is not None:
code &= (F.MINIPCHI2(pvs) < max_ipchi2_muon)
return ParticleFilter(make_particles(), name=name, Cut=F.FILTER(code))
"""
"""
@configurable #currenctly does not work, no events selected even after removing all the requirements
def make_prompt_mue(name='prompt_mue_builder',
DecayDescriptor='[J/psi(1S) -> mu+ e-]CC',
min_dilepton_mass=0. * MeV,
max_dilepton_mass=100000. * MeV,
min_pt_mue=1. * GeV,
min_DIRA_mue=0.95,
min_bpvvdchi2_mue=100.,
max_ipchi2_mue=20,
max_vertexchi2_mue=20,
max_vchi2ndof=10,
min_pt_mu=0.25 * GeV,
min_p_mu=2. * GeV,
min_ipchi2_muon=0,
min_ip_muon=0,
max_ghostprob_muon=0.5,
min_pid_muon=-0,
min_pt_e=0.25 * GeV,
min_p_e=1. * GeV,
min_ipchi2_electron=0,
min_ip_electron=0,
max_ghostprob_electron=0.5,
min_pid_electron=-5,
max_trackchi2_muon=None,
max_trackchi2_electron=None):
#DecayDescriptor = '{} -> mu+ e-'.format(parent_id) # <- giving a weird error: ValueError: received an instance of <class 'list'>, but <class 'str'> expected
#if same_sign: DecayDescriptor = ['[{} -> mu+ e+]CC'.format(parent_id)]
pvs = make_pvs()
muons = make_prompt_long_muons(
pvs,
min_pt_mu=min_pt_mu,
min_p_mu=min_p_mu,
min_ipchi2_muon=min_ipchi2_muon,
min_ip_muon=min_ip_muon,
max_ghostprob_muon=max_ghostprob_muon,
max_trackchi2_muon=max_trackchi2_muon,
min_pid_muon=min_pid_muon)
electrons = make_prompt_long_electrons(
pvs,
min_pt_e=min_pt_e,
min_p_e=min_p_e,
min_ipchi2_electron=min_ipchi2_electron,
min_ip_electron=min_ip_electron,
max_ghostprob_electron=max_ghostprob_electron,
max_trackchi2_electron=max_trackchi2_electron,
min_pid_electron=min_pid_electron)
combination_code = require_all(
in_range(min_dilepton_mass, F.MASS, max_dilepton_mass))
# require that the muons come from the same vertex
vertex_code = require_all(
F.CHI2DOF < max_vertexchi2_mue,
#F.CHI2 / F.NDOF < max_vchi2ndof, <- doesn't work?
F.PT > min_pt_mue,
F.BPVFDCHI2(pvs) > min_bpvvdchi2_mue,
F.BPVIPCHI2(pvs) < max_ipchi2_mue,
F.BPVDIRA(pvs) > min_DIRA_mue)
return ParticleCombiner(
name=name,
Inputs=[muons, electrons],
DecayDescriptor=DecayDescriptor,
#CombinationCut=combination_code,
#CompositeCut=vertex_code
)
"""
#################
## END OF FILE ##
#################
Loading