From 08e736a6d359f01a799f08e475da78ea47f2bd74 Mon Sep 17 00:00:00 2001
From: Teng Jian Khoo <teng.jian.khoo@cern.ch>
Date: Tue, 15 Apr 2025 17:33:48 +0200
Subject: [PATCH 1/4] Minor edits

---
 docs/athena/trigger/algos.md      |  4 ++--
 docs/athena/trigger/combohypos.md | 10 +++++-----
 docs/athena/trigger/eventviews.md |  2 +-
 docs/athena/trigger/idc.md        |  2 +-
 docs/athena/trigger/menu.md       |  2 +-
 docs/athena/trigger/navigation.md |  2 +-
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/docs/athena/trigger/algos.md b/docs/athena/trigger/algos.md
index aa516b9..5099bd5 100644
--- a/docs/athena/trigger/algos.md
+++ b/docs/athena/trigger/algos.md
@@ -6,13 +6,13 @@ in the precision reconstruction step, whereas trigger specific ones are used in
 initial fast reconstruction step. An important difference in the trigger use-case is that the
 reconstruction algorithms are executed only if needed. This is done by embedding them between
 filter algorithms (control flow) that ensure that algorithms are only executed if the preceding
-steps passed. Other difference is that the algorithm instances may be executed multiple times per event in EventViews (briefly mentioned later).
+steps passed. Another difference is that the algorithm instances may be executed multiple times per event in EventViews (briefly mentioned later).
 
 
 ## Features of reconstruction algorithms
 1. It is required that the algorithms used by HLT are reentrant, that is inherited from `AthReentrantAlgorithm`.
   In practice this means that the `execute` method does not modify any state variable of the algorithm itself.
-1. The I/O of data items needed by the algorithm is done identically as in offline case and is documented here 
+1. The I/O of data items needed by the algorithm is done identically as in the offline case and is documented here
    [MultiThreadingEventDataAccess](https://twiki.cern.ch/twiki/bin/view/AtlasComputing/MultiThreadingEventDataAccessV2).
 1. Access to conditions data needs to be migrated following 
    [MultiThreadingConditionsAccess](https://twiki.cern.ch/twiki/bin/view/AtlasComputing/MultiThreadingConditionsAccess)
diff --git a/docs/athena/trigger/combohypos.md b/docs/athena/trigger/combohypos.md
index e8d2fc5..1d4f380 100644
--- a/docs/athena/trigger/combohypos.md
+++ b/docs/athena/trigger/combohypos.md
@@ -9,14 +9,14 @@ The evaluation of the `ComboHypo` results in rejection of the chain at a given s
 Outside of the `ComboHypo`, a chain's individual legs are running entirely independently of each other.
 
 ## Configuration
-This is a framework algorithm, and is not configured directly by trigger signature developer. There are however two cases when it may be necessary to alter its default behaviour. These will both be covered in more detail below.
+This is a framework algorithm, and should not be configured directly by a trigger signature developer. There are however two cases when it may be necessary to alter its default behaviour. These will both be covered in more detail below.
 
 1. *Request to disable multiplicity checks*. In some cases it is not appropriate for the `ComboHypo` algorithm to apply its regular requirement of 
 satisfying each chain-leg's specified multiplicity requirement with unique physics objects. There are a number of ways to communicate this as 
 detailed below - this is always done by encoding special properties into the navigation graph which the downstream `ComboHypo` is able to pick up.
 2. *Request to perform special combinatorial logic*. When the regular `HypoAlg` was discussed, we saw that it was required to host one `HypoTool` 
 per configured HLT chain-leg. The `ComboHypo` algorithm can also host one `ComboHypoTool` per chain to customise the multi-leg decision. (note: unlike for `HypoAlg` the tool here is required per chain rather than per chain leg). The configuration of `ComboHypoTool` is optional and there is a generic `ComboHypoTool`  which can perform common 
-kinematic selections between objects pertaining to chain legs (ΔR, ΔM, etc.). This common implementation can be configured from set of keywords encoded in the chain's name. All implementations of `ComboHypoTool` need to implement `IComboHypoTool` interface. 
+kinematic selections between objects pertaining to chain legs (ΔR, ΔM, etc.). This common implementation can be configured from set of keywords encoded in the chain's name. All implementations of `ComboHypoTool` need to implement the `IComboHypoTool` interface.
 
 ## Inner workings of a ComboHypo algorithm
 The logic of the `ComboHypo` is one of the most complicated aspects of the HLT, so let's work through its functionality piece by piece to understand what's going on.
@@ -87,7 +87,7 @@ This stage goes from a set of `Decision` objects associated to each leg to a set
 We're going to use these hash values to enforce the multiplicity check. Thus by modifying them we can also program that the multiplicity check is skipped. This is done under the following situations:
 
  * If there was no `feature` and we fell back on the `initialRoI`, and the `initialRoI` is the special `FSNOSEED` full-scan ROI.
- * If the `feature` is itself and RoI, and that RoI is flagged as full-scan.
+ * If the `feature` is itself and an RoI, and that RoI is flagged as full-scan.
  * If the `HypoAlg` signalled to the `ComboHypo` algorithm that it should not act on this decision object. This is achieved by decorating  `Decision` objects with `<int32_t>("noCombo") == 1`.
 
 If any of these three conditions are satisfied, then instead of adding our single hash value we instead add 
@@ -133,7 +133,7 @@ leg.
 The unique-hash enforcement identifies all hash values which are duplicated in more than one leg, and it also computes how close each leg is to failing its 
 multiplicity requirement. For example, if there were currently three hashes on the `e15` leg - then this leg is able to loose up to two hashes and still satisfy 
 its multiplicity requirement of 1. 
-If there were at the same time five hashes on the `e10` leg - then this leg is able to loose up to three hashes and still 
+If there were at the same time five hashes on the `e10` leg - then this leg is able to lose up to three hashes and still 
 satisfy its multiplicity requirement of 2.
 In this case, a hash which was common to the `e15` and `e10` legs would be excluded from the `e10` leg - as 
 this was the leg with the largest margin. In case of a tie, the hash gets removed from the earlier leg.
@@ -180,7 +180,7 @@ The `ComboHypoToolBase` has two configurable parameters.
  which physics objects get propagated to later steps of the trigger!
 
 You are required to implement the
-```
+```cpp
 virtual bool executeAlg(const std::vector<Combo::LegDecision>& combination) const;
 ```
 method, here `Combo::LegDecision` is a `std::pair` where the first element of the pair is the `DecisionID` of a chain-leg and the second element of the pair is 
diff --git a/docs/athena/trigger/eventviews.md b/docs/athena/trigger/eventviews.md
index dfa06a9..4479918 100644
--- a/docs/athena/trigger/eventviews.md
+++ b/docs/athena/trigger/eventviews.md
@@ -81,7 +81,7 @@ In the case of HypoAlg the view objects can be obtained from each of the input d
 ```c++
 auto viewELInfo = TrigCompositeUtils::findLink< ViewContainer >( previousDecision, "view" );
 ```
-Each `ReadHandleKey` that is supposed to point to the input data has to be hidden from scheduler (renounced), because the scheduler will not allow data dependencies across a view boundary.
+Each `ReadHandleKey` that is supposed to point to the input data has to be hidden from the scheduler (renounced), because the scheduler will not allow data dependencies across a view boundary.
 ```c++
 // in header, an usual handle declaration
 SG::ReadHandleKey< InputContainerType > m_inputKey {this, "MyInputContainer", "DefaultName", "Input"};
diff --git a/docs/athena/trigger/idc.md b/docs/athena/trigger/idc.md
index 9b1ac42..7d96d14 100644
--- a/docs/athena/trigger/idc.md
+++ b/docs/athena/trigger/idc.md
@@ -123,7 +123,7 @@ for(auto iterator = container->indexFind(hash); iterator != container->end(); ++
 ## Creating a Cache
 
 Cache creation must occur in an algorithm run outside of the views and before the views are executed.
-The algorithm need to simply create a the cache object and give it to storegate by a non-const method (caches are then accessed within views by update handles).
+The algorithm simply needs to create a cache object and give it to StoreGate by a non-const method (caches are then accessed within views by update handles).
 This algorithm must then be scheduled to run outside the view appropriately.
 
 ```cpp
diff --git a/docs/athena/trigger/menu.md b/docs/athena/trigger/menu.md
index 021f069..1ac0c11 100644
--- a/docs/athena/trigger/menu.md
+++ b/docs/athena/trigger/menu.md
@@ -109,7 +109,7 @@ are read into a big list.
    [`SignatureDicts.py`]({{data.athena_git_url}}/blob/{{data.branchMainShort}}/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Menu/SignatureDicts.py).
 * The chain dictionaries are then prepared to be passed to the corresponding signature code to generate the chain step configuration. This means in particular:
       * Combined chains: The dictionary is divided according to the signatures of the combined chain and sent to the corresponding signature code. The returned configuration will then be combined given the merging strategy specified in the chain definition.
-      * Chains of one signature type with more than one leg (e.g. HLT_mu6_mu8): The dictionary with both chain parts is passed to the corresponding signature code, similarly to the case of a chain with multiplicity great than 1 (e.g. HLT_2mu6). The multiplicities are then handled according to the specific setups within a given signature.
+      * Chains of one signature type with more than one leg (e.g. `HLT_mu6_mu8`): The dictionary with both chain parts is passed to the corresponding signature code, similarly to the case of a chain with multiplicity great than 1 (e.g. `HLT_2mu6`). The multiplicities are then handled according to the specific setups within a given signature.
 * The dictionaries are sent to the corresponding signature code. The handling of the step setup is individual to a signature and won't be discussed here. The signature code sends back a `Chain` object which is defined in
 [`MenuComponents.py`]({{data.athena_git_url}}/blob/{{data.branchMainShort}}/Trigger/TriggerCommon/TriggerMenuMT/python/HLT/Config/MenuComponents.py) to contain the HLT chain name, the L1 item seeding the chain and a list of chain steps.
 * The configuration of all chain objects is then added to a list and passed to the control flow via the `makeHLTTree` function.
diff --git a/docs/athena/trigger/navigation.md b/docs/athena/trigger/navigation.md
index e61c656..c961f46 100644
--- a/docs/athena/trigger/navigation.md
+++ b/docs/athena/trigger/navigation.md
@@ -61,7 +61,7 @@ An additional node (not illustrated above) is created to track chains which do n
 
 The nodes are written into a number of containers, one per type of threshold. E.g, `HLT_MURoIs`, `HLT_eEMRoIs`, `HLT_eTAURoIs`, `HLT_jTAURoIs`, etc. with `HLT_FSRoI` holding the single FullScan node.
 
-Trigger chains are activated based on L1 seed and HLT prescale requirements. Activated chains have L1 threshold requirement for each of their legs, this may be e.g. something like `eEM26M` (L1 26 GeV e/gamma with medium ID) or `FSNOSEED` which maps to the node with the FullScan RoI. The HLT seeding is aware of which L1 threshold are satisfied by each initial node, and will add the Leg-ID of each activated chain-leg to each node which satisfied the leg's L1 threshold requirement.
+Trigger chains are activated based on L1 seed and HLT prescale requirements. Activated chains have L1 threshold requirement for each of their legs, this may be e.g. something like `eEM26M` (L1 26 GeV e/gamma with medium ID) or `FSNOSEED` which maps to the node with the FullScan RoI. The HLT seeding is aware of which L1 thresholds are satisfied by each initial node, and will add the Leg-ID of each activated chain-leg to each node which satisfied the leg's L1 threshold requirement.
 
 ### Filtering
 
-- 
GitLab


From c2b8779c1267db9b310459cf25f64d2a8b7177f0 Mon Sep 17 00:00:00 2001
From: Teng Jian Khoo <teng.jian.khoo@cern.ch>
Date: Tue, 15 Apr 2025 17:35:14 +0200
Subject: [PATCH 2/4] Clarify details on ComboHypos

---
 docs/athena/trigger/combohypos.md | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/docs/athena/trigger/combohypos.md b/docs/athena/trigger/combohypos.md
index 1d4f380..5a0f578 100644
--- a/docs/athena/trigger/combohypos.md
+++ b/docs/athena/trigger/combohypos.md
@@ -101,8 +101,12 @@ after an RoI-based muon has been identified) can progress up to the point where
 even though there is only one unique `feature` (the `initialRoI` known as `FSNOSEED`).
 
 It additionally enables preselections such as in the hadronic sector. Pre-selection jets are not tracked in the navigation individually 
-like the subsequently reconstructed jets are. Hence the `HypoAlg` needs to be able to disable the multiplicity checks when it only supplies 
+like the subsequently reconstructed jets are; this prevents generating spurious dependencies between preselection and final selection jets when
+all step decisions independently consider the full jet container.
+Hence the `HypoAlg` needs to be able to disable the multiplicity checks when it only supplies
 a single dummy `Decision` object which represents just the final decision of the preselection.
+As a further subtlety, the jet hypo evaluates the full decision for all legs simultaneously and
+does not defer this to the `ComboHypo` either.
 
 #### 2. Up-cast physics objects
 We now have a set of hash values on each leg. Some might correspond to physics objects, others to ROI.
@@ -161,11 +165,13 @@ It performs generic two-body kinematic cuts over parings of physics objects from
 Supported cuts are angular `dR`, `deta` or `dphi`; and mass `invm` or `mT`.
 
 Lower and upper cut bounds are given sandwiched with the cut type and a pair of letters correspond to the legs from which to take the physics objects.
-Here, `A` is the first leg, `B` the second etc.. 
+Here, `A` is the first leg, `B` the second etc...
 
-Using this syntax, `11invmAA60` denotes requirement of an invariant mass between 11 and 60 GeV for any pairing of two physics objects from the first leg (`A`).
+Using this syntax, `11invmAA60` denotes requirement of an invariant mass between 11 and 60 GeV for any pairing of two physics objects from the first leg (`A`). Specifying the same leg here also forces a check that the leg multiplicity is exactly two.
 
-`90invmAB_02dRAB` is then a requirement of an invariant mass above 90 GeV and a ΔR greater than 0.2 between any pairing of one physics object from the first leg (`A`) and one physics object from the second leg (`B`).
+`90invmAB_02dRAB` is then a requirement of an invariant mass above 90 GeV and a ΔR greater than 0.2 between any pairing of one physics object from the first leg (`A`) and one physics object from the second leg (`B`). Calculations involving two separate legs require that each leg has a multiplicity of exactly one.
+
+To satisfy the multiplicity checks, it may be necessary to split a higher multiplicity leg (e.g. `3mu6`) into multiple lower multiplicity legs (e.g. `2mu6_mu6_11invmAA60`).
 
 #### 2. A bespoke ComboHypoTool
 A custom `ComboHypoTool` may be used to implement any arbitrary selection. The base requirement is that the tool implements `IComboHypoTool`, however it is 
-- 
GitLab


From 8184daefd1523700acf71779e14ca0c02c4f0721 Mon Sep 17 00:00:00 2001
From: Teng Jian Khoo <teng.jian.khoo@cern.ch>
Date: Tue, 15 Apr 2025 17:42:10 +0200
Subject: [PATCH 3/4] Colours more legible in dark mode

---
 docs/athena/trigger/validation.md | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/docs/athena/trigger/validation.md b/docs/athena/trigger/validation.md
index dcf5474..36cee02 100644
--- a/docs/athena/trigger/validation.md
+++ b/docs/athena/trigger/validation.md
@@ -134,7 +134,7 @@ athenaHLT on data. These CI tests are simply executing a pre-defined set of ART
 In the main branch, tests of the Phase-II trigger are performed. The configuration of the three main sets is as follows:
 
 <table>
-  <tr style="border-bottom: 1px solid silver; background-color: #f2f2f2;">
+  <tr style="border-bottom: 1px solid silver; background-color: #929292;">
     <th>branch,&nbsp;project</th>
     <th>Trigger_athena_data</th>
     <th>Trigger_athena_MC</th>
@@ -146,12 +146,12 @@ In the main branch, tests of the Phase-II trigger are performed. The configurati
       test_trig_data_v1Dev_build.py<br>
     </td>
     <td>
-      <span style="color: #0b751b;">test_trig_mc_v1DevHI_build.py<sup>[!]</sup></span><br>
-      <span style="color: #1037a3;">test_trig_mc_v1Dev_ITk_ttbar200PU_build.py</span><br>
-      <span style="color: #1037a3;">test_FPGATrackSimWorkflow.sh</span>
+      <span style="color: #0b9a1b;">test_trig_mc_v1DevHI_build.py<sup>[!]</sup></span><br>
+      <span style="color: #3050dd;">test_trig_mc_v1Dev_ITk_ttbar200PU_build.py</span><br>
+      <span style="color: #3050dd;">test_FPGATrackSimWorkflow.sh</span>
     </td>
     <td>
-      <span style="color: #0b751b;">test_trigP1_v1Dev_decodeBS_build.py<sup>[!]</sup></span><br>
+      <span style="color: #0b9a1b;">test_trigP1_v1Dev_decodeBS_build.py<sup>[!]</sup></span><br>
       test_trigP1_v1PhysP1_build.py<br>
       test_trigP1_v1Cosmic_build.py
     </td>
@@ -160,24 +160,24 @@ In the main branch, tests of the Phase-II trigger are performed. The configurati
     <th>{{data.branchTier0Short}},&nbsp;Athena</th>
     <td>test_trig_data_v1Dev_build.py</td>
     <td>
-      <span style="color: #0b751b;">test_trigAna_RDOtoRDOTrig_v1Dev_build.py<sup>[!]</sup></span><br>
-      <span style="color: #0b751b;">test_trig_mc_v1DevHI_build.py<sup>[!]</sup></span>
+      <span style="color: #0b9a1b;">test_trigAna_RDOtoRDOTrig_v1Dev_build.py<sup>[!]</sup></span><br>
+      <span style="color: #0b9a1b;">test_trig_mc_v1DevHI_build.py<sup>[!]</sup></span>
     </td>
     <td>
-      <span style="color: #0b751b;">test_trigP1_v1Dev_decodeBS_build.py<sup>[!]</sup></span><br>
+      <span style="color: #0b9a1b;">test_trigP1_v1Dev_decodeBS_build.py<sup>[!]</sup></span><br>
       test_trigP1_v1PhysP1_build.py<br>
       test_trigP1_v1Cosmic_build.py
     </td>
   </tr>
 </table>
 
-The tests marked <span style="color: #1037a3;">in blue</span> are running Phase-II trigger simulation.
+The tests marked <span style="color: #3050dd;">in blue</span> are running Phase-II trigger simulation.
 
 In addition to the tests in the table above, the CI runs unit tests of the `TriggerJobOpts.TriggerConfigFlags`
 module with `python -m TriggerJobOpts.TriggerConfigFlags --verbose`.
 
 #### Updating reference files for MRs changing trigger counts
-The tests marked <span style="color: #0b751b;">in green and with <sup>[!]</sup></span> in the table above include a step
+The tests marked <span style="color: #0b9a1b;">in green and with <sup>[!]</sup></span> in the table above include a step
 comparing trigger counts in the log file to a reference located in the source tree of athena. Any MR changing these
 counts must include an update of these references as part of the submitted change set. In order to do this, run the
 affected test in any of the above ways - either [directly](#when-writing-code) or with `runTrigART.py -m` and follow the
-- 
GitLab


From 7a57b66b02fb7c2af818685fb0c93bd4d0575e4a Mon Sep 17 00:00:00 2001
From: Teng Jian Khoo <teng.jian.khoo@cern.ch>
Date: Wed, 23 Apr 2025 13:56:54 +0000
Subject: [PATCH 4/4] Grammatical fix

---
 docs/athena/trigger/combohypos.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/athena/trigger/combohypos.md b/docs/athena/trigger/combohypos.md
index 5a0f578..6949b0c 100644
--- a/docs/athena/trigger/combohypos.md
+++ b/docs/athena/trigger/combohypos.md
@@ -87,7 +87,7 @@ This stage goes from a set of `Decision` objects associated to each leg to a set
 We're going to use these hash values to enforce the multiplicity check. Thus by modifying them we can also program that the multiplicity check is skipped. This is done under the following situations:
 
  * If there was no `feature` and we fell back on the `initialRoI`, and the `initialRoI` is the special `FSNOSEED` full-scan ROI.
- * If the `feature` is itself and an RoI, and that RoI is flagged as full-scan.
+ * If the `feature` is itself an RoI, and this RoI is flagged as full-scan.
  * If the `HypoAlg` signalled to the `ComboHypo` algorithm that it should not act on this decision object. This is achieved by decorating  `Decision` objects with `<int32_t>("noCombo") == 1`.
 
 If any of these three conditions are satisfied, then instead of adding our single hash value we instead add 
-- 
GitLab