diff --git a/Beauty_XS_Bs2DsPi/README.md b/Beauty_XS_Bs2DsPi/README.md deleted file mode 100644 index 769ed08b696e40389437865e22cb34a3bab2cfa9..0000000000000000000000000000000000000000 --- a/Beauty_XS_Bs2DsPi/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Production of Bs -> Ds pi to run on 2024 collision data to include both up and down polarities - -This is for use in early measurements of Beauty XS diff --git a/Beauty_XS_Bs2DsPi/dv_simple.py b/Beauty_XS_Bs2DsPi/dv_simple.py deleted file mode 100644 index b4254db88035c1df0041355ffc4ef5974a6b8c2f..0000000000000000000000000000000000000000 --- a/Beauty_XS_Bs2DsPi/dv_simple.py +++ /dev/null @@ -1,252 +0,0 @@ -# Based on: -# https://gitlab.cern.ch/lhcb/DaVinci/-/blob/v63r2/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_from_hlt2.py - -import Functors as F -import FunTuple.functorcollections as FC -from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple -from PyConf.reading import get_particles, get_pvs, get_rec_summary, get_odin -#from PyConf.Algorithms import AdvancedCloneKiller, Run2SSPionTagger -from GaudiKernel.SystemOfUnits import GeV -from Hlt2Conf.algorithms_thor import ParticleFilter -#from DaVinci.common_particles import make_long_pions -from DaVinci.algorithms import create_lines_filter -from DaVinci import Options, make_config -from DaVinciMCTools import MCTruthAndBkgCat -from DecayTreeFitter import DecayTreeFitter -from Hlt2Conf.flavourTagging import run2_all_taggers -# specific for the B2OC SigmaNet -import Functors.math as fmath -import os - - -def alg_config(options: Options): - - line = "Hlt2B2OC_BdToDsmPi_DsmToKpKmPim" - line_data = get_particles(f"/Event/HLT2/{line}/Particles") - my_filter = create_lines_filter("Hlt2Line_Filter", - lines=[f"{line}"]) - Hlt1_decisions = [ - "Hlt1TrackMVADecision", - "Hlt1TwoTrackMVADecision", - ] - Hlt2_decisions = ['Hlt2B2OC_BdToDsmPi_DsmToKpKmPimDecision', - 'Hlt2Topo2BodyDecision', - 'Hlt2Topo3BodyDecision'] - - fields = { - "lab0": "[[B0]CC -> (D_s- -> K+ K- pi-) pi+]CC", - "lab1": "[[B0]CC -> (D_s- -> K+ K- pi-) ^pi+]CC", - "lab2": "[[B0]CC -> ^(D_s- -> K+ K- pi-) pi+]CC", - "lab3": "[[B0]CC -> (D_s- -> ^K+ K- pi-) pi+]CC", - "lab4": "[[B0]CC -> (D_s- -> K+ ^K- pi-) pi+]CC", - "lab5": "[[B0]CC -> (D_s- -> K+ K- ^pi-) pi+]CC", - } - - pvs = get_pvs() - - DTF_MassFitConsD = DecayTreeFitter(name="DTF_MassFitConsD", - input_particles=line_data, - mass_constraints=["D_s-"]) - DTF_LifetimeFit = DecayTreeFitter(name="DTF_LifetimeFit", - input_particles=line_data, - input_pvs=pvs) - - all_tagging = run2_all_taggers(line_data) - - # define helper functors - get_child = F.CHILD(1, F.FORWARDARG0) # change here the index of the child - get_SV = F.ENDVERTEX @ F.FORWARDARG0 - get_SV_pos = F.TOLINALG @ F.POSITION @ get_SV # only if composite (i.e. has vertex) - get_child_endvtx_pos = F.ENDVERTEX_POS @ get_child - get_fdvec_child = get_child_endvtx_pos - get_SV_pos - - # define observables - IP_wrt_SV = F.IP.bind(get_SV_pos , get_child) - IPCHI2_wrt_SV = F.IPCHI2.bind(get_SV , get_child) # only if child is composite (i.e. has vertex) - FD_wrt_SV = F.MAGNITUDE @ get_fdvec_child - FDCHI2_wrt_SV = F.VTX_FDCHI2.bind(get_SV, get_child) - - B_variables = FunctorCollection( - { - "ID": F.PARTICLE_ID, - "PT": F.PT, - "ETA": F.ETA, - "P": F.P, - "SUMPT": F.SUM(F.PT), - "MASS": F.MASS, - "BPVDIRA": F.BPVDIRA(pvs), - "CHI2DOF": F.CHI2DOF, - "BPVIPCHI2": F.BPVIPCHI2(pvs), - "BPVIP": F.BPVIP(pvs), - "BPVFDCHI2": F.BPVFDCHI2(pvs), - "BPVLTIME": F.BPVLTIME(pvs), - "BPVFD": F.BPVFD(pvs), - "CHILD1_IPwrtSV": IP_wrt_SV, - "CHILD1_IPCHI2wrtSV": IPCHI2_wrt_SV, - "CHILD1_FDwrtSV": FD_wrt_SV, - "CHILD1_FDCHI2wrtSV": FDCHI2_wrt_SV, - "DTF_MassFitConsD_MASS": DTF_MassFitConsD(F.MASS), - "DTF_MassFitConsD_CHI2DOF": DTF_MassFitConsD(F.CHI2DOF), # track or vertex chi2/ndf - "DTF_MassFitConsD_P": DTF_MassFitConsD(F.P), - "DTF_LifetimeFit_MASS": DTF_LifetimeFit(F.MASS), - "DTF_LifetimeFit_CHI2DOF": DTF_LifetimeFit(F.CHI2DOF), # track or vertex chi2/ndf - "DTF_LifetimeFit_CTAU": DTF_LifetimeFit.CTAU, - "DTF_LifetimeFit_CTAUERR": DTF_LifetimeFit.CTAUERR, - "PX": F.PX, - "PY": F.PY, - "PZ": F.PZ, - "BPVX": F.BPVX(pvs), - "BPVY": F.BPVY(pvs), - "BPVZ": F.BPVZ(pvs), - "END_VX": F.END_VX, - "END_VY": F.END_VY, - "END_VZ": F.END_VZ, - "END_VCHI2DOF": F.CHI2DOF @ F.ENDVERTEX, - "BPVCHI2DOF": F.CHI2DOF @ F.BPV(pvs), - # B2OC generic B hadron NN Hlt2 algorithm, - # not planning to use it directly for B2OC EM - "MVA": F.MVA( - MVAType="SigmaNet", - Config={ - "File": - "paramfile://data/Hlt2B2OC_B_SigmaNet_Run3-v2.json", - "Name": - "B2OC_SigmaNet_Generic", - "Lambda": - "2.0", - "NLayers": - "3", - "InputSize": - "6", - "Monotone_Constraints": - "[1,-1,-1,-1,-1,-1]", - "Variables": - "log_B_PT,B_ETA,log_B_DIRA,log_B_ENDVERTEX_CHI2,log_B_IPCHI2_OWNPV,log_B_IP_OWNPV", - }, - Inputs={ - "log_B_PT": fmath.log(F.PT), - "B_ETA": F.ETA, - "log_B_DIRA": fmath.log(1. +1.e-6 - F.BPVDIRA(pvs)), - "log_B_ENDVERTEX_CHI2": fmath.log(F.CHI2DOF), - "log_B_IPCHI2_OWNPV": fmath.log(F.BPVIPCHI2(pvs)), - "log_B_IP_OWNPV": fmath.log(F.BPVIP(pvs)), - }), - } - ) - B_variables+=FC.HltTisTos(selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=line_data) - B_variables+=FC.FlavourTaggingResults(all_tagging) - - C_variables = FunctorCollection( - { - "ID": F.PARTICLE_ID, - "PT": F.PT, - "ETA": F.ETA, - "P": F.P, - "SUMPT": F.SUM(F.PT), - "MASS": F.MASS, - "DOCA12": F.DOCA(1, 2), - "DOCA13": F.DOCA(1, 3), - "DOCA23": F.DOCA(2, 3), - "BPVDIRA": F.BPVDIRA(pvs), - "CHI2DOF": F.CHI2DOF, - "BPVIP": F.BPVIP(pvs), - "BPVIPCHI2": F.BPVIPCHI2(pvs), - "BPVFD": F.BPVFD(pvs), - "BPVFDCHI2": F.BPVFDCHI2(pvs), - "MINIPCHI2": F.MINIPCHI2(pvs), - "PX": F.PX, - "PY": F.PY, - "PZ": F.PZ, - "BPVX": F.BPVX(pvs), - "BPVY": F.BPVY(pvs), - "BPVZ": F.BPVZ(pvs), - "END_VX": F.END_VX, - "END_VY": F.END_VY, - "END_VZ": F.END_VZ, - "END_VCHI2DOF": F.CHI2DOF @ F.ENDVERTEX, - } - ) - - fs_variables = FunctorCollection( - { - "ID": F.PARTICLE_ID, - "PT": F.PT, - "ETA": F.ETA, - "PHI": F.PHI, - "P": F.P, - "MASS": F.MASS, - "CHI2DOF": F.CHI2DOF, - "MINIPCHI2": F.MINIPCHI2(pvs), - "BPVIPCHI2": F.BPVIPCHI2(pvs), - "PX": F.PX, - "PY": F.PY, - "PZ": F.PZ, - "hasRICH": F.PPHASRICH() @ F.PROTOPARTICLE(), - "PIDK": F.PID_K, - "PIDp": F.PID_P, - "PIDe": F.PID_E, - "PIDmu": F.PID_MU, - "isMuon": F.ISMUON, - "TRACK_GhostProb": F.GHOSTPROB, - "ProbNNp": F.PROBNN_P, - "NHITS": F.VALUE_OR(-1) @ F.NHITS @ F.TRACK, - "NVPHITS": F.VALUE_OR(-1) @ F.NVPHITS @ F.TRACK, # VeloPixel hits - "NUTHITS": F.VALUE_OR(-1) @ F.NUTHITS @ F.TRACK, # UpstreamTracker hits - "NFTHITS": F.VALUE_OR(-1) @ F.NFTHITS @ F.TRACK, # ForwardTracker hits - "TRACKHASVELO": F.VALUE_OR(-1) @ F.TRACKHASVELO @ F.TRACK, - } - ) - - variables = { - "lab0": B_variables, - "lab1": fs_variables, - "lab2": C_variables, - "lab3": fs_variables, - "lab4": fs_variables, - "lab5": fs_variables, - } - - if options.simulation: - mctruth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat") - trueid_bkgcat_info = { - "TRUEID": F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID), - "TRUEKEY": F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY), - "TRUEPT": mctruth(F.PT), - "TRUEPX": mctruth(F.PX), - "TRUEPY": mctruth(F.PY), - "TRUEPZ": mctruth(F.PZ), - "TRUEENERGY": mctruth(F.ENERGY), - "TRUEP": mctruth(F.P), - "TRUEFOURMOMENTUM": mctruth(F.FOURMOMENTUM), - "TRUETAU": mctruth(F.MC_LIFETIME), - "BKGCAT": mctruth.BkgCat, - } - for field in variables.keys(): - variables[field] += FunctorCollection(trueid_bkgcat_info) - - - odin = get_odin() - rec_summary = get_rec_summary() - # define event level variables - evt_variables = FunctorCollection({ - "RUNNUMBER": F.RUNNUMBER(odin), - "EVENTNUMBER": F.EVENTNUMBER(odin), - "nPVs": F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_summary, "nPVs"), - "nLongTracks": F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_summary, "nLongTracks"), - }) - evt_variables+=FC.SelectionInfo(selection_type="Hlt1", trigger_lines=Hlt1_decisions) - evt_variables+=FC.SelectionInfo(selection_type="Hlt2", trigger_lines=Hlt2_decisions) - - # define FunTuple instance - my_tuple = Funtuple( - name="Tuple", - tuple_name="DecayTree", - fields=fields, - variables=variables, - event_variables=evt_variables, - inputs=line_data, - store_multiple_cand_info=True, - ) - - return make_config(options, [my_filter, my_tuple]) - diff --git a/Beauty_XS_Bs2DsPi/hlt1.py b/Beauty_XS_Bs2DsPi/hlt1.py deleted file mode 100644 index d40c23bc29209d15b3ced30b1959c81368527495..0000000000000000000000000000000000000000 --- a/Beauty_XS_Bs2DsPi/hlt1.py +++ /dev/null @@ -1,31 +0,0 @@ -############################################################################### -# (c) Copyright 2023 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. # -############################################################################### -""" -Configures running HLT1 via Moore. -""" - -from Moore import Options -from Moore.config import allen_control_flow -from RecoConf.hlt1_allen import allen_gaudi_config, get_allen_line_names -from PyConf.application import configure_input, configure - -def alg_config(options: Options): - """ - Configures algorithm running of HLT1 via Moore to be passed to Analysis Productions. - """ - - config = configure_input(options) - with allen_gaudi_config.bind(sequence="hlt1_pp_matching_no_ut_1000KHz"): - line_names = get_allen_line_names() - allen_node = allen_control_flow(options) - config.update(configure(options, allen_node)) - - return config diff --git a/Beauty_XS_Bs2DsPi/hlt2.py b/Beauty_XS_Bs2DsPi/hlt2.py deleted file mode 100644 index 86070c155cc3219e654c040a0f7dd22cda4b9dd7..0000000000000000000000000000000000000000 --- a/Beauty_XS_Bs2DsPi/hlt2.py +++ /dev/null @@ -1,68 +0,0 @@ -############################################################################### -# (c) Copyright 2023 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. # -############################################################################### -""" -Configures running HLT2 via Moore. -""" - -from Moore import options, Options, run_moore -from Hlt2Conf.lines.b_to_open_charm import all_lines -# -from RecoConf.global_tools import stateProvider_with_simplified_geom, trackMasterExtrapolator_with_simplified_geom -from RecoConf.reconstruction_objects import reconstruction -from RecoConf.hlt2_global_reco import reconstruction as hlt2_reconstruction, make_light_reco_pr_kf_without_UT -from RecoConf.hlt2_tracking import ( - make_TrackBestTrackCreator_tracks, - make_PrKalmanFilter_noUT_tracks, - make_PrKalmanFilter_Velo_tracks, - make_PrKalmanFilter_Seed_tracks, -) -from RecoConf.decoders import default_VeloCluster_source -from RecoConf.event_filters import require_gec -from Hlt2Conf.settings.defaults import get_default_hlt1_filter_code_for_hlt2 -import sys - -all_lines = {} -from Hlt2Conf.lines.b_to_open_charm.hlt2_b2oc import make_hlt2_lines -default_lines = [ - 'BdToDsmPi_DsmToKpKmPim', -] -extra_config = { - 'flavour_tagging': [ - 'BdToDsmPi_DsmToKpKmPim', - ] -} -make_hlt2_lines( - line_dict=all_lines, - all_lines=default_lines, - extra_config=extra_config) - -def make_lines(): - lines = [builder() for builder in all_lines.values()] - return lines - -def alg_config(options: Options): - - public_tools = [ - trackMasterExtrapolator_with_simplified_geom(), - stateProvider_with_simplified_geom() - ] - - # require_gec.bind(skipUT=True),\ # B2OC lines do not have require_gec() - with reconstruction.bind(from_file=False),\ - hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf_without_UT),\ - default_VeloCluster_source.bind(bank_type="VPRetinaCluster"),\ - make_TrackBestTrackCreator_tracks.bind(max_ghost_prob=0.7, max_chi2ndof=sys.float_info.max),\ - make_PrKalmanFilter_Velo_tracks.bind(max_chi2ndof=5.),\ - make_PrKalmanFilter_noUT_tracks.bind(max_chi2ndof=4.),\ - make_PrKalmanFilter_Seed_tracks.bind(max_chi2ndof=6.): - config = run_moore(options, make_lines, public_tools) - - return config diff --git a/Beauty_XS_Bs2DsPi/info.yaml b/Beauty_XS_Bs2DsPi/info.yaml deleted file mode 100644 index b903958273f8fca7b499470ad64cf523c5cc60e2..0000000000000000000000000000000000000000 --- a/Beauty_XS_Bs2DsPi/info.yaml +++ /dev/null @@ -1,79 +0,0 @@ - -defaults: - wg: B2OC - automatically_configure: no - inform: - - alessandro.bertolin@pd.infn.it - -{%- set mc_datasets = [ -('13264021', 'Down', 'sim10-2024.Q1.2-v1.0-md100', 'dddb-20240427'), -('13264021', 'Up', 'sim10-2024.Q1.2-v1.0-mu100', 'dddb-20240427'), -]%} - -{%- for evttype, polarity, conddb, dddb in mc_datasets %} - -MC_Bs2DsPi_{{ polarity }}_Nu4d3_hlt1: - application: Moore/v55r9@x86_64_v2-el9-gcc13+detdesc-opt - input: - bk_query: "/MC/Dev/Beam6800GeV-2024.Q1.2-Mag{{ polarity }}-VeloDrift-Nu4.3-25ns-Pythia8/Sim10d/{{ evttype }}/DIGI" - dq_flags: - - OK - n_test_lfns: 1 - options: - entrypoint: Beauty_XS_Bs2DsPi.hlt1:alg_config - extra_options: - input_raw_format: 0.5 - conddb_tag: {{ conddb }} - dddb_tag: {{ dddb }} - input_type: "ROOT" - output_type: "ROOT" - simulation: True - data_type: "Upgrade" - scheduler_legacy_mode: False - compression: - algorithm: ZSTD - level: 1 - max_buffer_size: 1048576 - output: hlt1.dst - -MC_Bs2DsPi_{{ polarity }}_Nu4d3_hlt2: - application: Moore/v55r9@x86_64_v2-el9-gcc13+detdesc-opt - input: - job_name: MC_Bs2DsPi_{{ polarity }}_Nu4d3_hlt1 - options: - entrypoint: Beauty_XS_Bs2DsPi.hlt2:alg_config - extra_options: - input_raw_format: 0.5 - persistreco_version: 0.0 - conddb_tag: {{ conddb }} - dddb_tag: {{ dddb }} - input_type: "ROOT" - output_type: "ROOT" - simulation: True - data_type: "Upgrade" - output_manifest_file: hlt2_{{ evttype }}_{{ polarity }}.tck.json - scheduler_legacy_mode: False - compression: - algorithm: ZSTD - level: 1 - max_buffer_size: 1048576 - output: hlt2.dst - -MC_Bs2DsPi_{{ polarity }}_Nu4d3_DV: - application: DaVinci/v64r6@x86_64_v2-el9-gcc13+detdesc-opt - input: - job_name: MC_Bs2DsPi_{{ polarity }}_Nu4d3_hlt2 - output: dv_{{ polarity }}.root - options: - entrypoint: Beauty_XS_Bs2DsPi.dv_simple:alg_config - extra_options: - input_raw_format: 0.5 - input_type: "ROOT" - simulation: True - data_type: "Upgrade" - conddb_tag: {{ conddb }} - dddb_tag: {{ dddb }} - input_process: "Hlt2" - -{%- endfor %} - diff --git a/btracking_b2dpipi/dv_b2dpipi_options.py b/btracking_b2dpipi/dv_b2dpipi_options.py new file mode 100644 index 0000000000000000000000000000000000000000..4a44ec21525992cd0b4529d9744564c2078ebf7a --- /dev/null +++ b/btracking_b2dpipi/dv_b2dpipi_options.py @@ -0,0 +1,475 @@ +############################################################################### +# (c) Copyright 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. # +############################################################################### + +from PyConf import configurable +from PyConf.reading import get_particles, get_pvs +from GaudiKernel.SystemOfUnits import GeV, MeV, mm +from Hlt2Conf.algorithms_thor import ParticleFilter, ParticleCombiner, ParticleContainersMerger +from Hlt2Conf.standard_particles import make_long_pions +from Hlt2Conf.lines.semileptonic.builders.base_builder import make_candidate +from Hlt2Conf.lines.semileptonic.HbToTauNu_BTracking import get_heavyflavourtrack_table, make_pions as hlt2_make_pions, make_parts_with_btracking +from RecoConf.reconstruction_objects import reconstruction +from RecoConf.decoders import default_VeloCluster_source + +import Functors as F +from FunTuple import FunctorCollection +from FunTuple import FunTuple_Particles as Funtuple +import FunTuple.functorcollections as FC +from Functors.math import in_range +from DaVinci.algorithms import create_lines_filter +from DaVinci import Options, make_config +from DecayTreeFitter import DecayTreeFitter +from IsolationTools import VertexAndConeIsolation + + +# data getters +@configurable +def make_pions_iso(line_name="", add_rich_filter=False): + pions = get_particles( + f"/Event/Spruce/{line_name}/Bu_LongTrackIsolation/Particles") + return ParticleFilter( + pions, + F.FILTER(F.PPHASRICH @ F.PROTOPARTICLE), + name="pions_with_rich_info") if add_rich_filter else pions + + +def make_pions(line_name, name="pions_for_Bp2Dmpipip", from_persistreco=True): + if from_persistreco: + with reconstruction.bind(from_file=True): + return hlt2_make_pions() + else: + with make_candidate.bind(make_particles=make_pions_iso),\ + make_pions_input.bind(line_name=line_name): + return hlt2_make_pions() + + +def make_bps( + dms, + pions, + name="Bps_for_Bp2Dmpipi", + vchi2_max=16, + m_min=5.0 * GeV, + m_max=5.7 * GeV, + dira_min=0.9995, + twopi_doca_max=0.1 * mm, + twopi_mass_max=3.5 * GeV, +): + # combine to form full B with some additional requirements on pi+pi+ combination + combination_code = F.require_all( + F.SUBCOMB(Functor=F.MAXSDOCACUT(twopi_doca_max), Indices=(2, 3)), + F.SUBCOMB(Functor=(F.MASS < twopi_mass_max), Indices=(2, 3)), + in_range(m_min - 50 * MeV, F.MASS, m_max + 50 * MeV)) + + vertex_code = F.require_all( + in_range(m_min, F.MASS, m_max), F.CHI2 < vchi2_max, + F.OWNPVDIRA > dira_min) + + bps = ParticleCombiner([dms, pions, pions], + DecayDescriptor="[B+ -> D- pi+ pi+]cc", + CombinationCut=combination_code, + CompositeCut=vertex_code, + name=name) + return bps + + +## isolation +def get_isolation_variables(line_name, ref_parts, name, vertex_decay_os, + vertex_decay_ss, vertex_decay_twotrack): + charged_data = get_particles( + f"/Event/Spruce/{line_name}/Bu_LongTrackIsolation/Particles") + neutral_data = get_particles( + f"/Event/Spruce/{line_name}/Bu_NeutralIsolation/Particles") + # default cone isolation + b_charged_iso = VertexAndConeIsolation( + name=f"ChargedIsofor_{name}", + reference_particles=ref_parts, + related_particles=charged_data, + cut=F.SQRT @ F.DR2 < 0.5) + b_neutral_iso = VertexAndConeIsolation( + name=f"NeutralIso_for_{name}", + reference_particles=ref_parts, + related_particles=neutral_data, + cut=F.SQRT @ F.DR2 < 0.5) + iso_vars = FC.ConeIsolation( + charged_cone_isolation_alg=b_charged_iso, + neutral_cone_isolation_alg=b_neutral_iso, + array_indx_name=f"{name}_cone_indx") + # isolation with one/two tracks combined with reference particle + # two types: + # - DOCA (distance of closest approach)-based selection + # DOCA is important for isolation against signal related tracks not coming from the same vertex + # like if you have a charm with lifetime coming from B + # especially important for decays like B+ -> tau+ ( -> pi+ pi- pi+ ) X + # where one wants to reject X, as these would still come clone to the line of vertex + direction/momentum + # - vertex selection + # isolation against track coming from same vertex + b_vertex_iso_onetrack_data_os = ParticleCombiner( + [ref_parts, charged_data], + name=f"OneTrack_OS_combination_for_isolation_for_{name}", + DecayDescriptor=vertex_decay_os, + CombinationCut=F.MAXSDOCACUT(0.2 * mm), + CompositeCut=F.ALL) + b_vertex_iso_onetrack_data_ss = ParticleCombiner( + [ref_parts, charged_data], + name=f"OneTrack_SS_combination_for_isolation_for_{name}", + DecayDescriptor=vertex_decay_ss, + CombinationCut=F.MAXSDOCACUT(0.2 * mm), + CompositeCut=F.ALL) + b_vertex_iso_onetrack_data = ParticleContainersMerger( + [b_vertex_iso_onetrack_data_os, b_vertex_iso_onetrack_data_ss], + name=f"OneTrack_combination_for_isolation_for_{name}") + b_vertex_iso_twotrack_data = ParticleCombiner( + [ref_parts, charged_data, charged_data], + name=f"Two_extra_tracks_combination_for_isolation_for_{name}", + DecayDescriptor=vertex_decay_twotrack, + CombinationCut=F.MAXSDOCACUT(0.2 * mm), + CompositeCut=F.ALL) + b_vertex_iso_onetrack_alg = VertexAndConeIsolation( + name=f"OneTrackVertexIso_for_{name}", + reference_particles=ref_parts, + related_particles=b_vertex_iso_onetrack_data, + cut=F.CHI2() @ F.FORWARDARG1 < 9) + b_vertex_iso_twotrack_alg = VertexAndConeIsolation( + name=f"TwoTrackVertexIso_for_{name}", + reference_particles=ref_parts, + related_particles=b_vertex_iso_twotrack_data, + cut=F.CHI2() @ F.FORWARDARG1 < 16) + b_doca_iso_onetrack_alg = VertexAndConeIsolation( + name=f"OneTrackDocaIso_for_{name}", + reference_particles=ref_parts, + related_particles=b_vertex_iso_onetrack_data, + cut=F.ALL) + b_doca_iso_twotrack_alg = VertexAndConeIsolation( + name=f"TwoTrackDocaIso_for_{name}", + reference_particles=ref_parts, + related_particles=b_vertex_iso_twotrack_data, + cut=F.ALL) + iso_vars += FC.ParticleIsolation( + isolation_alg=b_doca_iso_onetrack_alg, + array_indx_name=f'{name}_doca_onetrack_indx') + iso_vars += FC.ParticleIsolation( + isolation_alg=b_doca_iso_twotrack_alg, + array_indx_name=f'{name}_doca_twotrack_indx') + iso_vars += FC.ParticleIsolation( + isolation_alg=b_vertex_iso_onetrack_alg, + array_indx_name=f'{name}_vtx_onetrack_indx') + iso_vars += FC.ParticleIsolation( + isolation_alg=b_vertex_iso_twotrack_alg, + array_indx_name=f'{name}_vtx_twotrack_indx') + iso_vars += FC.VertexIsolation(isolation_alg=b_vertex_iso_onetrack_alg) + iso_vars += FC.VertexIsolation(isolation_alg=b_vertex_iso_twotrack_alg) + return iso_vars + + +def run_b2dpipi(options: Options, MC=False): + fields = { + "Bp_0": "[B+ -> (D- -> K+ pi- pi- ) pi+ pi+]CC", + "Dm_0": "[B+ -> ^(D- -> K+ pi- pi- ) pi+ pi+]CC", + "pip_0": "[B+ -> (D- -> K+ pi- pi- ) ^pi+ pi+]CC", + "pip_1": "[B+ -> (D- -> K+ pi- pi- ) pi+ ^pi+]CC", + "Kp_0": "[B+ -> (D- -> ^K+ pi- pi- ) pi+ pi+]CC", + "pim_0": "[B+ -> (D- -> K+ ^pi- pi- ) pi+ pi+]CC", + "pim_1": "[B+ -> (D- -> K+ pi- ^pi- ) pi+ pi+]CC", + } + + # data getters + line_name = "SpruceSLB_BToDPiPi_DToKPiPi_BTracking" + + btrack_parts = get_particles( + f"/Event/Spruce/{line_name}/ParticlesWithHeavyFlavourTracks/Particles") + rels, dms = get_heavyflavourtrack_table(btrack_parts) + + pions = make_pions(line_name) + bps = make_bps(dms, pions) + + # make extra control B-tracking track with B vertex or D only + # NOTE: make sure one has the right raw banks! + VP_source = "VPRetinaCluster" + with default_VeloCluster_source.bind(bank_type=VP_source): + btracks_bp = make_parts_with_btracking(bps) + rels_bp = btracks_bp['BTracking'].OutputRelations + + # DecayTree branches + variables_all = FunctorCollection({ + "ID": F.PARTICLE_ID, + "KEY": F.OBJECT_KEY, + "P": F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ENERGY": F.ENERGY, + "ETA": F.ETA, + "PHI": F.PHI, + "IP": F.OWNPVIP, + "IPCHI2": F.OWNPVIPCHI2, + "CHI2DOF": F.CHI2DOF, + }) + + variables_basic = FunctorCollection({ + "GHOSTPROB": + F.GHOSTPROB, + "CHI2": + F.VALUE_OR(-1) @ F.CHI2 @ F.TRACK, + "NDOF": + F.VALUE_OR(-1) @ F.NDOF @ F.TRACK, + "NVPHITS": + F.VALUE_OR(-1) @ F.NVPHITS @ F.TRACK, + "NUTHITS": + F.VALUE_OR(-1) @ F.NUTHITS @ F.TRACK, + "NFTHITS": + F.VALUE_OR(-1) @ F.NFTHITS @ F.TRACK, + "TX": + F.VALUE_OR(0) @ F.TX @ F.TRACK, + "TY": + F.VALUE_OR(0) @ F.TY @ F.TRACK, + "FIRSTHIT_X": + F.VALUE_OR(0) @ F.X_COORDINATE @ F.POSITION + @ F.STATE_AT('FirstMeasurement') @ F.TRACK, + "FIRSTHIT_Y": + F.VALUE_OR(0) @ F.Y_COORDINATE @ F.POSITION + @ F.STATE_AT('FirstMeasurement') @ F.TRACK, + "FIRSTHIT_Z": + F.VALUE_OR(0) @ F.Z_COORDINATE @ F.POSITION + @ F.STATE_AT('FirstMeasurement') @ F.TRACK, + }) + variables_basic += FC.ParticleID(extra_info=True) + + variables_comb = FunctorCollection({ + "M": + F.MASS, + "CHI2": + F.CHI2, + "ENDVTX_X": + F.END_VX, + "ENDVTX_Y": + F.END_VY, + "ENDVTX_Z": + F.END_VZ, + "ENDVTX_COV_XX": + F.CALL(0, 0) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "ENDVTX_COV_XY": + F.CALL(0, 1) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "ENDVTX_COV_XZ": + F.CALL(0, 2) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "ENDVTX_COV_YY": + F.CALL(1, 1) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "ENDVTX_COV_YZ": + F.CALL(1, 2) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "ENDVTX_COV_ZZ": + F.CALL(2, 2) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "OWNPV_X": + F.OWNPVX, + "OWNPV_Y": + F.OWNPVY, + "OWNPV_Z": + F.OWNPVZ, + "OWNPV_NDOF": + F.NDOF @ F.OWNPV, + "OWNPV_DIRA": + F.OWNPVDIRA, + "OWNPV_VDRHO": + F.OWNPVVDRHO, + "OWNPV_FD": + F.OWNPVFD, + "OWNPV_FDCHI2": + F.OWNPVFDCHI2, + "OWNPV_CORRM": + F.OWNPVCORRM, + "OWNPV_CORRMERR": + F.OWNPVCORRMERR, + "TAU": + F.OWNPVLTIME, + }) + + # include here the BTracking info, as it was run on the D candidate + def get_BTracking_FC(rels, name="", state_info=True): + if name != "": name += "_" + fc = FunctorCollection({ + f"{name}BTRACKING_NHITS": + F.VALUE_OR(-1) @ F.BTRACKING_NHITS(rels), + f"{name}BTRACKING_NPRVELO3DEXPECT": + F.VALUE_OR(-1) @ F.BTRACKING_NPRVELO3DEXPECT(rels), + f"{name}BTRACKING_MCORR": + F.BTRACKING_BPVCORRM(rels), + f"{name}BTRACKING_TX": + F.VALUE_OR(0) @ F.TX @ F.BTRACKING_TRACK(rels), + f"{name}BTRACKING_TY": + F.VALUE_OR(0) @ F.TY @ F.BTRACKING_TRACK(rels), + }) + if state_info: + fc += FunctorCollection({ + f"{name}BTRACKING_FIRSTHIT_X": + F.VALUE_OR(0) @ F.X_COORDINATE @ F.POSITION + @ F.STATE_AT('FirstMeasurement') @ F.BTRACKING_TRACK(rels), + f"{name}BTRACKING_FIRSTHIT_Y": + F.VALUE_OR(0) @ F.Y_COORDINATE @ F.POSITION + @ F.STATE_AT('FirstMeasurement') @ F.BTRACKING_TRACK(rels), + f"{name}BTRACKING_FIRSTHIT_Z": + F.VALUE_OR(0) @ F.Z_COORDINATE @ F.POSITION + @ F.STATE_AT('FirstMeasurement') @ F.BTRACKING_TRACK(rels), + f"{name}BTRACKING_LASTHIT_X": + F.VALUE_OR(0) @ F.X_COORDINATE @ F.POSITION + @ F.STATE_AT('LastMeasurement') @ F.BTRACKING_TRACK(rels), + f"{name}BTRACKING_LASTHIT_Y": + F.VALUE_OR(0) @ F.Y_COORDINATE @ F.POSITION + @ F.STATE_AT('LastMeasurement') @ F.BTRACKING_TRACK(rels), + f"{name}BTRACKING_LASTHIT_Z": + F.VALUE_OR(0) @ F.Z_COORDINATE @ F.POSITION + @ F.STATE_AT('LastMeasurement') @ F.BTRACKING_TRACK(rels), + }) + return fc + + variables_D = get_BTracking_FC(rels) + + trigger_lines_D = [ + "Hlt1TwoTrackMVADecision", "Hlt1TrackMVADecision", "Hlt1KsToPiPi", + "Hlt1D2PiPi", "Hlt1D2KPi", "Hlt1D2KK" + ] + variables_D += FC.HltTisTos( + selection_type="Hlt1", trigger_lines=trigger_lines_D, data=dms) + + variables_D += get_isolation_variables( + line_name, dms, "Dm", "[D*(2007)0 -> D- pi+]cc", + "[D*(2007)0 -> D- pi-]cc", "[D*(2010)+ -> D+ pi- pi+]cc") + + # Bp variables + pvs = get_pvs() + + DTF_default = DecayTreeFitter( + name="DTF_default", + input_particles=bps, + ) + + DTF_Dpipi = DecayTreeFitter( + name="DTF_Dpipi", + input_particles=bps, + mass_constraints=["D-"], + ) + + DTF_PV = DecayTreeFitter( + name="DTF_PV", + input_particles=bps, + mass_constraints=[], + input_pvs=pvs, + constrain_to_ownpv=True, + ) + + DTF_Dpipi_PV = DecayTreeFitter( + name="DTF_Dpipi_PV", + input_particles=bps, + mass_constraints=["D-"], + input_pvs=pvs, + constrain_to_ownpv=True, + ) + + variables_B = FunctorCollection({ + "Dmpip_0_M": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 2)), + "Dmpip_1_M": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 3)), + "pippip_M": + F.SUBCOMB(Functor=F.MASS, Indices=(2, 3)), + "pippip_SDOCA": + F.SUBCOMB(Functor=F.MAXSDOCA, Indices=(2, 3)), + "pippip_SDOCACHI2": + F.SUBCOMB(Functor=F.MAXSDOCACHI2, Indices=(2, 3)), + "VTX_DLS_to_Dm": + F.VTX_DLS.bind(F.CHILD(1, F.ENDVERTEX), F.FORWARDARGS), + "OWNPV_COV_XX": + F.CALL(0, 0) @ F.POS_COV_MATRIX @ F.OWNPV, + "OWNPV_COV_XY": + F.CALL(0, 1) @ F.POS_COV_MATRIX @ F.OWNPV, + "OWNPV_COV_XZ": + F.CALL(0, 2) @ F.POS_COV_MATRIX @ F.OWNPV, + "OWNPV_COV_YY": + F.CALL(1, 1) @ F.POS_COV_MATRIX @ F.OWNPV, + "OWNPV_COV_YZ": + F.CALL(1, 2) @ F.POS_COV_MATRIX @ F.OWNPV, + "OWNPV_COV_ZZ": + F.CALL(2, 2) @ F.POS_COV_MATRIX @ F.OWNPV, + }) + + DTFs = [("DTF", DTF_default), ("DTF_Dpipi", DTF_Dpipi), ("DTF_PV", DTF_PV), + ("DTF_Dpipi_PV", DTF_Dpipi_PV)] + for name, dtf in DTFs: + variables_B += FunctorCollection({ + f"{name}_M": + dtf(F.MASS), + f"{name}_CHI2": + dtf(F.CHI2), + f"{name}_ENDVTX_X": + dtf(F.END_VX), + f"{name}_ENDVTX_Y": + dtf(F.END_VY), + f"{name}_ENDVTX_Z": + dtf(F.END_VZ), + f"{name}_Dm_ENDVTX_X": + dtf(F.CHILD(1, F.END_VX)), + f"{name}_Dm_ENDVTX_Y": + dtf(F.CHILD(1, F.END_VY)), + f"{name}_Dm_ENDVTX_Z": + dtf(F.CHILD(1, F.END_VZ)), + }) + + variables_B += get_BTracking_FC(rels_bp, name="BOnly") + + trigger_lines_B = [ + "Hlt1TwoTrackMVADecision", "Hlt1TrackMVADecision", "Hlt1KsToPiPi", + "Hlt1D2PiPi", "Hlt1D2KPi", "Hlt1D2KK" + ] + variables_B += FC.HltTisTos( + selection_type="Hlt1", trigger_lines=trigger_lines_B, data=bps) + + variables_B += get_isolation_variables( + line_name, bps, "Bp", "[B*0 -> B+ pi-]cc", "[B*0 -> B+ pi+]cc", + "[B*+ -> B+ pi- pi+]cc") + + # declare variables for each branch + variables = { + "ALL": variables_all, + "Dm_0": variables_comb + variables_D, + "Bp_0": variables_comb + variables_B, + "pip_0": variables_basic, + "pip_1": variables_basic, + "Kp_0": variables_basic, + "pim_0": variables_basic, + "pim_1": variables_basic, + } + + # global/event variables + evt_vars = FC.EventInfo() + evt_vars += FC.RecSummary(detector_info=True) + evt_vars += FC.SelectionInfo( + selection_type="Hlt1", trigger_lines=trigger_lines_B) + + # sequence + filter_bs = create_lines_filter( + name="HDRFilter_Bdpipi", lines=[f"{line_name}"]) + + tuple_bs = Funtuple( + name="BDpipi_Tuple", + tuple_name="DecayTree", + fields=fields, + variables=variables, + event_variables=evt_vars, + inputs=bps, + ) + + algs = { + "SpruceSLB_BToDPiPi_DToKPiPi_BTracking": [filter_bs, tuple_bs], + } + + return make_config(options, algs) + + +def run_data(options: Options): + return run_b2dpipi(options, MC=False) diff --git a/btracking_b2dpipi/info.yaml b/btracking_b2dpipi/info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a07a6a58b4dbb580d62f4c8ff02638d95b10d677 --- /dev/null +++ b/btracking_b2dpipi/info.yaml @@ -0,0 +1,34 @@ +defaults: + inform: + - maarten.vanveghel@cern.ch + - mick.mulder@cern.ch + wg: SL + + +{%- set datasets = [ + ( '2024Data_noUT', 'MagDown', '-Excl-UT/Real Data/Sprucing24c1', false, 'v64r8'), + ( '2024Data_noUT', 'MagUp', '-Excl-UT/Real Data/Sprucing24c1', false, 'v64r8'), + ( '2024Data_withUT', 'MagDown', '/Real Data/Sprucing24c2', true, 'v64r8'), +]%} +{%- for evttype, polarity, campaign, keep_running, dv_version in datasets %} +b2dpipi_btracking_{{ evttype }}_{{ polarity }}: + application: DaVinci/{{ dv_version }} + input: + bk_query: "/LHCb/Collision24/Beam6800GeV-VeloClosed-{{ polarity }}{{ campaign }}/90000000/SL.DST" + dq_flags: + - UNCHECKED + - OK + keep_running: {{ keep_running }} + n_test_lfns: 3 + output: data.root + options: + entrypoint: btracking_b2dpipi.dv_b2dpipi_options:run_data + extra_options: + input_raw_format: 0.5 + input_type: ROOT + simulation: False + geometry_version: run3/2024.Q1.2-v00.00 + conditions_version: master + input_process: "Spruce" + input_stream: "sl" +{%- endfor %}