Skip to content

Commit d4b2d18

Browse files
committed
Merge branch 'master' of github.com:Unidata/python-training
2 parents 8789738 + 455ffa0 commit d4b2d18

File tree

5 files changed

+219
-23
lines changed

5 files changed

+219
-23
lines changed
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Dynamic Tropopause Calculation\n",
8+
"\n",
9+
"By: Kevin Goebbert\n",
10+
"\n",
11+
"This example uses MetPy calculation ability to determine the potential temperature on the dynamic tropopause (2 PVU surface), add the derived variables to the xarray dataset and plot using the MetPy declarative syntax."
12+
]
13+
},
14+
{
15+
"cell_type": "code",
16+
"execution_count": null,
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"from datetime import datetime, timedelta\n",
21+
"\n",
22+
"import metpy.calc as mpcalc\n",
23+
"from metpy.interpolate import interpolate_to_isosurface\n",
24+
"from metpy.plots.declarative import *\n",
25+
"from metpy.units import units\n",
26+
"import xarray as xr"
27+
]
28+
},
29+
{
30+
"cell_type": "markdown",
31+
"metadata": {},
32+
"source": [
33+
"## Get GFS Data\n",
34+
"\n",
35+
"Obtain and subset GFS data to cover the CONUS region"
36+
]
37+
},
38+
{
39+
"cell_type": "code",
40+
"execution_count": null,
41+
"metadata": {},
42+
"outputs": [],
43+
"source": [
44+
"date = datetime.utcnow() - timedelta(days=1)\n",
45+
"ds = xr.open_dataset('https://thredds.ucar.edu/thredds/dodsC/grib/NCEP/GFS/'\n",
46+
" f'Global_onedeg_ana/GFS_Global_onedeg_ana_{date:%Y%m%d}_1200.grib2').metpy.parse_cf()\n",
47+
"\n",
48+
"ds = ds.sel(lat=slice(80, -10), lon=slice(360-140, 360-40))\n",
49+
"\n",
50+
"vtime = ds.time.values[0].astype('datetime64[ms]').astype('O')"
51+
]
52+
},
53+
{
54+
"cell_type": "markdown",
55+
"metadata": {},
56+
"source": [
57+
"## Compute Potential Temperature at 2 PVU\n",
58+
"The following cell takes the necessary data from the GFS analysis, smooths and calculates needed variables to obtain the potential temperature on the 2 PVU surface (e.g., the dynamic tropopause), as well as interpolate the wind components to that level as well."
59+
]
60+
},
61+
{
62+
"cell_type": "code",
63+
"execution_count": null,
64+
"metadata": {},
65+
"outputs": [],
66+
"source": [
67+
"pressure = ds.isobaric.values * units.Pa\n",
68+
"\n",
69+
"lats = ds.lat.values\n",
70+
"lons = ds.lon.values\n",
71+
"\n",
72+
"dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats)\n",
73+
"\n",
74+
"uwind = mpcalc.smooth_n_point(ds['u-component_of_wind_isobaric'].squeeze(), 9, 2)\n",
75+
"vwind = mpcalc.smooth_n_point(ds['v-component_of_wind_isobaric'].squeeze(), 9, 2)\n",
76+
"\n",
77+
"LL_avor = mpcalc.smooth_n_point(ds.Absolute_vorticity_isobaric.metpy.sel(vertical=slice(850 * units.hPa,\n",
78+
" 925 * units.hPa)).squeeze(), 9, 2)\n",
79+
"avg_LL_avor = LL_avor.mean(axis=0)\n",
80+
"\n",
81+
"potemp = mpcalc.smooth_n_point(mpcalc.potential_temperature(pressure[:, None, None], ds.Temperature_isobaric.squeeze()), 9, 2)\n",
82+
"avg_LL_rvor = avg_LL_avor - mpcalc.coriolis_parameter(lats[:, None] * units.degree)\n",
83+
"\n",
84+
"pvor = mpcalc.potential_vorticity_baroclinic(potemp, pressure[:, None, None], uwind, vwind,\n",
85+
" dx[None, :, :], dy[None, :, :], lats[None, :, None] * units.degrees)\n",
86+
"\n",
87+
"DT_potemp = interpolate_to_isosurface(pvor.m*1e6, potemp.m, 2, bottom_up_search=False)\n",
88+
"DT_uwnd = (interpolate_to_isosurface(pvor.m*1e6, uwind.m, 2, bottom_up_search=False) * units('m/s')).to(units.knots)\n",
89+
"DT_vwnd = (interpolate_to_isosurface(pvor.m*1e6, vwind.m, 2, bottom_up_search=False) * units('m/s')).to(units.knots)"
90+
]
91+
},
92+
{
93+
"cell_type": "markdown",
94+
"metadata": {},
95+
"source": [
96+
"## Add Variables to Dataset\n",
97+
"This next cell adds the variables calculated/derived above to the xarray dataset, which will make them available for plotting with the MetPy declarative syntax."
98+
]
99+
},
100+
{
101+
"cell_type": "code",
102+
"execution_count": null,
103+
"metadata": {},
104+
"outputs": [],
105+
"source": [
106+
"ds = ds.assign(dynamic_trop=(tuple(('lat', 'lon')), DT_potemp,\n",
107+
" {'grid_mapping': ds['u-component_of_wind_isobaric'].grid_mapping,\n",
108+
" 'units': 'PVU'}))\n",
109+
"ds = ds.assign(uwnd_DT=(tuple(('lat', 'lon')), DT_uwnd.m,\n",
110+
" {'grid_mapping': ds['u-component_of_wind_isobaric'].grid_mapping,\n",
111+
" 'units': 'knots'}))\n",
112+
"ds = ds.assign(vwnd_DT=(tuple(('lat', 'lon')), DT_vwnd.m,\n",
113+
" {'grid_mapping': ds['u-component_of_wind_isobaric'].grid_mapping,\n",
114+
" 'units': 'knots'}))\n",
115+
"ds = ds.assign(avg_LL_rel_vort=(tuple(('lat', 'lon')), avg_LL_rvor*1e4,\n",
116+
" {'grid_mapping': ds['u-component_of_wind_isobaric'].grid_mapping,\n",
117+
" 'units': '1/s'}))"
118+
]
119+
},
120+
{
121+
"cell_type": "markdown",
122+
"metadata": {},
123+
"source": [
124+
"## Create the Plot"
125+
]
126+
},
127+
{
128+
"cell_type": "code",
129+
"execution_count": null,
130+
"metadata": {},
131+
"outputs": [],
132+
"source": [
133+
"cntr = ContourPlot()\n",
134+
"cntr.data = ds\n",
135+
"cntr.level = None\n",
136+
"cntr.field = 'avg_LL_rel_vort'\n",
137+
"cntr.clabels = True\n",
138+
"cntr.contours = [0.5, 1.5, 2.5, 3.5, 4.5]\n",
139+
"\n",
140+
"cntr2 = FilledContourPlot()\n",
141+
"cntr2.data = ds\n",
142+
"cntr2.level = None\n",
143+
"cntr2.field = 'dynamic_trop'\n",
144+
"cntr2.contours = list(range(250, 420, 1))\n",
145+
"cntr2.colormap = 'coolwarm'\n",
146+
"cntr2.colorbar = 'horizontal'\n",
147+
"\n",
148+
"barbs = BarbPlot()\n",
149+
"barbs.data = ds\n",
150+
"barbs.field = ['uwnd_DT', 'vwnd_DT']\n",
151+
"barbs.skip = (3, 3)\n",
152+
"\n",
153+
"panel = MapPanel()\n",
154+
"panel.projection = 'lcc'\n",
155+
"panel.area = 'us'\n",
156+
"panel.layers = ['states', 'borders', 'coastline']\n",
157+
"panel.title = ('Dynamic Tropopause Potential Temperature (K), Wind Barbs (kts), and LL Rel. Vort. (s$^{-1}$) at '\n",
158+
" f'{vtime}')\n",
159+
"panel.plots = [cntr2, cntr, barbs]\n",
160+
"\n",
161+
"pc = PanelContainer()\n",
162+
"pc.size = (18, 14)\n",
163+
"pc.panels = [panel]\n",
164+
"\n",
165+
"pc.show()"
166+
]
167+
},
168+
{
169+
"cell_type": "code",
170+
"execution_count": null,
171+
"metadata": {},
172+
"outputs": [],
173+
"source": []
174+
}
175+
],
176+
"metadata": {
177+
"kernelspec": {
178+
"display_name": "Python 3",
179+
"language": "python",
180+
"name": "python3"
181+
},
182+
"language_info": {
183+
"codemirror_mode": {
184+
"name": "ipython",
185+
"version": 3
186+
},
187+
"file_extension": ".py",
188+
"mimetype": "text/x-python",
189+
"name": "python",
190+
"nbconvert_exporter": "python",
191+
"pygments_lexer": "ipython3",
192+
"version": "3.7.3"
193+
}
194+
},
195+
"nbformat": 4,
196+
"nbformat_minor": 4
197+
}

pages/gallery/mapping_GOES16_TrueColor.ipynb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@
140140
},
141141
"outputs": [],
142142
"source": [
143-
"FILE = ('http://ramadda-jetstream.unidata.ucar.edu/repository/opendap'\n",
143+
"FILE = ('https://ramadda.scigw.unidata.ucar.edu/repository/opendap'\n",
144144
" '/4ef52e10-a7da-4405-bff4-e48f68bb6ba2/entry.das#fillmismatch')\n",
145145
"C = xarray.open_dataset(FILE)"
146146
]
@@ -665,7 +665,7 @@
665665
"outputs": [],
666666
"source": [
667667
"# A GOES-16 file with half day and half night\n",
668-
"FILE = ('http://ramadda-jetstream.unidata.ucar.edu/repository/opendap'\n",
668+
"FILE = ('https://ramadda.scigw.unidata.ucar.edu/repository/opendap'\n",
669669
" '/85da3304-b910-472b-aedf-a6d8c1148131/entry.das#fillmismatch')\n",
670670
"C = xarray.open_dataset(FILE)\n",
671671
"\n",
@@ -1000,7 +1000,7 @@
10001000
"outputs": [],
10011001
"source": [
10021002
"# M1 is for the Mesoscale1 NetCDF file\n",
1003-
"FILE = ('http://ramadda-jetstream.unidata.ucar.edu/repository/opendap'\n",
1003+
"FILE = ('https://ramadda.scigw.unidata.ucar.edu/repository/opendap'\n",
10041004
" '/5e02eafa-5cee-4d00-9f58-6e201e69b014/entry.das#fillmismatch')\n",
10051005
"M1 = xarray.open_dataset(FILE)\n",
10061006
"\n",
@@ -1125,7 +1125,7 @@
11251125
},
11261126
"outputs": [],
11271127
"source": [
1128-
"FILE = ('http://ramadda-jetstream.unidata.ucar.edu/repository/opendap'\n",
1128+
"FILE = ('https://ramadda.scigw.unidata.ucar.edu/repository/opendap'\n",
11291129
" '/deb91f58-f997-41a3-a077-987529bf02b3/entry.das#fillmismatch')\n",
11301130
"F = xarray.open_dataset(FILE)\n",
11311131
"\n",

pages/workshop/MetPy_Advanced/QG Analysis.ipynb

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
"import cartopy.crs as ccrs\n",
5353
"import cartopy.feature as cfeature\n",
5454
"import numpy as np\n",
55-
"from scipy.ndimage import gaussian_filter\n",
5655
"from siphon.catalog import TDSCatalog\n",
5756
"from siphon.ncss import NCSS\n",
5857
"import matplotlib.pyplot as plt\n",
@@ -312,20 +311,20 @@
312311
"n_reps = 50\n",
313312
"\n",
314313
"# Apply the 9-point smoother\n",
315-
"hght_700s = mpcalc.smooth_n_point(hght_700, 9, n_reps)\n",
316-
"hght_500s = mpcalc.smooth_n_point(hght_500, 9, n_reps)\n",
314+
"hght_700s = mpcalc.smooth_n_point(hght_700, 9, n_reps).metpy.unit_array\n",
315+
"hght_500s = mpcalc.smooth_n_point(hght_500, 9, n_reps).metpy.unit_array\n",
317316
"\n",
318-
"tmpk_700s = mpcalc.smooth_n_point(tmpk_700, 9, n_reps)\n",
317+
"tmpk_700s = mpcalc.smooth_n_point(tmpk_700, 9, n_reps).metpy.unit_array\n",
319318
"tmpc_700s = tmpk_700s.to('degC')\n",
320319
"\n",
321-
"uwnd_700s = mpcalc.smooth_n_point(uwnd_700, 9, n_reps)\n",
322-
"vwnd_700s = mpcalc.smooth_n_point(vwnd_700, 9, n_reps)\n",
320+
"uwnd_700s = mpcalc.smooth_n_point(uwnd_700, 9, n_reps).metpy.unit_array\n",
321+
"vwnd_700s = mpcalc.smooth_n_point(vwnd_700, 9, n_reps).metpy.unit_array\n",
323322
"\n",
324-
"uwnd_500s = mpcalc.smooth_n_point(uwnd_500, 9, n_reps)\n",
325-
"vwnd_500s = mpcalc.smooth_n_point(vwnd_500, 9, n_reps)\n",
323+
"uwnd_500s = mpcalc.smooth_n_point(uwnd_500, 9, n_reps).metpy.unit_array\n",
324+
"vwnd_500s = mpcalc.smooth_n_point(vwnd_500, 9, n_reps).metpy.unit_array\n",
326325
"\n",
327-
"uwnd_900s = mpcalc.smooth_n_point(uwnd_900, 9, n_reps)\n",
328-
"vwnd_900s = mpcalc.smooth_n_point(vwnd_900, 9, n_reps)"
326+
"uwnd_900s = mpcalc.smooth_n_point(uwnd_900, 9, n_reps).metpy.unit_array\n",
327+
"vwnd_900s = mpcalc.smooth_n_point(vwnd_900, 9, n_reps).metpy.unit_array"
329328
]
330329
},
331330
{

pages/workshop/Metpy_Introduction/Introduction to MetPy.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@
493493
"metadata": {},
494494
"outputs": [],
495495
"source": [
496-
"mpcalc.dewpoint_rh(25 * units.degC, 75 * units.percent)"
496+
"mpcalc.dewpoint_from_relative_humidity(25 * units.degC, 75 * units.percent)"
497497
]
498498
},
499499
{

pages/workshop/Pythonic_Data_Analysis/Pythonic Data Analysis.ipynb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
"fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, figsize=(18, 6))\n",
104104
"\n",
105105
"# Panel 1\n",
106-
"ax1.plot(df.time, df.wind_speed, color='tab:orange', label='Windspeed')\n",
106+
"ax1.plot(df.time.values, df.wind_speed, color='tab:orange', label='Windspeed')\n",
107107
"ax1.set_xlabel('Time')\n",
108108
"ax1.set_ylabel('Speed')\n",
109109
"ax1.set_title('Measured Winds')\n",
@@ -115,7 +115,7 @@
115115
"ax1.xaxis.set_major_locator(DayLocator())\n",
116116
"\n",
117117
"# Panel 2\n",
118-
"ax2.plot(df.time, df.pressure, color='black', label='Pressure')\n",
118+
"ax2.plot(df.time.values, df.pressure, color='black', label='Pressure')\n",
119119
"ax2.set_xlabel('Time')\n",
120120
"ax2.set_ylabel('hPa')\n",
121121
"ax2.set_title('Atmospheric Pressure')\n",
@@ -587,7 +587,7 @@
587587
"# Loop over the list of subplots and names together\n",
588588
"for ax, var_name in zip(axes, plot_variables):\n",
589589
" \n",
590-
" ax.plot(df.time, df[var_name])\n",
590+
" ax.plot(df.time.values, df[var_name])\n",
591591
"\n",
592592
" # Set label/title based on variable name--no longer hard-coded\n",
593593
" ax.set_ylabel(var_name)\n",
@@ -653,7 +653,7 @@
653653
"\n",
654654
" # Grab the color from our dictionary and pass it to plot()\n",
655655
" color = colors[var_name]\n",
656-
" ax.plot(df.time, df[var_name], color)\n",
656+
" ax.plot(df.time.values, df[var_name], color)\n",
657657
"\n",
658658
" ax.set_ylabel(var_name)\n",
659659
" ax.set_title(f'Buoy {var_name}')\n",
@@ -686,7 +686,7 @@
686686
" for var_name in var_names:\n",
687687
" # Grab the color from our dictionary and pass it to plot()\n",
688688
" color = colors[var_name]\n",
689-
" ax.plot(df.time, df[var_name], color)\n",
689+
" ax.plot(df.time.values, df[var_name], color)\n",
690690
"\n",
691691
" ax.set_ylabel(var_name)\n",
692692
" ax.set_title(f'Buoy {var_name}')\n",
@@ -725,7 +725,7 @@
725725
" for var_name in var_names:\n",
726726
" # Grab the color from our dictionary and pass it to plot()\n",
727727
" color = colors[var_name]\n",
728-
" ax.plot(df.time, df[var_name], color)\n",
728+
" ax.plot(df.time.values, df[var_name], color)\n",
729729
"\n",
730730
" ax.set_ylabel(var_name)\n",
731731
" ax.set_title(f'Buoy {var_name}')\n",
@@ -791,7 +791,7 @@
791791
" \n",
792792
" color = colors[var_name]\n",
793793
" linestyle = linestyles[var_name]\n",
794-
" ax.plot(df.time, df[var_name], color, linestyle=linestyle, label=label)\n",
794+
" ax.plot(df.time.values, df[var_name], color, linestyle=linestyle, label=label)\n",
795795
"\n",
796796
" ax.set_ylabel(title)\n",
797797
" ax.set_title(f'Buoy {title}')\n",
@@ -840,7 +840,7 @@
840840
" title, label = format_varname(var_name)\n",
841841
" color = colors[var_name]\n",
842842
" linestyle = linestyles[var_name]\n",
843-
" ax.plot(df.time, df[var_name], color, linestyle=linestyle, label=label)\n",
843+
" ax.plot(df.time.values, df[var_name], color, linestyle=linestyle, label=label)\n",
844844
"\n",
845845
" ax.set_ylabel(title)\n",
846846
" ax.set_title(f'Buoy {buoy} {title}')\n",

0 commit comments

Comments
 (0)