Skip to content

Commit 42ebf73

Browse files
feat: add small tests (#73)
* add minimal ServiceX + coffea test * add servicex-databinder example * query examples for ServiceX
1 parent 5832fe7 commit 42ebf73

File tree

5 files changed

+744
-1
lines changed

5 files changed

+744
-1
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ venv/
77
.ipynb_checkpoints
88

99
servicex.yml
10+
servicex.yaml
1011

1112
analyses/**/*.root
1213
analyses/**/*.pdf
@@ -24,4 +25,6 @@ workshops/agctools2022/statistical-inference/input
2425

2526
# CMS ttbar
2627
analyses/cms-open-data-ttbar/workspace.json
27-
analyses/cms-open-data-ttbar/dask-worker-space
28+
29+
# dask
30+
dask-worker-space/

tests/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# tests
2+
3+
This is a space to collect miscellaneous scripts / notebooks etc. that do not fit anywhere else but are useful for testing.
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"id": "c8dc945e-0f70-4542-8725-7fbfa7b47865",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"import asyncio\n",
11+
"import time\n",
12+
"\n",
13+
"import awkward as ak\n",
14+
"from coffea.processor import servicex\n",
15+
"from func_adl import ObjectStream\n",
16+
"from func_adl_servicex import ServiceXSourceUpROOT\n",
17+
"import hist\n",
18+
"import matplotlib.pyplot as plt\n",
19+
"from servicex import ServiceXDataset"
20+
]
21+
},
22+
{
23+
"cell_type": "markdown",
24+
"id": "8d8fd413-6c3e-46a0-9945-75a4c1bc6725",
25+
"metadata": {},
26+
"source": [
27+
"Configuration options: enable / disable `dask` and the use of caching with `ServiceX` (to force re-running transforms)."
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": 2,
33+
"id": "9900ed24-64ac-4661-aa31-0f4714c7db4e",
34+
"metadata": {},
35+
"outputs": [],
36+
"source": [
37+
"# enable Dask\n",
38+
"USE_DASK = False\n",
39+
"\n",
40+
"# ServiceX behavior: ignore cache with repeated queries\n",
41+
"SERVICEX_IGNORE_CACHE = True"
42+
]
43+
},
44+
{
45+
"cell_type": "markdown",
46+
"id": "545eacca-c610-4069-b96d-6c44d8083abf",
47+
"metadata": {},
48+
"source": [
49+
"The processor used here: select jets with $p_T > 25$ GeV and calculate $\\textrm{H}_\\textrm{T}^{\\textrm{had}}$ (scalar sum of jet $p_T$) as observable."
50+
]
51+
},
52+
{
53+
"cell_type": "code",
54+
"execution_count": 3,
55+
"id": "d4e60d23-795c-4417-86c6-1696be3b65ec",
56+
"metadata": {},
57+
"outputs": [],
58+
"source": [
59+
"class TtbarAnalysis(servicex.Analysis):\n",
60+
" def __init__(self):\n",
61+
" self.hist = hist.Hist.new.Reg(50, 0, 1000, name=\"ht\", label=\"HT\").Weight()\n",
62+
"\n",
63+
" def process(self, events):\n",
64+
" histogram = self.hist.copy()\n",
65+
"\n",
66+
" # select jets with pT > 25 GeV\n",
67+
" selected_jets = events.jet[events.jet.pt > 25]\n",
68+
"\n",
69+
" # use HT (scalar sum of jet pT) as observable\n",
70+
" ht = ak.sum(selected_jets.pt, axis=-1)\n",
71+
" histogram.fill(ht=ht, weight=1.0)\n",
72+
"\n",
73+
" return histogram\n",
74+
"\n",
75+
" def postprocess(self, accumulator):\n",
76+
" return accumulator"
77+
]
78+
},
79+
{
80+
"cell_type": "markdown",
81+
"id": "6702d39b-70b2-4252-a569-d9db01444469",
82+
"metadata": {},
83+
"source": [
84+
"Specify which data to process, using a small public file here taken from 2015 CMS Open Data."
85+
]
86+
},
87+
{
88+
"cell_type": "code",
89+
"execution_count": 4,
90+
"id": "34588fe7-67dd-4b87-9306-b05334fc86d4",
91+
"metadata": {},
92+
"outputs": [],
93+
"source": [
94+
"# input data to process\n",
95+
"fileset = {\n",
96+
" \"ttbar\": {\n",
97+
" \"files\": [\"https://xrootd-local.unl.edu:1094//store/user/AGC/datasets/RunIIFall15MiniAODv2/TT_TuneCUETP8M1_13TeV-powheg-pythia8/MINIAODSIM//PU25nsData2015v1_76X_mcRun2_asymptotic_v12_ext3-v1/00000/00DF0A73-17C2-E511-B086-E41D2D08DE30.root\"],\n",
98+
" \"metadata\": {\"process\": \"ttbar\"}\n",
99+
" }\n",
100+
"}"
101+
]
102+
},
103+
{
104+
"cell_type": "markdown",
105+
"id": "1bbe9b7b-19dd-4945-92e8-1757bb1b6d73",
106+
"metadata": {},
107+
"source": [
108+
"Set up the query: only requesting specific columns here without any filtering applied."
109+
]
110+
},
111+
{
112+
"cell_type": "code",
113+
"execution_count": 5,
114+
"id": "13b93c01-24ae-49a3-a91b-3a432c7d2f2b",
115+
"metadata": {},
116+
"outputs": [],
117+
"source": [
118+
"def get_query(source: ObjectStream) -> ObjectStream:\n",
119+
" \"\"\"Query for event / column selection: no filter, select single jet column\n",
120+
" \"\"\"\n",
121+
" return source.Select(lambda e: {\"jet_pt\": e.jet_pt})"
122+
]
123+
},
124+
{
125+
"cell_type": "markdown",
126+
"id": "2b55e5ac-885f-455c-a742-b30b364559c3",
127+
"metadata": {},
128+
"source": [
129+
"The following cell is mostly boilerplate, which can hopefully be improved in the future."
130+
]
131+
},
132+
{
133+
"cell_type": "code",
134+
"execution_count": 6,
135+
"id": "4022b82b-1aee-43d8-8958-b6947e5ed975",
136+
"metadata": {},
137+
"outputs": [],
138+
"source": [
139+
"def make_datasource(fileset:dict, name: str, query: ObjectStream, ignore_cache: bool):\n",
140+
" \"\"\"Creates a ServiceX datasource for a particular Open Data file.\"\"\"\n",
141+
" datasets = [ServiceXDataset(fileset[name][\"files\"], backend_name=\"uproot\", ignore_cache=ignore_cache)]\n",
142+
" return servicex.DataSource(\n",
143+
" query=query, metadata=fileset[name][\"metadata\"], datasets=datasets\n",
144+
" )\n",
145+
"\n",
146+
"\n",
147+
"async def produce_all_histograms(fileset, query, procesor_class, use_dask=False, ignore_cache=False):\n",
148+
" \"\"\"Runs the histogram production, processing input files with ServiceX and\n",
149+
" producing histograms with coffea.\n",
150+
" \"\"\"\n",
151+
" # create the query\n",
152+
" ds = ServiceXSourceUpROOT(\"cernopendata://dummy\", \"events\", backend_name=\"uproot\")\n",
153+
" ds.return_qastle = True\n",
154+
" data_query = query(ds)\n",
155+
"\n",
156+
" # executor: local or Dask\n",
157+
" if not use_dask:\n",
158+
" executor = servicex.LocalExecutor()\n",
159+
" else:\n",
160+
" # for coffea-casa\n",
161+
" executor = servicex.DaskExecutor(client_addr=\"tls://localhost:8786\")\n",
162+
" # locally\n",
163+
" # executor = servicex.DaskExecutor()\n",
164+
"\n",
165+
" datasources = [\n",
166+
" make_datasource(fileset, ds_name, data_query, ignore_cache=ignore_cache)\n",
167+
" for ds_name in fileset.keys()\n",
168+
" ]\n",
169+
"\n",
170+
" # create the analysis processor\n",
171+
" analysis_processor = procesor_class()\n",
172+
"\n",
173+
" async def run_updates_stream(accumulator_stream):\n",
174+
" \"\"\"Run to get the last item in the stream\"\"\"\n",
175+
" coffea_info = None\n",
176+
" try:\n",
177+
" async for coffea_info in accumulator_stream:\n",
178+
" pass\n",
179+
" except Exception as e:\n",
180+
" raise Exception(f\"Failure while processing\") from e\n",
181+
" return coffea_info\n",
182+
"\n",
183+
" output = await asyncio.gather(\n",
184+
" *[\n",
185+
" run_updates_stream(executor.execute(analysis_processor, source, title=source.metadata['process']))\n",
186+
" for source in datasources\n",
187+
" ]\n",
188+
" )\n",
189+
"\n",
190+
" return output"
191+
]
192+
},
193+
{
194+
"cell_type": "markdown",
195+
"id": "908d64f0-bbfa-4f75-9da4-9b5ee3e1745e",
196+
"metadata": {},
197+
"source": [
198+
"Execute everything: query `ServiceX`, which sends columns back to `coffea` processors asynchronously, collect the aggregated histogram built by `coffea`."
199+
]
200+
},
201+
{
202+
"cell_type": "code",
203+
"execution_count": 7,
204+
"id": "5b1d63a1-d9e5-4f23-a709-a73eeb0460ab",
205+
"metadata": {},
206+
"outputs": [
207+
{
208+
"data": {
209+
"application/vnd.jupyter.widget-view+json": {
210+
"model_id": "",
211+
"version_major": 2,
212+
"version_minor": 0
213+
},
214+
"text/plain": [
215+
"ttbar: 0%| | 0/9000000000.0 [00:00]"
216+
]
217+
},
218+
"metadata": {},
219+
"output_type": "display_data"
220+
},
221+
{
222+
"name": "stdout",
223+
"output_type": "stream",
224+
"text": [
225+
"execution took 13.32 seconds\n"
226+
]
227+
}
228+
],
229+
"source": [
230+
"t0 = time.time()\n",
231+
"\n",
232+
"# in a notebook\n",
233+
"output = await produce_all_histograms(\n",
234+
" fileset, get_query, TtbarAnalysis, use_dask=USE_DASK, ignore_cache=SERVICEX_IGNORE_CACHE\n",
235+
")\n",
236+
"\n",
237+
"# as a script:\n",
238+
"# async def produce_all_the_histograms():\n",
239+
"# return await produce_all_histograms(\n",
240+
"# fileset, get_query, TtbarAnalysis, use_dask=USE_DASK, ignore_cache=SERVICEX_IGNORE_CACHE\n",
241+
"# )\n",
242+
"# output = asyncio.run(produce_all_the_histograms())\n",
243+
"\n",
244+
"print(f\"execution took {time.time()-t0:.2f} seconds\")"
245+
]
246+
},
247+
{
248+
"cell_type": "code",
249+
"execution_count": 8,
250+
"id": "f9e969b9-9925-4d43-9d0f-201d1547681f",
251+
"metadata": {},
252+
"outputs": [
253+
{
254+
"data": {
255+
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAX0AAAEGCAYAAACJnEVTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAAsTAAALEwEAmpwYAAAXc0lEQVR4nO3dcYyc9Z3f8ff3DMF28OrsxUGLTWrfyUFam8QJCzglqmgpxU3a2heUxokOsETlNAI1aaO05k5K4kiWaMVBS+8g+IIL3IUQ6xKCQaE5Q4MSJINjqHvYayjm7INlt9gHl9qkgQPft3/Ms86wntmd2Z2d3Znn/ZJW88xvnmfm+c3ufuY3v+f3/J7ITCRJ5fAbM70DkqT2MfQlqUQMfUkqEUNfkkrE0JekEjljpndgIuecc04uW7ZspndDkjrKM88889eZuXhs+awP/WXLlrF3796Z3g1J6igR8Ve1yu3ekaQSMfQlqUQMfUkqkVnfpy9JzXjnnXcYGhrirbfemuldaYu5c+eydOlSzjzzzIbWN/QldZWhoSEWLFjAsmXLiIiZ3p1plZm8/vrrDA0NsXz58oa2sXtHUld566236O3t7frAB4gIent7m/pWY+hL6jplCPxRzdbV0JdUep+9azefvWv3TO9GWxj6ktRCv/jFL7jjjjsAOHLkCPfff/+px+655x5uvPHGmdo1wNDXBOq1gMrUMpKaMV7oT9XJkyen/ByGviS10ObNm3nppZdYvXo1X/3qV/nZz37G6tWrue222wB45ZVXWLt2LRdccAFbtmw5td369eu56KKLWLlyJdu2bTtVfvbZZ/O1r32NSy+9lN27p97QcsimpK615eEDDA4fP618cOS9Zf/v7XcBuPAbP35PeX9fz2nb9p/Xw9f/+cq6r3nzzTezf/9+9u3bxxNPPMEtt9zCI488AlS6d/bs2cP+/fuZP38+F198MZ/61KcYGBhg+/btLFq0iF/96ldcfPHFXH311fT29vLLX/6SVatW8c1vfrPp+tdi6Os01f8oo/8cY7tyxpZP9I8gqeLKK6+kt7cXgE9/+tM8+eSTDAwMcPvtt/Pggw8ClW8DL774Ir29vcyZM4err766Za9v6Os0g8PHGRw5XrOVU3P9kdNbUtJs0GhDZLTx8r0vfHw6dwc4fYhlRPDEE0/w2GOPsXv3bubPn8/ll19+auz93LlzmTNnTste39BXTf19PXzvCx+v+89QXe4BXenXFixYwIkTJ05bHrVr1y7eeOMN5s2bxw9/+EO2b9/Oq6++ysKFC5k/fz7PP/88Tz311LTtn6EvSS3U29vLZZddxqpVq7jyyis544wz+MhHPsLGjRtZuHAhn/jEJ7jmmms4dOgQn//85xkYGODCCy/kW9/6Fh/+8Ie54IILWLNmzbTtn6EvSS023jDNjRs3nlZ21lln8eijj9Zc/80332zVbgGGviZQr4+zHX2fUruU6e/ZcfoCWneylSdtSbOboS+p62TmTO9C2zRbV0NfUleZO3cur7/+eimCf3Q+/blz5za8jX36JVbvJKxmxuiPGhw5fmrb0ecBT9pS+y1dupShoSGOHTs207vSFqNXzmqUoV9i9U7C6u/rof+8xkO/3rqetKWZcOaZZzZ8FakyMvRLbqKTsBpR3ZL3pC1pdrNPX5JKxNCXpBKxe0dA605OKdNJLlInmrClHxHnR8RPIuJgRByIiC8V5d+IiFcjYl/x88mqbW6KiEMR8UJEXFVVflFEPFc8dnuU6erFkjQLNNLSfxf4SmY+GxELgGciYlfx2G2ZeUv1yhHRD2wAVgLnAY9FxIcy8yRwJ7AJeAr4EbAWqD3hhCSp5SZs6WfmSGY+WyyfAA4CS8bZZB3wQGa+nZmHgUPAJRHRB/Rk5u6snDVxH7B+qhWQJDWuqQO5EbEM+CjwdFF0Y0T8RURsj4iFRdkS4JWqzYaKsiXF8thySVKbNBz6EXE28H3gy5l5nEpXzW8Dq4ER4A9GV62xeY5TXuu1NkXE3ojYW5az6iSpHRoK/Yg4k0rgfyczfwCQma9l5snM/Dvgj4FLitWHgPOrNl8KDBflS2uUnyYzt2XmQGYOLF68uJn6SJLG0cjonQDuBg5m5q1V5X1Vq/0OsL9Y3glsiIizImI5sALYk5kjwImIWFM857XAQy2qhxrk1MdSuTUyeucy4BrguYjYV5T9HvC5iFhNpYvmCPAFgMw8EBE7gEEqI39uKEbuAHwRuAeYR2XUjiN3SqKdF56WVN+EoZ+ZT1K7P/5H42yzFdhao3wvsKqZHZQktY5n5JZAK6dQltTZDP0SaNUUypN6befZl2YVQ78kWjGFctOv6Tz70qxj6GvaOM++NPsY+iXj6Bmp3Ax9tYUfNtLs4EVUJKlEDH1JKhFDX5JKxNCXpBIx9CWpRAx9SSoRQ1+SSsTQ14xyfn+pvQx9SSoRQ1+SSsRpGDQjnHJZmhmGvtrOKZelmWPoq+2cclmaOfbpS1KJ2NLXjHLKZam9bOlLUokY+pJUIoa+JJWIod+lnN5AUi2GviSViKEvSSXikM0usuXhAwwOV85qrZ7eYHDkOP19tc+ClVQuE7b0I+L8iPhJRByMiAMR8aWifFFE7IqIF4vbhVXb3BQRhyLihYi4qqr8ooh4rnjs9oiI6alWOQ0OH685lUF/X0/dqQ8klUsjLf13ga9k5rMRsQB4JiJ2ARuBxzPz5ojYDGwG/kNE9AMbgJXAecBjEfGhzDwJ3AlsAp4CfgSsBR5tdaXKrL+v5z1TGnjyk6RqE7b0M3MkM58tlk8AB4ElwDrg3mK1e4H1xfI64IHMfDszDwOHgEsiog/oyczdmZnAfVXbSJLaoKk+/YhYBnwUeBo4NzNHoPLBEBEfKFZbQqUlP2qoKHunWB5brmlgC19SLQ2P3omIs4HvA1/OzPHmwK3VT5/jlNd6rU0RsTci9h47dqzRXVSX8VwDqfUaCv2IOJNK4H8nM39QFL9WdNlQ3B4tyoeA86s2XwoMF+VLa5SfJjO3ZeZAZg4sXry40bpIkiYwYfdOMcLmbuBgZt5a9dBO4Drg5uL2oary+yPiVioHclcAezLzZESciIg1VLqHrgX+a8tqoq4wekWt0WXwqlpSKzXSp38ZcA3wXETsK8p+j0rY74iI64GXgc8AZOaBiNgBDFIZ+XNDMXIH4IvAPcA8KqN2HLmjU8YbVupVtaTWmDD0M/NJavfHA1xRZ5utwNYa5XuBVc3soMpjbCveq2pJrec0DJJUIk7DoFnLYadS69nSl6QSMfQlqUQMfUkqEUNfkkrE0JekEjH0JalEDH1JKhFDX5JKxNCXpBIx9NVxnGdfmjxDX5JKxLl31DFG59p3nn1p8gx9dYR6c+07z77UHEO/w1XPOd/NqlvyzrMvTZ59+pJUIrb01XG6/VuNNJ0M/Q605eEDDA5X+rKrD2oOjhynv6/+dWYlye6dDjQ4fLzmAcz+vp5xLy4uSbb0O1R/X897DmTa5SGpEbb0JalEbOl3OFv4kpphS1+SSsTQl6QSMfQlqUQMfUkqEUNfXcN59qWJTRj6EbE9Io5GxP6qsm9ExKsRsa/4+WTVYzdFxKGIeCEirqoqvyginiseuz0iovXVkSSNp5Ehm/cAfwjcN6b8tsy8pbogIvqBDcBK4DzgsYj4UGaeBO4ENgFPAT8C1gKPTmnvJZxnX2rGhKGfmT+NiGUNPt864IHMfBs4HBGHgEsi4gjQk5m7ASLiPmA9hr6myHn2peZM5eSsGyPiWmAv8JXM/BtgCZWW/KihouydYnlsuTQlzrMvNWeyB3LvBH4bWA2MAH9QlNfqp89xymuKiE0RsTci9h47dmySuyhJGmtSLf3MfG10OSL+GHikuDsEnF+16lJguChfWqO83vNvA7YBDAwM1P1wkKo5JYU0sUm19COir+ru7wCjI3t2Ahsi4qyIWA6sAPZk5ghwIiLWFKN2rgUemsJ+Sw1zKKf0axO29CPiu8DlwDkRMQR8Hbg8IlZT6aI5AnwBIDMPRMQOYBB4F7ihGLkD8EUqI4HmUTmA60FcSWqzRkbvfK5G8d3jrL8V2FqjfC+wqqm9k6bAoZzS6ZxaWV3JoZxSbYa+upJDOaXanHtHkkrElr66nkM5pV+zpS9JJWLoS1KJGPqSVCKGviSViKEvSSVi6EtSiRj6klQihr4klYihr9JyymWVkWfkdojq+WM0Nc6+qTIz9FUqzr6psjP0Z7EtDx9gcLgSRtWt0sGR4/T31Q4vjc/ZN1V29unPYoPDx2u2QPv7euq2WCVpPLb0Z7n+vp73tETt028d30uVkS19SSoRW/odwlappFawpS9JJWLoS2N40pa6md07UsGTtlQGhr6EJ22pPAx9CU/aUnnYpy9JJWJLXxrD4bHqZrb0JalEDH1JKpEJQz8itkfE0YjYX1W2KCJ2RcSLxe3CqsduiohDEfFCRFxVVX5RRDxXPHZ7RETrqyNJGk8jLf17gLVjyjYDj2fmCuDx4j4R0Q9sAFYW29wREXOKbe4ENgErip+xzylJmmYThn5m/hR4Y0zxOuDeYvleYH1V+QOZ+XZmHgYOAZdERB/Qk5m7MzOB+6q2kSS1yWT79M/NzBGA4vYDRfkS4JWq9YaKsiXF8tjymiJiU0TsjYi9x44dm+QuSpLGavWB3Fr99DlOeU2ZuS0zBzJzYPHixS3bOUkqu8mG/mtFlw3F7dGifAg4v2q9pcBwUb60RrkkqY0mG/o7geuK5euAh6rKN0TEWRGxnMoB2z1FF9CJiFhTjNq5tmobSVKbTHhGbkR8F7gcOCcihoCvAzcDOyLieuBl4DMAmXkgInYAg8C7wA2ZebJ4qi9SGQk0D3i0+JE6hpesVDeYMPQz83N1Hrqizvpbga01yvcCq5raO2kWcMpldRPn3pHG4ZTL6jaGvjQOp1xWt3HuHUkqEVv6UoM8gKtuYEtfkkrE0JekEjH0Z5nP3rXbg4Qdxt+ZOol9+tIkOX5fncjQnwW2PHyAweFKcFQHyODIcfr7ao8T18xy/L46laE/CwwOH68Z8P19PXXDRTPL8fvqVIb+LNHf1/Oe0HB4YOfwd6VOYujPMgaIpOnk6B1JKhFDX5omDuXUbGT3jtRiDuXUbGboSy3kUE7Ndoa+1EIO5dRsZ+hL08SRWJqNPJArSSVi6EtSiRj6klQihr7UZo7f10zyQK7UJo7f12xg6Ett4Ph9zRaG/gxwJs3ycfy+ZgtDv03qXShl9L4XSymPeh/2NgbUDoZ+m9S7UAp4sZSys69f7WTot9HohVKkUfb1q92mFPoRcQQ4AZwE3s3MgYhYBHwPWAYcAf5lZv5Nsf5NwPXF+v8mM388ldeXOl29lrx9/ZourRin/w8zc3VmDhT3NwOPZ+YK4PHiPhHRD2wAVgJrgTsiYk4LXl+S1KDpODlrHXBvsXwvsL6q/IHMfDszDwOHgEum4fUlSXVMtU8/gT+PiATuysxtwLmZOQKQmSMR8YFi3SXAU1XbDhVlp4mITcAmgA9+8INT3EWpM409wFs9CMCDvJqsqYb+ZZk5XAT7roh4fpx1o0ZZ1lqx+PDYBjAwMFBzHambjTeaq/ogr8M81awphX5mDhe3RyPiQSrdNa9FRF/Ryu8DjharDwHnV22+FBieyutL3areyVyj9x3mqcmadOhHxPuB38jME8XyPwG+CewErgNuLm4fKjbZCdwfEbcC5wErgD1T2HepFMa24h3mqamYSkv/XODBiBh9nvsz879HxM+BHRFxPfAy8BmAzDwQETuAQeBd4IbMPDmlvZdKyGGemopJh35m/iXwkRrlrwNX1NlmK7B1sq8pSZoa59OXpBJxGgapi9Qb5ukBXo0y9Fus1mya/X09zqSpaecBXjXC0G+xerNpOpOmplsjc/Y7rl+G/jQYnU3TfzDNlLF/c47r1yhDfxoZ9poN7PZRNUNf6nKO61c1h2xKUokY+pJUIoa+JD571267e0rCPn2pxBzVUz6GvlRS9Ub1PH34DZ4+/Mapc07AM3u7iaEvlVS98K4+q7yaQzy7g6Ev6T0aObNXncvQl1TXRGf22u3TeQx9SQ3xGEB3MPQnydk0VTbNHgPww2B2MvQnydk0pYpWHRCu15ACPyRaydCfgtHZNCWdrtk5f+o1pBw11FqGvqS2q3VAeDTwxzakRtfzAHJrGPqS2qpe92e9rlGnhm4tQ19SWzXbMh+vm2j0G0AtfguozdCfwHgHoxylI82csd8AxnYVqTZDfwLVB5eq/6gcpSPNrPFa8eMdBxhV1uMDhn4DHKUjdZZmG2RlOqfA0JfUdZoN6VadYNYJ5xoY+pJKr5ETzKq7h+p9GDx9+A0ALl2+6D3PU73+WO3+MDD0Cx6wlTRWsx8Gly5f1NQ3gJn4MGh76EfEWuC/AHOAb2fmze3eh1o8YCupUa0adjreHF7Tpa2hHxFzgD8CrgSGgJ9HxM7MHGz1a9VruVdr5GxASZouzU5V0QrtvjD6JcChzPzLzPxb4AFg3XS80ODw8VP9a4Mjx2t+co625E8t26KX1OXa3b2zBHil6v4QcOnYlSJiE7CpuPtmRLwwydc756/gr0fv7G9gg29M8oVmkXOoqnNJWOfuV7b6Apyz419Pqc5/r1Zhu0M/apTlaQWZ24BtU36xiL2ZOTDV5+kk1rkcylbnstUXpq/O7e7eGQLOr7q/FBhu8z5IUmm1O/R/DqyIiOUR8T5gA7CzzfsgSaXV1u6dzHw3Im4EfkxlyOb2zDwwjS855S6iDmSdy6FsdS5bfWGa6hyZp3WpS5K6VLu7dyRJM8jQl6QS6crQj4i1EfFCRByKiM0zvT+tEhHnR8RPIuJgRByIiC8V5YsiYldEvFjcLqza5qbifXghIq6aub2fmoiYExH/MyIeKe53dZ0j4jcj4s8i4vni9/3xbq5zRPzb4m96f0R8NyLmdmN9I2J7RByNiP1VZU3XMyIuiojnisduj4haw+Fry8yu+qFygPgl4LeA9wH/C+if6f1qUd36gI8VywuA/w30A/8J2FyUbwb+Y7HcX9T/LGB58b7Mmel6TLLu/w64H3ikuN/VdQbuBf5Vsfw+4De7tc5UTto8DMwr7u8ANnZjfYF/AHwM2F9V1nQ9gT3Ax6mc+/Qo8E8b3YdubOm3baqHdsvMkcx8tlg+ARyk8g+zjkpIUNyuL5bXAQ9k5tuZeRg4ROX96SgRsRT4FPDtquKurXNE9FAJh7sBMvNvM/MXdHGdqYwknBcRZwDzqZy/03X1zcyfAm+MKW6qnhHRB/Rk5u6sfALcV7XNhLox9GtN9bBkhvZl2kTEMuCjwNPAuZk5ApUPBuADxWrd8l78Z+DfA39XVdbNdf4t4Bjw34ourW9HxPvp0jpn5qvALcDLwAjwfzPzz+nS+tbQbD2XFMtjyxvSjaHf0FQPnSwizga+D3w5M8ebSrTj34uI+GfA0cx8ptFNapR1VJ2ptHo/BtyZmR8Ffknla389HV3nog97HZUujPOA90fE7463SY2yjqlvE+rVc0r178bQ7+qpHiLiTCqB/53M/EFR/FrxlY/i9mhR3g3vxWXAv4iII1S66v5RRPwp3V3nIWAoM58u7v8ZlQ+Bbq3zPwYOZ+axzHwH+AHw9+ne+o7VbD2HiuWx5Q3pxtDv2qkeiiP0dwMHM/PWqod2AtcVy9cBD1WVb4iIsyJiObCCygGgjpGZN2Xm0sxcRuV3+T8y83fp7jr/H+CViLigKLoCGKR76/wysCYi5hd/41dQOV7VrfUdq6l6Fl1AJyJiTfF+XVu1zcRm+mj2NB0h/ySVkS0vAb8/0/vTwnp9gsrXuL8A9hU/nwR6gceBF4vbRVXb/H7xPrxAE0f4Z+MPcDm/Hr3T1XUGVgN7i9/1D4GF3VxnYAvwPJUZ0P+EyoiVrqsv8F0qxy3eodJiv34y9QQGivfqJeAPKWZXaOTHaRgkqUS6sXtHklSHoS9JJWLoS1KJGPqSVCKGviSVSLsvjC51nIh4MzPPrrq/kcqQuRHgM0XxhcBzxfL2zLy9rTspNcjQlyYpM7cCW+HUB8Pqmd0jaWJ270hSidjSlyY2LyL2Vd1fRJdM7aHyMfSlif2quuumqk9f6jh270hSiRj6klQihr4klYizbEpSidjSl6QSMfQlqUQMfUkqEUNfkkrE0JekEjH0JalEDH1JKpH/D/oDvd85CN/+AAAAAElFTkSuQmCC",
256+
"text/plain": [
257+
"<Figure size 432x288 with 1 Axes>"
258+
]
259+
},
260+
"metadata": {
261+
"needs_background": "light"
262+
},
263+
"output_type": "display_data"
264+
}
265+
],
266+
"source": [
267+
"output[0].plot(label=\"ttbar\")\n",
268+
"plt.legend();"
269+
]
270+
}
271+
],
272+
"metadata": {
273+
"kernelspec": {
274+
"display_name": "Python 3 (ipykernel)",
275+
"language": "python",
276+
"name": "python3"
277+
},
278+
"language_info": {
279+
"codemirror_mode": {
280+
"name": "ipython",
281+
"version": 3
282+
},
283+
"file_extension": ".py",
284+
"mimetype": "text/x-python",
285+
"name": "python",
286+
"nbconvert_exporter": "python",
287+
"pygments_lexer": "ipython3",
288+
"version": "3.8.13"
289+
}
290+
},
291+
"nbformat": 4,
292+
"nbformat_minor": 5
293+
}

0 commit comments

Comments
 (0)