Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save deeplycloudy/7b8412094c7a249d19b771374f312750 to your computer and use it in GitHub Desktop.
Save deeplycloudy/7b8412094c7a249d19b771374f312750 to your computer and use it in GitHub Desktop.
map factor exploration notebook by @kgoebber
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "afaa4d0d",
"metadata": {},
"outputs": [],
"source": [
"from datetime import datetime\n",
"\n",
"import cartopy.crs as ccrs\n",
"import cartopy.feature as cfeature\n",
"import matplotlib.pyplot as plt\n",
"import metpy.calc as mpcalc\n",
"import metpy.constants as mpconst\n",
"from metpy.units import units\n",
"import numpy as np\n",
"import pint\n",
"from pyproj import Proj\n",
"import xarray as xr"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "9f1ce617",
"metadata": {},
"outputs": [],
"source": [
"def read_gdlist(name):\n",
" file = open(name, 'rb')\n",
"\n",
" for _ in range(6):\n",
" file.readline()\n",
"\n",
" grid_row = file.readline()\n",
" nlon = int(grid_row[-11:-5].strip())\n",
" nlat = int(grid_row[-4:].strip())\n",
" #print(nlon,nlat)\n",
"\n",
" gempak_array = np.empty((nlat,nlon))\n",
"\n",
" for _ in range(2):\n",
" file.readline()\n",
"\n",
" scale_row = file.readline()\n",
" scale_factor = int(scale_row[19:].strip())\n",
" #print(scale_factor)\n",
"\n",
" for _ in range(92):\n",
" file.readline()\n",
"\n",
" col = 0\n",
" row = 0\n",
" for line in file.readlines():\n",
" if (line[:13].strip() != b'') & (col >= nlon):\n",
" col = 0\n",
" row+=1\n",
" for count in [0,1,2,3,4,5,6,7]:\n",
" gempak_array[row,col] = line[8+count*9:17+count*9]\n",
" col+=1\n",
"\n",
" file.close()\n",
" \n",
" return (gempak_array, -scale_factor)\n",
"\n",
"def error_stats(metpy_data, gempak_data):\n",
" ignore = (gempak_data != -9999.0) * ~np.isnan(metpy_data)\n",
" \n",
" if isinstance(metpy_data.data, pint.Quantity):\n",
" print(f'Is Xarray with Quantity? True')\n",
" mdata = metpy_data.values[ignore]\n",
" elif isinstance(metpy_data, pint.Quantity):\n",
" print(f'Is Xarray with Quantity? False')\n",
" print(f'Is Metpy Unit Array? True')\n",
" mdata = metpy_data.m[ignore]\n",
" else:\n",
" print(f'Is Xarray with Quantity? False')\n",
" print(f'Is Metpy Unit Array? False')\n",
" print(f'I got back just a numpy array')\n",
" try:\n",
" mdata = metpy_data.values[ignore]\n",
" except:\n",
" mdata = metpy_data[ignore]\n",
" gempak_data = gempak_data[ignore]\n",
" \n",
" print()\n",
" print('Mean Comparison')\n",
" print(f' Mean Values (MetPy): {mdata.mean()}')\n",
" print(f' Mean Values (GEMPAK): {gempak_data.mean()}')\n",
" print()\n",
" print('Max Comparison')\n",
" print(f' Max Values (MetPy): {mdata.max()}')\n",
" print(f' Max Values (GEMPAK): {gempak_data.max()}')\n",
" print()\n",
" print('Min Comparison')\n",
" print(f' Min Values (MetPy): {mdata.min()}')\n",
" print(f' Min Values (GEMPAK): {gempak_data.min()}')\n",
"\n",
" print()\n",
" print('Difference Array')\n",
" diff = mdata - gempak_data\n",
" print(diff)\n",
" print()\n",
" print('Various Statistical Analyses')\n",
" print(f' Average Absolute Difference: {np.nanmean(np.abs(diff))}')\n",
" print(f' RMS Error: {np.sqrt(np.nansum(diff**2))/len(diff.ravel())}')\n",
" print(f' Standard Deviation of Difference: {np.nanstd(diff)}')\n",
" print(f' Max Diff: {np.max(diff)}')\n",
" print(f' Min Diff: {np.min(diff)}')\n",
" print(f' Correlation: {np.corrcoef(mdata.ravel(), gempak_data.ravel())[0][1]}')\n",
" print(f' Relative Magnitude Difference: {np.nanmean(np.abs(diff))/np.nanmax(mdata)}')\n",
" print()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1f78dbd6",
"metadata": {},
"outputs": [],
"source": [
"# %%bash\n",
"# To get data sources uncomment and run these lines\n",
"# wget http://bergeron.valpo.edu/testing_data/gempak_absolute_vorticity.out\n",
"# wget http://bergeron.valpo.edu/testing_data/gempak_vorticity.out\n",
"# wget http://bergeron.valpo.edu/testing_data/gfs_test_data.nc"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "3be937a5",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Could not find variable corresponding to the value of grid_mapping: LatLon_Projection\n",
"Found valid latitude/longitude coordinates, assuming latitude_longitude for projection grid_mapping variable\n",
"Could not find variable corresponding to the value of grid_mapping: LatLon_Projection\n",
"Found valid latitude/longitude coordinates, assuming latitude_longitude for projection grid_mapping variable\n",
"Could not find variable corresponding to the value of grid_mapping: LatLon_Projection\n",
"Found valid latitude/longitude coordinates, assuming latitude_longitude for projection grid_mapping variable\n",
"Could not find variable corresponding to the value of grid_mapping: LatLon_Projection\n",
"Found valid latitude/longitude coordinates, assuming latitude_longitude for projection grid_mapping variable\n",
"Could not find variable corresponding to the value of grid_mapping: LatLon_Projection\n",
"Found valid latitude/longitude coordinates, assuming latitude_longitude for projection grid_mapping variable\n",
"Could not find variable corresponding to the value of grid_mapping: LatLon_Projection\n",
"Found valid latitude/longitude coordinates, assuming latitude_longitude for projection grid_mapping variable\n"
]
}
],
"source": [
"gfs_data = xr.open_dataset('gfs_test_data.nc').metpy.parse_cf()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "248399da",
"metadata": {},
"outputs": [],
"source": [
"nominal_dlon = np.diff(gfs_data.lon).min(), np.diff(gfs_data.lon).max()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "6beff0d4",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/ebruning/miniconda3/envs/glmval/lib/python3.6/site-packages/metpy/xarray.py:350: UserWarning: More than one vertical coordinate present for variable \"u-component_of_wind_isobaric\".\n",
" + varname + '.')\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Vorticity \n",
"\n",
"Is Xarray with Quantity? True\n",
"\n",
"Mean Comparison\n",
" Mean Values (MetPy): 0.004190604253050805\n",
" Mean Values (GEMPAK): -0.04004379610999328\n",
"\n",
"Max Comparison\n",
" Max Values (MetPy): 36.85836141622791\n",
" Max Values (GEMPAK): 37.241\n",
"\n",
"Min Comparison\n",
" Min Values (MetPy): -109.36218724456099\n",
" Min Values (GEMPAK): -109.249\n",
"\n",
"Difference Array\n",
"[4.8571861 4.81715645 4.77918593 ... 4.10353833 4.11470056 4.12481571]\n",
"\n",
"Various Statistical Analyses\n",
" Average Absolute Difference: 0.28709621883200087\n",
" RMS Error: 0.001081157362941307\n",
" Standard Deviation of Difference: 0.5425170190877117\n",
" Max Diff: 6.099662681357114\n",
" Min Diff: -7.052885069441876\n",
" Correlation: 0.9917837585441162\n",
" Relative Magnitude Difference: 0.007789174770683074\n",
"\n",
"\n",
"Vorticity with spherical corrections \n",
"\n",
"Is Xarray with Quantity? True\n",
"\n",
"Mean Comparison\n",
" Mean Values (MetPy): -0.040009735834369675\n",
" Mean Values (GEMPAK): -0.04004379610999328\n",
"\n",
"Max Comparison\n",
" Max Values (MetPy): 37.12151797836928\n",
" Max Values (GEMPAK): 37.241\n",
"\n",
"Min Comparison\n",
" Min Values (MetPy): -109.42257747106937\n",
" Min Values (GEMPAK): -109.249\n",
"\n",
"Difference Array\n",
"[-0.01930622 -0.01737796 -0.01938306 ... -0.02309015 -0.02391615\n",
" -0.02578924]\n",
"\n",
"Various Statistical Analyses\n",
" Average Absolute Difference: 0.008749093806363292\n",
" RMS Error: 2.4846320358544894e-05\n",
" Standard Deviation of Difference: 0.012509033426775323\n",
" Max Diff: 0.1384043786487581\n",
" Min Diff: -0.1780466505300069\n",
" Correlation: 0.9999970652706868\n",
" Relative Magnitude Difference: 0.00023568793203611422\n",
"\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/ebruning/miniconda3/envs/glmval/lib/python3.6/site-packages/pint/quantity.py:1237: RuntimeWarning: invalid value encountered in true_divide\n",
" magnitude = magnitude_op(new_self._magnitude, other._magnitude)\n"
]
}
],
"source": [
"# Vorticity\n",
"\n",
"gempak_out_var, scale = read_gdlist('gempak_vorticity.out')\n",
"\n",
"out_var = gempak_out_var * 10**scale\n",
"\n",
"data_var_u = gfs_data['u-component_of_wind_isobaric'].sel(time=datetime(2018, 3, 8, 0), isobaric2=50000).metpy.quantify()\n",
"data_var_v = gfs_data['v-component_of_wind_isobaric'].sel(time=datetime(2018, 3, 8, 0), isobaric2=50000).metpy.quantify()\n",
"\n",
"data_var_lat = gfs_data.lat.values\n",
"\n",
"vor = mpcalc.vorticity(data_var_u, data_var_v)\n",
"\n",
"print('Vorticity \\n')\n",
"error_stats(vor[3:-3,3:-3]*1e5, out_var[3:-3,3:-3]*1e5)\n",
"\n",
"vor_corrected = vor + data_var_u / mpconst.earth_avg_radius * np.tan(np.deg2rad(data_var_lat[:, None]))\n",
"\n",
"print('\\nVorticity with spherical corrections \\n')\n",
"error_stats(vor_corrected[3:-3,3:-3]*1e5, out_var[3:-3,3:-3]*1e5)"
]
},
{
"cell_type": "markdown",
"id": "bf57ff87",
"metadata": {},
"source": [
"## Begin Testing Calcualtions with Map Factor"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "5a38b78a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Geographic 2D CRS: {\"$schema\": \"https://proj.org/schemas/v0.2/projjso ...>\n",
"Name: undefined\n",
"Axis Info [ellipsoidal]:\n",
"- lon[east]: Longitude (degree)\n",
"- lat[north]: Latitude (degree)\n",
"Area of Use:\n",
"- undefined\n",
"Datum: World Geodetic System 1984\n",
"- Ellipsoid: WGS 84\n",
"- Prime Meridian: Greenwich"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data_var_u.metpy.pyproj_crs"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "ceecf4eb",
"metadata": {},
"outputs": [],
"source": [
"xx, yy = np.meshgrid(gfs_data.lon.values, gfs_data.lat.values)\n",
"factors = Proj(data_var_u.metpy.pyproj_crs).get_factors(xx, yy)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "967a6b45",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/ebruning/miniconda3/envs/glmval/lib/python3.6/site-packages/pint/quantity.py:1237: RuntimeWarning: invalid value encountered in true_divide\n",
" magnitude = magnitude_op(new_self._magnitude, other._magnitude)\n"
]
}
],
"source": [
"dx, dy = mpcalc.lat_lon_grid_deltas(gfs_data.lon, gfs_data.lat)\n",
"dudy = mpcalc.first_derivative(data_var_u, delta=dy, axis=-2)\n",
"dvdx = mpcalc.first_derivative(data_var_v, delta=dx, axis=-1)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "14260d1e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.9999999999954489 1.0000000000065512\n",
"0.0 0.0\n",
"-5.551115123125782e-12 5.551115123125782e-12\n",
"0.9999999999954489 1.000000000001\n"
]
}
],
"source": [
"# Since the data are in lat-lon, there is no gradient in the data coordinate as a function of latitude and longitude.\n",
"print(factors.dx_dlam.min(), factors.dx_dlam.max())\n",
"print(factors.dx_dphi.min(), factors.dx_dphi.max())\n",
"print(factors.dy_dlam.min(), factors.dy_dlam.max())\n",
"print(factors.dy_dphi.min(), factors.dy_dphi.max())"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "8c722858",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.9999999999954489 99664.71893460966\n",
"0.9966471893317242 1.0067394967422765\n"
]
}
],
"source": [
"print(factors.parallel_scale.min(), factors.parallel_scale.max())\n",
"print(factors.meridional_scale.min(), factors.meridional_scale.max())"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "3189b63e",
"metadata": {},
"outputs": [],
"source": [
"m_x = factors.parallel_scale #*0.0+1.0\n",
"m_y = factors.meridional_scale #*0.0+1.0"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "753d75f2",
"metadata": {},
"outputs": [],
"source": [
"# Calculating Vorticity using Map Factors\n",
"zeta = (m_x * dvdx - m_y * dudy\n",
" - data_var_v * (m_x/m_y) * mpcalc.first_derivative(m_y, delta=dx, axis=-1)\n",
" + data_var_u * (m_y/m_x) * mpcalc.first_derivative(m_x, delta=dy, axis=-2)\n",
"# - (data_var_v * (m_y/m_x) * 1.0* mpcalc.first_derivative(m_x, delta=dx, axis=-1))\n",
"# + (data_var_u * (m_x/m_y) * 1.0* mpcalc.first_derivative(m_y, delta=dy, axis=-2))\n",
" )\n",
"avor = zeta + mpcalc.coriolis_parameter(gfs_data.lat * units.degree)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "cc5dee50-cfc5-45ad-b4a2-0dfcc31a5e55",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-4.336808689942018e-19 / meter 4.336808689942018e-19 / meter\n",
"-2.685325470474315 / meter 2.6853254704743144 / meter\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/ebruning/miniconda3/envs/glmval/lib/python3.6/site-packages/pint/quantity.py:1237: RuntimeWarning: invalid value encountered in true_divide\n",
" magnitude = magnitude_op(new_self._magnitude, other._magnitude)\n"
]
}
],
"source": [
"dmy_dx = mpcalc.first_derivative(m_y, delta=dx, axis=-1)\n",
"dmx_dy = mpcalc.first_derivative(m_x, delta=dy, axis=-2)\n",
"print(np.nanmin(dmy_dx), np.nanmax(dmy_dx))\n",
"print(np.nanmin(dmx_dy), np.nanmax(dmx_dy))"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "3da25d0a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Is Xarray with Quantity? True\n",
"\n",
"Mean Comparison\n",
" Mean Values (MetPy): -0.07183678672193368\n",
" Mean Values (GEMPAK): -0.04004379610999328\n",
"\n",
"Max Comparison\n",
" Max Values (MetPy): 342.1814814160154\n",
" Max Values (GEMPAK): 37.241\n",
"\n",
"Min Comparison\n",
" Min Values (MetPy): -355.58664420657874\n",
" Min Values (GEMPAK): -109.249\n",
"\n",
"Difference Array\n",
"[164.98828745 152.25663386 164.9976588 ... 126.8622315 139.59828822\n",
" 152.33330786]\n",
"\n",
"Various Statistical Analyses\n",
" Average Absolute Difference: 4.435518627841254\n",
" RMS Error: 0.033026679397460214\n",
" Standard Deviation of Difference: 16.627516946222677\n",
" Max Diff: 309.0504814160154\n",
" Min Diff: -327.34164420657874\n",
" Correlation: 0.4426999229702113\n",
" Relative Magnitude Difference: 0.012962474209551583\n",
"\n"
]
}
],
"source": [
"error_stats(zeta[3:-3,3:-3]*1e5, out_var[3:-3,3:-3]*1e5)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "71906cd6",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div><svg style=\"position: absolute; width: 0; height: 0; overflow: hidden\">\n",
"<defs>\n",
"<symbol id=\"icon-database\" viewBox=\"0 0 32 32\">\n",
"<path d=\"M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z\"></path>\n",
"<path d=\"M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n",
"<path d=\"M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n",
"</symbol>\n",
"<symbol id=\"icon-file-text2\" viewBox=\"0 0 32 32\">\n",
"<path d=\"M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z\"></path>\n",
"<path d=\"M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"<path d=\"M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"<path d=\"M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n",
"</symbol>\n",
"</defs>\n",
"</svg>\n",
"<style>/* CSS stylesheet for displaying xarray objects in jupyterlab.\n",
" *\n",
" */\n",
"\n",
":root {\n",
" --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));\n",
" --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));\n",
" --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));\n",
" --xr-border-color: var(--jp-border-color2, #e0e0e0);\n",
" --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);\n",
" --xr-background-color: var(--jp-layout-color0, white);\n",
" --xr-background-color-row-even: var(--jp-layout-color1, white);\n",
" --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);\n",
"}\n",
"\n",
"html[theme=dark],\n",
"body.vscode-dark {\n",
" --xr-font-color0: rgba(255, 255, 255, 1);\n",
" --xr-font-color2: rgba(255, 255, 255, 0.54);\n",
" --xr-font-color3: rgba(255, 255, 255, 0.38);\n",
" --xr-border-color: #1F1F1F;\n",
" --xr-disabled-color: #515151;\n",
" --xr-background-color: #111111;\n",
" --xr-background-color-row-even: #111111;\n",
" --xr-background-color-row-odd: #313131;\n",
"}\n",
"\n",
".xr-wrap {\n",
" display: block;\n",
" min-width: 300px;\n",
" max-width: 700px;\n",
"}\n",
"\n",
".xr-text-repr-fallback {\n",
" /* fallback to plain text repr when CSS is not injected (untrusted notebook) */\n",
" display: none;\n",
"}\n",
"\n",
".xr-header {\n",
" padding-top: 6px;\n",
" padding-bottom: 6px;\n",
" margin-bottom: 4px;\n",
" border-bottom: solid 1px var(--xr-border-color);\n",
"}\n",
"\n",
".xr-header > div,\n",
".xr-header > ul {\n",
" display: inline;\n",
" margin-top: 0;\n",
" margin-bottom: 0;\n",
"}\n",
"\n",
".xr-obj-type,\n",
".xr-array-name {\n",
" margin-left: 2px;\n",
" margin-right: 10px;\n",
"}\n",
"\n",
".xr-obj-type {\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-sections {\n",
" padding-left: 0 !important;\n",
" display: grid;\n",
" grid-template-columns: 150px auto auto 1fr 20px 20px;\n",
"}\n",
"\n",
".xr-section-item {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-section-item input {\n",
" display: none;\n",
"}\n",
"\n",
".xr-section-item input + label {\n",
" color: var(--xr-disabled-color);\n",
"}\n",
"\n",
".xr-section-item input:enabled + label {\n",
" cursor: pointer;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-section-item input:enabled + label:hover {\n",
" color: var(--xr-font-color0);\n",
"}\n",
"\n",
".xr-section-summary {\n",
" grid-column: 1;\n",
" color: var(--xr-font-color2);\n",
" font-weight: 500;\n",
"}\n",
"\n",
".xr-section-summary > span {\n",
" display: inline-block;\n",
" padding-left: 0.5em;\n",
"}\n",
"\n",
".xr-section-summary-in:disabled + label {\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-section-summary-in + label:before {\n",
" display: inline-block;\n",
" content: '►';\n",
" font-size: 11px;\n",
" width: 15px;\n",
" text-align: center;\n",
"}\n",
"\n",
".xr-section-summary-in:disabled + label:before {\n",
" color: var(--xr-disabled-color);\n",
"}\n",
"\n",
".xr-section-summary-in:checked + label:before {\n",
" content: '▼';\n",
"}\n",
"\n",
".xr-section-summary-in:checked + label > span {\n",
" display: none;\n",
"}\n",
"\n",
".xr-section-summary,\n",
".xr-section-inline-details {\n",
" padding-top: 4px;\n",
" padding-bottom: 4px;\n",
"}\n",
"\n",
".xr-section-inline-details {\n",
" grid-column: 2 / -1;\n",
"}\n",
"\n",
".xr-section-details {\n",
" display: none;\n",
" grid-column: 1 / -1;\n",
" margin-bottom: 5px;\n",
"}\n",
"\n",
".xr-section-summary-in:checked ~ .xr-section-details {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-array-wrap {\n",
" grid-column: 1 / -1;\n",
" display: grid;\n",
" grid-template-columns: 20px auto;\n",
"}\n",
"\n",
".xr-array-wrap > label {\n",
" grid-column: 1;\n",
" vertical-align: top;\n",
"}\n",
"\n",
".xr-preview {\n",
" color: var(--xr-font-color3);\n",
"}\n",
"\n",
".xr-array-preview,\n",
".xr-array-data {\n",
" padding: 0 5px !important;\n",
" grid-column: 2;\n",
"}\n",
"\n",
".xr-array-data,\n",
".xr-array-in:checked ~ .xr-array-preview {\n",
" display: none;\n",
"}\n",
"\n",
".xr-array-in:checked ~ .xr-array-data,\n",
".xr-array-preview {\n",
" display: inline-block;\n",
"}\n",
"\n",
".xr-dim-list {\n",
" display: inline-block !important;\n",
" list-style: none;\n",
" padding: 0 !important;\n",
" margin: 0;\n",
"}\n",
"\n",
".xr-dim-list li {\n",
" display: inline-block;\n",
" padding: 0;\n",
" margin: 0;\n",
"}\n",
"\n",
".xr-dim-list:before {\n",
" content: '(';\n",
"}\n",
"\n",
".xr-dim-list:after {\n",
" content: ')';\n",
"}\n",
"\n",
".xr-dim-list li:not(:last-child):after {\n",
" content: ',';\n",
" padding-right: 5px;\n",
"}\n",
"\n",
".xr-has-index {\n",
" font-weight: bold;\n",
"}\n",
"\n",
".xr-var-list,\n",
".xr-var-item {\n",
" display: contents;\n",
"}\n",
"\n",
".xr-var-item > div,\n",
".xr-var-item label,\n",
".xr-var-item > .xr-var-name span {\n",
" background-color: var(--xr-background-color-row-even);\n",
" margin-bottom: 0;\n",
"}\n",
"\n",
".xr-var-item > .xr-var-name:hover span {\n",
" padding-right: 5px;\n",
"}\n",
"\n",
".xr-var-list > li:nth-child(odd) > div,\n",
".xr-var-list > li:nth-child(odd) > label,\n",
".xr-var-list > li:nth-child(odd) > .xr-var-name span {\n",
" background-color: var(--xr-background-color-row-odd);\n",
"}\n",
"\n",
".xr-var-name {\n",
" grid-column: 1;\n",
"}\n",
"\n",
".xr-var-dims {\n",
" grid-column: 2;\n",
"}\n",
"\n",
".xr-var-dtype {\n",
" grid-column: 3;\n",
" text-align: right;\n",
" color: var(--xr-font-color2);\n",
"}\n",
"\n",
".xr-var-preview {\n",
" grid-column: 4;\n",
"}\n",
"\n",
".xr-var-name,\n",
".xr-var-dims,\n",
".xr-var-dtype,\n",
".xr-preview,\n",
".xr-attrs dt {\n",
" white-space: nowrap;\n",
" overflow: hidden;\n",
" text-overflow: ellipsis;\n",
" padding-right: 10px;\n",
"}\n",
"\n",
".xr-var-name:hover,\n",
".xr-var-dims:hover,\n",
".xr-var-dtype:hover,\n",
".xr-attrs dt:hover {\n",
" overflow: visible;\n",
" width: auto;\n",
" z-index: 1;\n",
"}\n",
"\n",
".xr-var-attrs,\n",
".xr-var-data {\n",
" display: none;\n",
" background-color: var(--xr-background-color) !important;\n",
" padding-bottom: 5px !important;\n",
"}\n",
"\n",
".xr-var-attrs-in:checked ~ .xr-var-attrs,\n",
".xr-var-data-in:checked ~ .xr-var-data {\n",
" display: block;\n",
"}\n",
"\n",
".xr-var-data > table {\n",
" float: right;\n",
"}\n",
"\n",
".xr-var-name span,\n",
".xr-var-data,\n",
".xr-attrs {\n",
" padding-left: 25px !important;\n",
"}\n",
"\n",
".xr-attrs,\n",
".xr-var-attrs,\n",
".xr-var-data {\n",
" grid-column: 1 / -1;\n",
"}\n",
"\n",
"dl.xr-attrs {\n",
" padding: 0;\n",
" margin: 0;\n",
" display: grid;\n",
" grid-template-columns: 125px auto;\n",
"}\n",
"\n",
".xr-attrs dt,\n",
".xr-attrs dd {\n",
" padding: 0;\n",
" margin: 0;\n",
" float: left;\n",
" padding-right: 10px;\n",
" width: auto;\n",
"}\n",
"\n",
".xr-attrs dt {\n",
" font-weight: normal;\n",
" grid-column: 1;\n",
"}\n",
"\n",
".xr-attrs dt:hover span {\n",
" display: inline-block;\n",
" background: var(--xr-background-color);\n",
" padding-right: 10px;\n",
"}\n",
"\n",
".xr-attrs dd {\n",
" grid-column: 2;\n",
" white-space: pre-wrap;\n",
" word-break: break-all;\n",
"}\n",
"\n",
".xr-icon-database,\n",
".xr-icon-file-text2 {\n",
" display: inline-block;\n",
" vertical-align: middle;\n",
" width: 1em;\n",
" height: 1.5em !important;\n",
" stroke-width: 0;\n",
" stroke: currentColor;\n",
" fill: currentColor;\n",
"}\n",
"</style><pre class='xr-text-repr-fallback'>&lt;xarray.Dataset&gt;\n",
"Dimensions: (isobaric2: 5, lat: 361, lon: 720, time: 1)\n",
"Coordinates:\n",
" * lon (lon) float32 0.0 0.5 1.0 ... 359.0 359.5\n",
" height_above_ground3 float32 2.0\n",
" * time (time) datetime64[ns] 2018-03-08\n",
" * lat (lat) float32 90.0 89.5 ... -89.5 -90.0\n",
" metpy_crs object Projection: latitude_longitude\n",
" * isobaric2 (isobaric2) float32 1e+05 ... 4.5e+04\n",
"Data variables:\n",
" Temperature_height_above_ground (time, lat, lon) float32 250.5 ... 229.7\n",
" u-component_of_wind_isobaric (time, isobaric2, lat, lon) float32 -1.6...\n",
" v-component_of_wind_isobaric (time, isobaric2, lat, lon) float32 4.35...\n",
" Temperature_isobaric (time, isobaric2, lat, lon) float32 252....\n",
" Geopotential_height_isobaric (time, isobaric2, lat, lon) float32 235....\n",
" Relative_humidity_isobaric (time, isobaric2, lat, lon) float32 100....\n",
"Attributes:\n",
" Originating_or_generating_Center: ...\n",
" Originating_or_generating_Subcenter: ...\n",
" GRIB_table_version: ...\n",
" Type_of_generating_process: ...\n",
" Analysis_or_forecast_generating_process_identifier_defined_by_originating...\n",
" Conventions: ...\n",
" history: ...\n",
" featureType: ...\n",
" file_format: ...</pre><div class='xr-wrap' hidden><div class='xr-header'><div class='xr-obj-type'>xarray.Dataset</div></div><ul class='xr-sections'><li class='xr-section-item'><input id='section-b31a35d3-dc45-4c66-ba9e-e18df9954c4b' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-b31a35d3-dc45-4c66-ba9e-e18df9954c4b' class='xr-section-summary' title='Expand/collapse section'>Dimensions:</label><div class='xr-section-inline-details'><ul class='xr-dim-list'><li><span class='xr-has-index'>isobaric2</span>: 5</li><li><span class='xr-has-index'>lat</span>: 361</li><li><span class='xr-has-index'>lon</span>: 720</li><li><span class='xr-has-index'>time</span>: 1</li></ul></div><div class='xr-section-details'></div></li><li class='xr-section-item'><input id='section-43a46a55-fd8b-4b12-b864-bb8fa93b330c' class='xr-section-summary-in' type='checkbox' checked><label for='section-43a46a55-fd8b-4b12-b864-bb8fa93b330c' class='xr-section-summary' >Coordinates: <span>(6)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>lon</span></div><div class='xr-var-dims'>(lon)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>0.0 0.5 1.0 ... 358.5 359.0 359.5</div><input id='attrs-9821144b-be96-49c5-833a-90e7b97ed245' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-9821144b-be96-49c5-833a-90e7b97ed245' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-fdcd0af8-7908-4712-ac88-f5897bbef568' class='xr-var-data-in' type='checkbox'><label for='data-fdcd0af8-7908-4712-ac88-f5897bbef568' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>degrees_east</dd></dl></div><div class='xr-var-data'><pre>array([ 0. , 0.5, 1. , ..., 358.5, 359. , 359.5], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>height_above_ground3</span></div><div class='xr-var-dims'>()</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>2.0</div><input id='attrs-5d08c6cf-1fc2-48d2-b87d-1a4ef2908b0c' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-5d08c6cf-1fc2-48d2-b87d-1a4ef2908b0c' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-2b0442ad-30a2-4a5b-87db-e899813e2ff2' class='xr-var-data-in' type='checkbox'><label for='data-2b0442ad-30a2-4a5b-87db-e899813e2ff2' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>m</dd><dt><span>long_name :</span></dt><dd>Specified height level above ground</dd><dt><span>positive :</span></dt><dd>up</dd><dt><span>Grib2_level_type :</span></dt><dd>103</dd><dt><span>datum :</span></dt><dd>ground</dd></dl></div><div class='xr-var-data'><pre>array(2., dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>time</span></div><div class='xr-var-dims'>(time)</div><div class='xr-var-dtype'>datetime64[ns]</div><div class='xr-var-preview xr-preview'>2018-03-08</div><input id='attrs-f773946c-674d-43cd-a651-675d40bf8493' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-f773946c-674d-43cd-a651-675d40bf8493' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-e06c9c55-4be5-4ffc-96b1-e4f233c47594' class='xr-var-data-in' type='checkbox'><label for='data-e06c9c55-4be5-4ffc-96b1-e4f233c47594' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>standard_name :</span></dt><dd>time</dd></dl></div><div class='xr-var-data'><pre>array([&#x27;2018-03-08T00:00:00.000000000&#x27;], dtype=&#x27;datetime64[ns]&#x27;)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>lat</span></div><div class='xr-var-dims'>(lat)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>90.0 89.5 89.0 ... -89.5 -90.0</div><input id='attrs-ae124ff8-65d5-41b9-96bc-cdcc341db3e4' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-ae124ff8-65d5-41b9-96bc-cdcc341db3e4' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-a0341623-934e-4538-9c11-e215ef5c6873' class='xr-var-data-in' type='checkbox'><label for='data-a0341623-934e-4538-9c11-e215ef5c6873' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>degrees_north</dd></dl></div><div class='xr-var-data'><pre>array([ 90. , 89.5, 89. , ..., -89. , -89.5, -90. ], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>metpy_crs</span></div><div class='xr-var-dims'>()</div><div class='xr-var-dtype'>object</div><div class='xr-var-preview xr-preview'>Projection: latitude_longitude</div><input id='attrs-2537ec81-641f-4135-b76d-b03433c55c24' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-2537ec81-641f-4135-b76d-b03433c55c24' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-d1dc45af-5821-45ed-8bd0-39f225de0932' class='xr-var-data-in' type='checkbox'><label for='data-d1dc45af-5821-45ed-8bd0-39f225de0932' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array(&lt;metpy.plots.mapping.CFProjection object at 0x7fb4f8555630&gt;,\n",
" dtype=object)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>isobaric2</span></div><div class='xr-var-dims'>(isobaric2)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>1e+05 8.5e+04 5.5e+04 5e+04 4.5e+04</div><input id='attrs-d32ae1e5-7dff-4cb5-aaf7-00dcb762400f' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-d32ae1e5-7dff-4cb5-aaf7-00dcb762400f' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-30447d2a-87c0-44be-9ef7-1cae2b5833a6' class='xr-var-data-in' type='checkbox'><label for='data-30447d2a-87c0-44be-9ef7-1cae2b5833a6' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>units :</span></dt><dd>Pa</dd><dt><span>long_name :</span></dt><dd>Isobaric surface</dd><dt><span>positive :</span></dt><dd>down</dd><dt><span>Grib2_level_type :</span></dt><dd>100</dd></dl></div><div class='xr-var-data'><pre>array([100000., 85000., 55000., 50000., 45000.], dtype=float32)</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-4dd3bfbf-0e3c-4c7a-b54a-cff0f7db4c7b' class='xr-section-summary-in' type='checkbox' checked><label for='section-4dd3bfbf-0e3c-4c7a-b54a-cff0f7db4c7b' class='xr-section-summary' >Data variables: <span>(6)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span>Temperature_height_above_ground</span></div><div class='xr-var-dims'>(time, lat, lon)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>250.5 250.5 250.5 ... 229.7 229.7</div><input id='attrs-ed91ab28-868d-4c3e-a894-5d00715212c5' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-ed91ab28-868d-4c3e-a894-5d00715212c5' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-00386d54-3796-48b3-8e74-60a762a2c4c2' class='xr-var-data-in' type='checkbox'><label for='data-00386d54-3796-48b3-8e74-60a762a2c4c2' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>Temperature @ Specified height level above ground</dd><dt><span>units :</span></dt><dd>K</dd><dt><span>abbreviation :</span></dt><dd>TMP</dd><dt><span>grid_mapping :</span></dt><dd>LatLon_Projection</dd><dt><span>Grib_Variable_Id :</span></dt><dd>VAR_0-0-0_L103</dd><dt><span>Grib2_Parameter :</span></dt><dd>[0 0 0]</dd><dt><span>Grib2_Parameter_Discipline :</span></dt><dd>Meteorological products</dd><dt><span>Grib2_Parameter_Category :</span></dt><dd>Temperature</dd><dt><span>Grib2_Parameter_Name :</span></dt><dd>Temperature</dd><dt><span>Grib2_Level_Type :</span></dt><dd>103</dd><dt><span>Grib2_Generating_Process_Type :</span></dt><dd>Forecast</dd></dl></div><div class='xr-var-data'><pre>array([[[250.4568 , 250.4568 , ..., 250.4568 , 250.4568 ],\n",
" [249.2668 , 249.25679, ..., 249.2868 , 249.2768 ],\n",
" ...,\n",
" [228.9668 , 228.9468 , ..., 228.9868 , 228.97679],\n",
" [229.6568 , 229.6568 , ..., 229.6568 , 229.6568 ]]], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>u-component_of_wind_isobaric</span></div><div class='xr-var-dims'>(time, isobaric2, lat, lon)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>-1.631 -1.591 ... 5.524 5.484</div><input id='attrs-62697603-a683-4f5e-8ad6-b4b0129861c5' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-62697603-a683-4f5e-8ad6-b4b0129861c5' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-0aed8a9d-0063-4c65-89fa-cd95107c2567' class='xr-var-data-in' type='checkbox'><label for='data-0aed8a9d-0063-4c65-89fa-cd95107c2567' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>u-component of wind @ Isobaric surface</dd><dt><span>units :</span></dt><dd>m/s</dd><dt><span>abbreviation :</span></dt><dd>UGRD</dd><dt><span>grid_mapping :</span></dt><dd>LatLon_Projection</dd><dt><span>Grib_Variable_Id :</span></dt><dd>VAR_0-2-2_L100</dd><dt><span>Grib2_Parameter :</span></dt><dd>[0 2 2]</dd><dt><span>Grib2_Parameter_Discipline :</span></dt><dd>Meteorological products</dd><dt><span>Grib2_Parameter_Category :</span></dt><dd>Momentum</dd><dt><span>Grib2_Parameter_Name :</span></dt><dd>u-component of wind</dd><dt><span>Grib2_Level_Type :</span></dt><dd>100</dd><dt><span>Grib2_Generating_Process_Type :</span></dt><dd>Forecast</dd></dl></div><div class='xr-var-data'><pre>array([[[[-1.63052 , ..., -1.67052 ],\n",
" ...,\n",
" [ 1.23948 , ..., 1.16948 ]],\n",
"\n",
" ...,\n",
"\n",
" [[-4.045796, ..., -4.055796],\n",
" ...,\n",
" [ 5.454204, ..., 5.484204]]]], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>v-component_of_wind_isobaric</span></div><div class='xr-var-dims'>(time, isobaric2, lat, lon)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>4.359 4.369 4.389 ... 4.295 4.345</div><input id='attrs-be2a4f8b-326c-4015-8f32-d5a1e67089ab' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-be2a4f8b-326c-4015-8f32-d5a1e67089ab' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-a2b3e80c-c877-4aef-8dbf-b66bf079f749' class='xr-var-data-in' type='checkbox'><label for='data-a2b3e80c-c877-4aef-8dbf-b66bf079f749' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>v-component of wind @ Isobaric surface</dd><dt><span>units :</span></dt><dd>m/s</dd><dt><span>abbreviation :</span></dt><dd>VGRD</dd><dt><span>grid_mapping :</span></dt><dd>LatLon_Projection</dd><dt><span>Grib_Variable_Id :</span></dt><dd>VAR_0-2-3_L100</dd><dt><span>Grib2_Parameter :</span></dt><dd>[0 2 3]</dd><dt><span>Grib2_Parameter_Discipline :</span></dt><dd>Meteorological products</dd><dt><span>Grib2_Parameter_Category :</span></dt><dd>Momentum</dd><dt><span>Grib2_Parameter_Name :</span></dt><dd>v-component of wind</dd><dt><span>Grib2_Level_Type :</span></dt><dd>100</dd><dt><span>Grib2_Generating_Process_Type :</span></dt><dd>Forecast</dd></dl></div><div class='xr-var-data'><pre>array([[[[ 4.358794, ..., 4.338794],\n",
" ...,\n",
" [-7.121206, ..., -7.131206]],\n",
"\n",
" ...,\n",
"\n",
" [[ 1.414526, ..., 1.374526],\n",
" ...,\n",
" [ 4.384526, ..., 4.344526]]]], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>Temperature_isobaric</span></div><div class='xr-var-dims'>(time, isobaric2, lat, lon)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>252.6 252.6 252.6 ... 229.9 229.9</div><input id='attrs-0fa24593-395e-4550-a0f8-28145591a578' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-0fa24593-395e-4550-a0f8-28145591a578' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-45606379-7ec1-4da2-9f68-1d24a2e2183c' class='xr-var-data-in' type='checkbox'><label for='data-45606379-7ec1-4da2-9f68-1d24a2e2183c' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>Temperature @ Isobaric surface</dd><dt><span>units :</span></dt><dd>K</dd><dt><span>abbreviation :</span></dt><dd>TMP</dd><dt><span>grid_mapping :</span></dt><dd>LatLon_Projection</dd><dt><span>Grib_Variable_Id :</span></dt><dd>VAR_0-0-0_L100</dd><dt><span>Grib2_Parameter :</span></dt><dd>[0 0 0]</dd><dt><span>Grib2_Parameter_Discipline :</span></dt><dd>Meteorological products</dd><dt><span>Grib2_Parameter_Category :</span></dt><dd>Temperature</dd><dt><span>Grib2_Parameter_Name :</span></dt><dd>Temperature</dd><dt><span>Grib2_Level_Type :</span></dt><dd>100</dd><dt><span>Grib2_Generating_Process_Type :</span></dt><dd>Forecast</dd></dl></div><div class='xr-var-data'><pre>array([[[[252.5935 , ..., 252.5935 ],\n",
" ...,\n",
" [246.9935 , ..., 246.9935 ]],\n",
"\n",
" ...,\n",
"\n",
" [[222.21024, ..., 222.21024],\n",
" ...,\n",
" [229.91023, ..., 229.91023]]]], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>Geopotential_height_isobaric</span></div><div class='xr-var-dims'>(time, isobaric2, lat, lon)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>235.5 235.5 ... 5.631e+03 5.631e+03</div><input id='attrs-cd71ac23-59a4-429a-b941-ea8dedae6ded' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-cd71ac23-59a4-429a-b941-ea8dedae6ded' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-cd921cb8-6156-4349-b2a3-e080765a02c7' class='xr-var-data-in' type='checkbox'><label for='data-cd921cb8-6156-4349-b2a3-e080765a02c7' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>Geopotential height @ Isobaric surface</dd><dt><span>units :</span></dt><dd>gpm</dd><dt><span>abbreviation :</span></dt><dd>HGT</dd><dt><span>grid_mapping :</span></dt><dd>LatLon_Projection</dd><dt><span>Grib_Variable_Id :</span></dt><dd>VAR_0-3-5_L100</dd><dt><span>Grib2_Parameter :</span></dt><dd>[0 3 5]</dd><dt><span>Grib2_Parameter_Discipline :</span></dt><dd>Meteorological products</dd><dt><span>Grib2_Parameter_Category :</span></dt><dd>Mass</dd><dt><span>Grib2_Parameter_Name :</span></dt><dd>Geopotential height</dd><dt><span>Grib2_Level_Type :</span></dt><dd>100</dd><dt><span>Grib2_Generating_Process_Type :</span></dt><dd>Forecast</dd></dl></div><div class='xr-var-data'><pre>array([[[[ 235.4638 , ..., 235.4638 ],\n",
" ...,\n",
" [ 128.24782, ..., 128.24782]],\n",
"\n",
" ...,\n",
"\n",
" [[5855.063 , ..., 5855.063 ],\n",
" ...,\n",
" [5630.803 , ..., 5630.803 ]]]], dtype=float32)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span>Relative_humidity_isobaric</span></div><div class='xr-var-dims'>(time, isobaric2, lat, lon)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>100.0 100.0 100.0 ... 100.0 100.0</div><input id='attrs-1fa4ed87-a9c1-49a6-be21-41c86d4c610a' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-1fa4ed87-a9c1-49a6-be21-41c86d4c610a' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-abb3147a-484e-4dde-88fd-904a55653684' class='xr-var-data-in' type='checkbox'><label for='data-abb3147a-484e-4dde-88fd-904a55653684' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>Relative humidity @ Isobaric surface</dd><dt><span>units :</span></dt><dd>%</dd><dt><span>abbreviation :</span></dt><dd>RH</dd><dt><span>grid_mapping :</span></dt><dd>LatLon_Projection</dd><dt><span>Grib_Variable_Id :</span></dt><dd>VAR_0-1-1_L100</dd><dt><span>Grib2_Parameter :</span></dt><dd>[0 1 1]</dd><dt><span>Grib2_Parameter_Discipline :</span></dt><dd>Meteorological products</dd><dt><span>Grib2_Parameter_Category :</span></dt><dd>Moisture</dd><dt><span>Grib2_Parameter_Name :</span></dt><dd>Relative humidity</dd><dt><span>Grib2_Level_Type :</span></dt><dd>100</dd><dt><span>Grib2_Generating_Process_Type :</span></dt><dd>Forecast</dd></dl></div><div class='xr-var-data'><pre>array([[[[100. , ..., 100. ],\n",
" ...,\n",
" [100. , ..., 100. ]],\n",
"\n",
" ...,\n",
"\n",
" [[ 99.4, ..., 99.4],\n",
" ...,\n",
" [100. , ..., 100. ]]]], dtype=float32)</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-f31475e3-af8e-4853-8889-896ffc7e894b' class='xr-section-summary-in' type='checkbox' checked><label for='section-f31475e3-af8e-4853-8889-896ffc7e894b' class='xr-section-summary' >Attributes: <span>(9)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><dl class='xr-attrs'><dt><span>Originating_or_generating_Center :</span></dt><dd>US National Weather Service, National Centres for Environmental Prediction (NCEP)</dd><dt><span>Originating_or_generating_Subcenter :</span></dt><dd>0</dd><dt><span>GRIB_table_version :</span></dt><dd>2,1</dd><dt><span>Type_of_generating_process :</span></dt><dd>Forecast</dd><dt><span>Analysis_or_forecast_generating_process_identifier_defined_by_originating_centre :</span></dt><dd>Analysis from GFS (Global Forecast System)</dd><dt><span>Conventions :</span></dt><dd>CF-1.6</dd><dt><span>history :</span></dt><dd>Read using CDM IOSP Grib2Collection</dd><dt><span>featureType :</span></dt><dd>GRID</dd><dt><span>file_format :</span></dt><dd>GRIB-2</dd></dl></div></li></ul></div></div>"
],
"text/plain": [
"<xarray.Dataset>\n",
"Dimensions: (isobaric2: 5, lat: 361, lon: 720, time: 1)\n",
"Coordinates:\n",
" * lon (lon) float32 0.0 0.5 1.0 ... 359.0 359.5\n",
" height_above_ground3 float32 2.0\n",
" * time (time) datetime64[ns] 2018-03-08\n",
" * lat (lat) float32 90.0 89.5 ... -89.5 -90.0\n",
" metpy_crs object Projection: latitude_longitude\n",
" * isobaric2 (isobaric2) float32 1e+05 ... 4.5e+04\n",
"Data variables:\n",
" Temperature_height_above_ground (time, lat, lon) float32 250.5 ... 229.7\n",
" u-component_of_wind_isobaric (time, isobaric2, lat, lon) float32 -1.6...\n",
" v-component_of_wind_isobaric (time, isobaric2, lat, lon) float32 4.35...\n",
" Temperature_isobaric (time, isobaric2, lat, lon) float32 252....\n",
" Geopotential_height_isobaric (time, isobaric2, lat, lon) float32 235....\n",
" Relative_humidity_isobaric (time, isobaric2, lat, lon) float32 100....\n",
"Attributes:\n",
" Originating_or_generating_Center: ...\n",
" Originating_or_generating_Subcenter: ...\n",
" GRIB_table_version: ...\n",
" Type_of_generating_process: ...\n",
" Analysis_or_forecast_generating_process_identifier_defined_by_originating...\n",
" Conventions: ...\n",
" history: ...\n",
" featureType: ...\n",
" file_format: ..."
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gfs_data"
]
},
{
"cell_type": "markdown",
"id": "fb762ce1",
"metadata": {},
"source": [
"**Notes from @deeplycloudy, 28 June – 6 July 2021**\n",
"\n",
"from [`factors.cpp`](https://github.com/OSGeo/PROJ/blob/master/src/factors.cpp), with phi (p) being latitude and lambda (l) being longitude,\n",
"\n",
"```\n",
"/* Scale factors */\n",
"cosphi = cos (lp.phi);\n",
"fac->h = hypot (fac->der.x_p, fac->der.y_p);\n",
"fac->k = hypot (fac->der.x_l, fac->der.y_l) / cosphi;\n",
"```\n",
"\n",
" \n",
"from [`proj.h`](https://github.com/OSGeo/PROJ/blob/master/src/proj.h)\n",
"\n",
"```\n",
"struct P5_FACTORS { /* Common designation */\n",
" double meridional_scale; /* h */\n",
" double parallel_scale; /* k */\n",
" double areal_scale; /* s */\n",
"\n",
" double angular_distortion; /* omega */\n",
" double meridian_parallel_angle; /* theta-prime */\n",
" double meridian_convergence; /* alpha */\n",
"\n",
" double tissot_semimajor; /* a */\n",
" double tissot_semiminor; /* b */\n",
"\n",
" double dx_dlam, dx_dphi;\n",
" double dy_dlam, dy_dphi;\n",
"};\n",
"```\n",
"\n",
"So, aligning terminology, meridional scale is h and is calculated as the root of the sum of the squares of the derivatives of the x and y coordinates with respect to latitude. It's the gradient along (the/any) meridian.\n",
"\n",
"The parallel scale is k and is calculated as the root of the sum of the squares of the derivatives of the x and y coordinates with respect to longitude, and divided by the cosine of the latitude. It's the gradient following a parallel at a specific latitude. \n",
"\n",
"In `m_x * dvdx - m_y * dudy`, where we need `m_x` and `m_y`, what do we use? The idea, inherited from calculus, is that m_x and m_y are constants related to the rate of change between two coordinates, with X being a proper, orthogonal carteisan basis and x being something else - curvilinear, angled, etc., just as we'd find in a map projection.\n",
"\n",
"```\n",
"Dq dq dx dq\n",
"-- = m_x -- + ... = -- -- + ...\n",
"DX dx DX dx\n",
"```\n",
"\n",
"So m_x is the change in the x coordinate along the (other) X coordinate. Parallel scale is the change along longitude, i.e., the nominal x coordinate, so we should relate it to m_x.\n",
"\n",
"In the specific case for the GFS data in this notebook, dx and dy are calculated by MetPy ([using proper great circle curvilinear distances!](https://github.com/Unidata/MetPy/blob/main/src/metpy/calc/tools.py#L835)) as a local distance in units of meters, but the map factors from proj are rates of change of angular coordiantes with respect to other angular coordinates, and not with respect to meters. Proj does not know of any other projection (see the printout of `data_var_u.metpy.pyproj_crs` above), so it can't define meters. Per the proj source, in this case m_x the root of the sum of the square of the derivatives of both latitude and longitude with respect to longitude, and then divided by the cosine of latitude. This is unitless. \n",
"\n",
"**In a setting where dx and dy have already been calculated from lon and lat, m_x and m_y derived from a lat lon coordinate system are not appropriate for use in correcting dq_dx, because the units don't match.** The use of the map factors is only relevant when a map projection has been defined. Latitude and longitude are not a map projection, and dx and dy from MetPy are also not from a map projection.\n",
"\n",
"A **practical recommendation for implementation in MetPy** is then as follows:\n",
"- When data are provided in latitude and longitude, use the method in the first part of this notebook, which is well-defined and matches GEMPAK.\n",
"- When data are provided in a map projection (with units in meters) then the method proposed in [MetPy#893](https://github.com/Unidata/MetPy/issues/893) is appropriate.\n",
"\n",
"To test and implement the second item above, and verify equivalency to GEMPAK, we would need to\n",
"1. convert model data in map projection coordinates to a 2D lat and 2D lon grid\n",
"2. convert those spacings to dx and dy using MetPy, and calculate using the GEMPAK method with high-latitude correction.\n",
"3. compare 2. to the direct calculation that uses the model-provided map factors.\n",
"\n",
"If 3. checks out, then we can implement the second bullet above as an alternate, and faster, code path that is equivalent to GEMPAK but avoids the calculation of dx and dy within MetPy.\n",
"\n",
"*I still haven't figured out how to reconcile the definition of map factors and the method proposed in #893 *. They seem like they should be compatible."
]
},
{
"cell_type": "markdown",
"id": "322f2ee3-2c93-472a-b638-73db954c844d",
"metadata": {},
"source": [
"**Other comments**\n",
"\n",
"Note that other than tiny ellipsoidal effects all of the variation in parallel_scale comes from the division by `cos(latitude)`. `parallel_scale` also blows up near the poles because of a divide by zero (and proj has some logic to check for this condition and keep things finite).\n",
"\n",
"It is _CRUCIAL_ not to conflate Plate Carree projection coordinates with latitude and longitude coordintes, because plate carree *does* make an explicit conversion to physical units - it is a (very simple) projection, whose name is `eqc` in proj4 with `lat_0=0.0`. Specifically, for plate carree the longitude and latitude coordinates are multiplied by earth's radius to get \"meters\". \n",
"\n",
"Some further calculations with `eqc` are below. I would have thought that they would be identical except for a constant scaling factor of the earth's radius, but they show that the map factors are identical to `latlon`. Earth's radius must be divided out somewhere - probably because the map_factor is defined as the geometric distortion *within the same units*.\n",
"\n",
"**An aside about Cartopy**\n",
"\n",
"Cartopy's design decision seems to have been to convert all coordinates to units of meters, i.e., everything is a projection, instead of permitting the possibility of plotting data in native measurement coordinates. After this design decision was made, it led to the use of a plate carree projection for a \"simple\" lat-lon plot, with constant-radius scaling to meters. (Constant radius is of course not compatible with ellipsoidal coordinates, and I seem to recall this is why Cartopy struggled with alternate globes at one point.)\n",
"\n",
"I don't like Cartopy's design decision in this regard (and I have the same disagreement with the \"geostationary\" projection inhereited from proj.4, which multiplies the view angle from a satellite by the height of the satellite to get a \"projection\"). Sometimes it is desirable convert and plot in some dataset's native coordinates, whether that is a map projection or instrument-native coordinates, and a \"flatten-the-earth and give me meters\" mindset prevents this flexibility."
]
},
{
"cell_type": "markdown",
"id": "1d5f0d64-8e79-47f4-9a29-f21ff30eee4a",
"metadata": {},
"source": [
"**Equidistant cylindrical (i.e., Plate Carree) map factors**\n",
"\n",
"These turn out to be almost identical to those for a `latlon` projection - identical for a spherical earth and slightly different for an ellipsoidal earth."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "e7d1419c-f7bf-4a1a-a84b-abe5a4ff3810",
"metadata": {},
"outputs": [],
"source": [
"import pyproj as proj4\n",
"def get_proj():\n",
" # Define a WGS84 earth\n",
" earth_major, earth_minor = 6378137.0, 6356752.3142\n",
" \n",
" # Spherical earth\n",
"# earth_major, earth_minor = 6378137.0, 6378137.0 #6356752.3142\n",
" \n",
" eqc = proj4.crs.CRS(proj='eqc', a=earth_major, b=earth_minor,\n",
" lat_0=0.0, lon_0=0.0)\n",
" lla = proj4.crs.CRS(proj='latlong', a=earth_major, b=earth_minor)\n",
" ecef = proj4.crs.CRS(proj='geocent', a=earth_major, b=earth_minor)\n",
"\n",
" return lla, ecef, eqc"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "5af11c1b-8f7a-421a-aa2b-790a0ec8d23b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(-11298928.315517267, 3729202.941574665, 0.0)\n",
"(-101.5, 33.5, 0.0)\n"
]
}
],
"source": [
"lla, ecef, eqc = get_proj()\n",
"eqc_proj = Proj(eqc)\n",
"lla_proj = Proj(lla)\n",
"eqc_factors = eqc_proj.get_factors(xx,yy)\n",
"lla_factors = lla_proj.get_factors(xx,yy)\n",
"print(eqc_proj.transform(-101.5, 33.5, 0.0))\n",
"print(lla_proj.transform(-101.5, 33.5, 0.0))"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "45030868-2173-4bf8-87de-6eb4d8e511b0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" ...\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]]\n",
"[[0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" ...\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]]\n",
"[[-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]\n",
" [-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]\n",
" [ 5.55111512e-12 5.55111512e-12 5.55111512e-12 ... 5.55111512e-12\n",
" 5.55111512e-12 5.55111512e-12]\n",
" ...\n",
" [ 5.55111512e-12 5.55111512e-12 5.55111512e-12 ... 5.55111512e-12\n",
" 5.55111512e-12 5.55111512e-12]\n",
" [-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]\n",
" [-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]]\n",
"[[1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" ...\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]]\n"
]
}
],
"source": [
"print(eqc_factors.dx_dlam)\n",
"print(eqc_factors.dx_dphi)\n",
"print(eqc_factors.dy_dlam)\n",
"print(eqc_factors.dy_dphi)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "25093253-9d48-45c4-9861-66815bf4a6a7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" ...\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]]\n",
"[[0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" ...\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]\n",
" [0. 0. 0. ... 0. 0. 0.]]\n",
"[[-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]\n",
" [-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]\n",
" [ 5.55111512e-12 5.55111512e-12 5.55111512e-12 ... 5.55111512e-12\n",
" 5.55111512e-12 5.55111512e-12]\n",
" ...\n",
" [ 5.55111512e-12 5.55111512e-12 5.55111512e-12 ... 5.55111512e-12\n",
" 5.55111512e-12 5.55111512e-12]\n",
" [-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]\n",
" [-5.55111512e-12 -5.55111512e-12 -5.55111512e-12 ... -5.55111512e-12\n",
" -5.55111512e-12 -5.55111512e-12]]\n",
"[[1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" ...\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]\n",
" [1. 1. 1. ... 1. 1. 1.]]\n"
]
}
],
"source": [
"# Since the data are in lat-lon, there is no gradient in the data coordinate as a function of latitude and longitude.\n",
"print(lla_factors.dx_dlam)\n",
"print(lla_factors.dx_dphi)\n",
"print(lla_factors.dy_dlam)\n",
"print(lla_factors.dy_dphi)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "8dccd7a2-bad5-4815-8010-508f9de65d60",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.9999999999954489 99664.71893390131\n",
"0.9966471893246407 1.0067394967565868\n"
]
}
],
"source": [
"print(lla_factors.parallel_scale.min(), lla_factors.parallel_scale.max())\n",
"print(lla_factors.meridional_scale.min(), lla_factors.meridional_scale.max())"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "cb33a3dc-d63f-4ca1-a81b-be5416de43b0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.9999999999954489 100000.00000105436\n",
"0.9999999999954489 1.000000000001\n"
]
}
],
"source": [
"print(eqc_factors.parallel_scale.min(), eqc_factors.parallel_scale.max())\n",
"print(eqc_factors.meridional_scale.min(), eqc_factors.meridional_scale.max())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a06011c2-870f-4a7f-98a6-ce3fee2a9763",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:glmval]",
"language": "python",
"name": "conda-env-glmval-py"
},
"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.6.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment