From d498d162c2aa5992fff7279389c605aa2c4a0873 Mon Sep 17 00:00:00 2001
From: Davide Fazzini <davide.fazzini@cern.ch>
Date: Fri, 21 Oct 2022 21:57:41 +0200
Subject: [PATCH] Update tagging array qmtest including mctruth infos

---
 .../option_davinci_tupling_array_taggers.py   | 144 +++++++++++++++---
 .../test_davinci_tupling_array_taggers.qmt    |   3 +-
 .../test_davinci_tupling_array_taggers.ref    |  87 +++++++----
 3 files changed, 187 insertions(+), 47 deletions(-)

diff --git a/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py b/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py
index 272b7726c..c493dbcfa 100644
--- a/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py
+++ b/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_array_taggers.py
@@ -10,68 +10,175 @@
 ###############################################################################
 """
 Option file for testing the ParticleTaggerAlg algorithm and the related ThOr
-functors MAP_INPUT_ARRAY. The job runs over a spruced sample and retrieves a
+functors MAP_INPUT_ARRAY. 
+
+The aim of this example, is to retrieve and store in the final ntuple some
+variables related to the additional tracks generated in the event that are not
+included in the decay chain. This kind of task has been developed for flavour 
+tagging pourposes but can be extended also to other area.
+
+In particular, the job runs over a spruced sample and retrieves a
 set of B0 -> Ds K+ candidates. For each candidate the ParticleTaggerAlg
 looks at the TES location defined via the 'make_long_pions'
-function and creates a 'one-to-many' relation map relating all the available
+function and creates a 'one-to-many' relation map linking all the available
 tracks to the B candidate of the events.
 
 Then the MAP_INPUT_ARRAY functor takes in input this relation map and for each
 entry stores the output of an external functor (i.e F.P, F.PT) in a vector.
+
+In addition, MC truth information for each track in the 'make_long-pions' 
+location is retrieved and stored in the final tuples via the 'configured_MCTruthAndBkgCatAlg' function.
+
+N.B. the job runs over a spruced sample, but the same flow can be used also for
+turbo .dst.
 """
 
-import Functors as F
-from PyConf.Algorithms import ParticleTaggerAlg, ParticleContainerMerger
-from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple
 from PyConf.reading import get_particles
+from PyConf.Algorithms import ParticleTaggerAlg, ParticleContainerMerger
+
+import Functors as F
+from FunTuple import FunctorCollection as FC, FunTuple_Particles as Funtuple
 
 from DaVinci import Options, make_config
 from DaVinci.algorithms import add_filter
 from DaVinci.common_particles import make_long_pions
+from DaVinci.truth_matching import configured_MCTruthAndBkgCatAlg
 
 
 def main(options: Options):
-    bd2dsk_line = "SpruceB2OC_BdToDsmK_DsmToHHH_FEST_Line"
+    # Define the fields of the decay chain of interest
+    fields = {
+        'B0': "[B0 -> D_s- K+]CC",
+        'Ds': "[B0 -> ^D_s- K+]CC",
+        'Kp': "[B0 -> D_s- ^K+]CC",
+    }
+
+    # Retrieve particles surviving a specific spruced line
+    bd2dsk_line = "Spruce_Test_line"
     bd2dsk_data = get_particles(f"/Event/Spruce/{bd2dsk_line}/Particles")
 
+    # Create a new pion container via the 'make_long_pions()' function
+    # implemented in DaVinci.common_particles modulo.
     pions = make_long_pions()
 
+    # Since the provenance of the tracks is not important in this kind of task,
+    # the 'ParticleTaggerAlg' runs over a unique 'ParticleContainerMerger'
+    # object, merging together all the track containers defined by the user.
     tagging_container = ParticleContainerMerger(
         InputContainers=[pions]).OutputContainer
 
+    # Define ParticleTagger algorithm and create a relation table between the
+    # decay mother particle, i.e. B0 meson and all the tracks defined in the
+    # 'tagging_contaienr'.
     tagAlg = ParticleTaggerAlg(
         Input=bd2dsk_data, TaggingContainer=tagging_container, OutputLevel=3)
+    # Retrieve the relation map linking all the underlying tracks availanle in the 'tagging_container'
+    # to the B meson. This map will be used in the next steps for the functor evaluation.
     tagAlg_rels = tagAlg.OutputRelations
 
+    # If the user needs to store the MC truth information related to the tracks
+    # available in the event, the same fucntions used for the decay chain
+    # particles can be followed.
+    # For a comparison define both a relation map to the corresponding MC particles
+    # for the decay chain ('mctruth') and for the other tracks in the event ('mctruth_pions').
+    mctruth = configured_MCTruthAndBkgCatAlg(inputs=bd2dsk_data)
+    mctruth_pions = configured_MCTruthAndBkgCatAlg(inputs=tagging_container)
+
+    # Helper 'lambda functions' can be used to evaluate a specific functor (func) over all the particles
+    # linked in a relation table, defined by the 'Relations' keyword.
+    # In this case we create a lambda function that apply a functor, given as input by the user,
+    # to all the MC particles found by the 'configured_MCTruthAndBkgCatAlg' instances
+    # defined before: both for the signal decay chain and for the underlying tracks.
+    # In particular the 'MCAssocTable' method can be used to obtain the correct relation map from the
+    # 'mctruth' and 'mctruth_pions' objects defined before.
+    MCTRUTH = lambda func: F.MAP_INPUT(Functor=func, Relations=mctruth.MCAssocTable)
+    MCTRUTH_pions = lambda func: F.MAP_INPUT(Functor=func, Relations=mctruth_pions.MCAssocTable)
+
     #make collection of functors
-    variables_B = FunctorCollection({
+    # Define all the variables to be associated to the B field
+    #
+    #N.B: a default value has to be defined for functors returning an int/bool value (or an array of int/bool values)
+    #in case the output is empty: e.g. "TRUEID" or "TagTr_TRUEKEY[nTags]".
+    variables_B = FC({
         'THOR_MASS':
         F.MASS,
+        'PT':
+        F.PT,
+        # Retrieve the true ID for the B meson usign the 'MCTRUTH' lambda fucntion definded above
+        "TRUEID":
+        F.VALUE_OR(0) @ MCTRUTH(F.PARTICLE_ID),
+        # Define variables for the tagging particles associated to the B meson.
+        # The 'MAP_INPUT_ARRAY' functor can be used to evaluate the functor of interest to all the tracks
+        # linked the 'tagAlg_rels' relation table generated via the 'ParticleTaggeerAlg' algorithm.
         "TagTr_P":
         F.MAP_INPUT_ARRAY(Functor=F.P, Relations=tagAlg_rels),
         # Currently this stores a branch called "indx" which corresponds to nPVs.
         # You can give a custom name for this via following
         "TagTr_PT[nTags]":
         F.MAP_INPUT_ARRAY(Functor=F.PT, Relations=tagAlg_rels),
+        "TagTr_PHI[nTags]":
+        F.MAP_INPUT_ARRAY(Functor=F.PHI, Relations=tagAlg_rels),
+        # Define variables containing the MC truth information for the underlying tracks.
+        # The 'MAP_INPUT_ARRAY' functor can be used as in the previous example, but in this case
+        # the 'MCTRUTH_pions' lambda funtion has to be exploited for applying the functor of interest
+        # to MC particles associated to the underlying tracks.
+        #
+        # N.B.: an additional default value has to be added in the definition of MAP_INPUT_ARRAY
+        # in case of internal functors built via lambda functions in order to ensure that a valid
+        # output is always defined, e.g. MCTRUTH_pions.
+        "TagTr_TRUEID[nTags]":
+        F.VALUE_OR([0]) @ F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(0) @ MCTRUTH_pions(F.PARTICLE_ID),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEKEY[nTags]":
+        F.VALUE_OR([-1]) @ F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(-1) @ MCTRUTH_pions(F.OBJECT_KEY),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEP[nTags]":
+        F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(F.NaN) @ MCTRUTH_pions(F.P),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEPT[nTags]":
+        F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(F.NaN) @ MCTRUTH_pions(F.PT),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEPX[nTags]":
+        F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(F.NaN) @ MCTRUTH_pions(F.PX),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEPY[nTags]":
+        F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(F.NaN) @ MCTRUTH_pions(F.PY),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEPZ[nTags]":
+        F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(F.NaN) @ MCTRUTH_pions(F.PZ),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEENERGY[nTags]":
+        F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(F.NaN) @ MCTRUTH_pions(F.ENERGY),
+            Relations=tagAlg_rels),
+        "TagTr_TRUEPHI[nTags]":
+        F.MAP_INPUT_ARRAY(
+            Functor=F.VALUE_OR(F.NaN) @ MCTRUTH_pions(F.PHI),
+            Relations=tagAlg_rels),
     })
 
-    #make collection of functors for Muplus
-    variables_all = FunctorCollection({
+    # Make collection of functors for all the signal decay chain particles
+    variables_all = FC({
         'THOR_P': F.P,
         'THOR_PT': F.PT,
     })
 
-    fields = {
-        'B0': "[B0 -> D_s- K+]CC",
-        'Ds': "[B0 -> ^D_s- K+]CC",
-        'Kp': "[B0 -> D_s- ^K+]CC",
-    }
-
+    # Define a dict with all the variables to be stored associated to the corresponding field.
     variables = {
         'ALL': variables_all,  #adds variables to all fields
         'B0': variables_B,
     }
 
+    # Define the FunTuple object that will produce the final .root files, passing the directory and name
+    # of the output tree, the list of fields and the dict of variables to be stored, and the input data
+    # location containing the signal decay chain particles.
     tuple_B0DsK = Funtuple(
         name="B0DsK_Tuple",
         tuple_name="DecayTree",
@@ -79,8 +186,11 @@ def main(options: Options):
         variables=variables,
         inputs=bd2dsk_data)
 
+    # Define a filter in order to process only the event with at least on candidates of interest.
+    # This is a very important step aimed to reduce both the computation time required by the job and
+    # to prevent any failure due to empty TES location.
     filter_B0DsK = add_filter(options, "HDRFilter_B0DsK",
                               f"HLT_PASS('{bd2dsk_line}')")
 
-    algs = [filter_B0DsK, tuple_B0DsK]
-    return make_config(options, algs)
+    # Configure DaVinci passing the options and a list of the user-defined algortithms to be run.
+    return make_config(options, [filter_B0DsK, tuple_B0DsK])
diff --git a/DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt b/DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt
index 35238856a..9d4afa92e 100644
--- a/DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt
+++ b/DaVinciExamples/tests/qmtest/tupling.qms/test_davinci_tupling_array_taggers.qmt
@@ -17,9 +17,8 @@
   <argument name="args"><set>
     <text>DaVinciExamples.tupling.option_davinci_tupling_array_taggers:main</text>
   </set></argument>
-  <argument name="options_yaml_fn"><text>$DAVINCIEXAMPLESROOT/example_data/Spruce_all_lines_dst.yaml</text></argument>
+  <argument name="options_yaml_fn"><text>$DAVINCIEXAMPLESROOT/example_data/test_spruce_MCtools.yaml</text></argument>
   <argument name="extra_options_yaml"><text>
-    process: Spruce
     histo_file: DV-example-tagger-his.root
     ntuple_file: DV-example-tagger-ntp.root
   </text></argument>
diff --git a/DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref b/DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref
index f2e08b620..73402b708 100644
--- a/DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref
+++ b/DaVinciExamples/tests/refs/test_davinci_tupling_array_taggers.ref
@@ -6,7 +6,13 @@ NTupleSvc                              INFO Added stream file:DV-example-tagger-
 RootHistSvc                            INFO Writing ROOT histograms to: DV-example-tagger-his.root
 HistogramPersistencySvc                INFO Added successfully Conversion service:RootHistSvc
 FSROutputStreamDstWriter               INFO Data source: EventDataSvc output: SVC='Gaudi::RootCnvSvc'
+MCTruthAndBkgCatAlg#1.DaVinciSma...    INFO Will look into [/Event/Spruce/HLT2/Relations/ChargedPP2MCP, /Event/Spruce/HLT2/Relations/NeutralPP2MCP]
+MCTruthAndBkgCatAlg#1.DaVinciSma...    INFO Will look into [/Event/Spruce/HLT2/Relations/ChargedPP2MCP, /Event/Spruce/HLT2/Relations/NeutralPP2MCP]
+MCTruthAndBkgCatAlg#1.Background...    INFO Will look into [/Event/Spruce/HLT2/Relations/ChargedPP2MCP, /Event/Spruce/HLT2/Relations/NeutralPP2MCP]
 FunctionalParticleMaker.LoKi::Hy...    INFO CUT: ' ( (TrTYPE==3) &TrALL) '
+MCTruthAndBkgCatAlg#2.DaVinciSma...    INFO Will look into [/Event/Spruce/HLT2/Relations/ChargedPP2MCP, /Event/Spruce/HLT2/Relations/NeutralPP2MCP]
+MCTruthAndBkgCatAlg#2.DaVinciSma...    INFO Will look into [/Event/Spruce/HLT2/Relations/ChargedPP2MCP, /Event/Spruce/HLT2/Relations/NeutralPP2MCP]
+MCTruthAndBkgCatAlg#2.Background...    INFO Will look into [/Event/Spruce/HLT2/Relations/ChargedPP2MCP, /Event/Spruce/HLT2/Relations/NeutralPP2MCP]
 ApplicationMgr                         INFO Application Manager Initialized successfully
 ApplicationMgr                         INFO Application Manager Started successfully
 EventPersistencySvc                    INFO Added successfully Conversion service:RootCnvSvc
@@ -20,15 +26,16 @@ FSROutputStreamDstWriter               INFO Set up File Summary Record
 FSROutputStreamDstWriter               INFO Events output: 1
 B0DsK_Tuple                         SUCCESS Booked 1 N-Tuples and 0 Event Tag Collections
 B0DsK_Tuple                         SUCCESS List of booked N-Tuples in directory "FILE1/B0DsK_Tuple"
-B0DsK_Tuple                         SUCCESS  ID=DecayTree     Title="DecayTree"                               #items=11 {B0_THOR_MASS,indx,B0_TagTr_P[1]/V,nTags,B0_TagTr_PT[1]/V,B0_THOR_P,B0_THOR_PT,Ds_}
-LAZY_AND: DaVinci                         #=118     Sum=75          Eff=|( 63.55932 +- 4.43039 )%|
- NONLAZY_OR: FileSummaryRecords           #=118     Sum=118         Eff=|( 100.0000 +- 0.00000 )%|
-  LAZY_AND: GenFSR                        #=118     Sum=118         Eff=|( 100.0000 +- 0.00000 )%|
-   RecordStream/FSROutputStreamDstWriter  #=118     Sum=118         Eff=|( 100.0000 +- 0.00000 )%|
- NONLAZY_OR: UserAnalysis                 #=118     Sum=75          Eff=|( 63.55932 +- 4.43039 )%|
-  LAZY_AND: default                       #=118     Sum=75          Eff=|( 63.55932 +- 4.43039 )%|
-   LoKi__HDRFilter/HDRFilter_B0DsK        #=118     Sum=75          Eff=|( 63.55932 +- 4.43039 )%|
-   FunTupleBase_Particles/B0DsK_Tuple     #=75      Sum=75          Eff=|( 100.0000 +- 0.00000 )%|
+B0DsK_Tuple                         SUCCESS  ID=DecayTree     Title="DecayTree"                               #items=23 {B0_THOR_MASS,B0_PT,B0_TRUEID,indx,B0_TagTr_P[1]/V,nTags,B0_TagTr_PT[1]/V,B0_TagTr}
+LAZY_AND: DaVinci                               #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+ NONLAZY_OR: FileSummaryRecords                 #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+  LAZY_AND: GenFSR                              #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+   RecordStream/FSROutputStreamDstWriter        #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+ NONLAZY_OR: UserAnalysis                       #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+  LAZY_AND: default                             #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+   LHCb__UnpackRawEvent/LHCb__UnpackRawEvent#1  #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+   LoKi__HDRFilter/HDRFilter_B0DsK              #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
+   FunTupleBase_Particles/B0DsK_Tuple           #=14      Sum=14          Eff=|( 100.0000 +- 0.00000 )%|
 RFileCnv                               INFO dumping contents of /NTUPLES/FILE1
 TFile: name=DV-example-tagger-ntp.root, title=Gaudi Trees, option=CREATE
 NTupleSvc                              INFO NTuples saved successfully
@@ -36,35 +43,59 @@ ApplicationMgr                         INFO Application Manager Finalized succes
 ApplicationMgr                         INFO Application Manager Terminated successfully
 B0DsK_Tuple                            INFO Number of counters : 7
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "# events with multiple candidates for field B0"|        65 |
- | "# events with multiple candidates for field Ds"|        65 |
- | "# events with multiple candidates for field Kp"|        65 |
- | "# non-empty events for field B0"               |        75 |
- | "# non-empty events for field Ds"               |        75 |
- | "# non-empty events for field Kp"               |        75 |
- | "# processed events"                            |        75 |
+ | "# events with multiple candidates for field B0"|         2 |
+ | "# events with multiple candidates for field Ds"|         2 |
+ | "# events with multiple candidates for field Kp"|         2 |
+ | "# non-empty events for field B0"               |        14 |
+ | "# non-empty events for field Ds"               |        14 |
+ | "# non-empty events for field Kp"               |        14 |
+ | "# processed events"                            |        14 |
 FunctionalParticleMaker                INFO Number of counters : 4
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"# passed ProtoParticle filter"                 |      2117 |       2117 |( 100.0000 +-  0.000000)% |
- |*"# passed Track filter"                         |      2117 |       2117 |( 100.0000 +-  0.000000)% |
- | "Nb created anti-particles"                     |        75 |       1074 |     14.320 |     28.046 |      2.0000 |      148.00 |
- | "Nb created particles"                          |        75 |       1043 |     13.907 |     27.832 |      2.0000 |      144.00 |
+ |*"# passed ProtoParticle filter"                 |        57 |         57 |( 100.0000 +-  0.000000)% |
+ |*"# passed Track filter"                         |        57 |         57 |( 100.0000 +-  0.000000)% |
+ | "Nb created anti-particles"                     |        14 |         28 |     2.0000 |      0.0000 |      2.0000 |      2.0000 |
+ | "Nb created particles"                          |        14 |         29 |     2.0714 |    0.25754 |      2.0000 |      3.0000 |
 HDRFilter_B0DsK                        INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"#passed"                                       |       118 |         75 |( 63.55932 +- 4.430389)% |
+ |*"#passed"                                       |        14 |         14 |( 100.0000 +-  0.000000)% |
+HltPackedBufferDecoder                 INFO Number of counters : 1
+ |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
+ | " DstData raw bank  has a zero encoding key, and it is not explicitly specified for decoding -- make sure that this really what you want"|        14 |
+MCTruthAndBkgCatAlg#1                  INFO Number of counters : 3
+ |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
+ | "Events"                                        |        14 |
+ | "Ghosts"                                        |         1 |          0 |      0.0000 |      0.0000 |  4.2950e+09 |       0.0000 |
+ | "Particles"                                     |        96 |          0 |      0.0000 |      0.0000 |  4.2950e+09 |       0.0000 |
+MCTruthAndBkgCatAlg#2                  INFO Number of counters : 2
+ |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
+ | "Events"                                        |        14 |
+ | "Particles"                                     |        57 |          0 |      0.0000 |      0.0000 |  4.2950e+09 |       0.0000 |
+PP2MCPRelationUnpacker                 INFO Number of counters : 1
+ |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
+ | "# PackedData"                                  |        14 |         84 |     6.0000 |
+PP2MCPRelationUnpacker#1               INFO Number of counters : 1
+ |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
+ | "# AbsentBuffer"                                |        14 |          0 |      0.0000 |
 ParticleContainerMerger                INFO Number of counters : 2
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "# input particles"                             |        75 |       2117 |     28.227 |
- | "# output particles"                            |      2117 |          0 |      0.0000 |
+ | "# input particles"                             |        14 |         57 |     4.0714 |
+ | "# output particles"                            |        57 |          0 |      0.0000 |
 ParticleTaggerAlg                      INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "Events"                                        |        75 |
- | "Input Particles"                               |        75 |        459 |     6.1200 |     7.6680 |      1.0000 |      50.000 |
- | "Output Particles"                              |        75 |       2117 |     28.227 |     55.806 |      4.0000 |      292.00 |
+ | "Events"                                        |        14 |
+ | "Input Particles"                               |        14 |         16 |     1.1429 |    0.34993 |      1.0000 |      2.0000 |
+ | "Output Particles"                              |        14 |         57 |     4.0714 |    0.25754 |      4.0000 |      5.0000 |
 ParticleUnpacker                       INFO Number of counters : 2
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "# Linked BufferData"                           |       826 |    4290998 |     5194.9 |
- | "# UnpackedData"                                |       150 |      91119 |     607.46 |
+ | "# Linked BufferData"                           |       161 |     117195 |     727.92 |
+ | "# UnpackedData"                                |        28 |       3700 |     132.14 |
+ProtoParticleUnpacker#1                INFO Number of counters : 1
+ |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
+ | "# AbsentBuffer"                                |        14 |          0 |      0.0000 |
+Spruce                                 INFO Number of counters : 1
+ |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
+ | " HltDecReports has a zero TCK, and it is not explicitly specified for decoding -- make sure that this really what you want"|        14 |
 ToolSvc.HltFactory                     INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
 ToolSvc.PPFactoryHybridFactory         INFO Number of counters : 1
-- 
GitLab