From de632ae88de62d64d5609d8718bdaeb9d91a9e78 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Tue, 18 Jun 2024 14:54:54 +0200
Subject: [PATCH 01/18] scripts to get samples

---
 pvassoc/dv.py       | 342 ++++++++++++++++++++++++++++++++++++++++++++
 pvassoc/hlt2.py     | 249 ++++++++++++++++++++++++++++++++
 pvassoc/info.yaml   |  69 +++++++++
 pvassoc/run_dv.py   |  21 +++
 pvassoc/run_hlt1.py |  42 ++++++
 pvassoc/run_hlt2.py |  91 ++++++++++++
 6 files changed, 814 insertions(+)
 create mode 100755 pvassoc/dv.py
 create mode 100755 pvassoc/hlt2.py
 create mode 100644 pvassoc/info.yaml
 create mode 100755 pvassoc/run_dv.py
 create mode 100755 pvassoc/run_hlt1.py
 create mode 100755 pvassoc/run_hlt2.py

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
new file mode 100755
index 0000000000..074108dbd6
--- /dev/null
+++ b/pvassoc/dv.py
@@ -0,0 +1,342 @@
+###############################################################################
+# (c) Copyright 2024 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+from PyConf.reading import get_pvs, get_particles  # type: ignore[import]
+import Functors as F # type: ignore[import]
+from FunTuple import FunTuple_Event  # type: ignore[import]
+from DaVinci.algorithms import create_lines_filter  # type: ignore[import]
+import FunTuple.functorcollections as FC  # type: ignore[import]
+from DaVinciMCTools import MCTruthAndBkgCat  # type: ignore[import]
+from Hlt2Conf.algorithms_thor import ParticleFilter  # type: ignore[import]
+from PyConf.Algorithms import VoidFilter  # type: ignore[import]
+import Functors.math as fmath  # type: ignore[import]
+from PyConf.Algorithms import FlattenDecayTree  # type: ignore[import]
+from GaudiKernel import SystemOfUnits  # type: ignore[import]
+from RecoConf.reconstruction_objects import make_tracks  # type: ignore[import]
+
+#Variables for pvs
+ALLPV_CHI2      = lambda Vertices: F.MAP(F.CHI2) @ F.TES(Vertices)
+ALLPV_NDOF      = lambda Vertices: F.MAP(F.NDOF) @ F.TES(Vertices)  # Can infer nVelo tracks from this
+ALLPV_X         = lambda Vertices: F.MAP(F.X_COORDINATE @ F.POSITION) @ F.TES(Vertices)
+ALLPV_Y         = lambda Vertices: F.MAP(F.Y_COORDINATE @ F.POSITION) @ F.TES(Vertices)
+ALLPV_Z         = lambda Vertices: F.MAP(F.Z_COORDINATE @ F.POSITION) @ F.TES(Vertices)
+ALLPV_POSERR    = lambda Vertices, indx_i: F.MAP(fmath.sqrt(F.CALL(indx_i, indx_i)) @ F.POS_COV_MATRIX) @ F.TES(Vertices)
+
+#Variables for particles
+ALLPART_KEY      = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.OBJECT_KEY) @ F.TES(particles) #to differentiate from particles forming B candidate
+ALLPART_Q        = lambda particles: F.MAP(F.CHARGE) @ F.TES(particles)
+ALLPART_PX       = lambda particles: F.MAP(F.PX) @ F.TES(particles)
+ALLPART_PY       = lambda particles: F.MAP(F.PY) @ F.TES(particles)
+ALLPART_PZ       = lambda particles: F.MAP(F.PZ) @ F.TES(particles)
+ALLPART_MOMERR   = lambda particles, indx_i: F.MAP(F.CALL(indx_i, indx_i) @ F.THREE_MOM_COV_MATRIX) @ F.TES(particles)
+ALLPART_ETA      = lambda particles: F.MAP(F.ETA) @ F.TES(particles)
+ALLPART_PHI      = lambda particles: F.MAP(F.PHI) @ F.TES(particles)
+ALLPART_PIDPI    = lambda particles: F.MAP(F.PID_PI) @ F.TES(particles)
+ALLPART_PIDK     = lambda particles: F.MAP(F.PID_K) @ F.TES(particles)
+ALLPART_PIDP     = lambda particles: F.MAP(F.PID_P) @ F.TES(particles)
+ALLPART_PIDE     = lambda particles: F.MAP(F.PID_E) @ F.TES(particles)
+ALLPART_PIDMU    = lambda particles: F.MAP(F.PID_MU) @ F.TES(particles)
+#P -> Proto -> Track
+ALLPART_TRACK_CHI2     = lambda particles: F.MAP(F.CHI2 @ F.TRACK) @ F.TES(particles)
+ALLPART_TRACK_NDOF     = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.NDOF @ F.TRACK) @ F.TES(particles)
+ALLPART_TRACK_TYPE     = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.CAST_TO_INT @ F.TRACKTYPE @ F.TRACK) @ F.TES(particles)
+ALLPART_TRACK_GHOSTPROB= lambda particles: F.MAP(F.GHOSTPROB) @ F.TES(particles)
+## particle has track but not a closest to beam state, so throws an error (Should this be an error at all?)
+#ALLPART_CLOSESTTOBEAM_X = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+#ALLPART_CLOSESTTOBEAM_Y = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+#ALLPART_CLOSESTTOBEAM_TX = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TX @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+#ALLPART_CLOSESTTOBEAM_TY = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TY @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+#ALLPART_CLOSESTTOBEAM_QOP = lambda particles:F.MAP(F.VALUE_OR(F.NaN) @ F.QOVERP @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+#ALLPART_CLOSESTTOBEAM_STATEERR = lambda particles, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+ALLPART_FIRSTMEAS_X = lambda particles:   F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
+ALLPART_FIRSTMEAS_Y = lambda particles:   F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
+ALLPART_FIRSTMEAS_Z = lambda particles:   F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
+ALLPART_FIRSTMEAS_TX = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.TX @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
+ALLPART_FIRSTMEAS_TY = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.TY @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
+ALLPART_FIRSTMEAS_QOP = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.QOVERP @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
+ALLPART_FIRSTMEAS_STATEERR = lambda particles, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
+### particle has no endut state, so throws an error (should this be an error at all?)
+#ALLPART_ENDUT_X = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("EndUT") @ F.TRACK) @ F.TES(particles)
+#ALLPART_ENDUT_Y = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("EndUT") @ F.TRACK) @ F.TES(particles)
+#ALLPART_ENDUT_Z = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION @ F.STATE_AT("EndUT") @ F.TRACK) @ F.TES(particles)
+#ALLPART_ENDUT_TX = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TX @ F.STATE_AT("EndUT") @ F.TRACK) @ F.TES(particles)
+#ALLPART_ENDUT_TY = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TY @ F.STATE_AT("EndUT") @ F.TRACK) @ F.TES(particles)
+#ALLPART_ENDUT_QOP = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.QOVERP @ F.STATE_AT("EndUT") @ F.TRACK) @ F.TES(particles)
+#ALLPART_ENDUT_STATEERR = lambda particles, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("EndUT") @ F.TRACK) @ F.TES(particles)
+#P -> MCP
+ALLPART_MC_ISPROMPT  = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.MC_ISPROMPT())) @ F.TES(particles)
+ALLPART_TRUE_PV_X = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VX)) @ F.TES(particles) #for association of PV <-> MCPV
+ALLPART_TRUE_PV_Y = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VY)) @ F.TES(particles)
+ALLPART_TRUE_PV_Z = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VZ)) @ F.TES(particles)
+#P -> LONG LIVED ANCESTOR (Helpful to find which PV has produced B using MCPV <-> PV association)
+## 10^-15 seconds is between the lifetimes of the pi0 (considered prompt) and the tau (nonprompt).
+LONGLIVED_ANCESTOR = F.MC_FIRST_LONGLIVED_ANCESTOR(MinLifetime=1e-7 * SystemOfUnits.ns)
+ALLPART_LONGLIVED_ANCESTOR_ID  = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID  @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
+ALLPART_LONGLIVED_ANCESTOR_KEY = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY  @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
+#the following we don't need (but keep commented out in case we do)
+#ALLPART_LONGLIVED_ANCESTOR_PVX = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VX @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
+#ALLPART_LONGLIVED_ANCESTOR_PVY = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VY @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
+#ALLPART_LONGLIVED_ANCESTOR_PVZ = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VZ @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
+#ALLPART_TRUE_ID  = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID)) @ F.TES(particles)
+#ALLPART_TRUE_KEY = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY)) @ F.TES(particles)
+#ALLPART_TRUE_ORGIN_X = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VX)) @ F.TES(particles)
+#ALLPART_TRUE_ORGIN_Y = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VY)) @ F.TES(particles)
+#ALLPART_TRUE_ORGIN_Z = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VZ)) @ F.TES(particles)
+#ALLPART_MCP_NGEN_MOTHER_ID  = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.MC_MOTHER(ngen, F.PARTICLE_ID))) @ F.TES(particles)
+#ALLPART_MCP_NGEN_MOTHER_KEY = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.MC_MOTHER(ngen, F.OBJECT_KEY))) @ F.TES(particles)
+#ALLPART_ID        = lambda particles: F.MAP(F.VALUE_OR(0) @ F.PARTICLE_ID) @ F.TES(particles)
+#ALLPART_HISTORY   = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.CAST_TO_INT @ F.TRACKHISTORY @ F.TRACK) @ F.TES(particles)
+#ALLPART_FLAG      = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.CAST_TO_INT @ F.TRACKFLAG @ F.TRACK) @ F.TES(particles)
+
+#Variables for particles
+ALLB_ENDVTX_CHI2 = lambda particles: F.MAP(F.CHI2 @ F.ENDVERTEX) @ F.TES(particles)
+ALLB_ENDVTX_NDOF = lambda particles: F.MAP(F.NDOF @ F.ENDVERTEX) @ F.TES(particles)
+ALLB_ENDVTX_X    = lambda particles: F.MAP(F.END_VX) @ F.TES(particles)
+ALLB_ENDVTX_Y    = lambda particles: F.MAP(F.END_VY) @ F.TES(particles)
+ALLB_ENDVTX_Z    = lambda particles: F.MAP(F.END_VZ) @ F.TES(particles)
+ALLB_ENDVTX_POSERR = lambda particles, indx_i: F.MAP(fmath.sqrt(F.CALL(indx_i, indx_i)) @ F.POS_COV_MATRIX @ F.ENDVERTEX) @ F.TES(particles)
+ALLB_PX        = lambda particles: F.MAP(F.PX) @ F.TES(particles)
+ALLB_PY        = lambda particles: F.MAP(F.PY) @ F.TES(particles)
+ALLB_PZ        = lambda particles: F.MAP(F.PZ) @ F.TES(particles)
+ALLB_MOMERR    = lambda particles, indx_i: F.MAP(F.CALL(indx_i, indx_i) @ F.THREE_MOM_COV_MATRIX) @ F.TES(particles)
+ALLB_ETA       = lambda particles: F.MAP(F.ETA) @ F.TES(particles)
+ALLB_PHI       = lambda particles: F.MAP(F.PHI) @ F.TES(particles)
+#P -> MCP
+ALLB_TRUE_PV_X = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VX)) @ F.TES(particles) #for association of PV <-> MCPV
+ALLB_TRUE_PV_Y = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VY)) @ F.TES(particles)
+ALLB_TRUE_PV_Z = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VZ)) @ F.TES(particles)
+#the following we don't need (but keep commented out in case we do)
+#ALLB_TRUE_ID   = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID)) @ F.TES(particles)
+#ALLB_TRUE_CHILD1_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #D*-
+#ALLB_TRUE_CHILD11_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #D0
+#ALLB_TRUE_CHILD12_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(2, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #pi
+#ALLB_TRUE_CHILD111_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #K
+#ALLB_TRUE_CHILD112_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(2, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #pi
+#ALLB_TRUE_CHILD2_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(2, F.FORWARDARGS)) @ F.TES(particles) #mu
+#ALLB_ID       = lambda particles: F.MAP(F.PARTICLE_ID) @ F.TES(particles)
+#ALLB_KEY     = lambda particles: F.MAP(F.OBJECT_KEY) @ F.TES(particles)
+
+#velo tracks
+ALLVELOTRACKS_ETA = lambda tracks: F.MAP(F.ETA) @ F.TES(tracks)
+ALLVELOTRACKS_PHI = lambda tracks: F.MAP(F.PHI) @ F.TES(tracks)
+ALLVELOTRACKS_X = lambda tracks: F.MAP(F.X_COORDINATE @ F.POSITION) @ F.TES(tracks)
+ALLVELOTRACKS_Y = lambda tracks: F.MAP(F.Y_COORDINATE @ F.POSITION) @ F.TES(tracks)
+ALLVELOTRACKS_Z = lambda tracks: F.MAP(F.Z_COORDINATE @ F.POSITION) @ F.TES(tracks)
+ALLVELOTRACKS_TX = lambda tracks: F.MAP(F.TX) @ F.TES(tracks)
+ALLVELOTRACKS_TY = lambda tracks: F.MAP(F.TY) @ F.TES(tracks)
+##throw as error about pointers
+#ALLVELOTRACKS_FIRSTMEAS_X = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement")) @ F.TES(tracks)
+#ALLVELOTRACKS_FIRSTMEAS_Y = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement")) @ F.TES(tracks)
+#ALLVELOTRACKS_FIRSTMEAS_Z = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement")) @ F.TES(tracks)
+#ALLVELOTRACKS_POSERR = lambda tracks, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement")) @ F.TES(tracks)
+#ALLVELOTRACKS_ENDVELO_X = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
+#ALLVELOTRACKS_ENDVELO_Y = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
+#ALLVELOTRACKS_ENDVELO_Z = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
+#ALLVELOTRACKS_ENDVELO_POSERR = lambda tracks, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
+
+def get_user_algs(decay_channel):
+  """
+  decay_channel: decay channel to be used in the lines. 
+    Options: DstMu, DstTau_Lep, DstTau_Had, JpsiK_E, JpsiK_Mu
+  """
+  #line name
+  line_name = f'Hlt2SLB_BTo{decay_channel}'
+  #Run over events that have fired the line
+  my_filter = create_lines_filter(name="Filter", lines=[line_name])
+
+  #get Bs and particles
+  Bs = get_particles(f"/Event/HLT2/{line_name}/Particles")
+  particles = get_particles(f"/Event/HLT2/{line_name}/ExtraPions/Particles")
+
+  #get MCTRUTH for Bs
+  MCTRUTH_Bs = MCTruthAndBkgCat(Bs, name='MCTRUTH_Bs')
+  #get MCTRUTH for particles
+  MCTRUTH_parts = MCTruthAndBkgCat(particles, name='MCTRUTH_extra')
+
+  #get true id of B candidate (hepful to run over events that have a true Bcand)
+  if decay_channel == 'DstMu' or decay_channel == 'DstTau_Lep':
+    #Bd -> D*- mu+ nu
+    B_ID = 511
+  elif decay_channel == 'DstTau_Had' or decay_channel == 'JpsiK_E' or decay_channel == 'JpsiK_Mu':
+    #Bu -> D*- tau+ nu or Bu -> Jpsi K 
+    B_ID = 521
+  else:
+    raise ValueError(f"Invalid decay channel {decay_channel}")
+
+  #run over events that have a true Bcand
+  cut_event = F.MAP_ANY_OF(F.VALUE_OR(0) @ MCTRUTH_Bs(F.ABS @ F.PARTICLE_ID) == B_ID) @ F.TES(Bs)
+  truth_filter_event = VoidFilter(name='EventTruthFilter', Cut=cut_event)
+
+  #filter Bcands
+  cut_B = F.VALUE_OR(0) @ MCTRUTH_Bs(F.ABS @ F.PARTICLE_ID) == B_ID
+  Bcands = ParticleFilter(Input=Bs, Cut=F.FILTER(cut_B), name='signalB') #filter the B candidates
+
+  #get TES location of all descendants
+  all_descendants = FlattenDecayTree(InputParticles=Bcands, name="FlattenedDecayTree").OutputParticles
+  all_basics = ParticleFilter(all_descendants, F.FILTER(F.ISBASICPARTICLE), name = "AllBasics")
+
+  #get velo tracks
+  velo_tracks = make_tracks('VeloTracks')
+
+  #get v2_pvs
+  v2_pvs  = get_pvs()
+
+  #get global event variables
+  evt_vars = FC.RecSummary()
+
+  #get pv variables
+  evt_vars['ALLPV_CHI2[pv_indx]']   = ALLPV_CHI2(v2_pvs)
+  evt_vars['ALLPV_NDOF[pv_indx]']   = ALLPV_NDOF(v2_pvs)
+  evt_vars['ALLPV_X[pv_indx]']      = ALLPV_X(v2_pvs)
+  evt_vars['ALLPV_Y[pv_indx]']      = ALLPV_Y(v2_pvs)
+  evt_vars['ALLPV_Z[pv_indx]']      = ALLPV_Z(v2_pvs)
+  evt_vars['ALLPV_XERR[pv_indx]']   = ALLPV_POSERR(v2_pvs, 0)
+  evt_vars['ALLPV_YERR[pv_indx]']   = ALLPV_POSERR(v2_pvs, 1)
+  evt_vars['ALLPV_ZERR[pv_indx]']   = ALLPV_POSERR(v2_pvs, 2)
+
+  #get particle variables
+  evt_vars['ALLPART_KEY[part_indx]'] = ALLPART_KEY(particles)
+  evt_vars['ALLPART_Q[part_indx]'] = ALLPART_Q(particles)
+  evt_vars['ALLPART_PX[part_indx]'] = ALLPART_PX(particles)
+  evt_vars['ALLPART_PY[part_indx]'] = ALLPART_PY(particles)
+  evt_vars['ALLPART_PZ[part_indx]'] = ALLPART_PZ(particles)
+  evt_vars['ALLPART_PXERR[part_indx]'] = ALLPART_MOMERR(particles, 0)
+  evt_vars['ALLPART_PYERR[part_indx]'] = ALLPART_MOMERR(particles, 1)
+  evt_vars['ALLPART_PZERR[part_indx]'] = ALLPART_MOMERR(particles, 2)
+  evt_vars['ALLPART_ETA[part_indx]'] = ALLPART_ETA(particles)
+  evt_vars['ALLPART_PHI[part_indx]'] = ALLPART_PHI(particles)
+  evt_vars['ALLPART_PIDPI[part_indx]'] = ALLPART_PIDPI(particles)
+  evt_vars['ALLPART_PIDK[part_indx]'] = ALLPART_PIDK(particles)
+  evt_vars['ALLPART_PIDP[part_indx]'] = ALLPART_PIDP(particles)
+  evt_vars['ALLPART_PIDE[part_indx]'] = ALLPART_PIDE(particles)
+  evt_vars['ALLPART_PIDMU[part_indx]'] = ALLPART_PIDMU(particles)
+  #P -> Proto -> Track
+  evt_vars['ALLPART_TRACK_CHI2[part_indx]'] = ALLPART_TRACK_CHI2(particles)
+  evt_vars['ALLPART_TRACK_NDOF[part_indx]'] = ALLPART_TRACK_NDOF(particles)
+  evt_vars['ALLPART_TRACK_TYPE[part_indx]'] = ALLPART_TRACK_TYPE(particles)
+  evt_vars['ALLPART_TRACK_GHOSTPROB[part_indx]'] = ALLPART_TRACK_GHOSTPROB(particles)
+  # particle has track but not a closest to beam state, so throws an error (Should this be an error at all?)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_X[part_indx]'] = ALLPART_CLOSESTTOBEAM_X(particles)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_Y[part_indx]'] = ALLPART_CLOSESTTOBEAM_Y(particles)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_TX[part_indx]'] = ALLPART_CLOSESTTOBEAM_TX(particles)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_TY[part_indx]'] = ALLPART_CLOSESTTOBEAM_TY(particles)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_QOP[part_indx]'] = ALLPART_CLOSESTTOBEAM_QOP(particles)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_XERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 0)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_YERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 1)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_TXERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 2)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_TYERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 3)
+  #evt_vars['ALLPART_CLOSESTTOBEAM_QOPERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 4)
+  evt_vars['ALLPART_FIRSTMEAS_X[part_indx]'] = ALLPART_FIRSTMEAS_X(particles)
+  evt_vars['ALLPART_FIRSTMEAS_Y[part_indx]'] = ALLPART_FIRSTMEAS_Y(particles)
+  evt_vars['ALLPART_FIRSTMEAS_Z[part_indx]'] = ALLPART_FIRSTMEAS_Z(particles)
+  evt_vars['ALLPART_FIRSTMEAS_TX[part_indx]'] = ALLPART_FIRSTMEAS_TX(particles)
+  evt_vars['ALLPART_FIRSTMEAS_TY[part_indx]'] = ALLPART_FIRSTMEAS_TY(particles)
+  evt_vars['ALLPART_FIRSTMEAS_QOP[part_indx]'] = ALLPART_FIRSTMEAS_QOP(particles)
+  evt_vars['ALLPART_FIRSTMEAS_XERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 0)
+  evt_vars['ALLPART_FIRSTMEAS_YERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 1)
+  evt_vars['ALLPART_FIRSTMEAS_TXERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 2)
+  evt_vars['ALLPART_FIRSTMEAS_TYERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 3)
+  evt_vars['ALLPART_FIRSTMEAS_QOPERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 4)
+  # particle has no endut state, so throws an error (should this be an error at all?)
+  #evt_vars['ALLPART_ENDUT_X[part_indx]'] = ALLPART_ENDUT_X(particles)
+  #evt_vars['ALLPART_ENDUT_Y[part_indx]'] = ALLPART_ENDUT_Y(particles)
+  #evt_vars['ALLPART_ENDUT_Z[part_indx]'] = ALLPART_ENDUT_Z(particles)
+  #evt_vars['ALLPART_ENDUT_TX[part_indx]'] = ALLPART_ENDUT_TX(particles)
+  #evt_vars['ALLPART_ENDUT_TY[part_indx]'] = ALLPART_ENDUT_TY(particles)
+  #evt_vars['ALLPART_ENDUT_QOP[part_indx]'] = ALLPART_ENDUT_QOP(particles)
+  #evt_vars['ALLPART_ENDUT_XERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 0)
+  #evt_vars['ALLPART_ENDUT_YERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 1)
+  #evt_vars['ALLPART_ENDUT_TXERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 2)
+  #evt_vars['ALLPART_ENDUT_TYERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 3)
+  #evt_vars['ALLPART_ENDUT_QOPERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 4)
+  #P -> MCP
+  evt_vars['ALLPART_MC_ISPROMPT[part_indx]'] = ALLPART_MC_ISPROMPT(particles, MCTRUTH_parts)
+  evt_vars['ALLPART_TRUE_PV_X[part_indx]'] = ALLPART_TRUE_PV_X(particles, MCTRUTH_parts)
+  evt_vars['ALLPART_TRUE_PV_Y[part_indx]'] = ALLPART_TRUE_PV_Y(particles, MCTRUTH_parts)
+  evt_vars['ALLPART_TRUE_PV_Z[part_indx]'] = ALLPART_TRUE_PV_Z(particles, MCTRUTH_parts)
+  #P -> LONG LIVED ANCESTOR
+  evt_vars['ALLPART_LONGLIVED_ANCESTOR_ID[part_indx]']  = ALLPART_LONGLIVED_ANCESTOR_ID(particles, MCTRUTH_parts)
+  evt_vars['ALLPART_LONGLIVED_ANCESTOR_KEY[part_indx]'] = ALLPART_LONGLIVED_ANCESTOR_KEY(particles, MCTRUTH_parts)
+  #evt_vars['ALLPART_TRUE_ID[part_indx]'] = ALLPART_TRUE_ID(particles, MCTRUTH_parts)
+  #evt_vars['ALLPART_TRUE_KEY[part_indx]'] = ALLPART_TRUE_KEY(particles, MCTRUTH_parts)
+  #evt_vars['ALLPART_TRUE_ORGIN_X[part_indx]'] = ALLPART_TRUE_ORGIN_X(particles, MCTRUTH_parts)
+  #evt_vars['ALLPART_TRUE_ORGIN_Y[part_indx]'] = ALLPART_TRUE_ORGIN_Y(particles, MCTRUTH_parts)
+  #evt_vars['ALLPART_TRUE_ORGIN_Z[part_indx]'] = ALLPART_TRUE_ORGIN_Z(particles, MCTRUTH_parts)
+  #evt_vars['ALLPART_MCP_NGEN_MOTHER_ID[part_indx]'] = ALLPART_MCP_NGEN_MOTHER_ID(particles, 1, MCTRUTH_parts)
+  #evt_vars['ALLPART_MCP_NGEN_MOTHER_KEY[part_indx]'] = ALLPART_MCP_NGEN_MOTHER_KEY(particles, 1, MCTRUTH_parts)
+  #evt_vars['ALLPART_ID[part_indx]'] = ALLPART_ID(particles)
+  #evt_vars['ALLPART_HISTORY[part_indx]'] = ALLPART_HISTORY(particles)
+  #evt_vars['ALLPART_FLAG[part_indx]'] = ALLPART_FLAG(particles)
+
+  #get Bcand variables
+  evt_vars['ALLB_ENDVTX_CHI2[bcand_indx]'] = ALLB_ENDVTX_CHI2(Bcands)
+  evt_vars['ALLB_ENDVTX_NDOF[bcand_indx]'] = ALLB_ENDVTX_NDOF(Bcands)
+  evt_vars['ALLB_ENDVTX_X[bcand_indx]'] = ALLB_ENDVTX_X(Bcands)
+  evt_vars['ALLB_ENDVTX_Y[bcand_indx]'] = ALLB_ENDVTX_Y(Bcands)
+  evt_vars['ALLB_ENDVTX_Z[bcand_indx]'] = ALLB_ENDVTX_Z(Bcands)
+  evt_vars['ALLB_ENDVTX_XERR[bcand_indx]'] = ALLB_ENDVTX_POSERR(Bcands, 0)
+  evt_vars['ALLB_ENDVTX_YERR[bcand_indx]'] = ALLB_ENDVTX_POSERR(Bcands, 1)
+  evt_vars['ALLB_ENDVTX_ZERR[bcand_indx]'] = ALLB_ENDVTX_POSERR(Bcands, 2)
+  evt_vars['ALLB_PX[bcand_indx]'] = ALLB_PX(Bcands)
+  evt_vars['ALLB_PY[bcand_indx]'] = ALLB_PY(Bcands)
+  evt_vars['ALLB_PZ[bcand_indx]'] = ALLB_PZ(Bcands)
+  evt_vars['ALLB_PXERR[bcand_indx]'] = ALLB_MOMERR(Bcands, 0)
+  evt_vars['ALLB_PYERR[bcand_indx]'] = ALLB_MOMERR(Bcands, 1)
+  evt_vars['ALLB_PZERR[bcand_indx]'] = ALLB_MOMERR(Bcands, 2)
+  evt_vars['ALLB_ETA[bcand_indx]'] = ALLB_ETA(Bcands)
+  evt_vars['ALLB_PHI[bcand_indx]'] = ALLB_PHI(Bcands)
+  #P -> MCP
+  evt_vars['ALLB_TRUE_PV_X[bcand_indx]'] = ALLB_TRUE_PV_X(Bcands, MCTRUTH_Bs)
+  evt_vars['ALLB_TRUE_PV_Y[bcand_indx]'] = ALLB_TRUE_PV_Y(Bcands, MCTRUTH_Bs)
+  evt_vars['ALLB_TRUE_PV_Z[bcand_indx]'] = ALLB_TRUE_PV_Z(Bcands, MCTRUTH_Bs)
+  ##evt_vars['ALLB_TRUE_B0[bcand_indx]'] = ALLB_TRUE_ID(Bcands, MCTRUTH_Bs)
+  ##evt_vars['ALLB_TRUE_DST[bcand_indx]'] = ALLB_TRUE_CHILD1_ID(Bcands, MCTRUTH_Bs) #D*-
+  ##evt_vars['ALLB_TRUE_MU[bcand_indx]'] = ALLB_TRUE_CHILD2_ID(Bcands, MCTRUTH_Bs) #mu
+  ##evt_vars['ALLB_TRUE_D0[bcand_indx]'] = ALLB_TRUE_CHILD11_ID(Bcands, MCTRUTH_Bs) #D0
+  ##evt_vars['ALLB_TRUE_PI1[bcand_indx]'] = ALLB_TRUE_CHILD12_ID(Bcands, MCTRUTH_Bs) #pi
+  ##evt_vars['ALLB_TRUE_K[bcand_indx]'] = ALLB_TRUE_CHILD111_ID(Bcands, MCTRUTH_Bs) #K
+  ##evt_vars['ALLB_TRUE_PI2[bcand_indx]'] = ALLB_TRUE_CHILD112_ID(Bcands, MCTRUTH_Bs) #pi
+
+  #all basic particles of Bcands
+  evt_vars['ALLBASICS_KEY[basics_indx]'] = ALLPART_KEY(all_basics) #helpful to remove duplicates in particles
+  #evt_vars['ALLBASICS_ID[basics_indx]'] = ALLPART_ID(all_basics)
+  #evt_vars['ALLBASICS_TRUE_ID[basics_indx]'] = ALLPART_TRUE_ID(all_basics, MCTRUTH_Bs)
+  #evt_vars['ALLBASICS_TRUE_KEY[basics_indx]'] = ALLPART_TRUE_KEY(all_basics, MCTRUTH_Bs)
+
+  #get velo tracks variables
+  evt_vars['ALLVELOTRACKS_ETA[velo_trk_indx]'] = ALLVELOTRACKS_ETA(velo_tracks)
+  evt_vars['ALLVELOTRACKS_PHI[velo_trk_indx]'] = ALLVELOTRACKS_PHI(velo_tracks)
+  #FirstState
+  evt_vars['ALLVELOTRACKS_X[velo_trk_indx]'] = ALLVELOTRACKS_X(velo_tracks)
+  evt_vars['ALLVELOTRACKS_Y[velo_trk_indx]'] = ALLVELOTRACKS_Y(velo_tracks)
+  evt_vars['ALLVELOTRACKS_Z[velo_trk_indx]'] = ALLVELOTRACKS_Z(velo_tracks)
+  evt_vars['ALLVELOTRACKS_TX[velo_trk_indx]'] = ALLVELOTRACKS_TX(velo_tracks)
+  evt_vars['ALLVELOTRACKS_TY[velo_trk_indx]'] = ALLVELOTRACKS_TY(velo_tracks)
+  #throws error about pointer
+  #evt_vars['ALLVELOTRACKS_FIRSTMEAS_X[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_X(velo_tracks)
+  #evt_vars['ALLVELOTRACKS_FIRSTMEAS_Y[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_Y(velo_tracks)
+  #evt_vars['ALLVELOTRACKS_FIRSTMEAS_Z[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_Z(velo_tracks)
+  #evt_vars['ALLVELOTRACKS_FIRSTMEAS_XERR[velo_trk_indx]'] = ALLVELOTRACKS_POSERR(velo_tracks, 0)
+  #evt_vars['ALLVELOTRACKS_FIRSTMEAS_YERR[velo_trk_indx]'] = ALLVELOTRACKS_POSERR(velo_tracks, 1)
+  #evt_vars['ALLVELOTRACKS_FIRSTMEAS_ZERR[velo_trk_indx]'] = ALLVELOTRACKS_POSERR(velo_tracks, 2)
+  #evt_vars['ALLVELOTRACKS_ENDVELO_X[velo_trk_indx]'] = ALLVELOTRACKS_ENDVELO_X(velo_tracks)
+  #evt_vars['ALLVELOTRACKS_ENDVELO_Y[velo_trk_indx]'] = ALLVELOTRACKS_ENDVELO_Y(velo_tracks)
+  #evt_vars['ALLVELOTRACKS_ENDVELO_Z[velo_trk_indx]'] = ALLVELOTRACKS_ENDVELO_Z(velo_tracks)
+  #evt_vars['ALLVELOTRACKS_ENDVELO_XERR[velo_trk_indx]'] = ALLVELOTRACKS_ENDVELO_POSERR(velo_tracks, 0)
+  #evt_vars['ALLVELOTRACKS_ENDVELO_YERR[velo_trk_indx]'] = ALLVELOTRACKS_ENDVELO_POSERR(velo_tracks, 1)
+  #evt_vars['ALLVELOTRACKS_ENDVELO_ZERR[velo_trk_indx]'] = ALLVELOTRACKS_ENDVELO_POSERR(velo_tracks, 2)
+
+  # define tupling algorithm
+  tuple_file = FunTuple_Event(name="Tuple", tuple_name="EventInfo", variables=evt_vars)
+
+  #define algorithms
+  user_algorithms = {}
+  user_algorithms['Alg'] = [my_filter, truth_filter_event, tuple_file]
+  return user_algorithms
\ No newline at end of file
diff --git a/pvassoc/hlt2.py b/pvassoc/hlt2.py
new file mode 100755
index 0000000000..e02dded72d
--- /dev/null
+++ b/pvassoc/hlt2.py
@@ -0,0 +1,249 @@
+###############################################################################
+# (c) Copyright 2024 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Common HLT2 utilities for semileptonic lines
+"""
+from Hlt2Conf.lines.semileptonic.builders.charm_hadron_builder import (
+    make_Hc_to_nbody)  # type: ignore
+from GaudiKernel.SystemOfUnits import MeV, GeV, mm  # type: ignore
+from Hlt2Conf.algorithms_thor import ParticleCombiner  # type: ignore
+import Functors as F  # type: ignore
+from Hlt2Conf.lines.semileptonic.builders.base_builder import (  # type: ignore
+    make_candidate, make_kaons, make_pions, make_kaons_from_b,
+    make_tauons_hadronic_decay, make_muons_from_b)  # type: ignore
+from Hlt2Conf.standard_particles import (  # type: ignore
+    make_long_pions, make_up_pions, make_down_pions, make_resolved_pi0s,
+    make_merged_pi0s, make_photons, make_detached_mumu,
+    make_detached_dielectron_with_brem)
+from Hlt2Conf.algorithms_thor import ParticleContainersMerger  # type: ignore
+from Hlt2Conf.lines.semileptonic.builders import sl_line_prefilter # type: ignore
+from Moore.lines import Hlt2Line  # type: ignore
+
+
+def make_D0():
+    "Descriptor: [D0 -> K- pi+]cc"
+    # get kaons and pions for D0
+    daughter_p_min = 1. * GeV  # 2 * GeV 
+    daughter_pt_min = 50. * MeV  # 250 * MeV (could do 100)
+    daughter_mipchi2_min = 2.  # 4.
+    kaon_pid = (F.PID_K > 0)  # > 3
+    pion_pid = (F.PID_K < 40)  # < 20
+    with make_candidate.bind(p_min=daughter_p_min,
+                             pt_min=daughter_pt_min,
+                             mipchi2_min=daughter_mipchi2_min):
+        particles = [make_kaons(pid=kaon_pid), make_pions(pid=pion_pid)]
+
+    # set descriptor for D0
+    descriptor = '[D0 -> K- pi+]cc'
+
+    # set mass cuts for D0
+    D0_mass = 1864.84  # D0 mass
+    delta_mass = 120.
+    comb_m_min = (D0_mass - delta_mass) * MeV
+    comb_m_max = (D0_mass + delta_mass) * MeV
+    mother_m_min = None
+    mother_m_max = None
+    mother_pt_min = None
+    comb_pt_min = 500 * MeV # 2000 * MeV
+    comb_pt_any_min = None
+    comb_pt_sum_min = None
+    comb_doca_max = 1.0 * mm # 0.1 * mm
+    comb_docachi2_max = None
+    vchi2pdof_max = 12 # 6
+    bpvdira_min = 0.98 # 0.99
+    bpvfdchi2_min = 10 # 25
+    bpvvdz_min = None
+
+    # get D0 to Kpi
+    D0s = make_Hc_to_nbody(particles,
+                           descriptor,
+                           comb_m_min,
+                           comb_m_max,
+                           mother_m_min,
+                           mother_m_max,
+                           mother_pt_min,
+                           name='D0ToKpi_combiner',
+                           comb_pt_min=comb_pt_min,
+                           comb_pt_any_min=comb_pt_any_min,
+                           comb_pt_sum_min=comb_pt_sum_min,
+                           comb_doca_max=comb_doca_max,
+                           comb_docachi2_max=comb_docachi2_max,
+                           vchi2pdof_max=vchi2pdof_max,
+                           bpvdira_min=bpvdira_min,
+                           bpvfdchi2_min=bpvfdchi2_min,
+                           bpvvdz_min=bpvvdz_min)
+    return D0s
+
+
+def make_Dst():
+    "Descriptor: [D*(2010)+ -> D0 pi+]cc"
+    # get D0 and pions for D*(2010)+
+    daughter_p_min = 1. * GeV  # 2 * GeV
+    daughter_pt_min = 50. * MeV  # 250 * MeV (could do 100)
+    daughter_mipchi2_min = 4.  # 4.
+    pion_pid = (F.PID_K < 40)  # < 20
+    with make_candidate.bind(p_min=daughter_p_min,
+                             pt_min=daughter_pt_min,
+                             mipchi2_min=daughter_mipchi2_min):
+        pions = make_pions(pid=pion_pid)
+    particles = [make_D0(), pions]
+
+    # make descriptor for D*(2010)+
+    descriptor = '[D*(2010)+ -> D0 pi+]cc'
+
+    # apply some DOCA cuts on D0 and pions
+    cut_combination = F.ALL
+    Dsts = ParticleCombiner(Inputs=particles,
+                           name='DstToD0pi_combiner',
+                           DecayDescriptor=descriptor,
+                           CombinationCut=cut_combination,
+                           CompositeCut=F.ALL,
+                           ParticleCombiner="ParticleVertexFitter")
+    return Dsts
+
+def make_loose_mu():
+    "Descriptor: [mu+]cc"
+    return make_muons_from_b(
+      p_min=1. * GeV,  # original 2 * GeV, muons-for-b is 6 * GeV, tau-to-mu is 3 * GeV
+      pt_min=None,  # original 250 * MeV, muons-for-b is 1 * GeV, tau-to-mu is None
+      mipchi2_min=2.,  # original 4., muons-for-b is 9., tau-to-mu is 16
+      mip_min=0,  # original 0, muons-for-b is 0
+      pid=(F.PID_MU > -8.0))  # original None, muons-for-b is > 0.0, tau-to-mu is > 0.0
+
+def make_tau_to_3pi():
+    "Descriptor: [tau+ -> pi- pi+ pi+]cc"
+    return make_tauons_hadronic_decay(
+        name='HadronicTauTo3Pi_combiner',
+        comb_m_min=100. * MeV,  # original 400 * MeV
+        comb_m_max=5000. * MeV,  # original 3500 * MeV
+        comb_pt_any_max=500 * MeV,  # original 300 * MeV
+        comb_doca_max=0.6 * mm,  # original 0.15 * mm
+        mipchi2_min=5,  # original 15
+        bpvdira_min=0.98,  # original 0.99
+        vchi2_max=25,  # original 16
+        m_min=100. * MeV,  # original 400 * MeV
+        m_max=5000. * MeV,  # original 3500 * MeV
+        twobody_m_max=2500 * MeV)  # original 1670 * MeV
+
+def make_jpsi_mumu():
+    "Descriptor: [J/psi(1S) -> mu+ mu-]cc"
+    return make_detached_mumu(opposite_sign=False)
+
+def make_jpsi_ee():
+    "Descriptor: [J/psi(1S) -> e+ e-]cc"
+    return make_detached_dielectron_with_brem(opposite_sign=False)
+
+def make_kaons_for_b():
+    "Descriptor: [K+]cc"
+    return make_kaons_from_b(p_min=3000. * MeV,
+                             pt_min=400. * MeV,
+                             mipchi2_min=9.,
+                             pid=(F.PID_K > 5.),
+                             mip_min=0.)
+
+def make_b_to_Dstpmu():
+    "Descriptor: [B~0 -> D*(2010)+ mu-]cc"
+    particles = [make_Dst(), make_loose_mu()]
+
+    # make descriptor for B+
+    descriptor = '[B~0 -> D*(2010)+ mu-]cc'
+
+    # apply some DOCA cuts on D*(2010)+ and muons
+    #cut_combination = F.require_all(F.MAXDOCA < 8.0, F.MAXDOCACHI2 < 20)
+    cut_combination = F.require_all(F.MAXDOCA < 16.0, F.MAXDOCACHI2 < 30)
+    return ParticleCombiner(Inputs=particles,
+                              name='BToDstpmu_combiner',
+                              DecayDescriptor=descriptor,
+                              CombinationCut=cut_combination,
+                              CompositeCut=F.ALL,
+                              ParticleCombiner="ParticleVertexFitter")
+
+def make_b_to_Dsttau_hadronic():
+    "Descriptor: [B+ -> D~0 tau+]cc"
+    # get D0 and tauons for B+
+    particles = [make_D0(), make_tau_to_3pi()]
+
+    # make descriptor for B+
+    descriptor = '[B+ -> D~0 tau+]cc'
+
+    # apply some DOCA cuts on D0 and tauons
+    #cut_combination = F.require_all(F.MAXDOCA < 8.0, F.MAXDOCACHI2 < 20)
+    cut_combination = F.require_all(F.MAXDOCA < 16.0, F.MAXDOCACHI2 < 30)
+    return ParticleCombiner(Inputs=particles,
+                              name='BuToD0tau_combiner',
+                              DecayDescriptor=descriptor,
+                              CombinationCut=cut_combination,
+                              CompositeCut=F.ALL,
+                              ParticleCombiner="ParticleVertexFitter")
+
+def make_b_to_jpsik(jpsi_final_state):
+    "Descriptor: [B+ -> J/psi(1S) K+]cc"
+    # get J/psi(1S) and kaons for B+
+    if jpsi_final_state == 'ee':
+        jpsi = make_jpsi_ee()
+    elif jpsi_final_state == 'mumu':
+        jpsi = make_jpsi_mumu()
+    else:
+        raise ValueError(f"Jpsi final state {jpsi_final_state} not supported")
+
+    kaons = make_kaons_for_b()
+    particles = [jpsi, kaons]
+
+    # make descriptor for B+
+    descriptor = '[B+ -> J/psi(1S) K+]cc'
+
+    # apply some DOCA cuts on J/psi(1S) and kaons
+    cut_combination = F.require_all(F.MAXDOCA < 8.0, F.MAXDOCACHI2 < 20)
+    return ParticleCombiner(Inputs=particles,
+                              name='BToJpsik_combiner',
+                              DecayDescriptor=descriptor,
+                              CombinationCut=cut_combination,
+                              CompositeCut=F.ALL,
+                              ParticleCombiner="ParticleVertexFitter")
+
+def make_b(decay_channel):
+    if decay_channel == 'DstMu' or decay_channel == 'DstTau_Lep':
+        Bcands = make_b_to_Dstpmu()
+    elif decay_channel == 'D0Tau_Had':
+        Bcands = make_b_to_Dsttau_hadronic()
+    elif decay_channel == 'JpsiK_E':
+        Bcands = make_b_to_jpsik('ee')
+    elif decay_channel == 'JpsiK_Mu':
+        Bcands = make_b_to_jpsik('mumu')
+    else:
+        raise ValueError(f"Decay channel {decay_channel} not supported")
+
+    return Bcands
+
+def make_my_lines(decay_channel):
+    HLT2LINE = f'Hlt2SLB_BTo{decay_channel}'
+    def hlt2_lines(name=HLT2LINE, prescale=1):
+        Bcands = make_b(decay_channel)
+        long_pions = make_long_pions()
+        up_pions = make_up_pions()
+        down_pions = make_down_pions()
+        pions = ParticleContainersMerger([long_pions, up_pions, down_pions],
+                                         name='Pions_combiner')
+        resolved_pi0s = make_resolved_pi0s()
+        merged_pi0s = make_merged_pi0s()
+        photons = make_photons()
+        extra_output = [('ExtraPions', pions),
+                        ('ExtraResolvedPi0s', resolved_pi0s),
+                        ('ExtraMergedPi0s', merged_pi0s),
+                        ('ExtraPhotons', photons)]
+        return Hlt2Line(name=name,
+                        prescale=prescale,
+                        algs=sl_line_prefilter() + [Bcands],
+                        extra_outputs=extra_output, 
+                        persistreco=True)
+
+    lines = [hlt2_lines()]
+    return lines
\ No newline at end of file
diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
new file mode 100644
index 0000000000..a337e9b484
--- /dev/null
+++ b/pvassoc/info.yaml
@@ -0,0 +1,69 @@
+defaults:
+  wg: SL
+  automatically_configure: no 
+  inform:
+    - abhijit.mathad@cern.ch
+
+{%- set datasets = [
+('DstMu',  11574020)
+('DstTau_Lep', 11574010)
+('DstTau_Had', 12562000)
+('JpsiK_Mu', 12143001)
+('JpsiK_E', 12153001)
+]%}
+
+{%- for sample, evtID in datasets %}
+    {%- for polarity, tagpol in [('MagDown', 'md'), ('MagUp', 'mu')] %}
+
+Hlt1{{sample}}_{{polarity}}:
+  application: Moore/v55r9@x86_64_v2-el9-gcc13+detdesc-opt
+  input:
+    bk_query: /MC/Dev/Beam6800GeV-expected-2024-{{polarity}}-Nu7.6-25ns-Pythia8/Sim10c/{{evtID}}/DIGI
+  output: MYHLT1.dst
+  options:
+    entrypoint: run_hlt1:main
+    extra_options:
+      input_raw_format: 0.5
+      conddb_tag: sim-20231017-vc-{{tagpol}}100
+      dddb_tag: dddb-20231017
+      input_type: ROOT 
+      output_type: ROOT
+      simulation: True
+      data_type: "Upgrade"
+      scheduler_legacy_mode: False
+
+Hlt2{{sample}}_{{polarity}}:
+  application: Moore/v55r9@x86_64_v2-el9-gcc13+detdesc-opt
+  input:
+    job_name: Hlt1{{sample}}_{{polarity}}
+  output: MYHLT2.dst
+  options:
+    entrypoint: Dzl.run_hlt2:main_{{sample}}
+    extra_options:
+      input_raw_format: 0.5
+      conddb_tag: sim-20231017-vc-{{tagpol}}100
+      dddb_tag: dddb-20231017
+      input_type: ROOT 
+      output_type: ROOT
+      simulation: True
+      data_type: "Upgrade"
+      scheduler_legacy_mode: False
+
+DV{{sample}}_{{polarity}}:
+  application: DaVinci/v64r6@x86_64_v2-el9-gcc13+detdesc-opt
+  input:
+    job_name: Hlt2{{sample}}_{{polarity}}
+  output: MYNTUPLE.root
+  options:
+    entrypoint: Dzl.run_dv:main
+    extra_options:
+      input_raw_format: 0.5
+      input_type: ROOT
+      simulation: True
+      data_type: "Upgrade"
+      conddb_tag: sim-20231017-vc-{{tagpol}}100
+      dddb_tag: dddb-20231017
+      input_process: "Hlt2"
+    
+    {%- endfor %}
+{%- endfor %}
\ No newline at end of file
diff --git a/pvassoc/run_dv.py b/pvassoc/run_dv.py
new file mode 100755
index 0000000000..e9d9048bce
--- /dev/null
+++ b/pvassoc/run_dv.py
@@ -0,0 +1,21 @@
+###############################################################################
+# (c) Copyright 2024 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+from DaVinci import Options
+from pvassoc.dv import get_user_algs
+from DaVinci import make_config
+
+def main(options: Options):
+  """
+  decay_channel: decay channel to be used in the lines. 
+    Options: DstMu, DstTau_Lep, D0Tau_Had, JpsiK_E, JpsiK_Mu
+  """
+  user_algorithms = get_user_algs(decay_channel='DstMu')
+  return make_config(options, user_algorithms)
diff --git a/pvassoc/run_hlt1.py b/pvassoc/run_hlt1.py
new file mode 100755
index 0000000000..ebe98b7a71
--- /dev/null
+++ b/pvassoc/run_hlt1.py
@@ -0,0 +1,42 @@
+###############################################################################
+# (c) Copyright 2024 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Configures running HLT1 via Moore.
+"""
+
+from Moore import Options  # type: ignore
+from Moore.config import allen_control_flow  # type: ignore
+from RecoConf.hlt1_allen import allen_gaudi_config, get_allen_line_names  # type: ignore
+from PyConf.application import configure_input, configure  # type: ignore
+
+# WITH UT
+def main(options: Options):
+    """
+    Configures algorithm running of HLT1 via Moore to be passed to Analysis Productions.
+    """
+    config = configure_input(options)
+    with allen_gaudi_config.bind(sequence="hlt1_pp_forward_then_matching"):
+        line_names = get_allen_line_names()
+        allen_node = allen_control_flow(options)
+        config.update(configure(options, allen_node))
+    return config
+
+# WITHOUT UT
+#def main_without_ut(options: Options):
+#    """
+#    Configures algorithm running of HLT1 via Moore to be passed to Analysis Productions.
+#    """
+#    config = configure_input(options)
+#    with allen_gaudi_config.bind(sequence="hlt1_pp_matching_no_ut_1000KHz"):
+#        line_names = get_allen_line_names()
+#        allen_node = allen_control_flow(options)
+#        config.update(configure(options, allen_node))
+#    return config
\ No newline at end of file
diff --git a/pvassoc/run_hlt2.py b/pvassoc/run_hlt2.py
new file mode 100755
index 0000000000..4978389827
--- /dev/null
+++ b/pvassoc/run_hlt2.py
@@ -0,0 +1,91 @@
+###############################################################################
+# (c) Copyright 2024 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Configures running HLT2 via Moore.
+"""
+
+from pvassoc.hlt2 import make_my_lines
+from Moore import Options, run_moore
+from RecoConf.hlt2_global_reco import reconstruction as hlt2_reconstruction, make_light_reco_pr_kf, make_light_reco_pr_kf_without_UT
+from RecoConf.global_tools import stateProvider_with_simplified_geom, trackMasterExtrapolator_with_simplified_geom
+from RecoConf.reconstruction_objects import reconstruction
+
+def make_lines_DstMu():
+  """
+  decay_channel: decay channel to be used in the lines. 
+    Options: DstMu, DstTau_Lep, D0Tau_Had, JpsiK_E, JpsiK_Mu
+  """
+  return make_my_lines(decay_channel='DstMu')
+
+def make_lines_DstTau_Lep():
+  return make_my_lines(decay_channel='DstTau_Lep')
+
+def make_lines_D0Tau_Had():
+  return make_my_lines(decay_channel='D0Tau_Had')
+
+def make_lines_JpsiK_E():
+  return make_my_lines(decay_channel='JpsiK_E')
+
+def make_lines_JpsiK_Mu():
+  return make_my_lines(decay_channel='JpsiK_Mu')
+
+# WITH UT
+public_tools = [trackMasterExtrapolator_with_simplified_geom(), stateProvider_with_simplified_geom()]
+def main_DstMu(options: Options):
+  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf):
+    config = run_moore(options, make_streams=make_lines_DstMu, public_tools=public_tools)
+    return config
+
+def main_DstTau_Lep(options: Options):
+  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf):
+    config = run_moore(options, make_streams=make_lines_DstTau_Lep, public_tools=public_tools)
+    return config
+  
+def main_D0Tau_Had(options: Options):
+  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf):
+    config = run_moore(options, make_streams=make_lines_D0Tau_Had, public_tools=public_tools)
+    return config
+  
+def main_JpsiK_E(options: Options):
+  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf):
+    config = run_moore(options, make_streams=make_lines_JpsiK_E, public_tools=public_tools)
+    return config
+  
+def main_JpsiK_Mu(options: Options):
+  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf):
+    config = run_moore(options, make_streams=make_lines_JpsiK_Mu, public_tools=public_tools)
+    return config
+  
+# Without UT
+#def main_without_ut_DstTau_Lep(options: Options):
+#  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf_without_UT):
+#    config = run_moore(options, make_streams=make_lines_DstTau_Lep, public_tools=public_tools)
+#    return config
+#  
+#def main_without_ut_D0Tau_Had(options: Options):
+#  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf_without_UT):
+#    config = run_moore(options, make_streams=make_lines_D0Tau_Had, public_tools=public_tools)
+#    return config
+#  
+#def main_without_ut_JpsiK_E(options: Options):
+#  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf_without_UT):
+#    config = run_moore(options, make_streams=make_lines_JpsiK_E, public_tools=public_tools)
+#    return config
+#  
+#def main_without_ut_DstMu(options: Options):
+#  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf_without_UT):
+#    config = run_moore(options, make_streams=make_lines_DstMu, public_tools=public_tools)
+#    return config
+#  
+#def main_without_ut_JpsiK_Mu(options: Options):
+#  with reconstruction.bind(from_file=False), hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf_without_UT):
+#    config = run_moore(options, make_streams=make_lines_JpsiK_Mu, public_tools=public_tools)
+#    return config
-- 
GitLab


From 7787e4ea16852878c7d59b559ebe71ce260ddedf Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Tue, 18 Jun 2024 18:10:56 +0200
Subject: [PATCH 02/18] simplify script

---
 pvassoc/info.yaml | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index a337e9b484..f088767a7c 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -6,10 +6,10 @@ defaults:
 
 {%- set datasets = [
 ('DstMu',  11574020)
-('DstTau_Lep', 11574010)
-('DstTau_Had', 12562000)
-('JpsiK_Mu', 12143001)
-('JpsiK_E', 12153001)
+#('DstTau_Lep', 11574010)
+#('DstTau_Had', 12562000)
+#('JpsiK_Mu', 12143001)
+#('JpsiK_E', 12153001)
 ]%}
 
 {%- for sample, evtID in datasets %}
@@ -66,4 +66,4 @@ DV{{sample}}_{{polarity}}:
       input_process: "Hlt2"
     
     {%- endfor %}
-{%- endfor %}
\ No newline at end of file
+{%- endfor %}
-- 
GitLab


From 08ccd72592574da194c1d3e0e52ea5cc0e63d5a8 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Tue, 18 Jun 2024 18:17:09 +0200
Subject: [PATCH 03/18] simplify script

---
 pvassoc/info.yaml | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index f088767a7c..b00555f76a 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -5,15 +5,15 @@ defaults:
     - abhijit.mathad@cern.ch
 
 {%- set datasets = [
-('DstMu',  11574020)
-#('DstTau_Lep', 11574010)
-#('DstTau_Had', 12562000)
-#('JpsiK_Mu', 12143001)
-#('JpsiK_E', 12153001)
-]%}
+    ('DstMu',  11574020)
+    #('DstTau_Lep', 11574010)
+    #('DstTau_Had', 12562000)
+    #('JpsiK_Mu', 12143001)
+    #('JpsiK_E', 12153001)
+] %}
 
 {%- for sample, evtID in datasets %}
-    {%- for polarity, tagpol in [('MagDown', 'md'), ('MagUp', 'mu')] %}
+  {%- for polarity, tagpol in [('MagDown', 'md'), ('MagUp', 'mu')] %}
 
 Hlt1{{sample}}_{{polarity}}:
   application: Moore/v55r9@x86_64_v2-el9-gcc13+detdesc-opt
@@ -64,6 +64,5 @@ DV{{sample}}_{{polarity}}:
       conddb_tag: sim-20231017-vc-{{tagpol}}100
       dddb_tag: dddb-20231017
       input_process: "Hlt2"
-    
-    {%- endfor %}
+  {%- endfor %}
 {%- endfor %}
-- 
GitLab


From 2ae993e13a643d69ff4cf7f0677851f98bd9ebf4 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Tue, 18 Jun 2024 18:19:19 +0200
Subject: [PATCH 04/18] simplify script

---
 pvassoc/info.yaml | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index b00555f76a..3aa89032ce 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -6,10 +6,6 @@ defaults:
 
 {%- set datasets = [
     ('DstMu',  11574020)
-    #('DstTau_Lep', 11574010)
-    #('DstTau_Had', 12562000)
-    #('JpsiK_Mu', 12143001)
-    #('JpsiK_E', 12153001)
 ] %}
 
 {%- for sample, evtID in datasets %}
-- 
GitLab


From 85e87d70bdac7e1eb1a1b384810b6523a8dfd07a Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Tue, 18 Jun 2024 18:25:15 +0200
Subject: [PATCH 05/18] fix bug

---
 pvassoc/info.yaml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index 3aa89032ce..3a75d6f176 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -17,7 +17,7 @@ Hlt1{{sample}}_{{polarity}}:
     bk_query: /MC/Dev/Beam6800GeV-expected-2024-{{polarity}}-Nu7.6-25ns-Pythia8/Sim10c/{{evtID}}/DIGI
   output: MYHLT1.dst
   options:
-    entrypoint: run_hlt1:main
+    entrypoint: pvassoc.run_hlt1:main
     extra_options:
       input_raw_format: 0.5
       conddb_tag: sim-20231017-vc-{{tagpol}}100
@@ -34,7 +34,7 @@ Hlt2{{sample}}_{{polarity}}:
     job_name: Hlt1{{sample}}_{{polarity}}
   output: MYHLT2.dst
   options:
-    entrypoint: Dzl.run_hlt2:main_{{sample}}
+    entrypoint: pvassoc.run_hlt2:main_{{sample}}
     extra_options:
       input_raw_format: 0.5
       conddb_tag: sim-20231017-vc-{{tagpol}}100
@@ -51,7 +51,7 @@ DV{{sample}}_{{polarity}}:
     job_name: Hlt2{{sample}}_{{polarity}}
   output: MYNTUPLE.root
   options:
-    entrypoint: Dzl.run_dv:main
+    entrypoint: pvassoc.run_dv:main
     extra_options:
       input_raw_format: 0.5
       input_type: ROOT
-- 
GitLab


From 25a31710325e1ded4c4351c31d671fb5e5d1f035 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Tue, 18 Jun 2024 22:11:04 +0200
Subject: [PATCH 06/18] fix bug

---
 pvassoc/hlt2.py   | 3 ++-
 pvassoc/info.yaml | 6 +++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/pvassoc/hlt2.py b/pvassoc/hlt2.py
index e02dded72d..e6654ff0fa 100755
--- a/pvassoc/hlt2.py
+++ b/pvassoc/hlt2.py
@@ -201,7 +201,8 @@ def make_b_to_jpsik(jpsi_final_state):
     descriptor = '[B+ -> J/psi(1S) K+]cc'
 
     # apply some DOCA cuts on J/psi(1S) and kaons
-    cut_combination = F.require_all(F.MAXDOCA < 8.0, F.MAXDOCACHI2 < 20)
+    #cut_combination = F.require_all(F.MAXDOCA < 8.0, F.MAXDOCACHI2 < 20)
+    cut_combination = F.require_all(F.MAXDOCA < 16.0, F.MAXDOCACHI2 < 30)
     return ParticleCombiner(Inputs=particles,
                               name='BToJpsik_combiner',
                               DecayDescriptor=descriptor,
diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index 3a75d6f176..8d96fbe774 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -5,7 +5,11 @@ defaults:
     - abhijit.mathad@cern.ch
 
 {%- set datasets = [
-    ('DstMu',  11574020)
+    ('DstMu',  11574020),
+    ('DstTau_Lep', 11574010),
+    ('DstTau_Had', 12562000),
+    ('JpsiK_Mu', 12143001),
+    ('JpsiK_E', 12153001)
 ] %}
 
 {%- for sample, evtID in datasets %}
-- 
GitLab


From 18cf73f3d8e6b755d7ab79cbf07dd0f253129b22 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Wed, 19 Jun 2024 10:38:41 +0200
Subject: [PATCH 07/18] fix bug

---
 pvassoc/hlt2.py   | 4 ++--
 pvassoc/info.yaml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/pvassoc/hlt2.py b/pvassoc/hlt2.py
index e6654ff0fa..ffe4cf2d41 100755
--- a/pvassoc/hlt2.py
+++ b/pvassoc/hlt2.py
@@ -166,7 +166,7 @@ def make_b_to_Dstpmu():
                               CompositeCut=F.ALL,
                               ParticleCombiner="ParticleVertexFitter")
 
-def make_b_to_Dsttau_hadronic():
+def make_b_to_D0tau_hadronic():
     "Descriptor: [B+ -> D~0 tau+]cc"
     # get D0 and tauons for B+
     particles = [make_D0(), make_tau_to_3pi()]
@@ -214,7 +214,7 @@ def make_b(decay_channel):
     if decay_channel == 'DstMu' or decay_channel == 'DstTau_Lep':
         Bcands = make_b_to_Dstpmu()
     elif decay_channel == 'D0Tau_Had':
-        Bcands = make_b_to_Dsttau_hadronic()
+        Bcands = make_b_to_D0tau_hadronic()
     elif decay_channel == 'JpsiK_E':
         Bcands = make_b_to_jpsik('ee')
     elif decay_channel == 'JpsiK_Mu':
diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index 8d96fbe774..4205db05c2 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -7,7 +7,7 @@ defaults:
 {%- set datasets = [
     ('DstMu',  11574020),
     ('DstTau_Lep', 11574010),
-    ('DstTau_Had', 12562000),
+    ('D0Tau_Had', 12562000),
     ('JpsiK_Mu', 12143001),
     ('JpsiK_E', 12153001)
 ] %}
-- 
GitLab


From d598f54ebf615cff009f364d9f334de758f0779e Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Wed, 19 Jun 2024 11:15:24 +0200
Subject: [PATCH 08/18] fix bug

---
 pvassoc/info.yaml |  2 +-
 pvassoc/run_dv.py | 18 +++++++++++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index 4205db05c2..c022da3913 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -55,7 +55,7 @@ DV{{sample}}_{{polarity}}:
     job_name: Hlt2{{sample}}_{{polarity}}
   output: MYNTUPLE.root
   options:
-    entrypoint: pvassoc.run_dv:main
+    entrypoint: pvassoc.run_dv:main_{{sample}}
     extra_options:
       input_raw_format: 0.5
       input_type: ROOT
diff --git a/pvassoc/run_dv.py b/pvassoc/run_dv.py
index e9d9048bce..7ecfa0a288 100755
--- a/pvassoc/run_dv.py
+++ b/pvassoc/run_dv.py
@@ -12,10 +12,26 @@ from DaVinci import Options
 from pvassoc.dv import get_user_algs
 from DaVinci import make_config
 
-def main(options: Options):
+def main_DstMu(options: Options):
   """
   decay_channel: decay channel to be used in the lines. 
     Options: DstMu, DstTau_Lep, D0Tau_Had, JpsiK_E, JpsiK_Mu
   """
   user_algorithms = get_user_algs(decay_channel='DstMu')
   return make_config(options, user_algorithms)
+
+def main_DstTau_Lep(options: Options):
+  user_algorithms = get_user_algs(decay_channel='DstTau_Lep')
+  return make_config(options, user_algorithms)
+
+def main_D0Tau_Had(options: Options):
+  user_algorithms = get_user_algs(decay_channel='D0Tau_Had')
+  return make_config(options, user_algorithms)
+
+def main_JpsiK_E(options: Options):
+  user_algorithms = get_user_algs(decay_channel='JpsiK_E')
+  return make_config(options, user_algorithms)
+
+def main_JpsiK_Mu(options: Options):
+  user_algorithms = get_user_algs(decay_channel='JpsiK_Mu')
+  return make_config(options, user_algorithms)
\ No newline at end of file
-- 
GitLab


From b41fa5f52b20000bc811807ac51407e4e9859c0d Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Wed, 19 Jun 2024 12:04:27 +0200
Subject: [PATCH 09/18] fix bug

---
 pvassoc/dv.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
index 074108dbd6..d81e5e81cf 100755
--- a/pvassoc/dv.py
+++ b/pvassoc/dv.py
@@ -164,7 +164,7 @@ def get_user_algs(decay_channel):
   if decay_channel == 'DstMu' or decay_channel == 'DstTau_Lep':
     #Bd -> D*- mu+ nu
     B_ID = 511
-  elif decay_channel == 'DstTau_Had' or decay_channel == 'JpsiK_E' or decay_channel == 'JpsiK_Mu':
+  elif decay_channel == 'D0Tau_Had' or decay_channel == 'JpsiK_E' or decay_channel == 'JpsiK_Mu':
     #Bu -> D*- tau+ nu or Bu -> Jpsi K 
     B_ID = 521
   else:
@@ -339,4 +339,4 @@ def get_user_algs(decay_channel):
   #define algorithms
   user_algorithms = {}
   user_algorithms['Alg'] = [my_filter, truth_filter_event, tuple_file]
-  return user_algorithms
\ No newline at end of file
+  return user_algorithms
-- 
GitLab


From 3e82a449210d21b8b17cd80323dd46c2fa562cc9 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Thu, 11 Jul 2024 14:57:41 +0200
Subject: [PATCH 10/18] update scripts

---
 pvassoc/dv.py   | 263 ++++++++++++++++++++++++++++--------------------
 pvassoc/hlt2.py |   6 +-
 2 files changed, 156 insertions(+), 113 deletions(-)

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
index d81e5e81cf..ff31495a0a 100755
--- a/pvassoc/dv.py
+++ b/pvassoc/dv.py
@@ -22,6 +22,7 @@ from GaudiKernel import SystemOfUnits  # type: ignore[import]
 from RecoConf.reconstruction_objects import make_tracks  # type: ignore[import]
 
 #Variables for pvs
+ALLPV_KEY       = lambda Vertices: F.MAP(F.OBJECT_KEY) @ F.TES(Vertices)
 ALLPV_CHI2      = lambda Vertices: F.MAP(F.CHI2) @ F.TES(Vertices)
 ALLPV_NDOF      = lambda Vertices: F.MAP(F.NDOF) @ F.TES(Vertices)  # Can infer nVelo tracks from this
 ALLPV_X         = lambda Vertices: F.MAP(F.X_COORDINATE @ F.POSITION) @ F.TES(Vertices)
@@ -36,6 +37,8 @@ ALLPART_PX       = lambda particles: F.MAP(F.PX) @ F.TES(particles)
 ALLPART_PY       = lambda particles: F.MAP(F.PY) @ F.TES(particles)
 ALLPART_PZ       = lambda particles: F.MAP(F.PZ) @ F.TES(particles)
 ALLPART_MOMERR   = lambda particles, indx_i: F.MAP(F.CALL(indx_i, indx_i) @ F.THREE_MOM_COV_MATRIX) @ F.TES(particles)
+ALLPART_ENERGY   = lambda particles: F.MAP(F.ENERGY) @ F.TES(particles)
+ALLPART_MASS     = lambda particles: F.MAP(F.MASS) @ F.TES(particles)
 ALLPART_ETA      = lambda particles: F.MAP(F.ETA) @ F.TES(particles)
 ALLPART_PHI      = lambda particles: F.MAP(F.PHI) @ F.TES(particles)
 ALLPART_PIDPI    = lambda particles: F.MAP(F.PID_PI) @ F.TES(particles)
@@ -48,13 +51,20 @@ ALLPART_TRACK_CHI2     = lambda particles: F.MAP(F.CHI2 @ F.TRACK) @ F.TES(parti
 ALLPART_TRACK_NDOF     = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.NDOF @ F.TRACK) @ F.TES(particles)
 ALLPART_TRACK_TYPE     = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.CAST_TO_INT @ F.TRACKTYPE @ F.TRACK) @ F.TES(particles)
 ALLPART_TRACK_GHOSTPROB= lambda particles: F.MAP(F.GHOSTPROB) @ F.TES(particles)
+#get the BPV information for particles
+ALLPART_BPV_KEY = lambda particles, pvs: F.MAP(F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.BPV(pvs)) @ F.TES(particles)
+ALLPART_BPV_X  = lambda particles, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVX(pvs)) @ F.TES(particles)
+ALLPART_BPV_Y  = lambda particles, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVY(pvs)) @ F.TES(particles)
+ALLPART_BPV_Z  = lambda particles, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVZ(pvs)) @ F.TES(particles)
+ALLPART_BPV_IP = lambda particles, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVIP(pvs)) @ F.TES(particles)
+ALLPART_BPV_IPCHI2 = lambda particles, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVIPCHI2(pvs)) @ F.TES(particles)
 ## particle has track but not a closest to beam state, so throws an error (Should this be an error at all?)
-#ALLPART_CLOSESTTOBEAM_X = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
-#ALLPART_CLOSESTTOBEAM_Y = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
-#ALLPART_CLOSESTTOBEAM_TX = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TX @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
-#ALLPART_CLOSESTTOBEAM_TY = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TY @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
-#ALLPART_CLOSESTTOBEAM_QOP = lambda particles:F.MAP(F.VALUE_OR(F.NaN) @ F.QOVERP @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
-#ALLPART_CLOSESTTOBEAM_STATEERR = lambda particles, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+ALLPART_CLOSESTTOBEAM_X = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+ALLPART_CLOSESTTOBEAM_Y = lambda particles:  F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+ALLPART_CLOSESTTOBEAM_TX = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TX @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+ALLPART_CLOSESTTOBEAM_TY = lambda particles: F.MAP(F.VALUE_OR(F.NaN) @ F.TY @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+ALLPART_CLOSESTTOBEAM_QOP = lambda particles:F.MAP(F.VALUE_OR(F.NaN) @ F.QOVERP @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
+ALLPART_CLOSESTTOBEAM_STATEERR = lambda particles, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("ClosestToBeam") @ F.TRACK) @ F.TES(particles)
 ALLPART_FIRSTMEAS_X = lambda particles:   F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
 ALLPART_FIRSTMEAS_Y = lambda particles:   F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
 ALLPART_FIRSTMEAS_Z = lambda particles:   F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement") @ F.TRACK) @ F.TES(particles)
@@ -84,18 +94,26 @@ ALLPART_LONGLIVED_ANCESTOR_KEY = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1)
 #ALLPART_LONGLIVED_ANCESTOR_PVX = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VX @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
 #ALLPART_LONGLIVED_ANCESTOR_PVY = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VY @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
 #ALLPART_LONGLIVED_ANCESTOR_PVZ = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VZ @ LONGLIVED_ANCESTOR)) @ F.TES(particles)
-#ALLPART_TRUE_ID  = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID)) @ F.TES(particles)
-#ALLPART_TRUE_KEY = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY)) @ F.TES(particles)
-#ALLPART_TRUE_ORGIN_X = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VX)) @ F.TES(particles)
-#ALLPART_TRUE_ORGIN_Y = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VY)) @ F.TES(particles)
-#ALLPART_TRUE_ORGIN_Z = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VZ)) @ F.TES(particles)
-#ALLPART_MCP_NGEN_MOTHER_ID  = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.MC_MOTHER(ngen, F.PARTICLE_ID))) @ F.TES(particles)
-#ALLPART_MCP_NGEN_MOTHER_KEY = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.MC_MOTHER(ngen, F.OBJECT_KEY))) @ F.TES(particles)
-#ALLPART_ID        = lambda particles: F.MAP(F.VALUE_OR(0) @ F.PARTICLE_ID) @ F.TES(particles)
+ALLPART_TRUE_ID  = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID)) @ F.TES(particles)
+ALLPART_TRUE_KEY = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY)) @ F.TES(particles)
+ALLPART_TRUE_PX  = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.PX)) @ F.TES(particles)
+ALLPART_TRUE_PY  = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.PY)) @ F.TES(particles)
+ALLPART_TRUE_PZ  = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.PZ)) @ F.TES(particles)
+ALLPART_TRUE_ENERGY = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.ENERGY)) @ F.TES(particles)
+ALLPART_TRUE_MASS = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MASS)) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_KEY  = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY) @ F.MC_PRIMARYVERTEX) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_X = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VX)) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_Y = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VY)) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_Z = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VZ)) @ F.TES(particles)
+ALLPART_MOTHER_ID  = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.MC_MOTHER(ngen, F.PARTICLE_ID))) @ F.TES(particles)
+ALLPART_MOTHER_KEY = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.MC_MOTHER(ngen, F.OBJECT_KEY))) @ F.TES(particles)
+ALLPART_ID        = lambda particles: F.MAP(F.VALUE_OR(0) @ F.PARTICLE_ID) @ F.TES(particles)
 #ALLPART_HISTORY   = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.CAST_TO_INT @ F.TRACKHISTORY @ F.TRACK) @ F.TES(particles)
 #ALLPART_FLAG      = lambda particles: F.MAP(F.VALUE_OR(-1) @ F.CAST_TO_INT @ F.TRACKFLAG @ F.TRACK) @ F.TES(particles)
 
 #Variables for particles
+ALLB_ID      = lambda particles: F.MAP(F.PARTICLE_ID) @ F.TES(particles)
+ALLB_KEY     = lambda particles: F.MAP(F.OBJECT_KEY) @ F.TES(particles)
 ALLB_ENDVTX_CHI2 = lambda particles: F.MAP(F.CHI2 @ F.ENDVERTEX) @ F.TES(particles)
 ALLB_ENDVTX_NDOF = lambda particles: F.MAP(F.NDOF @ F.ENDVERTEX) @ F.TES(particles)
 ALLB_ENDVTX_X    = lambda particles: F.MAP(F.END_VX) @ F.TES(particles)
@@ -106,22 +124,23 @@ ALLB_PX        = lambda particles: F.MAP(F.PX) @ F.TES(particles)
 ALLB_PY        = lambda particles: F.MAP(F.PY) @ F.TES(particles)
 ALLB_PZ        = lambda particles: F.MAP(F.PZ) @ F.TES(particles)
 ALLB_MOMERR    = lambda particles, indx_i: F.MAP(F.CALL(indx_i, indx_i) @ F.THREE_MOM_COV_MATRIX) @ F.TES(particles)
+ALLB_ENERGY    = lambda particles: F.MAP(F.ENERGY) @ F.TES(particles)
+ALLB_MASS      = lambda particles: F.MAP(F.MASS) @ F.TES(particles)
 ALLB_ETA       = lambda particles: F.MAP(F.ETA) @ F.TES(particles)
 ALLB_PHI       = lambda particles: F.MAP(F.PHI) @ F.TES(particles)
 #P -> MCP
+ALLB_TRUE_ID   = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID)) @ F.TES(particles)
+ALLB_TRUE_KEY  = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY)) @ F.TES(particles)
 ALLB_TRUE_PV_X = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VX)) @ F.TES(particles) #for association of PV <-> MCPV
 ALLB_TRUE_PV_Y = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VY)) @ F.TES(particles)
 ALLB_TRUE_PV_Z = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MC_PV_VZ)) @ F.TES(particles)
 #the following we don't need (but keep commented out in case we do)
-#ALLB_TRUE_ID   = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID)) @ F.TES(particles)
 #ALLB_TRUE_CHILD1_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #D*-
 #ALLB_TRUE_CHILD11_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #D0
 #ALLB_TRUE_CHILD12_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(2, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #pi
 #ALLB_TRUE_CHILD111_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #K
 #ALLB_TRUE_CHILD112_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(2, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS) @ F.CHILD(1, F.FORWARDARGS)) @ F.TES(particles) #pi
 #ALLB_TRUE_CHILD2_ID = lambda particles, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID) @ F.CHILD(2, F.FORWARDARGS)) @ F.TES(particles) #mu
-#ALLB_ID       = lambda particles: F.MAP(F.PARTICLE_ID) @ F.TES(particles)
-#ALLB_KEY     = lambda particles: F.MAP(F.OBJECT_KEY) @ F.TES(particles)
 
 #velo tracks
 ALLVELOTRACKS_ETA = lambda tracks: F.MAP(F.ETA) @ F.TES(tracks)
@@ -141,6 +160,90 @@ ALLVELOTRACKS_TY = lambda tracks: F.MAP(F.TY) @ F.TES(tracks)
 #ALLVELOTRACKS_ENDVELO_Z = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
 #ALLVELOTRACKS_ENDVELO_POSERR = lambda tracks, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
 
+def get_all_part_vars(evt_vars, particles, pvs, MCTRUTH_parts, suffix = 'PARTS', is_long = False):
+  evt_vars[f'ALL{suffix}_ID[part_indx]'] = ALLPART_ID(particles)
+  evt_vars[f'ALL{suffix}_KEY[part_indx]'] = ALLPART_KEY(particles)
+  evt_vars[f'ALL{suffix}_Q[part_indx]']  = ALLPART_Q(particles)
+  evt_vars[f'ALL{suffix}_PX[part_indx]'] = ALLPART_PX(particles)
+  evt_vars[f'ALL{suffix}_PY[part_indx]'] = ALLPART_PY(particles)
+  evt_vars[f'ALL{suffix}_PZ[part_indx]'] = ALLPART_PZ(particles)
+  evt_vars[f'ALL{suffix}_PXERR[part_indx]'] = ALLPART_MOMERR(particles, 0)
+  evt_vars[f'ALL{suffix}_PYERR[part_indx]'] = ALLPART_MOMERR(particles, 1)
+  evt_vars[f'ALL{suffix}_PZERR[part_indx]'] = ALLPART_MOMERR(particles, 2)
+  evt_vars[f'ALL{suffix}_MASS[part_indx]'] = ALLPART_MASS(particles)
+  evt_vars[f'ALL{suffix}_ENERGY[part_indx]'] = ALLPART_ENERGY(particles)
+  evt_vars[f'ALL{suffix}_ETA[part_indx]'] = ALLPART_ETA(particles)
+  evt_vars[f'ALL{suffix}_PHI[part_indx]'] = ALLPART_PHI(particles)
+  evt_vars[f'ALL{suffix}_PIDPI[part_indx]'] = ALLPART_PIDPI(particles)
+  evt_vars[f'ALL{suffix}_PIDK[part_indx]'] = ALLPART_PIDK(particles)
+  evt_vars[f'ALL{suffix}_PIDP[part_indx]'] = ALLPART_PIDP(particles)
+  evt_vars[f'ALL{suffix}_PIDE[part_indx]'] = ALLPART_PIDE(particles)
+  evt_vars[f'ALL{suffix}_PIDMU[part_indx]'] = ALLPART_PIDMU(particles)
+  #P -> Proto -> Track
+  evt_vars[f'ALL{suffix}_TRACK_CHI2[part_indx]'] = ALLPART_TRACK_CHI2(particles)
+  evt_vars[f'ALL{suffix}_TRACK_NDOF[part_indx]'] = ALLPART_TRACK_NDOF(particles)
+  evt_vars[f'ALL{suffix}_TRACK_TYPE[part_indx]'] = ALLPART_TRACK_TYPE(particles)
+  evt_vars[f'ALL{suffix}_TRACK_GHOSTPROB[part_indx]'] = ALLPART_TRACK_GHOSTPROB(particles)
+  # BPV information
+  evt_vars[f'ALL{suffix}_BPV_KEY[part_indx]'] = ALLPART_BPV_KEY(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_X[part_indx]'] = ALLPART_BPV_X(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_Y[part_indx]'] = ALLPART_BPV_Y(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_Z[part_indx]'] = ALLPART_BPV_Z(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_IP[part_indx]'] = ALLPART_BPV_IP(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_IPCHI2[part_indx]'] = ALLPART_BPV_IPCHI2(particles, pvs)
+  # particle has track but not a closest to beam state, so throws an error (Should this be an error at all?)
+  if is_long:
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_X[part_indx]'] = ALLPART_CLOSESTTOBEAM_X(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_Y[part_indx]'] = ALLPART_CLOSESTTOBEAM_Y(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TX[part_indx]'] = ALLPART_CLOSESTTOBEAM_TX(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TY[part_indx]'] = ALLPART_CLOSESTTOBEAM_TY(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_QOP[part_indx]'] = ALLPART_CLOSESTTOBEAM_QOP(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_XERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 0)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_YERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 1)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TXERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 2)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TYERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 3)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_QOPERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 4)
+
+  # store first measurement
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_X[part_indx]'] = ALLPART_FIRSTMEAS_X(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_Y[part_indx]'] = ALLPART_FIRSTMEAS_Y(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_Z[part_indx]'] = ALLPART_FIRSTMEAS_Z(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TX[part_indx]'] = ALLPART_FIRSTMEAS_TX(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TY[part_indx]'] = ALLPART_FIRSTMEAS_TY(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_QOP[part_indx]'] = ALLPART_FIRSTMEAS_QOP(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_XERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 0)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_YERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 1)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TXERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 2)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TYERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 3)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_QOPERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 4)
+  #P -> MCP
+  evt_vars[f'ALL{suffix}_TRUE_ID[part_indx]'] = ALLPART_TRUE_ID(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_KEY[part_indx]'] = ALLPART_TRUE_KEY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PX[part_indx]'] = ALLPART_TRUE_PX(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PY[part_indx]'] = ALLPART_TRUE_PY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PZ[part_indx]'] = ALLPART_TRUE_PZ(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ENERGY[part_indx]'] = ALLPART_TRUE_ENERGY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_MASS[part_indx]'] = ALLPART_TRUE_MASS(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MC_ISPROMPT[part_indx]'] = ALLPART_MC_ISPROMPT(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PV_X[part_indx]'] = ALLPART_TRUE_PV_X(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PV_Y[part_indx]'] = ALLPART_TRUE_PV_Y(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PV_Z[part_indx]'] = ALLPART_TRUE_PV_Z(particles, MCTRUTH_parts)
+  #P -> LONG LIVED ANCESTOR
+  evt_vars[f'ALL{suffix}_LONGLIVED_ANCESTOR_ID[part_indx]']  = ALLPART_LONGLIVED_ANCESTOR_ID(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_LONGLIVED_ANCESTOR_KEY[part_indx]'] = ALLPART_LONGLIVED_ANCESTOR_KEY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_KEY[part_indx]'] = ALLPART_TRUE_ORGIN_KEY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_X[part_indx]'] = ALLPART_TRUE_ORGIN_X(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_Y[part_indx]'] = ALLPART_TRUE_ORGIN_Y(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_Z[part_indx]'] = ALLPART_TRUE_ORGIN_Z(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_1_ID[part_indx]'] = ALLPART_MOTHER_ID(particles, 1, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_1_KEY[part_indx]'] = ALLPART_MOTHER_KEY(particles, 1, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_2_ID[part_indx]'] = ALLPART_MOTHER_ID(particles, 2, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_2_KEY[part_indx]'] = ALLPART_MOTHER_KEY(particles, 2, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_3_ID[part_indx]'] = ALLPART_MOTHER_ID(particles, 3, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_3_KEY[part_indx]'] = ALLPART_MOTHER_KEY(particles, 3, MCTRUTH_parts)
+  #evt_vars[f'ALL{suffix}_HISTORY[part_indx]'] = ALLPART_HISTORY(particles)
+  #evt_vars[f'ALL{suffix}_FLAG[part_indx]'] = ALLPART_FLAG(particles)
+
 def get_user_algs(decay_channel):
   """
   decay_channel: decay channel to be used in the lines. 
@@ -153,19 +256,25 @@ def get_user_algs(decay_channel):
 
   #get Bs and particles
   Bs = get_particles(f"/Event/HLT2/{line_name}/Particles")
-  particles = get_particles(f"/Event/HLT2/{line_name}/ExtraPions/Particles")
+  long_particles = get_particles(f"/Event/HLT2/{line_name}/ExtraLongPions/Particles")
+  down_particles = get_particles(f"/Event/HLT2/{line_name}/ExtraDownPions/Particles")
+  up_particles = get_particles(f"/Event/HLT2/{line_name}/ExtraUpPions/Particles")
 
   #get MCTRUTH for Bs
   MCTRUTH_Bs = MCTruthAndBkgCat(Bs, name='MCTRUTH_Bs')
   #get MCTRUTH for particles
-  MCTRUTH_parts = MCTruthAndBkgCat(particles, name='MCTRUTH_extra')
+  MCTRUTH_long_parts = MCTruthAndBkgCat(long_particles, name='MCTRUTHLONG_extra')
+  MCTRUTH_down_parts = MCTruthAndBkgCat(down_particles, name='MCTRUTHDOWN_extra')
+  MCTRUTH_up_parts = MCTruthAndBkgCat(up_particles, name='MCTRUTHUP_extra')
 
   #get true id of B candidate (hepful to run over events that have a true Bcand)
   if decay_channel == 'DstMu' or decay_channel == 'DstTau_Lep':
-    #Bd -> D*- mu+ nu
+    #Bd -> D*- mu+ nu; D*- -> D0 pi-; D0 -> K pi
+    #Bd -> D*- tau+ nu; D*- -> D0 pi-; D0 -> K pi and tau -> mu nu nu
     B_ID = 511
   elif decay_channel == 'D0Tau_Had' or decay_channel == 'JpsiK_E' or decay_channel == 'JpsiK_Mu':
-    #Bu -> D*- tau+ nu or Bu -> Jpsi K 
+    #Bu -> D*- tau+ nu; D*- -> D0 pi-; D0 -> K pi and tau -> 3pi
+    #Bu -> Jpsi K; Jpsi -> mu mu
     B_ID = 521
   else:
     raise ValueError(f"Invalid decay channel {decay_channel}")
@@ -185,97 +294,30 @@ def get_user_algs(decay_channel):
   #get velo tracks
   velo_tracks = make_tracks('VeloTracks')
 
-  #get v2_pvs
-  v2_pvs  = get_pvs()
+  #get pvs
+  pvs  = get_pvs()
 
   #get global event variables
   evt_vars = FC.RecSummary()
 
   #get pv variables
-  evt_vars['ALLPV_CHI2[pv_indx]']   = ALLPV_CHI2(v2_pvs)
-  evt_vars['ALLPV_NDOF[pv_indx]']   = ALLPV_NDOF(v2_pvs)
-  evt_vars['ALLPV_X[pv_indx]']      = ALLPV_X(v2_pvs)
-  evt_vars['ALLPV_Y[pv_indx]']      = ALLPV_Y(v2_pvs)
-  evt_vars['ALLPV_Z[pv_indx]']      = ALLPV_Z(v2_pvs)
-  evt_vars['ALLPV_XERR[pv_indx]']   = ALLPV_POSERR(v2_pvs, 0)
-  evt_vars['ALLPV_YERR[pv_indx]']   = ALLPV_POSERR(v2_pvs, 1)
-  evt_vars['ALLPV_ZERR[pv_indx]']   = ALLPV_POSERR(v2_pvs, 2)
+  evt_vars['ALLPV_CHI2[pv_indx]']   = ALLPV_CHI2(pvs)
+  evt_vars['ALLPV_NDOF[pv_indx]']   = ALLPV_NDOF(pvs)
+  evt_vars['ALLPV_X[pv_indx]']      = ALLPV_X(pvs)
+  evt_vars['ALLPV_Y[pv_indx]']      = ALLPV_Y(pvs)
+  evt_vars['ALLPV_Z[pv_indx]']      = ALLPV_Z(pvs)
+  evt_vars['ALLPV_XERR[pv_indx]']   = ALLPV_POSERR(pvs, 0)
+  evt_vars['ALLPV_YERR[pv_indx]']   = ALLPV_POSERR(pvs, 1)
+  evt_vars['ALLPV_ZERR[pv_indx]']   = ALLPV_POSERR(pvs, 2)
 
-  #get particle variables
-  evt_vars['ALLPART_KEY[part_indx]'] = ALLPART_KEY(particles)
-  evt_vars['ALLPART_Q[part_indx]'] = ALLPART_Q(particles)
-  evt_vars['ALLPART_PX[part_indx]'] = ALLPART_PX(particles)
-  evt_vars['ALLPART_PY[part_indx]'] = ALLPART_PY(particles)
-  evt_vars['ALLPART_PZ[part_indx]'] = ALLPART_PZ(particles)
-  evt_vars['ALLPART_PXERR[part_indx]'] = ALLPART_MOMERR(particles, 0)
-  evt_vars['ALLPART_PYERR[part_indx]'] = ALLPART_MOMERR(particles, 1)
-  evt_vars['ALLPART_PZERR[part_indx]'] = ALLPART_MOMERR(particles, 2)
-  evt_vars['ALLPART_ETA[part_indx]'] = ALLPART_ETA(particles)
-  evt_vars['ALLPART_PHI[part_indx]'] = ALLPART_PHI(particles)
-  evt_vars['ALLPART_PIDPI[part_indx]'] = ALLPART_PIDPI(particles)
-  evt_vars['ALLPART_PIDK[part_indx]'] = ALLPART_PIDK(particles)
-  evt_vars['ALLPART_PIDP[part_indx]'] = ALLPART_PIDP(particles)
-  evt_vars['ALLPART_PIDE[part_indx]'] = ALLPART_PIDE(particles)
-  evt_vars['ALLPART_PIDMU[part_indx]'] = ALLPART_PIDMU(particles)
-  #P -> Proto -> Track
-  evt_vars['ALLPART_TRACK_CHI2[part_indx]'] = ALLPART_TRACK_CHI2(particles)
-  evt_vars['ALLPART_TRACK_NDOF[part_indx]'] = ALLPART_TRACK_NDOF(particles)
-  evt_vars['ALLPART_TRACK_TYPE[part_indx]'] = ALLPART_TRACK_TYPE(particles)
-  evt_vars['ALLPART_TRACK_GHOSTPROB[part_indx]'] = ALLPART_TRACK_GHOSTPROB(particles)
-  # particle has track but not a closest to beam state, so throws an error (Should this be an error at all?)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_X[part_indx]'] = ALLPART_CLOSESTTOBEAM_X(particles)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_Y[part_indx]'] = ALLPART_CLOSESTTOBEAM_Y(particles)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_TX[part_indx]'] = ALLPART_CLOSESTTOBEAM_TX(particles)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_TY[part_indx]'] = ALLPART_CLOSESTTOBEAM_TY(particles)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_QOP[part_indx]'] = ALLPART_CLOSESTTOBEAM_QOP(particles)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_XERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 0)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_YERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 1)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_TXERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 2)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_TYERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 3)
-  #evt_vars['ALLPART_CLOSESTTOBEAM_QOPERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 4)
-  evt_vars['ALLPART_FIRSTMEAS_X[part_indx]'] = ALLPART_FIRSTMEAS_X(particles)
-  evt_vars['ALLPART_FIRSTMEAS_Y[part_indx]'] = ALLPART_FIRSTMEAS_Y(particles)
-  evt_vars['ALLPART_FIRSTMEAS_Z[part_indx]'] = ALLPART_FIRSTMEAS_Z(particles)
-  evt_vars['ALLPART_FIRSTMEAS_TX[part_indx]'] = ALLPART_FIRSTMEAS_TX(particles)
-  evt_vars['ALLPART_FIRSTMEAS_TY[part_indx]'] = ALLPART_FIRSTMEAS_TY(particles)
-  evt_vars['ALLPART_FIRSTMEAS_QOP[part_indx]'] = ALLPART_FIRSTMEAS_QOP(particles)
-  evt_vars['ALLPART_FIRSTMEAS_XERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 0)
-  evt_vars['ALLPART_FIRSTMEAS_YERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 1)
-  evt_vars['ALLPART_FIRSTMEAS_TXERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 2)
-  evt_vars['ALLPART_FIRSTMEAS_TYERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 3)
-  evt_vars['ALLPART_FIRSTMEAS_QOPERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 4)
-  # particle has no endut state, so throws an error (should this be an error at all?)
-  #evt_vars['ALLPART_ENDUT_X[part_indx]'] = ALLPART_ENDUT_X(particles)
-  #evt_vars['ALLPART_ENDUT_Y[part_indx]'] = ALLPART_ENDUT_Y(particles)
-  #evt_vars['ALLPART_ENDUT_Z[part_indx]'] = ALLPART_ENDUT_Z(particles)
-  #evt_vars['ALLPART_ENDUT_TX[part_indx]'] = ALLPART_ENDUT_TX(particles)
-  #evt_vars['ALLPART_ENDUT_TY[part_indx]'] = ALLPART_ENDUT_TY(particles)
-  #evt_vars['ALLPART_ENDUT_QOP[part_indx]'] = ALLPART_ENDUT_QOP(particles)
-  #evt_vars['ALLPART_ENDUT_XERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 0)
-  #evt_vars['ALLPART_ENDUT_YERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 1)
-  #evt_vars['ALLPART_ENDUT_TXERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 2)
-  #evt_vars['ALLPART_ENDUT_TYERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 3)
-  #evt_vars['ALLPART_ENDUT_QOPERR[part_indx]'] = ALLPART_ENDUT_STATEERR(particles, 4)
-  #P -> MCP
-  evt_vars['ALLPART_MC_ISPROMPT[part_indx]'] = ALLPART_MC_ISPROMPT(particles, MCTRUTH_parts)
-  evt_vars['ALLPART_TRUE_PV_X[part_indx]'] = ALLPART_TRUE_PV_X(particles, MCTRUTH_parts)
-  evt_vars['ALLPART_TRUE_PV_Y[part_indx]'] = ALLPART_TRUE_PV_Y(particles, MCTRUTH_parts)
-  evt_vars['ALLPART_TRUE_PV_Z[part_indx]'] = ALLPART_TRUE_PV_Z(particles, MCTRUTH_parts)
-  #P -> LONG LIVED ANCESTOR
-  evt_vars['ALLPART_LONGLIVED_ANCESTOR_ID[part_indx]']  = ALLPART_LONGLIVED_ANCESTOR_ID(particles, MCTRUTH_parts)
-  evt_vars['ALLPART_LONGLIVED_ANCESTOR_KEY[part_indx]'] = ALLPART_LONGLIVED_ANCESTOR_KEY(particles, MCTRUTH_parts)
-  #evt_vars['ALLPART_TRUE_ID[part_indx]'] = ALLPART_TRUE_ID(particles, MCTRUTH_parts)
-  #evt_vars['ALLPART_TRUE_KEY[part_indx]'] = ALLPART_TRUE_KEY(particles, MCTRUTH_parts)
-  #evt_vars['ALLPART_TRUE_ORGIN_X[part_indx]'] = ALLPART_TRUE_ORGIN_X(particles, MCTRUTH_parts)
-  #evt_vars['ALLPART_TRUE_ORGIN_Y[part_indx]'] = ALLPART_TRUE_ORGIN_Y(particles, MCTRUTH_parts)
-  #evt_vars['ALLPART_TRUE_ORGIN_Z[part_indx]'] = ALLPART_TRUE_ORGIN_Z(particles, MCTRUTH_parts)
-  #evt_vars['ALLPART_MCP_NGEN_MOTHER_ID[part_indx]'] = ALLPART_MCP_NGEN_MOTHER_ID(particles, 1, MCTRUTH_parts)
-  #evt_vars['ALLPART_MCP_NGEN_MOTHER_KEY[part_indx]'] = ALLPART_MCP_NGEN_MOTHER_KEY(particles, 1, MCTRUTH_parts)
-  #evt_vars['ALLPART_ID[part_indx]'] = ALLPART_ID(particles)
-  #evt_vars['ALLPART_HISTORY[part_indx]'] = ALLPART_HISTORY(particles)
-  #evt_vars['ALLPART_FLAG[part_indx]'] = ALLPART_FLAG(particles)
+  #get long/down/up type particle variables
+  get_all_part_vars(evt_vars, long_particles, pvs, MCTRUTH_long_parts, suffix="LONGPART", is_long=True)
+  get_all_part_vars(evt_vars, down_particles, pvs, MCTRUTH_down_parts, suffix="DOWNPART")
+  get_all_part_vars(evt_vars,   up_particles, pvs,   MCTRUTH_up_parts, suffix="UPPART")
 
   #get Bcand variables
+  evt_vars['ALLB_ID[bcand_indx]'] = ALLB_ID(Bcands)
+  evt_vars['ALLB_KEY[bcand_indx]'] = ALLB_KEY(Bcands)
   evt_vars['ALLB_ENDVTX_CHI2[bcand_indx]'] = ALLB_ENDVTX_CHI2(Bcands)
   evt_vars['ALLB_ENDVTX_NDOF[bcand_indx]'] = ALLB_ENDVTX_NDOF(Bcands)
   evt_vars['ALLB_ENDVTX_X[bcand_indx]'] = ALLB_ENDVTX_X(Bcands)
@@ -290,9 +332,13 @@ def get_user_algs(decay_channel):
   evt_vars['ALLB_PXERR[bcand_indx]'] = ALLB_MOMERR(Bcands, 0)
   evt_vars['ALLB_PYERR[bcand_indx]'] = ALLB_MOMERR(Bcands, 1)
   evt_vars['ALLB_PZERR[bcand_indx]'] = ALLB_MOMERR(Bcands, 2)
+  evt_vars['ALLB_ENERGY[bcand_indx]'] = ALLB_ENERGY(Bcands)
+  evt_vars['ALLB_MASS[bcand_indx]'] = ALLB_MASS(Bcands)
   evt_vars['ALLB_ETA[bcand_indx]'] = ALLB_ETA(Bcands)
   evt_vars['ALLB_PHI[bcand_indx]'] = ALLB_PHI(Bcands)
   #P -> MCP
+  evt_vars['ALLB_TRUE_ID[bcand_indx]'] = ALLB_TRUE_ID(Bcands, MCTRUTH_Bs)
+  evt_vars['ALLB_TRUE_KEY[bcand_indx]'] = ALLB_TRUE_KEY(Bcands, MCTRUTH_Bs)
   evt_vars['ALLB_TRUE_PV_X[bcand_indx]'] = ALLB_TRUE_PV_X(Bcands, MCTRUTH_Bs)
   evt_vars['ALLB_TRUE_PV_Y[bcand_indx]'] = ALLB_TRUE_PV_Y(Bcands, MCTRUTH_Bs)
   evt_vars['ALLB_TRUE_PV_Z[bcand_indx]'] = ALLB_TRUE_PV_Z(Bcands, MCTRUTH_Bs)
@@ -304,11 +350,8 @@ def get_user_algs(decay_channel):
   ##evt_vars['ALLB_TRUE_K[bcand_indx]'] = ALLB_TRUE_CHILD111_ID(Bcands, MCTRUTH_Bs) #K
   ##evt_vars['ALLB_TRUE_PI2[bcand_indx]'] = ALLB_TRUE_CHILD112_ID(Bcands, MCTRUTH_Bs) #pi
 
-  #all basic particles of Bcands
-  evt_vars['ALLBASICS_KEY[basics_indx]'] = ALLPART_KEY(all_basics) #helpful to remove duplicates in particles
-  #evt_vars['ALLBASICS_ID[basics_indx]'] = ALLPART_ID(all_basics)
-  #evt_vars['ALLBASICS_TRUE_ID[basics_indx]'] = ALLPART_TRUE_ID(all_basics, MCTRUTH_Bs)
-  #evt_vars['ALLBASICS_TRUE_KEY[basics_indx]'] = ALLPART_TRUE_KEY(all_basics, MCTRUTH_Bs)
+  ##all basic particles of Bcands
+  get_all_part_vars(evt_vars, all_basics, pvs, MCTRUTH_Bs, suffix="BASICS")
 
   #get velo tracks variables
   evt_vars['ALLVELOTRACKS_ETA[velo_trk_indx]'] = ALLVELOTRACKS_ETA(velo_tracks)
@@ -339,4 +382,4 @@ def get_user_algs(decay_channel):
   #define algorithms
   user_algorithms = {}
   user_algorithms['Alg'] = [my_filter, truth_filter_event, tuple_file]
-  return user_algorithms
+  return user_algorithms
\ No newline at end of file
diff --git a/pvassoc/hlt2.py b/pvassoc/hlt2.py
index ffe4cf2d41..0943a4333e 100755
--- a/pvassoc/hlt2.py
+++ b/pvassoc/hlt2.py
@@ -231,12 +231,12 @@ def make_my_lines(decay_channel):
         long_pions = make_long_pions()
         up_pions = make_up_pions()
         down_pions = make_down_pions()
-        pions = ParticleContainersMerger([long_pions, up_pions, down_pions],
-                                         name='Pions_combiner')
         resolved_pi0s = make_resolved_pi0s()
         merged_pi0s = make_merged_pi0s()
         photons = make_photons()
-        extra_output = [('ExtraPions', pions),
+        extra_output = [('ExtraLongPions', long_pions),
+                        ('ExtraUpPions', up_pions),
+                        ('ExtraDownPions', down_pions),
                         ('ExtraResolvedPi0s', resolved_pi0s),
                         ('ExtraMergedPi0s', merged_pi0s),
                         ('ExtraPhotons', photons)]
-- 
GitLab


From 017e6a358a9c5ac765cdd7c6aa0355a1ebed9565 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Thu, 11 Jul 2024 20:33:52 +0200
Subject: [PATCH 11/18] fix mc pv

---
 pvassoc/dv.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
index ff31495a0a..e3d1667487 100755
--- a/pvassoc/dv.py
+++ b/pvassoc/dv.py
@@ -101,7 +101,7 @@ ALLPART_TRUE_PY  = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(
 ALLPART_TRUE_PZ  = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.PZ)) @ F.TES(particles)
 ALLPART_TRUE_ENERGY = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.ENERGY)) @ F.TES(particles)
 ALLPART_TRUE_MASS = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MASS)) @ F.TES(particles)
-ALLPART_TRUE_ORGIN_KEY  = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY) @ F.MC_PRIMARYVERTEX) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_KEY  = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY @ F.MC_PRIMARYVERTEX)) @ F.TES(particles)
 ALLPART_TRUE_ORGIN_X = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VX)) @ F.TES(particles)
 ALLPART_TRUE_ORGIN_Y = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VY)) @ F.TES(particles)
 ALLPART_TRUE_ORGIN_Z = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VZ)) @ F.TES(particles)
-- 
GitLab


From 28023a2240462714b0697557537400faf2a3135b Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Thu, 11 Jul 2024 21:11:12 +0200
Subject: [PATCH 12/18] correct origin vertex

---
 pvassoc/dv.py | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
index e3d1667487..4f78318e1b 100755
--- a/pvassoc/dv.py
+++ b/pvassoc/dv.py
@@ -102,9 +102,9 @@ ALLPART_TRUE_PZ  = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(
 ALLPART_TRUE_ENERGY = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.ENERGY)) @ F.TES(particles)
 ALLPART_TRUE_MASS = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.MASS)) @ F.TES(particles)
 ALLPART_TRUE_ORGIN_KEY  = lambda particles, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY @ F.MC_PRIMARYVERTEX)) @ F.TES(particles)
-ALLPART_TRUE_ORGIN_X = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VX)) @ F.TES(particles)
-ALLPART_TRUE_ORGIN_Y = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VY)) @ F.TES(particles)
-ALLPART_TRUE_ORGIN_Z = lambda particles, mctruth: F.MAP(mctruth(F.ORIGIN_VZ)) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_X = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.ORIGIN_VX)) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_Y = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.ORIGIN_VY)) @ F.TES(particles)
+ALLPART_TRUE_ORGIN_Z = lambda particles, mctruth: F.MAP(F.VALUE_OR(F.NaN) @ mctruth(F.ORIGIN_VZ)) @ F.TES(particles)
 ALLPART_MOTHER_ID  = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(0) @ mctruth(F.MC_MOTHER(ngen, F.PARTICLE_ID))) @ F.TES(particles)
 ALLPART_MOTHER_KEY = lambda particles, ngen, mctruth: F.MAP(F.VALUE_OR(-1) @ mctruth(F.MC_MOTHER(ngen, F.OBJECT_KEY))) @ F.TES(particles)
 ALLPART_ID        = lambda particles: F.MAP(F.VALUE_OR(0) @ F.PARTICLE_ID) @ F.TES(particles)
@@ -150,6 +150,12 @@ ALLVELOTRACKS_Y = lambda tracks: F.MAP(F.Y_COORDINATE @ F.POSITION) @ F.TES(trac
 ALLVELOTRACKS_Z = lambda tracks: F.MAP(F.Z_COORDINATE @ F.POSITION) @ F.TES(tracks)
 ALLVELOTRACKS_TX = lambda tracks: F.MAP(F.TX) @ F.TES(tracks)
 ALLVELOTRACKS_TY = lambda tracks: F.MAP(F.TY) @ F.TES(tracks)
+ALLVELOTRACKS_BPV_KEY= lambda tracks, pvs: F.MAP(F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.BPV(pvs)) @ F.TES(tracks)
+ALLVELOTRACKS_BPV_X  = lambda tracks, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVX(pvs)) @ F.TES(tracks)
+ALLVELOTRACKS_BPV_Y  = lambda tracks, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVY(pvs)) @ F.TES(tracks)
+ALLVELOTRACKS_BPV_Z  = lambda tracks, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVZ(pvs)) @ F.TES(tracks)
+ALLVELOTRACKS_BPV_IP = lambda tracks, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVIP(pvs)) @ F.TES(tracks)
+ALLVELOTRACKS_BPV_IPCHI2 = lambda tracks, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVIPCHI2(pvs)) @ F.TES(tracks)
 ##throw as error about pointers
 #ALLVELOTRACKS_FIRSTMEAS_X = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement")) @ F.TES(tracks)
 #ALLVELOTRACKS_FIRSTMEAS_Y = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION @ F.STATE_AT("FirstMeasurement")) @ F.TES(tracks)
@@ -362,6 +368,12 @@ def get_user_algs(decay_channel):
   evt_vars['ALLVELOTRACKS_Z[velo_trk_indx]'] = ALLVELOTRACKS_Z(velo_tracks)
   evt_vars['ALLVELOTRACKS_TX[velo_trk_indx]'] = ALLVELOTRACKS_TX(velo_tracks)
   evt_vars['ALLVELOTRACKS_TY[velo_trk_indx]'] = ALLVELOTRACKS_TY(velo_tracks)
+  #evt_vars['ALLVELOTRACKS_BPV_KEY[velo_trk_indx]'] = ALLVELOTRACKS_BPV_KEY(velo_tracks, pvs)
+  #evt_vars['ALLVELOTRACKS_BPV_X[velo_trk_indx]'] = ALLVELOTRACKS_BPV_X(velo_tracks, pvs)
+  #evt_vars['ALLVELOTRACKS_BPV_Y[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Y(velo_tracks, pvs)
+  #evt_vars['ALLVELOTRACKS_BPV_Z[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Z(velo_tracks, pvs)
+  #evt_vars['ALLVELOTRACKS_BPV_IP[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IP(velo_tracks, pvs)
+  #evt_vars['ALLVELOTRACKS_BPV_IPCHI2[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IPCHI2(velo_tracks, pvs)
   #throws error about pointer
   #evt_vars['ALLVELOTRACKS_FIRSTMEAS_X[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_X(velo_tracks)
   #evt_vars['ALLVELOTRACKS_FIRSTMEAS_Y[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_Y(velo_tracks)
-- 
GitLab


From c457876ec2fdac16282f1014bd3c8d69e5de3866 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Thu, 11 Jul 2024 23:01:41 +0200
Subject: [PATCH 13/18] bpv for velo

---
 pvassoc/dv.py     |  4 ++--
 pvassoc/info.yaml | 15 ++++++++++-----
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
index 4f78318e1b..fedb02f2a8 100755
--- a/pvassoc/dv.py
+++ b/pvassoc/dv.py
@@ -368,11 +368,11 @@ def get_user_algs(decay_channel):
   evt_vars['ALLVELOTRACKS_Z[velo_trk_indx]'] = ALLVELOTRACKS_Z(velo_tracks)
   evt_vars['ALLVELOTRACKS_TX[velo_trk_indx]'] = ALLVELOTRACKS_TX(velo_tracks)
   evt_vars['ALLVELOTRACKS_TY[velo_trk_indx]'] = ALLVELOTRACKS_TY(velo_tracks)
-  #evt_vars['ALLVELOTRACKS_BPV_KEY[velo_trk_indx]'] = ALLVELOTRACKS_BPV_KEY(velo_tracks, pvs)
+  evt_vars['ALLVELOTRACKS_BPV_KEY[velo_trk_indx]'] = ALLVELOTRACKS_BPV_KEY(velo_tracks, pvs)
   #evt_vars['ALLVELOTRACKS_BPV_X[velo_trk_indx]'] = ALLVELOTRACKS_BPV_X(velo_tracks, pvs)
   #evt_vars['ALLVELOTRACKS_BPV_Y[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Y(velo_tracks, pvs)
   #evt_vars['ALLVELOTRACKS_BPV_Z[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Z(velo_tracks, pvs)
-  #evt_vars['ALLVELOTRACKS_BPV_IP[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IP(velo_tracks, pvs)
+  evt_vars['ALLVELOTRACKS_BPV_IP[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IP(velo_tracks, pvs)
   #evt_vars['ALLVELOTRACKS_BPV_IPCHI2[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IPCHI2(velo_tracks, pvs)
   #throws error about pointer
   #evt_vars['ALLVELOTRACKS_FIRSTMEAS_X[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_X(velo_tracks)
diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index c022da3913..84666452a9 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -6,14 +6,19 @@ defaults:
 
 {%- set datasets = [
     ('DstMu',  11574020),
-    ('DstTau_Lep', 11574010),
-    ('D0Tau_Had', 12562000),
-    ('JpsiK_Mu', 12143001),
-    ('JpsiK_E', 12153001)
+    #('DstTau_Lep', 11574010),
+    #('D0Tau_Had', 12562000),
+    #('JpsiK_Mu', 12143001),
+    #('JpsiK_E', 12153001)
 ] %}
 
+{%- set magtypes = [
+    ('MagDown', 'md'),
+    #('MagUp', 'mu')
+] %}
+  
 {%- for sample, evtID in datasets %}
-  {%- for polarity, tagpol in [('MagDown', 'md'), ('MagUp', 'mu')] %}
+  {%- for polarity, tagpol in magtypes %}
 
 Hlt1{{sample}}_{{polarity}}:
   application: Moore/v55r9@x86_64_v2-el9-gcc13+detdesc-opt
-- 
GitLab


From 7c2cb0d5fd6e8546a946aece920efee964919a03 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Thu, 11 Jul 2024 23:04:50 +0200
Subject: [PATCH 14/18] test

---
 pvassoc/info.yaml | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index 84666452a9..dc280b6421 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -5,16 +5,11 @@ defaults:
     - abhijit.mathad@cern.ch
 
 {%- set datasets = [
-    ('DstMu',  11574020),
-    #('DstTau_Lep', 11574010),
-    #('D0Tau_Had', 12562000),
-    #('JpsiK_Mu', 12143001),
-    #('JpsiK_E', 12153001)
+    ('DstMu',  11574020)
 ] %}
 
 {%- set magtypes = [
-    ('MagDown', 'md'),
-    #('MagUp', 'mu')
+    ('MagDown', 'md')
 ] %}
   
 {%- for sample, evtID in datasets %}
-- 
GitLab


From 332b13267867462c85dbb6da78666701e0031d99 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Thu, 11 Jul 2024 23:12:55 +0200
Subject: [PATCH 15/18] test

---
 pvassoc/info.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index dc280b6421..9d729a349a 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -30,6 +30,7 @@ Hlt1{{sample}}_{{polarity}}:
       output_type: ROOT
       simulation: True
       data_type: "Upgrade"
+      evt_max: 20
       scheduler_legacy_mode: False
 
 Hlt2{{sample}}_{{polarity}}:
@@ -47,6 +48,7 @@ Hlt2{{sample}}_{{polarity}}:
       output_type: ROOT
       simulation: True
       data_type: "Upgrade"
+      evt_max: 20
       scheduler_legacy_mode: False
 
 DV{{sample}}_{{polarity}}:
@@ -63,6 +65,7 @@ DV{{sample}}_{{polarity}}:
       data_type: "Upgrade"
       conddb_tag: sim-20231017-vc-{{tagpol}}100
       dddb_tag: dddb-20231017
+      evt_max: 20
       input_process: "Hlt2"
   {%- endfor %}
 {%- endfor %}
-- 
GitLab


From 0da79b2694b789417929a3c996afc6f494f1e5ef Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Thu, 11 Jul 2024 23:19:16 +0200
Subject: [PATCH 16/18] test

---
 pvassoc/info.yaml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index 9d729a349a..dc280b6421 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -30,7 +30,6 @@ Hlt1{{sample}}_{{polarity}}:
       output_type: ROOT
       simulation: True
       data_type: "Upgrade"
-      evt_max: 20
       scheduler_legacy_mode: False
 
 Hlt2{{sample}}_{{polarity}}:
@@ -48,7 +47,6 @@ Hlt2{{sample}}_{{polarity}}:
       output_type: ROOT
       simulation: True
       data_type: "Upgrade"
-      evt_max: 20
       scheduler_legacy_mode: False
 
 DV{{sample}}_{{polarity}}:
@@ -65,7 +63,6 @@ DV{{sample}}_{{polarity}}:
       data_type: "Upgrade"
       conddb_tag: sim-20231017-vc-{{tagpol}}100
       dddb_tag: dddb-20231017
-      evt_max: 20
       input_process: "Hlt2"
   {%- endfor %}
 {%- endfor %}
-- 
GitLab


From aab9850cc17c7643cf9579ed6ab2daaec0bc329c Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Fri, 12 Jul 2024 00:17:19 +0200
Subject: [PATCH 17/18] final

---
 pvassoc/dv.py     |  9 +++++----
 pvassoc/info.yaml | 10 ++++++++--
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
index fedb02f2a8..481aab8416 100755
--- a/pvassoc/dv.py
+++ b/pvassoc/dv.py
@@ -368,12 +368,13 @@ def get_user_algs(decay_channel):
   evt_vars['ALLVELOTRACKS_Z[velo_trk_indx]'] = ALLVELOTRACKS_Z(velo_tracks)
   evt_vars['ALLVELOTRACKS_TX[velo_trk_indx]'] = ALLVELOTRACKS_TX(velo_tracks)
   evt_vars['ALLVELOTRACKS_TY[velo_trk_indx]'] = ALLVELOTRACKS_TY(velo_tracks)
+  #velo BPV information
   evt_vars['ALLVELOTRACKS_BPV_KEY[velo_trk_indx]'] = ALLVELOTRACKS_BPV_KEY(velo_tracks, pvs)
-  #evt_vars['ALLVELOTRACKS_BPV_X[velo_trk_indx]'] = ALLVELOTRACKS_BPV_X(velo_tracks, pvs)
-  #evt_vars['ALLVELOTRACKS_BPV_Y[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Y(velo_tracks, pvs)
-  #evt_vars['ALLVELOTRACKS_BPV_Z[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Z(velo_tracks, pvs)
+  evt_vars['ALLVELOTRACKS_BPV_X[velo_trk_indx]'] = ALLVELOTRACKS_BPV_X(velo_tracks, pvs)
+  evt_vars['ALLVELOTRACKS_BPV_Y[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Y(velo_tracks, pvs)
+  evt_vars['ALLVELOTRACKS_BPV_Z[velo_trk_indx]'] = ALLVELOTRACKS_BPV_Z(velo_tracks, pvs)
   evt_vars['ALLVELOTRACKS_BPV_IP[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IP(velo_tracks, pvs)
-  #evt_vars['ALLVELOTRACKS_BPV_IPCHI2[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IPCHI2(velo_tracks, pvs)
+  evt_vars['ALLVELOTRACKS_BPV_IPCHI2[velo_trk_indx]'] = ALLVELOTRACKS_BPV_IPCHI2(velo_tracks, pvs)
   #throws error about pointer
   #evt_vars['ALLVELOTRACKS_FIRSTMEAS_X[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_X(velo_tracks)
   #evt_vars['ALLVELOTRACKS_FIRSTMEAS_Y[velo_trk_indx]'] = ALLVELOTRACKS_FIRSTMEAS_Y(velo_tracks)
diff --git a/pvassoc/info.yaml b/pvassoc/info.yaml
index dc280b6421..db7113460a 100644
--- a/pvassoc/info.yaml
+++ b/pvassoc/info.yaml
@@ -5,12 +5,18 @@ defaults:
     - abhijit.mathad@cern.ch
 
 {%- set datasets = [
-    ('DstMu',  11574020)
+    ('DstMu',  11574020),
+    ('DstTau_Lep', 11574010),
+    ('D0Tau_Had', 12562000),
+    ('JpsiK_Mu', 12143001),
+    ('JpsiK_E', 12153001)
 ] %}
 
 {%- set magtypes = [
-    ('MagDown', 'md')
+    ('MagDown', 'md'),
+    ('MagUp', 'mu')
 ] %}
+
   
 {%- for sample, evtID in datasets %}
   {%- for polarity, tagpol in magtypes %}
-- 
GitLab


From 8eb05eee1413a1a1d3e6087223d065d209e5d268 Mon Sep 17 00:00:00 2001
From: amathad <Abhijit Mathad amathad@cern.ch>
Date: Mon, 15 Jul 2024 16:58:34 +0200
Subject: [PATCH 18/18] fix a bug

---
 pvassoc/dv.py | 158 +++++++++++++++++++++++++-------------------------
 1 file changed, 79 insertions(+), 79 deletions(-)

diff --git a/pvassoc/dv.py b/pvassoc/dv.py
index 481aab8416..7e9bde4bcc 100755
--- a/pvassoc/dv.py
+++ b/pvassoc/dv.py
@@ -166,89 +166,89 @@ ALLVELOTRACKS_BPV_IPCHI2 = lambda tracks, pvs: F.MAP(F.VALUE_OR(F.NaN) @ F.BPVIP
 #ALLVELOTRACKS_ENDVELO_Z = lambda tracks: F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
 #ALLVELOTRACKS_ENDVELO_POSERR = lambda tracks, indx_i: F.MAP(F.VALUE_OR(F.NaN) @ F.CALL(indx_i, indx_i) @ F.TRACK_COVARIANCE @ F.STATE_AT("EndVelo")) @ F.TES(tracks)
 
-def get_all_part_vars(evt_vars, particles, pvs, MCTRUTH_parts, suffix = 'PARTS', is_long = False):
-  evt_vars[f'ALL{suffix}_ID[part_indx]'] = ALLPART_ID(particles)
-  evt_vars[f'ALL{suffix}_KEY[part_indx]'] = ALLPART_KEY(particles)
-  evt_vars[f'ALL{suffix}_Q[part_indx]']  = ALLPART_Q(particles)
-  evt_vars[f'ALL{suffix}_PX[part_indx]'] = ALLPART_PX(particles)
-  evt_vars[f'ALL{suffix}_PY[part_indx]'] = ALLPART_PY(particles)
-  evt_vars[f'ALL{suffix}_PZ[part_indx]'] = ALLPART_PZ(particles)
-  evt_vars[f'ALL{suffix}_PXERR[part_indx]'] = ALLPART_MOMERR(particles, 0)
-  evt_vars[f'ALL{suffix}_PYERR[part_indx]'] = ALLPART_MOMERR(particles, 1)
-  evt_vars[f'ALL{suffix}_PZERR[part_indx]'] = ALLPART_MOMERR(particles, 2)
-  evt_vars[f'ALL{suffix}_MASS[part_indx]'] = ALLPART_MASS(particles)
-  evt_vars[f'ALL{suffix}_ENERGY[part_indx]'] = ALLPART_ENERGY(particles)
-  evt_vars[f'ALL{suffix}_ETA[part_indx]'] = ALLPART_ETA(particles)
-  evt_vars[f'ALL{suffix}_PHI[part_indx]'] = ALLPART_PHI(particles)
-  evt_vars[f'ALL{suffix}_PIDPI[part_indx]'] = ALLPART_PIDPI(particles)
-  evt_vars[f'ALL{suffix}_PIDK[part_indx]'] = ALLPART_PIDK(particles)
-  evt_vars[f'ALL{suffix}_PIDP[part_indx]'] = ALLPART_PIDP(particles)
-  evt_vars[f'ALL{suffix}_PIDE[part_indx]'] = ALLPART_PIDE(particles)
-  evt_vars[f'ALL{suffix}_PIDMU[part_indx]'] = ALLPART_PIDMU(particles)
+def get_all_part_vars(evt_vars, particles, pvs, MCTRUTH_parts, index_name, suffix = 'PARTS', is_long = False):
+  evt_vars[f'ALL{suffix}_ID[{index_name}]'] = ALLPART_ID(particles)
+  evt_vars[f'ALL{suffix}_KEY[{index_name}]'] = ALLPART_KEY(particles)
+  evt_vars[f'ALL{suffix}_Q[{index_name}]']  = ALLPART_Q(particles)
+  evt_vars[f'ALL{suffix}_PX[{index_name}]'] = ALLPART_PX(particles)
+  evt_vars[f'ALL{suffix}_PY[{index_name}]'] = ALLPART_PY(particles)
+  evt_vars[f'ALL{suffix}_PZ[{index_name}]'] = ALLPART_PZ(particles)
+  evt_vars[f'ALL{suffix}_PXERR[{index_name}]'] = ALLPART_MOMERR(particles, 0)
+  evt_vars[f'ALL{suffix}_PYERR[{index_name}]'] = ALLPART_MOMERR(particles, 1)
+  evt_vars[f'ALL{suffix}_PZERR[{index_name}]'] = ALLPART_MOMERR(particles, 2)
+  evt_vars[f'ALL{suffix}_MASS[{index_name}]'] = ALLPART_MASS(particles)
+  evt_vars[f'ALL{suffix}_ENERGY[{index_name}]'] = ALLPART_ENERGY(particles)
+  evt_vars[f'ALL{suffix}_ETA[{index_name}]'] = ALLPART_ETA(particles)
+  evt_vars[f'ALL{suffix}_PHI[{index_name}]'] = ALLPART_PHI(particles)
+  evt_vars[f'ALL{suffix}_PIDPI[{index_name}]'] = ALLPART_PIDPI(particles)
+  evt_vars[f'ALL{suffix}_PIDK[{index_name}]'] = ALLPART_PIDK(particles)
+  evt_vars[f'ALL{suffix}_PIDP[{index_name}]'] = ALLPART_PIDP(particles)
+  evt_vars[f'ALL{suffix}_PIDE[{index_name}]'] = ALLPART_PIDE(particles)
+  evt_vars[f'ALL{suffix}_PIDMU[{index_name}]'] = ALLPART_PIDMU(particles)
   #P -> Proto -> Track
-  evt_vars[f'ALL{suffix}_TRACK_CHI2[part_indx]'] = ALLPART_TRACK_CHI2(particles)
-  evt_vars[f'ALL{suffix}_TRACK_NDOF[part_indx]'] = ALLPART_TRACK_NDOF(particles)
-  evt_vars[f'ALL{suffix}_TRACK_TYPE[part_indx]'] = ALLPART_TRACK_TYPE(particles)
-  evt_vars[f'ALL{suffix}_TRACK_GHOSTPROB[part_indx]'] = ALLPART_TRACK_GHOSTPROB(particles)
+  evt_vars[f'ALL{suffix}_TRACK_CHI2[{index_name}]'] = ALLPART_TRACK_CHI2(particles)
+  evt_vars[f'ALL{suffix}_TRACK_NDOF[{index_name}]'] = ALLPART_TRACK_NDOF(particles)
+  evt_vars[f'ALL{suffix}_TRACK_TYPE[{index_name}]'] = ALLPART_TRACK_TYPE(particles)
+  evt_vars[f'ALL{suffix}_TRACK_GHOSTPROB[{index_name}]'] = ALLPART_TRACK_GHOSTPROB(particles)
   # BPV information
-  evt_vars[f'ALL{suffix}_BPV_KEY[part_indx]'] = ALLPART_BPV_KEY(particles, pvs)
-  evt_vars[f'ALL{suffix}_BPV_X[part_indx]'] = ALLPART_BPV_X(particles, pvs)
-  evt_vars[f'ALL{suffix}_BPV_Y[part_indx]'] = ALLPART_BPV_Y(particles, pvs)
-  evt_vars[f'ALL{suffix}_BPV_Z[part_indx]'] = ALLPART_BPV_Z(particles, pvs)
-  evt_vars[f'ALL{suffix}_BPV_IP[part_indx]'] = ALLPART_BPV_IP(particles, pvs)
-  evt_vars[f'ALL{suffix}_BPV_IPCHI2[part_indx]'] = ALLPART_BPV_IPCHI2(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_KEY[{index_name}]'] = ALLPART_BPV_KEY(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_X[{index_name}]'] = ALLPART_BPV_X(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_Y[{index_name}]'] = ALLPART_BPV_Y(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_Z[{index_name}]'] = ALLPART_BPV_Z(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_IP[{index_name}]'] = ALLPART_BPV_IP(particles, pvs)
+  evt_vars[f'ALL{suffix}_BPV_IPCHI2[{index_name}]'] = ALLPART_BPV_IPCHI2(particles, pvs)
   # particle has track but not a closest to beam state, so throws an error (Should this be an error at all?)
   if is_long:
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_X[part_indx]'] = ALLPART_CLOSESTTOBEAM_X(particles)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_Y[part_indx]'] = ALLPART_CLOSESTTOBEAM_Y(particles)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TX[part_indx]'] = ALLPART_CLOSESTTOBEAM_TX(particles)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TY[part_indx]'] = ALLPART_CLOSESTTOBEAM_TY(particles)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_QOP[part_indx]'] = ALLPART_CLOSESTTOBEAM_QOP(particles)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_XERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 0)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_YERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 1)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TXERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 2)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TYERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 3)
-    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_QOPERR[part_indx]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 4)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_X[{index_name}]'] = ALLPART_CLOSESTTOBEAM_X(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_Y[{index_name}]'] = ALLPART_CLOSESTTOBEAM_Y(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TX[{index_name}]'] = ALLPART_CLOSESTTOBEAM_TX(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TY[{index_name}]'] = ALLPART_CLOSESTTOBEAM_TY(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_QOP[{index_name}]'] = ALLPART_CLOSESTTOBEAM_QOP(particles)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_XERR[{index_name}]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 0)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_YERR[{index_name}]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 1)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TXERR[{index_name}]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 2)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_TYERR[{index_name}]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 3)
+    evt_vars[f'ALL{suffix}_CLOSESTTOBEAM_QOPERR[{index_name}]'] = ALLPART_CLOSESTTOBEAM_STATEERR(particles, 4)
 
   # store first measurement
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_X[part_indx]'] = ALLPART_FIRSTMEAS_X(particles)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_Y[part_indx]'] = ALLPART_FIRSTMEAS_Y(particles)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_Z[part_indx]'] = ALLPART_FIRSTMEAS_Z(particles)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_TX[part_indx]'] = ALLPART_FIRSTMEAS_TX(particles)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_TY[part_indx]'] = ALLPART_FIRSTMEAS_TY(particles)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_QOP[part_indx]'] = ALLPART_FIRSTMEAS_QOP(particles)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_XERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 0)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_YERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 1)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_TXERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 2)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_TYERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 3)
-  evt_vars[f'ALL{suffix}_FIRSTMEAS_QOPERR[part_indx]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 4)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_X[{index_name}]'] = ALLPART_FIRSTMEAS_X(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_Y[{index_name}]'] = ALLPART_FIRSTMEAS_Y(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_Z[{index_name}]'] = ALLPART_FIRSTMEAS_Z(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TX[{index_name}]'] = ALLPART_FIRSTMEAS_TX(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TY[{index_name}]'] = ALLPART_FIRSTMEAS_TY(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_QOP[{index_name}]'] = ALLPART_FIRSTMEAS_QOP(particles)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_XERR[{index_name}]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 0)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_YERR[{index_name}]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 1)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TXERR[{index_name}]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 2)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_TYERR[{index_name}]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 3)
+  evt_vars[f'ALL{suffix}_FIRSTMEAS_QOPERR[{index_name}]'] = ALLPART_FIRSTMEAS_STATEERR(particles, 4)
   #P -> MCP
-  evt_vars[f'ALL{suffix}_TRUE_ID[part_indx]'] = ALLPART_TRUE_ID(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_KEY[part_indx]'] = ALLPART_TRUE_KEY(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_PX[part_indx]'] = ALLPART_TRUE_PX(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_PY[part_indx]'] = ALLPART_TRUE_PY(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_PZ[part_indx]'] = ALLPART_TRUE_PZ(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_ENERGY[part_indx]'] = ALLPART_TRUE_ENERGY(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_MASS[part_indx]'] = ALLPART_TRUE_MASS(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_MC_ISPROMPT[part_indx]'] = ALLPART_MC_ISPROMPT(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_PV_X[part_indx]'] = ALLPART_TRUE_PV_X(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_PV_Y[part_indx]'] = ALLPART_TRUE_PV_Y(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_PV_Z[part_indx]'] = ALLPART_TRUE_PV_Z(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ID[{index_name}]'] = ALLPART_TRUE_ID(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_KEY[{index_name}]'] = ALLPART_TRUE_KEY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PX[{index_name}]'] = ALLPART_TRUE_PX(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PY[{index_name}]'] = ALLPART_TRUE_PY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PZ[{index_name}]'] = ALLPART_TRUE_PZ(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ENERGY[{index_name}]'] = ALLPART_TRUE_ENERGY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_MASS[{index_name}]'] = ALLPART_TRUE_MASS(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MC_ISPROMPT[{index_name}]'] = ALLPART_MC_ISPROMPT(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PV_X[{index_name}]'] = ALLPART_TRUE_PV_X(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PV_Y[{index_name}]'] = ALLPART_TRUE_PV_Y(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_PV_Z[{index_name}]'] = ALLPART_TRUE_PV_Z(particles, MCTRUTH_parts)
   #P -> LONG LIVED ANCESTOR
-  evt_vars[f'ALL{suffix}_LONGLIVED_ANCESTOR_ID[part_indx]']  = ALLPART_LONGLIVED_ANCESTOR_ID(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_LONGLIVED_ANCESTOR_KEY[part_indx]'] = ALLPART_LONGLIVED_ANCESTOR_KEY(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_ORGIN_KEY[part_indx]'] = ALLPART_TRUE_ORGIN_KEY(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_ORGIN_X[part_indx]'] = ALLPART_TRUE_ORGIN_X(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_ORGIN_Y[part_indx]'] = ALLPART_TRUE_ORGIN_Y(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_TRUE_ORGIN_Z[part_indx]'] = ALLPART_TRUE_ORGIN_Z(particles, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_MOTHER_1_ID[part_indx]'] = ALLPART_MOTHER_ID(particles, 1, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_MOTHER_1_KEY[part_indx]'] = ALLPART_MOTHER_KEY(particles, 1, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_MOTHER_2_ID[part_indx]'] = ALLPART_MOTHER_ID(particles, 2, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_MOTHER_2_KEY[part_indx]'] = ALLPART_MOTHER_KEY(particles, 2, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_MOTHER_3_ID[part_indx]'] = ALLPART_MOTHER_ID(particles, 3, MCTRUTH_parts)
-  evt_vars[f'ALL{suffix}_MOTHER_3_KEY[part_indx]'] = ALLPART_MOTHER_KEY(particles, 3, MCTRUTH_parts)
-  #evt_vars[f'ALL{suffix}_HISTORY[part_indx]'] = ALLPART_HISTORY(particles)
-  #evt_vars[f'ALL{suffix}_FLAG[part_indx]'] = ALLPART_FLAG(particles)
+  evt_vars[f'ALL{suffix}_LONGLIVED_ANCESTOR_ID[{index_name}]']  = ALLPART_LONGLIVED_ANCESTOR_ID(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_LONGLIVED_ANCESTOR_KEY[{index_name}]'] = ALLPART_LONGLIVED_ANCESTOR_KEY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_KEY[{index_name}]'] = ALLPART_TRUE_ORGIN_KEY(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_X[{index_name}]'] = ALLPART_TRUE_ORGIN_X(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_Y[{index_name}]'] = ALLPART_TRUE_ORGIN_Y(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_TRUE_ORGIN_Z[{index_name}]'] = ALLPART_TRUE_ORGIN_Z(particles, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_1_ID[{index_name}]'] = ALLPART_MOTHER_ID(particles, 1, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_1_KEY[{index_name}]'] = ALLPART_MOTHER_KEY(particles, 1, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_2_ID[{index_name}]'] = ALLPART_MOTHER_ID(particles, 2, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_2_KEY[{index_name}]'] = ALLPART_MOTHER_KEY(particles, 2, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_3_ID[{index_name}]'] = ALLPART_MOTHER_ID(particles, 3, MCTRUTH_parts)
+  evt_vars[f'ALL{suffix}_MOTHER_3_KEY[{index_name}]'] = ALLPART_MOTHER_KEY(particles, 3, MCTRUTH_parts)
+  #evt_vars[f'ALL{suffix}_HISTORY[{index_name}]'] = ALLPART_HISTORY(particles)
+  #evt_vars[f'ALL{suffix}_FLAG[{index_name}]'] = ALLPART_FLAG(particles)
 
 def get_user_algs(decay_channel):
   """
@@ -317,9 +317,9 @@ def get_user_algs(decay_channel):
   evt_vars['ALLPV_ZERR[pv_indx]']   = ALLPV_POSERR(pvs, 2)
 
   #get long/down/up type particle variables
-  get_all_part_vars(evt_vars, long_particles, pvs, MCTRUTH_long_parts, suffix="LONGPART", is_long=True)
-  get_all_part_vars(evt_vars, down_particles, pvs, MCTRUTH_down_parts, suffix="DOWNPART")
-  get_all_part_vars(evt_vars,   up_particles, pvs,   MCTRUTH_up_parts, suffix="UPPART")
+  get_all_part_vars(evt_vars, long_particles, pvs, MCTRUTH_long_parts, index_name='long_indx', suffix="LONGPART", is_long=True)
+  get_all_part_vars(evt_vars, down_particles, pvs, MCTRUTH_down_parts, index_name='down_indx', suffix="DOWNPART")
+  get_all_part_vars(evt_vars,   up_particles, pvs,   MCTRUTH_up_parts, index_name='up_indx', suffix="UPPART")
 
   #get Bcand variables
   evt_vars['ALLB_ID[bcand_indx]'] = ALLB_ID(Bcands)
@@ -357,7 +357,7 @@ def get_user_algs(decay_channel):
   ##evt_vars['ALLB_TRUE_PI2[bcand_indx]'] = ALLB_TRUE_CHILD112_ID(Bcands, MCTRUTH_Bs) #pi
 
   ##all basic particles of Bcands
-  get_all_part_vars(evt_vars, all_basics, pvs, MCTRUTH_Bs, suffix="BASICS")
+  get_all_part_vars(evt_vars, all_basics, pvs, MCTRUTH_Bs, index_name='basics_indx', suffix="BASICS")
 
   #get velo tracks variables
   evt_vars['ALLVELOTRACKS_ETA[velo_trk_indx]'] = ALLVELOTRACKS_ETA(velo_tracks)
-- 
GitLab