"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# How to rediscover the Higgs boson yourself - with a BDT!\n",
"This notebook uses ATLAS Open Data http://opendata.atlas.cern to show you the steps to apply Machine Learning in search for the Higgs boson!\n",
"\n",
"ATLAS Open Data provides open access to proton-proton collision data at the LHC for educational purposes. ATLAS Open Data resources are ideal for high-school, undergraduate and postgraduate students.\n",
"\n",
"Notebooks are web applications that allow you to create and share documents that can contain for example:\n",
"1. live code\n",
"2. visualisations\n",
"3. narrative text\n",
"\n",
"This notebook builds on [HZZAnalysis.ipynb](https://github.com/atlas-outreach-data-tools/notebooks-collection-opendata/blob/master/13-TeV-examples/uproot_python/HZZAnalysis.ipynb) in the same folder as this notebook. \n",
"\n",
"HZZAnalysis.ipynb loosely follows the [discovery of the Higgs boson by ATLAS](https://www.sciencedirect.com/science/article/pii/S037026931200857X) (mostly Section 4 and 4.1)\n",
"\n",
"Notebooks are a perfect platform to develop Machine Learning for your work, since you'll need exactly those 3 things: code, visualisations and narrative text!\n",
"\n",
"We're interested in Machine Learning because we can design an algorithm to figure out for itself how to do various analyses, potentially saving us countless human-hours of design and analysis work.\n",
"\n",
"Machine Learning use within ATLAS includes: \n",
"* particle tracking\n",
"* particle identification\n",
"* signal/background classification\n",
"* and more!\n",
"\n",
"This notebook will focus on signal/background classification.\n",
"\n",
"By the end of this notebook you will be able to:\n",
"1. run a Boosted Decision Tree to classify signal and background\n",
"2. know some things you can change to improve your Boosted Decision Tree\n",
"\n",
"Feynman diagram pictures are borrowed from our friends at https://www.particlezoo.net"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Contents: \n",
"\n",
"[Running a Jupyter notebook](#running) \n",
"[First time setup on your computer (no need on mybinder)](#setup_computer) \n",
"[To setup everytime](#setup_everytime) \n",
"[Lumi, fraction, file path](#fraction) \n",
"[Samples](#samples) \n",
"[Changing a cut](#changing_cut) \n",
"[Applying a cut](#applying_cut) \n",
"[Optimisation](#optimisation) \n",
"[Boosted Decision Tree (BDT)](#BDT) \n",
" [Training and Testing split](#train_test) \n",
" [Training Decision Trees](#training) \n",
" [Assessing a Classifier's Performance](#performance) \n",
" [Receiver Operating Characteristic (ROC) curve](#ROC) \n",
" [Overtraining check](#overtraining) \n",
" [Optimisation](#BDT_optimisation) \n",
"[Going further](#going_further) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Running a Jupyter notebook\n",
"\n",
"To run the whole Jupyter notebook, in the top menu click Cell -> Run All.\n",
"\n",
"To propagate a change you've made to a piece of code, click Cell -> Run All Below.\n",
"\n",
"You can also run a single code cell, by clicking Cell -> Run Cells, or using the keyboard shortcut Shift+Enter."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## First time setup on your computer (no need on mybinder)\n",
"This first cell only needs to be run the first time you open this notebook on your computer. \n",
"\n",
"If you close Jupyter and re-open on the same computer, you won't need to run this first cell again.\n",
"\n",
"If you open on mybinder, you don't need to run this cell."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"!{sys.executable} -m pip install --upgrade --user pip # update the pip package installer\n",
"!{sys.executable} -m pip install uproot3 pandas numpy matplotlib sklearn --user # install required packages"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## To setup everytime\n",
"Cell -> Run All Below\n",
"\n",
"to be done every time you re-open this notebook.\n",
"\n",
"We're going to be using a number of tools to help us:\n",
"* uproot: lets us read .root files typically used in particle physics into data formats used in Machine Learning\n",
"* pandas: lets us store data as dataframes, a format widely used in Machine Learning\n",
"* numpy: provides numerical calculations such as histogramming\n",
"* matplotlib: common tool for making plots, figures, images, visualisations"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import uproot3 # for reading .root files\n",
"import pandas as pd # to store data as dataframe\n",
"import time # to measure time to analyse\n",
"import math # for mathematical functions such as square root\n",
"import numpy as np # # for numerical calculations such as histogramming\n",
"import matplotlib.pyplot as plt # for plotting\n",
"from matplotlib.ticker import AutoMinorLocator # for minor ticks\n",
"\n",
"import infofile # local file containing info on cross-sections, sums of weights, dataset IDs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Lumi, fraction, file path\n",
"\n",
"General definitions of fraction of data used, where to access the input files"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"lumi = 10 # fb-1 # data_A+B+C+D\n",
"\n",
"fraction = 0.03 # reduce this is you want the code to run quicker\n",
" \n",
"#tuple_path = \"Input/4lep/\" # local \n",
"tuple_path = \"https://atlas-opendata.web.cern.ch/atlas-opendata/samples/2020/4lep/\" # web address"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Samples\n",
"\n",
"In this notebook we only process the signal H->ZZ and the main background ZZ, for illustration purposes. You can add data and the Z and ttbar backgrounds after if you wish."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"samples = {\n",
"\n",
" 'ZZ' : {\n",
" 'list' : ['llll']\n",
" },\n",
"\n",
" r'$H \\rightarrow ZZ \\rightarrow \\ell\\ell\\ell\\ell$' : { # H -> ZZ -> llll\n",
" 'list' : ['ggH125_ZZ4lep'] # gluon-gluon fusion\n",
" }\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define function to get data from files.\n",
"\n",
"The datasets used in this notebook have already been filtered to include at least 4 leptons per event, so that processing is quicker."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def get_data_from_files():\n",
"\n",
" data = {} # define empty dictionary to hold dataframes\n",
" for s in samples: # loop over samples\n",
" print('Processing '+s+' samples') # print which sample\n",
" frames = [] # define empty list to hold data\n",
" for val in samples[s]['list']: # loop over each file\n",
" if s == 'data': prefix = \"Data/\" # Data prefix\n",
" else: # MC prefix\n",
" prefix = \"MC/mc_\"+str(infofile.infos[val][\"DSID\"])+\".\"\n",
" fileString = tuple_path+prefix+val+\".4lep.root\" # file name to open\n",
" temp = read_file(fileString,val) # call the function read_file defined below\n",
" frames.append(temp) # append dataframe returned from read_file to list of dataframes\n",
" data[s] = pd.concat(frames) # dictionary entry is concatenated dataframes\n",
" \n",
" return data # return dictionary of dataframes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"define function to get cross-section weight"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def get_xsec_weight(sample):\n",
" info = infofile.infos[sample] # open infofile\n",
" xsec_weight = (lumi*1000*info[\"xsec\"])/(info[\"sumw\"]*info[\"red_eff\"]) #*1000 to go from fb-1 to pb-1\n",
" return xsec_weight # return cross-section weight"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"define function to calculate weight of MC event"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def calc_weight(xsec_weight, mcWeight, scaleFactor_PILEUP,\n",
" scaleFactor_ELE, scaleFactor_MUON, \n",
" scaleFactor_LepTRIGGER ):\n",
" return xsec_weight*mcWeight*scaleFactor_PILEUP*scaleFactor_ELE*scaleFactor_MUON*scaleFactor_LepTRIGGER"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We add functions to return the individual lepton transverse momenta, in GeV"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def calc_lep_pt_i(lep_pt,i):\n",
" return lep_pt[i]/1000 # /1000 to go from MeV to GeV"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Changing a cut\n",
"\n",
"We apply 'cuts' to throw away collisions that have properties different to the signal we're looking for.\n",
"\n",
"If you change a cut: Cell -> Run All Below\n",
"\n",
"If you change a cut here, you also need to make sure the cut is applied in the \"[Applying a cut](#applying_cut)\" cell."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# cut on lepton charge\n",
"# paper: \"selecting two pairs of isolated leptons, each of which is comprised of two leptons with the same flavour and opposite charge\"\n",
"def cut_lep_charge(lep_charge):\n",
"# throw away when sum of lepton charges is not equal to 0\n",
"# first lepton is [0], 2nd lepton is [1] etc\n",
" return lep_charge[0] + lep_charge[1] + lep_charge[2] + lep_charge[3] != 0\n",
"\n",
"# cut on lepton type\n",
"# paper: \"selecting two pairs of isolated leptons, each of which is comprised of two leptons with the same flavour and opposite charge\"\n",
"def cut_lep_type(lep_type):\n",
"# for an electron lep_type is 11\n",
"# for a muon lep_type is 13\n",
"# throw away when none of eeee, mumumumu, eemumu\n",
" sum_lep_type = lep_type[0] + lep_type[1] + lep_type[2] + lep_type[3]\n",
" return (sum_lep_type != 44) and (sum_lep_type != 48) and (sum_lep_type != 52)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Applying a cut\n",
"If you add a cut: Cell -> Run All Below"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def read_file(path,sample):\n",
" start = time.time() # start the clock\n",
" print(\"\\tProcessing: \"+sample) # print which sample is being processed\n",
" data_all = pd.DataFrame() # define empty pandas DataFrame to hold all data for this sample\n",
" tree = uproot3.open(path)[\"mini\"] # open the tree called mini\n",
" numevents = uproot3.numentries(path, \"mini\") # number of events\n",
" if 'data' not in sample: xsec_weight = get_xsec_weight(sample) # get cross-section weight\n",
" for data in tree.iterate(['lep_charge','lep_type','lep_pt',\n",
" # uncomment these variables if you want to calculate masses \n",
" #,'lep_eta','lep_phi','lep_E', \n",
" # add more variables here if you make cuts on them \n",
" 'mcWeight','scaleFactor_PILEUP',\n",
" 'scaleFactor_ELE','scaleFactor_MUON',\n",
" 'scaleFactor_LepTRIGGER'\n",
" ], # variables to calculate Monte Carlo weight\n",
" outputtype=pd.DataFrame, # choose output type as pandas DataFrame\n",
" entrystop=numevents*fraction): # process up to numevents*fraction\n",
"\n",
" nIn = len(data.index) # number of events in this batch\n",
"\n",
" if 'data' not in sample: # only do this for Monte Carlo simulation files\n",
" # multiply all Monte Carlo weights and scale factors together to give total weight\n",
" data['totalWeight'] = np.vectorize(calc_weight)(xsec_weight,\n",
" data.mcWeight,\n",
" data.scaleFactor_PILEUP,\n",
" data.scaleFactor_ELE,\n",
" data.scaleFactor_MUON,\n",
" data.scaleFactor_LepTRIGGER)\n",
"\n",
" # cut on lepton charge using the function cut_lep_charge defined above\n",
" fail = data[ np.vectorize(cut_lep_charge)(data.lep_charge) ].index\n",
" data.drop(fail, inplace=True)\n",
"\n",
" # cut on lepton type using the function cut_lep_type defined above\n",
" fail = data[ np.vectorize(cut_lep_type)(data.lep_type) ].index\n",
" data.drop(fail, inplace=True)\n",
"\n",
" # return the individual lepton transverse momenta in GeV\n",
" data['lep_pt_1'] = np.vectorize(calc_lep_pt_i)(data.lep_pt,1)\n",
" data['lep_pt_2'] = np.vectorize(calc_lep_pt_i)(data.lep_pt,2)\n",
" \n",
" # dataframe contents can be printed at any stage like this\n",
" #print(data)\n",
"\n",
" # dataframe column can be printed at any stage like this\n",
" #print(data['lep_pt'])\n",
"\n",
" # multiple dataframe columns can be printed at any stage like this\n",
" #print(data[['lep_pt','lep_eta']])\n",
"\n",
" nOut = len(data.index) # number of events passing cuts in this batch\n",
" data_all = data_all.append(data) # append dataframe from this batch to the dataframe for the whole sample\n",
" elapsed = time.time() - start # time taken to process\n",
" print(\"\\t\\t nIn: \"+str(nIn)+\",\\t nOut: \\t\"+str(nOut)+\"\\t in \"+str(round(elapsed,1))+\"s\") # events before and after\n",
" \n",
" return data_all # return dataframe containing events passing all cuts\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is where the processing happens (this will take some minutes)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Processing ZZ samples\n",
"\tProcessing: llll\n",
"\t\t nIn: 16628,\t nOut: \t15740\t in 105.9s\n",
"Processing $H \\rightarrow ZZ \\rightarrow \\ell\\ell\\ell\\ell$ samples\n",
"\tProcessing: ggH125_ZZ4lep\n",
"\t\t nIn: 4941,\t nOut: \t4841\t in 250.9s\n",
"Time taken: 356.7s\n"
]
}
],
"source": [
"start = time.time() # time at start of whole processing\n",
"data = get_data_from_files() # process all files\n",
"elapsed = time.time() - start # time after whole processing\n",
"print(\"Time taken: \"+str(round(elapsed,1))+\"s\") # print total time taken to process every file"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Optimisation\n",
"\n",
"Here we define histograms for the variables that we'll look to optimise"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"lep_pt_2 = { # dictionary containing plotting parameters for the lep_pt_2 histogram\n",
" # change plotting parameters\n",
" 'bin_width':1, # width of each histogram bin\n",
" 'num_bins':13, # number of histogram bins\n",
" 'xrange_min':7, # minimum on x-axis\n",
" 'xlabel':r'$lep\\_pt$[2] [GeV]', # x-axis label\n",
"}\n",
"\n",
"lep_pt_1 = { # dictionary containing plotting parameters for the lep_pt_1 histogram\n",
" # change plotting parameters\n",
" 'bin_width':1, # width of each histogram bin\n",
" 'num_bins':28, # number of histogram bins\n",
" 'xrange_min':7, # minimum on x-axis\n",
" 'xlabel':r'$lep\\_pt$[1] [GeV]', # x-axis label\n",
"}\n",
"\n",
"SoverB_hist_dict = {'lep_pt_2':lep_pt_2,'lep_pt_1':lep_pt_1} \n",
"# add a histogram here if you want it plotted"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we define a function to illustrate the optimum cut value on individual variables, based on signal to background ratio."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"def plot_SoverB(data):\n",
" \n",
" signal = r'$H \\rightarrow ZZ \\rightarrow \\ell\\ell\\ell\\ell$' # which sample is the signal\n",
"\n",
" # *******************\n",
" # general definitions (shouldn't need to change)\n",
"\n",
" for x_variable,hist in SoverB_hist_dict.items(): # access the dictionary of histograms defined in the cell above\n",
"\n",
" h_bin_width = hist['bin_width'] # get the bin width defined in the cell above\n",
" h_num_bins = hist['num_bins'] # get the number of bins defined in the cell above\n",
" h_xrange_min = hist['xrange_min'] # get the x-range minimum defined in the cell above\n",
" h_xlabel = hist['xlabel'] # get the x-axis label defined in the cell above\n",
" \n",
" bin_edges = [ h_xrange_min + x*h_bin_width for x in range(h_num_bins+1) ] # bin limits\n",
" bin_centres = [ h_xrange_min+h_bin_width/2 + x*h_bin_width for x in range(h_num_bins) ] # bin centres\n",
" \n",
" signal_x = data[signal][x_variable] # histogram the signal\n",
" \n",
" mc_x = [] # define list to hold the Monte Carlo histogram entries\n",
"\n",
" for s in samples: # loop over samples\n",
" if s not in ['data', signal]: # if not data nor signal\n",
" mc_x = [*mc_x, *data[s][x_variable] ] # append to the list of Monte Carlo histogram entries\n",
"\n",
" \n",
" \n",
" # *************\n",
" # Signal and background distributions\n",
" # *************\n",
" distributions_axes = plt.gca() # get current axes\n",
" \n",
" mc_heights = distributions_axes.hist(mc_x, bins=bin_edges, color='red', \n",
" label='Total background',\n",
" histtype='step', # lineplot that's unfilled\n",
" density=True ) # normalize to form probability density\n",
" signal_heights = distributions_axes.hist(signal_x, bins=bin_edges, color='blue',\n",
" label=signal, \n",
" histtype='step', # lineplot that's unfilled\n",
" density=True, # normalize to form probability density\n",
" linestyle='--' ) # dashed line\n",
" \n",
" distributions_axes.set_xlim( left=bin_edges[0], right=bin_edges[-1] ) # x-limits of the distributions axes\n",
" distributions_axes.set_ylabel('Arbitrary units' ) # y-axis label for distributions axes\n",
" distributions_axes.set_ylim( top=max(signal_heights[0])*1.3 ) # set y-axis limits\n",
" plt.title('Signal and background '+x_variable+' distributions') # add title\n",
" distributions_axes.legend() # draw the legend\n",
" distributions_axes.set_xlabel( h_xlabel ) # x-axis label\n",
" \n",
" # Add text 'ATLAS Open Data' on plot\n",
" plt.text(0.05, # x\n",
" 0.93, # y\n",
" 'ATLAS Open Data', # text\n",
" transform=distributions_axes.transAxes, # coordinate system used is that of distributions_axes\n",
" fontsize=13 ) \n",
" # Add text 'for education' on plot\n",
" plt.text(0.05, # x\n",
" 0.88, # y\n",
" 'for education', # text\n",
" transform=distributions_axes.transAxes, # coordinate system used is that of distributions_axes\n",
" style='italic',\n",
" fontsize=8 ) \n",
" \n",
" plt.show() # show the Signal and background distributions\n",
" \n",
" \n",
" # *************\n",
" # Signal to background ratio\n",
" # *************\n",
" plt.figure() # start new figure\n",
" SoverB = [] # list to hold S/B values\n",
" for cut_value in bin_edges: # loop over bins\n",
" signal_weights_passing_cut = sum(data[signal][data[signal][x_variable]>cut_value].totalWeight)\n",
" background_weights_passing_cut = 0 # start counter for background weights passing cut\n",
" for s in samples: # loop over samples\n",
" if s not in ['data', signal]: # if not data nor signal\n",
" background_weights_passing_cut += sum(data[s][data[s][x_variable]>cut_value].totalWeight)\n",
" if background_weights_passing_cut!=0: # some background passes cut\n",
" SoverB_value = signal_weights_passing_cut/background_weights_passing_cut\n",
" SoverB_percent = 100*SoverB_value # multiply by 100 for percentage\n",
" SoverB.append(SoverB_percent) # append to list of S/B values\n",
" \n",
" SoverB_axes = plt.gca() # get current axes\n",
" SoverB_axes.plot( bin_edges[:len(SoverB)], SoverB ) # plot the data points\n",
" SoverB_axes.set_xlim( left=bin_edges[0], right=bin_edges[-1] ) # set the x-limit of the main axes\n",
" SoverB_axes.set_ylabel( 'S/B (%)' ) # write y-axis label for main axes\n",
" plt.title('Signal to background ratio for different '+x_variable+' cut values', family='sans-serif')\n",
" SoverB_axes.set_xlabel( h_xlabel ) # x-axis label \n",
" \n",
" plt.show() # show S/B plot\n",
" \n",
" return"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to contents](#contents)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we call our function to illustrate the optimum cut value on individual variables, based on signal to background ratio.\n",
"\n",
"We're not doing any Machine Learning yet! We're looking at the variables we'll later use for Machine Learning.\n",
"\n",
"Let's talk through the lep_pt_2 plots.\n",
"1. Imagine placing a cut at 7 GeV in the distributions of signal and background (1st plot). This means keeping all events above 7 GeV in the signal and background histograms. \n",
"2. We then take the ratio of the number of signal events that pass this cut, to the number of background events that pass this cut. This gives us a starting value for S/B (2nd plot). \n",
"3. We then increase this cut value to 8 GeV, 9 GeV, 10 GeV, 11 GeV, 12 GeV. Cuts at these values are throwing away more background than signal, so S/B increases. \n",
"4. There comes a point around 13 GeV where we start throwing away too much signal, thus S/B starts to decrease. \n",
"5. Our goal is to find the maximum in S/B, and place the cut there.\n",
"\n",
"The same logic applies to lep_pt_1."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"image/png": "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8UUefvjhoPts0qQJW7cGv68yNzeXpKQkGjZs6F8WOCzLscceS5MmTcjJyWHnzp3s37+fgQMHkpyc7H9s3LiRnJxfJm1r1qxZkWPUqVOHffv2hfxe5OTk0KiRM/30zz//zJgxY2jTpg3HHXccycnJ7Nmzhx07dpS6fWFhIX/6059o164d9evXJzk5mRUrVpS5jQnR5s2gGr7H5pBvUGbRokWcccYZdOjQgeuvv55Dhw7x9NNPk5ubS8+ePenZsycAN998MxkZGZx++umMG+dt3q4JEybQoUMHunbt6q+ynTt3Lt26deOMM87gggsu4IcffgBg//79XHfddXTo0IGOHTsye/bsIvvauXMn3bt3Z/78+RQWFnLLLbdw6qmncuGFF3LxxRcza5Yz8Hdqair33nsvXbp04Y033mD69Ol06NCB9u3bc++99/r3V7duXf/zWbNmMWLECMCpLh47dixnnXUWbdq08e9XVRkzZgzt2rXjggsuYPv2yI4Ja4kjQGFhIS+88AJ5eXm0aNGCpk2bkpaWRkFBQUh1+aXxNbRfdNFFNG3alKZNm7J69WpmzpxJXl5eifI1atRg0KBBXHDBBaX+qu/bty85OTl8+OGHJda99tpr9OjRg9q1a/uXbdq0yf/8wIED7NixgxYtWtC4cWPq1KnDO++8Q15env/x008/cd999x3lmRe1Z88eFi5cSK9evQB44okn+OCDD1i0aBF79+4lLy+PBg0a4FxFwzHHlPyYTp8+ncmTJzN79mz27NlDXl4enTp18m9jKr+DBw8yYsQIZsyYwapVq8jPz+df//oXY8eOJSUlhffee4/33nMmzPzLX/7C0qVLWblyJe+//76nTiH169dn1apVjBkzhttvvx2Ac845h88++4wvv/ySoUOHMmHCBAAeeughf/mVK1f6P7sAP/zwA/379+fBBx+kf//+/Pvf/2bTpk2sXr2aadOmFalRAOfKKisri/POO497772Xd999l+XLl7NkyRLefLP8ece2bdvGRx99xLx58/z/N//zn/+wdu1aVq9e7W+bjSRLHAH+97//sWXLFj755BP/JfLy5cuZN28en332GatWrfK0nyNHjnDw4EH/49ChQ+zevZtZs2bx7LPPFtn36tWrqVWrlr+R/M4772TJkiUcPHiQwsJCFi9ezHvvvce5554b9FjnnXceV199NcOGDeOdd97h8OHDfP/999x66618/vnnPPbYY0XKP/nkk2zYsIGDBw9y33330aZNG7p164aIcNttt3H33Xezbt06wPmVtWDBAnJzc4/iXf1Ffn4+n332GZdeein16tXzN9z/+OOP1KxZk0aNGnH48GEefPDBIom0adOmFBQU8O233/qX/fjjj1SrVo0mTZpQWFjIlClTWLFiRVjiNPGhoKCA1q1b07ZtWwCGDx/OBx98ELTszJkz6dKlC2eccQbZ2dmsXl3+QBNXXXWV/1/fl3tOTg59+vShQ4cOPProo/7eku+88w6jR4/2b9ugQQPA+b/eu3dvJkyYwIUXXgg4HVYuv/xyjjnmGJo2beq/KvK58sorAViyZAnnn38+TZo0oVq1agwbNqzU8wt0ySWXcMwxx5CWlua/Ivrggw+46qqrSEpKIiUlpUhiiwRLHAEmTpzIJZdcQnp6uv+KoGnTpvTp04fu3bt7vuq4/vrrqV27tv9Rv359XnrpJRo0aMANN9xQZN+tWrVi1KhR/n0XFhZy3XXXcfzxx9OgQQNuueUW7r77bu66665Sj/fyyy8zduxYxo4dS3JyMmlpaeTk5PDZZ59xxhlnFCl7ww03MGTIEJo0acKKFSt46623SEpKAuCBBx5g8ODBDB48mOOOO45TTjmF5557jsLCwmCH9axdu3bUq1ePxo0bc8stt3DuueeybNkyGjduDDjJMjk5mZSUFE466SSOPfbYIlVqbdu25eabb6Zr164kJyczbdo0hg8fTrdu3Tj55JNp3rw5q1evLjW5msT27bff8thjj7Fo0SJWrlxJ//79PXU7Dexl5Ht+6623MmbMGFatWsXEiRPL3U+1atVIT09nwYIFnuOtU6dOSLEVj6FmzZr+5zG7wg61NT1eH+G+ATARAfrhhx/GOgwTp0r0uIHwHiCE/Y0bN04feughbdmypa5bt05VnZ5CTz31lKqqtm/f3n8z2/Lly7Vjx45aUFCg33//vR5//PH64osvqmrZvar++te/qqrqtGnTdMCAAaqq2rlzZ126dKmqqo4YMUJ79Oihqqr33nuv3nbbbf7tfT0N69Spo/n5+XrppZfqI488oqqqM2fO1P79+/vjadCggb+HU2BvrtzcXD3xxBN1x44dmp+fr71799Y333xTVVVPOukkXb16tRYUFOiQIUN0+PDh/vcgsLeUr1fX7Nmz9aKLLtL8/HzNzc3V5OTkiPaqitdh1Y0xVVytWrV48cUXufzyy8nPz+fMM89k1KhRAGRmZtK3b19/W8cZZ5zBqaeeSsuWLTn77LM97X/Pnj107NiRmjVrMn36dADGjx/P5ZdfToMGDejVq5e/evQPf/gDo0ePpn379iQlJTFu3DiGDBkCQFJSEtOnT2fQoEHUq1ePUaNGsWjRItLS0mjZsiVdunShfv36JY7frFkzHnnkEXr27Imq0r9/fwYPHgzAI488woABA2jSpAkZGRns31/2XHaXXnop7777LmlpaZx44ol0797d25tcQTZWVRUiInz44Yecc845sQ7FxKE1a9Zw2mmn/bIgNbVCPaFK1aoVBHTOSGT79++nbt267Nq1i65du/Lxxx+XehNvNJX4G1OxsarsiqMKSZQfCSZKqsiXfCQMGDCAvLw8Dh8+zB//+Me4SBrhZI3jxaxfv57u3bszZsyYsO3zzTff9HfFrajp06f7bxiaMGGCjfNkTBxbvHixv9ek7x6MRGKJo5hp06bx5JNP8swzz5RZLpSeRmvWrOH0008/qrimTJni7/10zz33+G+eM8aYaLPEEeDdd9/lmWee4b777mPFihXcfvvtnHXWWfTt25effvqJrKws+vTpw6WXXsrcuXP9223dupXBgwdz7rnnMn78eAC+/PJLzjnnHPr06cPHH3/M6aefzj333OO/MemWW25h48aNHDhwgGuvvZaePXty2WWXAU731HPPPZfOnTuTm5vLM888w5dffsn555/P119/Tb9+/QDnvpNf/epXdOvWzX8jVI8ePbjttttIS0vj1VdfjeK7Z4ypMkLthhWvj3B1x+3Tp4+qqk6dOtXfve7vf/+7Tp8+XV966SW94YYbSmxzxRVX6DfffKOqqgMHDtRDhw5pnz59dOfOnbpv3z5t3bq1qqoOGDBADx48qKqqffv21cLCQr3zzjt13rx5qqp6+PBhVVXdv3+/qqpOmTJFX3vtNd2wYYOOHj1aVZ15QW688Ubdu3evnn/++XrgwAHNy8vTvn376qFDh7RVq1a6Z88e3bhxo1577bVheU9M1RDrQQ5N5Fl33Ag4dOgQtWrVApwxa6ZMmQI4Q17Url2brKwsMjMzi2xz+PBh3n//fW688UYAdu3axXfffUfbtm3949+feuqpgDPER82aNVFVCgsLERGy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\n",
"text/plain": [
"