A trigger, sometimes also called a chain, is the combination of a level-1 (L1) hardware trigger seed and some high-level trigger (HLT) software reconstruction algorithms (that e.g. reconstruct some muons) and hypotheses (that e.g. make sure these muons pass the correct thresholds). Both the L1 and HLT components have an associated prescale, which says what fraction of possible times you want the trigger to actually run and select events.
Let’s start by going through a simple trigger that some of you might use in your analyses: HLT_2mu14_L12MU10
.
This trigger has a level-1 seed of L1_2MU10
. This means that, in order for the HLT algorithms to run, the hardware trigger must satisfy the requirement of two, 10 GeV muon regions of interest (RoIs).
This trigger is a primary trigger, meaning it is identified as being one of the key triggers for the ATLAS physics programme. Additionally, it is unprescaled, meaning the prescale of this trigger is always exactly one at both L1 and HLT: there is no artificial reduction in the fraction of events that could pass this chain. The L1_2MU10
item is flagged as passing in all events that have two, 10 GeV muon RoIs, and we process the HLT algorithms on all events that the L1 item passes.
In events where the L1 item has been satisfied, the HLT runs muon reconstruction around all the muon regions of interest that are of the correct pT
. These RoIs are said to seed the HLT reconstruction. For example, in HLT_2mu14_L12MU10
, the muon reconstruction is seeded by all MU10
RoIs, but the pT thresholds do not have to match - this is a choice that we make when configuring the trigger.
After each step in the reconstruction, a ComboHypo
runs, and makes sure that there are actually two unique HLT objects - i.e. that the trigger satisfies a multiplicity of 2.
Triggers have legs, which each leg being something that has multiplicity N > 0
that is unique from everything else in the chain. Each leg must have its own L1 seed, but these seeds do not have to actually match the L1 item that seeds the trigger itself.
For example, the chain HLT_2mu14_L12MU10
has one leg with multiplicity two, and 2mu14
is seeded by 2MU10
. The chain HLT_2mu10_j40_L12MU10
has two legs, one with multiplicity two and one with multiplicity one, and the seeding must be explicitly defined in the menu, since it is not implicit in the L1 item. The chain HLT_2mu10_mu6noL1_L12MU10
also has two legs (and needs explicit L1 seeding), as does HLT_mu6_mu4_L1MU6_2MU4
.
An example of a real, five leg chain that is currently in the menu is HLT_j70_0eta320_j50_0eta490_j0_dijetSEP50j12etSEP1000djmassSEPdjdphi240_xe90_tcpufit_xe50_cell_L1MJJ-500-NFF
, where each of the five legs have multiplicity one. The legs are:
j70_0eta320
j50_0eta490
j0_dijetSEP50j12etSEP1000djmassSEPdjdphi240
==> this is not an object in the traditional sense, but is the calculated dijet pairs that have dPhi
and invariant mass cuts applied
xe90_tcpufit
xe50_cell
==> MET algorithms are combined with different thresholds to have optimal signal efficiency and background rejection.
Menu/
folder, but all the config and setup files go into MenuConfig/
ChainProp
defined inside ChainDefInMenu.py
is confusing, because we use ChainDef
to refer to something else. This should be changed to ChainPropInMenu.py
, at the very least.ChainProp
jargon alert: menu file, menu python file, menu - these refer to the file that has a the long list of triggers in it - for example, LS2_v1.py
or MC_pp_run3.py
.
Chains are defined with a ChainProp
inside of the menu files themselves. The ChainProp
object is a namedtuple
, defined inside ChainDefInMenu.py
. The ChainProp
has a very limited set of properties:
Property | Use | Default value |
---|---|---|
name |
the name of the trigger | - |
l1SeedThresholds |
what L1 threshold seeds each leg | [] |
stream |
what stream(s) does this trigger seed | ['Main'] |
groups |
what prescale/rate groups should this trigger be in | [] |
mergingStrategy |
should the legs be parallel or serial merged, or should the menu determine which automatically | auto |
mergingOrder |
unknown | [] |
mergingOffset |
unknown | -1 |
topoStartFrom |
unknown | False |
monGroups |
unknown | [] |
We can now go through these one-by-one:
The trigger name (often also called the chain name) encodes nearly everything for the chain. Every piece of the name holds some important meaning, and it must follow the Run 3 naming convention.
Names are structured HLT_
+ the important stuff + _L1ItemThatSeedsTheChain
.
The L1 seed threshold must be a list with the same length as the number of legs in the trigger. Jets, MET, and noL1 muons run unseeded, and must be seeded by FSNOSEED
. Electrons and photons must be seeded by an EM threshold, muons by a MU threshold, and taus by a TAU threshold.
Thresholds must be defined in the L1 menu, but do not need to correspond to the L1 item that seeds the chain.
For example, the chain HLT_2mu10_e5_L12MU10
should be seeded by ['MU10','EM3']
: but this does not mean that the L1 item needs to actually contain EM3
. In this case, what happens is the very first HLT step applies a requirement on EM3
in addition to 2MU10
, and if there are no EM3
RoIs in the event the reconstruction does not proceed and the trigger is marked as failing.
In the muon case discussed above, the choice of MU10
to seed muon reconstruction seems obvious, but it is not always so cut and dry: for example, should e9
be seeded by EM8VH
or EM7
? Never guess, always check with the relevant signature!
The stream indicates where the events selected by the trigger are going to be written out. All possible choices are listed inside StreamInfo.py
. For physics triggers, this is generally Main
, i.e. physics_Main
, but this will not always be the case. You should be especially careful to clarify exactly which stream the trigger should go into when preparing monitoring or partial event partial event building (PEB) triggers!
As you can see in the table above, the stream
parameter is set to default as ['Main']
. Thus, for many triggers in the menu this stream is not explicitly defined.
The only case in which a trigger should go into more than one stream is when one of those streams is 'express'
. No trigger should go only into express
, so if you are requested to add a trigger into the express stream when it does not already have an explicit stream=[PhysicsStream]
in the ChainProp
, make sure to add this. i.e. we want this:
stream=[PhysicsStream,'express']
not this:
stream=['express']
.
The groups list is used for three purposes:
PS:Online
, which means that these triggers do not run in either MC or data reprocessings - we only intend them to run online. They are disabled in the default prescale sets prepared when the menu is generated.HLT_timeburner_L1All
, beamspot triggers, and minimum bias triggers.RATE
) and bandwidth (BW
) groups
pbeast
and are saved into IS for later plotting.Most of the groups should be designated using the variables set inside Physics_pp_run3_v1.py
. These are imported at the top of the menu file (if the required group is not yet imported, you can add it). Please be careful to add the variables in a way such that the list has depth 1, i.e. do this:
SingleMuonGroup = ['RATE:SingleMuon', 'BW:Muon']
PrimaryGroup = ['Primary']
...
groups = SingleMuonGroup + PrimaryGroup
not this:
groups = [SingleMuonGroup + PrimaryGroup]
Be careful to set the groups in the Run 3 style - if you are implementing Run 2 triggers, don’t blindly copy over the groups!
mergingStrategy
: Unless you are performing a specific test, there is no reason to specify this variable. The default is auto
, which means that alignment strategy hardcoded in MenuAlignmentTools.py
is what specifies how the legs are going to be merged. If the default merging is not doing what you think the chain should be, do not attempt to force the strategy to parallel
or serial
. This will likely cause stalls at runtime. Instead, this should be discussed in detail on JIRA.
mergingOrder
: ?? no idea, we don’t use it
mergingOffset
: ?? no idea, we don’t use it
topoStartFrom
I think this isn’t used either - maybe a holdover from Run 2?
Not really sure, to be filled in.
Chain dictionaries (what we colloquially call a chainDict) are an expanded dictionary created from default parameters set by each signature and the parameters configured in the ChainProp
(i.e. the chain name). Since each signature has a different set of necessary parameters, the ChainDicts
look different between signatures. However, they all follow the same basic structure.
The parsing from ChainProp
to ChainDict
happens inside the file SignatureFromChainDict.py
, and which is called per-chain from the function xxx
inside GenerateMenuMT.py
.
It is crucial that the parameters in the ChainDict
be correctly set, since this is what the signature code later uses to configure the the algorithms and hypos that comprise a trigger.
Every signature
We’ll start by walking through a simple, single