From a5c99ffc2fed603037dd203c8db63ebbed40236d Mon Sep 17 00:00:00 2001
From: Zihan Gao <zihan.gao@cern.ch>
Date: Wed, 11 Sep 2024 21:36:01 +0200
Subject: [PATCH 01/12] fix truth match and add track cov

---
 ...allen_mc_hlt1_pp_matching_no_ut_1000KHz.py |   6 +
 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py        |  29 +
 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py    |  39 ++
 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py       |  30 +
 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py   |  28 +
 QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py        |  29 +
 QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py        |  29 +
 QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py        |  29 +
 QuarkoniaToMuMu2024/helpers/dv_mctree.py      | 136 +++++
 QuarkoniaToMuMu2024/helpers/dv_tree.py        | 511 ++++++++++++++++++
 QuarkoniaToMuMu2024/info.yaml                 | 107 ++++
 QuarkoniaToMuMu2024/moore_mc_turbo.py         |  44 ++
 QuarkoniaToMuMu2024/spruce_turbo.py           |  53 ++
 13 files changed, 1070 insertions(+)
 create mode 100644 QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py
 create mode 100644 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
 create mode 100644 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py
 create mode 100644 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
 create mode 100644 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py
 create mode 100644 QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
 create mode 100644 QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
 create mode 100644 QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
 create mode 100644 QuarkoniaToMuMu2024/helpers/dv_mctree.py
 create mode 100644 QuarkoniaToMuMu2024/helpers/dv_tree.py
 create mode 100644 QuarkoniaToMuMu2024/info.yaml
 create mode 100644 QuarkoniaToMuMu2024/moore_mc_turbo.py
 create mode 100644 QuarkoniaToMuMu2024/spruce_turbo.py

diff --git a/QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py b/QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py
new file mode 100644
index 0000000000..affdbe1228
--- /dev/null
+++ b/QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py
@@ -0,0 +1,6 @@
+from Moore import options, Options
+from Moore.production import hlt1
+
+def main(options: Options):       
+    return hlt1(options, "--sequence=hlt1_pp_matching_no_ut_1000KHz", "--flagging")
+
diff --git a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
new file mode 100644
index 0000000000..b83f4336a1
--- /dev/null
+++ b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
@@ -0,0 +1,29 @@
+import os
+import sys
+sys.path.append(os.path.join(
+    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
+from helpers import dv_tree, dv_mctree
+from DaVinci import Options, make_config
+
+def main(options: Options):
+    decay_descriptor = {
+        "QQbar": "J/psi(1S) -> mu+ mu-",
+        "mup": "J/psi(1S) -> ^mu+ mu-",
+        "mum": "J/psi(1S) -> mu+ ^mu-",
+    }
+    decay_descriptor_mctree = {
+        "QQbar": "J/psi(1S) ==> mu+ mu-",
+        "mup": "J/psi(1S) ==> ^mu+ mu-",
+        "mum": "J/psi(1S) ==> mu+ ^mu-",
+    }
+
+    line_name = 'Hlt2_JpsiToMuMu'
+    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
+    user_algorithms = {
+            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_mctuple': [my_mctuple],
+            }
+    return make_config(options, user_algorithms) 
+
diff --git a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py
new file mode 100644
index 0000000000..c23b8ff27f
--- /dev/null
+++ b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py
@@ -0,0 +1,39 @@
+import os
+import sys
+sys.path.append(os.path.join(
+    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
+from helpers import dv_tree, dv_mctree
+from DaVinci import Options, make_config
+
+def main(options: Options):
+    decay_descriptor = {
+        "QQbar": "J/psi(1S) -> mu+ mu-",
+        "mup": "J/psi(1S) -> ^mu+ mu-",
+        "mum": "J/psi(1S) -> mu+ ^mu-",
+    }
+
+    decay_descriptor_mctree = {
+        "QQbar": "J/psi(1S) ==> mu+ mu-",
+        "mup": "J/psi(1S) ==> ^mu+ mu-",
+        "mum": "J/psi(1S) ==> mu+ ^mu-",
+    }
+
+
+    line_name0 = 'Hlt2QEE_DiMuonNoIP_massRange5'
+    my_tuple0 = dv_tree.tree_template(decay_descriptor, line_name0, True, [])
+    my_filter0 = dv_tree.line_prefilter(line_name0)
+    line_name1 = 'Hlt2QEE_DiMuonNoIP_massRange4'
+    my_tuple1 = dv_tree.tree_template(decay_descriptor, line_name1, True, [])
+    my_filter1 = dv_tree.line_prefilter(line_name1)
+    line_name2 = 'Hlt2QEE_DiMuonNoIP_massRange3'
+    my_tuple2 = dv_tree.tree_template(decay_descriptor, line_name2, True, [])
+    my_filter2 = dv_tree.line_prefilter(line_name2)
+    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
+    user_algorithms = {
+            "Alg_massRange5": [my_filter0, my_tuple0],
+            "Alg_massRange4": [my_filter1, my_tuple1],
+            "Alg_massRange3": [my_filter2, my_tuple2],
+            'Alg_mctuple': [my_mctuple],
+            }
+    return make_config(options, user_algorithms) 
+
diff --git a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
new file mode 100644
index 0000000000..e779f100ba
--- /dev/null
+++ b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
@@ -0,0 +1,30 @@
+import os
+import sys
+sys.path.append(os.path.join(
+    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
+from helpers import dv_tree, dv_mctree
+from DaVinci import Options, make_config
+
+def main(options: Options):
+    decay_descriptor = {
+        "QQbar": "psi(2S) -> mu+ mu-",
+        "mup": "psi(2S) -> ^mu+ mu-",
+        "mum": "psi(2S) -> mu+ ^mu-",
+    }
+
+    decay_descriptor_mctree = {
+        "QQbar": "psi(2S) ==> mu+ mu-",
+        "mup": "psi(2S) ==> ^mu+ mu-",
+        "mum": "psi(2S) ==> mu+ ^mu-",
+    }
+
+    line_name = 'Hlt2_Psi2SToMuMu'
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
+    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
+    user_algorithms = {
+            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_mctuple': [my_mctuple],
+            }
+    return make_config(options, user_algorithms)
+
diff --git a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py
new file mode 100644
index 0000000000..c662b904e3
--- /dev/null
+++ b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py
@@ -0,0 +1,28 @@
+import os
+import sys
+sys.path.append(os.path.join(
+    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
+from helpers import dv_tree, dv_mctree
+from DaVinci import Options, make_config
+
+def main(options: Options):
+    decay_descriptor = {
+        "QQbar": "J/psi(1S) -> mu+ mu-",
+        "mup": "J/psi(1S) -> ^mu+ mu-",
+        "mum": "J/psi(1S) -> mu+ ^mu-",
+    }
+    decay_descriptor_mctree = {
+        "QQbar": "psi(2S) ==> mu+ mu-",
+        "mup": "psi(2S) ==> ^mu+ mu-",
+        "mum": "psi(2S) ==> mu+ ^mu-",
+    }
+
+    line_name = 'Hlt2QEE_DiMuonNoIP_massRange5'
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
+    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
+    user_algorithms = {
+            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_mctuple': [my_mctuple],
+            }
+    return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
new file mode 100644
index 0000000000..69ae7b831f
--- /dev/null
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
@@ -0,0 +1,29 @@
+import os
+import sys
+sys.path.append(os.path.join(
+    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
+from helpers import dv_tree, dv_mctree
+from DaVinci import Options, make_config
+
+def main(options: Options):
+    decay_descriptor = {
+        "QQbar": "Upsilon(1S) -> mu+ mu-",
+        "mup": "Upsilon(1S) -> ^mu+ mu-",
+        "mum": "Upsilon(1S) -> mu+ ^mu-",
+    }
+    decay_descriptor_mctree = {
+        "QQbar": "Upsilon(1S) ==> mu+ mu-",
+        "mup": "Upsilon(1S) ==> ^mu+ mu-",
+        "mum": "Upsilon(1S) ==> mu+ ^mu-",
+    }
+
+    line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
+
+    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
+    user_algorithms = {
+            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_mctuple': [my_mctuple],
+            }
+    return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
new file mode 100644
index 0000000000..0212d0d8a4
--- /dev/null
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
@@ -0,0 +1,29 @@
+import os
+import sys
+sys.path.append(os.path.join(
+    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
+from helpers import dv_tree, dv_mctree
+from DaVinci import Options, make_config
+
+def main(options: Options):
+    decay_descriptor = {
+        "QQbar": "Upsilon(1S) -> mu+ mu-",
+        "mup": "Upsilon(1S) -> ^mu+ mu-",
+        "mum": "Upsilon(1S) -> mu+ ^mu-",
+    }
+    decay_descriptor_mctree = {
+        "QQbar": "Upsilon(2S) ==> mu+ mu-",
+        "mup": "Upsilon(2S) ==> ^mu+ mu-",
+        "mum": "Upsilon(2S) ==> mu+ ^mu-",
+    }
+
+    line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
+
+    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
+    user_algorithms = {
+            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_mctuple': [my_mctuple],
+            }
+    return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
new file mode 100644
index 0000000000..4c2b84a3f0
--- /dev/null
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
@@ -0,0 +1,29 @@
+import os
+import sys
+sys.path.append(os.path.join(
+    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
+from helpers import dv_tree, dv_mctree
+from DaVinci import Options, make_config
+
+def main(options: Options):
+    decay_descriptor = {
+        "QQbar": "Upsilon(1S) -> mu+ mu-",
+        "mup": "Upsilon(1S) -> ^mu+ mu-",
+        "mum": "Upsilon(1S) -> mu+ ^mu-",
+    }
+    decay_descriptor_mctree = {
+        "QQbar": "Upsilon(3S) ==> mu+ mu-",
+        "mup": "Upsilon(3S) ==> ^mu+ mu-",
+        "mum": "Upsilon(3S) ==> mu+ ^mu-",
+    }
+
+    line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
+
+    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
+    user_algorithms = {
+            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_mctuple': [my_mctuple],
+            }
+    return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/helpers/dv_mctree.py b/QuarkoniaToMuMu2024/helpers/dv_mctree.py
new file mode 100644
index 0000000000..2eaeb70d25
--- /dev/null
+++ b/QuarkoniaToMuMu2024/helpers/dv_mctree.py
@@ -0,0 +1,136 @@
+###############################################################################
+# (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Read and process a .xgen file with the new DaVinci configuration.
+rst_title: Run on XGEN files
+rst_description: This example reads and process a `.xgen` file.
+rst_running: lbexec DaVinciExamples.tupling.option_davinci_tupling_from_xgen:main $DAVINCIEXAMPLESROOT/example_data/Gauss_12143001_xgen.yaml
+rst_yaml: ../DaVinciExamples/example_data/Gauss_12143001_xgen.yaml
+"""
+import Functors as F
+import FunTuple.functorcollections as FC
+from FunTuple import FunctorCollection, FunTuple_MCParticles as FuntupleMC
+from PyConf.reading import get_particles, get_pvs, get_rec_summary
+from PyConf.Algorithms import PrintMCTree
+from DaVinci import Options, make_config
+from DaVinci.algorithms import create_lines_filter
+from DaVinciMCTools import MCTruthAndBkgCat
+from FunTuple.functorcollections import MCHierarchy, MCPrimaries, MCPromptDecay, Kinematics, SelectionInfo, HltTisTos, MCVertexInfo, MCKinematics, ParticleID, EventInfo
+from PyConf.reading import get_mc_particles, get_mc_header
+from PyConf.reading import get_odin  # get_decreports,
+from DecayTreeFitter import DecayTreeFitter
+
+def mctree_template(fields):
+    # FunTuple: define fields (branches)
+    #fields = {
+    #    "QQbar": "J/psi(1S) ==> mu+ mu-",
+    #    "mup": "J/psi(1S) ==> ^mu+ mu-",
+    #    "mum": "J/psi(1S) ==> mu+ ^mu-",
+    #}
+
+    # FunTuple: define input data
+    QQbar2mumu_line = get_mc_particles("/Event/HLT2/MC/Particles")
+
+    pvs = get_pvs()
+
+    #define event level variables
+    odin = get_odin()
+    rec_sum=get_rec_summary()
+
+    event_info = FunctorCollection({
+        "nPVs": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nPVs"),
+        "nTTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTracks"),
+        "nLongTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nLongTracks"),
+        "nDownstreamTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nDownstreamTracks"),
+        "nUpstreamTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUpstreamTracks"),
+        "nVeloTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloTracks"),
+        "nBackTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nBackTracks"),
+        #"nGhosts": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nGhosts"),
+        "nRich1Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich1Hits"),
+        "nRich2Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich2Hits"),
+        #"nVeloClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloClusters"),
+        "nVPClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVPClusters"),
+        #"nITClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nITClusters"),
+        #"nTTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTClusters"),
+        #"nUTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUTClusters"),
+        #"nOTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nOTClusters"),
+        "nFTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nFTClusters"),
+        #"nSPDhits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nSPDhits"),
+        "eCalTot": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"eCalTot"),
+        "hCalTot": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"hCalTot"),
+        "nEcalClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nEcalClusters"),
+        #"nMuonCoordsS0": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS0"),
+        #"nMuonCoordsS1": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS1"),
+        #"nMuonCoordsS2": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS2"),
+        #"nMuonCoordsS3": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS3"),
+        #"nMuonCoordsS4": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS4"),
+        #"nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"),
+    })
+
+    # FunTuple: define variables for the J/psi
+    composite_variables = FunctorCollection(
+        {
+            "ETA": F.ETA,
+            "PHI": F.PHI,
+            "TAU": F.MC_LIFETIME,
+            "ORIGIN_VX": F.ORIGIN_VX,
+            "ORIGIN_VY": F.ORIGIN_VY,
+            "ORIGIN_VZ": F.ORIGIN_VZ,
+            "END_VX": F.END_VX,
+            "END_VY": F.END_VY,
+            "END_VZ": F.END_VZ,
+            "M": F.MASS,
+            "FOURMOMENTUM": F.FOURMOMENTUM,
+            "PT": F.PT,
+        }
+     )                                                                    
+
+    # FunTuple: define variables for the muon
+    basic_variables = FunctorCollection(
+        {
+            "ETA": F.ETA,
+            "PHI": F.PHI,
+            "ORIGIN_VX": F.ORIGIN_VX,
+            "ORIGIN_VY": F.ORIGIN_VY,
+            "ORIGIN_VZ": F.ORIGIN_VZ,
+            "M": F.MASS,
+            "FOURMOMENTUM": F.FOURMOMENTUM,
+            "PT": F.PT,
+        }
+    )
+
+    # FunTuple: associate functor collections to field (branch) name
+    variables = {
+        "QQbar": composite_variables + FC.Kinematics(),
+        "mup": basic_variables + FC.Kinematics(),
+        "mum": basic_variables + FC.Kinematics(),
+    }
+
+    # FunTuple: define event-level variables using functor collections
+    mc_header = get_mc_header(extra_inputs=[QQbar2mumu_line])
+    evt_vars = event_info
+    #evt_vars = FC.MCPrimaries(mc_header=mc_header) + event_info
+
+    #printMC = PrintMCTree(
+    #    MCParticles=QQbar2mumu_line, ParticleNames=["J/psi(1S)"], OutputLevel=4
+    #)
+
+    tuple_QQbar2mumu = FuntupleMC(
+        name="MCDecayTreeTuple",
+        tuple_name="MCDecayTree",
+        fields=fields,
+        variables=variables,
+        event_variables=evt_vars,
+        inputs=QQbar2mumu_line,
+    )
+
+    return tuple_QQbar2mumu
+
diff --git a/QuarkoniaToMuMu2024/helpers/dv_tree.py b/QuarkoniaToMuMu2024/helpers/dv_tree.py
new file mode 100644
index 0000000000..3e0b84bbd6
--- /dev/null
+++ b/QuarkoniaToMuMu2024/helpers/dv_tree.py
@@ -0,0 +1,511 @@
+###############################################################################
+# (c) Copyright 2021-2022 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Read an HLT2 file and create an ntuple with the new DaVinci configuration.
+"""
+import Functors as F
+import FunTuple.functorcollections as FC
+from FunTuple import FunctorCollection
+from FunTuple import FunTuple_Particles as Funtuple
+from PyConf.reading import get_particles, get_pvs, get_rec_summary
+from DaVinci.algorithms import create_lines_filter
+from DaVinciMCTools import MCTruthAndBkgCat
+from FunTuple.functorcollections import MCHierarchy, MCPrimaries, MCPromptDecay, Kinematics, SelectionInfo, HltTisTos, MCVertexInfo, MCKinematics, ParticleID, EventInfo
+from PyConf.reading import get_odin  # get_decreports,
+from DecayTreeFitter import DecayTreeFitter
+
+_basic = "basic"
+_composite = "composite"
+_toplevel = "toplevel"
+
+#def all_variables(pvs, dtf, mctruth, ptype, candidates=None, ftAlg=None):
+def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None):
+    """
+    function that returns dictionary of functors that work.
+    
+    functors are listed in order of https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/selection/thor_functors_reference.html#module-Functo
+    """
+    if ptype not in [_basic, _composite]:
+        Exception(f"I want {_basic} or {_composite}. Got {ptype}")
+    all_vars = FunctorCollection({})
+    
+    comp = _composite == ptype or _toplevel == ptype  # is composite
+    basic = _basic == ptype  # is not composite
+    top = _toplevel == ptype  # the B
+
+    # First import everything that comes in functorcollections
+    all_vars += FC.Kinematics()
+    if basic:
+        all_vars += FC.ParticleID(extra_info=True)
+    all_vars += FC.MCKinematics(mctruth_alg=mctruth)
+    all_vars += FC.MCHierarchy(mctruth_alg=mctruth)
+    #all_vars += FC.MCPrimaryVertexInfo(mctruth_alg=mctruth)
+    #Hlt1_decisions = ["Hlt1TrackMVADecision", "Hlt1TwoTrackMVADecision"]
+    #if candidates:
+        #all_vars += FC.HltTisTos(
+            #selection_type="Hlt", trigger_lines=Hlt1_decisions, data=candidates
+        #)
+    #if comp:
+    #    all_vars += FC.MCVertexInfo(mctruth_alg=mctruth)
+    #if top:
+    #    all_vars += FC.MCPromptDecay(mctruth_alg=mctruth)
+    
+    #
+    # FTAlg not yet implemented
+    # For Track isolation see weightedrelations_trackvariables
+    #
+    # Now all other functors
+    
+    # ALL : Not useful for tupling
+    
+    if comp:
+        all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)})
+        
+        all_vars.update({"BKGCAT": mctruth.BkgCat})
+        
+    if comp:  # all these require a vertex
+        all_vars.update({"BPVCORRM": F.BPVCORRM(pvs)})
+        all_vars.update({"BPVCORRMERR": F.BPVCORRMERR(pvs)})
+        all_vars.update({"BPVDIRA": F.BPVDIRA(pvs)})
+        all_vars.update({"BPVDLS": F.BPVDLS(pvs)})
+        all_vars.update({"BPVETA": F.BPVETA(pvs)})
+        all_vars.update({"BPVFD": F.BPVFD(pvs)})
+        all_vars.update({"BPVFDCHI2": F.BPVFDCHI2(pvs)})
+        all_vars.update({"BPVFDIR": F.BPVFDIR(pvs)})
+        all_vars.update({"BPVFDVEC": F.BPVFDVEC(pvs)})
+
+    all_vars.update({"BPVIP": F.BPVIP(pvs)})
+    all_vars.update({"BPVIPCHI2": F.BPVIPCHI2(pvs)})
+    all_vars.update({"BPVX": F.BPVX(pvs)})
+    all_vars.update({"BPVY": F.BPVY(pvs)})
+    all_vars.update({"BPVZ": F.BPVZ(pvs)})
+    # When storing variable length array one can
+    # give a custom branch name for the index.
+    # This can be achieved by enclosing custom index
+    # name within square brackets (see code below).
+    # The branch name ("nPV") will correspond to the
+    # index of the PV. If no index branch name given i.e.
+    # all_vars.update({ 'ALLPVX'] the default "indx" is used.
+    #all_vars.update({"ALLPVX[nPVs]": F.ALLPVX(pvs)})
+    #all_vars.update({"ALLPVY[nPVs]": F.ALLPVY(pvs)})
+    #all_vars.update({"ALLPVZ[nPVs]": F.ALLPVZ(pvs)})
+    all_vars.update({"ALLPVX": F.ALLPVX(pvs)})
+    all_vars.update({"ALLPVY": F.ALLPVY(pvs)})
+    all_vars.update({"ALLPVZ": F.ALLPVZ(pvs)})
+
+    if comp:  # all these require a vertex
+        #all_vars.update({"ALLPV_FD[nPVs]": F.ALLPV_FD(pvs)})
+        #all_vars.update({"ALLPV_IP[nPVs]": F.ALLPV_IP(pvs)})
+        all_vars.update({"ALLPV_FD": F.ALLPV_FD(pvs)})
+        all_vars.update({"ALLPV_IP": F.ALLPV_IP(pvs)})
+        all_vars.update({"BPVLTIME": F.BPVLTIME(pvs)})
+        all_vars.update({"BPVVDRHO": F.BPVVDRHO(pvs)})
+        all_vars.update({"BPVVDX": F.BPVVDX(pvs)})
+        all_vars.update({"BPVVDY": F.BPVVDY(pvs)})
+        all_vars.update({"BPVVDZ": F.BPVVDZ(pvs)})
+    
+    all_vars.update({"CHARGE": F.CHARGE})
+    all_vars.update({"CHI2": F.CHI2})
+    all_vars.update({"CHI2DOF": F.CHI2DOF})
+    if top:  # apply this only to B
+        all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)})  # example of CHILD
+        all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)})
+        all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ})
+    
+    # if basic: all_vars.update({ 'CLOSESTTOBEAM' : F.CLOSESTTOBEAM # 'Track__ClosestToBeamState' object has no attribute 'to_json'
+    # COMB
+    # if basic: all_vars.update({ 'COV' : F.COV # 'Track__Covariance' object has no attribute 'to_json'
+
+    if comp:
+        all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)})
+        all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)})
+        all_vars.update({"END_VRHO": F.END_VRHO})
+        all_vars.update({"END_VX": F.END_VX})
+        all_vars.update({"END_VY": F.END_VY})
+        all_vars.update({"END_VZ": F.END_VZ})
+    
+    # duplicated from FC   all_vars.update({"ENERGY" : F.ENERGY})
+    all_vars.update({"ETA": F.ETA})
+    all_vars.update({"FOURMOMENTUM": F.FOURMOMENTUM})
+    all_vars.update({"ISBASIC": F.ISBASICPARTICLE})
+
+    if basic:
+        all_vars.update({"GHOSTPROB": F.GHOSTPROB})
+        all_vars.update({"ISMUON": F.ISMUON})
+        all_vars.update({"INMUON": F.INMUON})
+        all_vars.update({"INECAL": F.INECAL})
+        all_vars.update({"INHCAL": F.INHCAL})
+        all_vars.update({"HASBREM": F.HASBREM})
+        all_vars.update({"BREMENERGY": F.BREMENERGY})
+        all_vars.update({"BREMBENDCORR": F.BREMBENDCORR})
+        all_vars.update({"BREMPIDE": F.BREMPIDE})
+        all_vars.update({"ECALPIDE": F.ECALPIDE})
+        all_vars.update({"ECALPIDMU": F.ECALPIDMU})
+        all_vars.update({"HCALPIDE": F.HCALPIDE})
+        all_vars.update({"HCALPIDMU": F.HCALPIDMU})
+        all_vars.update({"ELECTRONSHOWEREOP": F.ELECTRONSHOWEREOP})
+        all_vars.update({"CLUSTERMATCH": F.CLUSTERMATCH_CHI2})
+        all_vars.update({"ELECTRONMATCH": F.ELECTRONMATCH_CHI2})
+        all_vars.update({"BREMHYPOMATCH": F.BREMHYPOMATCH_CHI2})
+        all_vars.update({"ELECTRONENERGY": F.ELECTRONENERGY})
+        all_vars.update({"BREMHYPOENERGY": F.BREMHYPOENERGY})
+        all_vars.update({"BREMHYPODELTAX": F.BREMHYPODELTAX})
+        all_vars.update({"ELECTRONID": F.ELECTRONID})
+        all_vars.update({"HCALEOP": F.HCALEOP})
+        # Note: the observables for the two functors below are (TRACK_MOM_X, TRACK_MOM_Y, TRACK_MOM_Z})
+        # and (TRACK_POS_CLOSEST_TO_BEAM_X, TRACK_POS_CLOSEST_TO_BEAM_Y, TRACK_POS_CLOSEST_TO_BEAM_Z),
+        # which is why the trailing underscore in the name is added i.e. "TRACK_MOM_" and "TRACK_POS_CLOSEST_TO_BEAM_"
+        all_vars.update({"TRACK_MOM_": F.TRACK_MOMVEC})
+        all_vars.update({"TRACK_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM})
+        
+        all_vars.update({"IS_ABS_ID_pi": F.IS_ABS_ID("pi+")})
+        all_vars.update({"IS_ID_pi": F.IS_ID("pi-")})
+        all_vars.update({"PDG_MASS_pi": F.PDG_MASS("pi+")})
+        all_vars.update({"SIGNED_DELTA_MASS_pi": F.SIGNED_DELTA_MASS("pi+")})
+        all_vars.update({"ABS_DELTA_MASS_pi": F.ABS_DELTA_MASS("pi+")})
+        all_vars.update({"IS_NOT_H": F.IS_NOT_H})
+        all_vars.update({"IS_PHOTON": F.IS_PHOTON})
+
+    #if dtf:
+    #    all_vars.update({"DTF_PT": dtf(F.PT)})
+    #    all_vars.update({"DTF_BPVIPCHI2": dtf(F.BPVIPCHI2(pvs))})
+        
+    #if top and dtf:
+    #    all_vars.update({"DTF_NITER": dtf.NITER})
+    #    all_vars.update({"DTF_CHI2": dtf.CHI2})
+    #    all_vars.update({"DTF_NDOF": dtf.NDOF})
+    #    all_vars.update({"DTF_CHI2DOF": dtf.CHI2DOF})
+         
+    #if comp and dtf:
+    #    all_vars.update({"DTF_MASS": dtf.MASS})
+    #    all_vars.update({"DTF_MASSERR": dtf.MASSERR})
+    #    all_vars.update({"DTF_P": dtf.P})
+    #    all_vars.update({"DTF_PERR": dtf.PERR})
+    #    all_vars.update({"DTF_TAU": dtf.TAU})
+    #    all_vars.update({"DTF_TAUERR": dtf.TAUERR})
+    #    all_vars.update({"DTF_FD": dtf.FD})
+    #    all_vars.update({"DTF_FDERR": dtf.FDERR})
+
+    all_vars.update({"MASS": F.MASS})
+    #if top:  # B
+    #    all_vars.update({"MASSWITHHYPOTHESES": F.MASSWITHHYPOTHESES((939.0, 939.0))})
+    #elif comp:  # Ds
+    #    all_vars.update(
+    #        {"MASSWITHHYPOTHESES": F.MASSWITHHYPOTHESES((493.7, 493.7, 139.6))}
+    #    )
+    if comp:
+        all_vars.update({"MAXPT": F.MAX(F.PT)})
+        all_vars.update({"MAXDOCA": F.MAXSDOCA})
+        all_vars.update({"MAXDOCACHI2": F.MAXSDOCACHI2})
+        # the above in cut versions.
+         
+    # duplicated from FC    all_vars.update({ 'MC_MOTHER_ID' : F.VALUE_OR(0) @ mctruth(
+    # duplicated from FC        F.MC_MOTHER(1, F.PARTICLE_ID))})
+
+    if comp:
+        all_vars.update({"MINPT": F.MIN(F.PT)})
+    all_vars.update({"MINIP": F.MINIP(pvs)})
+    all_vars.update({"MINIPCHI2": F.MINIPCHI2(pvs)})
+    
+    if basic:
+        all_vars.update({"TRACKPT": F.TRACK_PT})
+        all_vars.update({"TRACKHISTORY": F.VALUE_OR(-1) @ F.TRACKHISTORY @ F.TRACK})
+        all_vars.update({"QOVERP": F.QOVERP @ F.TRACK})
+        all_vars.update({"NDOF": F.VALUE_OR(-1) @ F.NDOF @ F.TRACK})
+        all_vars.update({"NFTHITS": F.VALUE_OR(-1) @ F.NFTHITS @ F.TRACK})
+        all_vars.update({"NHITS": F.VALUE_OR(-1) @ F.NHITS @ F.TRACK})
+        all_vars.update({"NUTHITS": F.VALUE_OR(-1) @ F.NUTHITS @ F.TRACK})
+        all_vars.update({"NVPHITS": F.VALUE_OR(-1) @ F.NVPHITS @ F.TRACK})
+        all_vars.update({"TRACKHASVELO": F.VALUE_OR(-1) @ F.TRACKHASVELO @ F.TRACK})
+        all_vars.update({"TRACKHASUT": F.VALUE_OR(-1) @ F.TRACKHASUT @ F.TRACK})
+         
+    all_vars.update({"OBJECT_KEY": F.OBJECT_KEY})
+
+    # duplicated from FC        all_vars.update({ 'ORIGIN_VX' : mctruth(F.ORIGIN_VX) })
+    # duplicated from FC        all_vars.update({ 'ORIGIN_VY' : mctruth(F.ORIGIN_VY) })
+    # duplicated from FC        all_vars.update({ 'ORIGIN_VZ' : mctruth(F.ORIGIN_VZ) })
+    
+    # duplicated from FC        all_vars.update({"P" : F.P})
+    # duplicated from FC        all_vars.update({"PARTICLE_ID" : F.PARTICLE_ID})
+    all_vars.update({"PHI": F.PHI})
+    
+    # duplicated from FC    if basic:
+    # duplicated from FC        all_vars.update({"PID_E" : F.PID_E})
+    # duplicated from FC        all_vars.update({"PID_K" : F.PID_K})
+    # duplicated from FC        all_vars.update({"PID_MU" : F.PID_MU})
+    # duplicated from FC        all_vars.update({"PID_P" : F.PID_P})
+    # duplicated from FC        all_vars.update({"PID_PI" : F.PID_PI})
+    # duplicated from FC        #all_vars.update({"PROBNN_D" : F.PROBNN_D})
+    # duplicated from FC        all_vars.update({"PROBNN_E" : F.PROBNN_E})
+    # duplicated from FC        all_vars.update({"PROBNN_GHOST" : F.PROBNN_GHOST})
+    # duplicated from FC        all_vars.update({"PROBNN_K" : F.PROBNN_K})
+    # duplicated from FC        all_vars.update({"PROBNN_MU" : F.PROBNN_MU})
+    # duplicated from FC        all_vars.update({"PROBNN_P" : F.PROBNN_P})
+    # duplicated from FC        all_vars.update({"PROBNN_PI" : F.PROBNN_PI})
+
+    # duplicated from FC    all_vars.update({ 'PT' : F.PT })
+    # duplicated from FC    all_vars.update({ 'PX' : F.PX })
+    # duplicated from FC    all_vars.update({ 'PY' : F.PY })
+    # duplicated from FC    all_vars.update({ 'PZ' : F.PZ })
+    all_vars.update({"ABS_PX": F.ABS @ F.PX})
+    
+    all_vars.update({"REFERENCEPOINT_X": F.REFERENCEPOINT_X})
+    all_vars.update({"REFERENCEPOINT_Y": F.REFERENCEPOINT_Y})
+    all_vars.update({"REFERENCEPOINT_Z": F.REFERENCEPOINT_Z})
+
+    if comp:
+        all_vars.update({"SDOCA": F.SDOCA(1, 2)})
+        all_vars.update({"SDOCACHI2": F.SDOCACHI2(1, 2)})
+    if basic:
+        all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE})
+        
+    if comp:
+        all_vars.update({"SUBCOMB12_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 2))})
+        all_vars.update({"SUMPT": F.SUM(F.PT)})
+        
+    if basic:
+        all_vars.update({"TX": F.TX})
+        all_vars.update({"TY": F.TY})
+        
+    print(f"### For {ptype} returning variables {all_vars.functor_dict.keys()}")
+    return all_vars
+
+
+def event_variables(PVs, ODIN, decreports, lines, hlt1lines):
+    """
+    event variables
+    """
+     
+    evt_vars = FunctorCollection({})
+    evt_vars += FC.EventInfo()
+    
+    evt_vars += FC.SelectionInfo(selection_type="Hlt2", trigger_lines=lines)
+    evt_vars += FC.SelectionInfo(selection_type="Hlt1", trigger_lines=hlt1lines)
+    # duplicated from FC    if ODIN:
+    # duplicated from FC        evt_vars.update({ 'BUNCHCROSSING_ID' : F.BUNCHCROSSING_ID(ODIN) })
+    # duplicated from FC        evt_vars.update({ 'BUNCHCROSSING_TYPE' : F.BUNCHCROSSING_TYPE(ODIN) })
+
+    if decreports:                                                                                                                       
+        evt_vars.update(
+            {
+                "DECISIONS": F.DECISIONS(
+                    Lines=[bd2dsk_line + "Decision"], DecReports=decreports
+                )
+            }
+        )
+        evt_vars.update(
+            {
+                "DECREPORTS_FILTER": F.DECREPORTS_FILTER(
+                    Lines=[bd2dsk_line + "Decision"], DecReports=decreports
+                )
+            }
+        )
+         
+    if ODIN:
+        evt_vars.update({"EVENTTYPE": F.EVENTTYPE(ODIN)})
+
+    # duplicated from FC        evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN) })
+    # duplicated from FC        evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN) })
+    
+    evt_vars.update({"PV_SIZE": F.SIZE(PVs)})
+    # duplicated from FC        evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN) })
+    # duplicated from FC        evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN) })
+    
+    if decreports:
+        evt_vars.update({"TCK": F.TCK(decreports)})
+         
+    print(f"### For event returning variables {evt_vars.functor_dict.keys()}")
+    return evt_vars
+
+
+def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions):
+    evtpath_prefix = "/Event/Spruce/"
+    if isturbo:
+        evtpath_prefix = "/Event/HLT2/"
+
+    QQbar2mumu_data = get_particles(evtpath_prefix+f"{line_name}/Particles")
+
+    pvs = get_pvs()
+
+    Hlt1_decisions = [
+# Global line
+        "Hlt1GlobalDecision", "Hlt1PhysDecision", 
+# Physics lines
+        "Hlt1TrackMVADecision", "Hlt1TwoTrackMVADecision", "Hlt1D2KKDecision", "Hlt1D2KPiDecision", "Hlt1D2PiPiDecision", "Hlt1Dst2D0PiDecision", "Hlt1KsToPiPiDecision", "Hlt1KsToPiPiDoubleMuonMisIDDecision", "Hlt1TwoTrackKsDecision", "Hlt1TwoKsDecision", "Hlt1LambdaLLDetachedTrackDecision", "Hlt1XiOmegaLLLDecision", "Hlt1SingleHighPtMuonDecision", "Hlt1SingleHighPtMuonNoMuIDDecision", "Hlt1DiMuonHighMassDecision", "Hlt1DiMuonDisplacedDecision", "Hlt1DiMuonSoftDecision", "Hlt1TrackMuonMVADecision", "Hlt1DiMuonNoIP_SSDecision", "Hlt1DiMuonDrellYan_VLowMassDecision", "Hlt1DiMuonDrellYan_VLowMass_SSDecision", "Hlt1DiMuonDrellYanDecision", "Hlt1DiMuonDrellYan_SSDecision", "Hlt1DetJpsiToMuMuPosTagLineDecision", "Hlt1DetJpsiToMuMuNegTagLineDecision", "Hlt1TrackElectronMVADecision", "Hlt1SingleHighPtElectronDecision", "Hlt1DiElectronDisplacedDecision", "Hlt1SingleHighEtDecision", "Hlt1DiPhotonHighMassDecision", "Hlt1Pi02GammaGammaDecision", "Hlt1DiElectronHighMass_SSDecision", "Hlt1DiElectronHighMassDecision", "Hlt1DiMuonNoIPDecision"
+## alignment lines
+#        "Hlt1RICH1AlignmentDecision", "Hlt1RICH2AlignmentDecision", "Hlt1D2KPiAlignmentDecision", "Hlt1Dst2D0PiAlignmentDecision", "Hlt1MaterialVertexSeedsDownstreamzDecision", "Hlt1MaterialVertexSeeds_DWFSDecision", "Hlt1DiMuonHighMassAlignmentDecision", "Hlt1DiMuonJpsiMassAlignmentDecision", "Hlt1OneMuonTrackLineDecision", "Hlt1BeamGasDecision",
+## smog2 lines
+#        "Hlt1SMOG2D2KpiDecision", "Hlt1VeloMicroBiasDecision", "Hlt1SMOG2etacToppDecision", "Hlt1SMOG2KsTopipiDecision", "Hlt1SMOG2etacToppDecision", "Hlt1SMOG2KsTopipiDecision", "Hlt1SMOG22BodyGenericDecision", "Hlt1SMOG22BodyGenericLowPtDecision", "Hlt1SMOG2SingleTrackVeryHighPtDecision", "Hlt1SMOG2SingleTrackHighPtDecision", "Hlt1SMOG2DiMuonHighMassDecision", "Hlt1SMOG2SingleMuonDecision", "Hlt1SMOG2L0ToppiDecision",
+## bgi lines
+#         "Hlt1BGIPseudoPVsNoBeamDecision", "Hlt1BGIPseudoPVsBeamOneDecision", "Hlt1BGIPseudoPVsBeamTwoDecision", "Hlt1BGIPseudoPVsUpBeamBeamDecision", "Hlt1BGIPseudoPVsDownBeamBeamDecision", "Hlt1BGIPseudoPVsIRBeamBeamDecision", "Hlt1BGIPVsCylNoBeamDecision", "Hlt1BGIPVsCylBeamOneDecision", "Hlt1BGIPVsCylBeamTwoDecision", "Hlt1BGIPVsCylUpBeamBeamDecision", "Hlt1BGIPVsCylDownBeamBeamDecision", "Hlt1BGIPVsCylIRBeamBeamDecision", "Hlt1BGIVeloClustersMicroBiasDecision", "Hlt1BGICaloDigitsDecision", "Hlt1BGIPlumeActivityDecision",
+## setup hlt1 nodes lines
+#        "Hlt1ODINCalibDecision", "Hlt1TAEPassthroughDecision", "Hlt1ErrorBankDecision", "Hlt1VeloMicroBiasVeloClosingDecision", "Hlt1GECPassthroughDecision", "Hlt1SMOG2BENoBiasDecision", "Hlt1SMOG2PassThroughLowMult5Decision", "Hlt1SMOG2BELowMultElectronsDecision", "Hlt1SMOG2MinimumBiasDecision", "Hlt1PassthroughPVinSMOG2Decision"
+     ]
+
+
+    composite_variables = FunctorCollection({
+        #"ID": F.PARTICLE_ID,
+        #"KEY": F.OBJECT_KEY,
+        #"PT": F.PT,
+        #"PX": F.PX,
+        #"PY": F.PY,
+        #"PZ": F.PZ,
+        #"ENERGY": F.ENERGY,
+        #"P": F.P,
+        #"M": F.MASS,
+        #"ETA": F.ETA,
+        #"PHI": F.PHI,
+        #"ENDVERTEX_CHI2NDOF": F.CHI2DOF,
+        #"FOURMOMENTUM": F.FOURMOMENTUM,
+        #"BPVDIRA": F.BPVDIRA(pvs),
+        #"BPVX": F.BPVX(pvs),
+        #"BPVY": F.BPVY(pvs),
+        #"BPVZ": F.BPVZ(pvs),
+        #"END_VX": F.END_VX,
+        #"END_VY": F.END_VY,
+        #"END_VZ": F.END_VZ,
+        "END_VZ_ERR":F.SQRT @ F.CALL(2,2) @ F.POS_COV_MATRIX @ F.ENDVERTEX,
+        "END_VY_ERR":F.SQRT @ F.CALL(1,1) @ F.POS_COV_MATRIX @ F.ENDVERTEX,
+        "END_VX_ERR":F.SQRT @ F.CALL(0,0) @ F.POS_COV_MATRIX @ F.ENDVERTEX,
+        "BPVZ_ERR": F.SQRT @ F.CALL(2,2) @ F.POS_COV_MATRIX @ F.BPV(pvs),
+        "BPVY_ERR": F.SQRT @ F.CALL(1,1) @ F.POS_COV_MATRIX @ F.BPV(pvs),
+        "BPVX_ERR": F.SQRT @ F.CALL(0,0) @ F.POS_COV_MATRIX @ F.BPV(pvs),
+        #"TAU": F.BPVLTIME(pvs),
+        #"BPVFDCHI2": F.BPVFDCHI2(pvs),
+        #"BPVIPCHI2": F.BPVIPCHI2(pvs)
+    })
+
+    #composite_variables += Kinematics()
+    #composite_variables += ParticleID(extra_info=True)
+    composite_variables += HltTisTos( selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=QQbar2mumu_data)
+    if not isturbo:
+        composite_variables += HltTisTos( selection_type="Hlt2", trigger_lines=Hlt2_decisions, data=QQbar2mumu_data)
+
+    daughter_variables = FunctorCollection({
+        #"ID": F.PARTICLE_ID,
+        #"PT": F.PT,
+        #"PX": F.PX,
+        #"PY": F.PY,
+        #"PZ": F.PZ,
+        #"M": F.MASS,
+        #"ENERGY": F.ENERGY,
+        #"P": F.P,
+        #"ETA": F.ETA,
+        #"PHI": F.PHI,
+        #"Track_CHI2NDOF": F.CHI2DOF,
+        #"ProbNNmu": F.PROBNN_MU,
+        #"PIDmu": F.PID_MU,
+        #"IsMuon": F.ISMUON,
+        #"GhostProb": F.GHOSTPROB,
+        #"FOURMOMENTUM": F.FOURMOMENTUM,
+        "PERR": F.SQRT @ F.PERR2,
+        "PZERR": F.SQRT @ F.CALL(2,2) @ F.THREE_MOM_COV_MATRIX,
+        "TXERR": F.SQRT @ F.CALL(2,2) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement")@ F.TRACK,
+        "TYERR": F.SQRT @ F.CALL(3,3) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement")@ F.TRACK,
+        "COVTXTY": F.CALL(2,3) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement")@ F.TRACK,
+    })
+
+    #daughter_variables += Kinematics()
+    #daughter_variables += ParticleID(extra_info=True)
+
+#    line_prefilter = create_lines_filter(name=f"HLT_PASS{line_name}", lines=[line_name])
+
+    #define event level variables
+    odin = get_odin()
+    decreports = None
+    rec_sum=get_rec_summary()
+    event_info = event_variables(pvs, odin, decreports, [line_name], Hlt1_decisions) + FunctorCollection({
+        "nPVs": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nPVs"),
+        "nTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTracks"),
+        "nLongTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nLongTracks"),
+        "nDownstreamTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nDownstreamTracks"),
+        "nUpstreamTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUpstreamTracks"),
+        "nVeloTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloTracks"),
+        "nBackTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nBackTracks"),
+        "nGhosts": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nGhosts"),
+        "nRich1Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich1Hits"),
+        "nRich2Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich2Hits"),
+        "nVeloClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloClusters"),
+        "nVPClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVPClusters"),
+        "nITClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nITClusters"),
+        "nTTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTClusters"),
+        "nUTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUTClusters"),
+        "nOTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nOTClusters"),
+        "nFTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nFTClusters"),
+        "nSPDhits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nSPDhits"),
+        "eCalTot": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"eCalTot"),
+        "hCalTot": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"hCalTot"),
+        "nEcalClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nEcalClusters"),
+        "nMuonCoordsS0": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS0"),
+        "nMuonCoordsS1": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS1"),
+        "nMuonCoordsS2": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS2"),
+        "nMuonCoordsS3": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS3"),
+        "nMuonCoordsS4": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS4"),
+        "nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"),
+        "ALLPVX": F.ALLPVX(pvs),
+        "ALLPVY": F.ALLPVY(pvs),
+        "ALLPVZ": F.ALLPVZ(pvs),
+    })
+
+    # get trueid bkgcat info
+    MC_TRUTH = MCTruthAndBkgCat(QQbar2mumu_data, name='MCTruthAndBkgCat_'+line_name)
+    MCMOTHER_ID = lambda n: F.VALUE_OR(0) @ MC_TRUTH(F.MC_MOTHER(n, F.PARTICLE_ID))
+    MCMOTHER_KEY = lambda n: F.VALUE_OR(-1) @ MC_TRUTH(F.MC_MOTHER(n, F.OBJECT_KEY))
+
+    trueid_bkgcat_info = FunctorCollection({
+        #"TRUEID": F.VALUE_OR(0) @ MC_TRUTH(F.PARTICLE_ID),
+        "TRUEKEY": F.VALUE_OR(-1) @ MC_TRUTH(F.OBJECT_KEY),
+        #"TRUEPT": MC_TRUTH(F.PT),
+        #"TRUEPX": MC_TRUTH(F.PX),
+        #"TRUEPY": MC_TRUTH(F.PY),
+        #"TRUEPZ": MC_TRUTH(F.PZ),
+        #"TRUEENERGY": MC_TRUTH(F.ENERGY),
+        #"TRUEP": MC_TRUTH(F.P),
+        "TRUEM": MC_TRUTH(F.MASS),
+        "TRUEETA": MC_TRUTH(F.ETA),
+        "TRUEPHI": MC_TRUTH(F.PHI),
+        "TRUEFOURMOMENTUM": MC_TRUTH(F.FOURMOMENTUM),
+        #"MC_MOTHER_ID": MCMOTHER_ID(1),
+        #"MC_MOTHER_KEY": MCMOTHER_KEY(1),
+        #"MC_GD_MOTHER_ID": MCMOTHER_ID(2),
+        #"MC_GD_MOTHER_KEY": MCMOTHER_KEY(2),
+        #"MC_GD_GD_MOTHER_ID": MCMOTHER_ID(3),
+        #"MC_GD_GD_MOTHER_KEY": MCMOTHER_KEY(3),
+        "TRUEORIGIN_VX": MC_TRUTH(F.ORIGIN_VX),
+        "TRUEORIGIN_VY": MC_TRUTH(F.ORIGIN_VY),
+        "TRUEORIGIN_VZ": MC_TRUTH(F.ORIGIN_VZ),
+        #"TRUEEND_VX": MC_TRUTH(F.END_VX),
+        #"TRUEEND_VY": MC_TRUTH(F.END_VY),
+        #"TRUEEND_VZ": MC_TRUTH(F.END_VZ),
+        "BKGCAT": MC_TRUTH.BkgCat,
+    })
+
+    variables = {
+        "QQbar": composite_variables + all_variables(pvs, MC_TRUTH, _composite) + trueid_bkgcat_info,
+        "mup": daughter_variables + all_variables(pvs, MC_TRUTH, _basic) + trueid_bkgcat_info,
+        "mum": daughter_variables + all_variables(pvs, MC_TRUTH, _basic) + trueid_bkgcat_info, 
+    }
+
+    #define FunTuple instance
+    my_tuple = Funtuple(
+        name=line_name,
+        tuple_name="DecayTree",
+        fields=decay_descriptor,
+        variables=variables,
+        event_variables=event_info,
+        store_multiple_cand_info = True,
+        inputs=QQbar2mumu_data)
+
+    return my_tuple
+
+def line_prefilter(line_name):
+    return create_lines_filter(name=f"HLT_PASS{line_name}", lines=[line_name])
+
diff --git a/QuarkoniaToMuMu2024/info.yaml b/QuarkoniaToMuMu2024/info.yaml
new file mode 100644
index 0000000000..c1cc8e8943
--- /dev/null
+++ b/QuarkoniaToMuMu2024/info.yaml
@@ -0,0 +1,107 @@
+defaults:
+    application: DaVinci/v64r8
+    wg: BandQ
+    inform:
+        - zihan.gao@cern.ch
+        - mengzhen.wang@cern.ch
+        - zehua.xu@cern.ch
+
+# mc configuration
+{%- set entrypoints = [
+  ("Jpsi_QEE", "Jpsi2mumu_QEE", "24142001", "turbo", "TurboPass"),
+  ("Psi2S_QEE", "Psi2S2mumu_QEE", "28142001", "turbo", "TurboPass"),
+  ("Jpsi", "Jpsi2mumu", "24142001", "turbo", "TurboPass"),
+  ("Psi2S", "Psi2S2mumu", "28142001", "turbo", "TurboPass"),
+  ("Upsilon1S", "Upsilon1S", "18112001", "turbo", "TurboPass"),
+  ("Upsilon2S", "Upsilon2S", "18112011", "turbo", "TurboPass"),
+  ("Upsilon3S", "Upsilon3S", "18112021", "turbo", "TurboPass"),
+]%}
+
+{%- set MC_conditions = [
+  ("MagDown", "MagDown", "7.6", "7_6", "dddb-20240427", "sim10-2024.Q1.2-v1.1-md100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
+  ("MagDown", "MagDown", "5.7", "5_7", "dddb-20240427", "sim10-2024.Q1.2-v1.1-md100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
+  ("MagDown", "MagDown", "4.3", "4_3", "dddb-20240427", "sim10-2024.Q1.2-v1.1-md100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
+  ("MagUp", "MagUp", "7.6", "7_6", "dddb-20240427", "sim10-2024.Q1.2-v1.1-mu100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
+]%}
+
+{%- set hlt_conditions = [
+  ("hlt1_pp_matching_no_ut_1000KHz", "hlt1v1"),
+]%}
+
+
+
+{%- for module, channel, eventtype, fullturbo, dv_input_process in entrypoints %}
+  {%- for polarity_mc, polarity_mc_jobtitle, nu, n_u, dddb, conddb, mcversion_jobtitle, BKK_label1, BKK_label2, simversion in MC_conditions %}
+    {% for hlt1_condition, hlt1_condition_jobtitle in hlt_conditions %}
+
+MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT1:
+    application: "Moore/v55r11@x86_64_v2-el9-gcc13+detdesc-opt"
+    input:
+        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/{{ eventtype }}/DIGI"
+        dq_flags:
+            - OK
+        keep_running: true
+        n_test_lfns: 1
+    output: QQbar2mumu_MC24_HLT1.DST
+    options: 
+        entrypoint: QuarkoniaToMuMu2024.allen_mc_{{hlt1_condition}}:main
+        extra_options:
+            input_raw_format: 0.5
+            conddb_tag: {{ conddb  }}
+            dddb_tag: {{ dddb  }}
+            input_type: "ROOT"
+            output_type: "ROOT"
+            simulation: True
+            data_type: "Upgrade"
+            scheduler_legacy_mode: False
+            compression:
+              algorithm: ZSTD
+              level: 1
+              max_buffer_size: 1048576
+
+MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT2:
+    application: "Moore/v55r11@x86_64_v2-el9-gcc13+detdesc-opt"
+    input:
+        job_name: MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT1
+    output: QQbar2mumu_MC24_HLT2_{{fullturbo}}.DST
+    options:
+        entrypoint: QuarkoniaToMuMu2024.moore_mc_{{fullturbo}}:main
+        extra_options:
+            conddb_tag: {{ conddb }}
+            dddb_tag: {{ dddb }}
+            input_type: "ROOT"
+            input_raw_format: 0.5
+            output_type: "ROOT"
+            simulation: True
+            data_type: "Upgrade"
+            scheduler_legacy_mode: False
+            compression:
+              algorithm: ZSTD
+              level: 1
+              max_buffer_size: 1048576
+
+
+MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_ROOT:
+    application: "DaVinci/v64r8@x86_64_v2-el9-clang16+detdesc-opt"
+    input:
+        job_name: MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT2
+    output: QQbar2mumu_MC24_tuple.ROOT
+    options:
+        entrypoint: QuarkoniaToMuMu2024.dv_mc_{{channel}}:main
+        extra_options:
+            input_raw_format: 0.5
+            conddb_tag: {{ conddb }}
+            dddb_tag: {{ dddb }}
+            input_type: ROOT
+            simulation: True
+            data_type: "Upgrade"
+            input_process: "Hlt2"
+            input_stream: "bandq"
+
+
+    {%- endfor %}
+  {%- endfor %}
+{%- endfor %}
+
+
+
diff --git a/QuarkoniaToMuMu2024/moore_mc_turbo.py b/QuarkoniaToMuMu2024/moore_mc_turbo.py
new file mode 100644
index 0000000000..48935ad0e9
--- /dev/null
+++ b/QuarkoniaToMuMu2024/moore_mc_turbo.py
@@ -0,0 +1,44 @@
+"""
+Stolen and adapted from Hlt/Hlt2Conf/options/hlt2_pp_expected_24_without_UT.py from v55r11.
+ - Added @cburr's AgeLimit to reduce memory consumption
+
+Stolen from https://gitlab.cern.ch/lhcb-datapkg/AnalysisProductions/-/merge_requests/1111/diffs#a8f09cbd701214f19adade2f979fd46d7a824702 , 2024-07-22
+"""
+from Moore import Options
+from RecoConf.reconstruction_objects import reconstruction
+
+from Hlt2Conf.lines.mc.mc_lines import MC_HLT2_PASSTHROUGH_LINE_NAME
+from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines  # Full-stream lines to run over
+from Hlt2Conf.lines.qee.quarkonia import all_lines as qee_quarkonia_lines  # Turbo-stream lines to run over
+from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines  # Turbo-stream lines to run over
+
+from Hlt2Conf.lines.charmonium_to_dimuon import turbo_lines as bandq_psi_lines
+from Hlt2Conf.lines.qee.dimuon_no_ip import turbo_lines as qee_psi_lines
+from Hlt2Conf.lines.bandq.hlt2_bandq import turbo_lines as bandq_upsilon_lines
+
+def _make_regex():
+    """Use some QEE lines for the sake of example."""
+    # Here we 'brute-force' this regex via a regex of each individual line name we want to consider.
+    # A neater format is possible via knowing how the lines are named but this feels almost less robust.
+    lnames = [
+        linename for line_dict in
+        [bandq_psi_lines, qee_psi_lines, bandq_upsilon_lines]
+        for linename in line_dict.keys()
+    ]
+    lnames.append(MC_HLT2_PASSTHROUGH_LINE_NAME)
+    return f"({'|'.join(lnames)})"
+
+
+def main(options: Options):
+    with reconstruction.bind(from_file=False):
+        from Moore.production import hlt2
+        # Rather than processing via Moore:run_moore, using Moore.production:hlt2 emulates MC centralised processing.
+        hlt2_extra_args = [
+            '--flagging',  # prescales+postscales removed + passthrough_line added
+            '--settings=hlt2_pp_2024',  # Decides which settings to create the streams from
+            f'--lines-regex={_make_regex()}',  # Filters the settings to only run the lines you wish
+        ]
+        # instantiates public_tools and run_moore
+        config = hlt2(options, '--velo-source=VPRetinaCluster')
+    config["Gaudi::IODataManager/IODataManager"].AgeLimit = 0
+    return config
diff --git a/QuarkoniaToMuMu2024/spruce_turbo.py b/QuarkoniaToMuMu2024/spruce_turbo.py
new file mode 100644
index 0000000000..2c4da09b36
--- /dev/null
+++ b/QuarkoniaToMuMu2024/spruce_turbo.py
@@ -0,0 +1,53 @@
+###############################################################################
+# (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 Moore import options, run_moore, Options
+from RecoConf.reconstruction_objects import reconstruction
+from Moore.streams import DETECTORS, Stream, Streams
+from Moore.lines import PassLine
+
+# Input-specific options
+#options.conddb_tag = "sim-20231017-vc-md100"
+#options.dddb_tag = "dddb-20231017"
+#options.input_files = ['hlt2_output__turbo.mdf']
+#options.input_type = 'MDF'
+#options.input_raw_format = 0.5
+#options.simulation = True
+#options.data_type = "Upgrade"
+
+# Output options
+#options.output_file = 'spruce_pass_output__{stream}.dst'
+#options.output_type = 'ROOT'
+#options.output_manifest_file = 'sprucepass.tck.json'
+
+
+# Misc options
+#options.scheduler_legacy_mode = False
+#options.input_process = 'Hlt2'
+#options.evt_max = -1
+
+WG = 'bandq'
+
+
+def make_streams():
+    streams = [
+        Stream(
+            WG,
+            lines=[
+                PassLine(
+                    name=f"Pass_{WG}", hlt2_filter_code="Hlt2.*Decision")
+            ],
+            detectors=DETECTORS)
+    ]
+    return Streams(streams=streams)
+
+def main(options: Options):
+    with reconstruction.bind(from_file=True, spruce=True):
+        return run_moore(options, make_streams, public_tools=[])
-- 
GitLab


From 95a170136dae46a1272c09bd1bcb465d48f57db8 Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus943.cern.ch>
Date: Thu, 12 Sep 2024 05:15:22 +0200
Subject: [PATCH 02/12] add motherID for MC

---
 QuarkoniaToMuMu2024/helpers/dv_mctree.py | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/QuarkoniaToMuMu2024/helpers/dv_mctree.py b/QuarkoniaToMuMu2024/helpers/dv_mctree.py
index 2eaeb70d25..8ecad3b62b 100644
--- a/QuarkoniaToMuMu2024/helpers/dv_mctree.py
+++ b/QuarkoniaToMuMu2024/helpers/dv_mctree.py
@@ -75,6 +75,10 @@ def mctree_template(fields):
         #"nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"),
     })
 
+
+    MC_MOTHER_ID = lambda gen: F.VALUE_OR(0) @ F.MC_MOTHER(gen, F.PARTICLE_ID)
+    MC_MOTHER_KEY = lambda gen: F.VALUE_OR(-1) @ F.MC_MOTHER(gen, F.OBJECT_KEY)
+
     # FunTuple: define variables for the J/psi
     composite_variables = FunctorCollection(
         {
@@ -104,6 +108,16 @@ def mctree_template(fields):
             "M": F.MASS,
             "FOURMOMENTUM": F.FOURMOMENTUM,
             "PT": F.PT,
+            "MC_MOTHER_ID": MC_MOTHER_ID(1),
+            "MC_MOTHER_KEY": MC_MOTHER_KEY(1),
+            "MC_GD_MOTHER_ID": MC_MOTHER_ID(2),
+            "MC_GD_MOTHER_KEY": MC_MOTHER_KEY(2),
+            "MC_GD_GD_MOTHER_ID": MC_MOTHER_ID(3),
+            "MC_GD_GD_MOTHER_KEY": MC_MOTHER_KEY(3),
+            "TAU": F.MC_LIFETIME,
+            "END_VX": F.END_VX,
+            "END_VY": F.END_VY,
+            "END_VZ": F.END_VZ,
         }
     )
 
-- 
GitLab


From f19889e1a87d27dcdd584c72cfd3f67016d949d5 Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus955.cern.ch>
Date: Thu, 12 Sep 2024 17:22:04 +0200
Subject: [PATCH 03/12] add MOTHERID to MCDecayTree Jpsi

---
 QuarkoniaToMuMu2024/helpers/dv_mctree.py | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/QuarkoniaToMuMu2024/helpers/dv_mctree.py b/QuarkoniaToMuMu2024/helpers/dv_mctree.py
index 8ecad3b62b..ce332790c6 100644
--- a/QuarkoniaToMuMu2024/helpers/dv_mctree.py
+++ b/QuarkoniaToMuMu2024/helpers/dv_mctree.py
@@ -94,6 +94,12 @@ def mctree_template(fields):
             "M": F.MASS,
             "FOURMOMENTUM": F.FOURMOMENTUM,
             "PT": F.PT,
+            "MC_MOTHER_ID": MC_MOTHER_ID(1),
+            "MC_MOTHER_KEY": MC_MOTHER_KEY(1),
+            "MC_GD_MOTHER_ID": MC_MOTHER_ID(2),
+            "MC_GD_MOTHER_KEY": MC_MOTHER_KEY(2),
+            "MC_GD_GD_MOTHER_ID": MC_MOTHER_ID(3),
+            "MC_GD_GD_MOTHER_KEY": MC_MOTHER_KEY(3),
         }
      )                                                                    
 
-- 
GitLab


From 37f71d1dd5f25d031a21b3b686c83acc8ba17210 Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus922.cern.ch>
Date: Thu, 31 Oct 2024 18:04:27 +0100
Subject: [PATCH 04/12] version one. pipeline fail expected as MC production
 not active yet

---
 ...allen_mc_hlt1_pp_matching_no_ut_1000KHz.py |  6 --
 QuarkoniaToMuMu2024/info.yaml                 | 82 +++----------------
 QuarkoniaToMuMu2024/moore_mc_turbo.py         | 44 ----------
 3 files changed, 12 insertions(+), 120 deletions(-)
 delete mode 100644 QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py
 delete mode 100644 QuarkoniaToMuMu2024/moore_mc_turbo.py

diff --git a/QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py b/QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py
deleted file mode 100644
index affdbe1228..0000000000
--- a/QuarkoniaToMuMu2024/allen_mc_hlt1_pp_matching_no_ut_1000KHz.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from Moore import options, Options
-from Moore.production import hlt1
-
-def main(options: Options):       
-    return hlt1(options, "--sequence=hlt1_pp_matching_no_ut_1000KHz", "--flagging")
-
diff --git a/QuarkoniaToMuMu2024/info.yaml b/QuarkoniaToMuMu2024/info.yaml
index c1cc8e8943..ac838c3e60 100644
--- a/QuarkoniaToMuMu2024/info.yaml
+++ b/QuarkoniaToMuMu2024/info.yaml
@@ -1,90 +1,33 @@
 defaults:
-    application: DaVinci/v64r8
+    application: DaVinci/v64r12
     wg: BandQ
     inform:
-        - zihan.gao@cern.ch
         - mengzhen.wang@cern.ch
         - zehua.xu@cern.ch
 
 # mc configuration
 {%- set entrypoints = [
-  ("Jpsi_QEE", "Jpsi2mumu_QEE", "24142001", "turbo", "TurboPass"),
-  ("Psi2S_QEE", "Psi2S2mumu_QEE", "28142001", "turbo", "TurboPass"),
-  ("Jpsi", "Jpsi2mumu", "24142001", "turbo", "TurboPass"),
-  ("Psi2S", "Psi2S2mumu", "28142001", "turbo", "TurboPass"),
-  ("Upsilon1S", "Upsilon1S", "18112001", "turbo", "TurboPass"),
-  ("Upsilon2S", "Upsilon2S", "18112011", "turbo", "TurboPass"),
-  ("Upsilon3S", "Upsilon3S", "18112021", "turbo", "TurboPass"),
+  ("Jpsi", "Jpsi2mumu", "24142001", "Hlt2"),
+  ("Psi2S", "Psi2S2mumu", "28142001", "Hlt2"),
+  ("Upsilon1S", "Upsilon1S", "18112001", "Hlt2"),
+  ("Upsilon2S", "Upsilon2S", "18112011", "Hlt2"),
+  ("Upsilon3S", "Upsilon3S", "18112021", "Hlt2"),
 ]%}
 
 {%- set MC_conditions = [
-  ("MagDown", "MagDown", "7.6", "7_6", "dddb-20240427", "sim10-2024.Q1.2-v1.1-md100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
-  ("MagDown", "MagDown", "5.7", "5_7", "dddb-20240427", "sim10-2024.Q1.2-v1.1-md100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
-  ("MagDown", "MagDown", "4.3", "4_3", "dddb-20240427", "sim10-2024.Q1.2-v1.1-md100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
-  ("MagUp", "MagUp", "7.6", "7_6", "dddb-20240427", "sim10-2024.Q1.2-v1.1-mu100", "24Q12", "2024", "2024.Q1.2", "Sim10d"),
-]%}
-
-{%- set hlt_conditions = [
-  ("hlt1_pp_matching_no_ut_1000KHz", "hlt1v1"),
+  ("MagUp", "MagUp", "6.3", "6_3", "dddb-20240427", "sim10-2024.Q3.4-v1.3-mu100", "24Block1_v1", "2024", "2024.W31.34", "Sim10d"),
 ]%}
 
 
 
-{%- for module, channel, eventtype, fullturbo, dv_input_process in entrypoints %}
+{%- for module, channel, eventtype, dv_input_process in entrypoints %}
   {%- for polarity_mc, polarity_mc_jobtitle, nu, n_u, dddb, conddb, mcversion_jobtitle, BKK_label1, BKK_label2, simversion in MC_conditions %}
-    {% for hlt1_condition, hlt1_condition_jobtitle in hlt_conditions %}
-
-MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT1:
-    application: "Moore/v55r11@x86_64_v2-el9-gcc13+detdesc-opt"
-    input:
-        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/{{ eventtype }}/DIGI"
-        dq_flags:
-            - OK
-        keep_running: true
-        n_test_lfns: 1
-    output: QQbar2mumu_MC24_HLT1.DST
-    options: 
-        entrypoint: QuarkoniaToMuMu2024.allen_mc_{{hlt1_condition}}:main
-        extra_options:
-            input_raw_format: 0.5
-            conddb_tag: {{ conddb  }}
-            dddb_tag: {{ dddb  }}
-            input_type: "ROOT"
-            output_type: "ROOT"
-            simulation: True
-            data_type: "Upgrade"
-            scheduler_legacy_mode: False
-            compression:
-              algorithm: ZSTD
-              level: 1
-              max_buffer_size: 1048576
-
-MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT2:
-    application: "Moore/v55r11@x86_64_v2-el9-gcc13+detdesc-opt"
-    input:
-        job_name: MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT1
-    output: QQbar2mumu_MC24_HLT2_{{fullturbo}}.DST
-    options:
-        entrypoint: QuarkoniaToMuMu2024.moore_mc_{{fullturbo}}:main
-        extra_options:
-            conddb_tag: {{ conddb }}
-            dddb_tag: {{ dddb }}
-            input_type: "ROOT"
-            input_raw_format: 0.5
-            output_type: "ROOT"
-            simulation: True
-            data_type: "Upgrade"
-            scheduler_legacy_mode: False
-            compression:
-              algorithm: ZSTD
-              level: 1
-              max_buffer_size: 1048576
-
 
-MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_ROOT:
-    application: "DaVinci/v64r8@x86_64_v2-el9-clang16+detdesc-opt"
+MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_{{mcversion_jobtitle}}_ROOT:
+    application: "DaVinci/v64r12@x86_64_v2-el9-clang16+detdesc-opt"
     input:
-        job_name: MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcversion_jobtitle}}_{{hlt1_condition_jobtitle}}_HLT2
+        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/{{ eventtype }}/DST"
+        keep_running: true 
     output: QQbar2mumu_MC24_tuple.ROOT
     options:
         entrypoint: QuarkoniaToMuMu2024.dv_mc_{{channel}}:main
@@ -99,7 +42,6 @@ MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_withUTHlt2_withTrackCOV_{{mcver
             input_stream: "bandq"
 
 
-    {%- endfor %}
   {%- endfor %}
 {%- endfor %}
 
diff --git a/QuarkoniaToMuMu2024/moore_mc_turbo.py b/QuarkoniaToMuMu2024/moore_mc_turbo.py
deleted file mode 100644
index 48935ad0e9..0000000000
--- a/QuarkoniaToMuMu2024/moore_mc_turbo.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-Stolen and adapted from Hlt/Hlt2Conf/options/hlt2_pp_expected_24_without_UT.py from v55r11.
- - Added @cburr's AgeLimit to reduce memory consumption
-
-Stolen from https://gitlab.cern.ch/lhcb-datapkg/AnalysisProductions/-/merge_requests/1111/diffs#a8f09cbd701214f19adade2f979fd46d7a824702 , 2024-07-22
-"""
-from Moore import Options
-from RecoConf.reconstruction_objects import reconstruction
-
-from Hlt2Conf.lines.mc.mc_lines import MC_HLT2_PASSTHROUGH_LINE_NAME
-from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines  # Full-stream lines to run over
-from Hlt2Conf.lines.qee.quarkonia import all_lines as qee_quarkonia_lines  # Turbo-stream lines to run over
-from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines  # Turbo-stream lines to run over
-
-from Hlt2Conf.lines.charmonium_to_dimuon import turbo_lines as bandq_psi_lines
-from Hlt2Conf.lines.qee.dimuon_no_ip import turbo_lines as qee_psi_lines
-from Hlt2Conf.lines.bandq.hlt2_bandq import turbo_lines as bandq_upsilon_lines
-
-def _make_regex():
-    """Use some QEE lines for the sake of example."""
-    # Here we 'brute-force' this regex via a regex of each individual line name we want to consider.
-    # A neater format is possible via knowing how the lines are named but this feels almost less robust.
-    lnames = [
-        linename for line_dict in
-        [bandq_psi_lines, qee_psi_lines, bandq_upsilon_lines]
-        for linename in line_dict.keys()
-    ]
-    lnames.append(MC_HLT2_PASSTHROUGH_LINE_NAME)
-    return f"({'|'.join(lnames)})"
-
-
-def main(options: Options):
-    with reconstruction.bind(from_file=False):
-        from Moore.production import hlt2
-        # Rather than processing via Moore:run_moore, using Moore.production:hlt2 emulates MC centralised processing.
-        hlt2_extra_args = [
-            '--flagging',  # prescales+postscales removed + passthrough_line added
-            '--settings=hlt2_pp_2024',  # Decides which settings to create the streams from
-            f'--lines-regex={_make_regex()}',  # Filters the settings to only run the lines you wish
-        ]
-        # instantiates public_tools and run_moore
-        config = hlt2(options, '--velo-source=VPRetinaCluster')
-    config["Gaudi::IODataManager/IODataManager"].AgeLimit = 0
-    return config
-- 
GitLab


From 2f8c562d2cd2b9d3e6078f331ad004dde6caae50 Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus965.cern.ch>
Date: Sun, 3 Nov 2024 10:42:08 +0100
Subject: [PATCH 05/12] prepare for production

---
 QuarkoniaToMuMu2024/info.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/QuarkoniaToMuMu2024/info.yaml b/QuarkoniaToMuMu2024/info.yaml
index ac838c3e60..324fd1e0ec 100644
--- a/QuarkoniaToMuMu2024/info.yaml
+++ b/QuarkoniaToMuMu2024/info.yaml
@@ -24,9 +24,9 @@ defaults:
   {%- for polarity_mc, polarity_mc_jobtitle, nu, n_u, dddb, conddb, mcversion_jobtitle, BKK_label1, BKK_label2, simversion in MC_conditions %}
 
 MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_{{mcversion_jobtitle}}_ROOT:
-    application: "DaVinci/v64r12@x86_64_v2-el9-clang16+detdesc-opt"
+    application: "DaVinci/v64r12@x86_64_v3-el9-gcc13+detdesc-opt+g"
     input:
-        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/{{ eventtype }}/DST"
+        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/HLT2-2024.W31.34/{{ eventtype }}/DST"
         keep_running: true 
     output: QQbar2mumu_MC24_tuple.ROOT
     options:
-- 
GitLab


From 8e4c337f6a0d0d475ed1b4784a609e73bd1159da Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus979.cern.ch>
Date: Sun, 3 Nov 2024 17:58:04 +0100
Subject: [PATCH 06/12] remove unused files

---
 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py  | 39 ---------------
 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py | 28 -----------
 QuarkoniaToMuMu2024/spruce_turbo.py         | 53 ---------------------
 3 files changed, 120 deletions(-)
 delete mode 100644 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py
 delete mode 100644 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py
 delete mode 100644 QuarkoniaToMuMu2024/spruce_turbo.py

diff --git a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py
deleted file mode 100644
index c23b8ff27f..0000000000
--- a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu_QEE.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import os
-import sys
-sys.path.append(os.path.join(
-    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree
-from DaVinci import Options, make_config
-
-def main(options: Options):
-    decay_descriptor = {
-        "QQbar": "J/psi(1S) -> mu+ mu-",
-        "mup": "J/psi(1S) -> ^mu+ mu-",
-        "mum": "J/psi(1S) -> mu+ ^mu-",
-    }
-
-    decay_descriptor_mctree = {
-        "QQbar": "J/psi(1S) ==> mu+ mu-",
-        "mup": "J/psi(1S) ==> ^mu+ mu-",
-        "mum": "J/psi(1S) ==> mu+ ^mu-",
-    }
-
-
-    line_name0 = 'Hlt2QEE_DiMuonNoIP_massRange5'
-    my_tuple0 = dv_tree.tree_template(decay_descriptor, line_name0, True, [])
-    my_filter0 = dv_tree.line_prefilter(line_name0)
-    line_name1 = 'Hlt2QEE_DiMuonNoIP_massRange4'
-    my_tuple1 = dv_tree.tree_template(decay_descriptor, line_name1, True, [])
-    my_filter1 = dv_tree.line_prefilter(line_name1)
-    line_name2 = 'Hlt2QEE_DiMuonNoIP_massRange3'
-    my_tuple2 = dv_tree.tree_template(decay_descriptor, line_name2, True, [])
-    my_filter2 = dv_tree.line_prefilter(line_name2)
-    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
-    user_algorithms = {
-            "Alg_massRange5": [my_filter0, my_tuple0],
-            "Alg_massRange4": [my_filter1, my_tuple1],
-            "Alg_massRange3": [my_filter2, my_tuple2],
-            'Alg_mctuple': [my_mctuple],
-            }
-    return make_config(options, user_algorithms) 
-
diff --git a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py
deleted file mode 100644
index c662b904e3..0000000000
--- a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu_QEE.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import os
-import sys
-sys.path.append(os.path.join(
-    os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree
-from DaVinci import Options, make_config
-
-def main(options: Options):
-    decay_descriptor = {
-        "QQbar": "J/psi(1S) -> mu+ mu-",
-        "mup": "J/psi(1S) -> ^mu+ mu-",
-        "mum": "J/psi(1S) -> mu+ ^mu-",
-    }
-    decay_descriptor_mctree = {
-        "QQbar": "psi(2S) ==> mu+ mu-",
-        "mup": "psi(2S) ==> ^mu+ mu-",
-        "mum": "psi(2S) ==> mu+ ^mu-",
-    }
-
-    line_name = 'Hlt2QEE_DiMuonNoIP_massRange5'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
-    my_filter = dv_tree.line_prefilter(line_name)
-    my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
-    user_algorithms = {
-            'Alg_tuple': [my_filter, my_tuple],
-            'Alg_mctuple': [my_mctuple],
-            }
-    return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/spruce_turbo.py b/QuarkoniaToMuMu2024/spruce_turbo.py
deleted file mode 100644
index 2c4da09b36..0000000000
--- a/QuarkoniaToMuMu2024/spruce_turbo.py
+++ /dev/null
@@ -1,53 +0,0 @@
-###############################################################################
-# (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 Moore import options, run_moore, Options
-from RecoConf.reconstruction_objects import reconstruction
-from Moore.streams import DETECTORS, Stream, Streams
-from Moore.lines import PassLine
-
-# Input-specific options
-#options.conddb_tag = "sim-20231017-vc-md100"
-#options.dddb_tag = "dddb-20231017"
-#options.input_files = ['hlt2_output__turbo.mdf']
-#options.input_type = 'MDF'
-#options.input_raw_format = 0.5
-#options.simulation = True
-#options.data_type = "Upgrade"
-
-# Output options
-#options.output_file = 'spruce_pass_output__{stream}.dst'
-#options.output_type = 'ROOT'
-#options.output_manifest_file = 'sprucepass.tck.json'
-
-
-# Misc options
-#options.scheduler_legacy_mode = False
-#options.input_process = 'Hlt2'
-#options.evt_max = -1
-
-WG = 'bandq'
-
-
-def make_streams():
-    streams = [
-        Stream(
-            WG,
-            lines=[
-                PassLine(
-                    name=f"Pass_{WG}", hlt2_filter_code="Hlt2.*Decision")
-            ],
-            detectors=DETECTORS)
-    ]
-    return Streams(streams=streams)
-
-def main(options: Options):
-    with reconstruction.bind(from_file=True, spruce=True):
-        return run_moore(options, make_streams, public_tools=[])
-- 
GitLab


From 55f82db6d1e19cca70c77f9796c8e632b66b3d3b Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus922.cern.ch>
Date: Tue, 5 Nov 2024 15:21:16 +0100
Subject: [PATCH 07/12] try to remove pidmu cuts in tupling from DST

---
 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py | 5 +++--
 QuarkoniaToMuMu2024/helpers/dv_tree.py | 6 +++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
index b83f4336a1..4ba1eeb62a 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
@@ -18,11 +18,12 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2_JpsiToMuMu'
-    my_filter = dv_tree.line_prefilter(line_name)
+#    my_filter = dv_tree.line_prefilter(line_name)
     my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple': [ my_tuple],
+            #'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms) 
diff --git a/QuarkoniaToMuMu2024/helpers/dv_tree.py b/QuarkoniaToMuMu2024/helpers/dv_tree.py
index 3e0b84bbd6..8126ec2e72 100644
--- a/QuarkoniaToMuMu2024/helpers/dv_tree.py
+++ b/QuarkoniaToMuMu2024/helpers/dv_tree.py
@@ -22,6 +22,9 @@ from FunTuple.functorcollections import MCHierarchy, MCPrimaries, MCPromptDecay,
 from PyConf.reading import get_odin  # get_decreports,
 from DecayTreeFitter import DecayTreeFitter
 
+from Hlt2Conf.lines.charmonium_to_dimuon import make_jpsi
+
+
 _basic = "basic"
 _composite = "composite"
 _toplevel = "toplevel"
@@ -331,7 +334,8 @@ def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions):
     if isturbo:
         evtpath_prefix = "/Event/HLT2/"
 
-    QQbar2mumu_data = get_particles(evtpath_prefix+f"{line_name}/Particles")
+    #QQbar2mumu_data = get_particles(evtpath_prefix+f"{line_name}/Particles")
+    QQbar2mumu_data = make_jpsi(minPIDmu=-999) 
 
     pvs = get_pvs()
 
-- 
GitLab


From f29f97a9434bd7cdeb2be8c2f6636b95a6288cf3 Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus938.cern.ch>
Date: Thu, 7 Nov 2024 13:28:56 +0100
Subject: [PATCH 08/12] test removing ismuon

---
 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py        |  11 +-
 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py       |  13 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py        |  13 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py        |  14 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py        |  13 +-
 QuarkoniaToMuMu2024/helpers/dv_tree.py        |   5 +-
 .../helpers/private_combiners.py              | 207 ++++++++++++++++++
 7 files changed, 254 insertions(+), 22 deletions(-)
 create mode 100644 QuarkoniaToMuMu2024/helpers/private_combiners.py

diff --git a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
index 4ba1eeb62a..fcb6c4a4e8 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
@@ -2,8 +2,13 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree
+from helpers import dv_tree, dv_mctree, private_combiners
 from DaVinci import Options, make_config
+from RecoConf.event_filters import require_pvs
+
+from RecoConf.reconstruction_objects import make_pvs
+
+
 
 def main(options: Options):
     decay_descriptor = {
@@ -19,10 +24,10 @@ def main(options: Options):
 
     line_name = 'Hlt2_JpsiToMuMu'
 #    my_filter = dv_tree.line_prefilter(line_name)
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_jpsi())
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [ my_tuple],
+            'Alg_tuple': [ require_pvs(make_pvs()), my_tuple],
             #'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
diff --git a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
index e779f100ba..a81937cda0 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
@@ -2,9 +2,13 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree
+from helpers import dv_tree, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
+from RecoConf.event_filters import require_pvs
+
+from RecoConf.reconstruction_objects import make_pvs
+
 def main(options: Options):
     decay_descriptor = {
         "QQbar": "psi(2S) -> mu+ mu-",
@@ -19,11 +23,12 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2_Psi2SToMuMu'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
-    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_psi2s())
+#    my_filter = dv_tree.line_prefilter(line_name)
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple': [require_pvs(make_pvs()), my_tuple],
+            #'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
index 69ae7b831f..d685b45b02 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
@@ -2,9 +2,13 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree
+from helpers import dv_tree, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
+from RecoConf.event_filters import require_pvs
+
+from RecoConf.reconstruction_objects import make_pvs
+
 def main(options: Options):
     decay_descriptor = {
         "QQbar": "Upsilon(1S) -> mu+ mu-",
@@ -18,12 +22,13 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
-    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
+#    my_filter = dv_tree.line_prefilter(line_name)
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple],
+            #'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
index 0212d0d8a4..9241ee7ca3 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
@@ -2,9 +2,14 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree
+from helpers import dv_tree, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
+from RecoConf.event_filters import require_pvs
+
+from RecoConf.reconstruction_objects import make_pvs
+
+
 def main(options: Options):
     decay_descriptor = {
         "QQbar": "Upsilon(1S) -> mu+ mu-",
@@ -18,12 +23,13 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
-    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
+#    my_filter = dv_tree.line_prefilter(line_name)
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple': [require_pvs(make_pvs()), my_tuple],
+            #'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
index 4c2b84a3f0..de60f00f67 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
@@ -2,9 +2,13 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree
+from helpers import dv_tree, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
+from RecoConf.event_filters import require_pvs
+
+from RecoConf.reconstruction_objects import make_pvs
+
 def main(options: Options):
     decay_descriptor = {
         "QQbar": "Upsilon(1S) -> mu+ mu-",
@@ -18,12 +22,13 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
-    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
+#    my_filter = dv_tree.line_prefilter(line_name)
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [my_filter, my_tuple],
+            #'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple': [require_pvs(make_pvs()), my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/helpers/dv_tree.py b/QuarkoniaToMuMu2024/helpers/dv_tree.py
index 8126ec2e72..cd5222f457 100644
--- a/QuarkoniaToMuMu2024/helpers/dv_tree.py
+++ b/QuarkoniaToMuMu2024/helpers/dv_tree.py
@@ -22,7 +22,6 @@ from FunTuple.functorcollections import MCHierarchy, MCPrimaries, MCPromptDecay,
 from PyConf.reading import get_odin  # get_decreports,
 from DecayTreeFitter import DecayTreeFitter
 
-from Hlt2Conf.lines.charmonium_to_dimuon import make_jpsi
 
 
 _basic = "basic"
@@ -329,13 +328,13 @@ def event_variables(PVs, ODIN, decreports, lines, hlt1lines):
     return evt_vars
 
 
-def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions):
+def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions, QQbar2mumu_data):
     evtpath_prefix = "/Event/Spruce/"
     if isturbo:
         evtpath_prefix = "/Event/HLT2/"
 
     #QQbar2mumu_data = get_particles(evtpath_prefix+f"{line_name}/Particles")
-    QQbar2mumu_data = make_jpsi(minPIDmu=-999) 
+    #QQbar2mumu_data = make_jpsi(minPIDmu=-999) 
 
     pvs = get_pvs()
 
diff --git a/QuarkoniaToMuMu2024/helpers/private_combiners.py b/QuarkoniaToMuMu2024/helpers/private_combiners.py
new file mode 100644
index 0000000000..fa0a5ad1c6
--- /dev/null
+++ b/QuarkoniaToMuMu2024/helpers/private_combiners.py
@@ -0,0 +1,207 @@
+# Copy from 
+# https://gitlab.cern.ch/lhcb/Moore/-/blob/2024-patches/Hlt/Hlt2Conf/python/Hlt2Conf/lines/charmonium_to_dimuon.py?ref_type=heads
+# https://gitlab.cern.ch/lhcb/Moore/-/blob/2024-patches/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/dimuon_lines.py?ref_type=heads
+import Functors as F
+
+from Hlt2Conf.standard_particles import make_long_muons
+from GaudiKernel.SystemOfUnits import MeV, GeV
+from RecoConf.reconstruction_objects import make_pvs
+from Hlt2Conf.algorithms_thor import ParticleFilter, ParticleCombiner
+
+
+_JPSI_PDG_MASS_ = 3096.9 * MeV
+_PSI2S_PDG_MASS_ = 3686.1 * MeV
+_MASSWINDOW_LOW_JPSI_ = 150 * MeV
+_MASSWINDOW_HIGH_JPSI_ = 150 * MeV
+_MASSWINDOW_LOW_PSI2S_ = 150 * MeV
+_MASSWINDOW_HIGH_PSI2S_ = 150 * MeV
+_MASSMIN_JPSI = _JPSI_PDG_MASS_ - _MASSWINDOW_LOW_JPSI_
+_MASSMAX_JPSI = _JPSI_PDG_MASS_ + _MASSWINDOW_HIGH_JPSI_
+_MASSMIN_PSI2S = _PSI2S_PDG_MASS_ - _MASSWINDOW_LOW_PSI2S_
+_MASSMAX_PSI2S = _PSI2S_PDG_MASS_ + _MASSWINDOW_HIGH_PSI2S_
+_MASSMIN_UPSILON = 7900 * MeV
+_MASSMAX_UPSILON = 12000 * MeV
+
+
+_PIDMU_JPSI = -999.
+_PIDMU_PSI2S = -999.
+_PIDMU_UPSILON = -999.
+
+def make_charmonium_muons(make_particles=make_long_muons,
+                          name='charmonium_muons_{hash}',
+                          minPt_muon=None,
+                          minP_muon=None,
+                          minIPChi2_muon=None,
+                          minIP_muon=None,
+                          minPIDmu=None,
+                          maxIPChi2_muon=None):
+
+    pvs = make_pvs()
+
+    code = F.require_all(F.ALL)
+
+    if minPt_muon is not None: code &= (F.PT > minPt_muon)
+    if minP_muon is not None: code &= (F.P > minP_muon)
+    if minIPChi2_muon is not None: code &= (F.MINIPCHI2(pvs) > minIPChi2_muon)
+    if minIP_muon is not None: code &= (F.MINIP(pvs) > minIP_muon)
+
+    # ignoring minPIDmu cut here, thus ignoring it in ALL lines in this file
+#    if not nopid_muons() and minPIDmu is not None:
+#        code &= F.require_all(F.PID_MU > minPIDmu)
+
+    if maxIPChi2_muon is not None:
+        code &= (F.MINIPCHI2(pvs) < maxIPChi2_muon)
+
+    return ParticleFilter(make_particles(), name=name, Cut=F.FILTER(code))
+
+
+
+def make_charmonium_dimuon_base(name='charmonium_dimuon_base_{hash}',
+                                DecayDescriptor='J/psi(1S) -> mu+ mu-',
+                                maxVertexChi2=25,
+                                maxDOCAChi2=None,
+                                minPt_muon=None,
+                                minP_muon=None,
+                                minIPChi2_muon=None,
+                                minIP_muon=None,
+                                minPIDmu=None,
+                                minPt_dimuon=None,
+                                minMass_dimuon=None,
+                                maxMass_dimuon=None):
+
+    # get the long muons
+    muons = make_charmonium_muons(
+        minPt_muon=minPt_muon,
+        minP_muon=minP_muon,
+        minIPChi2_muon=minIPChi2_muon,
+        minIP_muon=minIP_muon,
+        minPIDmu=minPIDmu)
+
+    combination_code = F.ALL
+    if minMass_dimuon is not None:
+        combination_code &= (F.MASS > minMass_dimuon)
+    if maxMass_dimuon is not None:
+        combination_code &= (F.MASS < maxMass_dimuon)
+    if maxDOCAChi2 is not None:
+        combination_code &= (F.SDOCACHI2(1, 2) < maxDOCAChi2)
+
+    # require that the muons come from the same vertex
+    vertex_code = F.require_all(F.CHI2DOF < maxVertexChi2)
+    if minPt_dimuon is not None: vertex_code &= (F.PT > minPt_dimuon)
+
+    return ParticleCombiner(
+        name=name,
+        Inputs=[muons, muons],
+        DecayDescriptor=DecayDescriptor,
+        CombinationCut=combination_code,
+        CompositeCut=vertex_code)
+
+
+def make_charmonium_dimuon(name='charmonium_dimuon_{hash}',
+                           DecayDescriptor='J/psi(1S) -> mu+ mu-',
+                           minPt_dimuon=None,
+                           minPt_muon=300 * MeV,
+                           minP_muon=None,
+                           minIPChi2_muon=None,
+                           maxVertexChi2=25,
+                           minPIDmu=None,
+                           bpvdls_min=None,
+                           maxDOCAChi2=None,
+                           minMass_dimuon=None,
+                           maxMass_dimuon=None):
+
+    make_particles = make_charmonium_dimuon_base(
+        DecayDescriptor=DecayDescriptor,
+        maxVertexChi2=maxVertexChi2,
+        minIPChi2_muon=minIPChi2_muon,
+        minPt_muon=minPt_muon,
+        minP_muon=minP_muon,
+        minPIDmu=minPIDmu,
+        maxDOCAChi2=maxDOCAChi2,
+        minMass_dimuon=minMass_dimuon,
+        maxMass_dimuon=maxMass_dimuon)
+
+    pvs = make_pvs()
+
+    code = F.require_all(F.CHI2DOF < maxVertexChi2)
+    if minPt_dimuon is not None: code &= (F.PT > minPt_dimuon)
+    if bpvdls_min is not None: code &= (F.BPVDLS(pvs) > bpvdls_min)
+
+    return ParticleFilter(make_particles, name=name, Cut=F.FILTER(code))
+
+
+
+
+def make_jpsi(name='jpsi_{hash}',
+              minMass_dimuon=_MASSMIN_JPSI,
+              maxMass_dimuon=_MASSMAX_JPSI,
+              minPt_muon=300 * MeV,
+              minP_muon=None,
+              minPt_Jpsi=None,
+              maxVertexChi2=25,
+              minPIDmu=_PIDMU_JPSI):
+
+    code = F.ALL
+    if minPt_Jpsi is not None: code &= F.PT > minPt_Jpsi
+
+    dimuon = make_charmonium_dimuon(
+        DecayDescriptor='J/psi(1S) -> mu+ mu-',
+        minPt_dimuon=minPt_Jpsi,
+        minPt_muon=minPt_muon,
+        minP_muon=minP_muon,
+        minPIDmu=minPIDmu,
+        minMass_dimuon=minMass_dimuon,
+        maxMass_dimuon=maxMass_dimuon,
+        maxVertexChi2=maxVertexChi2)
+
+    return ParticleFilter(dimuon, name=name, Cut=F.FILTER(code))
+
+
+def make_psi2s(name='psi2s_{hash}',
+               minMass_dimuon=_MASSMIN_PSI2S,
+               maxMass_dimuon=_MASSMAX_PSI2S,
+               minPt_muon=300 * MeV,
+               minP_muon=None,
+               minPt_Psi2S=None,
+               maxPt_Psi2S=None,
+               maxVertexChi2=25,
+               minPIDmu=_PIDMU_PSI2S):
+
+    code = F.ALL
+    if minPt_Psi2S is not None: code &= F.PT > minPt_Psi2S
+    if maxPt_Psi2S is not None: code &= F.PT < maxPt_Psi2S
+
+    dimuon = make_charmonium_dimuon(
+        DecayDescriptor='psi(2S) -> mu+ mu-',
+        minPt_dimuon=minPt_Psi2S,
+        minPt_muon=minPt_muon,
+        minP_muon=minP_muon,
+        minPIDmu=minPIDmu,
+        minMass_dimuon=minMass_dimuon,
+        maxMass_dimuon=maxMass_dimuon,
+        maxVertexChi2=maxVertexChi2)
+
+    return ParticleFilter(dimuon, name=name, Cut=F.FILTER(code))
+
+
+
+def make_upsilon(name='bandq_upsilon_{hash}',
+                 minMass_dimuon=_MASSMIN_UPSILON,
+                 maxMass_dimuon=_MASSMAX_UPSILON,
+                 minPt_muon=300 * MeV,
+                 minP_muon=0 * MeV,
+                 minPt_upsilon=0 * MeV):
+
+    code = (F.PT > minPt_upsilon)
+
+    dimuon = make_charmonium_dimuon(
+        DecayDescriptor='Upsilon(1S) -> mu+ mu-',
+        minPt_dimuon=minPt_upsilon,
+        minP_muon=minP_muon,
+        minPt_muon=minPt_muon,
+        minPIDmu=_PIDMU_UPSILON,
+        minMass_dimuon=minMass_dimuon,
+        maxMass_dimuon=maxMass_dimuon)
+
+    return ParticleFilter(dimuon, name=name, Cut=F.FILTER(code))
+
-- 
GitLab


From 9af10d07dd5a9c237dce6c98f24e99761cc6d95d Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus957.cern.ch>
Date: Mon, 25 Nov 2024 17:58:56 +0100
Subject: [PATCH 09/12] save mcdecaytree decaytree decaytreenopid together

---
 QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py       |  11 +-
 QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py      |  11 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py       |  11 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py       |  12 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py       |  11 +-
 QuarkoniaToMuMu2024/helpers/dv_tree.py       |   6 +-
 QuarkoniaToMuMu2024/helpers/dv_tree_nopid.py | 514 +++++++++++++++++++
 QuarkoniaToMuMu2024/log                      |   0
 8 files changed, 547 insertions(+), 29 deletions(-)
 create mode 100644 QuarkoniaToMuMu2024/helpers/dv_tree_nopid.py
 create mode 100644 QuarkoniaToMuMu2024/log

diff --git a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
index fcb6c4a4e8..7de5d8d987 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Jpsi2mumu.py
@@ -2,7 +2,7 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree, private_combiners
+from helpers import dv_tree_nopid, dv_tree, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 from RecoConf.event_filters import require_pvs
 
@@ -23,12 +23,13 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2_JpsiToMuMu'
-#    my_filter = dv_tree.line_prefilter(line_name)
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_jpsi())
+    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple_nopid = dv_tree_nopid.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_jpsi())
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [ require_pvs(make_pvs()), my_tuple],
-            #'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple_nopid': [ require_pvs(make_pvs()), my_tuple_nopid],
+            'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms) 
diff --git a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
index a81937cda0..5f45c9c2f0 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Psi2S2mumu.py
@@ -2,7 +2,7 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree, private_combiners
+from helpers import dv_tree, dv_tree_nopid, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
 from RecoConf.event_filters import require_pvs
@@ -23,12 +23,13 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2_Psi2SToMuMu'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_psi2s())
-#    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple_nopid = dv_tree_nopid.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_psi2s())
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [require_pvs(make_pvs()), my_tuple],
-            #'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple_nopid': [require_pvs(make_pvs()), my_tuple_nopid],
+            'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
index d685b45b02..fcfb66d7df 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
@@ -2,7 +2,7 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree, private_combiners
+from helpers import dv_tree, dv_tree_nopid, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
 from RecoConf.event_filters import require_pvs
@@ -22,13 +22,14 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
-#    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple_nopid = dv_tree_nopid.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple],
-            #'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple_nopid],
+            'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
index 9241ee7ca3..54e5a79bc7 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
@@ -2,14 +2,13 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree, private_combiners
+from helpers import dv_tree, dv_tree_nopid, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
 from RecoConf.event_filters import require_pvs
 
 from RecoConf.reconstruction_objects import make_pvs
 
-
 def main(options: Options):
     decay_descriptor = {
         "QQbar": "Upsilon(1S) -> mu+ mu-",
@@ -23,13 +22,14 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
-#    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple_nopid = dv_tree_nopid.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [require_pvs(make_pvs()), my_tuple],
-            #'Alg_tuple': [my_filter, my_tuple],
+            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple_nopid],
+            'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
index de60f00f67..65890de8c4 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
@@ -2,7 +2,7 @@ import os
 import sys
 sys.path.append(os.path.join(
     os.environ['ANALYSIS_PRODUCTIONS_BASE'], 'QuarkoniaToMuMu2024'))
-from helpers import dv_tree, dv_mctree, private_combiners
+from helpers import dv_tree, dv_tree_nopid, dv_mctree, private_combiners
 from DaVinci import Options, make_config
 
 from RecoConf.event_filters import require_pvs
@@ -22,13 +22,14 @@ def main(options: Options):
     }
 
     line_name = 'Hlt2BandQ_UpsilonToMuMuEMTF'
-    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
-#    my_filter = dv_tree.line_prefilter(line_name)
+    my_tuple_nopid = dv_tree_nopid.tree_template(decay_descriptor, line_name, True, [], private_combiners.make_upsilon())
+    my_tuple = dv_tree.tree_template(decay_descriptor, line_name, True, [])
+    my_filter = dv_tree.line_prefilter(line_name)
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            #'Alg_tuple': [my_filter, my_tuple],
-            'Alg_tuple': [require_pvs(make_pvs()), my_tuple],
+            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple_nopid],
+            'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
     return make_config(options, user_algorithms)
diff --git a/QuarkoniaToMuMu2024/helpers/dv_tree.py b/QuarkoniaToMuMu2024/helpers/dv_tree.py
index cd5222f457..8032c9a904 100644
--- a/QuarkoniaToMuMu2024/helpers/dv_tree.py
+++ b/QuarkoniaToMuMu2024/helpers/dv_tree.py
@@ -328,12 +328,12 @@ def event_variables(PVs, ODIN, decreports, lines, hlt1lines):
     return evt_vars
 
 
-def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions, QQbar2mumu_data):
+def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions):
     evtpath_prefix = "/Event/Spruce/"
     if isturbo:
         evtpath_prefix = "/Event/HLT2/"
 
-    #QQbar2mumu_data = get_particles(evtpath_prefix+f"{line_name}/Particles")
+    QQbar2mumu_data = get_particles(evtpath_prefix+f"{line_name}/Particles")
     #QQbar2mumu_data = make_jpsi(minPIDmu=-999) 
 
     pvs = get_pvs()
@@ -459,7 +459,7 @@ def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions, QQbar2mu
     })
 
     # get trueid bkgcat info
-    MC_TRUTH = MCTruthAndBkgCat(QQbar2mumu_data, name='MCTruthAndBkgCat_'+line_name)
+    MC_TRUTH = MCTruthAndBkgCat(QQbar2mumu_data, name='MCTruthAndBkgCat_'+line_name+"_{hash}")
     MCMOTHER_ID = lambda n: F.VALUE_OR(0) @ MC_TRUTH(F.MC_MOTHER(n, F.PARTICLE_ID))
     MCMOTHER_KEY = lambda n: F.VALUE_OR(-1) @ MC_TRUTH(F.MC_MOTHER(n, F.OBJECT_KEY))
 
diff --git a/QuarkoniaToMuMu2024/helpers/dv_tree_nopid.py b/QuarkoniaToMuMu2024/helpers/dv_tree_nopid.py
new file mode 100644
index 0000000000..5bfe4a88ee
--- /dev/null
+++ b/QuarkoniaToMuMu2024/helpers/dv_tree_nopid.py
@@ -0,0 +1,514 @@
+###############################################################################
+# (c) Copyright 2021-2022 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Read an HLT2 file and create an ntuple with the new DaVinci configuration.
+"""
+import Functors as F
+import FunTuple.functorcollections as FC
+from FunTuple import FunctorCollection
+from FunTuple import FunTuple_Particles as Funtuple
+from PyConf.reading import get_particles, get_pvs, get_rec_summary
+from DaVinci.algorithms import create_lines_filter
+from DaVinciMCTools import MCTruthAndBkgCat
+from FunTuple.functorcollections import MCHierarchy, MCPrimaries, MCPromptDecay, Kinematics, SelectionInfo, HltTisTos, MCVertexInfo, MCKinematics, ParticleID, EventInfo
+from PyConf.reading import get_odin  # get_decreports,
+from DecayTreeFitter import DecayTreeFitter
+
+
+
+_basic = "basic"
+_composite = "composite"
+_toplevel = "toplevel"
+
+#def all_variables(pvs, dtf, mctruth, ptype, candidates=None, ftAlg=None):
+def all_variables(pvs, mctruth, ptype, candidates=None, ftAlg=None):
+    """
+    function that returns dictionary of functors that work.
+    
+    functors are listed in order of https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/selection/thor_functors_reference.html#module-Functo
+    """
+    if ptype not in [_basic, _composite]:
+        Exception(f"I want {_basic} or {_composite}. Got {ptype}")
+    all_vars = FunctorCollection({})
+    
+    comp = _composite == ptype or _toplevel == ptype  # is composite
+    basic = _basic == ptype  # is not composite
+    top = _toplevel == ptype  # the B
+
+    # First import everything that comes in functorcollections
+    all_vars += FC.Kinematics()
+    if basic:
+        all_vars += FC.ParticleID(extra_info=True)
+    all_vars += FC.MCKinematics(mctruth_alg=mctruth)
+    all_vars += FC.MCHierarchy(mctruth_alg=mctruth)
+    #all_vars += FC.MCPrimaryVertexInfo(mctruth_alg=mctruth)
+    #Hlt1_decisions = ["Hlt1TrackMVADecision", "Hlt1TwoTrackMVADecision"]
+    #if candidates:
+        #all_vars += FC.HltTisTos(
+            #selection_type="Hlt", trigger_lines=Hlt1_decisions, data=candidates
+        #)
+    #if comp:
+    #    all_vars += FC.MCVertexInfo(mctruth_alg=mctruth)
+    #if top:
+    #    all_vars += FC.MCPromptDecay(mctruth_alg=mctruth)
+    
+    #
+    # FTAlg not yet implemented
+    # For Track isolation see weightedrelations_trackvariables
+    #
+    # Now all other functors
+    
+    # ALL : Not useful for tupling
+    
+    if comp:
+        all_vars.update({"ALV": F.ALV(Child1=1, Child2=2)})
+        
+        all_vars.update({"BKGCAT": mctruth.BkgCat})
+        
+    if comp:  # all these require a vertex
+        all_vars.update({"BPVCORRM": F.BPVCORRM(pvs)})
+        all_vars.update({"BPVCORRMERR": F.BPVCORRMERR(pvs)})
+        all_vars.update({"BPVDIRA": F.BPVDIRA(pvs)})
+        all_vars.update({"BPVDLS": F.BPVDLS(pvs)})
+        all_vars.update({"BPVETA": F.BPVETA(pvs)})
+        all_vars.update({"BPVFD": F.BPVFD(pvs)})
+        all_vars.update({"BPVFDCHI2": F.BPVFDCHI2(pvs)})
+        all_vars.update({"BPVFDIR": F.BPVFDIR(pvs)})
+        all_vars.update({"BPVFDVEC": F.BPVFDVEC(pvs)})
+
+    all_vars.update({"BPVIP": F.BPVIP(pvs)})
+    all_vars.update({"BPVIPCHI2": F.BPVIPCHI2(pvs)})
+    all_vars.update({"BPVX": F.BPVX(pvs)})
+    all_vars.update({"BPVY": F.BPVY(pvs)})
+    all_vars.update({"BPVZ": F.BPVZ(pvs)})
+    # When storing variable length array one can
+    # give a custom branch name for the index.
+    # This can be achieved by enclosing custom index
+    # name within square brackets (see code below).
+    # The branch name ("nPV") will correspond to the
+    # index of the PV. If no index branch name given i.e.
+    # all_vars.update({ 'ALLPVX'] the default "indx" is used.
+    #all_vars.update({"ALLPVX[nPVs]": F.ALLPVX(pvs)})
+    #all_vars.update({"ALLPVY[nPVs]": F.ALLPVY(pvs)})
+    #all_vars.update({"ALLPVZ[nPVs]": F.ALLPVZ(pvs)})
+    all_vars.update({"ALLPVX": F.ALLPVX(pvs)})
+    all_vars.update({"ALLPVY": F.ALLPVY(pvs)})
+    all_vars.update({"ALLPVZ": F.ALLPVZ(pvs)})
+
+    if comp:  # all these require a vertex
+        #all_vars.update({"ALLPV_FD[nPVs]": F.ALLPV_FD(pvs)})
+        #all_vars.update({"ALLPV_IP[nPVs]": F.ALLPV_IP(pvs)})
+        all_vars.update({"ALLPV_FD": F.ALLPV_FD(pvs)})
+        all_vars.update({"ALLPV_IP": F.ALLPV_IP(pvs)})
+        all_vars.update({"BPVLTIME": F.BPVLTIME(pvs)})
+        all_vars.update({"BPVVDRHO": F.BPVVDRHO(pvs)})
+        all_vars.update({"BPVVDX": F.BPVVDX(pvs)})
+        all_vars.update({"BPVVDY": F.BPVVDY(pvs)})
+        all_vars.update({"BPVVDZ": F.BPVVDZ(pvs)})
+    
+    all_vars.update({"CHARGE": F.CHARGE})
+    all_vars.update({"CHI2": F.CHI2})
+    all_vars.update({"CHI2DOF": F.CHI2DOF})
+    if top:  # apply this only to B
+        all_vars.update({"CHILD1_PT": F.CHILD(1, F.PT)})  # example of CHILD
+        all_vars.update({"Ds_END_VZ": F.CHILD(1, F.END_VZ)})
+        all_vars.update({"Delta_END_VZ_DsB0": F.CHILD(1, F.END_VZ) - F.END_VZ})
+    
+    # if basic: all_vars.update({ 'CLOSESTTOBEAM' : F.CLOSESTTOBEAM # 'Track__ClosestToBeamState' object has no attribute 'to_json'
+    # COMB
+    # if basic: all_vars.update({ 'COV' : F.COV # 'Track__Covariance' object has no attribute 'to_json'
+
+    if comp:
+        all_vars.update({"DOCA": F.SDOCA(Child1=1, Child2=2)})
+        all_vars.update({"DOCACHI2": F.SDOCACHI2(Child1=1, Child2=2)})
+        all_vars.update({"END_VRHO": F.END_VRHO})
+        all_vars.update({"END_VX": F.END_VX})
+        all_vars.update({"END_VY": F.END_VY})
+        all_vars.update({"END_VZ": F.END_VZ})
+    
+    # duplicated from FC   all_vars.update({"ENERGY" : F.ENERGY})
+    all_vars.update({"ETA": F.ETA})
+    all_vars.update({"FOURMOMENTUM": F.FOURMOMENTUM})
+    all_vars.update({"ISBASIC": F.ISBASICPARTICLE})
+
+    if basic:
+        all_vars.update({"GHOSTPROB": F.GHOSTPROB})
+        all_vars.update({"ISMUON": F.ISMUON})
+        all_vars.update({"INMUON": F.INMUON})
+        all_vars.update({"INECAL": F.INECAL})
+        all_vars.update({"INHCAL": F.INHCAL})
+        all_vars.update({"HASBREM": F.HASBREM})
+        all_vars.update({"BREMENERGY": F.BREMENERGY})
+        all_vars.update({"BREMBENDCORR": F.BREMBENDCORR})
+        all_vars.update({"BREMPIDE": F.BREMPIDE})
+        all_vars.update({"ECALPIDE": F.ECALPIDE})
+        all_vars.update({"ECALPIDMU": F.ECALPIDMU})
+        all_vars.update({"HCALPIDE": F.HCALPIDE})
+        all_vars.update({"HCALPIDMU": F.HCALPIDMU})
+        all_vars.update({"ELECTRONSHOWEREOP": F.ELECTRONSHOWEREOP})
+        all_vars.update({"CLUSTERMATCH": F.CLUSTERMATCH_CHI2})
+        all_vars.update({"ELECTRONMATCH": F.ELECTRONMATCH_CHI2})
+        all_vars.update({"BREMHYPOMATCH": F.BREMHYPOMATCH_CHI2})
+        all_vars.update({"ELECTRONENERGY": F.ELECTRONENERGY})
+        all_vars.update({"BREMHYPOENERGY": F.BREMHYPOENERGY})
+        all_vars.update({"BREMHYPODELTAX": F.BREMHYPODELTAX})
+        all_vars.update({"ELECTRONID": F.ELECTRONID})
+        all_vars.update({"HCALEOP": F.HCALEOP})
+        # Note: the observables for the two functors below are (TRACK_MOM_X, TRACK_MOM_Y, TRACK_MOM_Z})
+        # and (TRACK_POS_CLOSEST_TO_BEAM_X, TRACK_POS_CLOSEST_TO_BEAM_Y, TRACK_POS_CLOSEST_TO_BEAM_Z),
+        # which is why the trailing underscore in the name is added i.e. "TRACK_MOM_" and "TRACK_POS_CLOSEST_TO_BEAM_"
+        all_vars.update({"TRACK_MOM_": F.TRACK_MOMVEC})
+        all_vars.update({"TRACK_POS_CLOSESTTOBEAM_": F.TRACK_POSVEC_CLOSESTTOBEAM})
+        
+        all_vars.update({"IS_ABS_ID_pi": F.IS_ABS_ID("pi+")})
+        all_vars.update({"IS_ID_pi": F.IS_ID("pi-")})
+        all_vars.update({"PDG_MASS_pi": F.PDG_MASS("pi+")})
+        all_vars.update({"SIGNED_DELTA_MASS_pi": F.SIGNED_DELTA_MASS("pi+")})
+        all_vars.update({"ABS_DELTA_MASS_pi": F.ABS_DELTA_MASS("pi+")})
+        all_vars.update({"IS_NOT_H": F.IS_NOT_H})
+        all_vars.update({"IS_PHOTON": F.IS_PHOTON})
+
+    #if dtf:
+    #    all_vars.update({"DTF_PT": dtf(F.PT)})
+    #    all_vars.update({"DTF_BPVIPCHI2": dtf(F.BPVIPCHI2(pvs))})
+        
+    #if top and dtf:
+    #    all_vars.update({"DTF_NITER": dtf.NITER})
+    #    all_vars.update({"DTF_CHI2": dtf.CHI2})
+    #    all_vars.update({"DTF_NDOF": dtf.NDOF})
+    #    all_vars.update({"DTF_CHI2DOF": dtf.CHI2DOF})
+         
+    #if comp and dtf:
+    #    all_vars.update({"DTF_MASS": dtf.MASS})
+    #    all_vars.update({"DTF_MASSERR": dtf.MASSERR})
+    #    all_vars.update({"DTF_P": dtf.P})
+    #    all_vars.update({"DTF_PERR": dtf.PERR})
+    #    all_vars.update({"DTF_TAU": dtf.TAU})
+    #    all_vars.update({"DTF_TAUERR": dtf.TAUERR})
+    #    all_vars.update({"DTF_FD": dtf.FD})
+    #    all_vars.update({"DTF_FDERR": dtf.FDERR})
+
+    all_vars.update({"MASS": F.MASS})
+    #if top:  # B
+    #    all_vars.update({"MASSWITHHYPOTHESES": F.MASSWITHHYPOTHESES((939.0, 939.0))})
+    #elif comp:  # Ds
+    #    all_vars.update(
+    #        {"MASSWITHHYPOTHESES": F.MASSWITHHYPOTHESES((493.7, 493.7, 139.6))}
+    #    )
+    if comp:
+        all_vars.update({"MAXPT": F.MAX(F.PT)})
+        all_vars.update({"MAXDOCA": F.MAXSDOCA})
+        all_vars.update({"MAXDOCACHI2": F.MAXSDOCACHI2})
+        # the above in cut versions.
+         
+    # duplicated from FC    all_vars.update({ 'MC_MOTHER_ID' : F.VALUE_OR(0) @ mctruth(
+    # duplicated from FC        F.MC_MOTHER(1, F.PARTICLE_ID))})
+
+    if comp:
+        all_vars.update({"MINPT": F.MIN(F.PT)})
+    all_vars.update({"MINIP": F.MINIP(pvs)})
+    all_vars.update({"MINIPCHI2": F.MINIPCHI2(pvs)})
+    
+    if basic:
+        all_vars.update({"TRACKPT": F.TRACK_PT})
+        all_vars.update({"TRACKHISTORY": F.VALUE_OR(-1) @ F.TRACKHISTORY @ F.TRACK})
+        all_vars.update({"QOVERP": F.QOVERP @ F.TRACK})
+        all_vars.update({"NDOF": F.VALUE_OR(-1) @ F.NDOF @ F.TRACK})
+        all_vars.update({"NFTHITS": F.VALUE_OR(-1) @ F.NFTHITS @ F.TRACK})
+        all_vars.update({"NHITS": F.VALUE_OR(-1) @ F.NHITS @ F.TRACK})
+        all_vars.update({"NUTHITS": F.VALUE_OR(-1) @ F.NUTHITS @ F.TRACK})
+        all_vars.update({"NVPHITS": F.VALUE_OR(-1) @ F.NVPHITS @ F.TRACK})
+        all_vars.update({"TRACKHASVELO": F.VALUE_OR(-1) @ F.TRACKHASVELO @ F.TRACK})
+        all_vars.update({"TRACKHASUT": F.VALUE_OR(-1) @ F.TRACKHASUT @ F.TRACK})
+         
+    all_vars.update({"OBJECT_KEY": F.OBJECT_KEY})
+
+    # duplicated from FC        all_vars.update({ 'ORIGIN_VX' : mctruth(F.ORIGIN_VX) })
+    # duplicated from FC        all_vars.update({ 'ORIGIN_VY' : mctruth(F.ORIGIN_VY) })
+    # duplicated from FC        all_vars.update({ 'ORIGIN_VZ' : mctruth(F.ORIGIN_VZ) })
+    
+    # duplicated from FC        all_vars.update({"P" : F.P})
+    # duplicated from FC        all_vars.update({"PARTICLE_ID" : F.PARTICLE_ID})
+    all_vars.update({"PHI": F.PHI})
+    
+    # duplicated from FC    if basic:
+    # duplicated from FC        all_vars.update({"PID_E" : F.PID_E})
+    # duplicated from FC        all_vars.update({"PID_K" : F.PID_K})
+    # duplicated from FC        all_vars.update({"PID_MU" : F.PID_MU})
+    # duplicated from FC        all_vars.update({"PID_P" : F.PID_P})
+    # duplicated from FC        all_vars.update({"PID_PI" : F.PID_PI})
+    # duplicated from FC        #all_vars.update({"PROBNN_D" : F.PROBNN_D})
+    # duplicated from FC        all_vars.update({"PROBNN_E" : F.PROBNN_E})
+    # duplicated from FC        all_vars.update({"PROBNN_GHOST" : F.PROBNN_GHOST})
+    # duplicated from FC        all_vars.update({"PROBNN_K" : F.PROBNN_K})
+    # duplicated from FC        all_vars.update({"PROBNN_MU" : F.PROBNN_MU})
+    # duplicated from FC        all_vars.update({"PROBNN_P" : F.PROBNN_P})
+    # duplicated from FC        all_vars.update({"PROBNN_PI" : F.PROBNN_PI})
+
+    # duplicated from FC    all_vars.update({ 'PT' : F.PT })
+    # duplicated from FC    all_vars.update({ 'PX' : F.PX })
+    # duplicated from FC    all_vars.update({ 'PY' : F.PY })
+    # duplicated from FC    all_vars.update({ 'PZ' : F.PZ })
+    all_vars.update({"ABS_PX": F.ABS @ F.PX})
+    
+    all_vars.update({"REFERENCEPOINT_X": F.REFERENCEPOINT_X})
+    all_vars.update({"REFERENCEPOINT_Y": F.REFERENCEPOINT_Y})
+    all_vars.update({"REFERENCEPOINT_Z": F.REFERENCEPOINT_Z})
+
+    if comp:
+        all_vars.update({"SDOCA": F.SDOCA(1, 2)})
+        all_vars.update({"SDOCACHI2": F.SDOCACHI2(1, 2)})
+    if basic:
+        all_vars.update({"SHOWER_SHAPE": F.CALO_NEUTRAL_SHOWER_SHAPE})
+        
+    if comp:
+        all_vars.update({"SUBCOMB12_MM": F.SUBCOMB(Functor=F.MASS, Indices=(1, 2))})
+        all_vars.update({"SUMPT": F.SUM(F.PT)})
+        
+    if basic:
+        all_vars.update({"TX": F.TX})
+        all_vars.update({"TY": F.TY})
+        
+    print(f"### For {ptype} returning variables {all_vars.functor_dict.keys()}")
+    return all_vars
+
+
+def event_variables(PVs, ODIN, decreports, lines, hlt1lines):
+    """
+    event variables
+    """
+     
+    evt_vars = FunctorCollection({})
+    evt_vars += FC.EventInfo()
+    
+    evt_vars += FC.SelectionInfo(selection_type="Hlt2", trigger_lines=lines)
+    evt_vars += FC.SelectionInfo(selection_type="Hlt1", trigger_lines=hlt1lines)
+    # duplicated from FC    if ODIN:
+    # duplicated from FC        evt_vars.update({ 'BUNCHCROSSING_ID' : F.BUNCHCROSSING_ID(ODIN) })
+    # duplicated from FC        evt_vars.update({ 'BUNCHCROSSING_TYPE' : F.BUNCHCROSSING_TYPE(ODIN) })
+
+    if decreports:                                                                                                                       
+        evt_vars.update(
+            {
+                "DECISIONS": F.DECISIONS(
+                    Lines=[bd2dsk_line + "Decision"], DecReports=decreports
+                )
+            }
+        )
+        evt_vars.update(
+            {
+                "DECREPORTS_FILTER": F.DECREPORTS_FILTER(
+                    Lines=[bd2dsk_line + "Decision"], DecReports=decreports
+                )
+            }
+        )
+         
+    if ODIN:
+        evt_vars.update({"EVENTTYPE": F.EVENTTYPE(ODIN)})
+
+    # duplicated from FC        evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN) })
+    # duplicated from FC        evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN) })
+    
+    evt_vars.update({"PV_SIZE": F.SIZE(PVs)})
+    # duplicated from FC        evt_vars.update({ 'GPSTIME' : F.GPSTIME(ODIN) })
+    # duplicated from FC        evt_vars.update({ 'ODINTCK' : F.ODINTCK(ODIN) })
+    
+    if decreports:
+        evt_vars.update({"TCK": F.TCK(decreports)})
+         
+    print(f"### For event returning variables {evt_vars.functor_dict.keys()}")
+    return evt_vars
+
+
+def tree_template(decay_descriptor, line_name, isturbo, Hlt2_decisions, QQbar2mumu_data):
+    evtpath_prefix = "/Event/Spruce/"
+    if isturbo:
+        evtpath_prefix = "/Event/HLT2/"
+
+    #QQbar2mumu_data = get_particles(evtpath_prefix+f"{line_name}/Particles")
+    #QQbar2mumu_data = make_jpsi(minPIDmu=-999) 
+
+    pvs = get_pvs()
+
+    Hlt1_decisions = [
+# Global line
+        "Hlt1GlobalDecision", "Hlt1PhysDecision", 
+# Physics lines
+        "Hlt1TrackMVADecision", "Hlt1TwoTrackMVADecision", "Hlt1D2KKDecision", "Hlt1D2KPiDecision", "Hlt1D2PiPiDecision", "Hlt1Dst2D0PiDecision", "Hlt1KsToPiPiDecision", "Hlt1KsToPiPiDoubleMuonMisIDDecision", "Hlt1TwoTrackKsDecision", "Hlt1TwoKsDecision", "Hlt1LambdaLLDetachedTrackDecision", "Hlt1XiOmegaLLLDecision", "Hlt1SingleHighPtMuonDecision", "Hlt1SingleHighPtMuonNoMuIDDecision", "Hlt1DiMuonHighMassDecision", "Hlt1DiMuonDisplacedDecision", "Hlt1DiMuonSoftDecision", "Hlt1TrackMuonMVADecision", "Hlt1DiMuonNoIP_SSDecision", "Hlt1DiMuonDrellYan_VLowMassDecision", "Hlt1DiMuonDrellYan_VLowMass_SSDecision", "Hlt1DiMuonDrellYanDecision", "Hlt1DiMuonDrellYan_SSDecision", "Hlt1DetJpsiToMuMuPosTagLineDecision", "Hlt1DetJpsiToMuMuNegTagLineDecision", "Hlt1TrackElectronMVADecision", "Hlt1SingleHighPtElectronDecision", "Hlt1DiElectronDisplacedDecision", "Hlt1SingleHighEtDecision", "Hlt1DiPhotonHighMassDecision", "Hlt1Pi02GammaGammaDecision", "Hlt1DiElectronHighMass_SSDecision", "Hlt1DiElectronHighMassDecision", "Hlt1DiMuonNoIPDecision"
+## alignment lines
+#        "Hlt1RICH1AlignmentDecision", "Hlt1RICH2AlignmentDecision", "Hlt1D2KPiAlignmentDecision", "Hlt1Dst2D0PiAlignmentDecision", "Hlt1MaterialVertexSeedsDownstreamzDecision", "Hlt1MaterialVertexSeeds_DWFSDecision", "Hlt1DiMuonHighMassAlignmentDecision", "Hlt1DiMuonJpsiMassAlignmentDecision", "Hlt1OneMuonTrackLineDecision", "Hlt1BeamGasDecision",
+## smog2 lines
+#        "Hlt1SMOG2D2KpiDecision", "Hlt1VeloMicroBiasDecision", "Hlt1SMOG2etacToppDecision", "Hlt1SMOG2KsTopipiDecision", "Hlt1SMOG2etacToppDecision", "Hlt1SMOG2KsTopipiDecision", "Hlt1SMOG22BodyGenericDecision", "Hlt1SMOG22BodyGenericLowPtDecision", "Hlt1SMOG2SingleTrackVeryHighPtDecision", "Hlt1SMOG2SingleTrackHighPtDecision", "Hlt1SMOG2DiMuonHighMassDecision", "Hlt1SMOG2SingleMuonDecision", "Hlt1SMOG2L0ToppiDecision",
+## bgi lines
+#         "Hlt1BGIPseudoPVsNoBeamDecision", "Hlt1BGIPseudoPVsBeamOneDecision", "Hlt1BGIPseudoPVsBeamTwoDecision", "Hlt1BGIPseudoPVsUpBeamBeamDecision", "Hlt1BGIPseudoPVsDownBeamBeamDecision", "Hlt1BGIPseudoPVsIRBeamBeamDecision", "Hlt1BGIPVsCylNoBeamDecision", "Hlt1BGIPVsCylBeamOneDecision", "Hlt1BGIPVsCylBeamTwoDecision", "Hlt1BGIPVsCylUpBeamBeamDecision", "Hlt1BGIPVsCylDownBeamBeamDecision", "Hlt1BGIPVsCylIRBeamBeamDecision", "Hlt1BGIVeloClustersMicroBiasDecision", "Hlt1BGICaloDigitsDecision", "Hlt1BGIPlumeActivityDecision",
+## setup hlt1 nodes lines
+#        "Hlt1ODINCalibDecision", "Hlt1TAEPassthroughDecision", "Hlt1ErrorBankDecision", "Hlt1VeloMicroBiasVeloClosingDecision", "Hlt1GECPassthroughDecision", "Hlt1SMOG2BENoBiasDecision", "Hlt1SMOG2PassThroughLowMult5Decision", "Hlt1SMOG2BELowMultElectronsDecision", "Hlt1SMOG2MinimumBiasDecision", "Hlt1PassthroughPVinSMOG2Decision"
+     ]
+
+
+    composite_variables = FunctorCollection({
+        #"ID": F.PARTICLE_ID,
+        #"KEY": F.OBJECT_KEY,
+        #"PT": F.PT,
+        #"PX": F.PX,
+        #"PY": F.PY,
+        #"PZ": F.PZ,
+        #"ENERGY": F.ENERGY,
+        #"P": F.P,
+        #"M": F.MASS,
+        #"ETA": F.ETA,
+        #"PHI": F.PHI,
+        #"ENDVERTEX_CHI2NDOF": F.CHI2DOF,
+        #"FOURMOMENTUM": F.FOURMOMENTUM,
+        #"BPVDIRA": F.BPVDIRA(pvs),
+        #"BPVX": F.BPVX(pvs),
+        #"BPVY": F.BPVY(pvs),
+        #"BPVZ": F.BPVZ(pvs),
+        #"END_VX": F.END_VX,
+        #"END_VY": F.END_VY,
+        #"END_VZ": F.END_VZ,
+        "END_VZ_ERR":F.SQRT @ F.CALL(2,2) @ F.POS_COV_MATRIX @ F.ENDVERTEX,
+        "END_VY_ERR":F.SQRT @ F.CALL(1,1) @ F.POS_COV_MATRIX @ F.ENDVERTEX,
+        "END_VX_ERR":F.SQRT @ F.CALL(0,0) @ F.POS_COV_MATRIX @ F.ENDVERTEX,
+        "BPVZ_ERR": F.SQRT @ F.CALL(2,2) @ F.POS_COV_MATRIX @ F.BPV(pvs),
+        "BPVY_ERR": F.SQRT @ F.CALL(1,1) @ F.POS_COV_MATRIX @ F.BPV(pvs),
+        "BPVX_ERR": F.SQRT @ F.CALL(0,0) @ F.POS_COV_MATRIX @ F.BPV(pvs),
+        #"TAU": F.BPVLTIME(pvs),
+        #"BPVFDCHI2": F.BPVFDCHI2(pvs),
+        #"BPVIPCHI2": F.BPVIPCHI2(pvs)
+    })
+
+    #composite_variables += Kinematics()
+    #composite_variables += ParticleID(extra_info=True)
+    composite_variables += HltTisTos( selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=QQbar2mumu_data)
+    if not isturbo:
+        composite_variables += HltTisTos( selection_type="Hlt2", trigger_lines=Hlt2_decisions, data=QQbar2mumu_data)
+
+    daughter_variables = FunctorCollection({
+        #"ID": F.PARTICLE_ID,
+        #"PT": F.PT,
+        #"PX": F.PX,
+        #"PY": F.PY,
+        #"PZ": F.PZ,
+        #"M": F.MASS,
+        #"ENERGY": F.ENERGY,
+        #"P": F.P,
+        #"ETA": F.ETA,
+        #"PHI": F.PHI,
+        #"Track_CHI2NDOF": F.CHI2DOF,
+        #"ProbNNmu": F.PROBNN_MU,
+        #"PIDmu": F.PID_MU,
+        #"IsMuon": F.ISMUON,
+        #"GhostProb": F.GHOSTPROB,
+        #"FOURMOMENTUM": F.FOURMOMENTUM,
+        "PERR": F.SQRT @ F.PERR2,
+        "PZERR": F.SQRT @ F.CALL(2,2) @ F.THREE_MOM_COV_MATRIX,
+        "TXERR": F.SQRT @ F.CALL(2,2) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement")@ F.TRACK,
+        "TYERR": F.SQRT @ F.CALL(3,3) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement")@ F.TRACK,
+        "COVTXTY": F.CALL(2,3) @ F.TRACK_COVARIANCE @ F.STATE_AT("FirstMeasurement")@ F.TRACK,
+    })
+
+    #daughter_variables += Kinematics()
+    #daughter_variables += ParticleID(extra_info=True)
+
+#    line_prefilter = create_lines_filter(name=f"HLT_PASS{line_name}", lines=[line_name])
+
+    #define event level variables
+    odin = get_odin()
+    decreports = None
+    rec_sum=get_rec_summary()
+    event_info = event_variables(pvs, odin, decreports, [line_name], Hlt1_decisions) + FunctorCollection({
+        "nPVs": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nPVs"),
+        "nTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTracks"),
+        "nLongTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nLongTracks"),
+        "nDownstreamTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nDownstreamTracks"),
+        "nUpstreamTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUpstreamTracks"),
+        "nVeloTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloTracks"),
+        "nBackTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nBackTracks"),
+        "nGhosts": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nGhosts"),
+        "nRich1Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich1Hits"),
+        "nRich2Hits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nRich2Hits"),
+        "nVeloClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVeloClusters"),
+        "nVPClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nVPClusters"),
+        "nITClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nITClusters"),
+        "nTTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nTTClusters"),
+        "nUTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nUTClusters"),
+        "nOTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nOTClusters"),
+        "nFTClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nFTClusters"),
+        "nSPDhits": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nSPDhits"),
+        "eCalTot": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"eCalTot"),
+        "hCalTot": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"hCalTot"),
+        "nEcalClusters": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nEcalClusters"),
+        "nMuonCoordsS0": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS0"),
+        "nMuonCoordsS1": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS1"),
+        "nMuonCoordsS2": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS2"),
+        "nMuonCoordsS3": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS3"),
+        "nMuonCoordsS4": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonCoordsS4"),
+        "nMuonTracks": F.VALUE_OR(-1) @F.RECSUMMARY_INFO(rec_sum,"nMuonTracks"),
+        "ALLPVX": F.ALLPVX(pvs),
+        "ALLPVY": F.ALLPVY(pvs),
+        "ALLPVZ": F.ALLPVZ(pvs),
+    })
+
+    # get trueid bkgcat info
+    MC_TRUTH = MCTruthAndBkgCat(QQbar2mumu_data, name='MCTruthAndBkgCat_'+line_name+"_{hash}")
+    MCMOTHER_ID = lambda n: F.VALUE_OR(0) @ MC_TRUTH(F.MC_MOTHER(n, F.PARTICLE_ID))
+    MCMOTHER_KEY = lambda n: F.VALUE_OR(-1) @ MC_TRUTH(F.MC_MOTHER(n, F.OBJECT_KEY))
+
+    trueid_bkgcat_info = FunctorCollection({
+        #"TRUEID": F.VALUE_OR(0) @ MC_TRUTH(F.PARTICLE_ID),
+        "TRUEKEY": F.VALUE_OR(-1) @ MC_TRUTH(F.OBJECT_KEY),
+        #"TRUEPT": MC_TRUTH(F.PT),
+        #"TRUEPX": MC_TRUTH(F.PX),
+        #"TRUEPY": MC_TRUTH(F.PY),
+        #"TRUEPZ": MC_TRUTH(F.PZ),
+        #"TRUEENERGY": MC_TRUTH(F.ENERGY),
+        #"TRUEP": MC_TRUTH(F.P),
+        "TRUEM": MC_TRUTH(F.MASS),
+        "TRUEETA": MC_TRUTH(F.ETA),
+        "TRUEPHI": MC_TRUTH(F.PHI),
+        "TRUEFOURMOMENTUM": MC_TRUTH(F.FOURMOMENTUM),
+        #"MC_MOTHER_ID": MCMOTHER_ID(1),
+        #"MC_MOTHER_KEY": MCMOTHER_KEY(1),
+        #"MC_GD_MOTHER_ID": MCMOTHER_ID(2),
+        #"MC_GD_MOTHER_KEY": MCMOTHER_KEY(2),
+        #"MC_GD_GD_MOTHER_ID": MCMOTHER_ID(3),
+        #"MC_GD_GD_MOTHER_KEY": MCMOTHER_KEY(3),
+        "TRUEORIGIN_VX": MC_TRUTH(F.ORIGIN_VX),
+        "TRUEORIGIN_VY": MC_TRUTH(F.ORIGIN_VY),
+        "TRUEORIGIN_VZ": MC_TRUTH(F.ORIGIN_VZ),
+        #"TRUEEND_VX": MC_TRUTH(F.END_VX),
+        #"TRUEEND_VY": MC_TRUTH(F.END_VY),
+        #"TRUEEND_VZ": MC_TRUTH(F.END_VZ),
+        "BKGCAT": MC_TRUTH.BkgCat,
+    })
+
+    variables = {
+        "QQbar": composite_variables + all_variables(pvs, MC_TRUTH, _composite) + trueid_bkgcat_info,
+        "mup": daughter_variables + all_variables(pvs, MC_TRUTH, _basic) + trueid_bkgcat_info,
+        "mum": daughter_variables + all_variables(pvs, MC_TRUTH, _basic) + trueid_bkgcat_info, 
+    }
+
+    #define FunTuple instance
+    my_tuple = Funtuple(
+        name=line_name+"_nopid",
+        tuple_name="DecayTree",
+        fields=decay_descriptor,
+        variables=variables,
+        event_variables=event_info,
+        store_multiple_cand_info = True,
+        inputs=QQbar2mumu_data)
+
+    return my_tuple
+
+#def line_prefilter(line_name):
+#    return create_lines_filter(name=f"HLT_PASS{line_name}", lines=[line_name])
+
diff --git a/QuarkoniaToMuMu2024/log b/QuarkoniaToMuMu2024/log
new file mode 100644
index 0000000000..e69de29bb2
-- 
GitLab


From b2b83d6046910671aa16f93abb9e2fa1877dcd82 Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus959.cern.ch>
Date: Thu, 28 Nov 2024 09:44:45 +0100
Subject: [PATCH 10/12] bug fix upsilon

---
 QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py | 2 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py | 2 +-
 QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
index fcfb66d7df..c7614b867d 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon1S.py
@@ -28,7 +28,7 @@ def main(options: Options):
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple_nopid],
+            'Alg_tuple_nopid': [require_pvs(make_pvs()),  my_tuple_nopid],
             'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
index 54e5a79bc7..8fd3e9496e 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon2S.py
@@ -28,7 +28,7 @@ def main(options: Options):
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple_nopid],
+            'Alg_tuple_nopid': [require_pvs(make_pvs()),  my_tuple_nopid],
             'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
diff --git a/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
index 65890de8c4..05fbcd49e5 100644
--- a/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
+++ b/QuarkoniaToMuMu2024/dv_mc_Upsilon3S.py
@@ -28,7 +28,7 @@ def main(options: Options):
 
     my_mctuple = dv_mctree.mctree_template(decay_descriptor_mctree)
     user_algorithms = {
-            'Alg_tuple': [require_pvs(make_pvs()),  my_tuple_nopid],
+            'Alg_tuple_nopid': [require_pvs(make_pvs()),  my_tuple_nopid],
             'Alg_tuple': [my_filter, my_tuple],
             'Alg_mctuple': [my_mctuple],
             }
-- 
GitLab


From 2ac0a1390d2f9d2ef11a64a1c01e0d9e0d61008e Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus904.cern.ch>
Date: Fri, 13 Dec 2024 10:19:33 +0100
Subject: [PATCH 11/12] test with new hlt1 noUT MC

---
 QuarkoniaToMuMu2024/info.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/QuarkoniaToMuMu2024/info.yaml b/QuarkoniaToMuMu2024/info.yaml
index 324fd1e0ec..357bb3dfc5 100644
--- a/QuarkoniaToMuMu2024/info.yaml
+++ b/QuarkoniaToMuMu2024/info.yaml
@@ -23,10 +23,10 @@ defaults:
 {%- for module, channel, eventtype, dv_input_process in entrypoints %}
   {%- for polarity_mc, polarity_mc_jobtitle, nu, n_u, dddb, conddb, mcversion_jobtitle, BKK_label1, BKK_label2, simversion in MC_conditions %}
 
-MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_{{mcversion_jobtitle}}_ROOT:
+MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_{{mcversion_jobtitle}}_ROOT_HLT1NoUT:
     application: "DaVinci/v64r12@x86_64_v3-el9-gcc13+detdesc-opt+g"
     input:
-        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/HLT2-2024.W31.34/{{ eventtype }}/DST"
+        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/HLT1_2024.W31.34_noUT/HLT2-2024.W31.34/{{ eventtype }}/DST"
         keep_running: true 
     output: QQbar2mumu_MC24_tuple.ROOT
     options:
-- 
GitLab


From d77b618f2ceb459e9cc88e5c56538055b2ea19f8 Mon Sep 17 00:00:00 2001
From: Mengzhen Wang <mengzhen@lxplus916.cern.ch>
Date: Fri, 13 Dec 2024 14:47:40 +0100
Subject: [PATCH 12/12] bug fix

---
 QuarkoniaToMuMu2024/info.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/QuarkoniaToMuMu2024/info.yaml b/QuarkoniaToMuMu2024/info.yaml
index 357bb3dfc5..41c5815222 100644
--- a/QuarkoniaToMuMu2024/info.yaml
+++ b/QuarkoniaToMuMu2024/info.yaml
@@ -26,7 +26,7 @@ defaults:
 MC_{{module}}_Nu{{n_u}}_{{polarity_mc_jobtitle}}_{{mcversion_jobtitle}}_ROOT_HLT1NoUT:
     application: "DaVinci/v64r12@x86_64_v3-el9-gcc13+detdesc-opt+g"
     input:
-        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/HLT1_2024.W31.34_noUT/HLT2-2024.W31.34/{{ eventtype }}/DST"
+        bk_query: "/MC/{{BKK_label1}}/Beam6800GeV-{{BKK_label2}}-{{ polarity_mc }}-Nu{{ nu }}-25ns-Pythia8/{{simversion}}/HLT1_2024.W31.34_noUT/HLT2-2024.W31.34/{{ eventtype }}/HLT2.DST"
         keep_running: true 
     output: QQbar2mumu_MC24_tuple.ROOT
     options:
-- 
GitLab