Using Triggers in Analysis

Last update: 16 Nov 2022 [History] [Edit]

Using the CP algorithms, it is much simpler to access trigger decision information than it previously was, which should be sufficient for most analyses. If your analysis requires additional functionality, you may need to work with the trigger group to create algorithms to do it.

We will require events to pass at least one of four different triggers (2 electron triggers and two muon triggers) to ensure we have good coverage of the various final states we care about. In an actual analysis, you may need to use significantly more triggers, depending on your final state signature.

Schedule trigger analysis sequence

We need to begin by defining the list of triggers that we want to use. First, add the following lines to MyAnalysisAlgorithms.py near the other configurations:

triggerChains = [
    'HLT_e26_lhtight_nod0_ivarloose',
    'HLT_e60_lhmedium',
    'HLT_mu26_ivarmedium',
    'HLT_mu50'
]

Next, add the following lines to makeSequence() in MyAnalysisAlgorithms.py anywhere before return algSeq:

    # Include and set up the trigger analysis sequence:
    from TriggerAnalysisAlgorithms.TriggerAnalysisSequence import makeTriggerAnalysisSequence
    triggerSequence = makeTriggerAnalysisSequence( dataType, triggerChains=triggerChains )

    # Add the trigger analysis sequence to the job:
    algSeq += triggerSequence

This will check which, if any, of the triggers in the list the event passes. It decorates EventInfo with a bool decoration for each trigger in the list. The decoration is called trigPassed_<trigger name>, where <trigger name> is replaced by the corresponding trigger name.

Retrieve trigger decisions and select events

Since the trigger passing information is decorated to EventInfo, we don’t need to do much to retrieve the information. However, we need to think carefully about what we want to do with this information. In many cases, it would be sensible to store the decision from each trigger to the output ntuple. But for the tutorial, we will simply use the trigger decisions to save only events that pass at least one trigger.

To do this, we will check each of the four available triggers and if none of them are true, we will skip the event. We want to do this check before anything else is done in each event so we don’t use CPU resources retrieving object information or looping over objects for events we don’t care about. Additionally, events need to be skipped before the TTree Fill() method is called.

Add the following lines to execute() after EventInfo is retrieved but before anything else is retrieved from the store:

  // Loop over triggers and check if any are passed
  bool passTrig = false;

  if(eventInfo->auxdata< bool >("trigPassed_HLT_e26_lhtight_nod0_ivarloose")) passTrig = true;
  if(eventInfo->auxdata< bool >("trigPassed_HLT_e60_lhmedium")) passTrig = true;
  if(eventInfo->auxdata< bool >("trigPassed_HLT_mu26_ivarmedium")) passTrig = true;
  if(eventInfo->auxdata< bool >("trigPassed_HLT_mu50")) passTrig = true;

  // If no trigger is passed, skip the event
  if(!passTrig) return StatusCode::SUCCESS;

Rerun your job and check how the output changes. When you are satisfied, commit and push your changes.


⭐️ Bonus Exercise

Add the following triggers to your analysis:

  • HLT_e140_lhloose
  • HLT_e300_etcut
  • HLT_mu60_0eta105_msonly

How do these change your ntuple output?