High Level Trigger

Complete: 3


This wiki topic collects and provides information about (the software implementation of) the High Level Trigger (HLT) of CMS in the CMS software framework/EDM. The HLT is discussed in the TSG (trigger studies group), see INDICO server for the presentations. The HLT algorithms and performance are described in CERN/LHCC 2007-021 (pdf).

Operation of the HLT follows that of the Level-1 trigger. The output of the online process is the so-called RAW data tier, which contains the raw data plus triggers plus some high-level objects reconstructed during HLT running for accepted events.

HLT Description

How it works

The HLT contains many trigger paths, each corresponding to a dedicated trigger (such as a prescaled single-electron trigger or a 3-jets-with-MET trigger). A path consists of several steps (software modules), each module performing a well-defined task such as unpacking (raw to digi), reconstruction of physics objects (electrons, muons, jets, MET, etc.), making intermediate decisions triggering more refined reconstructions in subsequent modules, or calculating the final decision for a trigger path. The CMSSW Framework/EDM ensures that if an intermediate filter decision on a trigger path is negative, the rest of the path is not executed (skipped) and the specific trigger is regarded as rejecting the event. In order to save CPU time, each reconstruction step is followed by a filter in order to avoid running time-consuming reco code if it is already clear it will not be needed.

In general it is expected that all HLT trigger paths are run, even if the event is already accepted by a path. In case this turns out to be too time-consuming, a truncated mode of HLT operations should be foreseen where the HLT short-circuits after the first accept (and after the triggers needed to classify the event for a primary data set and output stream are computed) and does not run the rest of the triggers. Presumably, the triggers not run online could be run in the offline reconstruction step to compute all trigger bits (for events written out) in order to get a complete trigger picture allowing trigger efficiency studies.

Each HLT trigger path must be seeded by one or more L1 trigger bit seeds: the first filter module in each HLT path is looking for a suitable L1 seed (consisting of L1 bit[s] and L1 object[s]) as a starting point for that specific HLT trigger.

Technical Aspects

The HLT is configured by specifying the trigger paths, being built from individual software modules and/or already defined sequences of modules, using the parameter set configuration language (see WorkBookConfigFileIntro).

For example, a hypothetical di-jet + MET trigger may look like this:

  myPrescJetMet    = cms.EDProducer("PrescJetMet", ...  // config of prescaler module
  myL1seedFilter   = cms.EDFilter("L1seedFilter", ...  // config of filter module
  myJetReco        =  cms.EDProducer(" ...  // config of reconstruction module
  myDijetminvFilter =  cms.EDFilter(" ...  // config of filter module
  myMetReco        = cms.EDProducer(" ...  // config of reconstruction module
  myMetFilter      = cms.EDFilter(" ...    // config of filter module

  path dijetMET = {myPrescJetMet, myL1seedFilter, myJetReco, myDijetminvFilter, myMetReco, myMetFilter}

It is possible to have different instances of any module (algorithm) if different values of their module parameters are needed. Each software module is either an EDProducer (reconstruction modules) or an HLTFilter (subclassed from EDFilter, to filter on trigger conditions and do related trigger book-keeping), getting its input (an EDProduct) from the Event, and, in case of an EDProducer, putting its output (another EDProduct) into the Event.

For accepted events, either all intermediate and final EDProducts of all trigger paths are written out - aka HLTDEBUG event content (CMS.RelVal, fraction of real data events) or only the highest-level collections (aka "L3" collections) and highest-level filter decisions (aka "L3" filters) are packed up in a single EDProduct and saved (MC bulk production), also depending on data tier - DEBUG, RAW, RECO, AOD. In the HLTDEBUG case, the original collections are saved; thus it is possible to trace back from intermediate and final HLT filter decisions of a trigger to the individual reconstructed objects (members of collections of reconstructed physics objects) used in that decision. Especially in case of "accept" decisions, the physics objects leading to the accept (EDProducts or members thereof) are accessible just knowing the trigger and filter module. The possible number of reconstructed objects or amount of detailed object information which is to be saved in the non-HLTDEBUG case (and cross-referenced from the trigger results) depends on time and progress in understanding the needs.

Modules performing reconstruction tasks (EDProducers, making new collections of reconstructed objects) should ideally be taken from the standard off-line reconstruction, with parameters configured for HLT, unless more drastic optimisation (in terms of memory and CPU time usage) is needed. By the same token, reconstructed objects in the HLT are thus standard reconstruction objects. The high-level trigger cuts - as opposed to low-level reconstruction cuts - are implemented as HLT filters (subclassed in turn from EDFilters, making intermediate decisions to proceed on the path or making the final decision of the path).

Services provided by the framework/EDM

Modules (EDProducers or HLTFilters) with different module (algorithm) parameters are considered different module instances. The Framework/EDM scheduler ensures that each module instance is called only once, and that the results, in case they are needed again, are simply re-used, see: SWGuideEDMPathsAndTriggerBits

Pre-scaling: A generic EDFilter module performing a configurable prescale is available, see the description at SWGuideEDMPathsAndTriggerBits#Generic_prescale_module. However, within the HLT context, the PrescaleService must be used involving additional book-keeping, hence within the HLT one must use only instances of the HLTPrescaler class and module. The configured module instance is inserted as a filter into the HLT path of the trigger to be prescaled. If this module is at the very end of the path, the trigger decision for the event from that path is still computed, allowing the study of trigger efficiencies with higher statistics. However, in order to save the processing time, the prescale module is usually put at the beginning of the path.

Basic timing and memory-usage services are provided by the framework, see: SWGuideEDMTimingAndMemory. The framework counts events as they progress through each trigger path and module instance, and provides a summary printout at the end of the run, see: SWGuideEDMPathsAndTriggerBits#Summary_report. This printout includes the time taken by each module and path, averaged over all events processed.

A MessageLogger service is available as well (SWGuideMessageLogger), which must be used instead of "cout/clog/cerr".

Persistent Trigger Results Objects

Depending on use case, two or three persistent HLT products are available:

  • A TriggerResults product (subclassed from HLTGlobalStatus object, described in this section), containing all the usual decision bits,
  • A TriggerEvent, summarising the "L3" trigger collections and "L3" filter decisions,
  • A TriggerEventWithRefs product, summarising the Refs to all trigger collections and all trigger filter decisions (requires the pointed-to collections to be present, i.e., only useful on files with the HLTDEBUG event content).

The TriggerResults product (one, available for events written to output) allows access to the configuration and trigger decisions, i.e., all the usual "trigger bits", including:

  • Final decision of individual path and of full trigger table
  • Which triggers were run (some triggers may not run due to lack of a corresponding L1 seed or HLT running in truncated mode)
  • For each trigger rejecting the event, (the index of) which intermediate or final module instances on the path rejected the event
  • For each trigger encountering an error condition, (the index of) which module instances on the path encountered un-recoverable errors (leading the event to be also routed to an error stream)

The rationale for the (predecessors to the) TriggerEvent and TriggerEventWithRefs products is described here; the technical implementation is by now different. In particular, we now use explicit typing instead of polymorphism.

Old class documentation is here: SWGuideDataFormatHLTrigger

The package HLTrigger/HLTcore contains several analyzers pulling out the trigger information. You can use the corresponding analyzers directly - see their cfi files in the python subdirectory - or copy relevant code pieces into your modules.

  • TriggerSummaryAnalyzerAOD - analyser printing the content of the TriggerEvent product
  • TriggerSummaryAnalyzerRAW - analyser printing the content of the TriggerEventWithRefs product
  • HLTEventAnalyzerAOD - analyser combining the information from TriggerResults and TriggerEvent products
  • HLTEventAnalyzerRAW - analyser combining the information from TriggerResults and TriggerEventWithRefs products

The HLTEventAnalyzer * plugins make use of the helper class HLTConfigProvider (also in HLTrigger/HLTcore), which extracts the HLT configuration (paths, modules) from the provenance. Note: this helper class must be initialised calling it's init(...) from the beginRun() method of your plugin using this helper class. The reason that it has to be (re-)initialised in beginRun() is that the HLT configuration can (only) change at the boundary between runs. See the HLTEventAnalyzer * plugins as examples on how to use the HLTConfigProvider class.

Policies and rules for HLT code

Location of trigger code in repository

As discussed above, each HLT trigger path is a sequence of reconstruction and filter module instances. Modules correspond to C++ classes with each module instance run by the Scheduler corresponding to a different setting of the module configuration parameters.

Reconstruction modules used in HLT trigger paths reside either in some package of their subdetector subsystem or in some other, higher-level reconstruction subsystem/package, even if they are different from the corresponding standard offline reconstruction modules (due to the requirement of using variants of algorithms optimised for CPU-time or other constraints of the online system). This should allow tighter integration and comparison as well as coherent development with the corresponding offline reconstruction modules.

In contrast, however, the filter modules on an HLT trigger path all reside in packages within the subsystem HLTrigger:

  • HLT framework code resides in HLTrigger/HLTcore.
  • Example and important generic HLT filters are provided in HLTrigger/HLTfilters.
  • Example modules are provided in HLTrigger/HLTexample
  • Specific HLT filter modules and config files for TriggerGroup s such as CMS.JetMET, Egamma, Muon, btau, etc., reside in their respective Package under HLTrigger: HLTrigger/_TriggerGroup_.
  • Configuration of the global trigger table resides in HLTrigger/Configuration

HLT filters (and producers)

Filtering (i.e., implementation of any kind of "trigger" cuts) must be performed by HLT filter modules, providing also the required book-keeping of physics objects used in filter decisions (see below for the details!). Therefore, do not use offline-analysis-oriented Generic Selector and/or Filter Modules or similar, because these are not HLT-aware. Also, do not "hide" high-level filter logic in producer modules.

Further conventions enforced for HLT filter modules are:

  • HLT filter classes (HLT filter modules) must derive from class HLTFilter in HLTrigger/HLTcore (attention: NOT EDFilter class).
  • The C++ names of HLT filter classes must start with "HLT" .
  • The module label (instance name) must start with "hlt".
  • Any prescaling filtering must be performed using the HLTPrescaler filter class in HLTrigger/HLTcore (attention: NOT Prescaler class).
  • Each HLT path must contain its own instance of an HLTPrescaler
  • Each HLT filter class module is accompanied by an example cfi configuration file in the python directory (see also here for conventions on file naming and suffixes such as cfg, cfi and cff).
  • For reasons of performance as well as control over verbosity, any printout must only use LogDebug or LogTrace provided by the MessageLogger service.
  • EDProducts used by HLT filter modules as inputs must be identified using the InputTag type from the configuration language (see the example filters), not strings.
  • Parameter names, as used for HLT filter module configuration in config files, must follow the naming convention MinName, MaxName, such as MinPt, MaxEta, or MinN, etc. (note capitalisation), with all filters using the same name for the same quantity. This helps to get a faster overview on the configuration of different HLT filters.
  • The C++ names of such configuration variables, as they are data members of the filter class, should start with a lower-case letter and end in an underscore (e.g., min_Pt_, max_Eta_, min_N_, in direct correspondence to the name used in the config files), for easy identification in the class code. Again, all filters should use the same name for the same quantity.
  • In general, the CMSSW rules on naming, coding and style are to be followed.
  • Instead of writing several different filter classes for similar filter algorithms, use (or extend) existing filters, or template it.
  • Each HLT filter module must put an TriggerFilterObjectWithRefs into the Event, which records "L3" collection tags as well as Refs pointing to those "L3" physics objects which passed this filter module. See the example filters for the C++ code on how this is done. This requires the pointed-to physics objects to be classes available in TriggerRefsCollection
  • HLT filter classes may not perform any heavy time-consuming computations. Typically, they acquire a collection of objects, loop over them and apply simple cuts on quantities derived from the objects in the collection. In case these quantities turn out to require heavy computing, one should factor out that computation into a separate reconstruction module (for example, in a reconstruction module producing an WorkBookAssociationMap - see DataFormats/Common - associating the newly calculated variables to objects in an existing collection, which makes these quantities available for re-use by other modules in the same or in another HLT trigger path). As a consequence, HLT filter classes contain very little code (Rule of thumb: if the code of the filter class does not fit on a screen, it's too long!).
  • Conversely, producer modules should not implement trigger cuts (as opposed to low-level reconstruction cuts).

Access by the HLT to Level-1 Trigger informations

  • Each HLT trigger path starts out with its specific module instance of the general HLTLevel1GTSeed filter module (class located in HLTfilters ), configured for the specific HLT trigger path
  • The HLTLevel1GTSeed filter module takes as configuration the list of Level-1 trigger bits of interest for the given HLT trigger path. The module's cfi file is available here. The module accesses the Level-1 data using the l1extra classes to obtain
    • the L1 decision for the set of Level-1 triggers requested in its configuration, and
    • the Level-1 physics objects (L1 EM, jets, muons, taus in the Candidate hierarchy) whiche fired the requested Level-1 set.
  • The Boolean filter decision of the HLTLevel1GTSeed filter module is simply the combination of the requested Level-1 triggers
  • The HLT filter object placed into the Event by the HLTLevel1GTSeed filter contains refs to all the physics objects found at Level-1 which fired the requested L1 triggers. Through the persistent references kept in the filter object as well, one can go down to the specific l1extra objects and their collections, and, if really needed, from there then further down to the level of the Level-1 internal objects. HLT modules should make use of the filter object placed by the HLTLevel1Seed filter and access the selected L1 objects through that, rather than accessing L1 classes directly.
  • Hence this HLT filter object provides a list of seed objects for regional unpacking and/or regional reconstruction, etc., of interest for the specific HLT trigger path; it can of course be used by any module on the path.

Event selection using trigger bits

Selecting events, for skimming or analysis, which have passed any number of HLT triggers is done by the filter modules HLTHighLevel or TriggerResultsFilter (classes located in HLTrigger/HLTfilters).

In the HLTHighLevel filter, the user specifies the list of HLT triggers s/he is interested in - an empty list defaults to all HLT paths in the trigger table. HLT trigger paths are specified by their path name. The Boolean filter result can be configured to be either the logical OR or the logical AND of the HLT triggers specified. For details, see the class header file; the module's cfi file is here.
In case you want to select events based on Level-1 trigger bits, simply use the HLTLevel1Seed filter described above.

The TriggerResultsFilter is able to parse any logical expression composed of L1 algorithmic triggers (e.g., L1_SingleMu3), L1 technical triggers (e.g., L1Tech_BSC_minBias_OR) and HLT paths (e.g., HLT_Mu9 or AlCa_EtaPi0). More information is provided in its own twiki page.

For a list of HLT trigger names, look here: SWGuideGlobalHLT .

Event selection using a (new) tighter HLT path

The filter HLTSummaryFilter allows to cut on the 4-momentum representation of objects having fired an L3 filter. This is useful for studies of new triggers resembling existing triggers but with higher thresholds on the final objects. here.

Access to the HLT configuration - the HLTConfigProvider

The HLTConfigProvider is a helper class allowing your CMSSW code access to the HLT configuration with which the data was taken, such as streams and data sets, trigger paths and filters, configurations of trigger paths and their modules, etc. (including HLT prescale sets). The information is extracted from the provenance, which itself is stored inside the data (or MC) event files.

The HLTConfigProvider class is located in the package HLTrigger/HLTcore. For both efficiency reasons and allowing proper initialization, you must put an instance of this class as a data member in your producer/analyzer/filter plugin (beware: it is really very inefficient to put it as a local variable in any method of your class!), for example:

#include "HLTrigger/HLTcore/interface/HLTConfigProvider.h"
class MyAnalyzer : public EDAnalyzer {
/// Make this a configurable module parameter of your plugin:
string processName_; // process name of (HLT) process for which to get HLT configuration

/// The instance of the HLTConfigProvider as a data member
HLTConfigProvider hltConfig_;

The HLTConfigProvider is then initialized in your plugin's beginRun(.) method. This is done because the HLT configuration can change between Runs, and you need to pick up the new configuration.

MyAnalyzer::beginRun(edm::Run const & iRun, edm::EventSetup const& iSetup)
  bool changed(true);
  if (hltConfig_.init(iRun,iSetup,processName_,changed)) {
    // if init returns TRUE, initialisation has succeeded!
    if (changed) {
     // The HLT config has actually changed wrt the previous Run, hence rebook your
     // histograms or do anything else dependent on the revised HLT config
  } else {
    // if init returns FALSE, initialisation has NOT succeeded, which indicates a problem
    // with the file and/or code and needs to be investigated!
    LogError("MyAnalyzer") << " HLT config extraction failure with process name " << processName_;
    // In this case, all access methods will return empty values!

The init method (if it returns true) of the HLTConfigProvider unpacks and caches all HLT configuration information internally, allowing fast and efficient access via the HLTConfigProvider 's const-ref access methods. Therefore it is a waste of resources (CPU time and RAM memory) to use local variables or data members simply to hold the HLT information accessed through the HLTConfigProvider. Since the HLT configuration is identical for all events of a Run, your setup work depending on the HLT configuration should all be done in your plugin's beginRun method. If the init method returns false, the internal caches of the HLTConfigProvider will be cleared and reset to empty/zero. Hence you need to check the return value of init and take appropriate action in your plugin, such as skipping booking/filling histograms or any other processing depending on a valid HLT configuration (experience shows that many run-time problems reported are due to developers NOT paying attention to the return value of init).

Once successfully initialized in beginRun, you can then call in your plugin's begin / endRun, begin / endLumiBlock, or analyze / produce / filter methods any of the various public const accessor methods of the HLTConfigProvider to get information on the HLT configuration. For a list of available access methods providing all the information, see the header file HLTConfigProvider.h.

HLT Prescales

HLT prescales in force when the data was taken are also accessed through the HLTConfigProvider helper class (see above) in CMSSW, but in a special way described in the following. The HLT configuration contains several pre-configured sets of prescale values, to cover different instantaneous luminosities - say, N sets of prescale values, with prescale value set indices running from 0 to N -1. For real data, the prescale sets are saved in the Provenance (and thus available through the HLTConfigProvider class) only since Run 136393 when CMSSW_3_5_7_onlpatch4 was put online (28-May-2010). For MC, these are available since CMSSW_3_5, but note that on MC all L1 and HLT prescales are set to 1 anyway.

HOWEVER: The index number of which prescale set is currently in use is stored in an L1 Event data product: the same index is used to select the L1 prescale set as well as the HLT prescale set. While the access to the HLT prescale sets is available as any other HLT configuration information (i.e., after a successfull init of the HLTConfigProvider class), the active prescale set index number and thus the currently active HLT prescale set (prescale value for each HLT path) are thus ONLY available through HLTConfigProvider accessors expecting also the Event data-structure (ie, these accessors can not be called in begin / endRun nor begin / endLumiBlock, but only in the produce / analyze / filter methods). It also means the relevant L1 product must be in the input data file (either directly or unpacked from the raw data collection before your plugin comes along).

The following accessors for HLT prescales are available as methods of the HLTConfigProvider class:

  /// prescale value for a given set index number (in case you know it from elsewhere)
  /// and a given trigger path
  unsigned int prescaleValue(unsigned int set, const std::string& trigger) const;

  /// getting the current (active) prescale set index number (needs Event/EventSetup as parameters)
  int prescaleSet(const edm::Event& iEvent, const edm::EventSetup& iSetup) const; 
  /// in case a negative number such as -1 is returned, the prescale set index number could not be obtained

  /// getting directly the currently active prescale value for a given trigger path
  /// (calls above prescaleSet and prescaleValue methods internally)
  unsigned int prescaleValue(const edm::Event& iEvent, const edm::EventSetup& iSetup, const std::string& trigger) const;

Note: the prescale set index number itself can only change between luminosity sections, for events within a lumi section it stays constant!

To get the current prescale set index number from the L1 data, the L1 helper class L1GtUtils is used internally by the HLTConfigProvider. This is a class similar in spirit to HLT's HLTConfigProvider class but for L1 information, including L1 prescales. This L1 helper class requires the corresponding L1 data product to be in the input file (either directly, or unpacked from the raw data collection before your plugin comes along) - if this is not the case, the method prescaleSet() returns -1, and prescaleValue() falls back to returning 1. Hence you should always check prescaleSet() first before using prescaleValue().

L1T and HLT Prescales for HLT paths

In recent versions of the HLTConfigProvider class (see the header file HLTConfigProvider.h for the CMSSW release you are using), an additional method is available which also returns the prescale of the L1 trigger seeding an HLT path. This obviously works only for HLT paths which are seeded by exactly (at most) one L1 physics bit. The HLTConfigProvider will print an informative LogError message in case something goes wrong. The corresponding accessor method is:

  /// Combined L1T (pair.first) and HLT (pair.second) prescales per HLT path
  std::pair<int,int> prescaleValues(const edm::Event& iEvent, const edm::EventSetup& iSetup, const std::string& trigger) const;
  // any one negative => error in retrieving this (L1T or HLT) prescale

In the CMSSW 7 series, a further prescale accessor, prescaleValuesInDetail(), has been added, which is usefull in the case the L1 seed condition of an HLT path is a complicated Boolean expression, such as 'L1_DoubleEG5 OR L1_SingleEG10'. This new accessor:

std::pair<std::vector<std::pair<std::string,int> >,int> prescaleValuesInDetail(const edm::Event& iEvent, const edm::EventSetup& iSetup, const std::string& trigger) const;

takes the HLT path name, figures out its L1 seed condition, and returns a vector of pairs, with the first component being the individual L1 name (such as L1_DoubleEG5) and the second component the L1 prescale valaue for it, this for all L1Ts used in the seed expression. This vector is then combined, with the (single) HLT prescale used at HLT level for the HLT path in question, in another pair, and retuned to the user.

The usage of this accessor is best described as follows: in almost all cases of a complex L1 seed Boolean expression, the expression is an OR of several L1Ts, say n of those. In such a case, the HLT path can be regarded as a short hand notation of n HLT paths, each with a single L1T as seed condition. An analysis user would pick ONE of those paths and derive the corresponding overall prescale as the product of L1T prescale and HLT prescale, select events based on passing both the single L1T condition and the (combined) HLT path, and calculate the effective luminosity.

As before, the helper class L1GtUtils is used internally, so the above remarks on L1GtUtils apply here as well.

Review Status

Reviewer/Editor and Date (copy from screen) Comments
AndreaBocci - 17 Sep 2014 update links to point to GitHub
HalilGamsizkan - 24 Sep 2012 updating content
JennyWilliams - 07 Feb 2007 editing to include in SWGuide
Main.gruen - 26 Jan 2006 page author

Responsible: MartinGrunewald
Last reviewed by: Reviewer

Topic attachments
I Attachment History Action Size Date Who Comment
Unknown file formatgz HLTAnalysis.tar.gz r1 manage 48.7 K 2006-08-07 - 05:52 UnknownUser Example of HLT jet analysis code (CMSSW_0_8_1)
Unknown file formatcfg run_hlt_070.cfg r1 manage 2.2 K 2006-06-21 - 19:03 LeonardApanasevich Configuration file for HLT example (CMSSW_0_7_0)
Unknown file formatcfg run_hlt_081.cfg r1 manage 3.0 K 2006-08-07 - 22:59 UnknownUser Configuration file for HLT example (CMSSW_0_8_1)
Unknown file formatcfg run_recojets_070.cfg r1 manage 5.7 K 2006-06-21 - 21:39 LeonardApanasevich Configuration file for detector and jet reconstruction (CMSSW_0_7_0)
Unknown file formatcfg run_recojets_081.cfg r1 manage 1.3 K 2006-08-07 - 23:00 UnknownUser Configuration file for detector and jet reconstruction (CMSSW_0_8_1)
Unknown file formatcfg run_simdigi_070.cfg r1 manage 5.7 K 2006-06-21 - 18:53 LeonardApanasevich Pythia simultation + digitization file (CMSSW_0_7_0)
Unknown file formatcfg run_simdigi_081.cfg r1 manage 3.2 K 2006-08-07 - 23:01 UnknownUser Pythia simultation + digitization file (CMSSW_0_8_1)
Edit | Attach | Watch | Print version | History: r120 < r119 < r118 < r117 < r116 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r120 - 2014-09-17 - AndreaBocci

    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    CMSPublic All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2018 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback