NanoAOD Documentation

NanoAOD format

NanoAOD format consists of an Ntuple like format, readable with bare root and containing the per-event information that is needed in most generic analyses. A NanoAOD is not a CMSSW EDM file but several EDM features are available in this simplified format too.

The size per event of NanoAOD is order of 1Kb, they can be centrally produced in ~1-2 week time, central production can be triggered often if many new features are made available in "hot periods". Users can easily extend NanoAOD for their specific study making a private production when needed (suggested for specific studies on samples that are not too large or for some special needs) or can ask for new features inclusion in the central format (suggested when need to run on multi billion events)

A NanoAOD file contains a main TTree named Events and some additional TTrees for run, lumi and metadata.

The Events TTree

The main TTree contains only scalar branches or simple array branches. No special dataformat is needed to read NanoAODs. Physics objects features are grouped via naming conventions and by sharing the same array dimensionality.

As an example there is a branch named Muon_pt[nMuon] and a branch named Muon_eta[nMuon], both are arrays of length nMuon. Access as whole objects can be obtained with light frameworks (see e.g. the NanoAOD -Tools below)

References across objects are implemented via branches with idx suffix that are just bare indices that contains information about the collection they point to, e.g. Electron_jetIdx contains information about the jet, if available that contains a given electron. A value of -1 means the ref is null, a value i >= 0 means that given Electron is associated to the i-th object in the Jet collection. Another example Jet_genJetIdx is the index to the GenJet collection. The pointer could also point outside the boundary of the collection if some elements in the tail of the collection are dropped. For example before accessing the GenJet associated to a Jet one should verify that 0<= Jet_genJetIdx < nGenJet.

HLT bits are automatically generated based on HLT bits available in the input file. Each time files are merged (in CMSSW or via the utility) if the list of bits is not matching the new/old bits are zero-filled so that the branches are properly aligned.

Object systematic uncertainties (e.g. all JES variations) are not stored persistently but, instead, the per-event information needed to compute those corrections is saved.

Many variables are stored with limited precision (i.e. less than 32bits float) by zeroing a given number of bits in the float mantissa (this results in a higher compression when stored on disk).

No skimming is applied at production level.

Some linking to gen and trigger objects is available. No cleaning is applied but objects are cross referenced (with indices, see above). The cross referencing is based on common PF constituents, not on DeltaR. DeltaR matching is less accurate and can be reproduced from NanoAOD if needed, while PF matching can only be done while reading MiniAOD. Predefined clean bitmasks can be used to store persistently a given cleaning choice (e.g. specific of a whole PAG), so that the user can clean by simply checking the proper bit.

Specific information on some branches/objects

  • Jets are corrected to latest available JECs and provided with latest available JetID, PU ID, b-tag and QGL.
  • No systematic variations of JECs are stored, but the quantities (rho, area, pt, eta) needed to recompute JECs or JEC systematic variations are available. Dedicated nanoAOD-tools modules exist to compute those quantities.
  • b-jet energy regression, developed for final states with one or more H->bb, is also available.
  • Jets of MC samples are not smeared (dedicated nanoAOD-tools modules exist to apply the smearing).



..e.g. explain the bitmask...


Trigger bits information is available for all trigger in the input files. If multiple files are given in input with different trigger bits, the bits not available in some events are filled with zeros. When merging two nanoaod file with the same algorithm to fill missing trigger bits is used (i.e. the output file will have zeros for events that had a given trigger bit not available)

Trigger objects are stored in nanoaod for some filters as defined here, if you need some additional object p4 to be stored please open an issue.

Generator, dressed leptons, LHE

Several collections are available for gen level information:

  • a subset of gen particle selected according to this pruner configuration
  • dressed lepton are also available as configured here
  • gen jets with pt > 10 are stored. Parton and Hadron flavour as well as link to gen jet is available in jets
  • Some LHE information is stored (see here)


The nominal generator-level weight is stored in branches genWeight and Generator_weight, which both contain the same value obtained from GenEventInfoProduct::weight() (here and here). This is typically the product of the nominal weight from LHE (if available) and the nominal weight from Pythia. The nominal LHE weight is available as LHEWeight_originalXWGTUP, filled from LHEEventProduct::originalXWGTUP() (here).

..e.g. explain the PDF weights...

The Other TTrees

Content auto-documentation

Each branch has built-in documentation distributed with every file, if you want to get the description of the content of a branch named e.g. SoftActivityJetNjets5, it is enough to do

root [1] Events->GetBranch("SoftActivityJetNjets5")->GetTitle()
(const char *) "number of soft activity jet pt, pt >5"
root [2] 

A dump of the documentation of content for different releases is available here (NB: the actual content of a branch could dependent on the input sample for some generator quantities):

NanoAOD -Tools Documentation

NanoAOD -Tools provide a simple and lightweight python post-processing framework for fast skimming, analysis and computation of derived quantities.

NanoAOD -Tools should contain code implementation of NanoAOD ready "POG recipes" so that no one has to translate from twiki to code and the code is already available to access the data in NanoAOD format.

We anticipate that many analysis would run skimming and computation of derived quantities or systematic variations in a single step. Such step can be easily implemented with the NanoAOD -Tools postprocessors.

Existing modules in NanoAOD -Tools


  • PU weighting

POG specific

  • BTV: tool to compute scale factors
  • JME: JEC uncertainties, JER smearing with MET propagation
  • MUO: momentum calibration (to be implemented)

How to run via crab on NanoAOD using NanoAOD -Tools

Such step can also be run on crab using the example give in PhysicsTools /NanoAODTools/crab/

It is sufficient to edit

replacing the settings of the PostProcessor with the ones you want

Quickly make plots with NanoAODTools postprocessor

The postprocessor can be used also to simply make histograms. Quick recipe for impatient user:

cmsrel CMSSW_9_4_11_cand1
cd CMSSW_9_4_11_cand1/src
git cms-init   #not really needed unless you later want to add some other cmssw stuff
git clone PhysicsTools/NanoAODTools
scram b
voms-proxy-init -voms cms

cd PhysicsTools/NanoAODTools/python/postprocessing/examples/

More information

now the post-processing engine allows you to recalculate and overwrite an already existing branch/variable, but be careful if you managed to recalculate an already existing variable in the Events tree, you have to keep the same type of the variable, for examples if you would like to overwrite the variable "Muon_mediumId" which is of type "Bool" you should do that by assigning the recomputed variable to the type Bool as well.

This is well discussed in :

issue 81, and solved by PR 84

Presentations on NanoAOD format

see presentation in the PPD general meeting of 21/09/2017 and PPD workshop

Centrally produced samples

NanoAOD are centrally produced. Available campaigns are

  • 05Feb2018 - 80X samples (2016 run, data and MC)
  • 12Apr2018 - 94X miniAODV2 samples (MC for 2017 run)
  • 31Mar2018 - 94X miniAODV2 samples (data of 2017 run)

How to check out the code and produce ntuples yourself:

In general you should not need to produce nanoAOD yourself. If there is a missing variable in standard centrally-produced nanoAOD we encourage to request the addition of such variable via a PR or Issue on nanoaod github.

You may want to make ntuples yourself for testing new features, for signal samples with special additional variables or for other particular workflows.

Recipe for the current HEAD of NanoAOD:

From CMSSW_9_4_X a version of NanoAOD is included in CMSSW. For a basic test you can use that one, for the latest version and developments please merge the HEAD of the repository as shown below.

If you want to integrate a new feature, please start with the master-cmsswmaster branch. The new feature will then be rebased (if code functionality allows that) on the master-102X and master-106X branches during the review of the pull request.

* NanoAOD is supposed to run on all supported data (e.g. MINIAOD files created with CMSSW_9_4_X) from the same CMSSW area. You will just have to configure the correct era in the cmsDriver command.*

* Support of running NanoAOD production from a 9_4_X area has been dropped. The currently supported releases are 10_2_X, 10_6_X and 11_0_X ones.*

# run the commands below in the src/ directory of a
# CMSSW_10_2_16_UL resp. CMSSW_10_6_4_patch1 resp. CMSSW_11_0_0_pre10 release area

git cms-merge-topic cms-nanoAOD:master-102X resp. master-106X resp. cms-nanoAOD:master-cmsswmaster
# create a branch directly on the nanoAOD branch, skipping the unnecessary merge commit from cms-merge-topic
git checkout -b nanoAOD cms-nanoAOD/master-102X resp. cms-nanoAOD/master-106X resp. cms-nanoAOD/master-cmsswmaster

# VERY TEMPORARY AND ONLY FOR DEVELOPMENT/TESTS (do not commit it to the nanoAOD repository):
# IN 10_2_X ONLY:
git cms-merge-topic 28095
git cms-merge-topic 28135
# IN 10_6_X ONLY:
git cms-merge-topic 28094
git cms-merge-topic 28136

# get also the support library if you want to use it
git clone PhysicsTools/NanoAODTools

# compile it
scram build

See below for how to generate configuration files with cmsDriver

Running on various datasets from past campaigns

In order to run NANOAOD production, this are the base cmsDriver command for MC and data: myNanoProdMc -s NANO --mc --eventcontent NANOAODSIM --datatier NANOAODSIM  --no_exec  --conditions MyGlobalTag --era MyEraModifiers myNanoProdData -s NANO --data --eventcontent NANOAOD --datatier NANOAOD  --no_exec  --conditions MyGlobalTag --era MyEraModifiers

You should replace MyGlobalTag with the GT you want to use for production (it is used, for instance, to correct jets). You must provide this! If unsure, as a starting point, you can use the same one used in MINIAOD production, that is present in the sample name. Please refer to and for more updated versions.

MyEraModifiers has to be replaced by one of the following strings (choose the line that fits your use case):

--era Run2_2016,run2_miniAOD_80XLegacy: for 2016 80X data (07Aug17) and RunIISummer16MiniAODv2 MC

--era Run2_2016,run2_nanoAOD_94X2016: for 2016 94X data (17Jul2018) and RunIISummer16MiniAODv3 MC

--era Run2_2017,run2_nanoAOD_94XMiniAODv1: for 2017 94X MiniAODv1 samples

--era Run2_2017,run2_nanoAOD_94XMiniAODv2: for 2017 94X MiniAODv2 samples (including 31Mar2018 data)

--era Run2_2018,run2_nanoAOD_102Xv1: for all 2018 10XY samples


Moreover, in order to avoid segfault errors in the output module when producing flat ntuples, the following options should be added to the cmsDriver command:

--customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"
as it is done in the merge jobs in central production (Configuration/DataProcessing/python/

Instructions for NanoAODv5 production


Run from a CMSSW_10_2_15 vanilla area, without merging any newer version of the NanoAOD package (e.g. master-102X continues to evolve with time!)

JEC in use are:

  • 2016: Summer16_07Aug2017_V11
  • 2017: Fall17_17Nov2017_V32
  • 2018: Autumn18_V8

2016 RunIISummer16MiniAODv3 MC: (change era modifier if you run on RunIISummer16MiniAODv2 80X MiniAOD) myNanoProdMc2016 -s NANO --mc --eventcontent NANOAODSIM --datatier NANOAODSIM  --no_exec  --conditions 102X_mcRun2_asymptotic_v7 --era  Run2_2016,run2_nanoAOD_94X2016 --customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"

2016 data (Run2016*-17Jul2018*): myNanoProdData2016 -s NANO --data --eventcontent NANOAOD --datatier NANOAOD  --no_exec  --conditions 102X_dataRun2_v11 --era Run2_2016,run2_nanoAOD_94X2016 --customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"

2017 MC: (change era modifier if you run on RunIIFall17MiniAOD v1 samples) myNanoProdMc2017 -s NANO --mc --eventcontent NANOAODSIM --datatier NANOAODSIM  --no_exec  --conditions 102X_mc2017_realistic_v7 --era Run2_2017,run2_nanoAOD_94XMiniAODv2 --customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"

2017 data (Run2017*-31Mar2018*): myNanoProdData2017 -s NANO --data --eventcontent NANOAOD --datatier NANOAOD  --no_exec  --conditions 102X_dataRun2_v11 --era Run2_2017,run2_nanoAOD_94XMiniAODv2 --customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"

2018 MC: myNanoProdMc2018 -s NANO --mc --eventcontent NANOAODSIM --datatier NANOAODSIM  --no_exec  --conditions 102X_upgrade2018_realistic_v19 --era Run2_2018,run2_nanoAOD_102Xv1 --customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"

2018 ABC data: myNanoProdData2018ABC -s NANO --data --eventcontent NANOAOD --datatier NANOAOD  --no_exec  --conditions 102X_dataRun2_v11 --era Run2_2018,run2_nanoAOD_102Xv1 --customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"

2018 D data: myNanoProdData2018D -s NANO --data --eventcontent NANOAOD --datatier NANOAOD  --no_exec  --conditions 102X_dataRun2_Prompt_v14 --era Run2_2018,run2_nanoAOD_102Xv1 --customise_commands="process.add_(cms.Service('InitRootHandlers', EnableIMT = cms.untracked.bool(False)))"

Where to get the ntuples

New test ntuples (CMSSW_9_4_X)

Older test ntuples are produced via crab (see below if you want to do it yourself) and you can have a look/play with them at the following links

NB: this is not the way NanoAOD are meant to be produced. Production will soon be handled centrally by computing

How to make NanoAOD via crab

While central production will take care soon of making nanoAOD for all CMS samples there are two use cases for NanoAOD made with crab:

  • test NanoAOD format before production is ready to handle them (expected late 2017)
  • add analysis specific information in the format for a few samples (e.g. signal samples), i.e. run your customized version of NanoAOD

Example config is available here: PhysicsTools /NanoAOD/test/

It is important to modify the input configuration so that it runs a single NanoAODOutputModule and add the following parameter as configuraion of the outputmodule.

    fakeNameForCrab =cms.untracked.bool(True),

How to run via crab on NanoAOD using NanoAOD -Tools

NanoAOD -tools provide a post processing framework for simple and fast skimming and computation of derived quantities.

Such step can also be run on crab using the example give in PhysicsTools /NanoAODTools/crab/

It is sufficient to edit

replacing the settings of the PostProcessor with the ones you want

Quickly make plots with NanoAODTools postprocessor

The postprocessor can be used also to simply make histograms. Quick recipe for impatient user:

cmsrel CMSSW_9_4_11_cand1
cd CMSSW_9_4_11_cand1/src
git cms-init   #not really needed unless you later want to add some other cmssw stuff
git clone PhysicsTools/NanoAODTools
scram b
voms-proxy-init -voms cms

cd PhysicsTools/NanoAODTools/python/postprocessing/examples/

How to contribute and request changes

You can contribute to NanoAOD the same way you contribute to the rest of CMSSW via github. The only difference is that NanoAOD related PR should be first submited to fork and then from there they will be collected, tested and pushed in main CMSSW via central Pull Requests. You should setup your area as indicated here.

If you want to help but do not know what you can do, have a look at the issues for NanoAOD and NanoAOD-Tools and tell us there that you are going to implement some of the missing features or fix some of the open issues.

If you want to add something first create an issue under (unless a similar issue doesn't exist already, in that case comment in the existing issue) clearly telling what you want to add/change and what is the use case.

So the workflow to contribute is something like:

  • set up a recent CMSSW release and take the appropriate branch of cms-nanoAOD/cmssw (as explained earlier in this twiki)
  • add/modify your content, mostly editing PhysicsTools /NanoAOD/python/ and PhysicsTools /NanoAOD/plugins/
  • if your code adds some variable, run the script on a file having the new variable to update the DQM configuration
    • -d -u nano_file_mc.root
    • if necessary, edit the file (e.g. to fix the range or binning of the plot; do not reoder the lines), and then re-run the script again so that the file is formatted properly (e.g. spacing, decimals, etc.)
  • push the code in your cmssw fork on github (please push only the stuff you need, without for example the merge commits to more recent versions of CMSSW than the one used in cms-nanoAOD master branch)
  • make a PR against cms-nanoAOD/cmssw
    • NB: most likely github offers you as default to make a PR against central CMSSW, please be sure you do not by changing the "base fork:" from cms-sw/cmssw to cms-nanoAOD/cmssw
  • mention in the PR the issue such PR is addressing (you should have created an issue first unless the change is trivial)

-- AndreaRizzi - 2017-09-21

Edit | Attach | Watch | Print version | History: r59 < r58 < r57 < r56 < r55 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r59 - 2019-10-11 - MarcoPeruzzi
    • 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