PAT Exercise 10: How to produce and analyze PAT trigger information


  • Learn how to produce trigger information in PAT and how to access it.

ALERT! Note:
This web course is part of the PAT Tutorial, which takes regularly place at cern and in other places. When following the PAT Tutorial the answers of questions marked in RED should be filled into the exercise form that has been introduced at the beginning of the tutorial. Also the solutions to the Exercises should be filled into the form. The exercises are marked in three colours, indicating whether this exercise is basic (obligatory), continuative (recommended) or optional (free). The colour coding is summarized in the table below:

Color Code Explanation
red Basic exercise, which is obligatory for the PAT Tutorial.
yellow Continuative exercise, which is recommended for the PAT Tutorial to deepen what has been learned.
green Optional exercise, which shows interesting applications of what has been learned.

Basic exercises ( red ) are obliged and the solutions to the exercises should be filled into the exercise form during the PAT Tutorial.


Triggering any interesting event and storing this information to the granularity level accessible at CMS is a complex and difficult task. The CMS trigger is nearly a parallel world to the world of RECO objects. To access trigger information within the EDM can be an extremely challenging task for a normal user. PAT provides you with an easy entry point to access trigger information via the pat::TriggerEvent. Nevertheless the amount accessible information via the PAT TriggerEvent can still be enormous and not all of this information you need. PAT provides sensible default configurations but not all use cases are covered. So configuring the amount of trigger information that will be written to your pat::Tuple to what you really need is not only beneficial because of the size of your pat::Tuple but might even be necessary. It is therefore important to have at least a basic understanding of how the PAT TriggerEvent is configured and produced. The following examples provide a gentle introduction on this subject. As you will see the PAT TriggerEvent is the central access door to all information related to CMS L1 and HLT triggers. By the end of these exercises you should be able to answer the following question: What is the PAT TriggerEvent, how can I produce it and how do I get access to trigger information from there?

Setting up of the environment


You can reuse the environment created in Exercise 9.

How to get and compile the code

Check out the required packages and recompile with

git cms-addpkg DataFormats/PatCandidates
git cms-addpkg PhysicsTools/PatAlgos
git cms-addpkg PhysicsTools/PatExamples
git cms-merge-topic -u CMS-PAT-Tutorial:CMSSW_7_4_1_patTutorial
scram b


Produce PAT trigger information

For the very beginning, let us inspect the most basic example found in PhysicsTools/PatAlgos/test/ It extends the minimal PAT configuration by a standard trigger information production by simply using the according Python tool:

## import skeleton process
from PhysicsTools.PatAlgos.patTemplate_cfg import *

# Switch on "unscheduled" mode
process.options.allowUnscheduled = cms.untracked.bool( True )
#process.Tracer = cms.Service( "Tracer" )

# Load default PAT
process.load( "PhysicsTools.PatAlgos.producersLayer1.patCandidates_cff" )
process.load( "PhysicsTools.PatAlgos.selectionLayer1.selectedPatCandidates_cff" )
process.p = cms.Path(

## add trigger information to the configuration
from import *
switchOnTrigger( process )

As you can already see from this configuration file, enabling trigger information in your pat::Tuple needs only a few lines. Have a look at:

less $CMSSW_BASE/src/PhysicsTools/PatAlgos/python/tools/

using your favorite text editor. There you will find the definition of all available PAT trigger tools. The documentation for these tools is provided in SWGuidePATTrigger - Tools.

However, these tools do not deal with manipulation of all available configuration parameters for the PAT trigger production. As in the example for the addition of L1 algorithms, such parameters have to be changed by hand, after the tools have been applied.

Now it is time to create an own configuration file:

red Exercise 10 a):
Produce a PAT-tuple, which contains the trigger information only.

As starting point, create a configuration file with this configuration skeleton, using promptly reconstructed muon data as input:

## --
## Start with pre-defined skeleton process
## --
from PhysicsTools.PatAlgos.patTemplate_cfg import *
## ... and modify it according to the needs:
# use 2012 data PromptReco as input
process.source.fileNames = [
  #some events /SingleMu/Run2012B-PromptReco_v1/AOD, run 196364
, '/store/data/Run2012B/SingleMu/AOD/PromptReco-v1/000/196/364/0C06CE57-C2B8-E111-BA54-001D09F242EF.root'
, '/store/data/Run2012B/SingleMu/AOD/PromptReco-v1/000/196/364/0C97DC6D-CBB8-E111-B39F-00237DDC5BBC.root'
# use only certified data
process.source.lumisToProcess = cms.untracked.VLuminosityBlockRange(
, '196364:96-196364:136'
, '196364:139-196364:365'
, '196364:368-196364:380'
, '196364:382-196364:601'
, '196364:603-196364:795'
, '196364:798-196364:884'
, '196364:887-196364:1196'
, '196364:1199-196364:1200'
, '196364:1203-196364:1302'
# use the correct conditions
from Configuration.AlCa.GlobalTag import GlobalTag
process.GlobalTag = GlobalTag( process.GlobalTag, 'auto:com10' ) # 2012B
# use a sufficient number of events
process.maxEvents.input = 1000
# have a proper output file name
process.out.fileName = 'patTuple_triggerOnly.root'

Now, extend the configuration in such a way that

  • the full PAT trigger information is produced;
  • it contains additionally to the defaults:
    • the L1 algorithms,
    • all l1extra particles (as found in the input data!)
    • the working references back to the original l1extra collections;
  • no PAT object collections are produced.

TIP Do not forget that you need a path.
TIP Do not forget that references need to point somewhere.
TIP Check for configuration parameters to modify or to add.

Question Question 10 a)
What is special in this case, compared to "normal" configurations?
TIP There are many possible answers. Try to find at least one.

## ---
## Define the path
## ---
process.p = cms.Path(
) # empty skeleton

### ===========
### PAT trigger
### ===========

## --
## Switch on
## --
from import switchOnTrigger
switchOnTrigger( process, sequence = 'p' ) # overwrite sequence default "patDefaultSequence", since it is not used in any path

## --
## Modify configuration according to your needs
## --
# add L1 algorithms' collection
process.patTrigger.addL1Algos     = cms.bool( True ) # default: 'False'
# add L1 objects collection-wise
process.patTrigger.l1ExtraMu      = cms.InputTag( 'l1extraParticles', ''           , 'RECO' )
process.patTrigger.l1ExtraNoIsoEG = cms.InputTag( 'l1extraParticles', 'NonIsolated', 'RECO' )
process.patTrigger.l1ExtraIsoEG   = cms.InputTag( 'l1extraParticles', 'Isolated'   , 'RECO' )
process.patTrigger.l1ExtraCenJet  = cms.InputTag( 'l1extraParticles', 'Central'    , 'RECO' )
process.patTrigger.l1ExtraForJet  = cms.InputTag( 'l1extraParticles', 'Forward'    , 'RECO' )
process.patTrigger.l1ExtraTauJet  = cms.InputTag( 'l1extraParticles', 'Tau'        , 'RECO' )
process.patTrigger.l1ExtraETM     = cms.InputTag( 'l1extraParticles', 'MET'        , 'RECO' )
process.patTrigger.l1ExtraHTM     = cms.InputTag( 'l1extraParticles', 'MHT'        , 'RECO' )
# save references to original L1 objects
process.patTrigger.saveL1Refs = cms.bool( True ) # default: 'False'
switchOnTrigger( process, sequence = 'p' )      # called once more to update the event content according to the changed parameters!!!
TIP You can also see the solution in

The special properties of this configuration are e.g:

  • that the same tool is called a second time in order to react on changes made in between;
  • that you start from an empty path, because the Python tool fills it automatically,
  • that in this case a functionality is switched on by adding a configuration parameter rather than changing a boolean;
  • that the proper usage of instance and process name in an input tag is essential.
These are still just examples, since the "speciality" of something also depends on what the user is already familiar with.

Analyse HLT information

In the lecture, you have seen a real life example of using the PAT trigger information. The problem of prescale changes during lumi sections has been shown with a histogram, where each bin contained the prescale value of a particular HLT path in an event.

red Exercise 10 b):
Reproduce the shown plot by filling a histogram with the prescale values of the HLT path HLT_HT450_v5 over 100 events.

As starting point, you can use the following code skeleton of an EDAnalyzer, save it as PhysicsTools/PatExamples/plugins/ in your CMSSW area:

#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Utilities/interface/InputTag.h"
#include "FWCore/Framework/interface/EDAnalyzer.h"
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"

#include "TH1D.h"

class PatTriggerAnalyzerPrescale : public edm::EDAnalyzer {

  /// default constructor
  explicit PatTriggerAnalyzerPrescale( const edm::ParameterSet & iConfig );
  /// default destructor

  /// everything that needs to be done before the event loop
  virtual void beginJob();
  /// everything that needs to be done during the event loop
  virtual void analyze( const edm::Event & iEvent, const edm::EventSetup & iSetup );
  /// everything that needs to be done after the event loop
  virtual void endJob(){};

  /// histogram
  TH1D * histo_;

  /// event counter
  Int_t bin_;

  /// HLT path name configuration parameter
  std::string pathName_;


#include "FWCore/ServiceRegistry/interface/Service.h"
#include "CommonTools/UtilAlgos/interface/TFileService.h"

#include "DataFormats/PatCandidates/interface/TriggerEvent.h"

using namespace pat;

PatTriggerAnalyzerPrescale::PatTriggerAnalyzerPrescale( const edm::ParameterSet & iConfig )
: bin_( 0 )
, pathName_( iConfig.getParameter< std::string >( "pathName" ) )

void PatTriggerAnalyzerPrescale::beginJob()
  edm::Service< TFileService > fileService;

  // Histogram definition for 100 events on the x-axis
  histo_ = fileService->make< TH1D >( "histo_", std::string( "Prescale values of " + pathName_ ).c_str(), 100, 0., 100.);

void PatTriggerAnalyzerPrescale::analyze( const edm::Event & iEvent, const edm::EventSetup & iSetup )
  // PAT trigger event
  edm::Handle< TriggerEvent > triggerEvent;
  iEvent.getByLabel( "patTriggerEvent", triggerEvent );

#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE( PatTriggerAnalyzerPrescale );

With this skeleton, the analyzer does basically nothing. The pat::TriggerEvent is opened, but not used in the event loop. You have to add lines to perform the task.
A few things are already defined:

  • The histogram exists and will be saved. You can possibly edit it, e.g by adding axis labels.
  • The class has a data member bin_, which is initialised to 0. The name suggests already, what this can be good for.
  • The name of the plugin to call in your configuration is set.

To run the analyser, you still need a configuration file. Also this is provided as a skeleton, you can save it as PhysicsTools/PatExamples/test/ in your CMSSW area:

import FWCore.ParameterSet.Config as cms

process = cms.Process( "TEST" )

process.load( "FWCore.MessageService.MessageLogger_cfi" )
process.options = cms.untracked.PSet(
    wantSummary = cms.untracked.bool( False )

process.source = cms.Source( "PoolSource",
    fileNames = cms.untracked.vstring(
process.maxEvents = cms.untracked.PSet(
    input = cms.untracked.int32( -1 )

process.TFileService = cms.Service( "TFileService",
    fileName = cms.string( 'analyzePatTriggerPrescale.root' )

process.p = cms.Path()

There exists no path yet. this is left to you.
TIP You saw from the constructor, that the name of the HLT path is configurable. Of course, this has consequences in the configuration file
Again, a few things are already defined:

  • The service to create your histogram file is already in the configuration.
  • The input file exists. It has been created from those events mentioned in the lecture. In this case, the trigger information was produced from a RAW data file. Find the corresponding configuration below :

import FWCore.ParameterSet.Config as cms

process = cms.Process( "PAT" )

## Options and Output Report
process.options = cms.untracked.PSet(
    wantSummary = cms.untracked.bool( True ),
    allowUnscheduled = cms.untracked.bool( True )

## Source
process.source = cms.Source( "PoolSource"
                             , fileNames = cms.untracked.vstring(
, lumisToProcess = cms.untracked.VLuminosityBlockRange(
process.maxEvents = cms.untracked.PSet(
  input = cms.untracked.int32( 100 )

## Geometry and Detector Conditions (needed for a few patTuple production steps)
process.load( "Configuration.StandardSequences.Services_cff" )
process.load( "Configuration.StandardSequences.Geometry_cff" )
process.load( "Configuration.StandardSequences.FrontierConditions_GlobalTag_cff" )
from Configuration.AlCa.GlobalTag import GlobalTag
process.GlobalTag = GlobalTag( process.GlobalTag, 'auto:com10' )
process.load( "Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff" )

# RAW to DIGI and RECO pre-requisites
process.load( "Configuration.StandardSequences.RawToDigi_Data_cff" )
process.load( "L1Trigger.Configuration.L1Reco_cff" )
process.p = cms.Path(
    * process.gtDigis
    * process.gtEvmDigis
    * process.scalersRawToDigi
    * process.L1Reco

## Output
from L1Trigger.Configuration.L1Trigger_EventContent_cff import L1TriggerAOD
process.out = cms.OutputModule(
, fileName       = cms.untracked.string( 'patTrigger_dataFromRAW.root' )
, SelectEvents   = cms.untracked.PSet(
    SelectEvents = cms.vstring(
, outputCommands = cms.untracked.vstring(
    'drop *'
process.outpath = cms.EndPath(

## PAT trigger
from import *
switchOnTrigger( process )
#switchOnTrigger( process, sequence = 'p', hltProcess = '*' ) # to update event content

And now you can look forward to your first PAT trigger plot...

Question Question 10 b)
What do you observe in the plot compared to what you expect?

You can get the solution and compare to your ideas as follows:

  // PAT trigger event
  edm::Handle< TriggerEvent > triggerEvent;
  iEvent.getByLabel( "patTriggerEvent", triggerEvent );

  // Get the HLT path
  const TriggerPath * path( triggerEvent->path( pathName_ ) );

  // Fill prescale factor into histogram
  if ( path ) histo_->SetBinContent( bin_, path->prescale() );

For the configuration file, you add

process.triggerAnalysisPrescale = cms.EDAnalyzer( "PatTriggerAnalyzerPrescale",
    pathName = cms.string( "HLT_HT450_v5" )

process.p = cms.Path(

Access L1 physics algorithms

We will now go through an example how to access L1 trigger bits via the pat::TriggerEvent.

Create a Template EDAnalyzer

To do this you can use the EDM tool mkedanlzr:

cd $CMSSW_BASE/src
mkdir PatExercise10c
cd PatExercise10c 
mkedanlzr -histo PatL1PhysAlgo

ALERT! By adding the -histo option to the mkedanlzr tool you get the EDAnalyzer ready up to the point to include histograms in your EDAnalyzer, which may be quite handy for you.
ALERT! We call our module PatL1PhysAlgo

We will now go through an example how to access L1 trigger bits via the pat::TriggerEvent.
As input file, you can either use the file patTuple_triggerOnly.root you have produced earlier.

Modify the EDAnalyzer source file

In this step modify the declaration part of your code (in the beginning of the file PatL1PhysAlgo/src/ and add the needed #include statements. You will need:

#include "DataFormats/PatCandidates/interface/TriggerEvent.h"
#include "DataFormats/Common/interface/RefVector.h"
#include <string>

Depending on your coding style, you might want to setup an edm::InputTag in your EDAnalyzer to make the trigger collection label of the pat::TriggerEvent configurable:

  • This goes into your class declaration:
edm::InputTag triggerEvent_;
  • This goes into your class constructor
triggerEvent_ = iConfig.getParameter< edm::InputTag >( "triggerEvent" );
  • This goes into your configuration file PatExercise10c/PatL1PhysAlgo/
process.demo.triggerEvent = cms.InputTag( 'patTriggerEvent' )

At this point you are ready to modify the analyze function of your EDAnalyzer. There you will need to get the edm::Handle on the trigger event information and run a loop over the different physics algo trigger bits, which are stored in there:

  • This goes into your analyze(...) function:
// PAT trigger information
  edm::Handle< pat::TriggerEvent > triggerEvent;
  iEvent.getByLabel( triggerEvent_, triggerEvent );

green Exercise 10 c):
Access information about the L1 physics algorithms .

Question Question 10 c)
Which methods of the pat::TriggerEvent return lists of L1 physics algorithms?
Have a look therefore to SWGuidePATTrigger, pat::TriggerEvent.

// algoBits is defined as a RefVector (think as it was a vector of pointers). It points to TriggerAlgorithm objects
  pat::TriggerAlgorithmRefVector algoBits = triggerEvent->physAlgorithms();

In order to use this function, it first must be made accessible from the package. You have to add

<use name="DataFormats/PatCandidates"/>
to PatExercise10c/PatL1PhysAlgo/BuildFile.xml.

You are now ready to loop over the L1 trigger information.

pat::TriggerAlgorithmRefVector::const_iterator itrBit = algoBits.begin();   
  int nbit = 0;
  while ( itrBit != algoBits.end()) {
    // put here the logic of your analysis (compare and check decision)
    // consult the documentation for the TriggerAlgorithm class        

To select a particular algorithm, you can follow the same strategy to make it configurable as for the PAT trigger event

  • This goes into your class declaration:
std::string l1algoName_;
  • This goes into your class constructor
l1algoName_ = iConfig.getParameter< std::string >( "l1algoName" );
  • This goes into your configuration file PatExercise10c/PatL1PhysAlgo/
process.demo.l1algoName = cms.string( 'L1_SingleMu12' ) # example algorithm name

Look into the pat::TriggerAlgorithm documentation for the adequate methods to access L1 algorithms' information: Here an example of what you can do inside your loop (simple print-out):

if ( (*itrBit)->name() ) == 0 )
      std::cout << "looping over algoBits: " << nbit << '\t' 
                << (*itrBit)->bit() << '\t' 
                << (*itrBit)->name() << '\n'
                << (*itrBit)->logicalExpression() << '\n'
                << (*itrBit)->conditionKeys().size() << '\t'
                << (*itrBit)->gtlResult() << '\t'
                << (*itrBit)->decision() << '\t'
                << (*itrBit)->decisionBeforeMask() << '\t'
                << (*itrBit)->decisionAfterMask() << '\t'
                << '\n';         

ALERT! Note:
In case of problems don't hesitate to contact the PAT support. Having successfully finished Exercise 10 you might want to proceed to Exercise 11 of the SWGuidePAT to learn more about the PAT support of matching trigger objects to offline reconstructed objects in your analysis. For an overview you can go back to the WorkBookPATTutorial entry page.

Review status

Reviewer/Editor and Date (copy from screen) Comments
RogerWolf - 13 March 2011 Added color coding.
VolkerAdler- 30 June 2012 Update for July 2012 tutorial
VolkerAdler- 3 December 2012 Update for Dec. 2012 tutorial
VolkerAdler- 20 December 2013 Update for July 2013 tutorial
PhatSrimanobhas- 2 July 2014 Update for July 2014 tutorial

Responsible: VolkerAdler

Topic attachments
I Attachment History Action Size Date Who Comment
Cascading Style Sheet filecss tutorial.css r1 manage 0.2 K 2010-06-16 - 17:17 RogerWolf  
Edit | Attach | Watch | Print version | History: r98 < r97 < r96 < r95 < r94 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r98 - 2015-07-02 - JunghwanGOH
    • 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-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback