From 49f0dab9f10ddf1db9fb2e4cec3d3c7c1ded57c1 Mon Sep 17 00:00:00 2001
From: Saverio Mariani <samarian@cern.ch>
Date: Wed, 15 Nov 2023 11:11:29 +0100
Subject: [PATCH 1/3] Group SMOG functors into a functor collection

---
 .../python/FunTuple/functorcollections.py     | 644 ++++++++++--------
 1 file changed, 362 insertions(+), 282 deletions(-)

diff --git a/Phys/FunTuple/python/FunTuple/functorcollections.py b/Phys/FunTuple/python/FunTuple/functorcollections.py
index 52be7e6c6..f97efd712 100644
--- a/Phys/FunTuple/python/FunTuple/functorcollections.py
+++ b/Phys/FunTuple/python/FunTuple/functorcollections.py
@@ -28,25 +28,13 @@ from PyConf.Algorithms import Hlt1TisTosAlg, Hlt2TisTosAlg, Hlt1TrueSimEffAlg, H
 import DaVinciMCTools  # type: ignore[import]
 from DecayTreeFitter import DecayTreeFitter  # type: ignore[import]
 from .FunctorCollection import FunctorCollection
+from PyConf.Algorithms import smogInfoAlg  # type: ignore[import]
 
-__all__ = (
-    "EventInfo",
-    "SelectionInfo",
-    "HltTisTos",
-    "Kinematics",
-    "MCHierarchy",
-    "MCKinematics",
-    "MCVertexInfo",
-    "MCPromptDecay",
-    "MCReconstructible",
-    "MCReconstructed",
-    "ParticleIsolation",
-    "ConeIsolation",
-    "NeutralCaloInfo",
-    "DecayTreeFitterResults",
-    "ParticleID",
-    "MCPrimaries",
-)
+__all__ = ("EventInfo", "SelectionInfo", "HltTisTos", "Kinematics",
+           "MCHierarchy", "MCKinematics", "MCVertexInfo", "MCPromptDecay",
+           "MCReconstructible", "MCReconstructed", "ParticleIsolation",
+           "ConeIsolation", "NeutralCaloInfo", "DecayTreeFitterResults",
+           "ParticleID", "MCPrimaries", "SMOGInfo")
 
 
 def EventInfo() -> FunctorCollection:
@@ -83,9 +71,8 @@ def EventInfo() -> FunctorCollection:
     return FunctorCollection(event_info)
 
 
-def SelectionInfo(
-    *, selection_type: HltSourceID, trigger_lines: list[str]
-) -> FunctorCollection:
+def SelectionInfo(*, selection_type: HltSourceID,
+                  trigger_lines: list[str]) -> FunctorCollection:
     """ "
     Event-level collection of most-used functors for tupling trigger/Sprucing information.
 
@@ -117,24 +104,26 @@ def SelectionInfo(
     # check that the code ends with decision
     add_suff_to_elem = lambda s: s + "Decision" if not s.endswith("Decision") else s
     trigger_lines = list(map(add_suff_to_elem, trigger_lines))
-    trigger_info = FunctorCollection({selection_type.name + "_TCK": F.TCK(dec_report)})
+    trigger_info = FunctorCollection({
+        selection_type.name + "_TCK":
+        F.TCK(dec_report)
+    })
     trigger_info += FunctorCollection(
-        {l: F.DECISION(dec_report, l) for l in trigger_lines}
-    )
+        {l: F.DECISION(dec_report, l)
+         for l in trigger_lines})
     return trigger_info
 
 
 def _HltMCTrueSimEff(
-    *,
-    selection_type: HltSourceID,
-    trigger_lines: list[str],
-    mcp_data: DataHandle,
-    dec_reports: DataHandle,
-    mc2IDLink: DataHandle,
-    sel_reports: DataHandle = make_data_with_FetchDataFromFile(
-        "dummy_sel_rep_location"
-    ),
-    cand_locations: list[str] = ["dummy_line_name_Decision_loc"],
+        *,
+        selection_type: HltSourceID,
+        trigger_lines: list[str],
+        mcp_data: DataHandle,
+        dec_reports: DataHandle,
+        mc2IDLink: DataHandle,
+        sel_reports: DataHandle = make_data_with_FetchDataFromFile(
+            "dummy_sel_rep_location"),
+        cand_locations: list[str] = ["dummy_line_name_Decision_loc"],
 ):
     """
     Candidate-level collection to store TrueSim efficiencies for HltEfficiencyChecker
@@ -187,22 +176,19 @@ def _HltMCTrueSimEff(
             f'selection_type "{selection_type}" is not supported in _HltMCTrueSimEff functor collection.'
         )
 
-    return FunctorCollection(
-        {
-            f"{line}TrueSim": F.VALUE_OR(False)
-            @ F.VALUE_FROM_DICT(line)
-            @ F.MAP_TO_RELATED(true_sim_relns)
-            for line in trigger_lines
-        }
-    )
+    return FunctorCollection({
+        f"{line}TrueSim": F.VALUE_OR(False) @ F.VALUE_FROM_DICT(line)
+        @ F.MAP_TO_RELATED(true_sim_relns)
+        for line in trigger_lines
+    })
 
 
 def HltTisTos(
-    *,
-    selection_type: HltSourceID,
-    trigger_lines: list[str],
-    data: DataHandle,
-    trigger_particles: Optional[list[DataHandle]] = None,
+        *,
+        selection_type: HltSourceID,
+        trigger_lines: list[str],
+        data: DataHandle,
+        trigger_particles: Optional[list[DataHandle]] = None,
 ) -> FunctorCollection:
     """
     Candidate-level collection to store TIS (Trigger Independent of Signal) or TOS (Trigger On Signal)
@@ -246,13 +232,14 @@ def HltTisTos(
 
     # Helper function to check if the trigger_lines contain some prefix
     def _check_if_lines_startswith(lines, prefix):
-        line_wo_hlt1prefix = [line for line in lines if not line.startswith(prefix)]
+        line_wo_hlt1prefix = [
+            line for line in lines if not line.startswith(prefix)
+        ]
         if len(line_wo_hlt1prefix) != 0:
             raise ValueError(
                 f"The 'selection_type' is {selection_type}, "
                 "but the following 'trigger_lines' do not "
-                f"contain '{prefix}' in their name: {line_wo_hlt1prefix}"
-            )
+                f"contain '{prefix}' in their name: {line_wo_hlt1prefix}")
 
     selection_type = HltSourceID(selection_type)
     if selection_type == HltSourceID.Spruce:
@@ -283,8 +270,7 @@ def HltTisTos(
             trigger_particles = [
                 get_particles(
                     f"{tes_root_for_tistos()}/{line.replace('Decision','')}/Particles"
-                )
-                for line in trigger_lines
+                ) for line in trigger_lines
             ]
         TisTosRelations = Hlt2TisTosAlg(
             name="Hlt2TisTosAlgName_{hash}",
@@ -294,12 +280,14 @@ def HltTisTos(
             TriggerParticles=trigger_particles,
         ).P2TisTosTable
 
-    hlttistos_info = FunctorCollection(
-        {f"{line}_TOS": F.IS_TOS(line, TisTosRelations) for line in trigger_lines}
-    )
-    hlttistos_info += FunctorCollection(
-        {f"{line}_TIS": F.IS_TIS(line, TisTosRelations) for line in trigger_lines}
-    )
+    hlttistos_info = FunctorCollection({
+        f"{line}_TOS": F.IS_TOS(line, TisTosRelations)
+        for line in trigger_lines
+    })
+    hlttistos_info += FunctorCollection({
+        f"{line}_TIS": F.IS_TIS(line, TisTosRelations)
+        for line in trigger_lines
+    })
     return hlttistos_info
 
 
@@ -331,7 +319,8 @@ def Kinematics() -> FunctorCollection:
     return FunctorCollection(kinematics)
 
 
-def MCKinematics(*, mctruth_alg: DaVinciMCTools.MCTruthAndBkgCat) -> FunctorCollection:
+def MCKinematics(
+        *, mctruth_alg: DaVinciMCTools.MCTruthAndBkgCat) -> FunctorCollection:
     """
     Candidate-level collection of most-used functors on kinematics on the related MC particle.
 
@@ -371,12 +360,12 @@ def MCKinematics(*, mctruth_alg: DaVinciMCTools.MCTruthAndBkgCat) -> FunctorColl
 
 
 def DecayTreeFitterResults(
-    *,
-    DTF: DecayTreeFitter,
-    decay_origin: bool = True,
-    with_lifetime: bool = False,
-    with_kinematics: bool = True,
-    prefix: str = "DTF",
+        *,
+        DTF: DecayTreeFitter,
+        decay_origin: bool = True,
+        with_lifetime: bool = False,
+        with_kinematics: bool = True,
+        prefix: str = "DTF",
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors that access DecayTreeFitter fit results.
@@ -421,57 +410,69 @@ def DecayTreeFitterResults(
     output_collection = FunctorCollection()
 
     if decay_origin:
-        output_collection += FunctorCollection(
-            {
-                f"{prefix}_CHI2{suffix}": DTF.CHI2,
-                f"{prefix}_NDOF{suffix}": DTF.NDOF,
-                f"{prefix}_CHI2DOF{suffix}": DTF.CHI2DOF,
-                f"{prefix}_NITER{suffix}": DTF.NITER,
-                f"{prefix}_MASS{suffix}": DTF.MASS,
-                f"{prefix}_MASSERR{suffix}": DTF.MASSERR,
-                f"{prefix}_P{suffix}": DTF.P,
-                f"{prefix}_PERR{suffix}": DTF.PERR,
-            }
-        )
+        output_collection += FunctorCollection({
+            f"{prefix}_CHI2{suffix}":
+            DTF.CHI2,
+            f"{prefix}_NDOF{suffix}":
+            DTF.NDOF,
+            f"{prefix}_CHI2DOF{suffix}":
+            DTF.CHI2DOF,
+            f"{prefix}_NITER{suffix}":
+            DTF.NITER,
+            f"{prefix}_MASS{suffix}":
+            DTF.MASS,
+            f"{prefix}_MASSERR{suffix}":
+            DTF.MASSERR,
+            f"{prefix}_P{suffix}":
+            DTF.P,
+            f"{prefix}_PERR{suffix}":
+            DTF.PERR,
+        })
         if DTF.HasPVConstraint:
-            output_collection += FunctorCollection(
-                {
-                    f"{prefix}_PV_KEY{suffix}": F.VALUE_OR(-1)
-                    @ DTF(F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.ENDVERTEX),
-                    f"{prefix}_PV_X{suffix}": DTF(F.END_VX),
-                    f"{prefix}_PV_Y{suffix}": DTF(F.END_VY),
-                    f"{prefix}_PV_Z{suffix}": DTF(F.END_VZ),
-                }
-            )
+            output_collection += FunctorCollection({
+                f"{prefix}_PV_KEY{suffix}":
+                F.VALUE_OR(-1) @ DTF(
+                    F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.ENDVERTEX),
+                f"{prefix}_PV_X{suffix}":
+                DTF(F.END_VX),
+                f"{prefix}_PV_Y{suffix}":
+                DTF(F.END_VY),
+                f"{prefix}_PV_Z{suffix}":
+                DTF(F.END_VZ),
+            })
 
     if with_lifetime:
-        output_collection += FunctorCollection(
-            {
-                f"{prefix}_TAU{suffix}": DTF.TAU,
-                f"{prefix}_TAUERR{suffix}": DTF.TAUERR,
-                f"{prefix}_FD{suffix}": DTF.FD,
-                f"{prefix}_FDERR{suffix}": DTF.FDERR,
-            }
-        )
+        output_collection += FunctorCollection({
+            f"{prefix}_TAU{suffix}":
+            DTF.TAU,
+            f"{prefix}_TAUERR{suffix}":
+            DTF.TAUERR,
+            f"{prefix}_FD{suffix}":
+            DTF.FD,
+            f"{prefix}_FDERR{suffix}":
+            DTF.FDERR,
+        })
 
     if with_kinematics:
-        output_collection += FunctorCollection(
-            {
-                f"{prefix}_PX{suffix}": DTF(F.PX),
-                f"{prefix}_PY{suffix}": DTF(F.PY),
-                f"{prefix}_PZ{suffix}": DTF(F.PZ),
-                f"{prefix}_PE{suffix}": DTF(F.ENERGY),
-            }
-        )
+        output_collection += FunctorCollection({
+            f"{prefix}_PX{suffix}":
+            DTF(F.PX),
+            f"{prefix}_PY{suffix}":
+            DTF(F.PY),
+            f"{prefix}_PZ{suffix}":
+            DTF(F.PZ),
+            f"{prefix}_PE{suffix}":
+            DTF(F.ENERGY),
+        })
 
     return output_collection
 
 
 def MCPromptDecay(
-    *,
-    mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
-    max_lifetime: float = 1e-7 * SystemOfUnits.ns,
-    store_longlived_particle_id: bool = True,
+        *,
+        mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
+        max_lifetime: float = 1e-7 * SystemOfUnits.ns,
+        store_longlived_particle_id: bool = True,
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors to determine if a decay is prompt based on the true lifetime of its ancestors.
@@ -514,34 +515,27 @@ def MCPromptDecay(
     else:
         MCTRUTH = mctruth_alg
 
-    collection = FunctorCollection(
-        {
-            "MC_ISPROMPT": F.VALUE_OR(False) @ MCTRUTH(F.MC_ISPROMPT(max_lifetime)),
-        }
-    )
+    collection = FunctorCollection({
+        "MC_ISPROMPT":
+        F.VALUE_OR(False) @ MCTRUTH(F.MC_ISPROMPT(max_lifetime)),
+    })
     if store_longlived_particle_id:
-        collection += FunctorCollection(
-            {
-                "MC_LONGLIVED_ID": F.VALUE_OR(0)
-                @ MCTRUTH(
-                    F.VALUE_OR(0)
-                    @ F.PARTICLE_ID
-                    @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)
-                ),
-                "MC_LONGLIVED_KEY": F.VALUE_OR(-1)
-                @ MCTRUTH(
-                    F.VALUE_OR(-1)
-                    @ F.OBJECT_KEY
-                    @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)
-                ),
-            }
-        )
+        collection += FunctorCollection({
+            "MC_LONGLIVED_ID":
+            F.VALUE_OR(0) @ MCTRUTH(
+                F.VALUE_OR(0) @ F.PARTICLE_ID
+                @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)),
+            "MC_LONGLIVED_KEY":
+            F.VALUE_OR(-1) @ MCTRUTH(
+                F.VALUE_OR(-1) @ F.OBJECT_KEY
+                @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)),
+        })
     return collection
 
 
-def MCHierarchy(
-    *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
-) -> FunctorCollection:
+def MCHierarchy(*,
+                mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
+                ) -> FunctorCollection:
     """
     Candidate-level collection of functors yielding the hierarchy/relationships among MC particles.
     If no argument is provided, i.e. mctruth_alg==None, this collection creates functors that apply to MCParticles;
@@ -590,9 +584,9 @@ def MCHierarchy(
     return FunctorCollection(MCHierarchy)
 
 
-def MCVertexInfo(
-    *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
-) -> FunctorCollection:
+def MCVertexInfo(*,
+                 mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
+                 ) -> FunctorCollection:
     """
     Candidate-level collection of functors on vertices of the related MC particle.
 
@@ -640,7 +634,7 @@ def MCVertexInfo(
 
 
 def MCPrimaryVertexInfo(
-    *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
+        *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors yielding the X, Y and Z positions of the primary vertex of the
@@ -691,24 +685,28 @@ def MCPrimaries(*, mc_header: DataHandle) -> FunctorCollection:
     """
 
     mcprimaries = {
-        "MCPVX[MCPV_IDX]": F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION)
+        "MCPVX[MCPV_IDX]":
+        F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION)
         @ F.MC_ALLPVS(mc_header),
-        "MCPVY[MCPV_IDX]": F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION)
+        "MCPVY[MCPV_IDX]":
+        F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION)
         @ F.MC_ALLPVS(mc_header),
-        "MCPVZ[MCPV_IDX]": F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION)
+        "MCPVZ[MCPV_IDX]":
+        F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION)
         @ F.MC_ALLPVS(mc_header),
-        "MCPVT[MCPV_IDX]": F.MAP(F.VALUE_OR(-1) @ F.MC_VTX_TIME)
-        @ F.MC_ALLPVS(mc_header),
-        "MCPV_SIZE": F.SIZE_OF @ F.MC_ALLPVS(mc_header),
+        "MCPVT[MCPV_IDX]":
+        F.MAP(F.VALUE_OR(-1) @ F.MC_VTX_TIME) @ F.MC_ALLPVS(mc_header),
+        "MCPV_SIZE":
+        F.SIZE_OF @ F.MC_ALLPVS(mc_header),
     }
     return FunctorCollection(mcprimaries)
 
 
 def MCReconstructible(
-    *,
-    mcreconstructible_alg: DaVinciMCTools.MCReconstructible,
-    extra_info: bool = False,
-    mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
+        *,
+        mcreconstructible_alg: DaVinciMCTools.MCReconstructible,
+        extra_info: bool = False,
+        mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors to store reconstrutible information for the MC particle.
@@ -760,57 +758,87 @@ def MCReconstructible(
         MCTRUTH = mctruth_alg
 
     # See above reconstructible categories or functor "MC_ChargeReconstructible" in "Simulation.h" in Rec.
-    func_dict = {"MC_RECONSTRUCTIBLE": MCTRUTH(mcreconstructible_alg.Reconstructible)}
+    func_dict = {
+        "MC_RECONSTRUCTIBLE": MCTRUTH(mcreconstructible_alg.Reconstructible)
+    }
     if extra_info:
-        func_dict.update(
-            {
-                # Has sub-detector hits
-                # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
-                "MC_HASVELO": MCTRUTH(mcreconstructible_alg.HasVelo),
-                "MC_HASVELO_AND_T": MCTRUTH(mcreconstructible_alg.HasVeloAndT),
-                "MC_HAST": MCTRUTH(mcreconstructible_alg.HasT),
-                "MC_HAST1": MCTRUTH(mcreconstructible_alg.HasT1),
-                "MC_HAST2": MCTRUTH(mcreconstructible_alg.HasT2),
-                "MC_HAST3": MCTRUTH(mcreconstructible_alg.HasT3),
-                "MC_HAST1X": MCTRUTH(mcreconstructible_alg.HasT1X),
-                "MC_HAST2X": MCTRUTH(mcreconstructible_alg.HasT2X),
-                "MC_HAST3X": MCTRUTH(mcreconstructible_alg.HasT3X),
-                "MC_HAST1S": MCTRUTH(mcreconstructible_alg.HasT1S),
-                "MC_HAST2S": MCTRUTH(mcreconstructible_alg.HasT2S),
-                "MC_HAST3S": MCTRUTH(mcreconstructible_alg.HasT3S),
-                "MC_HASUT": MCTRUTH(mcreconstructible_alg.HasUT),
-                "MC_HASUT1": MCTRUTH(mcreconstructible_alg.HasUT1),
-                "MC_HASUT2": MCTRUTH(mcreconstructible_alg.HasUT2),
-                # Within sub-detector acceptance
-                # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
-                "MC_ACCVELO": MCTRUTH(mcreconstructible_alg.AccVelo),
-                "MC_ACCVELO_AND_T": MCTRUTH(mcreconstructible_alg.AccVeloAndT),
-                "MC_ACCT": MCTRUTH(mcreconstructible_alg.AccT),
-                "MC_ACCT1": MCTRUTH(mcreconstructible_alg.AccT1),
-                "MC_ACCT2": MCTRUTH(mcreconstructible_alg.AccT2),
-                "MC_ACCT3": MCTRUTH(mcreconstructible_alg.AccT3),
-                "MC_ACCT1X": MCTRUTH(mcreconstructible_alg.AccT1X),
-                "MC_ACCT2X": MCTRUTH(mcreconstructible_alg.AccT2X),
-                "MC_ACCT3X": MCTRUTH(mcreconstructible_alg.AccT3X),
-                "MC_ACCT1S": MCTRUTH(mcreconstructible_alg.AccT1S),
-                "MC_ACCT2S": MCTRUTH(mcreconstructible_alg.AccT2S),
-                "MC_ACCT3S": MCTRUTH(mcreconstructible_alg.AccT3S),
-                "MC_ACCUT": MCTRUTH(mcreconstructible_alg.AccUT),
-                "MC_ACCUT1": MCTRUTH(mcreconstructible_alg.AccUT1),
-                "MC_ACCUT2": MCTRUTH(mcreconstructible_alg.AccUT2),
-                ##These should be updated
-                # "MC_HASVELOR": MCTRUTH(mcreconstructible_alg.HasVeloR),
-                # "MC_HASVELOPhi": MCTRUTH(mcreconstructible_alg.HasVeloPhi),
-                # "MC_ACCVELOR": MCTRUTH(mcreconstructible_alg.AccVeloR),
-                # "MC_ACCVELOPhi": MCTRUTH(mcreconstructible_alg.AccVeloPhi),
-            }
-        )
+        func_dict.update({
+            # Has sub-detector hits
+            # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
+            "MC_HASVELO":
+            MCTRUTH(mcreconstructible_alg.HasVelo),
+            "MC_HASVELO_AND_T":
+            MCTRUTH(mcreconstructible_alg.HasVeloAndT),
+            "MC_HAST":
+            MCTRUTH(mcreconstructible_alg.HasT),
+            "MC_HAST1":
+            MCTRUTH(mcreconstructible_alg.HasT1),
+            "MC_HAST2":
+            MCTRUTH(mcreconstructible_alg.HasT2),
+            "MC_HAST3":
+            MCTRUTH(mcreconstructible_alg.HasT3),
+            "MC_HAST1X":
+            MCTRUTH(mcreconstructible_alg.HasT1X),
+            "MC_HAST2X":
+            MCTRUTH(mcreconstructible_alg.HasT2X),
+            "MC_HAST3X":
+            MCTRUTH(mcreconstructible_alg.HasT3X),
+            "MC_HAST1S":
+            MCTRUTH(mcreconstructible_alg.HasT1S),
+            "MC_HAST2S":
+            MCTRUTH(mcreconstructible_alg.HasT2S),
+            "MC_HAST3S":
+            MCTRUTH(mcreconstructible_alg.HasT3S),
+            "MC_HASUT":
+            MCTRUTH(mcreconstructible_alg.HasUT),
+            "MC_HASUT1":
+            MCTRUTH(mcreconstructible_alg.HasUT1),
+            "MC_HASUT2":
+            MCTRUTH(mcreconstructible_alg.HasUT2),
+            # Within sub-detector acceptance
+            # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
+            "MC_ACCVELO":
+            MCTRUTH(mcreconstructible_alg.AccVelo),
+            "MC_ACCVELO_AND_T":
+            MCTRUTH(mcreconstructible_alg.AccVeloAndT),
+            "MC_ACCT":
+            MCTRUTH(mcreconstructible_alg.AccT),
+            "MC_ACCT1":
+            MCTRUTH(mcreconstructible_alg.AccT1),
+            "MC_ACCT2":
+            MCTRUTH(mcreconstructible_alg.AccT2),
+            "MC_ACCT3":
+            MCTRUTH(mcreconstructible_alg.AccT3),
+            "MC_ACCT1X":
+            MCTRUTH(mcreconstructible_alg.AccT1X),
+            "MC_ACCT2X":
+            MCTRUTH(mcreconstructible_alg.AccT2X),
+            "MC_ACCT3X":
+            MCTRUTH(mcreconstructible_alg.AccT3X),
+            "MC_ACCT1S":
+            MCTRUTH(mcreconstructible_alg.AccT1S),
+            "MC_ACCT2S":
+            MCTRUTH(mcreconstructible_alg.AccT2S),
+            "MC_ACCT3S":
+            MCTRUTH(mcreconstructible_alg.AccT3S),
+            "MC_ACCUT":
+            MCTRUTH(mcreconstructible_alg.AccUT),
+            "MC_ACCUT1":
+            MCTRUTH(mcreconstructible_alg.AccUT1),
+            "MC_ACCUT2":
+            MCTRUTH(mcreconstructible_alg.AccUT2),
+            ##These should be updated
+            # "MC_HASVELOR": MCTRUTH(mcreconstructible_alg.HasVeloR),
+            # "MC_HASVELOPhi": MCTRUTH(mcreconstructible_alg.HasVeloPhi),
+            # "MC_ACCVELOR": MCTRUTH(mcreconstructible_alg.AccVeloR),
+            # "MC_ACCVELOPhi": MCTRUTH(mcreconstructible_alg.AccVeloPhi),
+        })
     return FunctorCollection(func_dict)
 
 
-def MCReconstructed(
-    *, mcreconstructed_alg: DaVinciMCTools.MCReconstructed, extra_info: bool = False
-) -> FunctorCollection:
+def MCReconstructed(*,
+                    mcreconstructed_alg: DaVinciMCTools.MCReconstructed,
+                    extra_info: bool = False) -> FunctorCollection:
     """
     Candidate-level collection of functors to store reconstrutible information for the MC particle.
 
@@ -867,40 +895,62 @@ def MCReconstructed(
         f"RECONSTRUCTED{suffix}": mcreconstructed_alg.Reconstructed,
     }
     if extra_info:
-        func_dict.update(
-            {
-                # For various track properties (e.g track type) see:
-                # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/TrackEvent/include/Event/TrackEnums.h
-                f"TRACK_TYPE{suffix}": mcreconstructed_alg.TrackType,
-                f"TRACK_FLAG{suffix}": mcreconstructed_alg.Flag,
-                f"TRACK_HISTORY{suffix}": mcreconstructed_alg.History,
-                # Common track properties
-                f"TRACK_REFPOINT_X{suffix}": mcreconstructed_alg.ReferencePoint_X,
-                f"TRACK_REFPOINT_Y{suffix}": mcreconstructed_alg.ReferencePoint_Y,
-                f"TRACK_REFPOINT_Z{suffix}": mcreconstructed_alg.ReferencePoint_Z,
-                f"TRACK_QOVERP{suffix}": mcreconstructed_alg.QOVERP,
-                f"TRACK_CHI2{suffix}": mcreconstructed_alg.Chi2,
-                f"TRACK_CHI2DOF{suffix}": mcreconstructed_alg.Chi2DOF,
-                f"TRACK_NDOF{suffix}": mcreconstructed_alg.nDoF,
-                f"TRACK_GHOSTPROB{suffix}": mcreconstructed_alg.GhostProbability,
-                f"TRACK_HAST{suffix}": mcreconstructed_alg.HasT,
-                f"TRACK_HASUT{suffix}": mcreconstructed_alg.HasUT,
-                f"TRACK_HASVELO{suffix}": mcreconstructed_alg.HasVelo,
-                f"TRACK_NHITS{suffix}": mcreconstructed_alg.nHits,
-                f"TRACK_NVPHITS{suffix}": mcreconstructed_alg.nVPHits,
-                f"TRACK_NUTHITS{suffix}": mcreconstructed_alg.nUTHits,
-                f"TRACK_NFTHITS{suffix}": mcreconstructed_alg.nFTHits,
-                # PID properties
-                f"TRACK_PID_MU{suffix}": mcreconstructed_alg.PIDmu,
-                f"TRACK_PID_PI{suffix}": mcreconstructed_alg.PIDpi,
-                f"TRACK_PID_K{suffix}": mcreconstructed_alg.PIDk,
-                f"TRACK_PID_P{suffix}": mcreconstructed_alg.PIDp,
-                f"TRACK_PID_E{suffix}": mcreconstructed_alg.PIDe,
-            }
-        )
+        func_dict.update({
+            # For various track properties (e.g track type) see:
+            # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/TrackEvent/include/Event/TrackEnums.h
+            f"TRACK_TYPE{suffix}":
+            mcreconstructed_alg.TrackType,
+            f"TRACK_FLAG{suffix}":
+            mcreconstructed_alg.Flag,
+            f"TRACK_HISTORY{suffix}":
+            mcreconstructed_alg.History,
+            # Common track properties
+            f"TRACK_REFPOINT_X{suffix}":
+            mcreconstructed_alg.ReferencePoint_X,
+            f"TRACK_REFPOINT_Y{suffix}":
+            mcreconstructed_alg.ReferencePoint_Y,
+            f"TRACK_REFPOINT_Z{suffix}":
+            mcreconstructed_alg.ReferencePoint_Z,
+            f"TRACK_QOVERP{suffix}":
+            mcreconstructed_alg.QOVERP,
+            f"TRACK_CHI2{suffix}":
+            mcreconstructed_alg.Chi2,
+            f"TRACK_CHI2DOF{suffix}":
+            mcreconstructed_alg.Chi2DOF,
+            f"TRACK_NDOF{suffix}":
+            mcreconstructed_alg.nDoF,
+            f"TRACK_GHOSTPROB{suffix}":
+            mcreconstructed_alg.GhostProbability,
+            f"TRACK_HAST{suffix}":
+            mcreconstructed_alg.HasT,
+            f"TRACK_HASUT{suffix}":
+            mcreconstructed_alg.HasUT,
+            f"TRACK_HASVELO{suffix}":
+            mcreconstructed_alg.HasVelo,
+            f"TRACK_NHITS{suffix}":
+            mcreconstructed_alg.nHits,
+            f"TRACK_NVPHITS{suffix}":
+            mcreconstructed_alg.nVPHits,
+            f"TRACK_NUTHITS{suffix}":
+            mcreconstructed_alg.nUTHits,
+            f"TRACK_NFTHITS{suffix}":
+            mcreconstructed_alg.nFTHits,
+            # PID properties
+            f"TRACK_PID_MU{suffix}":
+            mcreconstructed_alg.PIDmu,
+            f"TRACK_PID_PI{suffix}":
+            mcreconstructed_alg.PIDpi,
+            f"TRACK_PID_K{suffix}":
+            mcreconstructed_alg.PIDk,
+            f"TRACK_PID_P{suffix}":
+            mcreconstructed_alg.PIDp,
+            f"TRACK_PID_E{suffix}":
+            mcreconstructed_alg.PIDe,
+        })
 
     if not mcreconstructed_alg.use_best_mcmatch:
-        func_dict[f"TRACK_MCASSOCWEIGHTS{suffix}"] = mcreconstructed_alg.MCAssoc_Weights
+        func_dict[
+            f"TRACK_MCASSOCWEIGHTS{suffix}"] = mcreconstructed_alg.MCAssoc_Weights
         # Note no suffix needed since we are returning simply a number representing
         # the number of reconstructed tracks associated to an MC particle
         # (in technical terms the size of object "range" from relations table)
@@ -910,11 +960,11 @@ def MCReconstructed(
 
 
 def ParticleIsolation(
-    *,
-    iso_rel_table: Algorithm,
-    name: str = "",
-    sumcone_invalid_value=F.NaN,
-    array_indx_name: str = "indx",
+        *,
+        iso_rel_table: Algorithm,
+        name: str = "",
+        sumcone_invalid_value=F.NaN,
+        array_indx_name: str = "indx",
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors on track or neutral isolation, using information from 'iso_rel_table' argument relating containers of reference and extra particle, namely head particles of the cone and particles inside the cone.
@@ -963,7 +1013,8 @@ def ParticleIsolation(
     ASYM = lambda func: F.ASYM(Functor=func, Relations=iso_rel_table.OutputRelations)
 
     # get the set of relations from the relation table stored in the TES location
-    RELS = F.RELATIONS.bind(F.TES(iso_rel_table.OutputRelations), F.FORWARDARGS)
+    RELS = F.RELATIONS.bind(
+        F.TES(iso_rel_table.OutputRelations), F.FORWARDARGS)
     # get ETA and PHI from the reference particle
     REF_ETA = F.ETA @ F.FORWARDARG1
     REF_PHI = F.PHI @ F.FORWARDARG1
@@ -980,35 +1031,44 @@ def ParticleIsolation(
         prefix += f"_{name}"
 
     ParticleIsolationVariables = {
-        f"{prefix}_CMULT": F.VALUE_OR(0)
+        f"{prefix}_CMULT":
+        F.VALUE_OR(0)
         @ F.MAP_INPUT_SIZE(Relations=iso_rel_table.OutputRelations),
-        f"{prefix}_CP": SUMCONE(F.P),
-        f"{prefix}_CPT": SUMCONE(F.PT),
-        f"{prefix}_CPX": SUMCONE(F.PX),
-        f"{prefix}_CPY": SUMCONE(F.PY),
-        f"{prefix}_CPZ": SUMCONE(F.PZ),
-        f"{prefix}_PASY": ASYM(F.P),
-        f"{prefix}_PTASY": ASYM(F.PT),
-        f"{prefix}_PXASY": ASYM(F.PX),
-        f"{prefix}_PYASY": ASYM(F.PY),
-        f"{prefix}_PZASY": ASYM(F.PZ),
-        f"{prefix}_DETA[{array_indx_name}]": F.MAP(DELTA_ETA()).bind(
-            RELS(), F.FORWARDARGS
-        ),
-        f"{prefix}_DPHI[{array_indx_name}]": F.MAP(DELTA_PHI()).bind(
-            RELS(), F.FORWARDARGS
-        ),
+        f"{prefix}_CP":
+        SUMCONE(F.P),
+        f"{prefix}_CPT":
+        SUMCONE(F.PT),
+        f"{prefix}_CPX":
+        SUMCONE(F.PX),
+        f"{prefix}_CPY":
+        SUMCONE(F.PY),
+        f"{prefix}_CPZ":
+        SUMCONE(F.PZ),
+        f"{prefix}_PASY":
+        ASYM(F.P),
+        f"{prefix}_PTASY":
+        ASYM(F.PT),
+        f"{prefix}_PXASY":
+        ASYM(F.PX),
+        f"{prefix}_PYASY":
+        ASYM(F.PY),
+        f"{prefix}_PZASY":
+        ASYM(F.PZ),
+        f"{prefix}_DETA[{array_indx_name}]":
+        F.MAP(DELTA_ETA()).bind(RELS(), F.FORWARDARGS),
+        f"{prefix}_DPHI[{array_indx_name}]":
+        F.MAP(DELTA_PHI()).bind(RELS(), F.FORWARDARGS),
     }
     return FunctorCollection(ParticleIsolationVariables)
 
 
 def ConeIsolation(
-    *,
-    head_cone: DataHandle,
-    charged_cone: DataHandle,
-    neutral_cone: DataHandle,
-    cut: DataHandle,
-    name: str = "",
+        *,
+        head_cone: DataHandle,
+        charged_cone: DataHandle,
+        neutral_cone: DataHandle,
+        cut: DataHandle,
+        name: str = "",
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors on charged and neutral isolation, using information from relations between sets of particles determined by a given criteria. Calculates the relations that 'head_cone' particle selection has with 'charged_cone' particle selection and 'neutral_cone' particle selection, respectively. The cone isolation criteria are determined by the expression in the 'cut'.
@@ -1045,11 +1105,9 @@ def ConeIsolation(
     """
     # Prepare relation tables
     cc_isoAlg = WeightedRelTableAlg(
-        ReferenceParticles=head_cone, InputCandidates=charged_cone, Cut=cut
-    )
+        ReferenceParticles=head_cone, InputCandidates=charged_cone, Cut=cut)
     nc_isoAlg = WeightedRelTableAlg(
-        ReferenceParticles=head_cone, InputCandidates=neutral_cone, Cut=cut
-    )
+        ReferenceParticles=head_cone, InputCandidates=neutral_cone, Cut=cut)
 
     cc_str = "CC"
     nc_str = "NC"
@@ -1061,25 +1119,21 @@ def ConeIsolation(
     nc_prefix = "HEAD_" + nc_str
     # Invoke twice the ParticleIsolation functorcollection, once for neutral and once for charged particles, then add to the functor dictionary
     func_dict = {
-        f"{cc_prefix}_Max_PT": F.MAXCONE(
-            Functor=F.PT, Relations=cc_isoAlg.OutputRelations
-        ),
-        f"{cc_prefix}_Min_PT": F.MINCONE(
-            Functor=F.PT, Relations=cc_isoAlg.OutputRelations
-        ),
-        f"{nc_prefix}_Max_PT": F.MAXCONE(
-            Functor=F.PT, Relations=nc_isoAlg.OutputRelations
-        ),
-        f"{nc_prefix}_Min_PT": F.MINCONE(
-            Functor=F.PT, Relations=nc_isoAlg.OutputRelations
-        ),
+        f"{cc_prefix}_Max_PT":
+        F.MAXCONE(Functor=F.PT, Relations=cc_isoAlg.OutputRelations),
+        f"{cc_prefix}_Min_PT":
+        F.MINCONE(Functor=F.PT, Relations=cc_isoAlg.OutputRelations),
+        f"{nc_prefix}_Max_PT":
+        F.MAXCONE(Functor=F.PT, Relations=nc_isoAlg.OutputRelations),
+        f"{nc_prefix}_Min_PT":
+        F.MINCONE(Functor=F.PT, Relations=nc_isoAlg.OutputRelations),
     }
     func_dict.update(
-        ParticleIsolation(name=f"{cc_str}", iso_rel_table=cc_isoAlg).functor_dict
-    )
+        ParticleIsolation(name=f"{cc_str}",
+                          iso_rel_table=cc_isoAlg).functor_dict)
     func_dict.update(
-        ParticleIsolation(name=f"{nc_str}", iso_rel_table=nc_isoAlg).functor_dict
-    )
+        ParticleIsolation(name=f"{nc_str}",
+                          iso_rel_table=nc_isoAlg).functor_dict)
 
     return FunctorCollection(func_dict)
 
@@ -1108,7 +1162,8 @@ def NeutralCaloInfo() -> FunctorCollection:
         "CaloNeutralEcalEnergy": F.CALO_NEUTRAL_ECAL_ENERGY,
         "CaloNeutral1To9EnergyRatio": F.CALO_NEUTRAL_1TO9_ENERGY_RATIO,
         "CaloNeutral4To9EnergyRatio": F.CALO_NEUTRAL_4TO9_ENERGY_RATIO,
-        "CaloNeutralHcal2EcalEnergyRatio": F.CALO_NEUTRAL_HCAL2ECAL_ENERGY_RATIO,
+        "CaloNeutralHcal2EcalEnergyRatio":
+        F.CALO_NEUTRAL_HCAL2ECAL_ENERGY_RATIO,
         "CaloNeutralID": F.CALO_NEUTRAL_ID,
         "CaloNumSaturatedCells": F.CALO_NUM_SATURATED_CELLS,
     }
@@ -1133,14 +1188,39 @@ def ParticleID(extra_info: bool = False) -> FunctorCollection:
         "PROBNN_PI": F.PROBNN_PI,
     }
     if extra_info:
-        pid_vars.update(
-            {
-                "PID_E": F.PID_E,
-                "PID_K": F.PID_K,
-                "PID_MU": F.PID_MU,
-                "PID_P": F.PID_P,
-                "PID_PI": F.PID_PI,
-            }
-        )
+        pid_vars.update({
+            "PID_E": F.PID_E,
+            "PID_K": F.PID_K,
+            "PID_MU": F.PID_MU,
+            "PID_P": F.PID_P,
+            "PID_PI": F.PID_PI,
+        })
 
     return FunctorCollection(pid_vars)
+
+
+def SMOGInfo() -> FunctorCollection:
+    """
+    Collection of SMOG conditions (injection mode, injected gas, stable injection flag)
+
+    Example:
+        import FunTuple.functorcollections as FC
+        from DaVinci import options
+
+        variables = FC.SMOGInfo()
+        # ...
+
+        tuple = Funtuple(name="MyTuple",
+                         fields=...,
+                         variables=variables,
+                         ...
+                         )
+    """
+    smog = smogInfoAlg(name='smogInfo').Output
+
+    smog_info = {}
+    smog_info["SMOG_InjectionMode"] = F.SMOG_INJECTION_MODE(smog)
+    smog_info["SMOG_InjectedGas"] = F.SMOG_INJECTED_GAS(smog)
+    smog_info["SMOG_StableInjection"] = F.SMOG_STABLE_INJECTION(smog)
+
+    return FunctorCollection(smog_info)
-- 
GitLab


From ebdecf72564dcd293338e65b9cbfa7c179a70171 Mon Sep 17 00:00:00 2001
From: Gitlab CI <noreply@cern.ch>
Date: Wed, 15 Nov 2023 10:12:06 +0000
Subject: [PATCH 2/3] pre-commit fixes

patch generated by https://gitlab.cern.ch/lhcb/Analysis/-/jobs/33975499
---
 .../python/FunTuple/functorcollections.py     | 619 ++++++++----------
 1 file changed, 284 insertions(+), 335 deletions(-)

diff --git a/Phys/FunTuple/python/FunTuple/functorcollections.py b/Phys/FunTuple/python/FunTuple/functorcollections.py
index f97efd712..87ab1629d 100644
--- a/Phys/FunTuple/python/FunTuple/functorcollections.py
+++ b/Phys/FunTuple/python/FunTuple/functorcollections.py
@@ -30,11 +30,25 @@ from DecayTreeFitter import DecayTreeFitter  # type: ignore[import]
 from .FunctorCollection import FunctorCollection
 from PyConf.Algorithms import smogInfoAlg  # type: ignore[import]
 
-__all__ = ("EventInfo", "SelectionInfo", "HltTisTos", "Kinematics",
-           "MCHierarchy", "MCKinematics", "MCVertexInfo", "MCPromptDecay",
-           "MCReconstructible", "MCReconstructed", "ParticleIsolation",
-           "ConeIsolation", "NeutralCaloInfo", "DecayTreeFitterResults",
-           "ParticleID", "MCPrimaries", "SMOGInfo")
+__all__ = (
+    "EventInfo",
+    "SelectionInfo",
+    "HltTisTos",
+    "Kinematics",
+    "MCHierarchy",
+    "MCKinematics",
+    "MCVertexInfo",
+    "MCPromptDecay",
+    "MCReconstructible",
+    "MCReconstructed",
+    "ParticleIsolation",
+    "ConeIsolation",
+    "NeutralCaloInfo",
+    "DecayTreeFitterResults",
+    "ParticleID",
+    "MCPrimaries",
+    "SMOGInfo",
+)
 
 
 def EventInfo() -> FunctorCollection:
@@ -71,8 +85,9 @@ def EventInfo() -> FunctorCollection:
     return FunctorCollection(event_info)
 
 
-def SelectionInfo(*, selection_type: HltSourceID,
-                  trigger_lines: list[str]) -> FunctorCollection:
+def SelectionInfo(
+    *, selection_type: HltSourceID, trigger_lines: list[str]
+) -> FunctorCollection:
     """ "
     Event-level collection of most-used functors for tupling trigger/Sprucing information.
 
@@ -104,26 +119,24 @@ def SelectionInfo(*, selection_type: HltSourceID,
     # check that the code ends with decision
     add_suff_to_elem = lambda s: s + "Decision" if not s.endswith("Decision") else s
     trigger_lines = list(map(add_suff_to_elem, trigger_lines))
-    trigger_info = FunctorCollection({
-        selection_type.name + "_TCK":
-        F.TCK(dec_report)
-    })
+    trigger_info = FunctorCollection({selection_type.name + "_TCK": F.TCK(dec_report)})
     trigger_info += FunctorCollection(
-        {l: F.DECISION(dec_report, l)
-         for l in trigger_lines})
+        {l: F.DECISION(dec_report, l) for l in trigger_lines}
+    )
     return trigger_info
 
 
 def _HltMCTrueSimEff(
-        *,
-        selection_type: HltSourceID,
-        trigger_lines: list[str],
-        mcp_data: DataHandle,
-        dec_reports: DataHandle,
-        mc2IDLink: DataHandle,
-        sel_reports: DataHandle = make_data_with_FetchDataFromFile(
-            "dummy_sel_rep_location"),
-        cand_locations: list[str] = ["dummy_line_name_Decision_loc"],
+    *,
+    selection_type: HltSourceID,
+    trigger_lines: list[str],
+    mcp_data: DataHandle,
+    dec_reports: DataHandle,
+    mc2IDLink: DataHandle,
+    sel_reports: DataHandle = make_data_with_FetchDataFromFile(
+        "dummy_sel_rep_location"
+    ),
+    cand_locations: list[str] = ["dummy_line_name_Decision_loc"],
 ):
     """
     Candidate-level collection to store TrueSim efficiencies for HltEfficiencyChecker
@@ -176,19 +189,22 @@ def _HltMCTrueSimEff(
             f'selection_type "{selection_type}" is not supported in _HltMCTrueSimEff functor collection.'
         )
 
-    return FunctorCollection({
-        f"{line}TrueSim": F.VALUE_OR(False) @ F.VALUE_FROM_DICT(line)
-        @ F.MAP_TO_RELATED(true_sim_relns)
-        for line in trigger_lines
-    })
+    return FunctorCollection(
+        {
+            f"{line}TrueSim": F.VALUE_OR(False)
+            @ F.VALUE_FROM_DICT(line)
+            @ F.MAP_TO_RELATED(true_sim_relns)
+            for line in trigger_lines
+        }
+    )
 
 
 def HltTisTos(
-        *,
-        selection_type: HltSourceID,
-        trigger_lines: list[str],
-        data: DataHandle,
-        trigger_particles: Optional[list[DataHandle]] = None,
+    *,
+    selection_type: HltSourceID,
+    trigger_lines: list[str],
+    data: DataHandle,
+    trigger_particles: Optional[list[DataHandle]] = None,
 ) -> FunctorCollection:
     """
     Candidate-level collection to store TIS (Trigger Independent of Signal) or TOS (Trigger On Signal)
@@ -232,14 +248,13 @@ def HltTisTos(
 
     # Helper function to check if the trigger_lines contain some prefix
     def _check_if_lines_startswith(lines, prefix):
-        line_wo_hlt1prefix = [
-            line for line in lines if not line.startswith(prefix)
-        ]
+        line_wo_hlt1prefix = [line for line in lines if not line.startswith(prefix)]
         if len(line_wo_hlt1prefix) != 0:
             raise ValueError(
                 f"The 'selection_type' is {selection_type}, "
                 "but the following 'trigger_lines' do not "
-                f"contain '{prefix}' in their name: {line_wo_hlt1prefix}")
+                f"contain '{prefix}' in their name: {line_wo_hlt1prefix}"
+            )
 
     selection_type = HltSourceID(selection_type)
     if selection_type == HltSourceID.Spruce:
@@ -270,7 +285,8 @@ def HltTisTos(
             trigger_particles = [
                 get_particles(
                     f"{tes_root_for_tistos()}/{line.replace('Decision','')}/Particles"
-                ) for line in trigger_lines
+                )
+                for line in trigger_lines
             ]
         TisTosRelations = Hlt2TisTosAlg(
             name="Hlt2TisTosAlgName_{hash}",
@@ -280,14 +296,12 @@ def HltTisTos(
             TriggerParticles=trigger_particles,
         ).P2TisTosTable
 
-    hlttistos_info = FunctorCollection({
-        f"{line}_TOS": F.IS_TOS(line, TisTosRelations)
-        for line in trigger_lines
-    })
-    hlttistos_info += FunctorCollection({
-        f"{line}_TIS": F.IS_TIS(line, TisTosRelations)
-        for line in trigger_lines
-    })
+    hlttistos_info = FunctorCollection(
+        {f"{line}_TOS": F.IS_TOS(line, TisTosRelations) for line in trigger_lines}
+    )
+    hlttistos_info += FunctorCollection(
+        {f"{line}_TIS": F.IS_TIS(line, TisTosRelations) for line in trigger_lines}
+    )
     return hlttistos_info
 
 
@@ -319,8 +333,7 @@ def Kinematics() -> FunctorCollection:
     return FunctorCollection(kinematics)
 
 
-def MCKinematics(
-        *, mctruth_alg: DaVinciMCTools.MCTruthAndBkgCat) -> FunctorCollection:
+def MCKinematics(*, mctruth_alg: DaVinciMCTools.MCTruthAndBkgCat) -> FunctorCollection:
     """
     Candidate-level collection of most-used functors on kinematics on the related MC particle.
 
@@ -360,12 +373,12 @@ def MCKinematics(
 
 
 def DecayTreeFitterResults(
-        *,
-        DTF: DecayTreeFitter,
-        decay_origin: bool = True,
-        with_lifetime: bool = False,
-        with_kinematics: bool = True,
-        prefix: str = "DTF",
+    *,
+    DTF: DecayTreeFitter,
+    decay_origin: bool = True,
+    with_lifetime: bool = False,
+    with_kinematics: bool = True,
+    prefix: str = "DTF",
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors that access DecayTreeFitter fit results.
@@ -410,69 +423,57 @@ def DecayTreeFitterResults(
     output_collection = FunctorCollection()
 
     if decay_origin:
-        output_collection += FunctorCollection({
-            f"{prefix}_CHI2{suffix}":
-            DTF.CHI2,
-            f"{prefix}_NDOF{suffix}":
-            DTF.NDOF,
-            f"{prefix}_CHI2DOF{suffix}":
-            DTF.CHI2DOF,
-            f"{prefix}_NITER{suffix}":
-            DTF.NITER,
-            f"{prefix}_MASS{suffix}":
-            DTF.MASS,
-            f"{prefix}_MASSERR{suffix}":
-            DTF.MASSERR,
-            f"{prefix}_P{suffix}":
-            DTF.P,
-            f"{prefix}_PERR{suffix}":
-            DTF.PERR,
-        })
+        output_collection += FunctorCollection(
+            {
+                f"{prefix}_CHI2{suffix}": DTF.CHI2,
+                f"{prefix}_NDOF{suffix}": DTF.NDOF,
+                f"{prefix}_CHI2DOF{suffix}": DTF.CHI2DOF,
+                f"{prefix}_NITER{suffix}": DTF.NITER,
+                f"{prefix}_MASS{suffix}": DTF.MASS,
+                f"{prefix}_MASSERR{suffix}": DTF.MASSERR,
+                f"{prefix}_P{suffix}": DTF.P,
+                f"{prefix}_PERR{suffix}": DTF.PERR,
+            }
+        )
         if DTF.HasPVConstraint:
-            output_collection += FunctorCollection({
-                f"{prefix}_PV_KEY{suffix}":
-                F.VALUE_OR(-1) @ DTF(
-                    F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.ENDVERTEX),
-                f"{prefix}_PV_X{suffix}":
-                DTF(F.END_VX),
-                f"{prefix}_PV_Y{suffix}":
-                DTF(F.END_VY),
-                f"{prefix}_PV_Z{suffix}":
-                DTF(F.END_VZ),
-            })
+            output_collection += FunctorCollection(
+                {
+                    f"{prefix}_PV_KEY{suffix}": F.VALUE_OR(-1)
+                    @ DTF(F.VALUE_OR(-1) @ F.OBJECT_KEY @ F.ENDVERTEX),
+                    f"{prefix}_PV_X{suffix}": DTF(F.END_VX),
+                    f"{prefix}_PV_Y{suffix}": DTF(F.END_VY),
+                    f"{prefix}_PV_Z{suffix}": DTF(F.END_VZ),
+                }
+            )
 
     if with_lifetime:
-        output_collection += FunctorCollection({
-            f"{prefix}_TAU{suffix}":
-            DTF.TAU,
-            f"{prefix}_TAUERR{suffix}":
-            DTF.TAUERR,
-            f"{prefix}_FD{suffix}":
-            DTF.FD,
-            f"{prefix}_FDERR{suffix}":
-            DTF.FDERR,
-        })
+        output_collection += FunctorCollection(
+            {
+                f"{prefix}_TAU{suffix}": DTF.TAU,
+                f"{prefix}_TAUERR{suffix}": DTF.TAUERR,
+                f"{prefix}_FD{suffix}": DTF.FD,
+                f"{prefix}_FDERR{suffix}": DTF.FDERR,
+            }
+        )
 
     if with_kinematics:
-        output_collection += FunctorCollection({
-            f"{prefix}_PX{suffix}":
-            DTF(F.PX),
-            f"{prefix}_PY{suffix}":
-            DTF(F.PY),
-            f"{prefix}_PZ{suffix}":
-            DTF(F.PZ),
-            f"{prefix}_PE{suffix}":
-            DTF(F.ENERGY),
-        })
+        output_collection += FunctorCollection(
+            {
+                f"{prefix}_PX{suffix}": DTF(F.PX),
+                f"{prefix}_PY{suffix}": DTF(F.PY),
+                f"{prefix}_PZ{suffix}": DTF(F.PZ),
+                f"{prefix}_PE{suffix}": DTF(F.ENERGY),
+            }
+        )
 
     return output_collection
 
 
 def MCPromptDecay(
-        *,
-        mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
-        max_lifetime: float = 1e-7 * SystemOfUnits.ns,
-        store_longlived_particle_id: bool = True,
+    *,
+    mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
+    max_lifetime: float = 1e-7 * SystemOfUnits.ns,
+    store_longlived_particle_id: bool = True,
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors to determine if a decay is prompt based on the true lifetime of its ancestors.
@@ -515,27 +516,34 @@ def MCPromptDecay(
     else:
         MCTRUTH = mctruth_alg
 
-    collection = FunctorCollection({
-        "MC_ISPROMPT":
-        F.VALUE_OR(False) @ MCTRUTH(F.MC_ISPROMPT(max_lifetime)),
-    })
+    collection = FunctorCollection(
+        {
+            "MC_ISPROMPT": F.VALUE_OR(False) @ MCTRUTH(F.MC_ISPROMPT(max_lifetime)),
+        }
+    )
     if store_longlived_particle_id:
-        collection += FunctorCollection({
-            "MC_LONGLIVED_ID":
-            F.VALUE_OR(0) @ MCTRUTH(
-                F.VALUE_OR(0) @ F.PARTICLE_ID
-                @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)),
-            "MC_LONGLIVED_KEY":
-            F.VALUE_OR(-1) @ MCTRUTH(
-                F.VALUE_OR(-1) @ F.OBJECT_KEY
-                @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)),
-        })
+        collection += FunctorCollection(
+            {
+                "MC_LONGLIVED_ID": F.VALUE_OR(0)
+                @ MCTRUTH(
+                    F.VALUE_OR(0)
+                    @ F.PARTICLE_ID
+                    @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)
+                ),
+                "MC_LONGLIVED_KEY": F.VALUE_OR(-1)
+                @ MCTRUTH(
+                    F.VALUE_OR(-1)
+                    @ F.OBJECT_KEY
+                    @ F.MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime)
+                ),
+            }
+        )
     return collection
 
 
-def MCHierarchy(*,
-                mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
-                ) -> FunctorCollection:
+def MCHierarchy(
+    *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
+) -> FunctorCollection:
     """
     Candidate-level collection of functors yielding the hierarchy/relationships among MC particles.
     If no argument is provided, i.e. mctruth_alg==None, this collection creates functors that apply to MCParticles;
@@ -584,9 +592,9 @@ def MCHierarchy(*,
     return FunctorCollection(MCHierarchy)
 
 
-def MCVertexInfo(*,
-                 mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
-                 ) -> FunctorCollection:
+def MCVertexInfo(
+    *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
+) -> FunctorCollection:
     """
     Candidate-level collection of functors on vertices of the related MC particle.
 
@@ -634,7 +642,7 @@ def MCVertexInfo(*,
 
 
 def MCPrimaryVertexInfo(
-        *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
+    *, mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors yielding the X, Y and Z positions of the primary vertex of the
@@ -685,28 +693,24 @@ def MCPrimaries(*, mc_header: DataHandle) -> FunctorCollection:
     """
 
     mcprimaries = {
-        "MCPVX[MCPV_IDX]":
-        F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION)
+        "MCPVX[MCPV_IDX]": F.MAP(F.VALUE_OR(F.NaN) @ F.X_COORDINATE @ F.POSITION)
+        @ F.MC_ALLPVS(mc_header),
+        "MCPVY[MCPV_IDX]": F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION)
         @ F.MC_ALLPVS(mc_header),
-        "MCPVY[MCPV_IDX]":
-        F.MAP(F.VALUE_OR(F.NaN) @ F.Y_COORDINATE @ F.POSITION)
+        "MCPVZ[MCPV_IDX]": F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION)
         @ F.MC_ALLPVS(mc_header),
-        "MCPVZ[MCPV_IDX]":
-        F.MAP(F.VALUE_OR(F.NaN) @ F.Z_COORDINATE @ F.POSITION)
+        "MCPVT[MCPV_IDX]": F.MAP(F.VALUE_OR(-1) @ F.MC_VTX_TIME)
         @ F.MC_ALLPVS(mc_header),
-        "MCPVT[MCPV_IDX]":
-        F.MAP(F.VALUE_OR(-1) @ F.MC_VTX_TIME) @ F.MC_ALLPVS(mc_header),
-        "MCPV_SIZE":
-        F.SIZE_OF @ F.MC_ALLPVS(mc_header),
+        "MCPV_SIZE": F.SIZE_OF @ F.MC_ALLPVS(mc_header),
     }
     return FunctorCollection(mcprimaries)
 
 
 def MCReconstructible(
-        *,
-        mcreconstructible_alg: DaVinciMCTools.MCReconstructible,
-        extra_info: bool = False,
-        mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
+    *,
+    mcreconstructible_alg: DaVinciMCTools.MCReconstructible,
+    extra_info: bool = False,
+    mctruth_alg: Optional[DaVinciMCTools.MCTruthAndBkgCat] = None,
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors to store reconstrutible information for the MC particle.
@@ -758,87 +762,57 @@ def MCReconstructible(
         MCTRUTH = mctruth_alg
 
     # See above reconstructible categories or functor "MC_ChargeReconstructible" in "Simulation.h" in Rec.
-    func_dict = {
-        "MC_RECONSTRUCTIBLE": MCTRUTH(mcreconstructible_alg.Reconstructible)
-    }
+    func_dict = {"MC_RECONSTRUCTIBLE": MCTRUTH(mcreconstructible_alg.Reconstructible)}
     if extra_info:
-        func_dict.update({
-            # Has sub-detector hits
-            # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
-            "MC_HASVELO":
-            MCTRUTH(mcreconstructible_alg.HasVelo),
-            "MC_HASVELO_AND_T":
-            MCTRUTH(mcreconstructible_alg.HasVeloAndT),
-            "MC_HAST":
-            MCTRUTH(mcreconstructible_alg.HasT),
-            "MC_HAST1":
-            MCTRUTH(mcreconstructible_alg.HasT1),
-            "MC_HAST2":
-            MCTRUTH(mcreconstructible_alg.HasT2),
-            "MC_HAST3":
-            MCTRUTH(mcreconstructible_alg.HasT3),
-            "MC_HAST1X":
-            MCTRUTH(mcreconstructible_alg.HasT1X),
-            "MC_HAST2X":
-            MCTRUTH(mcreconstructible_alg.HasT2X),
-            "MC_HAST3X":
-            MCTRUTH(mcreconstructible_alg.HasT3X),
-            "MC_HAST1S":
-            MCTRUTH(mcreconstructible_alg.HasT1S),
-            "MC_HAST2S":
-            MCTRUTH(mcreconstructible_alg.HasT2S),
-            "MC_HAST3S":
-            MCTRUTH(mcreconstructible_alg.HasT3S),
-            "MC_HASUT":
-            MCTRUTH(mcreconstructible_alg.HasUT),
-            "MC_HASUT1":
-            MCTRUTH(mcreconstructible_alg.HasUT1),
-            "MC_HASUT2":
-            MCTRUTH(mcreconstructible_alg.HasUT2),
-            # Within sub-detector acceptance
-            # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
-            "MC_ACCVELO":
-            MCTRUTH(mcreconstructible_alg.AccVelo),
-            "MC_ACCVELO_AND_T":
-            MCTRUTH(mcreconstructible_alg.AccVeloAndT),
-            "MC_ACCT":
-            MCTRUTH(mcreconstructible_alg.AccT),
-            "MC_ACCT1":
-            MCTRUTH(mcreconstructible_alg.AccT1),
-            "MC_ACCT2":
-            MCTRUTH(mcreconstructible_alg.AccT2),
-            "MC_ACCT3":
-            MCTRUTH(mcreconstructible_alg.AccT3),
-            "MC_ACCT1X":
-            MCTRUTH(mcreconstructible_alg.AccT1X),
-            "MC_ACCT2X":
-            MCTRUTH(mcreconstructible_alg.AccT2X),
-            "MC_ACCT3X":
-            MCTRUTH(mcreconstructible_alg.AccT3X),
-            "MC_ACCT1S":
-            MCTRUTH(mcreconstructible_alg.AccT1S),
-            "MC_ACCT2S":
-            MCTRUTH(mcreconstructible_alg.AccT2S),
-            "MC_ACCT3S":
-            MCTRUTH(mcreconstructible_alg.AccT3S),
-            "MC_ACCUT":
-            MCTRUTH(mcreconstructible_alg.AccUT),
-            "MC_ACCUT1":
-            MCTRUTH(mcreconstructible_alg.AccUT1),
-            "MC_ACCUT2":
-            MCTRUTH(mcreconstructible_alg.AccUT2),
-            ##These should be updated
-            # "MC_HASVELOR": MCTRUTH(mcreconstructible_alg.HasVeloR),
-            # "MC_HASVELOPhi": MCTRUTH(mcreconstructible_alg.HasVeloPhi),
-            # "MC_ACCVELOR": MCTRUTH(mcreconstructible_alg.AccVeloR),
-            # "MC_ACCVELOPhi": MCTRUTH(mcreconstructible_alg.AccVeloPhi),
-        })
+        func_dict.update(
+            {
+                # Has sub-detector hits
+                # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
+                "MC_HASVELO": MCTRUTH(mcreconstructible_alg.HasVelo),
+                "MC_HASVELO_AND_T": MCTRUTH(mcreconstructible_alg.HasVeloAndT),
+                "MC_HAST": MCTRUTH(mcreconstructible_alg.HasT),
+                "MC_HAST1": MCTRUTH(mcreconstructible_alg.HasT1),
+                "MC_HAST2": MCTRUTH(mcreconstructible_alg.HasT2),
+                "MC_HAST3": MCTRUTH(mcreconstructible_alg.HasT3),
+                "MC_HAST1X": MCTRUTH(mcreconstructible_alg.HasT1X),
+                "MC_HAST2X": MCTRUTH(mcreconstructible_alg.HasT2X),
+                "MC_HAST3X": MCTRUTH(mcreconstructible_alg.HasT3X),
+                "MC_HAST1S": MCTRUTH(mcreconstructible_alg.HasT1S),
+                "MC_HAST2S": MCTRUTH(mcreconstructible_alg.HasT2S),
+                "MC_HAST3S": MCTRUTH(mcreconstructible_alg.HasT3S),
+                "MC_HASUT": MCTRUTH(mcreconstructible_alg.HasUT),
+                "MC_HASUT1": MCTRUTH(mcreconstructible_alg.HasUT1),
+                "MC_HASUT2": MCTRUTH(mcreconstructible_alg.HasUT2),
+                # Within sub-detector acceptance
+                # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/MCEvent/include/Event/MCTrackInfo.h
+                "MC_ACCVELO": MCTRUTH(mcreconstructible_alg.AccVelo),
+                "MC_ACCVELO_AND_T": MCTRUTH(mcreconstructible_alg.AccVeloAndT),
+                "MC_ACCT": MCTRUTH(mcreconstructible_alg.AccT),
+                "MC_ACCT1": MCTRUTH(mcreconstructible_alg.AccT1),
+                "MC_ACCT2": MCTRUTH(mcreconstructible_alg.AccT2),
+                "MC_ACCT3": MCTRUTH(mcreconstructible_alg.AccT3),
+                "MC_ACCT1X": MCTRUTH(mcreconstructible_alg.AccT1X),
+                "MC_ACCT2X": MCTRUTH(mcreconstructible_alg.AccT2X),
+                "MC_ACCT3X": MCTRUTH(mcreconstructible_alg.AccT3X),
+                "MC_ACCT1S": MCTRUTH(mcreconstructible_alg.AccT1S),
+                "MC_ACCT2S": MCTRUTH(mcreconstructible_alg.AccT2S),
+                "MC_ACCT3S": MCTRUTH(mcreconstructible_alg.AccT3S),
+                "MC_ACCUT": MCTRUTH(mcreconstructible_alg.AccUT),
+                "MC_ACCUT1": MCTRUTH(mcreconstructible_alg.AccUT1),
+                "MC_ACCUT2": MCTRUTH(mcreconstructible_alg.AccUT2),
+                ##These should be updated
+                # "MC_HASVELOR": MCTRUTH(mcreconstructible_alg.HasVeloR),
+                # "MC_HASVELOPhi": MCTRUTH(mcreconstructible_alg.HasVeloPhi),
+                # "MC_ACCVELOR": MCTRUTH(mcreconstructible_alg.AccVeloR),
+                # "MC_ACCVELOPhi": MCTRUTH(mcreconstructible_alg.AccVeloPhi),
+            }
+        )
     return FunctorCollection(func_dict)
 
 
-def MCReconstructed(*,
-                    mcreconstructed_alg: DaVinciMCTools.MCReconstructed,
-                    extra_info: bool = False) -> FunctorCollection:
+def MCReconstructed(
+    *, mcreconstructed_alg: DaVinciMCTools.MCReconstructed, extra_info: bool = False
+) -> FunctorCollection:
     """
     Candidate-level collection of functors to store reconstrutible information for the MC particle.
 
@@ -895,62 +869,40 @@ def MCReconstructed(*,
         f"RECONSTRUCTED{suffix}": mcreconstructed_alg.Reconstructed,
     }
     if extra_info:
-        func_dict.update({
-            # For various track properties (e.g track type) see:
-            # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/TrackEvent/include/Event/TrackEnums.h
-            f"TRACK_TYPE{suffix}":
-            mcreconstructed_alg.TrackType,
-            f"TRACK_FLAG{suffix}":
-            mcreconstructed_alg.Flag,
-            f"TRACK_HISTORY{suffix}":
-            mcreconstructed_alg.History,
-            # Common track properties
-            f"TRACK_REFPOINT_X{suffix}":
-            mcreconstructed_alg.ReferencePoint_X,
-            f"TRACK_REFPOINT_Y{suffix}":
-            mcreconstructed_alg.ReferencePoint_Y,
-            f"TRACK_REFPOINT_Z{suffix}":
-            mcreconstructed_alg.ReferencePoint_Z,
-            f"TRACK_QOVERP{suffix}":
-            mcreconstructed_alg.QOVERP,
-            f"TRACK_CHI2{suffix}":
-            mcreconstructed_alg.Chi2,
-            f"TRACK_CHI2DOF{suffix}":
-            mcreconstructed_alg.Chi2DOF,
-            f"TRACK_NDOF{suffix}":
-            mcreconstructed_alg.nDoF,
-            f"TRACK_GHOSTPROB{suffix}":
-            mcreconstructed_alg.GhostProbability,
-            f"TRACK_HAST{suffix}":
-            mcreconstructed_alg.HasT,
-            f"TRACK_HASUT{suffix}":
-            mcreconstructed_alg.HasUT,
-            f"TRACK_HASVELO{suffix}":
-            mcreconstructed_alg.HasVelo,
-            f"TRACK_NHITS{suffix}":
-            mcreconstructed_alg.nHits,
-            f"TRACK_NVPHITS{suffix}":
-            mcreconstructed_alg.nVPHits,
-            f"TRACK_NUTHITS{suffix}":
-            mcreconstructed_alg.nUTHits,
-            f"TRACK_NFTHITS{suffix}":
-            mcreconstructed_alg.nFTHits,
-            # PID properties
-            f"TRACK_PID_MU{suffix}":
-            mcreconstructed_alg.PIDmu,
-            f"TRACK_PID_PI{suffix}":
-            mcreconstructed_alg.PIDpi,
-            f"TRACK_PID_K{suffix}":
-            mcreconstructed_alg.PIDk,
-            f"TRACK_PID_P{suffix}":
-            mcreconstructed_alg.PIDp,
-            f"TRACK_PID_E{suffix}":
-            mcreconstructed_alg.PIDe,
-        })
+        func_dict.update(
+            {
+                # For various track properties (e.g track type) see:
+                # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/TrackEvent/include/Event/TrackEnums.h
+                f"TRACK_TYPE{suffix}": mcreconstructed_alg.TrackType,
+                f"TRACK_FLAG{suffix}": mcreconstructed_alg.Flag,
+                f"TRACK_HISTORY{suffix}": mcreconstructed_alg.History,
+                # Common track properties
+                f"TRACK_REFPOINT_X{suffix}": mcreconstructed_alg.ReferencePoint_X,
+                f"TRACK_REFPOINT_Y{suffix}": mcreconstructed_alg.ReferencePoint_Y,
+                f"TRACK_REFPOINT_Z{suffix}": mcreconstructed_alg.ReferencePoint_Z,
+                f"TRACK_QOVERP{suffix}": mcreconstructed_alg.QOVERP,
+                f"TRACK_CHI2{suffix}": mcreconstructed_alg.Chi2,
+                f"TRACK_CHI2DOF{suffix}": mcreconstructed_alg.Chi2DOF,
+                f"TRACK_NDOF{suffix}": mcreconstructed_alg.nDoF,
+                f"TRACK_GHOSTPROB{suffix}": mcreconstructed_alg.GhostProbability,
+                f"TRACK_HAST{suffix}": mcreconstructed_alg.HasT,
+                f"TRACK_HASUT{suffix}": mcreconstructed_alg.HasUT,
+                f"TRACK_HASVELO{suffix}": mcreconstructed_alg.HasVelo,
+                f"TRACK_NHITS{suffix}": mcreconstructed_alg.nHits,
+                f"TRACK_NVPHITS{suffix}": mcreconstructed_alg.nVPHits,
+                f"TRACK_NUTHITS{suffix}": mcreconstructed_alg.nUTHits,
+                f"TRACK_NFTHITS{suffix}": mcreconstructed_alg.nFTHits,
+                # PID properties
+                f"TRACK_PID_MU{suffix}": mcreconstructed_alg.PIDmu,
+                f"TRACK_PID_PI{suffix}": mcreconstructed_alg.PIDpi,
+                f"TRACK_PID_K{suffix}": mcreconstructed_alg.PIDk,
+                f"TRACK_PID_P{suffix}": mcreconstructed_alg.PIDp,
+                f"TRACK_PID_E{suffix}": mcreconstructed_alg.PIDe,
+            }
+        )
 
     if not mcreconstructed_alg.use_best_mcmatch:
-        func_dict[
-            f"TRACK_MCASSOCWEIGHTS{suffix}"] = mcreconstructed_alg.MCAssoc_Weights
+        func_dict[f"TRACK_MCASSOCWEIGHTS{suffix}"] = mcreconstructed_alg.MCAssoc_Weights
         # Note no suffix needed since we are returning simply a number representing
         # the number of reconstructed tracks associated to an MC particle
         # (in technical terms the size of object "range" from relations table)
@@ -960,11 +912,11 @@ def MCReconstructed(*,
 
 
 def ParticleIsolation(
-        *,
-        iso_rel_table: Algorithm,
-        name: str = "",
-        sumcone_invalid_value=F.NaN,
-        array_indx_name: str = "indx",
+    *,
+    iso_rel_table: Algorithm,
+    name: str = "",
+    sumcone_invalid_value=F.NaN,
+    array_indx_name: str = "indx",
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors on track or neutral isolation, using information from 'iso_rel_table' argument relating containers of reference and extra particle, namely head particles of the cone and particles inside the cone.
@@ -1013,8 +965,7 @@ def ParticleIsolation(
     ASYM = lambda func: F.ASYM(Functor=func, Relations=iso_rel_table.OutputRelations)
 
     # get the set of relations from the relation table stored in the TES location
-    RELS = F.RELATIONS.bind(
-        F.TES(iso_rel_table.OutputRelations), F.FORWARDARGS)
+    RELS = F.RELATIONS.bind(F.TES(iso_rel_table.OutputRelations), F.FORWARDARGS)
     # get ETA and PHI from the reference particle
     REF_ETA = F.ETA @ F.FORWARDARG1
     REF_PHI = F.PHI @ F.FORWARDARG1
@@ -1031,44 +982,35 @@ def ParticleIsolation(
         prefix += f"_{name}"
 
     ParticleIsolationVariables = {
-        f"{prefix}_CMULT":
-        F.VALUE_OR(0)
+        f"{prefix}_CMULT": F.VALUE_OR(0)
         @ F.MAP_INPUT_SIZE(Relations=iso_rel_table.OutputRelations),
-        f"{prefix}_CP":
-        SUMCONE(F.P),
-        f"{prefix}_CPT":
-        SUMCONE(F.PT),
-        f"{prefix}_CPX":
-        SUMCONE(F.PX),
-        f"{prefix}_CPY":
-        SUMCONE(F.PY),
-        f"{prefix}_CPZ":
-        SUMCONE(F.PZ),
-        f"{prefix}_PASY":
-        ASYM(F.P),
-        f"{prefix}_PTASY":
-        ASYM(F.PT),
-        f"{prefix}_PXASY":
-        ASYM(F.PX),
-        f"{prefix}_PYASY":
-        ASYM(F.PY),
-        f"{prefix}_PZASY":
-        ASYM(F.PZ),
-        f"{prefix}_DETA[{array_indx_name}]":
-        F.MAP(DELTA_ETA()).bind(RELS(), F.FORWARDARGS),
-        f"{prefix}_DPHI[{array_indx_name}]":
-        F.MAP(DELTA_PHI()).bind(RELS(), F.FORWARDARGS),
+        f"{prefix}_CP": SUMCONE(F.P),
+        f"{prefix}_CPT": SUMCONE(F.PT),
+        f"{prefix}_CPX": SUMCONE(F.PX),
+        f"{prefix}_CPY": SUMCONE(F.PY),
+        f"{prefix}_CPZ": SUMCONE(F.PZ),
+        f"{prefix}_PASY": ASYM(F.P),
+        f"{prefix}_PTASY": ASYM(F.PT),
+        f"{prefix}_PXASY": ASYM(F.PX),
+        f"{prefix}_PYASY": ASYM(F.PY),
+        f"{prefix}_PZASY": ASYM(F.PZ),
+        f"{prefix}_DETA[{array_indx_name}]": F.MAP(DELTA_ETA()).bind(
+            RELS(), F.FORWARDARGS
+        ),
+        f"{prefix}_DPHI[{array_indx_name}]": F.MAP(DELTA_PHI()).bind(
+            RELS(), F.FORWARDARGS
+        ),
     }
     return FunctorCollection(ParticleIsolationVariables)
 
 
 def ConeIsolation(
-        *,
-        head_cone: DataHandle,
-        charged_cone: DataHandle,
-        neutral_cone: DataHandle,
-        cut: DataHandle,
-        name: str = "",
+    *,
+    head_cone: DataHandle,
+    charged_cone: DataHandle,
+    neutral_cone: DataHandle,
+    cut: DataHandle,
+    name: str = "",
 ) -> FunctorCollection:
     """
     Candidate-level collection of functors on charged and neutral isolation, using information from relations between sets of particles determined by a given criteria. Calculates the relations that 'head_cone' particle selection has with 'charged_cone' particle selection and 'neutral_cone' particle selection, respectively. The cone isolation criteria are determined by the expression in the 'cut'.
@@ -1105,9 +1047,11 @@ def ConeIsolation(
     """
     # Prepare relation tables
     cc_isoAlg = WeightedRelTableAlg(
-        ReferenceParticles=head_cone, InputCandidates=charged_cone, Cut=cut)
+        ReferenceParticles=head_cone, InputCandidates=charged_cone, Cut=cut
+    )
     nc_isoAlg = WeightedRelTableAlg(
-        ReferenceParticles=head_cone, InputCandidates=neutral_cone, Cut=cut)
+        ReferenceParticles=head_cone, InputCandidates=neutral_cone, Cut=cut
+    )
 
     cc_str = "CC"
     nc_str = "NC"
@@ -1119,21 +1063,25 @@ def ConeIsolation(
     nc_prefix = "HEAD_" + nc_str
     # Invoke twice the ParticleIsolation functorcollection, once for neutral and once for charged particles, then add to the functor dictionary
     func_dict = {
-        f"{cc_prefix}_Max_PT":
-        F.MAXCONE(Functor=F.PT, Relations=cc_isoAlg.OutputRelations),
-        f"{cc_prefix}_Min_PT":
-        F.MINCONE(Functor=F.PT, Relations=cc_isoAlg.OutputRelations),
-        f"{nc_prefix}_Max_PT":
-        F.MAXCONE(Functor=F.PT, Relations=nc_isoAlg.OutputRelations),
-        f"{nc_prefix}_Min_PT":
-        F.MINCONE(Functor=F.PT, Relations=nc_isoAlg.OutputRelations),
+        f"{cc_prefix}_Max_PT": F.MAXCONE(
+            Functor=F.PT, Relations=cc_isoAlg.OutputRelations
+        ),
+        f"{cc_prefix}_Min_PT": F.MINCONE(
+            Functor=F.PT, Relations=cc_isoAlg.OutputRelations
+        ),
+        f"{nc_prefix}_Max_PT": F.MAXCONE(
+            Functor=F.PT, Relations=nc_isoAlg.OutputRelations
+        ),
+        f"{nc_prefix}_Min_PT": F.MINCONE(
+            Functor=F.PT, Relations=nc_isoAlg.OutputRelations
+        ),
     }
     func_dict.update(
-        ParticleIsolation(name=f"{cc_str}",
-                          iso_rel_table=cc_isoAlg).functor_dict)
+        ParticleIsolation(name=f"{cc_str}", iso_rel_table=cc_isoAlg).functor_dict
+    )
     func_dict.update(
-        ParticleIsolation(name=f"{nc_str}",
-                          iso_rel_table=nc_isoAlg).functor_dict)
+        ParticleIsolation(name=f"{nc_str}", iso_rel_table=nc_isoAlg).functor_dict
+    )
 
     return FunctorCollection(func_dict)
 
@@ -1162,8 +1110,7 @@ def NeutralCaloInfo() -> FunctorCollection:
         "CaloNeutralEcalEnergy": F.CALO_NEUTRAL_ECAL_ENERGY,
         "CaloNeutral1To9EnergyRatio": F.CALO_NEUTRAL_1TO9_ENERGY_RATIO,
         "CaloNeutral4To9EnergyRatio": F.CALO_NEUTRAL_4TO9_ENERGY_RATIO,
-        "CaloNeutralHcal2EcalEnergyRatio":
-        F.CALO_NEUTRAL_HCAL2ECAL_ENERGY_RATIO,
+        "CaloNeutralHcal2EcalEnergyRatio": F.CALO_NEUTRAL_HCAL2ECAL_ENERGY_RATIO,
         "CaloNeutralID": F.CALO_NEUTRAL_ID,
         "CaloNumSaturatedCells": F.CALO_NUM_SATURATED_CELLS,
     }
@@ -1188,13 +1135,15 @@ def ParticleID(extra_info: bool = False) -> FunctorCollection:
         "PROBNN_PI": F.PROBNN_PI,
     }
     if extra_info:
-        pid_vars.update({
-            "PID_E": F.PID_E,
-            "PID_K": F.PID_K,
-            "PID_MU": F.PID_MU,
-            "PID_P": F.PID_P,
-            "PID_PI": F.PID_PI,
-        })
+        pid_vars.update(
+            {
+                "PID_E": F.PID_E,
+                "PID_K": F.PID_K,
+                "PID_MU": F.PID_MU,
+                "PID_P": F.PID_P,
+                "PID_PI": F.PID_PI,
+            }
+        )
 
     return FunctorCollection(pid_vars)
 
@@ -1216,7 +1165,7 @@ def SMOGInfo() -> FunctorCollection:
                          ...
                          )
     """
-    smog = smogInfoAlg(name='smogInfo').Output
+    smog = smogInfoAlg(name="smogInfo").Output
 
     smog_info = {}
     smog_info["SMOG_InjectionMode"] = F.SMOG_INJECTION_MODE(smog)
-- 
GitLab


From e3e956fdbabf748b3a74a6dd223673028f4eb971 Mon Sep 17 00:00:00 2001
From: Saverio Mariani <samarian@cern.ch>
Date: Fri, 17 Nov 2023 09:35:50 +0100
Subject: [PATCH 3/3] Apply comments by Abhijit

---
 .../python/FunTuple/functorcollections.py     | 25 ++++++++++---------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/Phys/FunTuple/python/FunTuple/functorcollections.py b/Phys/FunTuple/python/FunTuple/functorcollections.py
index 87ab1629d..c17ee4478 100644
--- a/Phys/FunTuple/python/FunTuple/functorcollections.py
+++ b/Phys/FunTuple/python/FunTuple/functorcollections.py
@@ -28,7 +28,7 @@ from PyConf.Algorithms import Hlt1TisTosAlg, Hlt2TisTosAlg, Hlt1TrueSimEffAlg, H
 import DaVinciMCTools  # type: ignore[import]
 from DecayTreeFitter import DecayTreeFitter  # type: ignore[import]
 from .FunctorCollection import FunctorCollection
-from PyConf.Algorithms import smogInfoAlg  # type: ignore[import]
+from PyConf.Algorithms import SMOGInfoAlg  # type: ignore[import]
 
 __all__ = (
     "EventInfo",
@@ -1151,6 +1151,7 @@ def ParticleID(extra_info: bool = False) -> FunctorCollection:
 def SMOGInfo() -> FunctorCollection:
     """
     Collection of SMOG conditions (injection mode, injected gas, stable injection flag)
+    See map of possible values at LHCb/Det/LHCbDet/include/LHCbDet/SMOGInfo.h
 
     Example:
         import FunTuple.functorcollections as FC
@@ -1159,17 +1160,17 @@ def SMOGInfo() -> FunctorCollection:
         variables = FC.SMOGInfo()
         # ...
 
-        tuple = Funtuple(name="MyTuple",
-                         fields=...,
-                         variables=variables,
-                         ...
-                         )
+        tuple = FuntupleEvent(name="MyTuple",
+                              fields=...,
+                              variables=variables,
+                              ...
+                             )
     """
-    smog = smogInfoAlg(name="smogInfo").Output
+    SMOG = SMOGInfoAlg(name="SMOGInfo").Output
 
-    smog_info = {}
-    smog_info["SMOG_InjectionMode"] = F.SMOG_INJECTION_MODE(smog)
-    smog_info["SMOG_InjectedGas"] = F.SMOG_INJECTED_GAS(smog)
-    smog_info["SMOG_StableInjection"] = F.SMOG_STABLE_INJECTION(smog)
+    SMOG_info = {}
+    SMOG_info["SMOG_InjectionMode"] = F.SMOG_INJECTION_MODE(SMOG)
+    SMOG_info["SMOG_InjectedGas"] = F.SMOG_INJECTED_GAS(SMOG)
+    SMOG_info["SMOG_StableInjection"] = F.SMOG_STABLE_INJECTION(SMOG)
 
-    return FunctorCollection(smog_info)
+    return FunctorCollection(SMOG_info)
-- 
GitLab