{ "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": [ "## Before starting the analysis\n", "\n", "Please import the requirements by running the cell below to avoid error" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ROOT\n", "%jsroot on" ] }, { "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", "- **parallel** : enter 0 to speed up analysis with multiprocessing\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" ] }, { "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": [ "# 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": [ "# 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": [ "# Let's see what is available:\n", "f.cd(\"Zll\")\n", "f.ls()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 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": [ "############ 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": [ "############ 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": [ "############ 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": [ "############ 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!" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.6" } }, "nbformat": 4, "nbformat_minor": 4 }