{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Z to leptons analysis with ATLAS open data and ADL/CutLang\n", "\n", "This is an exercise showing a simple analysis exploring the Z -> 2 lepton final state, focusing on the e+e- and μ+μ- channels. The analysis aims to explore the kinematics of Z --> e+e- OR μ+μ- events.\n", "\n", "The analysis is performed based on ATLAS run1 open data MC ntuples. The below cell retrieves such an ntuple.\n", "\n", "The analysis consists of two parts:\n", "1. Applying some event selection to the input events and making distributions. This part is performed using a special language called ADL, and via a software called CutLang that can read and process ADL.\n", "2. Drawing plots produced by the previous step. This part is performed using ROOT (with Python syntax). ROOT is the main analysis software used at CERN.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!wget --progress=dot:giga http://opendata.atlas.cern/release/samples/MC/mc_105987.WZ.root\n", "// Get the ROOT file containing the Z -> eemumu background events" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What are ADL and CutLang?\n", "\n", "(More information on [cern.ch/adl](cern.ch/adl))\n", "\n", "LHC data analyses are usually performed using complex analysis frameworks written in general purpose languages like C++ and python. \n", "But this method has a steep learning curve, as even the simplest tasks could be coded in a complicated way, and it is not straightforward to understand the code, make changes or additions.\n", "However there is another emerging alternative which allows to decouple physics content from the technical code and write analyses with a simple, self-describing syntax. **Analysis Description Language (ADL)** is a HEP-specific analysis language developed with this purpose. \n", "\n", "A HEP analysis includes 3 main parts:\n", " * Object definitions: Which objects are used? e.g. electrons? muons? jets? What are the selections applied on these?\n", " * Event variable definitions: Are there event-wide variables used such as a invariant mass or a transverse mass? How are they calculated?\n", " * Event selections: What selections do we apply on events, for example, to enhance the signal and reduce the backgrounds? Are there more than one event selections? How are they defined?\n", "\n", "ADL consists of blocks separating object, variable and event selection definitions for a clear separation of analysis components. Blocks have a keyword-expression structure. Keywords specify analysis concepts and operations. Syntax includes mathematical and logical operations, comparison and optimization operators, reducers, 4-vector algebra and HEP-specific functions (dφ, dR, …).\n", "\n", "ADL is designed with the goal to be self-describing, so especially for simple cases like in this example, one does not need to read syntax rules to understand an ADL description. However if you are interested, the set of syntax rules can be found [here]( https://twiki.cern.ch/twiki/bin/view/LHCPhysics/ADL).\n", "\n", "Once an analysis is written it needs to be run on events. This is achieved by **CutLang** , the runtime interpreter who reads and understands the ADL syntax and runs it on events. CutLang is also a framework which aturomatically handles many tedious tasks as reading input events, writing output histograms, etc. CutLang can be run on various environments such as linux, mac, conda, docker, jupyter, etc. \n", "\n", "In case you are interested to learn more on CutLang, please see the [CutLang github](https://github.com/unelg/CutLang)\n" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## Writing the analysis with ADL and running with CutLang\n", "\n", "**Writing the analysis with ADL:** In the following cell, part of the analysis is written using the ADL syntax. However there are some parts missing. Please follow the instructions in the comments to complete the missing parts. If you feel adventurous, you could modify the object or event selections, add new variables or new histograms.\n", "\n", "**Running the analysis with CutLang:** Executing the cell will run the analysis on both the signal and background events. The run parameters are given in the first line of the cell:\n", " * file : input root file\n", " * filetype : input event format (do not change!)\n", " * adlfile : the name we use for labeling the analysis \n", " * events : number of events used from each file\n", " * verbose : frequency of processed event numbers written in output text\n", "\n", "NOTE: When running jupyter/binder via direct link, if your run does not complete due to memory issues, please reduce the number of events via the \"events\" parameter.\n", "\n", "**Analysis output:** Running the analysis will produce two outputs:\n", " * Text output shown cell output: This includes \"cutflows\" for each region, i.e. the selections applied and how many events survive the various selections. Histograms are also listed. You should see a separate output for each ROOT file that is run.\n", " * ROOT output: One ROOT file called histoOut-\\-\\.root that includes all the histograms produced by the analysis. These ROOT files will be used in the next step." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "%%cutlang file=mc_105987.WZ.root filetype=ATLASOD adlfile=ZtoLL events=100000 verbose=10000\n", "\n", "# ADL file for Z->ee/mumu analysis\n", "\n", "# Object selection\n", "# Take input electrons, labeled \"ele\" and obtain a set of selected electrons \"elesel\"\n", "object goodEle\n", " take ele # start with initial electron set\n", " select pT(ele) > 25 # apply a cut on transverse momentum\n", " select abs(eta(ele)) < 2.5 # apply a cut on pseudorapidity\n", "\n", "# Take input muons, labeled \"muo\" and obtain a set of selected muons \"muosel\"\n", "object goodMuo\n", " take muo # start with initial muon set\n", " select pT(muo) > 25 # apply a cut on transverse momentum\n", " select abs(eta(muo)) < 2.5 # apply a cut on pseudorapidity\n", "\n", "object goodLeptons : Union (goodEle, goodMuo)\n", "\n", "# Useful definitions\n", "define mLL = m(goodLeptons[0] goodLeptons[1])\n", "define elePDGid = 11 \n", "define muoPDGid = 13\n", "\n", " \n", "# Event selection\n", "\n", "algo Zll\n", " select ALL #cut0: count all events\n", " histo hneinp, \"number of input electrons\", 6, 0, 6, size(ele)\n", " histo hnesel, \"number of selected electrons\", 6, 0, 6, size(goodEle)\n", " histo hnminp, \"number of input muons\", 6, 0, 6, size(muo)\n", " histo hnmsel, \"number of selected muons\", 6, 0, 6, size(goodMuo)\n", " histo hnleps, \"number of selected lepts\", 6, 0, 6, size(goodLeptons)\n", " histo hnenminp, \"number of input electrons vs muons\", 6, 0, 6, 6, 0, 6, size(ele), size(muo)\n", " histo hnenmsel, \"number of selected electrons vs muons\", 6, 0, 6, 6, 0, 6, size(goodEle), size(goodMuo) \n", " select Size(ele) + Size(muo) > 1 #cut1: We just want events with at least two leptons\n", " select Size(goodLeptons) == 2 #cut2: We want, in fact, exactly two good leptons\n", " select q(goodLeptons[0]) * q(goodLeptons[1]) == -1 #cut3: The two selected leptons must have opposite charge\n", " select pdgID(goodLeptons[0])+pdgID(goodLeptons[1])==0 #cut4: The two selected leptons have the same flavor\n", " histo hZllselbc, \"Z(->LL,selected) candidate mass (GeV)\", 50, 50, 150, mLL\n", " select abs(mLL - 91.18) < 20 #cut5: The absolute value of the difference between the \n", "# two leptons and the known Z boson mass (mz) must be less than 20 GeV \n", " histo hZllselac, \"Z(->LL,selected,massWindow) candidate mass (GeV)\", 50, 50, 150, mLL\n", " select abs(pdgID(goodLeptons[0])) == elePDGid ? hMZee,\"Inv.Mass of Z (Zee)\",50,50.0,150.0,mLL : ALL\n", " select abs(pdgID(goodLeptons[0])) == muoPDGid ? hMZmm,\"Inv.Mass of Z (Zmm)\",50,50.0,150.0,mLL : ALL\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Checking the analysis output with ROOT\n", "\n", "Now let's make some plots using the ROOT package in python (which is widely used at CERN).\n", "Instructions are shown within comments in the following cells.\n", "\n", "What to do:\n", " * Compare some of the histograms you made:\n", " * Electrons vs. muons\n", " * Initial leptons vs. selected leptons\n", " * Z candidate invariant mass before and after mass window selection\n", " * Z candidate from selected electrons vs selected muons" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python\n", "# Let's start with importing the needed modules\n", "from ROOT import gStyle, TFile, TH1, TH1D, TH2D, TCanvas, TLegend, TColor\n", "\n", "# Now let's set some ROOT styling parameters:\n", "# You do not need to know what they mean, but can directly use these settings\n", "\n", "gStyle.SetOptStat(0)\n", "gStyle.SetPalette(1)\n", "\n", "gStyle.SetTextFont(42)\n", "\n", "gStyle.SetTitleStyle(0000)\n", "gStyle.SetTitleBorderSize(0)\n", "gStyle.SetTitleFont(42)\n", "gStyle.SetTitleFontSize(0.055)\n", "\n", "gStyle.SetTitleFont(42, \"xyz\")\n", "gStyle.SetTitleSize(0.5, \"xyz\")\n", "gStyle.SetLabelFont(42, \"xyz\")\n", "gStyle.SetLabelSize(0.45, \"xyz\")\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python\n", "# Let's open the output file produced by CutLang: \n", "# (If you changed the adlfile option when running cutlang, you will need to change the file names)\n", "f = TFile(\"histoOut-ZtoLL-mc_105987.root\")\n", "# We can see what is inside the signal file:\n", "f.ls()\n", "# There should be a directory (TDirectoryFile) per selection algorithm also known as a region." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python\n", "# Let's see what is available:\n", "f.cd(\"Zll\")\n", "f.ls()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python\n", "\n", "# Get the histograms out of the file\n", "\n", "# lepton counts:\n", "hneinp = f.Get(\"Zll/hneinp\")\n", "hnminp = f.Get(\"Zll/hnminp\")\n", "hnesel = f.Get(\"Zll/hnesel\")\n", "hnmsel = f.Get(\"Zll/hnmsel\")\n", "hnenminp = f.Get(\"Zll/hnenminp\")\n", "hnenmsel = f.Get(\"Zll/hnenmsel\")\n", "# Z reconstruction before cut\n", "hZllselbc = f.Get(\"Zll/hZllselbc\")\n", "# Z reconstruction after cut\n", "hZllselac = f.Get(\"Zll/hZllselac\")\n", "# Z from electrons only\n", "hMZee = f.Get(\"Zll/hMZee\")\n", "# Z from muons only\n", "hMZmm = f.Get(\"Zll/hMZmm\")\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python\n", "############ LETS SEE 1D MULTIPLICITIES AND HOW TO MAKE NICE PLOTS\n", "\n", "# In order to be able to make many plots, let's define two generic histogrms to which we can \n", "# assign any of the histograms above:\n", "h1 = hneinp\n", "h2 = hnminp\n", "\n", "# Now we format the histograms: lines, colors, axes titles, etc.. \n", "# You do not need to learn the commands here unless you are really curious.\n", "# Otherwise just execute the cell.\n", "\n", "# Color numbers can be retrived from https://root.cern.ch/doc/master/classTColor.html\n", "# (check for color wheel)\n", "h1.SetLineColor(600) # kBlue\n", "h2.SetLineColor(416+2) # kGreen + 2\n", "\n", "# Make the x-axis title:\n", "title = h1.GetTitle()\n", " \n", "h1.SetTitle(\"\")\n", "h1.GetXaxis().SetTitle(title)\n", "h1.GetXaxis().SetTitleOffset(1.25)\n", "h1.GetXaxis().SetTitleSize(0.05)\n", "h1.GetXaxis().SetLabelSize(0.045)\n", "h1.GetXaxis().SetNdivisions(8, 5, 0)\n", "h1.GetYaxis().SetTitle(\"number of events\")\n", "h1.GetYaxis().SetTitleOffset(1.4)\n", "h1.GetYaxis().SetTitleSize(0.05)\n", "h1.GetYaxis().SetLabelSize(0.045)\n", "\n", "# Set the maximum of the y axis:\n", "if (h2.GetMaximum()>h1.GetMaximum()):\n", " h1.SetMaximum(h2.GetMaximum()*1.1)\n", " \n", "# Make a generically usable legend\n", "l = TLegend(0.65, 0.75, 0.88, 0.87)\n", "l.SetBorderSize(0)\n", "l.SetFillStyle(0000)\n", "# You can change the legend titles from here based on what you are plotting\n", "l.AddEntry(h1,h1.GetName(), \"l\")\n", "l.AddEntry(h2,h2.GetName(), \"l\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python %jsroot on\n", "############ LETS SEE 2D MULTIPLICITIES AND THE EFFECT OF MASS WINDOW CUT\n", "c = TCanvas(\"c\", \"c\", 620, 500)\n", "c.SetBottomMargin(0.15)\n", "c.SetLeftMargin(0.15)\n", "c.SetRightMargin(0.15)\n", "h1.Draw()\n", "h2.Draw(\"same\")\n", "l.Draw(\"same\")\n", "c.Draw()\n", "# Don't worry about the error that appears below!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python %jsroot on\n", "############ LETS SEE 2D MULTIPLICITIES AND THE EFFECT OF MASS WINDOW CUT\n", "c2 = TCanvas(\"c2\", \"c2\", 620, 500)\n", "c2.Divide(2,1)\n", "c2.SetBottomMargin(0.15)\n", "c2.SetLeftMargin(0.15)\n", "c2.SetRightMargin(0.15)\n", "c2.cd(1)\n", "hnenmsel.Draw(\"colz\") \n", "hnenmsel.Draw(\"sametext\") \n", "c2.cd(2) \n", "hZllselbc.SetLineColor(2)\n", "hZllselac.SetLineColor(4)\n", "hZllselbc.Draw(\"e\")\n", "hZllselac.Draw(\"esame\") \n", "c2.Draw()\n", "# Don't worry about the error that appears below!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%python %jsroot on\n", "############ LETS SEE MUON AND ELECTRON CHANNELS ON TOP OF EACH OTHER\n", "c3 = TCanvas(\"c3\", \"c3\", 620, 500)\n", "c3.SetBottomMargin(0.15)\n", "c3.SetLeftMargin(0.15)\n", "c3.SetRightMargin(0.15)\n", "hMZmm.SetLineColor(2)\n", "hMZmm.SetTitle(\"compare ee(blue) & mm(red) channels\")\n", "hMZmm.GetXaxis().SetTitle(\"mLL (GeV)\") \n", "hMZmm.Draw(\"e\") \n", "hMZee.Draw(\"esame\") \n", "c3.Draw()\n", "# Don't worry about the error that appears below!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "ROOT C++ with CutLang", "language": "c++", "name": "cutlang" }, "language_info": { "codemirror_mode": "text/x-c++src", "file_extension": ".C", "mimetype": " text/x-c++src", "name": "c++" } }, "nbformat": 4, "nbformat_minor": 4 }