From 6cf29f873995a62f7784ba03825669d141076df1 Mon Sep 17 00:00:00 2001 From: Stefan Wunsch <stefan.wunsch@cern.ch> Date: Thu, 30 Aug 2018 10:53:56 +0200 Subject: [PATCH] [RDF,Tutorial] Add tutorial processing NanoAOD-like file producing dimuon spectrum from Run2011A CMS OpenData --- .../dataframe/df102_NanoAODDimuonAnalysis.C | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 tutorials/dataframe/df102_NanoAODDimuonAnalysis.C diff --git a/tutorials/dataframe/df102_NanoAODDimuonAnalysis.C b/tutorials/dataframe/df102_NanoAODDimuonAnalysis.C new file mode 100644 index 00000000000..14e7ee10b98 --- /dev/null +++ b/tutorials/dataframe/df102_NanoAODDimuonAnalysis.C @@ -0,0 +1,122 @@ +/// \file +/// \ingroup tutorial_dataframe +/// \notebook -nodraw +/// This tutorial illustrates how NanoAOD files can be processed with ROOT +/// dataframes. The NanoAOD-like input file is filled with events from +/// CMS OpenData containing muon candidates from 2011 data +/// (DOI: 10.7483/OPENDATA.CMS.RZ34.QR6N). The script matches muon pairs +/// and produces an histogram of the dimuon mass spectrum showing resonances +/// up to the Z mass. +/// +/// \macro_code +/// +/// \date August 2018 +/// \author Stefan Wunsch + +#include "ROOT/RDataFrame.hxx" +#include "ROOT/RVec.hxx" +#include "TCanvas.h" +#include "TH1D.h" +#include "TLatex.h" +#include "TLorentzVector.h" +#include "TStyle.h" + +using namespace ROOT::VecOps; + +void DrawSpectrum(TH1D& h); + +void df102_NanoAODDimuonAnalysis() +{ + // Enable implicit multi-threading + ROOT::EnableImplicitMT(); + + // Create dataframe from NanoAOD file + ROOT::RDataFrame df("Events", "NanoAOD_DoubleMuon_CMS2011OpenData.root"); + + // Select events with more than two muons + auto df_filtered = df.Filter("nMuon>=2", "More than two muons"); + + // Find muon pair with highest pt and opposite charge + auto find_pair = [](const RVec<float> &pt, const RVec<int> &charge) { + // Get indices that sort the muon pts in descending order + const auto idx = Reversed(Argsort(pt)); + + // Find muon with second-highest pt and opposite charge + const auto i1 = idx[0]; + for (size_t i = 1; i < idx.size(); i++) { + const auto i2 = idx[i]; + if (charge[i1] != charge[i2]) { + return RVec<size_t>({i1, i2}); + } + } + + // Return empty selection if no candidate matches + return RVec<size_t>({}); + }; + auto df_pair = df_filtered.Define("Muon_pair", find_pair, {"Muon_pt", "Muon_charge"}) + .Filter("Muon_pair.size() == 2", "Found valid pair"); + + // Compute invariant mass of the di-muon system + auto compute_mass = [](RVec<float> &pt, RVec<float> &eta, RVec<float> &phi, + RVec<float> &mass, RVec<size_t> &idx) { + // Compose four-vectors of both muons + TLorentzVector p1; + const auto i1 = idx[0]; + p1.SetPtEtaPhiM(pt[i1], eta[i1], phi[i1], mass[i1]); + + TLorentzVector p2; + const auto i2 = idx[1]; + p2.SetPtEtaPhiM(pt[i2], eta[i2], phi[i2], mass[i2]); + + // Add four-vectors to build di-muon system and return the invariant mass + return (p1 + p2).M(); + }; + auto df_mass = df_pair.Define("Dimuon_mass", compute_mass, + {"Muon_pt", "Muon_eta", "Muon_phi", "Muon_mass", "Muon_pair"}); + + // Plot histogram of di-muon mass spectrum + auto h = df_mass.Histo1D({"Dimuon_mass", "Dimuon_mass", 20000, 0.25, 300}, "Dimuon_mass") + .GetValue(); + + // Draw histogram + DrawSpectrum(h); +} + +int main() +{ + df102_NanoAODDimuonAnalysis(); +} + +void DrawSpectrum(TH1D& h) +{ + gStyle->SetOptStat(0); + gStyle->SetTextFont(42); + TCanvas c("c", "c", 800, 600); + c.SetLogx(); + c.SetLogy(); + + h.SetTitle(""); + h.GetXaxis()->SetTitle("Invariant di-muon mass (GeV)"); + h.GetXaxis()->SetTitleSize(0.04); + h.GetYaxis()->SetTitle("N_{Events}"); + h.GetYaxis()->SetTitleSize(0.04); + h.Draw(); + + TLatex label; + label.SetNDC(true); + label.DrawLatex(0.175, 0.740, "#eta"); + label.DrawLatex(0.205, 0.785, "#rho,#omega"); + label.DrawLatex(0.270, 0.750, "#phi"); + label.DrawLatex(0.400, 0.800, "J/#psi"); + label.DrawLatex(0.415, 0.680, "#psi'"); + label.DrawLatex(0.485, 0.760, "Y(1,2,3S)"); + label.DrawLatex(0.755, 0.620, "Z"); + + label.DrawLatex(0.170, 0.350, "#bf{CMS Open Data}"); + label.DrawLatex(0.170, 0.275, "#bf{#sqrt{s} = 7 TeV}"); + label.DrawLatex(0.170, 0.200, "#bf{L_{int} = 2.4 fb^{-1}}"); + label.SetTextSize(0.032); + label.DrawLatex(0.10, 0.920, "Run2011A Double Muon Dataset (DOI: 10.7483/OPENDATA.CMS.RZ34.QR6N)"); + + c.SaveAs("nanoaod_dimuon_spectrum.pdf"); +} -- GitLab