From 78f91a3f18a3a5b4a49b3f76cc63dd76b18c9354 Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Thu, 20 Jun 2024 15:29:40 +0200 Subject: [PATCH 1/8] AP practice for exotic analyses --- Run3_b2psiX_pentaquark/Lb2JpsipK.py | 366 ++++++++++++++++++++ Run3_b2psiX_pentaquark/descriptor_writer.py | 72 ++++ Run3_b2psiX_pentaquark/info.yaml | 43 +++ Run3_b2psiX_pentaquark/tupling_maker.py | 331 ++++++++++++++++++ 4 files changed, 812 insertions(+) create mode 100644 Run3_b2psiX_pentaquark/Lb2JpsipK.py create mode 100644 Run3_b2psiX_pentaquark/descriptor_writer.py create mode 100644 Run3_b2psiX_pentaquark/info.yaml create mode 100644 Run3_b2psiX_pentaquark/tupling_maker.py diff --git a/Run3_b2psiX_pentaquark/Lb2JpsipK.py b/Run3_b2psiX_pentaquark/Lb2JpsipK.py new file mode 100644 index 0000000000..44b4fc11cc --- /dev/null +++ b/Run3_b2psiX_pentaquark/Lb2JpsipK.py @@ -0,0 +1,366 @@ +from DaVinci import make_config, Options +from DaVinci.algorithms import create_lines_filter + +from PyConf.reading import get_rec_summary, get_pvs +from PyConf.reading import get_particles + +import FunTuple.functorcollections as FC +import Functors as F +from FunTuple import FunctorCollection + +from FunTuple import FunTuple_Event +from FunTuple import FunTuple_Particles + +from Hlt2Conf.standard_particles import make_long_kaons, make_long_protons, make_long_pions + +#from PyConf.reading import (get_particles, get_charged_protoparticles, get_pvs, get_rec_summary, _get_unpacked) + +from Functors.math import in_range +from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleFilter + +from RecoConf.event_filters import require_pvs + + + +from Hlt2Conf.standard_particles import get_long_track_selector, standard_protoparticle_filter +from PyConf.Algorithms import FunctionalParticleMaker +from PyConf.reading import get_charged_protoparticles as _make_charged_protoparticles +from PyConf.reading import get_odin + +from GaudiKernel.SystemOfUnits import MeV, picosecond, mm + +from itertools import combinations + +from .descriptor_writer import decay_branches + +_basic = "basic" +_composite = "composite" +_toplevel = "toplevel" + + +def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): + + 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 + top = _toplevel == ptype # the B + + all_vars += FC.Kinematics() + if basic: + all_vars += FC.ParticleID(extra_info=True) + + if comp: + all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)}) + + if comp: # all these require a vertex + all_vars.update({"BPVCORRM": F.BPVCORRM(pvs)}) + all_vars.update({"BPVCORRMERR": F.BPVCORRMERR(pvs)}) + 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)}) + all_vars.update({"ALLPVX": F.ALLPVX(pvs)}) + all_vars.update({"ALLPVY": F.ALLPVY(pvs)}) + all_vars.update({"ALLPVZ": F.ALLPVZ(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 top: # apply this only to B + # all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)}) # example of CHILD + # all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)}) + # all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ}) + + if comp: + #all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)}) + #all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)}) + 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}) + + # duplicated from FC all_vars.update({"ENERGY" : F.ENERGY}) + 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}) + all_vars.update({"TRACK_MOM_": F.TRACK_MOMVEC}) + all_vars.update({"TRACK_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM}) + 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}) + + if comp: + all_vars.update({"MAXPT": F.MAX(F.PT)}) + all_vars.update({"MAXDOCA": F.MAXSDOCA}) + all_vars.update({"MAXDOCACHI2": F.MAXSDOCACHI2}) + #all_vars.update({"MINDOCA": F.MINSDOCA}) + #all_vars.update({"MINDOCACHI2": F.MINSDOCACHI2}) + # the above in cut versions. + + # duplicated from FC all_vars.update({ 'MC_MOTHER_ID' : F.VALUE_OR(0) @ mctruth( + # duplicated from FC F.MC_MOTHER(1, F.PARTICLE_ID))}) + + 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({"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({"SDOCA12": F.SDOCA(1, 2)}) + all_vars.update({"SDOCA12_CHI2": F.SDOCACHI2(1, 2)}) + if basic: + all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE}) + + if comp: + all_vars.update({"SUBCOMB12_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 2))}) + all_vars.update({"SUMPT": F.SUM(F.PT)}) + if top: + all_vars.update({"SDOCA13": F.SDOCA(1, 3)}) + all_vars.update({"SDOCA13_CHI2": F.SDOCACHI2(1, 3)}) + all_vars.update({"SDOCA23": F.SDOCA(2, 3)}) + all_vars.update({"SDOCA23_CHI2": F.SDOCACHI2(2, 3)}) + all_vars.update({"SUBCOMB13_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 3))}) + all_vars.update({"SUBCOMB23_MM": F.SUBCOMB(Functor=F.MASS, Indices=(2, 3))}) + + 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, rec_sum, hlt1_lines, sprucing_lines): + """ + event variables + """ + + ## Some empty summaries removed + evt_vars = FunctorCollection({ + "nPVs": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nPVs"), + "nTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTracks"), + "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"), + "nGhosts": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nGhosts"), + "nRich1Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich1Hits"), + "nRich2Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich2Hits"), + #"nVeloClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloClusters"), + "nVPClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVPClusters"), + #"nITClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nITClusters"), + #"nTTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTClusters"), + "nUTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUTClusters"), + #"nOTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nOTClusters"), + "nFTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nFTClusters"), + #"nSPDhits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nSPDhits"), + "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"), + #"nMuonCoordsS0": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS0"), + #"nMuonCoordsS1": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS1"), + #"nMuonCoordsS2": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS2"), + #"nMuonCoordsS3": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS3"), + #"nMuonCoordsS4": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS4"), + #"nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"), + "ALLPVX": F.ALLPVX(PVs), + "ALLPVY": F.ALLPVY(PVs), + "ALLPVZ": F.ALLPVZ(PVs), + }) + evt_vars += FC.EventInfo() + + evt_vars += FC.SelectionInfo( selection_type="Hlt1", trigger_lines=hlt1_lines) + evt_vars += FC.SelectionInfo( selection_type="Hlt2", trigger_lines=sprucing_lines) + # duplicated from FC if ODIN: + # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_ID' : F.BUNCHCROSSING_ID(ODIN)}) + # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_TYPE' : F.BUNCHCROSSING_TYPE(ODIN)}) + + 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)}) + + # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) + # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) + + evt_vars.update({"PV_SIZE": F.SIZE(PVs)}) + # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) + # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) + + if decreports: + evt_vars.update({"TCK": F.TCK(decreports)}) + + print(f"### For event returning variables {evt_vars.functor_dict.keys()}") + return evt_vars + +def candidate_variables(pvs, mother, daughters): + variables_B = {mother: all_variables(pvs, None, _toplevel)} + for daughter in daughters: + if ("psi" in daughter) or ("Lambda" in daughter) or ("lambda" in daughter): + variables_B.update( {daughter: all_variables(pvs, None, _composite)} ) + else: + variables_B.update( {daughter: all_variables(pvs, None, _basic)} ) + return variables_B + + +def main(options: Options): + + sprucing_line = 'SpruceBandQ_JpsiToMuMuDetached' + Jpsi2mumu_data = get_particles(f"/Event/Spruce/{sprucing_line}/Particles") + + rec_sum = get_rec_summary() + + v2_pvs = get_pvs() + + + pions = make_long_pions() + kaons = make_long_kaons() + protons = make_long_protons() + + # create particle containers + pid_pions = ParticleFilter( pions, Cut=F.FILTER( F.require_all( F.PID_K < 5 ) ) ) + pid_kaons = ParticleFilter( kaons, Cut=F.FILTER( F.require_all( F.PID_K > 0 ) ) ) + pid_protons = ParticleFilter( protons, Cut=F.FILTER( F.require_all( F.PID_P > 0, (F.PID_P-F.PID_K)>0 ) ) ) + + mother = "Lb" + daughters = ["Jpsi", "mup", "mum", "Pp", "Km"] + decay = "[Lambda_b0 -> J/psi(1S) p+ K-]cc" + + Lb2JpsipK = ParticleCombiner( + Inputs = [Jpsi2mumu_data, pid_protons, pid_kaons], + DecayDescriptor = decay, + name="JpsiToMuMu_Detached_line_validation", + CombinationCut=F.require_all(in_range(5400, F.MASS, 6600)), + CompositeCut=F.require_all(in_range(5400, F.MASS, 6600), F.CHI2DOF < 20, F.BPVLTIME(v2_pvs) > 0.2 * picosecond, F.BPVVDRHO(v2_pvs) > 0. * mm, F.BPVVDZ(v2_pvs) > 0. * mm, F.BPVDIRA(v2_pvs) > 0.), + ) + + #FunTuple: define branches. + + hlt1_trigger_lines = [ 'Hlt1TrackMVADecision', + 'Hlt1TwoTrackMVADecision', + 'Hlt1D2KKDecision', + 'Hlt1D2KPiDecision', + 'Hlt1D2PiPiDecision', + 'Hlt1DiMuonHighMassDecision', + 'Hlt1DiMuonLowMassDecision', + 'Hlt1DiMuonSoftDecision', + 'Hlt1KsToPiPiDecision', + 'Hlt1LowPtMuonDecision', + 'Hlt1LowPtDiMuonDecision', + 'Hlt1SingleHighPtMuonDecision', + 'Hlt1TrackMuonMVADecision'] + + + #variables_B = { "Lb": all_variables(v2_pvs, None, _toplevel), + # "Jpsi": all_variables(v2_pvs, None, _composite), + # "mup": all_variables(v2_pvs, None, _basic), + # "mum": all_variables(v2_pvs, None, _basic), + # "Pp": all_variables(v2_pvs, None, _basic), + # "Km": all_variables(v2_pvs, None, _basic), + #} + + odin = get_odin() + decreports = None + + line_prefilter = create_lines_filter(name=f"PreFilter_{sprucing_line}", lines=[sprucing_line]) + evt_vars = event_variables(v2_pvs, odin, decreports, rec_sum, hlt1_trigger_lines, [sprucing_line]) + candidate_vars = candidate_variables(v2_pvs, mother, daughters) + Lb2JpsipK_branches = decay_branches(mother, daughters, decay) + print(Lb2JpsipK_branches) + + # define tupling algorithms + Lb2JpsipK_tuple = FunTuple_Particles(name="Lb2JpsipKTuple", + inputs=Lb2JpsipK, + tuple_name="DecayTree", + fields=Lb2JpsipK_branches, + variables=candidate_vars, + store_multiple_cand_info = True, + event_variables = evt_vars) + + algs = { "Lb2JpsipK_tuple":[ Lb2JpsipK_tuple, line_prefilter ],} + + return make_config( options, algs ) + diff --git a/Run3_b2psiX_pentaquark/descriptor_writer.py b/Run3_b2psiX_pentaquark/descriptor_writer.py new file mode 100644 index 0000000000..ed43f03e41 --- /dev/null +++ b/Run3_b2psiX_pentaquark/descriptor_writer.py @@ -0,0 +1,72 @@ +def decay_branches(mother, daughters, decay_descriptor): + psi_pos = 0 + Pm_pos = Pp_pos = 0 + Km_pos = Kp_pos = 0 + Pim_pos = Pip_pos = 0 + mum_pos = mup_pos = 0 + em_pos = ep_pos = 0 + + #if decay_descriptor[0] == "[" or decay_descriptor[-3:] == "]cc": + if "cc" in decay_descriptor[-5:]: + branch_descriptor = decay_descriptor[:-2] + "CC" + else: branch_descriptor = decay_descriptor + if "J/psi(1S)" in decay_descriptor: + branch_descriptor = branch_descriptor.replace("J/psi(1S)", "(J/psi(1S) -> mu+ mu-)") + if "psi(2S)" in decay_descriptor: + branch_descriptor = branch_descriptor.replace("psi(2S)", "(psi(2S) -> mu+ mu-)") + if "psi(2S)" in decay_descriptor: + branch_descriptor = branch_descriptor.replace("psi(2S)", "(psi(2S) -> mu+ mu-)") + + branches = {mother: branch_descriptor} + + for daughter in daughters: + if "psi" in daughter: + true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("psi", psi_pos)) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + psi_pos = branch_descriptor.find("psi", psi_pos) + len("psi(nS)") + if "Pp" in daughter: + true_pos = branch_descriptor.find("p+", Pp_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pp_pos = true_pos + len("p+") + if "Pm" in daughter: + true_pos = branch_descriptor.find("p~-", Pm_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pm_pos = true_pos + len("p~-") + if "Kp" in daughter: + true_pos = branch_descriptor.find("K+", Kp_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Kp_pos = true_pos + len("K+") + if "Km" in daughter: + true_pos = branch_descriptor.find("K-", Km_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Km_pos = true_pos + len("K-") + if "Pip" in daughter or "Hp" in daughter: + true_pos = branch_descriptor.find("pi+", Pip_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pip_pos = true_pos + len("pi+") + if "Pim" in daughter or "Hm" in daughter: + true_pos = branch_descriptor.find("pi-", Pim_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pim_pos = true_pos + len("pi-") + if "mup" in daughter: + true_pos = branch_descriptor.find("mu+", mup_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + mup_pos = true_pos + len("mu+") + if "mum" in daughter: + true_pos = branch_descriptor.find("mu-", mum_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + mum_pos = true_pos + len("mu-") + if "ep" in daughter: + true_pos = branch_descriptor.find("e+", ep_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + ep_pos = true_pos + len("e+") + if "em" in daughter: + true_pos = branch_descriptor.find("e-", em_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + em_pos = true_pos + len("e-") + return branches + +#branches = decay_branches("Lb", ["Jpsi", "mup", "mum", "mup2", "mum2"], "[Lambda_b0 -> J/psi(1S) psi(2S)]cc") +#branches = decay_branches("Bs", ["Jpsi", "Pp", "Pm", "mup", "mum"], "[B_s0 -> J/psi(1S) p+ p~-]cc") +#print(branches) + diff --git a/Run3_b2psiX_pentaquark/info.yaml b/Run3_b2psiX_pentaquark/info.yaml new file mode 100644 index 0000000000..8b6ffc4cb0 --- /dev/null +++ b/Run3_b2psiX_pentaquark/info.yaml @@ -0,0 +1,43 @@ +defaults: + application: DaVinci/v64r5 + wg: BandQ + inform: + - sanqiang.qu@cern.ch + - mengzhen.wang@cern.ch + - jianqiao.wang@cern.ch + +# data configuration +{%- set datasets = [ + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), +]%} + + +{%- set dv_platform_detdesc = "x86_64_v2-el9-gcc13+detdesc-opt" %} + +{%- for data, Type, wg, decay, polarity, Velo, process, stream in datasets %} + +data_{{decay}}_{{wg}}_{{process}}_{{data}}_{{Velo}}_{{polarity}}: + application: "DaVinci/v64r5" + input: + bk_query: "/LHCb/{{data}}/Beam6800GeV-{{Velo}}-{{polarity}}-Excl-UT/Real Data/{{Type}}/{{wg}}.DST" + dq_flags: + - OK + - UNCHECKED + keep_running: False + n_test_lfns: 1 + options: + entrypoint: Run3_b2psiX_pentaquark.{{decay}}: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 + output: Data_{{process}}_{{stream}}_{{decay}}.ROOT +{%- endfor %} + + diff --git a/Run3_b2psiX_pentaquark/tupling_maker.py b/Run3_b2psiX_pentaquark/tupling_maker.py new file mode 100644 index 0000000000..7da9acc157 --- /dev/null +++ b/Run3_b2psiX_pentaquark/tupling_maker.py @@ -0,0 +1,331 @@ +############################################################################### +# (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 + +_basic = "basic" +_composite = "composite" +_toplevel = "toplevel" + +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 + top = _toplevel == ptype # the B + + # First import everything that comes in functorcollections + all_vars += FC.Kinematics() + if basic: + all_vars += FC.ParticleID(extra_info=True) + + if comp: + all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)}) + + if comp: # all these require a vertex + all_vars.update({"BPVCORRM": F.BPVCORRM(pvs)}) + all_vars.update({"BPVCORRMERR": F.BPVCORRMERR(pvs)}) + 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 top: # apply this only to B + all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)}) # example of CHILD + all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)}) + all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ}) + + if comp: + all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)}) + all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)}) + 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_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM}) + + 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({"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({"SDOCA": F.SDOCA(1, 2)}) + all_vars.update({"SDOCACHI2": F.SDOCACHI2(1, 2)}) + if basic: + all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE}) + + if comp: + all_vars.update({"SUBCOMB12_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 2))}) + 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 template(decay_descriptor, line_name, isturbo, Hlt2_decisions): + + evtpath_prefix = "/Event/Spruce/" + if isturbo: + evtpath_prefix = "/Event/HLT2/" + + QQbar2mumu_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, + }) + + composite_variables += HltTisTos( selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=QQbar2mumu_data) + if not isturbo: + composite_variables += HltTisTos( selection_type="Hlt2", trigger_lines=Hlt2_decisions, data=QQbar2mumu_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 + ) + + variables = { + "QQbar": composite_variables + all_variables(pvs, None, _composite), + "mup": daughter_variables + all_variables(pvs, None, _basic), + "mum": daughter_variables + all_variables(pvs, None, _basic), + } + + #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=QQbar2mumu_data) + + return my_tuple + +def line_prefilter(line_name): + return create_lines_filter(name=f"HLT_PASS{line_name}", lines=[line_name]) + -- GitLab From f7c4721d91587e1492b3479fbcd8c336c08e7d6d Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Sun, 23 Jun 2024 08:46:51 +0200 Subject: [PATCH 2/8] All channels implemented --- Run3_b2psiX_pentaquark/B2JpsiKpi.py | 6 + Run3_b2psiX_pentaquark/B2Jpsippbar.py | 6 + Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py | 6 + Run3_b2psiX_pentaquark/Lb2JpsipK.py | 366 +----------------- Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py | 6 + Run3_b2psiX_pentaquark/info.yaml | 9 +- Run3_b2psiX_pentaquark/template.py | 88 +++++ .../{ => tools}/descriptor_writer.py | 56 ++- .../{ => tools}/tupling_maker.py | 313 +++++++-------- 9 files changed, 316 insertions(+), 540 deletions(-) create mode 100644 Run3_b2psiX_pentaquark/B2JpsiKpi.py create mode 100644 Run3_b2psiX_pentaquark/B2Jpsippbar.py create mode 100644 Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py create mode 100644 Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py create mode 100644 Run3_b2psiX_pentaquark/template.py rename Run3_b2psiX_pentaquark/{ => tools}/descriptor_writer.py (61%) rename Run3_b2psiX_pentaquark/{ => tools}/tupling_maker.py (54%) diff --git a/Run3_b2psiX_pentaquark/B2JpsiKpi.py b/Run3_b2psiX_pentaquark/B2JpsiKpi.py new file mode 100644 index 0000000000..8fe4bf611a --- /dev/null +++ b/Run3_b2psiX_pentaquark/B2JpsiKpi.py @@ -0,0 +1,6 @@ +from .template import * + +def main(options: Options): + algs = template(["B0", "J/psi(1S)", "K+", "pi-"], True, "B2JpsiKpi") + return make_config( options, algs ) + diff --git a/Run3_b2psiX_pentaquark/B2Jpsippbar.py b/Run3_b2psiX_pentaquark/B2Jpsippbar.py new file mode 100644 index 0000000000..cd125179c9 --- /dev/null +++ b/Run3_b2psiX_pentaquark/B2Jpsippbar.py @@ -0,0 +1,6 @@ +from .template import * + +def main(options: Options): + algs = template(["B_s0", "J/psi(1S)", "p+", "p~-"], False, "B2Jpsippbar") + return make_config( options, algs ) + diff --git a/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py b/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py new file mode 100644 index 0000000000..a694aff783 --- /dev/null +++ b/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py @@ -0,0 +1,6 @@ +from .template import * + +def main(options: Options): + algs = template(["B+", "J/psi(1S)", "p+", "Lambda~0"], True, "Bp2JpsipLambdabar") + return make_config( options, algs ) + diff --git a/Run3_b2psiX_pentaquark/Lb2JpsipK.py b/Run3_b2psiX_pentaquark/Lb2JpsipK.py index 44b4fc11cc..208ffa2f16 100644 --- a/Run3_b2psiX_pentaquark/Lb2JpsipK.py +++ b/Run3_b2psiX_pentaquark/Lb2JpsipK.py @@ -1,366 +1,6 @@ -from DaVinci import make_config, Options -from DaVinci.algorithms import create_lines_filter - -from PyConf.reading import get_rec_summary, get_pvs -from PyConf.reading import get_particles - -import FunTuple.functorcollections as FC -import Functors as F -from FunTuple import FunctorCollection - -from FunTuple import FunTuple_Event -from FunTuple import FunTuple_Particles - -from Hlt2Conf.standard_particles import make_long_kaons, make_long_protons, make_long_pions - -#from PyConf.reading import (get_particles, get_charged_protoparticles, get_pvs, get_rec_summary, _get_unpacked) - -from Functors.math import in_range -from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleFilter - -from RecoConf.event_filters import require_pvs - - - -from Hlt2Conf.standard_particles import get_long_track_selector, standard_protoparticle_filter -from PyConf.Algorithms import FunctionalParticleMaker -from PyConf.reading import get_charged_protoparticles as _make_charged_protoparticles -from PyConf.reading import get_odin - -from GaudiKernel.SystemOfUnits import MeV, picosecond, mm - -from itertools import combinations - -from .descriptor_writer import decay_branches - -_basic = "basic" -_composite = "composite" -_toplevel = "toplevel" - - -def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): - - 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 - top = _toplevel == ptype # the B - - all_vars += FC.Kinematics() - if basic: - all_vars += FC.ParticleID(extra_info=True) - - if comp: - all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)}) - - if comp: # all these require a vertex - all_vars.update({"BPVCORRM": F.BPVCORRM(pvs)}) - all_vars.update({"BPVCORRMERR": F.BPVCORRMERR(pvs)}) - 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)}) - all_vars.update({"ALLPVX": F.ALLPVX(pvs)}) - all_vars.update({"ALLPVY": F.ALLPVY(pvs)}) - all_vars.update({"ALLPVZ": F.ALLPVZ(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 top: # apply this only to B - # all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)}) # example of CHILD - # all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)}) - # all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ}) - - if comp: - #all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)}) - #all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)}) - 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}) - - # duplicated from FC all_vars.update({"ENERGY" : F.ENERGY}) - 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}) - all_vars.update({"TRACK_MOM_": F.TRACK_MOMVEC}) - all_vars.update({"TRACK_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM}) - 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}) - - if comp: - all_vars.update({"MAXPT": F.MAX(F.PT)}) - all_vars.update({"MAXDOCA": F.MAXSDOCA}) - all_vars.update({"MAXDOCACHI2": F.MAXSDOCACHI2}) - #all_vars.update({"MINDOCA": F.MINSDOCA}) - #all_vars.update({"MINDOCACHI2": F.MINSDOCACHI2}) - # the above in cut versions. - - # duplicated from FC all_vars.update({ 'MC_MOTHER_ID' : F.VALUE_OR(0) @ mctruth( - # duplicated from FC F.MC_MOTHER(1, F.PARTICLE_ID))}) - - 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({"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({"SDOCA12": F.SDOCA(1, 2)}) - all_vars.update({"SDOCA12_CHI2": F.SDOCACHI2(1, 2)}) - if basic: - all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE}) - - if comp: - all_vars.update({"SUBCOMB12_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 2))}) - all_vars.update({"SUMPT": F.SUM(F.PT)}) - if top: - all_vars.update({"SDOCA13": F.SDOCA(1, 3)}) - all_vars.update({"SDOCA13_CHI2": F.SDOCACHI2(1, 3)}) - all_vars.update({"SDOCA23": F.SDOCA(2, 3)}) - all_vars.update({"SDOCA23_CHI2": F.SDOCACHI2(2, 3)}) - all_vars.update({"SUBCOMB13_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 3))}) - all_vars.update({"SUBCOMB23_MM": F.SUBCOMB(Functor=F.MASS, Indices=(2, 3))}) - - 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, rec_sum, hlt1_lines, sprucing_lines): - """ - event variables - """ - - ## Some empty summaries removed - evt_vars = FunctorCollection({ - "nPVs": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nPVs"), - "nTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTracks"), - "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"), - "nGhosts": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nGhosts"), - "nRich1Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich1Hits"), - "nRich2Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich2Hits"), - #"nVeloClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloClusters"), - "nVPClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVPClusters"), - #"nITClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nITClusters"), - #"nTTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTClusters"), - "nUTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUTClusters"), - #"nOTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nOTClusters"), - "nFTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nFTClusters"), - #"nSPDhits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nSPDhits"), - "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"), - #"nMuonCoordsS0": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS0"), - #"nMuonCoordsS1": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS1"), - #"nMuonCoordsS2": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS2"), - #"nMuonCoordsS3": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS3"), - #"nMuonCoordsS4": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS4"), - #"nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"), - "ALLPVX": F.ALLPVX(PVs), - "ALLPVY": F.ALLPVY(PVs), - "ALLPVZ": F.ALLPVZ(PVs), - }) - evt_vars += FC.EventInfo() - - evt_vars += FC.SelectionInfo( selection_type="Hlt1", trigger_lines=hlt1_lines) - evt_vars += FC.SelectionInfo( selection_type="Hlt2", trigger_lines=sprucing_lines) - # duplicated from FC if ODIN: - # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_ID' : F.BUNCHCROSSING_ID(ODIN)}) - # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_TYPE' : F.BUNCHCROSSING_TYPE(ODIN)}) - - 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)}) - - # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) - # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) - - evt_vars.update({"PV_SIZE": F.SIZE(PVs)}) - # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) - # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) - - if decreports: - evt_vars.update({"TCK": F.TCK(decreports)}) - - print(f"### For event returning variables {evt_vars.functor_dict.keys()}") - return evt_vars - -def candidate_variables(pvs, mother, daughters): - variables_B = {mother: all_variables(pvs, None, _toplevel)} - for daughter in daughters: - if ("psi" in daughter) or ("Lambda" in daughter) or ("lambda" in daughter): - variables_B.update( {daughter: all_variables(pvs, None, _composite)} ) - else: - variables_B.update( {daughter: all_variables(pvs, None, _basic)} ) - return variables_B - +from .template import * def main(options: Options): - - sprucing_line = 'SpruceBandQ_JpsiToMuMuDetached' - Jpsi2mumu_data = get_particles(f"/Event/Spruce/{sprucing_line}/Particles") - - rec_sum = get_rec_summary() - - v2_pvs = get_pvs() - - - pions = make_long_pions() - kaons = make_long_kaons() - protons = make_long_protons() - - # create particle containers - pid_pions = ParticleFilter( pions, Cut=F.FILTER( F.require_all( F.PID_K < 5 ) ) ) - pid_kaons = ParticleFilter( kaons, Cut=F.FILTER( F.require_all( F.PID_K > 0 ) ) ) - pid_protons = ParticleFilter( protons, Cut=F.FILTER( F.require_all( F.PID_P > 0, (F.PID_P-F.PID_K)>0 ) ) ) - - mother = "Lb" - daughters = ["Jpsi", "mup", "mum", "Pp", "Km"] - decay = "[Lambda_b0 -> J/psi(1S) p+ K-]cc" - - Lb2JpsipK = ParticleCombiner( - Inputs = [Jpsi2mumu_data, pid_protons, pid_kaons], - DecayDescriptor = decay, - name="JpsiToMuMu_Detached_line_validation", - CombinationCut=F.require_all(in_range(5400, F.MASS, 6600)), - CompositeCut=F.require_all(in_range(5400, F.MASS, 6600), F.CHI2DOF < 20, F.BPVLTIME(v2_pvs) > 0.2 * picosecond, F.BPVVDRHO(v2_pvs) > 0. * mm, F.BPVVDZ(v2_pvs) > 0. * mm, F.BPVDIRA(v2_pvs) > 0.), - ) - - #FunTuple: define branches. - - hlt1_trigger_lines = [ 'Hlt1TrackMVADecision', - 'Hlt1TwoTrackMVADecision', - 'Hlt1D2KKDecision', - 'Hlt1D2KPiDecision', - 'Hlt1D2PiPiDecision', - 'Hlt1DiMuonHighMassDecision', - 'Hlt1DiMuonLowMassDecision', - 'Hlt1DiMuonSoftDecision', - 'Hlt1KsToPiPiDecision', - 'Hlt1LowPtMuonDecision', - 'Hlt1LowPtDiMuonDecision', - 'Hlt1SingleHighPtMuonDecision', - 'Hlt1TrackMuonMVADecision'] - - - #variables_B = { "Lb": all_variables(v2_pvs, None, _toplevel), - # "Jpsi": all_variables(v2_pvs, None, _composite), - # "mup": all_variables(v2_pvs, None, _basic), - # "mum": all_variables(v2_pvs, None, _basic), - # "Pp": all_variables(v2_pvs, None, _basic), - # "Km": all_variables(v2_pvs, None, _basic), - #} - - odin = get_odin() - decreports = None - - line_prefilter = create_lines_filter(name=f"PreFilter_{sprucing_line}", lines=[sprucing_line]) - evt_vars = event_variables(v2_pvs, odin, decreports, rec_sum, hlt1_trigger_lines, [sprucing_line]) - candidate_vars = candidate_variables(v2_pvs, mother, daughters) - Lb2JpsipK_branches = decay_branches(mother, daughters, decay) - print(Lb2JpsipK_branches) - - # define tupling algorithms - Lb2JpsipK_tuple = FunTuple_Particles(name="Lb2JpsipKTuple", - inputs=Lb2JpsipK, - tuple_name="DecayTree", - fields=Lb2JpsipK_branches, - variables=candidate_vars, - store_multiple_cand_info = True, - event_variables = evt_vars) - - algs = { "Lb2JpsipK_tuple":[ Lb2JpsipK_tuple, line_prefilter ],} - - return make_config( options, algs ) + algs = template(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True, "Lb2JpsipK") + return make_config( options, algs ) diff --git a/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py b/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py new file mode 100644 index 0000000000..25f9e26e8c --- /dev/null +++ b/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py @@ -0,0 +1,6 @@ +from .template import * + +def main(options: Options): + algs = template(["Xi_b-", "J/psi(1S)", "Lambda0", "K-"], True, "Xib2JpsiLambdaK") + return make_config( options, algs ) + diff --git a/Run3_b2psiX_pentaquark/info.yaml b/Run3_b2psiX_pentaquark/info.yaml index 8b6ffc4cb0..b3d9352594 100644 --- a/Run3_b2psiX_pentaquark/info.yaml +++ b/Run3_b2psiX_pentaquark/info.yaml @@ -2,7 +2,6 @@ defaults: application: DaVinci/v64r5 wg: BandQ inform: - - sanqiang.qu@cern.ch - mengzhen.wang@cern.ch - jianqiao.wang@cern.ch @@ -10,6 +9,14 @@ defaults: {%- set datasets = [ ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2JpsiKpi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2JpsiKpi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2Jpsippbar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2Jpsippbar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ]%} diff --git a/Run3_b2psiX_pentaquark/template.py b/Run3_b2psiX_pentaquark/template.py new file mode 100644 index 0000000000..8bd521e36a --- /dev/null +++ b/Run3_b2psiX_pentaquark/template.py @@ -0,0 +1,88 @@ +from .tools.tupling_maker import * +from .tools.descriptor_writer import * + +from Hlt2Conf.standard_particles import make_long_kaons, make_long_protons, make_long_pions, make_LambdaLL, make_long_muons + +def template(particles, cc, directory): + + ##### Default inputs + sprucing_line = 'SpruceBandQ_JpsiToMuMuDetached' + Jpsi = get_particles(f"/Event/Spruce/{sprucing_line}/Particles") + + rec_sum = get_rec_summary() + v2_pvs = get_pvs() + odin = get_odin() + decreports = None + + long_pions = make_long_pions() + long_kaons = make_long_kaons() + long_protons = make_long_protons() + + DaughterCutp = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (P>10*GeV) & (PID_P>5) & (PID_P-PID_K>5) & (GHOSTPROB<0.5)" + DaughterCutpi = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K<5) & (GHOSTPROB<0.5)" + DaughterCutK = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K>5) & (GHOSTPROB<0.5)" + + protons = ParticleFilter( long_protons, Cut = F.FILTER( convert_cut(DaughterCutp) ) ) + kaons = ParticleFilter( long_kaons, Cut = F.FILTER( convert_cut(DaughterCutK) ) ) + pions = ParticleFilter( long_pions, Cut = F.FILTER( convert_cut(DaughterCutpi) ) ) + muons = make_long_muons() + Lambda = make_LambdaLL() + + input_dict = {"J/psi(1S)": Jpsi, + "Lambda0":Lambda, "Lambda~0":Lambda, + "pi+": pions, "pi-": pions, + "K+": kaons, "K-": kaons, + "p+": protons, "p~-": protons, + "mu+": muons, "mu~-": muons, + } + + # create particle containers + + B2JpsiX = ParticleCombiner( + Inputs = [input_dict[particle] for particle in particles[1:]], + DecayDescriptor = descriptor(particles, cc), + name = "JpsiToMuMu_Detached_line_validation", + CombinationCut = convert_cut("in_range(5000, MASS, 7000) & (CHILD(2, PT)+CHILD(3, PT)>900*MeV)"), + #CombinationCut = convert_cut("in_range(5200, MASS, 7000)"), + CompositeCut = convert_cut("in_range(5000, MASS, 7000) & CHI2DOF<20 & BPVLTIME(get_pvs())>0.2*picosecond & BPVVDZ(get_pvs())>0.*mm") + ) + + #FunTuple: define branches. + + hlt1_trigger_lines = [ 'Hlt1TrackMVADecision', + 'Hlt1TwoTrackMVADecision', + 'Hlt1D2KKDecision', + 'Hlt1D2KPiDecision', + 'Hlt1D2PiPiDecision', + 'Hlt1DiMuonHighMassDecision', + 'Hlt1DiMuonLowMassDecision', + 'Hlt1DiMuonSoftDecision', + 'Hlt1KsToPiPiDecision', + 'Hlt1LowPtMuonDecision', + 'Hlt1LowPtDiMuonDecision', + 'Hlt1SingleHighPtMuonDecision', + 'Hlt1TrackMuonMVADecision'] + + + mother = default_names(particles)[0] + daughters = default_names(particles)[1:] + + line_prefilter = create_lines_filter(name=f"PreFilter_{sprucing_line}", lines=[sprucing_line]) + evt_vars = event_variables(v2_pvs, odin, decreports, rec_sum, hlt1_trigger_lines, [sprucing_line]) + candidate_vars = candidate_variables(v2_pvs, mother, daughters) + print(candidate_vars) + B2JpsiX_branches = default_branches(particles, cc) + + # define tupling algorithms + B2JpsiX_tuple = FunTuple_Particles( name=directory, + inputs=B2JpsiX, + tuple_name="DecayTree", + fields=B2JpsiX_branches, + variables=candidate_vars, + store_multiple_cand_info = True, + event_variables = evt_vars) + + algs = { f"{directory}_tuple":[ B2JpsiX_tuple, line_prefilter ],} + + return algs + diff --git a/Run3_b2psiX_pentaquark/descriptor_writer.py b/Run3_b2psiX_pentaquark/tools/descriptor_writer.py similarity index 61% rename from Run3_b2psiX_pentaquark/descriptor_writer.py rename to Run3_b2psiX_pentaquark/tools/descriptor_writer.py index ed43f03e41..71882db092 100644 --- a/Run3_b2psiX_pentaquark/descriptor_writer.py +++ b/Run3_b2psiX_pentaquark/tools/descriptor_writer.py @@ -1,5 +1,13 @@ +def descriptor(particles, cc=False): + decay_descriptor = f"{particles[0]} ->" + for particle in particles[1:]: + decay_descriptor += f" {particle}" + if cc: decay_descriptor = f"[{decay_descriptor}]cc" + return decay_descriptor + def decay_branches(mother, daughters, decay_descriptor): psi_pos = 0 + Lambda_pos = 0 Pm_pos = Pp_pos = 0 Km_pos = Kp_pos = 0 Pim_pos = Pip_pos = 0 @@ -14,8 +22,10 @@ def decay_branches(mother, daughters, decay_descriptor): branch_descriptor = branch_descriptor.replace("J/psi(1S)", "(J/psi(1S) -> mu+ mu-)") if "psi(2S)" in decay_descriptor: branch_descriptor = branch_descriptor.replace("psi(2S)", "(psi(2S) -> mu+ mu-)") - if "psi(2S)" in decay_descriptor: - branch_descriptor = branch_descriptor.replace("psi(2S)", "(psi(2S) -> mu+ mu-)") + if "Lambda0" in decay_descriptor: + branch_descriptor = branch_descriptor.replace("Lambda0", "(Lambda0 -> p+ pi-)") + if "Lambda~0" in decay_descriptor: + branch_descriptor = branch_descriptor.replace("Lambda~0", "(Lambda~0 -> p~- pi+)") branches = {mother: branch_descriptor} @@ -24,6 +34,10 @@ def decay_branches(mother, daughters, decay_descriptor): true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("psi", psi_pos)) branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) psi_pos = branch_descriptor.find("psi", psi_pos) + len("psi(nS)") + if "Lambda" in daughter: + true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("Lambda", Lambda_pos)) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Lambda_pos = branch_descriptor.find("Lambda", Lambda_pos) + len("Lambda~0") if "Pp" in daughter: true_pos = branch_descriptor.find("p+", Pp_pos) branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) @@ -66,7 +80,43 @@ def decay_branches(mother, daughters, decay_descriptor): em_pos = true_pos + len("e-") return branches -#branches = decay_branches("Lb", ["Jpsi", "mup", "mum", "mup2", "mum2"], "[Lambda_b0 -> J/psi(1S) psi(2S)]cc") +def default_names(particles): + name_dict = {"Lambda_b0": "Lb", + "Xi_b-": "Xib", + "Xi_b0": "Xib", + "B0": "B0", + "B+": "Bp", + "B-": "Bm", + "B_s0": "Bs", + "J/psi(1S)": "Jpsi", + "psi(2S)": "psi2S", + "Lambda0": "Lambda", "Lambda~0": "Lambda", + "mu+": "mup", "mu-": "mum", + "e+": "ep", "e-": "em", + "pi+": "Pip", "pi-": "Pim", + "K+": "Kp", "K-": "Km", + "p+": "Pp", "p~-": "Pm", + } + names = [] + for particle in particles: + names.append( name_dict[ particle ] ) + if particle == "J/psi(1S)" or particle == "psi(2S)": + names += ["mup_psi", "mum_psi"] + elif particle == "Lambda0": + names += ["Pp_Lambda", "Pim_Lambda"] + elif particle == "Lambda~0": + names += ["Pm_Lambda", "Pip_Lambda"] + return names + +def default_branches(particles, cc=False): + names = default_names(particles) + return decay_branches(names[0], names[1:], descriptor(particles, cc)) + #branches = decay_branches("Bs", ["Jpsi", "Pp", "Pm", "mup", "mum"], "[B_s0 -> J/psi(1S) p+ p~-]cc") #print(branches) +#branches = default_name( ["B_s0","J/psi(1S)", "p+", "p~-"]) +#branches = default_branches( ["B_s0","J/psi(1S)", "p+", "p~-"], True) +#print(branches) + +#print(descriptor(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True)) diff --git a/Run3_b2psiX_pentaquark/tupling_maker.py b/Run3_b2psiX_pentaquark/tools/tupling_maker.py similarity index 54% rename from Run3_b2psiX_pentaquark/tupling_maker.py rename to Run3_b2psiX_pentaquark/tools/tupling_maker.py index 7da9acc157..840065c958 100644 --- a/Run3_b2psiX_pentaquark/tupling_maker.py +++ b/Run3_b2psiX_pentaquark/tools/tupling_maker.py @@ -1,53 +1,53 @@ -############################################################################### -# (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 +from DaVinci import make_config, Options +from DaVinci.algorithms import create_lines_filter + +from PyConf.reading import get_rec_summary, get_pvs +from PyConf.reading import get_particles + import FunTuple.functorcollections as FC +import Functors as F 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 FunTuple import FunTuple_Event +from FunTuple import FunTuple_Particles + + +#from PyConf.reading import (get_particles, get_charged_protoparticles, get_pvs, get_rec_summary, _get_unpacked) + +from Functors.math import in_range +from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleFilter + +from RecoConf.event_filters import require_pvs + +from Hlt2Conf.standard_particles import get_long_track_selector, standard_protoparticle_filter +from PyConf.Algorithms import FunctionalParticleMaker +from PyConf.reading import get_charged_protoparticles as _make_charged_protoparticles +from PyConf.reading import get_odin + +from GaudiKernel.SystemOfUnits import MeV, picosecond, mm, GeV _basic = "basic" _composite = "composite" _toplevel = "toplevel" + 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 top = _toplevel == ptype # the B - # First import everything that comes in functorcollections all_vars += FC.Kinematics() if basic: all_vars += FC.ParticleID(extra_info=True) - + if comp: all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)}) - + if comp: # all these require a vertex all_vars.update({"BPVCORRM": F.BPVCORRM(pvs)}) all_vars.update({"BPVCORRMERR": F.BPVCORRMERR(pvs)}) @@ -64,6 +64,9 @@ def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): all_vars.update({"BPVX": F.BPVX(pvs)}) all_vars.update({"BPVY": F.BPVY(pvs)}) all_vars.update({"BPVZ": F.BPVZ(pvs)}) + all_vars.update({"ALLPVX": F.ALLPVX(pvs)}) + all_vars.update({"ALLPVY": F.ALLPVY(pvs)}) + all_vars.update({"ALLPVZ": F.ALLPVZ(pvs)}) if comp: # all these require a vertex all_vars.update({"ALLPV_FD": F.ALLPV_FD(pvs)}) @@ -73,24 +76,24 @@ def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): 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 top: # apply this only to B + # all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)}) # example of CHILD + # all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)}) + # all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ}) - if top: # apply this only to B - all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)}) # example of CHILD - all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)}) - all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ}) - if comp: - all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)}) - all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)}) + #all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)}) + #all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)}) 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}) - + + # duplicated from FC all_vars.update({"ENERGY" : F.ENERGY}) all_vars.update({"ETA": F.ETA}) all_vars.update({"FOURMOMENTUM": F.FOURMOMENTUM}) all_vars.update({"ISBASIC": F.ISBASICPARTICLE}) @@ -118,13 +121,8 @@ def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): 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_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM}) - - 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+")}) @@ -132,19 +130,22 @@ def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): 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}) + #all_vars.update({"MINDOCA": F.MINSDOCA}) + #all_vars.update({"MINDOCACHI2": F.MINSDOCACHI2}) # the above in cut versions. - + + # duplicated from FC all_vars.update({ 'MC_MOTHER_ID' : F.VALUE_OR(0) @ mctruth( + # duplicated from FC F.MC_MOTHER(1, F.PARTICLE_ID))}) + 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}) @@ -156,46 +157,87 @@ def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): 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({"OBJECT_KEY": F.OBJECT_KEY}) + 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({"SDOCA": F.SDOCA(1, 2)}) - all_vars.update({"SDOCACHI2": F.SDOCACHI2(1, 2)}) + all_vars.update({"SDOCA12": F.SDOCA(1, 2)}) + all_vars.update({"SDOCA12_CHI2": F.SDOCACHI2(1, 2)}) if basic: all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE}) - + if comp: all_vars.update({"SUBCOMB12_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 2))}) all_vars.update({"SUMPT": F.SUM(F.PT)}) - + if top: + all_vars.update({"SDOCA13": F.SDOCA(1, 3)}) + all_vars.update({"SDOCA13_CHI2": F.SDOCACHI2(1, 3)}) + all_vars.update({"SDOCA23": F.SDOCA(2, 3)}) + all_vars.update({"SDOCA23_CHI2": F.SDOCACHI2(2, 3)}) + all_vars.update({"SUBCOMB13_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 3))}) + all_vars.update({"SUBCOMB23_MM": F.SUBCOMB(Functor=F.MASS, Indices=(2, 3))}) + 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 + print(f"### For {ptype} returning variables {all_vars.functor_dict.keys()}") + return all_vars -def event_variables(PVs, ODIN, decreports, lines): +def event_variables(PVs, ODIN, decreports, rec_sum, hlt1_lines, sprucing_lines): """ event variables """ - - evt_vars = FunctorCollection({}) + + ## Some empty summaries removed + evt_vars = FunctorCollection({ + "nPVs": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nPVs"), + "nTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTracks"), + "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"), + "nGhosts": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nGhosts"), + "nRich1Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich1Hits"), + "nRich2Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich2Hits"), + #"nVeloClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloClusters"), + "nVPClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVPClusters"), + #"nITClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nITClusters"), + #"nTTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTClusters"), + "nUTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUTClusters"), + #"nOTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nOTClusters"), + "nFTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nFTClusters"), + #"nSPDhits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nSPDhits"), + "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"), + #"nMuonCoordsS0": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS0"), + #"nMuonCoordsS1": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS1"), + #"nMuonCoordsS2": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS2"), + #"nMuonCoordsS3": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS3"), + #"nMuonCoordsS4": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS4"), + #"nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"), + "ALLPVX": F.ALLPVX(PVs), + "ALLPVY": F.ALLPVY(PVs), + "ALLPVZ": F.ALLPVZ(PVs), + }) evt_vars += FC.EventInfo() - - evt_vars += FC.SelectionInfo(selection_type="Hlt2", trigger_lines=lines) - if decreports: + evt_vars += FC.SelectionInfo( selection_type="Hlt1", trigger_lines=hlt1_lines) + evt_vars += FC.SelectionInfo( selection_type="Hlt2", trigger_lines=sprucing_lines) + # duplicated from FC if ODIN: + # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_ID' : F.BUNCHCROSSING_ID(ODIN)}) + # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_TYPE' : F.BUNCHCROSSING_TYPE(ODIN)}) + + if decreports: evt_vars.update( { "DECISIONS": F.DECISIONS( @@ -210,122 +252,47 @@ def event_variables(PVs, ODIN, decreports, lines): ) } ) - + if ODIN: evt_vars.update({"EVENTTYPE": F.EVENTTYPE(ODIN)}) + # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) + # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) + evt_vars.update({"PV_SIZE": F.SIZE(PVs)}) - + # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) + # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) + if decreports: evt_vars.update({"TCK": F.TCK(decreports)}) - + print(f"### For event returning variables {evt_vars.functor_dict.keys()}") return evt_vars +def candidate_variables(pvs, mother, daughters): + variables_B = {mother: all_variables(pvs, None, _toplevel)} + for daughter in daughters: + if daughter.startswith("P") or daughter.startswith("K") or daughter.startswith("Pi") or daughter.startswith("e") or daughter.startswith("mu"): + variables_B.update( {daughter: all_variables(pvs, None, _basic)} ) + else: + variables_B.update( {daughter: all_variables(pvs, None, _composite)} ) + return variables_B -def template(decay_descriptor, line_name, isturbo, Hlt2_decisions): - - evtpath_prefix = "/Event/Spruce/" - if isturbo: - evtpath_prefix = "/Event/HLT2/" - - QQbar2mumu_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, - }) - - composite_variables += HltTisTos( selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=QQbar2mumu_data) - if not isturbo: - composite_variables += HltTisTos( selection_type="Hlt2", trigger_lines=Hlt2_decisions, data=QQbar2mumu_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 - ) - - variables = { - "QQbar": composite_variables + all_variables(pvs, None, _composite), - "mup": daughter_variables + all_variables(pvs, None, _basic), - "mum": daughter_variables + all_variables(pvs, None, _basic), - } - - #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=QQbar2mumu_data) - - return my_tuple - -def line_prefilter(line_name): - return create_lines_filter(name=f"HLT_PASS{line_name}", lines=[line_name]) +import re +def convert_cut(string_cut): + cuts = string_cut.split("&") + paras = ["BPV", "PID_", "MASS", "CHARGE", "CHI2DOF", "END", "IS_ID", "ABS_", "MAX", "SUM", "GHOSTPROB", "CHILD"] + values = [] + for cut in cuts: + value = cut + for para in paras: + if para in cut: + value = value.replace(para, f"F.{para}") + value = re.sub(r"\bPT\b", "F.PT", value) + value = re.sub(r"\bP\b", "F.P", value) + value = re.sub(r"\bCHI2\b", "F.CHI2", value) + values.append(value) + functor_cut = ",".join(values) + return eval(f"F.require_all({functor_cut})") + #return f"F.require_all({functor_cut})" -- GitLab From 053861a5916456867c482299132cc1ac9527f10d Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Tue, 25 Jun 2024 18:18:54 +0200 Subject: [PATCH 3/8] TISTOS and DTF implemented --- Run3_b2psiX_pentaquark/B2JpsiKpi.py | 5 - Run3_b2psiX_pentaquark/B2Jpsippbar.py | 6 - Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py | 6 - Run3_b2psiX_pentaquark/Lb2JpsipK.py | 6 - Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py | 6 - Run3_b2psiX_pentaquark/dv_data.py | 22 +++ Run3_b2psiX_pentaquark/info.yaml | 2 +- Run3_b2psiX_pentaquark/template.py | 24 +++- .../tools/descriptor_writer.py | 92 ++++++++----- Run3_b2psiX_pentaquark/tools/tupling_maker.py | 126 +++++++++++++++--- 10 files changed, 205 insertions(+), 90 deletions(-) create mode 100644 Run3_b2psiX_pentaquark/dv_data.py diff --git a/Run3_b2psiX_pentaquark/B2JpsiKpi.py b/Run3_b2psiX_pentaquark/B2JpsiKpi.py index 8fe4bf611a..8b13789179 100644 --- a/Run3_b2psiX_pentaquark/B2JpsiKpi.py +++ b/Run3_b2psiX_pentaquark/B2JpsiKpi.py @@ -1,6 +1 @@ -from .template import * - -def main(options: Options): - algs = template(["B0", "J/psi(1S)", "K+", "pi-"], True, "B2JpsiKpi") - return make_config( options, algs ) diff --git a/Run3_b2psiX_pentaquark/B2Jpsippbar.py b/Run3_b2psiX_pentaquark/B2Jpsippbar.py index cd125179c9..e69de29bb2 100644 --- a/Run3_b2psiX_pentaquark/B2Jpsippbar.py +++ b/Run3_b2psiX_pentaquark/B2Jpsippbar.py @@ -1,6 +0,0 @@ -from .template import * - -def main(options: Options): - algs = template(["B_s0", "J/psi(1S)", "p+", "p~-"], False, "B2Jpsippbar") - return make_config( options, algs ) - diff --git a/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py b/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py index a694aff783..e69de29bb2 100644 --- a/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py +++ b/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py @@ -1,6 +0,0 @@ -from .template import * - -def main(options: Options): - algs = template(["B+", "J/psi(1S)", "p+", "Lambda~0"], True, "Bp2JpsipLambdabar") - return make_config( options, algs ) - diff --git a/Run3_b2psiX_pentaquark/Lb2JpsipK.py b/Run3_b2psiX_pentaquark/Lb2JpsipK.py index 208ffa2f16..e69de29bb2 100644 --- a/Run3_b2psiX_pentaquark/Lb2JpsipK.py +++ b/Run3_b2psiX_pentaquark/Lb2JpsipK.py @@ -1,6 +0,0 @@ -from .template import * - -def main(options: Options): - algs = template(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True, "Lb2JpsipK") - return make_config( options, algs ) - diff --git a/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py b/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py index 25f9e26e8c..e69de29bb2 100644 --- a/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py +++ b/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py @@ -1,6 +0,0 @@ -from .template import * - -def main(options: Options): - algs = template(["Xi_b-", "J/psi(1S)", "Lambda0", "K-"], True, "Xib2JpsiLambdaK") - return make_config( options, algs ) - diff --git a/Run3_b2psiX_pentaquark/dv_data.py b/Run3_b2psiX_pentaquark/dv_data.py new file mode 100644 index 0000000000..c2b84fc545 --- /dev/null +++ b/Run3_b2psiX_pentaquark/dv_data.py @@ -0,0 +1,22 @@ +from .template import * + +def Lb2JpsipK(options: Options): + algs = template(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True, "Lb2JpsipK") + return make_config( options, algs ) + +def B2JpsiKpi(options: Options): + algs = template(["B0", "J/psi(1S)", "K+", "pi-"], True, "B2JpsiKpi") + return make_config( options, algs ) + +def Xib2JpsiLambdaK(options: Options): + algs = template(["Xi_b-", "J/psi(1S)", "Lambda0", "K-"], True, "Xib2JpsiLambdaK") + return make_config( options, algs ) + +def Bp2JpsipLambdabar(options: Options): + algs = template(["B+", "J/psi(1S)", "p+", "Lambda~0"], True, "Bp2JpsipLambdabar") + return make_config( options, algs ) + +def B2Jpsippbar(options: Options): + algs = template(["B_s0", "J/psi(1S)", "p+", "p~-"], False, "B2Jpsippbar") + return make_config( options, algs ) + diff --git a/Run3_b2psiX_pentaquark/info.yaml b/Run3_b2psiX_pentaquark/info.yaml index b3d9352594..e89c53427e 100644 --- a/Run3_b2psiX_pentaquark/info.yaml +++ b/Run3_b2psiX_pentaquark/info.yaml @@ -34,7 +34,7 @@ data_{{decay}}_{{wg}}_{{process}}_{{data}}_{{Velo}}_{{polarity}}: keep_running: False n_test_lfns: 1 options: - entrypoint: Run3_b2psiX_pentaquark.{{decay}}:main + entrypoint: Run3_b2psiX_pentaquark.dv_data:{{decay}} extra_options: input_type: ROOT input_process: "{{process}}" diff --git a/Run3_b2psiX_pentaquark/template.py b/Run3_b2psiX_pentaquark/template.py index 8bd521e36a..b55fa24e69 100644 --- a/Run3_b2psiX_pentaquark/template.py +++ b/Run3_b2psiX_pentaquark/template.py @@ -42,9 +42,9 @@ def template(particles, cc, directory): Inputs = [input_dict[particle] for particle in particles[1:]], DecayDescriptor = descriptor(particles, cc), name = "JpsiToMuMu_Detached_line_validation", - CombinationCut = convert_cut("in_range(5000, MASS, 7000) & (CHILD(2, PT)+CHILD(3, PT)>900*MeV)"), + CombinationCut = convert_cut("in_range(4800, MASS, 7000) & (CHILD(2, PT)+CHILD(3, PT)>900*MeV)"), #CombinationCut = convert_cut("in_range(5200, MASS, 7000)"), - CompositeCut = convert_cut("in_range(5000, MASS, 7000) & CHI2DOF<20 & BPVLTIME(get_pvs())>0.2*picosecond & BPVVDZ(get_pvs())>0.*mm") + CompositeCut = convert_cut("in_range(4800, MASS, 7000) & CHI2DOF<20 & BPVLTIME(get_pvs())>0.2*picosecond & BPVVDZ(get_pvs())>0.*mm") ) #FunTuple: define branches. @@ -64,13 +64,23 @@ def template(particles, cc, directory): 'Hlt1TrackMuonMVADecision'] - mother = default_names(particles)[0] - daughters = default_names(particles)[1:] - line_prefilter = create_lines_filter(name=f"PreFilter_{sprucing_line}", lines=[sprucing_line]) evt_vars = event_variables(v2_pvs, odin, decreports, rec_sum, hlt1_trigger_lines, [sprucing_line]) - candidate_vars = candidate_variables(v2_pvs, mother, daughters) - print(candidate_vars) + candidate_vars = candidate_variables(v2_pvs, particles) + tistos_vars = tistos_variables(hlt1_trigger_lines, [], Jpsi, False) + + dtf_vars1 = make_dtf_variables(v2_pvs, B2JpsiX, particles, False, []) + dtf_vars2 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, + [particle for particle in particles if particle_df["type"][particle] != "basic" ]) + + for particle in particles: + if particle_df["type"][particle] != "basic": + candidate_vars[particle_df["abbr"][particle]] += tistos_vars + + for key in candidate_vars.keys(): + candidate_vars[key] += dtf_vars1[key] + candidate_vars[key] += dtf_vars2[key] + B2JpsiX_branches = default_branches(particles, cc) # define tupling algorithms diff --git a/Run3_b2psiX_pentaquark/tools/descriptor_writer.py b/Run3_b2psiX_pentaquark/tools/descriptor_writer.py index 71882db092..770729694b 100644 --- a/Run3_b2psiX_pentaquark/tools/descriptor_writer.py +++ b/Run3_b2psiX_pentaquark/tools/descriptor_writer.py @@ -1,3 +1,29 @@ +import pandas as pd +import numpy as np +particle_dict = {"Lambda_b0": {"abbr": "Lb", "type": "toplevel", "daughters":[]}, + "Xi_b-": {"abbr": "Xibm", "type": "toplevel", "daughters":[]}, + "Xi_b0": {"abbr": "Xib0", "type": "toplevel", "daughters":[]}, + "B0": {"abbr": "B0", "type": "toplevel", "daughters":[]}, + "B+": {"abbr": "Bp", "type": "toplevel", "daughters":[]}, + "B-": {"abbr": "Bm", "type": "toplevel", "daughters":[]}, + "B_s0": {"abbr": "Bs", "type": "toplevel", "daughters":[]}, + "J/psi(1S)": {"abbr": "Jpsi", "type": "composite", "daughters": ["mu+", "mu-"]}, + "psi(2S)": {"abbr": "psi2S", "type": "composite", "daughters": ["mu+", "mu-"]}, + "Lambda0": {"abbr": "Lambda", "type": "composite", "daughters": ["p+", "pi-"]}, + "Lambda~0": {"abbr": "Lambda", "type": "composite", "daughters": ["p~-", "pi+"]}, + "mu+": {"abbr": "mup", "type": "basic", "daughters":[]}, + "mu-": {"abbr": "mum", "type": "basic", "daughters":[]}, + "e+": {"abbr": "ep", "type": "basic", "daughters":[]}, + "e-": {"abbr": "em", "type": "basic", "daughters":[]}, + "pi+": {"abbr": "Pip", "type": "basic", "daughters":[]}, + "pi-": {"abbr": "Pim", "type": "basic", "daughters":[]}, + "K+": {"abbr": "Kp", "type": "basic", "daughters":[]}, + "K-": {"abbr": "Km", "type": "basic", "daughters":[]}, + "p+": {"abbr": "Pp", "type": "basic", "daughters":[]}, + "p~-": {"abbr": "Pm", "type": "basic", "daughters":[]}, + } +particle_df = pd.DataFrame(particle_dict).T + def descriptor(particles, cc=False): decay_descriptor = f"{particles[0]} ->" for particle in particles[1:]: @@ -18,14 +44,18 @@ def decay_branches(mother, daughters, decay_descriptor): if "cc" in decay_descriptor[-5:]: branch_descriptor = decay_descriptor[:-2] + "CC" else: branch_descriptor = decay_descriptor - if "J/psi(1S)" in decay_descriptor: - branch_descriptor = branch_descriptor.replace("J/psi(1S)", "(J/psi(1S) -> mu+ mu-)") - if "psi(2S)" in decay_descriptor: - branch_descriptor = branch_descriptor.replace("psi(2S)", "(psi(2S) -> mu+ mu-)") - if "Lambda0" in decay_descriptor: - branch_descriptor = branch_descriptor.replace("Lambda0", "(Lambda0 -> p+ pi-)") - if "Lambda~0" in decay_descriptor: - branch_descriptor = branch_descriptor.replace("Lambda~0", "(Lambda~0 -> p~- pi+)") + #if "J/psi(1S)" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("J/psi(1S)", "(J/psi(1S) -> mu+ mu-)") + #if "psi(2S)" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("psi(2S)", "(psi(2S) -> mu+ mu-)") + #if "Lambda0" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("Lambda0", "(Lambda0 -> p+ pi-)") + #if "Lambda~0" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("Lambda~0", "(Lambda~0 -> p~- pi+)") + for comp_par in particle_df.query("type=='composite'").index: + if comp_par in decay_descriptor: + #branch_descriptor = branch_descriptor.replace(comp_par, comp_par + "->" + " ".join(particle_df["daughters"][comp_par])) + branch_descriptor = branch_descriptor.replace(comp_par, f'({comp_par} -> {" ".join(particle_df["daughters"][comp_par])})') branches = {mother: branch_descriptor} @@ -80,43 +110,37 @@ def decay_branches(mother, daughters, decay_descriptor): em_pos = true_pos + len("e-") return branches +def all_particles(particles): + all_pars = [] + for particle in particles: + all_pars += ( [ particle ] + particle_df["daughters"][particle]) + return all_pars + +#print(all_particles(["B_s0","J/psi(1S)", "p+", "p~-"])) + def default_names(particles): - name_dict = {"Lambda_b0": "Lb", - "Xi_b-": "Xib", - "Xi_b0": "Xib", - "B0": "B0", - "B+": "Bp", - "B-": "Bm", - "B_s0": "Bs", - "J/psi(1S)": "Jpsi", - "psi(2S)": "psi2S", - "Lambda0": "Lambda", "Lambda~0": "Lambda", - "mu+": "mup", "mu-": "mum", - "e+": "ep", "e-": "em", - "pi+": "Pip", "pi-": "Pim", - "K+": "Kp", "K-": "Km", - "p+": "Pp", "p~-": "Pm", - } names = [] for particle in particles: - names.append( name_dict[ particle ] ) - if particle == "J/psi(1S)" or particle == "psi(2S)": - names += ["mup_psi", "mum_psi"] - elif particle == "Lambda0": - names += ["Pp_Lambda", "Pim_Lambda"] - elif particle == "Lambda~0": - names += ["Pm_Lambda", "Pip_Lambda"] + abbr = particle_df["abbr"][ particle ] + names.append( abbr ) + names += [f"{daughter_abbr}_{abbr}" for daughter_abbr in particle_df["abbr"][particle_df["daughters"][particle]]] + #if particle == "J/psi(1S)" or particle == "psi(2S)": + # names += ["mup_psi", "mum_psi"] + #elif particle == "Lambda0": + # names += ["Pp_Lambda", "Pim_Lambda"] + #elif particle == "Lambda~0": + # names += ["Pm_Lambda", "Pip_Lambda"] return names def default_branches(particles, cc=False): names = default_names(particles) return decay_branches(names[0], names[1:], descriptor(particles, cc)) -#branches = decay_branches("Bs", ["Jpsi", "Pp", "Pm", "mup", "mum"], "[B_s0 -> J/psi(1S) p+ p~-]cc") +#branches = default_branches( ["B+","J/psi(1S)", "p+", "Lambda~0"], True) #print(branches) -#branches = default_name( ["B_s0","J/psi(1S)", "p+", "p~-"]) -#branches = default_branches( ["B_s0","J/psi(1S)", "p+", "p~-"], True) +#branches = decay_branches("Bs", ["Jpsi", "Pp", "Pm", "mup", "mum"], "[B_s0 -> J/psi(1S) p+ p~-]cc") #print(branches) +#branches = default_names( ["B_s0","J/psi(1S)", "p+", "p~-"]) #print(descriptor(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True)) diff --git a/Run3_b2psiX_pentaquark/tools/tupling_maker.py b/Run3_b2psiX_pentaquark/tools/tupling_maker.py index 840065c958..dc81d630a2 100644 --- a/Run3_b2psiX_pentaquark/tools/tupling_maker.py +++ b/Run3_b2psiX_pentaquark/tools/tupling_maker.py @@ -10,6 +10,7 @@ from FunTuple import FunctorCollection from FunTuple import FunTuple_Event from FunTuple import FunTuple_Particles +from .descriptor_writer import * #from PyConf.reading import (get_particles, get_charged_protoparticles, get_pvs, get_rec_summary, _get_unpacked) @@ -25,12 +26,12 @@ from PyConf.reading import get_charged_protoparticles as _make_charged_protopart from PyConf.reading import get_odin from GaudiKernel.SystemOfUnits import MeV, picosecond, mm, GeV +from DecayTreeFitter import DecayTreeFitter _basic = "basic" _composite = "composite" _toplevel = "toplevel" - def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): if ptype not in [_basic, _composite]: @@ -191,6 +192,13 @@ def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): print(f"### For {ptype} returning variables {all_vars.functor_dict.keys()}") return all_vars +def tistos_variables(Hlt1_decisions, Hlt2_decisions, data, isturbo): + tistos_vars = FunctorCollection({}) + tistos_vars += FC.HltTisTos( selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=data) + if not isturbo: + tistos_vars += FC.HltTisTos( selection_type="Hlt2", trigger_lines=Hlt2_decisions, data=data) + return tistos_vars + def event_variables(PVs, ODIN, decreports, rec_sum, hlt1_lines, sprucing_lines): """ event variables @@ -239,19 +247,19 @@ def event_variables(PVs, ODIN, decreports, rec_sum, hlt1_lines, sprucing_lines): if decreports: evt_vars.update( - { - "DECISIONS": F.DECISIONS( - Lines=[bd2dsk_line + "Decision"], DecReports=decreports + { + "DECISIONS": F.DECISIONS( + Lines=[bd2dsk_line + "Decision"], DecReports=decreports + ) + } ) - } - ) evt_vars.update( - { - "DECREPORTS_FILTER": F.DECREPORTS_FILTER( - Lines=[bd2dsk_line + "Decision"], DecReports=decreports + { + "DECREPORTS_FILTER": F.DECREPORTS_FILTER( + Lines=[bd2dsk_line + "Decision"], DecReports=decreports + ) + } ) - } - ) if ODIN: evt_vars.update({"EVENTTYPE": F.EVENTTYPE(ODIN)}) @@ -269,15 +277,95 @@ def event_variables(PVs, ODIN, decreports, rec_sum, hlt1_lines, sprucing_lines): print(f"### For event returning variables {evt_vars.functor_dict.keys()}") return evt_vars -def candidate_variables(pvs, mother, daughters): - variables_B = {mother: all_variables(pvs, None, _toplevel)} - for daughter in daughters: - if daughter.startswith("P") or daughter.startswith("K") or daughter.startswith("Pi") or daughter.startswith("e") or daughter.startswith("mu"): - variables_B.update( {daughter: all_variables(pvs, None, _basic)} ) - else: - variables_B.update( {daughter: all_variables(pvs, None, _composite)} ) +def candidate_variables(pvs, particles): + abbrs = default_names(particles) + names = all_particles(particles) + variables_B = {abbr: all_variables(pvs, None, particle_df["type"][name]) for abbr, name in zip(abbrs, names)} return variables_B +from DecayTreeFitter import DecayTreeFitter +def make_dtf_variables(pvs, data, particles, pv_constraint=False, mass_constraints=[]): + + abbrs = default_names(particles) + names = all_particles(particles) + + if pv_constraint: dtf_name = "DTF_PV_" + else: dtf_name = "DTF_" + dtf_name += "".join(f"{par}_" for par in particle_df["abbr"][mass_constraints]) + + DTF = DecayTreeFitter( + name = f"{dtf_name}_DecayTreeFitter", + input_particles = data, + input_pvs = (pv_constraint and pvs), + mass_constraints = mass_constraints, + ) + + dtf_dict = {} + + shared_variables = FunctorCollection( + { "ETA": F.ETA, + "PHI": F.PHI, + "BPVIPCHI2": F.BPVIPCHI2(pvs), + "BPVIP": F.BPVIP(pvs), + "BPVX": F.BPVX(pvs), + "BPVY": F.BPVY(pvs), + "BPVZ": F.BPVZ(pvs), + } + ) + FC.Kinematics() + + dtf_quality_variables = FunctorCollection( { + dtf_name+"_DTFCHI2": DTF.CHI2, + dtf_name+"_DTFNDOF": DTF.NDOF, + dtf_name+"_CTAU": DTF.CTAU, + dtf_name+"_CTAUERR": DTF.CTAUERR, + dtf_name+"_MERR": DTF.MASSERR, + } + ) + + #make branches + for abbr, name in zip(abbrs, names): + is_basic = particle_df["type"][name] + if is_basic: + orig_variables = shared_variables + FunctorCollection( + { "TX" : F.TX, + "TY" : F.TY, + "MINIPCHI2" : F.MINIPCHI2(pvs), + "MINIP" : F.MINIP(pvs), + "KEY" : F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.TRACK, + "TRGHOSTPROB": F.GHOSTPROB, + "TRACKPT": F.TRACK_PT, + "TRACKHISTORY": F.VALUE_OR(-1) @ F.TRACKHISTORY @ F.TRACK, + "QOVERP": F.QOVERP @ F.TRACK, + "TRCHI2DOF": F.CHI2DOF @ F.TRACK, + "NDOF": F.VALUE_OR(-1) @ F.NDOF @ F.TRACK, + } + ) + else: + orig_variables = shared_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), + "CHI2DOF": F.CHI2DOF, #CHI2VXNDOF + "BPVFDCHI2": F.BPVFDCHI2(pvs), + "BPVFD": F.BPVFD(pvs), + "BPVVDRHO": F.BPVVDRHO(pvs), + "BPVVDZ": F.BPVVDZ(pvs), + "BPVLTIME": F.BPVLTIME(pvs), + "END_VX": F.END_VX, #END_ + "END_VY": F.END_VY, + "END_VZ": F.END_VZ, + } + ) + orig_variables += dtf_quality_variables + + dtf_variables = FunctorCollection({ dtf_name + expr: DTF(func) for expr, func in orig_variables.get_thor_functors().items() }) + dtf_dict.update( {abbr: dtf_variables} ) + + return dtf_dict + import re def convert_cut(string_cut): cuts = string_cut.split("&") @@ -294,5 +382,5 @@ def convert_cut(string_cut): values.append(value) functor_cut = ",".join(values) return eval(f"F.require_all({functor_cut})") - #return f"F.require_all({functor_cut})" +#return f"F.require_all({functor_cut})" -- GitLab From b2c03ab763074b36a3b961d85e9400d06ef8e774 Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Tue, 25 Jun 2024 23:16:43 +0200 Subject: [PATCH 4/8] delete empty files --- Run3_b2psiX_pentaquark/B2JpsiKpi.py | 1 - Run3_b2psiX_pentaquark/B2Jpsippbar.py | 0 Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py | 0 Run3_b2psiX_pentaquark/Lb2JpsipK.py | 0 Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py | 0 Run3_b2psiX_pentaquark/template.py | 7 ++++--- Run3_b2psiX_pentaquark/tools/tupling_maker.py | 2 +- 7 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 Run3_b2psiX_pentaquark/B2JpsiKpi.py delete mode 100644 Run3_b2psiX_pentaquark/B2Jpsippbar.py delete mode 100644 Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py delete mode 100644 Run3_b2psiX_pentaquark/Lb2JpsipK.py delete mode 100644 Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py diff --git a/Run3_b2psiX_pentaquark/B2JpsiKpi.py b/Run3_b2psiX_pentaquark/B2JpsiKpi.py deleted file mode 100644 index 8b13789179..0000000000 --- a/Run3_b2psiX_pentaquark/B2JpsiKpi.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Run3_b2psiX_pentaquark/B2Jpsippbar.py b/Run3_b2psiX_pentaquark/B2Jpsippbar.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py b/Run3_b2psiX_pentaquark/Bp2JpsipLambdabar.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Run3_b2psiX_pentaquark/Lb2JpsipK.py b/Run3_b2psiX_pentaquark/Lb2JpsipK.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py b/Run3_b2psiX_pentaquark/Xib2JpsiLambdaK.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Run3_b2psiX_pentaquark/template.py b/Run3_b2psiX_pentaquark/template.py index b55fa24e69..68d949d549 100644 --- a/Run3_b2psiX_pentaquark/template.py +++ b/Run3_b2psiX_pentaquark/template.py @@ -69,9 +69,10 @@ def template(particles, cc, directory): candidate_vars = candidate_variables(v2_pvs, particles) tistos_vars = tistos_variables(hlt1_trigger_lines, [], Jpsi, False) - dtf_vars1 = make_dtf_variables(v2_pvs, B2JpsiX, particles, False, []) - dtf_vars2 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, - [particle for particle in particles if particle_df["type"][particle] != "basic" ]) + composite_particles = [ particle for particle in particles if particle_df["type"][particle] != "basic" ] + print(composite_particles) + dtf_vars1 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, composite_particles) + dtf_vars2 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, composite_particles[1:]) for particle in particles: if particle_df["type"][particle] != "basic": diff --git a/Run3_b2psiX_pentaquark/tools/tupling_maker.py b/Run3_b2psiX_pentaquark/tools/tupling_maker.py index dc81d630a2..c9feb96573 100644 --- a/Run3_b2psiX_pentaquark/tools/tupling_maker.py +++ b/Run3_b2psiX_pentaquark/tools/tupling_maker.py @@ -294,7 +294,7 @@ def make_dtf_variables(pvs, data, particles, pv_constraint=False, mass_constrain dtf_name += "".join(f"{par}_" for par in particle_df["abbr"][mass_constraints]) DTF = DecayTreeFitter( - name = f"{dtf_name}_DecayTreeFitter", + name = f"{dtf_name}DecayTreeFitter", input_particles = data, input_pvs = (pv_constraint and pvs), mass_constraints = mass_constraints, -- GitLab From c430cb90d500a51d4891e506b3e4407bc2300568 Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Fri, 28 Jun 2024 12:43:15 +0200 Subject: [PATCH 5/8] add B->Jpsi phi K and Lb->Jpsi p pi --- Run3_b2psiX_pentaquark/dv_data.py | 8 ++++++++ Run3_b2psiX_pentaquark/info.yaml | 4 ++++ Run3_b2psiX_pentaquark/template.py | 12 ++++++------ .../tools/descriptor_writer.py | 16 ++++++++-------- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Run3_b2psiX_pentaquark/dv_data.py b/Run3_b2psiX_pentaquark/dv_data.py index c2b84fc545..edca5666d8 100644 --- a/Run3_b2psiX_pentaquark/dv_data.py +++ b/Run3_b2psiX_pentaquark/dv_data.py @@ -4,6 +4,10 @@ def Lb2JpsipK(options: Options): algs = template(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True, "Lb2JpsipK") return make_config( options, algs ) +def Lb2Jpsippi(options: Options): + algs = template(["Lambda_b0", "J/psi(1S)", "p+", "pi-"], True, "Lb2Jpsippi") + return make_config( options, algs ) + def B2JpsiKpi(options: Options): algs = template(["B0", "J/psi(1S)", "K+", "pi-"], True, "B2JpsiKpi") return make_config( options, algs ) @@ -16,6 +20,10 @@ def Bp2JpsipLambdabar(options: Options): algs = template(["B+", "J/psi(1S)", "p+", "Lambda~0"], True, "Bp2JpsipLambdabar") return make_config( options, algs ) +def Bp2JpsiphiK(options: Options): + algs = template(["B+", "J/psi(1S)", "phi(1020)", "K+"], True, "Bp2JpsiphiK") + return make_config( options, algs ) + def B2Jpsippbar(options: Options): algs = template(["B_s0", "J/psi(1S)", "p+", "p~-"], False, "B2Jpsippbar") return make_config( options, algs ) diff --git a/Run3_b2psiX_pentaquark/info.yaml b/Run3_b2psiX_pentaquark/info.yaml index e89c53427e..cbf93eb226 100644 --- a/Run3_b2psiX_pentaquark/info.yaml +++ b/Run3_b2psiX_pentaquark/info.yaml @@ -9,12 +9,16 @@ defaults: {%- set datasets = [ ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2JpsiKpi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2JpsiKpi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2Jpsippbar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2Jpsippbar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ]%} diff --git a/Run3_b2psiX_pentaquark/template.py b/Run3_b2psiX_pentaquark/template.py index 68d949d549..48c9254f70 100644 --- a/Run3_b2psiX_pentaquark/template.py +++ b/Run3_b2psiX_pentaquark/template.py @@ -1,7 +1,7 @@ from .tools.tupling_maker import * from .tools.descriptor_writer import * -from Hlt2Conf.standard_particles import make_long_kaons, make_long_protons, make_long_pions, make_LambdaLL, make_long_muons +from Hlt2Conf.standard_particles import make_long_kaons, make_long_protons, make_long_pions, make_LambdaLL, make_long_muons, make_phi2kk def template(particles, cc, directory): @@ -18,17 +18,18 @@ def template(particles, cc, directory): long_kaons = make_long_kaons() long_protons = make_long_protons() - DaughterCutp = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (P>10*GeV) & (PID_P>5) & (PID_P-PID_K>5) & (GHOSTPROB<0.5)" + DaughterCutp = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (P>10*GeV) & (PID_P>0) & (PID_P-PID_K>0) & (GHOSTPROB<0.5)" DaughterCutpi = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K<5) & (GHOSTPROB<0.5)" - DaughterCutK = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K>5) & (GHOSTPROB<0.5)" + DaughterCutK = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K>0) & (GHOSTPROB<0.5)" protons = ParticleFilter( long_protons, Cut = F.FILTER( convert_cut(DaughterCutp) ) ) kaons = ParticleFilter( long_kaons, Cut = F.FILTER( convert_cut(DaughterCutK) ) ) pions = ParticleFilter( long_pions, Cut = F.FILTER( convert_cut(DaughterCutpi) ) ) muons = make_long_muons() Lambda = make_LambdaLL() + phi = make_phi2kk(kaon_pidk_min=0) - input_dict = {"J/psi(1S)": Jpsi, + input_dict = {"J/psi(1S)": Jpsi, "phi(1020)": phi, "Lambda0":Lambda, "Lambda~0":Lambda, "pi+": pions, "pi-": pions, "K+": kaons, "K-": kaons, @@ -69,8 +70,7 @@ def template(particles, cc, directory): candidate_vars = candidate_variables(v2_pvs, particles) tistos_vars = tistos_variables(hlt1_trigger_lines, [], Jpsi, False) - composite_particles = [ particle for particle in particles if particle_df["type"][particle] != "basic" ] - print(composite_particles) + composite_particles = [ particle for particle in particles if (particle_df["type"][particle] != "basic") and (particle != "phi(1020)") ] dtf_vars1 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, composite_particles) dtf_vars2 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, composite_particles[1:]) diff --git a/Run3_b2psiX_pentaquark/tools/descriptor_writer.py b/Run3_b2psiX_pentaquark/tools/descriptor_writer.py index 770729694b..54444acc7a 100644 --- a/Run3_b2psiX_pentaquark/tools/descriptor_writer.py +++ b/Run3_b2psiX_pentaquark/tools/descriptor_writer.py @@ -9,6 +9,7 @@ particle_dict = {"Lambda_b0": {"abbr": "Lb", "type": "toplevel", "daughters":[]} "B_s0": {"abbr": "Bs", "type": "toplevel", "daughters":[]}, "J/psi(1S)": {"abbr": "Jpsi", "type": "composite", "daughters": ["mu+", "mu-"]}, "psi(2S)": {"abbr": "psi2S", "type": "composite", "daughters": ["mu+", "mu-"]}, + "phi(1020)": {"abbr": "phi", "type": "composite", "daughters": ["K+", "K-"]}, "Lambda0": {"abbr": "Lambda", "type": "composite", "daughters": ["p+", "pi-"]}, "Lambda~0": {"abbr": "Lambda", "type": "composite", "daughters": ["p~-", "pi+"]}, "mu+": {"abbr": "mup", "type": "basic", "daughters":[]}, @@ -33,6 +34,7 @@ def descriptor(particles, cc=False): def decay_branches(mother, daughters, decay_descriptor): psi_pos = 0 + phi_pos = 0 Lambda_pos = 0 Pm_pos = Pp_pos = 0 Km_pos = Kp_pos = 0 @@ -64,6 +66,10 @@ def decay_branches(mother, daughters, decay_descriptor): true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("psi", psi_pos)) branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) psi_pos = branch_descriptor.find("psi", psi_pos) + len("psi(nS)") + if "phi" in daughter: + true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("phi", phi_pos)) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + phi_pos = branch_descriptor.find("phi", phi_pos) + len("phi(1020)") if "Lambda" in daughter: true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("Lambda", Lambda_pos)) branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) @@ -124,20 +130,14 @@ def default_names(particles): abbr = particle_df["abbr"][ particle ] names.append( abbr ) names += [f"{daughter_abbr}_{abbr}" for daughter_abbr in particle_df["abbr"][particle_df["daughters"][particle]]] - #if particle == "J/psi(1S)" or particle == "psi(2S)": - # names += ["mup_psi", "mum_psi"] - #elif particle == "Lambda0": - # names += ["Pp_Lambda", "Pim_Lambda"] - #elif particle == "Lambda~0": - # names += ["Pm_Lambda", "Pip_Lambda"] return names def default_branches(particles, cc=False): names = default_names(particles) return decay_branches(names[0], names[1:], descriptor(particles, cc)) -#branches = default_branches( ["B+","J/psi(1S)", "p+", "Lambda~0"], True) -#print(branches) +branches = default_branches( ["B+","J/psi(1S)", "phi(1020)", "K+"], True) +print(branches) #branches = decay_branches("Bs", ["Jpsi", "Pp", "Pm", "mup", "mum"], "[B_s0 -> J/psi(1S) p+ p~-]cc") #print(branches) -- GitLab From 0e663b76082ac47e57981fcd002dcc0a5cc9f351 Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Tue, 2 Jul 2024 16:41:05 +0200 Subject: [PATCH 6/8] Include UT data --- Run3_b2psiX_pentaquark/info.yaml | 34 +++++++++++++++--------------- Run3_b2psiX_pentaquark/template.py | 6 +++--- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Run3_b2psiX_pentaquark/info.yaml b/Run3_b2psiX_pentaquark/info.yaml index cbf93eb226..cae839a2dc 100644 --- a/Run3_b2psiX_pentaquark/info.yaml +++ b/Run3_b2psiX_pentaquark/info.yaml @@ -7,20 +7,20 @@ defaults: # data configuration {%- set datasets = [ - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2JpsipK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2JpsiKpi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2JpsiKpi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2Jpsippbar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'B2Jpsippbar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - ('Collision24', 'Sprucing24c1/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2JpsipK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2JpsipK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2JpsiKpi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2JpsiKpi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2Jpsippbar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2Jpsippbar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ]%} @@ -29,13 +29,13 @@ defaults: {%- for data, Type, wg, decay, polarity, Velo, process, stream in datasets %} data_{{decay}}_{{wg}}_{{process}}_{{data}}_{{Velo}}_{{polarity}}: - application: "DaVinci/v64r5" + application: "DaVinci/v64r7" input: - bk_query: "/LHCb/{{data}}/Beam6800GeV-{{Velo}}-{{polarity}}-Excl-UT/Real Data/{{Type}}/{{wg}}.DST" + bk_query: "/LHCb/{{data}}/Beam6800GeV-{{Velo}}-{{polarity}}/Real Data/{{Type}}/{{wg}}.DST" dq_flags: - OK - UNCHECKED - keep_running: False + keep_running: True n_test_lfns: 1 options: entrypoint: Run3_b2psiX_pentaquark.dv_data:{{decay}} diff --git a/Run3_b2psiX_pentaquark/template.py b/Run3_b2psiX_pentaquark/template.py index 48c9254f70..b45eab1efc 100644 --- a/Run3_b2psiX_pentaquark/template.py +++ b/Run3_b2psiX_pentaquark/template.py @@ -18,16 +18,16 @@ def template(particles, cc, directory): long_kaons = make_long_kaons() long_protons = make_long_protons() - DaughterCutp = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (P>10*GeV) & (PID_P>0) & (PID_P-PID_K>0) & (GHOSTPROB<0.5)" + DaughterCutp = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (P>10*GeV) & (PID_P>5) & (PID_P-PID_K>5) & (GHOSTPROB<0.5)" DaughterCutpi = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K<5) & (GHOSTPROB<0.5)" - DaughterCutK = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K>0) & (GHOSTPROB<0.5)" + DaughterCutK = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K>5) & (GHOSTPROB<0.5)" protons = ParticleFilter( long_protons, Cut = F.FILTER( convert_cut(DaughterCutp) ) ) kaons = ParticleFilter( long_kaons, Cut = F.FILTER( convert_cut(DaughterCutK) ) ) pions = ParticleFilter( long_pions, Cut = F.FILTER( convert_cut(DaughterCutpi) ) ) muons = make_long_muons() Lambda = make_LambdaLL() - phi = make_phi2kk(kaon_pidk_min=0) + phi = make_phi2kk(kaon_pidk_min=5) input_dict = {"J/psi(1S)": Jpsi, "phi(1020)": phi, "Lambda0":Lambda, "Lambda~0":Lambda, -- GitLab From cd2c313fbb9ba68c8c64c04b03f21ba312381bd7 Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Tue, 2 Jul 2024 17:27:25 +0200 Subject: [PATCH 7/8] Bug fixed --- Run3_b2psiX_pentaquark/info.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Run3_b2psiX_pentaquark/info.yaml b/Run3_b2psiX_pentaquark/info.yaml index cae839a2dc..22dfcd2e64 100644 --- a/Run3_b2psiX_pentaquark/info.yaml +++ b/Run3_b2psiX_pentaquark/info.yaml @@ -8,19 +8,12 @@ defaults: # data configuration {%- set datasets = [ ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2JpsipK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2JpsipK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Lb2Jpsippi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2JpsiKpi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2JpsiKpi', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Xib2JpsiLambdaK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2Jpsippbar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2Jpsippbar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsiphiK', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), - #('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'Bp2JpsipLambdabar', 'MagUp', 'VeloClosed', 'Spruce', 'bandq'), ]%} -- GitLab From 4b8e1eaf5e2cd0284f31a62e29215ed59b79e82d Mon Sep 17 00:00:00 2001 From: Jianqiao Wang <jianqiao.wang@cern.ch> Date: Fri, 19 Jul 2024 10:55:35 +0200 Subject: [PATCH 8/8] Two new decays --- Run3_b2psiX_3body_withUT/dv_data.py | 38 ++ Run3_b2psiX_3body_withUT/info.yaml | 43 ++ Run3_b2psiX_3body_withUT/template.py | 99 +++++ .../tools/descriptor_writer.py | 146 +++++++ .../tools/tupling_maker.py | 386 ++++++++++++++++++ 5 files changed, 712 insertions(+) create mode 100644 Run3_b2psiX_3body_withUT/dv_data.py create mode 100644 Run3_b2psiX_3body_withUT/info.yaml create mode 100644 Run3_b2psiX_3body_withUT/template.py create mode 100644 Run3_b2psiX_3body_withUT/tools/descriptor_writer.py create mode 100644 Run3_b2psiX_3body_withUT/tools/tupling_maker.py diff --git a/Run3_b2psiX_3body_withUT/dv_data.py b/Run3_b2psiX_3body_withUT/dv_data.py new file mode 100644 index 0000000000..6bbec76cea --- /dev/null +++ b/Run3_b2psiX_3body_withUT/dv_data.py @@ -0,0 +1,38 @@ +from .template import * + +def Lb2JpsipK(options: Options): + algs = template(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True, "Lb2JpsipK") + return make_config( options, algs ) + +def Lb2Jpsippi(options: Options): + algs = template(["Lambda_b0", "J/psi(1S)", "p+", "pi-"], True, "Lb2Jpsippi") + return make_config( options, algs ) + +def B2JpsiKpi(options: Options): + algs = template(["B0", "J/psi(1S)", "K+", "pi-"], True, "B2JpsiKpi") + return make_config( options, algs ) + +def Xib2JpsiLambdaK(options: Options): + algs = template(["Xi_b-", "J/psi(1S)", "Lambda0", "K-"], True, "Xib2JpsiLambdaK") + return make_config( options, algs ) + +def Bp2JpsipLambdabar(options: Options): + algs = template(["B+", "J/psi(1S)", "p+", "Lambda~0"], True, "Bp2JpsipLambdabar") + return make_config( options, algs ) + +def Bp2JpsiphiK(options: Options): + algs = template(["B+", "J/psi(1S)", "phi(1020)", "K+"], True, "Bp2JpsiphiK") + return make_config( options, algs ) + +def B2Jpsippbar(options: Options): + algs = template(["B_s0", "J/psi(1S)", "p+", "p~-"], False, "B2Jpsippbar") + return make_config( options, algs ) + +def B2Jpsipipi(options: Options): + algs = template(["B0", "J/psi(1S)", "pi+", "pi-"], False, "B2Jpsipipi") + return make_config( options, algs ) + +def B2JpsiKK(options: Options): + algs = template(["B0", "J/psi(1S)", "K+", "K-"], False, "B2JpsiKK") + return make_config( options, algs ) + diff --git a/Run3_b2psiX_3body_withUT/info.yaml b/Run3_b2psiX_3body_withUT/info.yaml new file mode 100644 index 0000000000..57903d86f0 --- /dev/null +++ b/Run3_b2psiX_3body_withUT/info.yaml @@ -0,0 +1,43 @@ +defaults: + application: DaVinci/v64r5 + wg: BandQ + inform: + - mengzhen.wang@cern.ch + - jianqiao.wang@cern.ch + +# data configuration + +{%- set datasets = [ + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2Jpsipipi', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), + ('Collision24', 'Sprucing24c2/90000000', 'BANDQ', 'B2JpsiKK', 'MagDown', 'VeloClosed', 'Spruce', 'bandq'), +]%} + + +{%- set dv_platform_detdesc = "x86_64_v2-el9-gcc13+detdesc-opt" %} + +{%- for data, Type, wg, decay, polarity, Velo, process, stream in datasets %} + +data_{{decay}}_{{wg}}_{{process}}_{{data}}_{{Velo}}_{{polarity}}: + application: "DaVinci/v64r7" + input: + bk_query: "/LHCb/{{data}}/Beam6800GeV-{{Velo}}-{{polarity}}/Real Data/{{Type}}/{{wg}}.DST" + dq_flags: + - OK + - UNCHECKED + keep_running: True + n_test_lfns: 1 + options: + entrypoint: Run3_b2psiX_3body_withUT.dv_data:{{decay}} + 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 + output: Data_{{process}}_{{stream}}_{{decay}}.ROOT +{%- endfor %} + + diff --git a/Run3_b2psiX_3body_withUT/template.py b/Run3_b2psiX_3body_withUT/template.py new file mode 100644 index 0000000000..a8cd99fa6c --- /dev/null +++ b/Run3_b2psiX_3body_withUT/template.py @@ -0,0 +1,99 @@ +from .tools.tupling_maker import * +from .tools.descriptor_writer import * + +from Hlt2Conf.standard_particles import make_long_kaons, make_long_protons, make_long_pions, make_LambdaLL, make_long_muons, make_phi2kk + +def template(particles, cc, directory): + + ##### Default inputs + sprucing_line = 'SpruceBandQ_JpsiToMuMuDetached' + Jpsi = get_particles(f"/Event/Spruce/{sprucing_line}/Particles") + + rec_sum = get_rec_summary() + v2_pvs = get_pvs() + odin = get_odin() + decreports = None + + long_pions = make_long_pions() + long_kaons = make_long_kaons() + long_protons = make_long_protons() + + DaughterCutp = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (P>10*GeV) & (PID_P>5) & (PID_P-PID_K>5) & (GHOSTPROB<0.5)" + DaughterCutpi = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K<5) & (GHOSTPROB<0.5)" + DaughterCutK = "(BPVIPCHI2(get_pvs())>9) & (PT>250*MeV) & (PID_K>5) & (GHOSTPROB<0.5)" + + protons = ParticleFilter( long_protons, Cut = F.FILTER( convert_cut(DaughterCutp) ) ) + kaons = ParticleFilter( long_kaons, Cut = F.FILTER( convert_cut(DaughterCutK) ) ) + pions = ParticleFilter( long_pions, Cut = F.FILTER( convert_cut(DaughterCutpi) ) ) + muons = make_long_muons() + Lambda = make_LambdaLL() + phi = make_phi2kk(kaon_pidk_min=5) + + input_dict = {"J/psi(1S)": Jpsi, "phi(1020)": phi, + "Lambda0":Lambda, "Lambda~0":Lambda, + "pi+": pions, "pi-": pions, + "K+": kaons, "K-": kaons, + "p+": protons, "p~-": protons, + "mu+": muons, "mu~-": muons, + } + + # create particle containers + + B2JpsiX = ParticleCombiner( + Inputs = [input_dict[particle] for particle in particles[1:]], + DecayDescriptor = descriptor(particles, cc), + name = "JpsiToMuMu_Detached_line_validation", + CombinationCut = convert_cut("in_range(4000, MASS, 7000) & (CHILD(2, PT)+CHILD(3, PT)>900*MeV)"), + #CombinationCut = convert_cut("in_range(5200, MASS, 7000)"), + CompositeCut = convert_cut("in_range(4000, MASS, 7000) & CHI2DOF<20 & BPVLTIME(get_pvs())>0.2*picosecond & BPVVDZ(get_pvs())>0.*mm") + ) + + #FunTuple: define branches. + + hlt1_trigger_lines = [ 'Hlt1TrackMVADecision', + 'Hlt1TwoTrackMVADecision', + 'Hlt1D2KKDecision', + 'Hlt1D2KPiDecision', + 'Hlt1D2PiPiDecision', + 'Hlt1DiMuonHighMassDecision', + 'Hlt1DiMuonLowMassDecision', + 'Hlt1DiMuonSoftDecision', + 'Hlt1KsToPiPiDecision', + 'Hlt1LowPtMuonDecision', + 'Hlt1LowPtDiMuonDecision', + 'Hlt1SingleHighPtMuonDecision', + 'Hlt1TrackMuonMVADecision'] + + + line_prefilter = create_lines_filter(name=f"PreFilter_{sprucing_line}", lines=[sprucing_line]) + evt_vars = event_variables(v2_pvs, odin, decreports, rec_sum, hlt1_trigger_lines, [sprucing_line]) + candidate_vars = candidate_variables(v2_pvs, particles) + tistos_vars = tistos_variables(hlt1_trigger_lines, [], Jpsi, False) + + composite_particles = [ particle for particle in particles if (particle_df["type"][particle] != "basic") and (particle != "phi(1020)") ] + dtf_vars1 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, composite_particles) + dtf_vars2 = make_dtf_variables(v2_pvs, B2JpsiX, particles, True, composite_particles[1:]) + + for particle in particles: + if particle_df["type"][particle] != "basic": + candidate_vars[particle_df["abbr"][particle]] += tistos_vars + + for key in candidate_vars.keys(): + candidate_vars[key] += dtf_vars1[key] + candidate_vars[key] += dtf_vars2[key] + + B2JpsiX_branches = default_branches(particles, cc) + + # define tupling algorithms + B2JpsiX_tuple = FunTuple_Particles( name=directory, + inputs=B2JpsiX, + tuple_name="DecayTree", + fields=B2JpsiX_branches, + variables=candidate_vars, + store_multiple_cand_info = True, + event_variables = evt_vars) + + algs = { f"{directory}_tuple":[ B2JpsiX_tuple, line_prefilter ],} + + return algs + diff --git a/Run3_b2psiX_3body_withUT/tools/descriptor_writer.py b/Run3_b2psiX_3body_withUT/tools/descriptor_writer.py new file mode 100644 index 0000000000..54444acc7a --- /dev/null +++ b/Run3_b2psiX_3body_withUT/tools/descriptor_writer.py @@ -0,0 +1,146 @@ +import pandas as pd +import numpy as np +particle_dict = {"Lambda_b0": {"abbr": "Lb", "type": "toplevel", "daughters":[]}, + "Xi_b-": {"abbr": "Xibm", "type": "toplevel", "daughters":[]}, + "Xi_b0": {"abbr": "Xib0", "type": "toplevel", "daughters":[]}, + "B0": {"abbr": "B0", "type": "toplevel", "daughters":[]}, + "B+": {"abbr": "Bp", "type": "toplevel", "daughters":[]}, + "B-": {"abbr": "Bm", "type": "toplevel", "daughters":[]}, + "B_s0": {"abbr": "Bs", "type": "toplevel", "daughters":[]}, + "J/psi(1S)": {"abbr": "Jpsi", "type": "composite", "daughters": ["mu+", "mu-"]}, + "psi(2S)": {"abbr": "psi2S", "type": "composite", "daughters": ["mu+", "mu-"]}, + "phi(1020)": {"abbr": "phi", "type": "composite", "daughters": ["K+", "K-"]}, + "Lambda0": {"abbr": "Lambda", "type": "composite", "daughters": ["p+", "pi-"]}, + "Lambda~0": {"abbr": "Lambda", "type": "composite", "daughters": ["p~-", "pi+"]}, + "mu+": {"abbr": "mup", "type": "basic", "daughters":[]}, + "mu-": {"abbr": "mum", "type": "basic", "daughters":[]}, + "e+": {"abbr": "ep", "type": "basic", "daughters":[]}, + "e-": {"abbr": "em", "type": "basic", "daughters":[]}, + "pi+": {"abbr": "Pip", "type": "basic", "daughters":[]}, + "pi-": {"abbr": "Pim", "type": "basic", "daughters":[]}, + "K+": {"abbr": "Kp", "type": "basic", "daughters":[]}, + "K-": {"abbr": "Km", "type": "basic", "daughters":[]}, + "p+": {"abbr": "Pp", "type": "basic", "daughters":[]}, + "p~-": {"abbr": "Pm", "type": "basic", "daughters":[]}, + } +particle_df = pd.DataFrame(particle_dict).T + +def descriptor(particles, cc=False): + decay_descriptor = f"{particles[0]} ->" + for particle in particles[1:]: + decay_descriptor += f" {particle}" + if cc: decay_descriptor = f"[{decay_descriptor}]cc" + return decay_descriptor + +def decay_branches(mother, daughters, decay_descriptor): + psi_pos = 0 + phi_pos = 0 + Lambda_pos = 0 + Pm_pos = Pp_pos = 0 + Km_pos = Kp_pos = 0 + Pim_pos = Pip_pos = 0 + mum_pos = mup_pos = 0 + em_pos = ep_pos = 0 + + #if decay_descriptor[0] == "[" or decay_descriptor[-3:] == "]cc": + if "cc" in decay_descriptor[-5:]: + branch_descriptor = decay_descriptor[:-2] + "CC" + else: branch_descriptor = decay_descriptor + #if "J/psi(1S)" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("J/psi(1S)", "(J/psi(1S) -> mu+ mu-)") + #if "psi(2S)" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("psi(2S)", "(psi(2S) -> mu+ mu-)") + #if "Lambda0" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("Lambda0", "(Lambda0 -> p+ pi-)") + #if "Lambda~0" in decay_descriptor: + # branch_descriptor = branch_descriptor.replace("Lambda~0", "(Lambda~0 -> p~- pi+)") + for comp_par in particle_df.query("type=='composite'").index: + if comp_par in decay_descriptor: + #branch_descriptor = branch_descriptor.replace(comp_par, comp_par + "->" + " ".join(particle_df["daughters"][comp_par])) + branch_descriptor = branch_descriptor.replace(comp_par, f'({comp_par} -> {" ".join(particle_df["daughters"][comp_par])})') + + branches = {mother: branch_descriptor} + + for daughter in daughters: + if "psi" in daughter: + true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("psi", psi_pos)) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + psi_pos = branch_descriptor.find("psi", psi_pos) + len("psi(nS)") + if "phi" in daughter: + true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("phi", phi_pos)) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + phi_pos = branch_descriptor.find("phi", phi_pos) + len("phi(1020)") + if "Lambda" in daughter: + true_pos = branch_descriptor.rfind("(", 0, branch_descriptor.find("Lambda", Lambda_pos)) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Lambda_pos = branch_descriptor.find("Lambda", Lambda_pos) + len("Lambda~0") + if "Pp" in daughter: + true_pos = branch_descriptor.find("p+", Pp_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pp_pos = true_pos + len("p+") + if "Pm" in daughter: + true_pos = branch_descriptor.find("p~-", Pm_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pm_pos = true_pos + len("p~-") + if "Kp" in daughter: + true_pos = branch_descriptor.find("K+", Kp_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Kp_pos = true_pos + len("K+") + if "Km" in daughter: + true_pos = branch_descriptor.find("K-", Km_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Km_pos = true_pos + len("K-") + if "Pip" in daughter or "Hp" in daughter: + true_pos = branch_descriptor.find("pi+", Pip_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pip_pos = true_pos + len("pi+") + if "Pim" in daughter or "Hm" in daughter: + true_pos = branch_descriptor.find("pi-", Pim_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + Pim_pos = true_pos + len("pi-") + if "mup" in daughter: + true_pos = branch_descriptor.find("mu+", mup_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + mup_pos = true_pos + len("mu+") + if "mum" in daughter: + true_pos = branch_descriptor.find("mu-", mum_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + mum_pos = true_pos + len("mu-") + if "ep" in daughter: + true_pos = branch_descriptor.find("e+", ep_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + ep_pos = true_pos + len("e+") + if "em" in daughter: + true_pos = branch_descriptor.find("e-", em_pos) + branches.update({daughter: branch_descriptor[:true_pos]+"^"+branch_descriptor[true_pos:]}) + em_pos = true_pos + len("e-") + return branches + +def all_particles(particles): + all_pars = [] + for particle in particles: + all_pars += ( [ particle ] + particle_df["daughters"][particle]) + return all_pars + +#print(all_particles(["B_s0","J/psi(1S)", "p+", "p~-"])) + +def default_names(particles): + names = [] + for particle in particles: + abbr = particle_df["abbr"][ particle ] + names.append( abbr ) + names += [f"{daughter_abbr}_{abbr}" for daughter_abbr in particle_df["abbr"][particle_df["daughters"][particle]]] + return names + +def default_branches(particles, cc=False): + names = default_names(particles) + return decay_branches(names[0], names[1:], descriptor(particles, cc)) + +branches = default_branches( ["B+","J/psi(1S)", "phi(1020)", "K+"], True) +print(branches) + +#branches = decay_branches("Bs", ["Jpsi", "Pp", "Pm", "mup", "mum"], "[B_s0 -> J/psi(1S) p+ p~-]cc") +#print(branches) + +#branches = default_names( ["B_s0","J/psi(1S)", "p+", "p~-"]) +#print(descriptor(["Lambda_b0", "J/psi(1S)", "p+", "K-"], True)) diff --git a/Run3_b2psiX_3body_withUT/tools/tupling_maker.py b/Run3_b2psiX_3body_withUT/tools/tupling_maker.py new file mode 100644 index 0000000000..c9feb96573 --- /dev/null +++ b/Run3_b2psiX_3body_withUT/tools/tupling_maker.py @@ -0,0 +1,386 @@ +from DaVinci import make_config, Options +from DaVinci.algorithms import create_lines_filter + +from PyConf.reading import get_rec_summary, get_pvs +from PyConf.reading import get_particles + +import FunTuple.functorcollections as FC +import Functors as F +from FunTuple import FunctorCollection + +from FunTuple import FunTuple_Event +from FunTuple import FunTuple_Particles +from .descriptor_writer import * + + +#from PyConf.reading import (get_particles, get_charged_protoparticles, get_pvs, get_rec_summary, _get_unpacked) + +from Functors.math import in_range +from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleFilter + +from RecoConf.event_filters import require_pvs + +from Hlt2Conf.standard_particles import get_long_track_selector, standard_protoparticle_filter +from PyConf.Algorithms import FunctionalParticleMaker +from PyConf.reading import get_charged_protoparticles as _make_charged_protoparticles +from PyConf.reading import get_odin + +from GaudiKernel.SystemOfUnits import MeV, picosecond, mm, GeV +from DecayTreeFitter import DecayTreeFitter + +_basic = "basic" +_composite = "composite" +_toplevel = "toplevel" + +def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None): + + 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 + top = _toplevel == ptype # the B + + all_vars += FC.Kinematics() + if basic: + all_vars += FC.ParticleID(extra_info=True) + + if comp: + all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)}) + + if comp: # all these require a vertex + all_vars.update({"BPVCORRM": F.BPVCORRM(pvs)}) + all_vars.update({"BPVCORRMERR": F.BPVCORRMERR(pvs)}) + 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)}) + all_vars.update({"ALLPVX": F.ALLPVX(pvs)}) + all_vars.update({"ALLPVY": F.ALLPVY(pvs)}) + all_vars.update({"ALLPVZ": F.ALLPVZ(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 top: # apply this only to B + # all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)}) # example of CHILD + # all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)}) + # all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ}) + + if comp: + #all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)}) + #all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)}) + 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}) + + # duplicated from FC all_vars.update({"ENERGY" : F.ENERGY}) + 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}) + all_vars.update({"TRACK_MOM_": F.TRACK_MOMVEC}) + all_vars.update({"TRACK_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM}) + 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}) + + if comp: + all_vars.update({"MAXPT": F.MAX(F.PT)}) + all_vars.update({"MAXDOCA": F.MAXSDOCA}) + all_vars.update({"MAXDOCACHI2": F.MAXSDOCACHI2}) + #all_vars.update({"MINDOCA": F.MINSDOCA}) + #all_vars.update({"MINDOCACHI2": F.MINSDOCACHI2}) + # the above in cut versions. + + # duplicated from FC all_vars.update({ 'MC_MOTHER_ID' : F.VALUE_OR(0) @ mctruth( + # duplicated from FC F.MC_MOTHER(1, F.PARTICLE_ID))}) + + 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({"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({"SDOCA12": F.SDOCA(1, 2)}) + all_vars.update({"SDOCA12_CHI2": F.SDOCACHI2(1, 2)}) + if basic: + all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE}) + + if comp: + all_vars.update({"SUBCOMB12_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 2))}) + all_vars.update({"SUMPT": F.SUM(F.PT)}) + if top: + all_vars.update({"SDOCA13": F.SDOCA(1, 3)}) + all_vars.update({"SDOCA13_CHI2": F.SDOCACHI2(1, 3)}) + all_vars.update({"SDOCA23": F.SDOCA(2, 3)}) + all_vars.update({"SDOCA23_CHI2": F.SDOCACHI2(2, 3)}) + all_vars.update({"SUBCOMB13_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 3))}) + all_vars.update({"SUBCOMB23_MM": F.SUBCOMB(Functor=F.MASS, Indices=(2, 3))}) + + 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 tistos_variables(Hlt1_decisions, Hlt2_decisions, data, isturbo): + tistos_vars = FunctorCollection({}) + tistos_vars += FC.HltTisTos( selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=data) + if not isturbo: + tistos_vars += FC.HltTisTos( selection_type="Hlt2", trigger_lines=Hlt2_decisions, data=data) + return tistos_vars + +def event_variables(PVs, ODIN, decreports, rec_sum, hlt1_lines, sprucing_lines): + """ + event variables + """ + + ## Some empty summaries removed + evt_vars = FunctorCollection({ + "nPVs": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nPVs"), + "nTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTracks"), + "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"), + "nGhosts": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nGhosts"), + "nRich1Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich1Hits"), + "nRich2Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich2Hits"), + #"nVeloClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloClusters"), + "nVPClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVPClusters"), + #"nITClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nITClusters"), + #"nTTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTClusters"), + "nUTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUTClusters"), + #"nOTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nOTClusters"), + "nFTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nFTClusters"), + #"nSPDhits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nSPDhits"), + "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"), + #"nMuonCoordsS0": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS0"), + #"nMuonCoordsS1": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS1"), + #"nMuonCoordsS2": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS2"), + #"nMuonCoordsS3": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS3"), + #"nMuonCoordsS4": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS4"), + #"nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"), + "ALLPVX": F.ALLPVX(PVs), + "ALLPVY": F.ALLPVY(PVs), + "ALLPVZ": F.ALLPVZ(PVs), + }) + evt_vars += FC.EventInfo() + + evt_vars += FC.SelectionInfo( selection_type="Hlt1", trigger_lines=hlt1_lines) + evt_vars += FC.SelectionInfo( selection_type="Hlt2", trigger_lines=sprucing_lines) + # duplicated from FC if ODIN: + # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_ID' : F.BUNCHCROSSING_ID(ODIN)}) + # duplicated from FC evt_vars.update({ 'BUNCHCROSSING_TYPE' : F.BUNCHCROSSING_TYPE(ODIN)}) + + 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)}) + + # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) + # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) + + evt_vars.update({"PV_SIZE": F.SIZE(PVs)}) + # duplicated from FC evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN)}) + # duplicated from FC evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN)}) + + if decreports: + evt_vars.update({"TCK": F.TCK(decreports)}) + + print(f"### For event returning variables {evt_vars.functor_dict.keys()}") + return evt_vars + +def candidate_variables(pvs, particles): + abbrs = default_names(particles) + names = all_particles(particles) + variables_B = {abbr: all_variables(pvs, None, particle_df["type"][name]) for abbr, name in zip(abbrs, names)} + return variables_B + +from DecayTreeFitter import DecayTreeFitter +def make_dtf_variables(pvs, data, particles, pv_constraint=False, mass_constraints=[]): + + abbrs = default_names(particles) + names = all_particles(particles) + + if pv_constraint: dtf_name = "DTF_PV_" + else: dtf_name = "DTF_" + dtf_name += "".join(f"{par}_" for par in particle_df["abbr"][mass_constraints]) + + DTF = DecayTreeFitter( + name = f"{dtf_name}DecayTreeFitter", + input_particles = data, + input_pvs = (pv_constraint and pvs), + mass_constraints = mass_constraints, + ) + + dtf_dict = {} + + shared_variables = FunctorCollection( + { "ETA": F.ETA, + "PHI": F.PHI, + "BPVIPCHI2": F.BPVIPCHI2(pvs), + "BPVIP": F.BPVIP(pvs), + "BPVX": F.BPVX(pvs), + "BPVY": F.BPVY(pvs), + "BPVZ": F.BPVZ(pvs), + } + ) + FC.Kinematics() + + dtf_quality_variables = FunctorCollection( { + dtf_name+"_DTFCHI2": DTF.CHI2, + dtf_name+"_DTFNDOF": DTF.NDOF, + dtf_name+"_CTAU": DTF.CTAU, + dtf_name+"_CTAUERR": DTF.CTAUERR, + dtf_name+"_MERR": DTF.MASSERR, + } + ) + + #make branches + for abbr, name in zip(abbrs, names): + is_basic = particle_df["type"][name] + if is_basic: + orig_variables = shared_variables + FunctorCollection( + { "TX" : F.TX, + "TY" : F.TY, + "MINIPCHI2" : F.MINIPCHI2(pvs), + "MINIP" : F.MINIP(pvs), + "KEY" : F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.TRACK, + "TRGHOSTPROB": F.GHOSTPROB, + "TRACKPT": F.TRACK_PT, + "TRACKHISTORY": F.VALUE_OR(-1) @ F.TRACKHISTORY @ F.TRACK, + "QOVERP": F.QOVERP @ F.TRACK, + "TRCHI2DOF": F.CHI2DOF @ F.TRACK, + "NDOF": F.VALUE_OR(-1) @ F.NDOF @ F.TRACK, + } + ) + else: + orig_variables = shared_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), + "CHI2DOF": F.CHI2DOF, #CHI2VXNDOF + "BPVFDCHI2": F.BPVFDCHI2(pvs), + "BPVFD": F.BPVFD(pvs), + "BPVVDRHO": F.BPVVDRHO(pvs), + "BPVVDZ": F.BPVVDZ(pvs), + "BPVLTIME": F.BPVLTIME(pvs), + "END_VX": F.END_VX, #END_ + "END_VY": F.END_VY, + "END_VZ": F.END_VZ, + } + ) + orig_variables += dtf_quality_variables + + dtf_variables = FunctorCollection({ dtf_name + expr: DTF(func) for expr, func in orig_variables.get_thor_functors().items() }) + dtf_dict.update( {abbr: dtf_variables} ) + + return dtf_dict + +import re +def convert_cut(string_cut): + cuts = string_cut.split("&") + paras = ["BPV", "PID_", "MASS", "CHARGE", "CHI2DOF", "END", "IS_ID", "ABS_", "MAX", "SUM", "GHOSTPROB", "CHILD"] + values = [] + for cut in cuts: + value = cut + for para in paras: + if para in cut: + value = value.replace(para, f"F.{para}") + value = re.sub(r"\bPT\b", "F.PT", value) + value = re.sub(r"\bP\b", "F.P", value) + value = re.sub(r"\bCHI2\b", "F.CHI2", value) + values.append(value) + functor_cut = ",".join(values) + return eval(f"F.require_all({functor_cut})") +#return f"F.require_all({functor_cut})" + -- GitLab