{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": { "mystnb": { "nb_execution_mode": "off" } }, "source": [ "# Emissions Trends\n", "**A snapshot of emissions trends for both marginal and total with respect to regional prices**
\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Data Extraction\n", "#### Import Packages" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [ "hide-cell" ] }, "outputs": [], "source": [ "import nemed\n", "import nemosis\n", "\n", "# To generate plots shown\n", "import pandas as pd\n", "import numpy as np\n", "import plotly.graph_objects as go\n", "import plotly.express as px\n", "from plotly.subplots import make_subplots\n", "\n", "# Open plot in browser (optional)\n", "import plotly.io as pio\n", "pio.renderers.default = \"browser\"\n", "\n", "# Hide Logging output\n", "import logging\n", "logging.getLogger(\"nemosis\").setLevel(logging.WARNING)\n", "logging.getLogger(\"nemed\").setLevel(logging.WARNING)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "#### Processing Emissions Data\n", "This example serves as a snapshot of trends rather than a detailled tutorial. We recommend you first explore the [total emissions example](https://nemed.readthedocs.io/en/latest/examples/total_emissions.html) and [marginal emissions example](https://nemed.readthedocs.io/en/latest/examples/marginal_emissions.html) for understanding on how `NEMED` extracts and processes emissions.\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "start_time = \"2019/01/01 00:00\"\n", "end_time = \"2020/01/01 00:00\"\n", "cache = \"E:\\TEMPCACHE_nemed_demo\"" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Download market prices using NEMOSIS" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "prices = nemosis.dynamic_data_compiler(start_time=start_time+\":00\", \n", " end_time=end_time+\":00\", \n", " table_name='DISPATCHPRICE', \n", " raw_data_location=cache,\n", " fformat='feather',\n", " select_columns=['SETTLEMENTDATE','REGIONID','RRP','INTERVENTION'],\n", " keep_csv=False)\n", "prices = prices.rename(columns = {'SETTLEMENTDATE': 'Time', 'REGIONID': 'Region', 'RRP': 'Prices'})\n", "prices = prices[prices['INTERVENTION']==0]" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Download Total Emissions" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "tags": [ "hide-output" ] }, "outputs": [], "source": [ "total = nemed.get_total_emissions(start_time=start_time,\n", " end_time=end_time,\n", " cache=cache,\n", " by=None)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeEndingRegionEnergyTotal_EmissionsIntensity_Index
02019-01-01 00:05:00NEM0.0000000.0000000.000000
12019-01-01 00:05:00NSW10.0000000.0000000.000000
22019-01-01 00:05:00QLD10.0000000.0000000.000000
32019-01-01 00:05:00SA10.0000000.0000000.000000
42019-01-01 00:05:00TAS10.0000000.0000000.000000
..................
6307152020-01-01 00:00:00NSW1676.491550536.6092090.793224
6307162020-01-01 00:00:00QLD1513.112938411.9237000.802793
6307172020-01-01 00:00:00SA1117.76004349.0242130.416306
6307182020-01-01 00:00:00TAS152.4083700.0000000.000000
6307192020-01-01 00:00:00VIC1358.095808353.5486180.987302
\n", "

630720 rows × 5 columns

\n", "
" ], "text/plain": [ " TimeEnding Region Energy Total_Emissions \\\n", "0 2019-01-01 00:05:00 NEM 0.000000 0.000000 \n", "1 2019-01-01 00:05:00 NSW1 0.000000 0.000000 \n", "2 2019-01-01 00:05:00 QLD1 0.000000 0.000000 \n", "3 2019-01-01 00:05:00 SA1 0.000000 0.000000 \n", "4 2019-01-01 00:05:00 TAS1 0.000000 0.000000 \n", "... ... ... ... ... \n", "630715 2020-01-01 00:00:00 NSW1 676.491550 536.609209 \n", "630716 2020-01-01 00:00:00 QLD1 513.112938 411.923700 \n", "630717 2020-01-01 00:00:00 SA1 117.760043 49.024213 \n", "630718 2020-01-01 00:00:00 TAS1 52.408370 0.000000 \n", "630719 2020-01-01 00:00:00 VIC1 358.095808 353.548618 \n", "\n", " Intensity_Index \n", "0 0.000000 \n", "1 0.000000 \n", "2 0.000000 \n", "3 0.000000 \n", "4 0.000000 \n", "... ... \n", "630715 0.793224 \n", "630716 0.802793 \n", "630717 0.416306 \n", "630718 0.000000 \n", "630719 0.987302 \n", "\n", "[630720 rows x 5 columns]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "total" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Download Marginal Emissions" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "tags": [ "hide-output" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "WARNING: Warning: Gen_info table only has most recent NEM registration and exemption list. Does not account for retired generators\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " 0%| | 0/3 [00:00\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeRegionIntensity_IndexDUIDCO2E_ENERGY_SOURCE
02019-01-01 00:05:00NSW10.421647PPCCGTNatural Gas (Pipeline)
12019-01-01 00:05:00QLD10.401443PPCCGTNatural Gas (Pipeline)
22019-01-01 00:05:00SA10.473708PPCCGTNatural Gas (Pipeline)
32019-01-01 00:05:00TAS10.477227PPCCGTNatural Gas (Pipeline)
42019-01-01 00:05:00VIC10.453253PPCCGTNatural Gas (Pipeline)
..................
5190692020-01-01 00:00:00NSW10.908305VP5Black coal
5190702020-01-01 00:00:00QLD10.942021VP6Black coal
5190712020-01-01 00:00:00SA10.681150TORRB3Natural Gas (Pipeline)
5190722020-01-01 00:00:00TAS10.000000GORDONHydro
5190732020-01-01 00:00:00VIC10.672636TORRB3Natural Gas (Pipeline)
\n", "

519074 rows × 5 columns

\n", "" ], "text/plain": [ " Time Region Intensity_Index DUID \\\n", "0 2019-01-01 00:05:00 NSW1 0.421647 PPCCGT \n", "1 2019-01-01 00:05:00 QLD1 0.401443 PPCCGT \n", "2 2019-01-01 00:05:00 SA1 0.473708 PPCCGT \n", "3 2019-01-01 00:05:00 TAS1 0.477227 PPCCGT \n", "4 2019-01-01 00:05:00 VIC1 0.453253 PPCCGT \n", "... ... ... ... ... \n", "519069 2020-01-01 00:00:00 NSW1 0.908305 VP5 \n", "519070 2020-01-01 00:00:00 QLD1 0.942021 VP6 \n", "519071 2020-01-01 00:00:00 SA1 0.681150 TORRB3 \n", "519072 2020-01-01 00:00:00 TAS1 0.000000 GORDON \n", "519073 2020-01-01 00:00:00 VIC1 0.672636 TORRB3 \n", "\n", " CO2E_ENERGY_SOURCE \n", "0 Natural Gas (Pipeline) \n", "1 Natural Gas (Pipeline) \n", "2 Natural Gas (Pipeline) \n", "3 Natural Gas (Pipeline) \n", "4 Natural Gas (Pipeline) \n", "... ... \n", "519069 Black coal \n", "519070 Black coal \n", "519071 Natural Gas (Pipeline) \n", "519072 Hydro \n", "519073 Natural Gas (Pipeline) \n", "\n", "[519074 rows x 5 columns]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "marginal" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The following function helps to arrange the above data into a single dataframe and aggregate to average hourly resolution." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "def arrange_data_into_hourly(price_df, total_df, marginal_df):\n", " # Group data by Hour, Region\n", " total_df.rename(columns={'Intensity_Index': 'Average_EI',\n", " 'TimeEnding': 'Time'}, inplace=True)\n", " data = pd.merge(price_df, total, how='left', on=['Time','Region'])\n", " data = pd.merge(data, marginal_df.rename(columns={'Intensity_Index': 'Marginal_EI'}),\n", " how='left', on=['Time','Region'])\n", " data.set_index('Time', inplace=True)\n", " data_hr = data.groupby([data.index.hour, data.Region]).mean()\n", " data_hr.index.names = ['hour','Region']\n", " return data_hr.reset_index()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeRegionINTERVENTIONPrices
02019-01-01 00:05:00NSW1068.09260
12019-01-01 00:05:00QLD1064.82955
22019-01-01 00:05:00SA1076.50000
32019-01-01 00:05:00TAS1077.06842
42019-01-01 00:05:00VIC1073.19672
...............
537252020-01-01 00:00:00NSW1048.50000
537262020-01-01 00:00:00QLD1050.30038
537272020-01-01 00:00:00SA1069.00000
537282020-01-01 00:00:00TAS1081.95000
537292020-01-01 00:00:00VIC1068.13710
\n", "

525600 rows × 4 columns

\n", "
" ], "text/plain": [ " Time Region INTERVENTION Prices\n", "0 2019-01-01 00:05:00 NSW1 0 68.09260\n", "1 2019-01-01 00:05:00 QLD1 0 64.82955\n", "2 2019-01-01 00:05:00 SA1 0 76.50000\n", "3 2019-01-01 00:05:00 TAS1 0 77.06842\n", "4 2019-01-01 00:05:00 VIC1 0 73.19672\n", "... ... ... ... ...\n", "53725 2020-01-01 00:00:00 NSW1 0 48.50000\n", "53726 2020-01-01 00:00:00 QLD1 0 50.30038\n", "53727 2020-01-01 00:00:00 SA1 0 69.00000\n", "53728 2020-01-01 00:00:00 TAS1 0 81.95000\n", "53729 2020-01-01 00:00:00 VIC1 0 68.13710\n", "\n", "[525600 rows x 4 columns]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "prices" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hourRegionINTERVENTIONPricesEnergyTotal_EmissionsAverage_EIMarginal_EI
00NSW10.071.563565597.993603468.1586590.7804880.746162
10QLD10.064.302266517.315615401.5272640.7743280.767774
20SA10.087.138166127.77934437.7748710.3027470.514765
30TAS10.086.85724387.1872310.5457510.0070200.291249
40VIC10.088.493301386.696932354.7321100.9163010.497278
...........................
11523NSW10.077.933472628.251938489.9951850.7795990.702943
11623QLD10.068.372989547.849366423.3481450.7730680.744226
11723SA10.097.778069132.84823641.1430970.3159650.413469
11823TAS10.093.02747092.2450260.7163840.0085090.262014
11923VIC10.0103.507738396.581260357.8247310.9038700.389096
\n", "

120 rows × 8 columns

\n", "
" ], "text/plain": [ " hour Region INTERVENTION Prices Energy Total_Emissions \\\n", "0 0 NSW1 0.0 71.563565 597.993603 468.158659 \n", "1 0 QLD1 0.0 64.302266 517.315615 401.527264 \n", "2 0 SA1 0.0 87.138166 127.779344 37.774871 \n", "3 0 TAS1 0.0 86.857243 87.187231 0.545751 \n", "4 0 VIC1 0.0 88.493301 386.696932 354.732110 \n", ".. ... ... ... ... ... ... \n", "115 23 NSW1 0.0 77.933472 628.251938 489.995185 \n", "116 23 QLD1 0.0 68.372989 547.849366 423.348145 \n", "117 23 SA1 0.0 97.778069 132.848236 41.143097 \n", "118 23 TAS1 0.0 93.027470 92.245026 0.716384 \n", "119 23 VIC1 0.0 103.507738 396.581260 357.824731 \n", "\n", " Average_EI Marginal_EI \n", "0 0.780488 0.746162 \n", "1 0.774328 0.767774 \n", "2 0.302747 0.514765 \n", "3 0.007020 0.291249 \n", "4 0.916301 0.497278 \n", ".. ... ... \n", "115 0.779599 0.702943 \n", "116 0.773068 0.744226 \n", "117 0.315965 0.413469 \n", "118 0.008509 0.262014 \n", "119 0.903870 0.389096 \n", "\n", "[120 rows x 8 columns]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data_by_hr = arrange_data_into_hourly(prices, total, marginal)\n", "data_by_hr" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Chart 1 - CY2019 Emissions Trends\n", "Toggle to unhide the cell below containing a charting function for plotly" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "tags": [ "hide-cell" ] }, "outputs": [], "source": [ "def NORD_theme():\n", " plotly_NORD_theme = pio.templates[\"simple_white\"]\n", " plotly_NORD_theme.layout.plot_bgcolor = \"#f4f4f5\" \n", " plotly_NORD_theme.layout.paper_bgcolor = \"#ffffff\"\n", " plotly_NORD_theme.layout.xaxis.gridcolor = '#d8dee9'\n", " plotly_NORD_theme.layout.yaxis.gridcolor = '#d8dee9'\n", " return plotly_NORD_theme\n", "\n", "def emissions_trend_chart(hourly_df):\n", " # Mainland Only\n", " plt_df = hourly_df.copy()[hourly_df['Region']!='TAS1']\n", "\n", " from nemglo import defaults_plot\n", " fig = make_subplots(rows=2, cols=2,\n", " specs=2*[2*[{'secondary_y': True}]],\n", " vertical_spacing=0.15, horizontal_spacing=0.2,\n", " subplot_titles=(\"NSW\",\"QLD\",\"SA\",\"VIC\"),\n", " shared_xaxes=True, shared_yaxes=True)\n", "\n", " # Data\n", " for idx, reg in enumerate(plt_df['Region'].unique()):\n", " sub_df = plt_df[plt_df['Region'] == reg]\n", " fig.add_trace(go.Scatter(x=sub_df.hour,\n", " y=sub_df['Average_EI'].round(3),\n", " name=f\"Average EI (tCO2-e/MWh)\",\n", " showlegend=False,\n", " line={'color': '#5BC8C5'}), row=(idx)//2+1, col=(idx)%2+1)\n", "\n", " fig.add_trace(go.Scatter(x=sub_df.hour,\n", " y=sub_df['Marginal_EI'].round(3),\n", " name='Marginal EI (tCO2-e/MWh)',\n", " showlegend=False,\n", " line={'color': '#4f6980'}), row=(idx)//2+1, col=(idx)%2+1)\n", "\n", " fig.add_trace(go.Scatter(x=sub_df.hour,\n", " y=sub_df['Prices'].round(2),\n", " name='Energy Price ($/MWh)',\n", " showlegend=False,\n", " line={'color': '#AD134C'},\n", " ), secondary_y=True, row=(idx)//2+1, col=(idx)%2+1)\n", "\n", " # Axis definitions\n", " ax_time = dict(title=\"Hour of Day\", showgrid=True, mirror=True, showticklabels=True,\n", " tickvals=[i for i in range(0,25,2)])\n", "\n", " ax_price = dict(title=dict(text=\"Price ($/MWh)\",), showticklabels=True,\n", " showgrid=False, autorange=False, automargin=False,\n", " range=[0,250], tickvals=[i for i in range(0,251,50)],\n", " mirror=True,\n", " side=\"right\",\n", " color='#AD134C')\n", "\n", " ax_emissions = dict(title=\"Emissions Intensity (tCO2-e/MWh)\", showticklabels=True,\n", " showgrid=True, autorange=False,\n", " range=[0,1], tickvals=[i*10**-2 for i in range(0, 121, 20)],\n", " mirror=True, rangemode='tozero', constraintoward='bottom')\n", "\n", " # Layout\n", " fig.update_layout(xaxis=ax_time, xaxis2=ax_time, xaxis3=ax_time, xaxis4=ax_time,\n", " yaxis=ax_emissions, yaxis2=ax_price,\n", " yaxis3=ax_emissions, yaxis4=ax_price,\n", " yaxis5=ax_emissions, yaxis6=ax_price,\n", " yaxis7=ax_emissions, yaxis8=ax_price)\n", " fig._data_objs[0].showlegend = True\n", " fig._data_objs[1].showlegend = True\n", " fig._data_objs[2].showlegend = True\n", "\n", " # Fonts\n", " FONT_SIZE = 16\n", " FONT_STYLE = \"Raleway\"\n", " fonts = dict(tickfont=dict(size=FONT_SIZE, family=FONT_STYLE),\n", " titlefont=dict(size=FONT_SIZE, family=FONT_STYLE))\n", " fig.update_annotations(font=dict(size=FONT_SIZE, family=FONT_STYLE)) \n", " fig.update_layout(xaxis=fonts, xaxis2=fonts, xaxis3=fonts, xaxis4=fonts,\n", " yaxis=fonts, yaxis2=fonts, yaxis3=fonts, yaxis4=fonts,\n", " yaxis5=fonts, yaxis6=fonts, yaxis7=fonts, yaxis8=fonts, yaxis9=fonts,\n", " legend=dict(font=dict(size=FONT_SIZE-2, family=FONT_STYLE)),\n", " title_font_family=FONT_STYLE,\n", " title_font_size=22)\n", "\n", " # Other Formatting\n", " fig.update_layout(\n", " title=dict(text=f\"Historical CY2019 Hourly Average & Marginal Emissions \" + \\\n", " \"Intensities against Price
\" + \\\n", " \"NEMED | Average/Marginal Emissions Methodology | \" + \\\n", " \"Mainland Regional Emissions Trends\",\n", " y=0.95),\n", " margin=dict(l=80, r=60, t=120, b=20),\n", " legend=dict(xanchor='center', x=0.5, y=-0.15, orientation='h'),\n", " hovermode=\"x\",\n", " width=1000,\n", " height=800,\n", " template=NORD_theme())\n", " return fig" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "INFO: Using Python-MIP package version 1.13.0\n" ] } ], "source": [ "emissions_trend_chart(data_by_hr)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "```{admonition} Interactive Plot\n", "Click the image to open the plot as an interactive plotly\n", "```\n", "\n", "```{image} charts/emissions_trends_chart_1.png\n", ":target: ../_static/html_charts/emissions_trends_chart_1.html\n", "```" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.9.12 ('nempy')", "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.12 (main, Apr 4 2022, 05:22:27) [MSC v.1916 64 bit (AMD64)]" }, "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "4aab49ac747d4948ee2428bd46f4ac833ef94a37ecb38233c747c75e4d05fe4b" } } }, "nbformat": 4, "nbformat_minor": 2 }