diff --git a/LbToPp3pi_2024/dtf_maker.py b/LbToPp3pi_2024/dtf_maker.py new file mode 100644 index 0000000000000000000000000000000000000000..1f547a9ca851e621a81809477f79f30a735f08da --- /dev/null +++ b/LbToPp3pi_2024/dtf_maker.py @@ -0,0 +1,225 @@ +############################################################################## +# (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. # +############################################################################### +"""Configuration functions for DTF +""" +import Functors as F +from Functors.math import log + +from FunTuple import FunctorCollection +from FunTuple.functorcollections import Kinematics + +from DecayTreeFitter import DecayTreeFitter + + +def make_basic_dtf_variables(pvs, + data, + DTF=None, + pv_constraint=False, + mass_constraint=False, + particle_name=""): + variables = ( + FunctorCollection( + { + "TRCHI2DOF": F.CHI2DOF @ F.TRACK, + "ETA": F.ETA, + "PHI": F.PHI, + "TRGHOSTPROB": F.GHOSTPROB, + "BPVIPCHI2": F.BPVIPCHI2(pvs), + "BPVIP": F.BPVIP(pvs), + "BPVX": F.BPVX(pvs), + "BPVY": F.BPVY(pvs), + "BPVZ": F.BPVZ(pvs), + "TX": F.TX, + "TY": F.TY, + "MINIPCHI2": F.MINIPCHI2(pvs), + "MINIP": F.MINIP(pvs), + "KEY": F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.TRACK, + #"CTB" : F.POSITION @ F.CLOSESTTOBEAM @ F.TRACK, + "TRACKPT": F.TRACK_PT, + "TRACKHISTORY": F.VALUE_OR(-1) @ F.TRACKHISTORY @ F.TRACK, + "QOVERP": F.QOVERP @ F.TRACK, + "NDOF": F.VALUE_OR(-1) @ F.NDOF @ F.TRACK, + }) + Kinematics()) + + if (mass_constraint): + if (pv_constraint): # MASS + PV + dtf_variables_mass_pv = FunctorCollection({ + 'DTF_PV_Fix' + particle_name + '_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables_mass_pv + else: # MASS + dtf_variables_mass = FunctorCollection({ + 'DTF_Fix' + particle_name + '_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables_mass + elif (pv_constraint): # PV + dtf_variables_pv = FunctorCollection({ + 'DTF_PV_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables_pv + else: # NO MASS/PV + dtf_variables = FunctorCollection({ + 'DTF_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables + + +def make_composite_dtf_variables(pvs, + data, + DTF=None, + pv_constraint=False, + mass_constraint=False, + particle_name=""): + variables = ( + FunctorCollection({ + "MAXPT": F.MAX(F.PT), + "MINPT": F.MIN(F.PT), + "SUMPT": F.SUM(F.PT), + "MAXP": F.MAX(F.P), + "MINP": F.MIN(F.P), + "BPVDIRA": F.BPVDIRA(pvs), + "VCHI2DOF": F.CHI2DOF, #CHI2VXNDOF + "BPVFDCHI2": F.BPVFDCHI2(pvs), + "BPVFD": F.BPVFD(pvs), + "BPVVDRHO": F.BPVVDRHO(pvs), + "BPVVDZ": F.BPVVDZ(pvs), + "BPVIPCHI2": F.BPVIPCHI2(pvs), + "BPVIP": F.BPVIP(pvs), + "LOGBPVIPCHI2": log(F.BPVIPCHI2(pvs)), + "BPVLTIME": F.BPVLTIME(pvs), + "MAXBPVIPCHI2": F.MAX(F.BPVIPCHI2(pvs)), #MAX_ + "MINBPVIPCHI2": F.MIN(F.BPVIPCHI2(pvs)), + "MAXBPVIP": F.MAX(F.BPVIP(pvs)), + "MINBPVIP": F.MIN(F.BPVIP(pvs)), + "ETA": F.ETA, + "PHI": F.PHI, + "END_VX": F.END_VX, #END_ + "END_VY": F.END_VY, + "END_VZ": F.END_VZ, + "BPVX": F.BPVX(pvs), + "BPVY": F.BPVY(pvs), + "BPVZ": F.BPVZ(pvs), + "ALLPVFD": F.ALLPV_FD(pvs), + "ALLPVIP": F.ALLPV_IP(pvs), + }) + Kinematics()) + + addstring = "DTF" + if (pv_constraint): + addstring += '_PV' + if (mass_constraint): + addstring += '_Fix' + addstring += particle_name + + DTF_chi2ndof = FunctorCollection({ + addstring + "_DTFCHI2": DTF.CHI2, + addstring + "_DTFNDOF": DTF.NDOF, + addstring + "_CTAU": DTF.CTAU, + addstring + "_CTAUERR": DTF.CTAUERR, + addstring + "_MERR": DTF.MASSERR, + }) + + if (mass_constraint): + if (pv_constraint): # MASS + PV + dtf_variables_mass_pv = FunctorCollection({ + 'DTF_PV_Fix' + particle_name + '_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables_mass_pv + DTF_chi2ndof + else: # MASS + dtf_variables_mass = FunctorCollection({ + 'DTF_Fix' + particle_name + '_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables_mass + DTF_chi2ndof + elif (pv_constraint): # PV + dtf_variables_pv = FunctorCollection({ + 'DTF_PV_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables_pv + DTF_chi2ndof + else: # NO MASS/PV + dtf_variables = FunctorCollection({ + 'DTF_' + k: DTF(v) + for k, v in variables.get_thor_functors().items() + }) + return dtf_variables + DTF_chi2ndof + + +# +def make_dtf_variables(pvs, input_data, ptype, particle_to_constrain): + + if ptype not in ["basic", "composite"]: + Exception(f"I want \'basic\' or \'composite\'. Got {ptype}") + + #particle_to_constrain = ["KS0"] + + DTF = DecayTreeFitter( + name=f'DTF_{{hash}}', input_particles=input_data) + DTF_PV = DecayTreeFitter( + name=f'DTF_PV_{{hash}}', + input_particles=input_data, + input_pvs=pvs) + if particle_to_constrain is not None: + DTF_PV_mass = DecayTreeFitter( + name=f'DTF_PV_mass_{{hash}}', + input_particles=input_data, + input_pvs=pvs, + mass_constraints=particle_to_constrain) + + if ptype == "basic": + dtf_vars = make_basic_dtf_variables( + pvs, + input_data, + DTF=DTF, + pv_constraint=False, + mass_constraint=False) + dtf_vars += make_basic_dtf_variables( + pvs, + input_data, + DTF=DTF_PV, + pv_constraint=True, + mass_constraint=False) + if particle_to_constrain is not None: + dtf_vars += make_basic_dtf_variables( + pvs, + input_data, + DTF=DTF_PV_mass, + pv_constraint=True, + mass_constraint=True, + particle_name=particle_to_constrain[0]) + return dtf_vars + + if ptype == "composite": + dtf_vars = make_composite_dtf_variables( + pvs, + input_data, + DTF=DTF, + pv_constraint=False, + mass_constraint=False) + dtf_vars += make_composite_dtf_variables( + pvs, + input_data, + DTF=DTF_PV, + pv_constraint=True, + mass_constraint=False) + if particle_to_constrain is not None: + dtf_vars += make_composite_dtf_variables( + pvs, + input_data, + DTF=DTF_PV_mass, + pv_constraint=True, + mass_constraint=True, + particle_name=particle_to_constrain[0]) + return dtf_vars diff --git a/LbToPp3pi_2024/dv_data_LbToPp3pi.py b/LbToPp3pi_2024/dv_data_LbToPp3pi.py new file mode 100644 index 0000000000000000000000000000000000000000..595ead97a32799744065fc33816529a06d3d3701 --- /dev/null +++ b/LbToPp3pi_2024/dv_data_LbToPp3pi.py @@ -0,0 +1,21 @@ +from .tuple_maker import make_dv_tuple, tuple_template, line_prefilter +from DaVinci import Options, make_config + +decay_descriptor = { + "Lb0ToPpPipPimPim": { + "Lb": "[Lambda_b0 -> p+ pi+ pi- pi-]CC", + "Pp": "[Lambda_b0 -> ^p+ pi+ pi- pi-]CC", + "Pip": "[Lambda_b0 -> p+ ^pi+ pi- pi-]CC", + "Pim0": "[Lambda_b0 -> p+ pi+ ^pi- pi-]CC", + "Pim1": "[Lambda_b0 -> p+ pi+ pi- ^pi-]CC", + + } +} + + +def main(options: Options): + tuples = { + "Lb0ToPpPipPimPim": + make_dv_tuple(decay_descriptor["Lb0ToPpPipPimPim"], "Hlt2BnoC_Lb0ToPpPipPimPim_NoPID", particle_to_constrain=None), + } + return make_config(options, tuples) \ No newline at end of file diff --git a/LbToPp3pi_2024/info.yaml b/LbToPp3pi_2024/info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f765ea7b95e5ba86edf1dd0abe5ab64a833bae56 --- /dev/null +++ b/LbToPp3pi_2024/info.yaml @@ -0,0 +1,45 @@ +defaults: + application: DaVinci/v65r1 + wg: BnoC + inform: + - miroslav.saur@cern.ch + +# data configuration +{%- set datasets = [ + + ('Collision24', '24x', 'LbToPp3pi', 'MagDown-Excl-UT', 'TurboSpruce', 'bnoc'), + + ('Collision24', '24x', 'LbToPp3pi', 'MagUp-Excl-UT', 'TurboSpruce', 'bnoc'), + + ('Collision24', '24x', 'LbToPp3pi', 'MagDown', 'TurboSpruce', 'bnoc'), + + ('Collision24', '24x', 'LbToPp3pi', 'MagUp', 'TurboSpruce', 'bnoc'), + +]%} + +{%- for data, version, decay, polarity, process, stream in datasets %} + +data_{{decay}}_bnoc_{{data}}_{{version}}_{{polarity}}: + input: + bk_query: "/validation/{{data}}/Beam6800GeV-VeloClosed-{{polarity}}/Real Data/Sprucing{{version}}/94000000/BNOC.DST" + dq_flags: + - OK + keep_running: true + n_test_lfns: 1 + options: + entrypoint: LbToPp3pi_2024.dv_data_LbToPp3pi:main + extra_options: + input_type: ROOT + input_process: "{{process}}" + input_stream: "{{stream}}" + input_raw_format: 0.5 + simulation: False + data_type: "Upgrade" + geometry_version: run3/2024.Q1.2-v00.00 + conditions_version: master + compression: + algorithm: ZSTD + level: 1 + max_buffer_size: 131072 + output: Data_LbToPp3pi.ROOT +{%- endfor %} \ No newline at end of file diff --git a/LbToPp3pi_2024/tuple_maker.py b/LbToPp3pi_2024/tuple_maker.py new file mode 100644 index 0000000000000000000000000000000000000000..e669990e5c405e15e7baead5e47cc66a906392b3 --- /dev/null +++ b/LbToPp3pi_2024/tuple_maker.py @@ -0,0 +1,426 @@ +############################################################################### +# (c) Copyright 2021-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. # +############################################################################### +""" +Read an HLT2 file and create an ntuple with the new DaVinci configuration. +""" +import Functors as F +import FunTuple.functorcollections as FC +from FunTuple import FunctorCollection +from FunTuple import FunTuple_Particles as Funtuple +from PyConf.reading import get_particles, get_pvs, get_rec_summary +from DaVinci.algorithms import create_lines_filter +from DaVinciMCTools import MCTruthAndBkgCat +from FunTuple.functorcollections import MCHierarchy, MCPrimaries, MCPromptDecay, Kinematics, SelectionInfo, HltTisTos, MCVertexInfo, MCKinematics, ParticleID, EventInfo +from PyConf.reading import get_odin # get_decreports, +from DecayTreeFitter import DecayTreeFitter +from .dtf_maker import make_dtf_variables + +_basic = "basic" +_composite = "composite" +_toplevel = "toplevel" +_Lc = "Lc" +_Lb = "Lb" +_Xic = "Xic" +_Xibm = "Xibm" + + +def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): + """ + function that returns dictionary of functors that work. + + functors are listed in order of https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/selection/thor_functors_reference.html#module-Functo + """ + if ptype not in [_basic, _composite]: + Exception(f"I want {_basic} or {_composite}. Got {ptype}") + all_vars = FunctorCollection({}) + + comp = _composite == ptype or _toplevel == ptype # is composite + basic = _basic == ptype # is not composite + + # First import everything that comes in functorcollections + all_vars += FC.Kinematics() + if basic: + all_vars += FC.ParticleID(extra_info=True) + + if comp: # all these require a vertex + all_vars.update({"BPVDIRA": F.BPVDIRA(pvs)}) + all_vars.update({"BPVDLS": F.BPVDLS(pvs)}) + all_vars.update({"BPVETA": F.BPVETA(pvs)}) + all_vars.update({"BPVFD": F.BPVFD(pvs)}) + all_vars.update({"BPVFDCHI2": F.BPVFDCHI2(pvs)}) + all_vars.update({"BPVFDIR": F.BPVFDIR(pvs)}) + all_vars.update({"BPVFDVEC": F.BPVFDVEC(pvs)}) + + all_vars.update({"BPVIP": F.BPVIP(pvs)}) + all_vars.update({"BPVIPCHI2": F.BPVIPCHI2(pvs)}) + all_vars.update({"BPVX": F.BPVX(pvs)}) + all_vars.update({"BPVY": F.BPVY(pvs)}) + all_vars.update({"BPVZ": F.BPVZ(pvs)}) + + if comp: # all these require a vertex + all_vars.update({"ALLPV_FD": F.ALLPV_FD(pvs)}) + all_vars.update({"ALLPV_IP": F.ALLPV_IP(pvs)}) + all_vars.update({"BPVLTIME": F.BPVLTIME(pvs)}) + all_vars.update({"BPVVDRHO": F.BPVVDRHO(pvs)}) + all_vars.update({"BPVVDX": F.BPVVDX(pvs)}) + all_vars.update({"BPVVDY": F.BPVVDY(pvs)}) + all_vars.update({"BPVVDZ": F.BPVVDZ(pvs)}) + + all_vars.update({"CHARGE": F.CHARGE}) + all_vars.update({"CHI2": F.CHI2}) + all_vars.update({"CHI2DOF": F.CHI2DOF}) + + if comp: + all_vars.update({"END_VRHO": F.END_VRHO}) + all_vars.update({"END_VX": F.END_VX}) + all_vars.update({"END_VY": F.END_VY}) + all_vars.update({"END_VZ": F.END_VZ}) + + all_vars.update({"ETA": F.ETA}) + all_vars.update({"FOURMOMENTUM": F.FOURMOMENTUM}) + all_vars.update({"ISBASIC": F.ISBASICPARTICLE}) + + if basic: + all_vars.update({"GHOSTPROB": F.GHOSTPROB}) + all_vars.update({"ISMUON": F.ISMUON}) + all_vars.update({"INMUON": F.INMUON}) + all_vars.update({"INECAL": F.INECAL}) + all_vars.update({"INHCAL": F.INHCAL}) + #all_vars.update({"HASBREM": F.HASBREM}) + #all_vars.update({"BREMENERGY": F.BREMENERGY}) + #all_vars.update({"BREMBENDCORR": F.BREMBENDCORR}) + #all_vars.update({"BREMPIDE": F.BREMPIDE}) + #all_vars.update({"ECALPIDE": F.ECALPIDE}) + #all_vars.update({"ECALPIDMU": F.ECALPIDMU}) + #all_vars.update({"HCALPIDE": F.HCALPIDE}) + #all_vars.update({"HCALPIDMU": F.HCALPIDMU}) + #all_vars.update({"ELECTRONSHOWEREOP": F.ELECTRONSHOWEREOP}) + #all_vars.update({"CLUSTERMATCH": F.CLUSTERMATCH_CHI2}) + #all_vars.update({"ELECTRONMATCH": F.ELECTRONMATCH_CHI2}) + #all_vars.update({"BREMHYPOMATCH": F.BREMHYPOMATCH_CHI2}) + #all_vars.update({"ELECTRONENERGY": F.ELECTRONENERGY}) + #all_vars.update({"BREMHYPOENERGY": F.BREMHYPOENERGY}) + #all_vars.update({"BREMHYPODELTAX": F.BREMHYPODELTAX}) + #all_vars.update({"ELECTRONID": F.ELECTRONID}) + #all_vars.update({"HCALEOP": F.HCALEOP}) + # Note: the observables for the two functors below are (TRACK_MOM_X, TRACK_MOM_Y, TRACK_MOM_Z}) + # and (TRACK_POS_CLOSEST_TO_BEAM_X, TRACK_POS_CLOSEST_TO_BEAM_Y, TRACK_POS_CLOSEST_TO_BEAM_Z), + # which is why the trailing underscore in the name is added i.e. "TRACK_MOM_" and "TRACK_POS_CLOSEST_TO_BEAM_" + all_vars.update({"TRACK_MOM": F.TRACK_MOMVEC}) + all_vars.update({"TRACK_COVARIANCE": F.TRACK_COVARIANCE @ F.TRACKSTATE @ F.TRACK}) + all_vars.update({"TRACK_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM}) + all_vars.update({"POSITION_STATEAT_FirstMeasurement_X" : F.POSITION_X @ F.STATE_AT("FirstMeasurement")@ F.TRACK}) #NB only long tracks + all_vars.update({"POSITION_STATEAT_FirstMeasurement_Y" : F.POSITION_Y @ F.STATE_AT("FirstMeasurement")@ F.TRACK}) #NB only long tracks + all_vars.update({"POSITION_STATEAT_FirstMeasurement_Z" : F.POSITION_Z @ F.STATE_AT("FirstMeasurement")@ F.TRACK}) #NB only long tracks + + all_vars.update({"IS_ABS_ID_pi": F.IS_ABS_ID("pi+")}) + all_vars.update({"IS_ID_pi": F.IS_ID("pi-")}) + all_vars.update({"PDG_MASS_pi": F.PDG_MASS("pi+")}) + all_vars.update({"SIGNED_DELTA_MASS_pi": F.SIGNED_DELTA_MASS("pi+")}) + all_vars.update({"ABS_DELTA_MASS_pi": F.ABS_DELTA_MASS("pi+")}) + all_vars.update({"IS_NOT_H": F.IS_NOT_H}) + all_vars.update({"IS_PHOTON": F.IS_PHOTON}) + + all_vars.update({"MASS": F.MASS}) + + if comp: + all_vars.update({"MAXPT": F.MAX(F.PT)}) + all_vars.update({"MAXDOCA": F.MAXSDOCA}) + all_vars.update({"MAXDOCACHI2": F.MAXSDOCACHI2}) + # the above in cut versions. + + if comp: + all_vars.update({"MINPT": F.MIN(F.PT)}) + all_vars.update({"MINIP": F.MINIP(pvs)}) + all_vars.update({"MINIPCHI2": F.MINIPCHI2(pvs)}) + + if basic: + all_vars.update({"TRACKPT": F.TRACK_PT}) + all_vars.update({ + "TRACKHISTORY": + F.VALUE_OR(-1) @ F.TRACKHISTORY @ F.TRACK + }) + all_vars.update({"QOVERP": F.QOVERP @ F.TRACK}) + all_vars.update({"NDOF": F.VALUE_OR(-1) @ F.NDOF @ F.TRACK}) + all_vars.update({"NFTHITS": F.VALUE_OR(-1) @ F.NFTHITS @ F.TRACK}) + all_vars.update({"NHITS": F.VALUE_OR(-1) @ F.NHITS @ F.TRACK}) + all_vars.update({"NUTHITS": F.VALUE_OR(-1) @ F.NUTHITS @ F.TRACK}) + all_vars.update({"NVPHITS": F.VALUE_OR(-1) @ F.NVPHITS @ F.TRACK}) + all_vars.update({ + "TRACKHASVELO": + F.VALUE_OR(-1) @ F.TRACKHASVELO @ F.TRACK + }) + all_vars.update({ + "TRACKHASUT": F.VALUE_OR(-1) @ F.TRACKHASUT @ F.TRACK + }) + #all_vars.update({"POS_COV_MATRIX": F.POS_COV_MATRIX}) + #all_vars.update({"THREE_MOM_COV_MATRIX": F.THREE_MOM_COV_MATRIX}) + + all_vars.update({"OBJECT_KEY": F.OBJECT_KEY}) + + all_vars.update({"PHI": F.PHI}) + + all_vars.update({"ABS_PX": F.ABS @ F.PX}) + + all_vars.update({"REFERENCEPOINT_X": F.REFERENCEPOINT_X}) + all_vars.update({"REFERENCEPOINT_Y": F.REFERENCEPOINT_Y}) + all_vars.update({"REFERENCEPOINT_Z": F.REFERENCEPOINT_Z}) + + if comp: + all_vars.update({"DOCA": F.DOCA(Child1=1, Child2=2)}) + all_vars.update({"DOCACHI2": F.DOCACHI2(Child1=1, Child2=2)}) + all_vars.update({"SDOCA": F.SDOCA(1, 2)}) + all_vars.update({"SDOCACHI2": F.SDOCACHI2(1, 2)}) + all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)}) + if basic: + all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE}) + + if comp: + all_vars.update({"SUMPT": F.SUM(F.PT)}) + + if basic: + all_vars.update({"TX": F.TX}) + all_vars.update({"TY": F.TY}) + + print( + f"### For {ptype} returning variables {all_vars.functor_dict.keys()}") + return all_vars + + +def event_variables(PVs, ODIN, decreports, lines): + """ + event variables + """ + + evt_vars = FunctorCollection({}) + evt_vars += FC.EventInfo() + + evt_vars += FC.SelectionInfo(selection_type="Hlt2", trigger_lines=lines) + + if decreports: + evt_vars.update({ + "DECISIONS": + F.DECISIONS( + Lines=[bd2dsk_line + "Decision"], DecReports=decreports) + }) + evt_vars.update({ + "DECREPORTS_FILTER": + F.DECREPORTS_FILTER( + Lines=[bd2dsk_line + "Decision"], DecReports=decreports) + }) + + if ODIN: + evt_vars.update({"EVENTTYPE": F.EVENTTYPE(ODIN)}) + + evt_vars.update({"PV_SIZE": F.SIZE(PVs)}) + + if decreports: + evt_vars.update({"TCK": F.TCK(decreports)}) + + print(f"### For event returning variables {evt_vars.functor_dict.keys()}") + return evt_vars + + +def tuple_template(decay_descriptor, line_name, particle_to_constrain, isturbo, + Hlt2_decisions): + + evtpath_prefix = "/Event/Turbo/" + if not isturbo: + evtpath_prefix = "/Event/Spruce/" + + input_data = get_particles(evtpath_prefix + f"{line_name}/Particles") + + pvs = get_pvs() + + Hlt1_decisions = [ + 'Hlt1TrackMVADecision', + 'Hlt1TwoTrackMVADecision', + 'Hlt1D2KKDecision', + 'Hlt1D2KPiDecision', + 'Hlt1D2PiPiDecision', + 'Hlt1DiMuonHighMassDecision', + 'Hlt1DiMuonLowMassDecision', + 'Hlt1DiMuonSoftDecision', + 'Hlt1KsToPiPiDecision', + 'Hlt1LowPtMuonDecision', + 'Hlt1LowPtDiMuonDecision', + 'Hlt1SingleHighPtMuonDecision', + 'Hlt1TrackMuonMVADecision', + "Hlt1DiMuonNoIP_SSDecision", + "Hlt1DiMuonDrellYan_VLowMassDecision", + "Hlt1DiMuonDrellYan_VLowMass_SSDecision", + "Hlt1DiMuonDrellYanDecision", + "Hlt1DiMuonDrellYan_SSDecision", + "Hlt1DetJpsiToMuMuPosTagLineDecision", + "Hlt1DetJpsiToMuMuNegTagLineDecision", + "Hlt1TrackElectronMVADecision", + "Hlt1SingleHighPtElectronDecision", + "Hlt1DiElectronDisplacedDecision", + "Hlt1SingleHighEtDecision", + "Hlt1DiPhotonHighMassDecision", + "Hlt1Pi02GammaGammaDecision", + "Hlt1DiElectronHighMass_SSDecision", + "Hlt1DiElectronHighMassDecision", + "Hlt1DiMuonNoIPDecision", + ] + + composite_variables = FunctorCollection({ + "END_VX_ERR": + F.SQRT @ F.CALL(0, 0) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "END_VY_ERR": + F.SQRT @ F.CALL(1, 1) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "END_VZ_ERR": + F.SQRT @ F.CALL(2, 2) @ F.POS_COV_MATRIX @ F.ENDVERTEX, + "BPVX_ERR": + F.SQRT @ F.CALL(0, 0) @ F.POS_COV_MATRIX @ F.BPV(pvs), + "BPVY_ERR": + F.SQRT @ F.CALL(1, 1) @ F.POS_COV_MATRIX @ F.BPV(pvs), + "BPVZ_ERR": + F.SQRT @ F.CALL(2, 2) @ F.POS_COV_MATRIX @ F.BPV(pvs), + "PERR": + F.SQRT @ F.PERR2, + "PXERR": + F.SQRT @ F.CALL(0, 0) @ F.THREE_MOM_COV_MATRIX, + "PYERR": + F.SQRT @ F.CALL(1, 1) @ F.THREE_MOM_COV_MATRIX, + "PZERR": + F.SQRT @ F.CALL(2, 2) @ F.THREE_MOM_COV_MATRIX, + "M12": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 2)), + "M13": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 3)), + "M14": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 4)), + "M23": + F.SUBCOMB(Functor=F.MASS, Indices=(2, 3)), + "M24": + F.SUBCOMB(Functor=F.MASS, Indices=(2, 4)), + "M34": + F.SUBCOMB(Functor=F.MASS, Indices=(3, 4)), + "M123": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 2, 3)), + "M124": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 2, 4)), + "M134": + F.SUBCOMB(Functor=F.MASS, Indices=(1, 3, 4)), + "M234": + F.SUBCOMB(Functor=F.MASS, Indices=(2, 3, 4)), + }) + + composite_variables += HltTisTos( + selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=input_data) + if not isturbo: + composite_variables += HltTisTos( + selection_type="Hlt2", + trigger_lines=Hlt2_decisions, + data=input_data) + + daughter_variables = FunctorCollection({ + "PERR": + F.SQRT @ F.PERR2, + "PZERR": + F.SQRT @ F.CALL(2, 2) @ F.THREE_MOM_COV_MATRIX, + }) + + #define event level variables + odin = get_odin() + decreports = None + rec_sum = get_rec_summary() + event_info = event_variables( + pvs, odin, decreports, [line_name]) + FunctorCollection({ + "nPVs": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nPVs"), + "nTTracks": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nTTracks"), + "nLongTracks": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nLongTracks"), + "nDownstreamTracks": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nDownstreamTracks"), + "nUpstreamTracks": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nUpstreamTracks"), + "nVeloTracks": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nVeloTracks"), + "nBackTracks": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nBackTracks"), + "nRich1Hits": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nRich1Hits"), + "nRich2Hits": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nRich2Hits"), + "nVPClusters": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nVPClusters"), + "nFTClusters": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nFTClusters"), + "eCalTot": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "eCalTot"), + "hCalTot": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "hCalTot"), + "nEcalClusters": + F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_sum, "nEcalClusters"), + "ALLPVX": + F.ALLPVX(pvs), + "ALLPVY": + F.ALLPVY(pvs), + "ALLPVZ": + F.ALLPVZ(pvs), + }) + + event_info += FC.SelectionInfo( + selection_type="Hlt1", trigger_lines=Hlt1_decisions) + + allvariables = { + + ######################### + #### Lambda_b0 lines #### + ######################### + 'Hlt2BnoC_Lb0ToPpPipPimPim_NoPID': { + "Lb": + composite_variables + all_variables( + pvs, None, _composite) + make_dtf_variables( + pvs, input_data, _composite, particle_to_constrain), + "Pp": + daughter_variables + all_variables(pvs, None, _basic) + + make_dtf_variables(pvs, input_data, _basic, particle_to_constrain), + "Pip": + daughter_variables + all_variables(pvs, None, _basic) + + make_dtf_variables(pvs, input_data, _basic, particle_to_constrain), + "Pim0": + daughter_variables + all_variables(pvs, None, _basic) + + make_dtf_variables(pvs, input_data, _basic, particle_to_constrain), + "Pim1": + daughter_variables + all_variables(pvs, None, _basic) + + make_dtf_variables(pvs, input_data, _basic, particle_to_constrain), + }, + } + + variables = allvariables[line_name] + + #define FunTuple instance + my_tuple = Funtuple( + name=line_name, + tuple_name="DecayTree", + fields=decay_descriptor, + variables=variables, + event_variables=event_info, + store_multiple_cand_info=True, + inputs=input_data) + + return my_tuple + + +def line_prefilter(line_name): + return create_lines_filter(name=f"HLT_PASS{line_name}", lines=[line_name]) + + +def make_dv_tuple(decay_descriptor, line_name, particle_to_constrain): + my_tuple = tuple_template(decay_descriptor, line_name, + particle_to_constrain, True, []) + my_filter = line_prefilter(line_name) + return [my_filter, my_tuple]