From 5d36f3ec5677f8b3e0457c1d4fd87fda112ac6cd Mon Sep 17 00:00:00 2001 From: John Leeman Date: Tue, 20 Mar 2018 10:46:03 -0600 Subject: [PATCH 1/2] Move example solutions into notebooks. --- notebooks/Animation/Creating Animations.ipynb | 56 +++- notebooks/Animation/solutions/animation.py | 45 --- notebooks/CartoPy/CartoPy.ipynb | 21 +- notebooks/CartoPy/solutions/map.py | 12 - .../MetPy_Advanced/Isentropic Analysis.ipynb | 86 +++++- .../MetPy_Advanced/solutions/isen_ascent.py | 21 -- .../MetPy_Advanced/solutions/isen_mixing.py | 43 --- .../MetPy_Case_Study/MetPy_Case_Study.ipynb | 258 +++++++++++++++--- .../solutions/map_300_div_ageo.py | 33 --- .../solutions/map_500_Vort.py | 38 --- .../solutions/map_850_Tadv.py | 35 --- .../solutions/map_data_500.py | 28 -- .../MetPy_Case_Study/solutions/parse_data.py | 12 - .../MetPy_Case_Study/solutions/pick_levels.py | 18 -- .../MetPy_Case_Study/solutions/temp_adv.py | 3 - .../MetPy_Case_Study/solutions/vorticity.py | 11 - .../Introduction to MetPy.ipynb | 40 ++- .../solutions/intro_calc.py | 3 - .../solutions/intro_temperature.py | 4 - .../solutions/intro_units.py | 4 - .../Downloading model fields with NCSS.ipynb | 62 ++++- .../Model_Output/solutions/model_plot.py | 46 ---- notebooks/NumPy/Intermediate NumPy.ipynb | 85 ++++-- notebooks/NumPy/solutions/advection.py | 2 - notebooks/NumPy/solutions/average.py | 3 - notebooks/NumPy/solutions/average3.py | 3 - notebooks/NumPy/solutions/column_sums.py | 4 - notebooks/NumPy/solutions/heat_index.py | 22 -- .../Advanced Pythonic Data Analysis.ipynb | 116 +++++++- .../Pythonic Data Analysis.ipynb | 126 +++++++-- .../solutions/pythonic_bounds.py | 30 -- .../solutions/pythonic_dictionaryupdate.py | 24 -- .../solutions/pythonic_enumeration.py | 3 - .../solutions/pythonic_functions.py | 5 - .../solutions/pythonic_linestyles.py | 19 -- .../solutions/pythonic_parameter_iteration.py | 5 - .../solutions/pythonic_pressureconversion.py | 33 --- .../solutions/pythonic_troubleshooting.py | 47 ---- .../Working with Satellite Data.ipynb | 75 ++++- .../solutions/satellite_conus.py | 53 ---- .../solutions/satellite_data.py | 4 - notebooks/Siphon/Siphon Overview.ipynb | 23 +- notebooks/Siphon/solutions/goes_cat.py | 10 - .../Upper Air and the Skew-T Log-P.ipynb | 100 +++++-- .../Skew_T/solutions/skewt_bulk_shear.py | 2 - .../Skew_T/solutions/skewt_dewpoint_limits.py | 4 - .../Skew_T/solutions/skewt_fiducial_lines.py | 4 - notebooks/Skew_T/solutions/skewt_get_data.py | 7 - notebooks/Skew_T/solutions/skewt_lfc_el.py | 13 - notebooks/Skew_T/solutions/skewt_mucape.py | 1 - .../Skew_T/solutions/skewt_plot_hodograph.py | 4 - .../Surface Data with Siphon and MetPy.ipynb | 35 ++- .../Surface_Data/solutions/station_plot.py | 26 -- .../Basic Time Series Plotting.ipynb | 70 ++++- .../solutions/timeseries_basicfinalplot.py | 25 -- .../solutions/timeseries_gustplot.py | 8 - .../solutions/timeseries_parse_dates.py | 8 - 57 files changed, 954 insertions(+), 924 deletions(-) delete mode 100644 notebooks/Animation/solutions/animation.py delete mode 100644 notebooks/CartoPy/solutions/map.py delete mode 100644 notebooks/MetPy_Advanced/solutions/isen_ascent.py delete mode 100644 notebooks/MetPy_Advanced/solutions/isen_mixing.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/map_300_div_ageo.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/map_500_Vort.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/map_850_Tadv.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/map_data_500.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/parse_data.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/pick_levels.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/temp_adv.py delete mode 100644 notebooks/MetPy_Case_Study/solutions/vorticity.py delete mode 100644 notebooks/Metpy_Introduction/solutions/intro_calc.py delete mode 100644 notebooks/Metpy_Introduction/solutions/intro_temperature.py delete mode 100644 notebooks/Metpy_Introduction/solutions/intro_units.py delete mode 100644 notebooks/Model_Output/solutions/model_plot.py delete mode 100644 notebooks/NumPy/solutions/advection.py delete mode 100644 notebooks/NumPy/solutions/average.py delete mode 100644 notebooks/NumPy/solutions/average3.py delete mode 100644 notebooks/NumPy/solutions/column_sums.py delete mode 100644 notebooks/NumPy/solutions/heat_index.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_bounds.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_dictionaryupdate.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_enumeration.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_functions.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_linestyles.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_parameter_iteration.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_pressureconversion.py delete mode 100644 notebooks/Pythonic_Data_Analysis/solutions/pythonic_troubleshooting.py delete mode 100644 notebooks/Satellite_Data/solutions/satellite_conus.py delete mode 100644 notebooks/Satellite_Data/solutions/satellite_data.py delete mode 100644 notebooks/Siphon/solutions/goes_cat.py delete mode 100644 notebooks/Skew_T/solutions/skewt_bulk_shear.py delete mode 100644 notebooks/Skew_T/solutions/skewt_dewpoint_limits.py delete mode 100644 notebooks/Skew_T/solutions/skewt_fiducial_lines.py delete mode 100644 notebooks/Skew_T/solutions/skewt_get_data.py delete mode 100644 notebooks/Skew_T/solutions/skewt_lfc_el.py delete mode 100644 notebooks/Skew_T/solutions/skewt_mucape.py delete mode 100644 notebooks/Skew_T/solutions/skewt_plot_hodograph.py delete mode 100644 notebooks/Surface_Data/solutions/station_plot.py delete mode 100644 notebooks/Time_Series/solutions/timeseries_basicfinalplot.py delete mode 100644 notebooks/Time_Series/solutions/timeseries_gustplot.py delete mode 100644 notebooks/Time_Series/solutions/timeseries_parse_dates.py diff --git a/notebooks/Animation/Creating Animations.ipynb b/notebooks/Animation/Creating Animations.ipynb index c443ac5c..988bf14f 100644 --- a/notebooks/Animation/Creating Animations.ipynb +++ b/notebooks/Animation/Creating Animations.ipynb @@ -471,12 +471,58 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/animation.py" + "\n", + "
\n", + "```python\n", + "from netCDF4 import num2date\n", + "\n", + "# Load data\n", + "cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/casestudies/irma/model/gfs/catalog.xml')\n", + "best_ds = cat.datasets['Best GFS Half Degree Forecast Time Series']\n", + "\n", + "# Access the best dataset using the subset service and request data\n", + "ncss = best_ds.subset()\n", + "\n", + "# Set up query\n", + "query = ncss.query().accept('netcdf4')\n", + "query.lonlat_box(west=-90, east=-55, south=15, north=30)\n", + "query.variables('Pressure_surface', 'Wind_speed_gust_surface')\n", + "query.time_range(datetime(2017, 9, 6, 12), datetime(2017, 9, 11, 12))\n", + "\n", + "# Pull useful pieces out of nc\n", + "nc = ncss.get_data(query)\n", + "lon = nc.variables['longitude'][:]\n", + "lat = nc.variables['latitude'][:]\n", + "press = nc.variables['Pressure_surface']\n", + "winds = nc.variables['Wind_speed_gust_surface']\n", + "time_var = nc.variables['time1']\n", + "times = num2date(time_var[:], time_var.units)\n", + "\n", + "# Create a figure for plotting\n", + "proj = ccrs.LambertConformal(central_longitude=-70)\n", + "fig = plt.figure(figsize=(10, 5))\n", + "ax = fig.add_subplot(1, 1, 1, projection=proj)\n", + "ax.coastlines()\n", + "add_metpy_logo(fig, x=15, y=15)\n", + "\n", + "# Setup up the animation, looping over data to do the plotting that we want\n", + "pressure_levels = np.arange(95000, 105000, 800)\n", + "wind_levels = np.arange(0., 100., 10.)\n", + "artists = []\n", + "\n", + "for press_slice, wind_slice, time in zip(press, winds, times):\n", + " press_contour = ax.contour(lon, lat, press_slice, pressure_levels,\n", + " transform=ccrs.PlateCarree(), colors='black')\n", + " wind_contour = ax.contour(lon, lat, wind_slice, wind_levels,\n", + " transform=ccrs.PlateCarree(), colors='blue')\n", + " text = ax.text(0.5, 1.01, time, transform=ax.transAxes, ha='center')\n", + " artists.append(press_contour.collections + wind_contour.collections + [text])\n", + "\n", + "manimation.ArtistAnimation(fig, artists, interval=100)\n", + "```" ] }, { @@ -504,7 +550,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.6.4" } }, "nbformat": 4, diff --git a/notebooks/Animation/solutions/animation.py b/notebooks/Animation/solutions/animation.py deleted file mode 100644 index a9135f9c..00000000 --- a/notebooks/Animation/solutions/animation.py +++ /dev/null @@ -1,45 +0,0 @@ -from netCDF4 import num2date - -# Load data -cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/casestudies/irma/model/gfs/catalog.xml') -best_ds = cat.datasets['Best GFS Half Degree Forecast Time Series'] - -# Access the best dataset using the subset service and request data -ncss = best_ds.subset() - -# Set up query -query = ncss.query().accept('netcdf4') -query.lonlat_box(west=-90, east=-55, south=15, north=30) -query.variables('Pressure_surface', 'Wind_speed_gust_surface') -query.time_range(datetime(2017, 9, 6, 12), datetime(2017, 9, 11, 12)) - -# Pull useful pieces out of nc -nc = ncss.get_data(query) -lon = nc.variables['longitude'][:] -lat = nc.variables['latitude'][:] -press = nc.variables['Pressure_surface'] -winds = nc.variables['Wind_speed_gust_surface'] -time_var = nc.variables['time1'] -times = num2date(time_var[:], time_var.units) - -# Create a figure for plotting -proj = ccrs.LambertConformal(central_longitude=-70) -fig = plt.figure(figsize=(10, 5)) -ax = fig.add_subplot(1, 1, 1, projection=proj) -ax.coastlines() -add_metpy_logo(fig, x=15, y=15) - -# Setup up the animation, looping over data to do the plotting that we want -pressure_levels = np.arange(95000, 105000, 800) -wind_levels = np.arange(0., 100., 10.) -artists = [] - -for press_slice, wind_slice, time in zip(press, winds, times): - press_contour = ax.contour(lon, lat, press_slice, pressure_levels, - transform=ccrs.PlateCarree(), colors='black') - wind_contour = ax.contour(lon, lat, wind_slice, wind_levels, - transform=ccrs.PlateCarree(), colors='blue') - text = ax.text(0.5, 1.01, time, transform=ax.transAxes, ha='center') - artists.append(press_contour.collections + wind_contour.collections + [text]) - -manimation.ArtistAnimation(fig, artists, interval=100) diff --git a/notebooks/CartoPy/CartoPy.ipynb b/notebooks/CartoPy/CartoPy.ipynb index 235e82cf..0d663a7c 100644 --- a/notebooks/CartoPy/CartoPy.ipynb +++ b/notebooks/CartoPy/CartoPy.ipynb @@ -365,12 +365,25 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/map.py" + "\n", + "
\n", + "```python\n", + "fig = plt.figure(figsize=(10, 8))\n", + "ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator())\n", + "\n", + "ax.add_feature(cfeature.COASTLINE)\n", + "ax.add_feature(cfeature.LAND, facecolor='tab:brown')\n", + "ax.add_feature(cfeature.OCEAN, facecolor='tab:cyan')\n", + "ax.add_feature(cfeature.BORDERS, linewidth=2)\n", + "ax.add_feature(cfeature.STATES, linestyle=\"--\", edgecolor='black')\n", + "\n", + "ax.plot(-101.877, 33.583, marker='o', color='tab:green', transform=ccrs.PlateCarree())\n", + "\n", + "ax.set_extent([-108, -93, 25, 37])\n", + "```" ] } ], diff --git a/notebooks/CartoPy/solutions/map.py b/notebooks/CartoPy/solutions/map.py deleted file mode 100644 index 3d923a64..00000000 --- a/notebooks/CartoPy/solutions/map.py +++ /dev/null @@ -1,12 +0,0 @@ -fig = plt.figure(figsize=(10, 8)) -ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator()) - -ax.add_feature(cfeature.COASTLINE) -ax.add_feature(cfeature.LAND, facecolor='tab:brown') -ax.add_feature(cfeature.OCEAN, facecolor='tab:cyan') -ax.add_feature(cfeature.BORDERS, linewidth=2) -ax.add_feature(cfeature.STATES, linestyle="--", edgecolor='black') - -ax.plot(-101.877, 33.583, marker='o', color='tab:green', transform=ccrs.PlateCarree()) - -ax.set_extent([-108, -93, 25, 37]) diff --git a/notebooks/MetPy_Advanced/Isentropic Analysis.ipynb b/notebooks/MetPy_Advanced/Isentropic Analysis.ipynb index dc328984..7a2b8701 100644 --- a/notebooks/MetPy_Advanced/Isentropic Analysis.ipynb +++ b/notebooks/MetPy_Advanced/Isentropic Analysis.ipynb @@ -307,14 +307,58 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { "scrolled": false }, - "outputs": [], "source": [ - "# %load solutions/isen_mixing.py" + "\n", + "
\n", + "```python\n", + "# Needed to make numpy broadcasting work between 1D pressure and other 3D arrays\n", + "pressure_for_calc = press[:, None, None]\n", + "\n", + "# Calculate mixing ratio using something from mpcalc\n", + "mixing = mpcalc.mixing_ratio_from_relative_humidity(rh, temperature, pressure_for_calc)\n", + "\n", + "# Take the return and convert manually to units of 'dimenionless'\n", + "mixing.ito('dimensionless')\n", + "\n", + "# Interpolate all the data\n", + "isen_level = np.array([295]) * units.kelvin\n", + "ret = mpcalc.isentropic_interpolation(isen_level, press, temperature, mixing, u, v)\n", + "isen_press, isen_mixing, isen_u, isen_v = ret\n", + "\n", + "# Squeeze the returned arrays\n", + "isen_press = isen_press.squeeze()\n", + "isen_mixing = isen_mixing.squeeze()\n", + "isen_u = isen_u.squeeze()\n", + "isen_v = isen_v.squeeze()\n", + "\n", + "# Create Plot -- same as before\n", + "fig = plt.figure(figsize=(14, 8))\n", + "ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal(central_longitude=-100))\n", + "ax.coastlines()\n", + "\n", + "levels = np.arange(300, 1000, 25)\n", + "cntr = ax.contour(lon, lat, isen_press, transform=ccrs.PlateCarree(),\n", + " colors='black', levels=levels)\n", + "ax.clabel(cntr, fmt='%.0f')\n", + "\n", + "lon_slice = slice(None, None, 8)\n", + "lat_slice = slice(None, None, 8)\n", + "ax.barbs(lon[lon_slice], lat[lat_slice],\n", + " isen_u[lon_slice, lat_slice].to('knots').magnitude,\n", + " isen_v[lon_slice, lat_slice].to('knots').magnitude,\n", + " transform=ccrs.PlateCarree(), zorder=2)\n", + "\n", + "# Contourf the mixing ratio values\n", + "mixing_levels = [0.001, 0.002, 0.004, 0.006, 0.010, 0.012, 0.014, 0.016, 0.020]\n", + "ax.contourf(lon, lat, isen_mixing, transform=ccrs.PlateCarree(),\n", + " levels=mixing_levels, cmap='YlGn')\n", + "\n", + "ax.set_extent((-120, -70, 25, 55), crs=ccrs.PlateCarree())\n", + "```" ] }, { @@ -433,20 +477,42 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/isen_ascent.py" + "\n", + "
\n", + "```python\n", + "fig = plt.figure(figsize=(14, 8))\n", + "ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal(central_longitude=-100))\n", + "ax.coastlines()\n", + "\n", + "levels = np.arange(300, 1000, 25)\n", + "cntr = ax.contour(lon, lat, isen_press, transform=ccrs.PlateCarree(), colors='black', levels=levels)\n", + "ax.clabel(cntr, fmt='%.0f')\n", + "\n", + "lon_slice = slice(None, None, 5)\n", + "lat_slice = slice(None, None, 5)\n", + "ax.barbs(lon[lon_slice], lat[lat_slice],\n", + " isen_u[lon_slice, lat_slice].to('knots').magnitude,\n", + " isen_v[lon_slice, lat_slice].to('knots').magnitude,\n", + " transform=ccrs.PlateCarree(), zorder=2)\n", + "\n", + "levels = np.arange(-6, 7)\n", + "cs = ax.contourf(lon, lat, lift.to('microbar/s'), levels=levels, cmap='RdBu',\n", + " transform=ccrs.PlateCarree(), extend='both')\n", + "plt.colorbar(cs)\n", + "\n", + "ax.set_extent((-120, -70, 25, 55), crs=ccrs.PlateCarree())\n", + "```" ] } ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:unidata-workshop]", + "display_name": "Python 3", "language": "python", - "name": "conda-env-unidata-workshop-py" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/notebooks/MetPy_Advanced/solutions/isen_ascent.py b/notebooks/MetPy_Advanced/solutions/isen_ascent.py deleted file mode 100644 index e960b83b..00000000 --- a/notebooks/MetPy_Advanced/solutions/isen_ascent.py +++ /dev/null @@ -1,21 +0,0 @@ -fig = plt.figure(figsize=(14, 8)) -ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal(central_longitude=-100)) -ax.coastlines() - -levels = np.arange(300, 1000, 25) -cntr = ax.contour(lon, lat, isen_press, transform=ccrs.PlateCarree(), colors='black', levels=levels) -ax.clabel(cntr, fmt='%.0f') - -lon_slice = slice(None, None, 5) -lat_slice = slice(None, None, 5) -ax.barbs(lon[lon_slice], lat[lat_slice], - isen_u[lon_slice, lat_slice].to('knots').magnitude, - isen_v[lon_slice, lat_slice].to('knots').magnitude, - transform=ccrs.PlateCarree(), zorder=2) - -levels = np.arange(-6, 7) -cs = ax.contourf(lon, lat, lift.to('microbar/s'), levels=levels, cmap='RdBu', - transform=ccrs.PlateCarree(), extend='both') -plt.colorbar(cs) - -ax.set_extent((-120, -70, 25, 55), crs=ccrs.PlateCarree()) diff --git a/notebooks/MetPy_Advanced/solutions/isen_mixing.py b/notebooks/MetPy_Advanced/solutions/isen_mixing.py deleted file mode 100644 index 40be2dd2..00000000 --- a/notebooks/MetPy_Advanced/solutions/isen_mixing.py +++ /dev/null @@ -1,43 +0,0 @@ -# Needed to make numpy broadcasting work between 1D pressure and other 3D arrays -pressure_for_calc = press[:, None, None] - -# Calculate mixing ratio using something from mpcalc -mixing = mpcalc.mixing_ratio_from_relative_humidity(rh, temperature, pressure_for_calc) - -# Take the return and convert manually to units of 'dimenionless' -mixing.ito('dimensionless') - -# Interpolate all the data -isen_level = np.array([295]) * units.kelvin -ret = mpcalc.isentropic_interpolation(isen_level, press, temperature, mixing, u, v) -isen_press, isen_mixing, isen_u, isen_v = ret - -# Squeeze the returned arrays -isen_press = isen_press.squeeze() -isen_mixing = isen_mixing.squeeze() -isen_u = isen_u.squeeze() -isen_v = isen_v.squeeze() - -# Create Plot -- same as before -fig = plt.figure(figsize=(14, 8)) -ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal(central_longitude=-100)) -ax.coastlines() - -levels = np.arange(300, 1000, 25) -cntr = ax.contour(lon, lat, isen_press, transform=ccrs.PlateCarree(), - colors='black', levels=levels) -ax.clabel(cntr, fmt='%.0f') - -lon_slice = slice(None, None, 8) -lat_slice = slice(None, None, 8) -ax.barbs(lon[lon_slice], lat[lat_slice], - isen_u[lon_slice, lat_slice].to('knots').magnitude, - isen_v[lon_slice, lat_slice].to('knots').magnitude, - transform=ccrs.PlateCarree(), zorder=2) - -# Contourf the mixing ratio values -mixing_levels = [0.001, 0.002, 0.004, 0.006, 0.010, 0.012, 0.014, 0.016, 0.020] -ax.contourf(lon, lat, isen_mixing, transform=ccrs.PlateCarree(), - levels=mixing_levels, cmap='YlGn') - -ax.set_extent((-120, -70, 25, 55), crs=ccrs.PlateCarree()) diff --git a/notebooks/MetPy_Case_Study/MetPy_Case_Study.ipynb b/notebooks/MetPy_Case_Study/MetPy_Case_Study.ipynb index f88da66e..6a36111b 100644 --- a/notebooks/MetPy_Case_Study/MetPy_Case_Study.ipynb +++ b/notebooks/MetPy_Case_Study/MetPy_Case_Study.ipynb @@ -259,12 +259,25 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/parse_data.py\n" + "\n", + "
\n", + "```python\n", + "# Extract data and assign units\n", + "tmpk = gaussian_filter(data.variables['Temperature_isobaric'][0],\n", + " sigma=1.0) * units.K\n", + "hght = gaussian_filter(data.variables['Geopotential_height_isobaric'][0],\n", + " sigma=1.0) * units.meter\n", + "uwnd = gaussian_filter(data.variables['u-component_of_wind_isobaric'][0], sigma=1.0) * units('m/s')\n", + "vwnd = gaussian_filter(data.variables['v-component_of_wind_isobaric'][0], sigma=1.0) * units('m/s')\n", + "\n", + "# Extract coordinate data for plotting\n", + "lat = data.variables['lat'][:]\n", + "lon = data.variables['lon'][:]\n", + "lev = data.variables['isobaric1'][:]\n", + "```" ] }, { @@ -361,12 +374,31 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pick_levels.py\n" + "\n", + "
\n", + "```python\n", + "# Specify 850 hPa data\n", + "ilev850 = np.where(lev == 850)[0][0]\n", + "hght_850 = hght[ilev850]\n", + "tmpk_850 = tmpk[ilev850]\n", + "uwnd_850 = uwnd[ilev850]\n", + "vwnd_850 = vwnd[ilev850]\n", + "\n", + "# Specify 500 hPa data\n", + "ilev500 = np.where(lev == 500)[0][0]\n", + "hght_500 = hght[ilev500]\n", + "uwnd_500 = uwnd[ilev500]\n", + "vwnd_500 = vwnd[ilev500]\n", + "\n", + "# Specify 300 hPa data\n", + "ilev300 = np.where(lev == 300)[0][0]\n", + "hght_300 = hght[ilev300]\n", + "uwnd_300 = uwnd[ilev300]\n", + "vwnd_300 = vwnd[ilev300]\n", + "```" ] }, { @@ -418,12 +450,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/temp_adv.py\n" + "\n", + "
\n", + "```python\n", + "# Temperature Advection\n", + "tmpc_adv_850 = mpcalc.advection(tmpk_850, [uwnd_850, vwnd_850],\n", + " (dx, dy), dim_order='yx').to('degC/s')\n", + "\n", + "```" ] }, { @@ -483,12 +520,24 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/vorticity.py\n" + "\n", + "
\n", + "```python\n", + "# Vorticity and Absolute Vorticity Calculations\n", + "\n", + "# Planetary Vorticity\n", + "f = mpcalc.coriolis_parameter(np.deg2rad(lat)).to('1/s')\n", + "\n", + "# Relative Vorticity\n", + "vor_500 = mpcalc.vorticity(uwnd_500, vwnd_500, dx, dy,\n", + " dim_order='yx')\n", + "\n", + "# Abosolute Vorticity\n", + "avor_500 = vor_500 + f\n", + "```" ] }, { @@ -679,12 +728,48 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/map_850_Tadv.py\n" + "\n", + "
\n", + "```python\n", + "fig, ax = create_map_background()\n", + "\n", + "# Contour 1 - Temperature, dotted\n", + "cs2 = ax.contour(lon, lat, tmpk_850.to('degC'), range(-50, 50, 2),\n", + " colors='grey', linestyles='dotted', transform=dataproj)\n", + "\n", + "plt.clabel(cs2, fontsize=10, inline=1, inline_spacing=10, fmt='%i',\n", + " rightside_up=True, use_clabeltext=True)\n", + "\n", + "# Contour 2\n", + "clev850 = np.arange(0, 4000, 30)\n", + "cs = ax.contour(lon, lat, hght_850, clev850, colors='k',\n", + " linewidths=1.0, linestyles='solid', transform=dataproj)\n", + "\n", + "plt.clabel(cs, fontsize=10, inline=1, inline_spacing=10, fmt='%i',\n", + " rightside_up=True, use_clabeltext=True)\n", + "\n", + "# Filled contours - Temperature advection\n", + "contours = [-3, -2.2, -2, -1.5, -1, -0.5, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]\n", + "cf = ax.contourf(lon, lat, tmpc_adv_850*3600, contours,\n", + " cmap='bwr', extend='both', transform=dataproj)\n", + "plt.colorbar(cf, orientation='horizontal', pad=0, aspect=50,\n", + " extendrect=True, ticks=contours)\n", + "\n", + "# Vector\n", + "ax.barbs(lon, lat, uwnd_850.to('kts').m, vwnd_850.to('kts').m,\n", + " regrid_shape=15, transform=dataproj)\n", + "\n", + "# Titles\n", + "plt.title('850-hPa Geopotential Heights, Temperature (C), \\\n", + " Temp Adv (C/h), and Wind Barbs (kts)', loc='left')\n", + "plt.title('VALID: {}'.format(vtime), loc='right')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "```" ] }, { @@ -748,12 +833,51 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/map_500_Vort.py\n" + "\n", + "
\n", + "```python\n", + "fig, ax = create_map_background()\n", + "\n", + "# Contour 1\n", + "clev500 = np.arange(0, 7000, 60)\n", + "cs = ax.contour(lon, lat, hght_500, clev500, colors='k',\n", + " linewidths=1.0, linestyles='solid', transform=dataproj)\n", + "plt.clabel(cs, fontsize=10, inline=1, inline_spacing=4,\n", + " fmt='%i', rightside_up=True, use_clabeltext=True)\n", + "\n", + "# Filled contours\n", + "# Set contour intervals for Absolute Vorticity\n", + "clevavor500 = [-4, -3, -2, -1, 0, 7, 10, 13, 16, 19,\n", + " 22, 25, 28, 31, 34, 37, 40, 43, 46]\n", + "\n", + "# Set colorfill colors for absolute vorticity\n", + "# purple negative\n", + "# yellow to orange positive\n", + "colorsavor500 = ('#660066', '#660099', '#6600CC', '#6600FF',\n", + " '#FFFFFF', '#ffE800', '#ffD800', '#ffC800',\n", + " '#ffB800', '#ffA800', '#ff9800', '#ff8800',\n", + " '#ff7800', '#ff6800', '#ff5800', '#ff5000',\n", + " '#ff4000', '#ff3000')\n", + "\n", + "cf = ax.contourf(lon, lat, avor_500 * 10**5, clevavor500,\n", + " colors=colorsavor500, transform=dataproj)\n", + "plt.colorbar(cf, orientation='horizontal', pad=0, aspect=50)\n", + "\n", + "# Vector\n", + "ax.barbs(lon, lat, uwnd_500.to('kts').m, vwnd_500.to('kts').m,\n", + " regrid_shape=15, transform=dataproj)\n", + "\n", + "# Titles\n", + "plt.title('500-hPa Geopotential Heights, Absolute Vorticity \\\n", + " (1/s), and Wind Barbs (kts)', loc='left')\n", + "plt.title('VALID: {}'.format(vtime), loc='right')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "```" ] }, { @@ -811,12 +935,46 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/map_300_div_ageo.py\n" + "\n", + "
\n", + "```python\n", + "fig, ax = create_map_background()\n", + "\n", + "# Contour 1\n", + "clev300 = np.arange(0, 11000, 120)\n", + "cs2 = ax.contour(lon, lat, div_300 * 10**5, range(-10, 11, 2),\n", + " colors='grey', transform=dataproj)\n", + "plt.clabel(cs2, fontsize=10, inline=1, inline_spacing=4,\n", + " fmt='%i', rightside_up=True, use_clabeltext=True)\n", + "\n", + "# Contour 2\n", + "cs = ax.contour(lon, lat, hght_300, clev300, colors='k',\n", + " linewidths=1.0, linestyles='solid', transform=dataproj)\n", + "plt.clabel(cs, fontsize=10, inline=1, inline_spacing=4,\n", + " fmt='%i', rightside_up=True, use_clabeltext=True)\n", + "\n", + "# Filled Contours\n", + "spd300 = np.arange(50, 250, 20)\n", + "cf = ax.contourf(lon, lat, wspd_300, spd300, cmap='BuPu',\n", + " transform=dataproj, zorder=0)\n", + "plt.colorbar(cf, orientation='horizontal', pad=0.0, aspect=50)\n", + "\n", + "# Vector of 300-hPa Ageostrophic Wind Vectors\n", + "ax.quiver(lon, lat, uageo_300.m, vageo_300.m, regrid_shape=15,\n", + " pivot='mid', transform=dataproj, zorder=10)\n", + "\n", + "# Titles\n", + "plt.title('300-hPa Geopotential Heights, Divergence (1/s),\\\n", + " Wind Speed (kts), Ageostrophic Wind Vector (m/s)',\n", + " loc='left')\n", + "plt.title('VALID: {}'.format(vtime), loc='right')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "```" ] }, { @@ -1051,20 +1209,42 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/map_data_500.py\n" + "\n", + "
\n", + "```python\n", + "# Set up plot basics and use StationPlot class from MetPy to help with plotting\n", + "fig = plt.figure(figsize=(14, 8))\n", + "proj = ccrs.LambertConformal(central_latitude=50, central_longitude=-107)\n", + "ax = plt.subplot(111, projection=proj)\n", + "ax.coastlines('50m', edgecolor='grey', linewidth=0.75)\n", + "ax.add_feature(cfeature.STATES, edgecolor='grey', linewidth=0.5)\n", + "\n", + "# Set up station plotting using only every third\n", + "# element from arrays for plotting\n", + "stationplot = StationPlot(ax, lon[::3, ::3].ravel()[mask],\n", + " lat[::3, ::3].ravel()[mask],\n", + " transform=ccrs.PlateCarree(), fontsize=12)\n", + "\n", + "# Plot markers then data around marker for calculation purposes\n", + "ax.scatter(lon[::3, ::3].ravel()[mask], lat[::3, ::3].ravel()[mask],\n", + " marker='o', transform=dataproj)\n", + "stationplot.plot_parameter((0, 1), hght_500[::3, ::3].ravel()[mask])\n", + "stationplot.plot_parameter((-1.5, -1), uwnd_500[::3, ::3].ravel()[mask],\n", + " formatter='.1f')\n", + "stationplot.plot_parameter((1.5, -1), vwnd_500[::3, ::3].ravel()[mask],\n", + " formatter='.1f')\n", + "\n", + "# Title\n", + "plt.title('Geopotential (m; top), U-wind (m/s; Lower Left), \\\n", + " V-wind (m/s; Lower Right)')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "```" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/notebooks/MetPy_Case_Study/solutions/map_300_div_ageo.py b/notebooks/MetPy_Case_Study/solutions/map_300_div_ageo.py deleted file mode 100644 index 675144b1..00000000 --- a/notebooks/MetPy_Case_Study/solutions/map_300_div_ageo.py +++ /dev/null @@ -1,33 +0,0 @@ -fig, ax = create_map_background() - -# Contour 1 -clev300 = np.arange(0, 11000, 120) -cs2 = ax.contour(lon, lat, div_300 * 10**5, range(-10, 11, 2), - colors='grey', transform=dataproj) -plt.clabel(cs2, fontsize=10, inline=1, inline_spacing=4, - fmt='%i', rightside_up=True, use_clabeltext=True) - -# Contour 2 -cs = ax.contour(lon, lat, hght_300, clev300, colors='k', - linewidths=1.0, linestyles='solid', transform=dataproj) -plt.clabel(cs, fontsize=10, inline=1, inline_spacing=4, - fmt='%i', rightside_up=True, use_clabeltext=True) - -# Filled Contours -spd300 = np.arange(50, 250, 20) -cf = ax.contourf(lon, lat, wspd_300, spd300, cmap='BuPu', - transform=dataproj, zorder=0) -plt.colorbar(cf, orientation='horizontal', pad=0.0, aspect=50) - -# Vector of 300-hPa Ageostrophic Wind Vectors -ax.quiver(lon, lat, uageo_300.m, vageo_300.m, regrid_shape=15, - pivot='mid', transform=dataproj, zorder=10) - -# Titles -plt.title('300-hPa Geopotential Heights, Divergence (1/s),\ - Wind Speed (kts), Ageostrophic Wind Vector (m/s)', - loc='left') -plt.title('VALID: {}'.format(vtime), loc='right') - -plt.tight_layout() -plt.show() diff --git a/notebooks/MetPy_Case_Study/solutions/map_500_Vort.py b/notebooks/MetPy_Case_Study/solutions/map_500_Vort.py deleted file mode 100644 index 88229cb5..00000000 --- a/notebooks/MetPy_Case_Study/solutions/map_500_Vort.py +++ /dev/null @@ -1,38 +0,0 @@ -fig, ax = create_map_background() - -# Contour 1 -clev500 = np.arange(0, 7000, 60) -cs = ax.contour(lon, lat, hght_500, clev500, colors='k', - linewidths=1.0, linestyles='solid', transform=dataproj) -plt.clabel(cs, fontsize=10, inline=1, inline_spacing=4, - fmt='%i', rightside_up=True, use_clabeltext=True) - -# Filled contours -# Set contour intervals for Absolute Vorticity -clevavor500 = [-4, -3, -2, -1, 0, 7, 10, 13, 16, 19, - 22, 25, 28, 31, 34, 37, 40, 43, 46] - -# Set colorfill colors for absolute vorticity -# purple negative -# yellow to orange positive -colorsavor500 = ('#660066', '#660099', '#6600CC', '#6600FF', - '#FFFFFF', '#ffE800', '#ffD800', '#ffC800', - '#ffB800', '#ffA800', '#ff9800', '#ff8800', - '#ff7800', '#ff6800', '#ff5800', '#ff5000', - '#ff4000', '#ff3000') - -cf = ax.contourf(lon, lat, avor_500 * 10**5, clevavor500, - colors=colorsavor500, transform=dataproj) -plt.colorbar(cf, orientation='horizontal', pad=0, aspect=50) - -# Vector -ax.barbs(lon, lat, uwnd_500.to('kts').m, vwnd_500.to('kts').m, - regrid_shape=15, transform=dataproj) - -# Titles -plt.title('500-hPa Geopotential Heights, Absolute Vorticity \ - (1/s), and Wind Barbs (kts)', loc='left') -plt.title('VALID: {}'.format(vtime), loc='right') - -plt.tight_layout() -plt.show() diff --git a/notebooks/MetPy_Case_Study/solutions/map_850_Tadv.py b/notebooks/MetPy_Case_Study/solutions/map_850_Tadv.py deleted file mode 100644 index 2c2dacef..00000000 --- a/notebooks/MetPy_Case_Study/solutions/map_850_Tadv.py +++ /dev/null @@ -1,35 +0,0 @@ -fig, ax = create_map_background() - -# Contour 1 - Temperature, dotted -cs2 = ax.contour(lon, lat, tmpk_850.to('degC'), range(-50, 50, 2), - colors='grey', linestyles='dotted', transform=dataproj) - -plt.clabel(cs2, fontsize=10, inline=1, inline_spacing=10, fmt='%i', - rightside_up=True, use_clabeltext=True) - -# Contour 2 -clev850 = np.arange(0, 4000, 30) -cs = ax.contour(lon, lat, hght_850, clev850, colors='k', - linewidths=1.0, linestyles='solid', transform=dataproj) - -plt.clabel(cs, fontsize=10, inline=1, inline_spacing=10, fmt='%i', - rightside_up=True, use_clabeltext=True) - -# Filled contours - Temperature advection -contours = [-3, -2.2, -2, -1.5, -1, -0.5, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0] -cf = ax.contourf(lon, lat, tmpc_adv_850*3600, contours, - cmap='bwr', extend='both', transform=dataproj) -plt.colorbar(cf, orientation='horizontal', pad=0, aspect=50, - extendrect=True, ticks=contours) - -# Vector -ax.barbs(lon, lat, uwnd_850.to('kts').m, vwnd_850.to('kts').m, - regrid_shape=15, transform=dataproj) - -# Titles -plt.title('850-hPa Geopotential Heights, Temperature (C), \ - Temp Adv (C/h), and Wind Barbs (kts)', loc='left') -plt.title('VALID: {}'.format(vtime), loc='right') - -plt.tight_layout() -plt.show() diff --git a/notebooks/MetPy_Case_Study/solutions/map_data_500.py b/notebooks/MetPy_Case_Study/solutions/map_data_500.py deleted file mode 100644 index a64c58ee..00000000 --- a/notebooks/MetPy_Case_Study/solutions/map_data_500.py +++ /dev/null @@ -1,28 +0,0 @@ -# Set up plot basics and use StationPlot class from MetPy to help with plotting -fig = plt.figure(figsize=(14, 8)) -proj = ccrs.LambertConformal(central_latitude=50, central_longitude=-107) -ax = plt.subplot(111, projection=proj) -ax.coastlines('50m', edgecolor='grey', linewidth=0.75) -ax.add_feature(cfeature.STATES, edgecolor='grey', linewidth=0.5) - -# Set up station plotting using only every third -# element from arrays for plotting -stationplot = StationPlot(ax, lon[::3, ::3].ravel()[mask], - lat[::3, ::3].ravel()[mask], - transform=ccrs.PlateCarree(), fontsize=12) - -# Plot markers then data around marker for calculation purposes -ax.scatter(lon[::3, ::3].ravel()[mask], lat[::3, ::3].ravel()[mask], - marker='o', transform=dataproj) -stationplot.plot_parameter((0, 1), hght_500[::3, ::3].ravel()[mask]) -stationplot.plot_parameter((-1.5, -1), uwnd_500[::3, ::3].ravel()[mask], - formatter='.1f') -stationplot.plot_parameter((1.5, -1), vwnd_500[::3, ::3].ravel()[mask], - formatter='.1f') - -# Title -plt.title('Geopotential (m; top), U-wind (m/s; Lower Left), \ - V-wind (m/s; Lower Right)') - -plt.tight_layout() -plt.show() diff --git a/notebooks/MetPy_Case_Study/solutions/parse_data.py b/notebooks/MetPy_Case_Study/solutions/parse_data.py deleted file mode 100644 index e2b28c0e..00000000 --- a/notebooks/MetPy_Case_Study/solutions/parse_data.py +++ /dev/null @@ -1,12 +0,0 @@ -# Extract data and assign units -tmpk = gaussian_filter(data.variables['Temperature_isobaric'][0], - sigma=1.0) * units.K -hght = gaussian_filter(data.variables['Geopotential_height_isobaric'][0], - sigma=1.0) * units.meter -uwnd = gaussian_filter(data.variables['u-component_of_wind_isobaric'][0], sigma=1.0) * units('m/s') -vwnd = gaussian_filter(data.variables['v-component_of_wind_isobaric'][0], sigma=1.0) * units('m/s') - -# Extract coordinate data for plotting -lat = data.variables['lat'][:] -lon = data.variables['lon'][:] -lev = data.variables['isobaric1'][:] diff --git a/notebooks/MetPy_Case_Study/solutions/pick_levels.py b/notebooks/MetPy_Case_Study/solutions/pick_levels.py deleted file mode 100644 index 4debdfaa..00000000 --- a/notebooks/MetPy_Case_Study/solutions/pick_levels.py +++ /dev/null @@ -1,18 +0,0 @@ -# Specify 850 hPa data -ilev850 = np.where(lev == 850)[0][0] -hght_850 = hght[ilev850] -tmpk_850 = tmpk[ilev850] -uwnd_850 = uwnd[ilev850] -vwnd_850 = vwnd[ilev850] - -# Specify 500 hPa data -ilev500 = np.where(lev == 500)[0][0] -hght_500 = hght[ilev500] -uwnd_500 = uwnd[ilev500] -vwnd_500 = vwnd[ilev500] - -# Specify 300 hPa data -ilev300 = np.where(lev == 300)[0][0] -hght_300 = hght[ilev300] -uwnd_300 = uwnd[ilev300] -vwnd_300 = vwnd[ilev300] diff --git a/notebooks/MetPy_Case_Study/solutions/temp_adv.py b/notebooks/MetPy_Case_Study/solutions/temp_adv.py deleted file mode 100644 index d141c30d..00000000 --- a/notebooks/MetPy_Case_Study/solutions/temp_adv.py +++ /dev/null @@ -1,3 +0,0 @@ -# Temperature Advection -tmpc_adv_850 = mpcalc.advection(tmpk_850, [uwnd_850, vwnd_850], - (dx, dy), dim_order='yx').to('degC/s') diff --git a/notebooks/MetPy_Case_Study/solutions/vorticity.py b/notebooks/MetPy_Case_Study/solutions/vorticity.py deleted file mode 100644 index 2b1338ff..00000000 --- a/notebooks/MetPy_Case_Study/solutions/vorticity.py +++ /dev/null @@ -1,11 +0,0 @@ -# Vorticity and Absolute Vorticity Calculations - -# Planetary Vorticity -f = mpcalc.coriolis_parameter(np.deg2rad(lat)).to('1/s') - -# Relative Vorticity -vor_500 = mpcalc.vorticity(uwnd_500, vwnd_500, dx, dy, - dim_order='yx') - -# Abosolute Vorticity -avor_500 = vor_500 + f diff --git a/notebooks/Metpy_Introduction/Introduction to MetPy.ipynb b/notebooks/Metpy_Introduction/Introduction to MetPy.ipynb index 6143d321..1863b00b 100644 --- a/notebooks/Metpy_Introduction/Introduction to MetPy.ipynb +++ b/notebooks/Metpy_Introduction/Introduction to MetPy.ipynb @@ -148,12 +148,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/intro_units.py" + "\n", + "
\n", + "```python\n", + "speed = 25 * units.knots\n", + "time = 1 * units.fortnight\n", + "distance = speed * time\n", + "print(distance.to('furlongs'))\n", + "```" ] }, { @@ -220,12 +225,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/intro_temperature.py" + "\n", + "
\n", + "```python\n", + "temperature_change_rate = -2.3 * units.delta_degF / (10 * units.minutes)\n", + "temperature = 25 * units.degC\n", + "dt = 1.5 * units.hours\n", + "print(temperature + temperature_change_rate * dt)\n", + "```" ] }, { @@ -381,12 +391,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/intro_calc.py" + "\n", + "
\n", + "```python\n", + "speed = mpcalc.get_wind_speed(u, v)\n", + "print(speed)\n", + "print(speed.to('mph'))\n", + "```" ] }, { @@ -430,7 +444,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.6.4" } }, "nbformat": 4, diff --git a/notebooks/Metpy_Introduction/solutions/intro_calc.py b/notebooks/Metpy_Introduction/solutions/intro_calc.py deleted file mode 100644 index 79704c97..00000000 --- a/notebooks/Metpy_Introduction/solutions/intro_calc.py +++ /dev/null @@ -1,3 +0,0 @@ -speed = mpcalc.get_wind_speed(u, v) -print(speed) -print(speed.to('mph')) diff --git a/notebooks/Metpy_Introduction/solutions/intro_temperature.py b/notebooks/Metpy_Introduction/solutions/intro_temperature.py deleted file mode 100644 index af03a909..00000000 --- a/notebooks/Metpy_Introduction/solutions/intro_temperature.py +++ /dev/null @@ -1,4 +0,0 @@ -temperature_change_rate = -2.3 * units.delta_degF / (10 * units.minutes) -temperature = 25 * units.degC -dt = 1.5 * units.hours -print(temperature + temperature_change_rate * dt) diff --git a/notebooks/Metpy_Introduction/solutions/intro_units.py b/notebooks/Metpy_Introduction/solutions/intro_units.py deleted file mode 100644 index 6b7bcb22..00000000 --- a/notebooks/Metpy_Introduction/solutions/intro_units.py +++ /dev/null @@ -1,4 +0,0 @@ -speed = 25 * units.knots -time = 1 * units.fortnight -distance = speed * time -print(distance.to('furlongs')) diff --git a/notebooks/Model_Output/Downloading model fields with NCSS.ipynb b/notebooks/Model_Output/Downloading model fields with NCSS.ipynb index e7354fef..7f8fe940 100644 --- a/notebooks/Model_Output/Downloading model fields with NCSS.ipynb +++ b/notebooks/Model_Output/Downloading model fields with NCSS.ipynb @@ -318,14 +318,61 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { "scrolled": false }, - "outputs": [], "source": [ - "# %load solutions/model_plot.py\n" + "\n", + "
\n", + "```python\n", + "import numpy as np\n", + "\n", + "# Set up an NCSS query from thredds using siphon\n", + "query = ncss.query()\n", + "query.accept('netcdf4')\n", + "query.variables('Temperature_isobaric', 'Geopotential_height_isobaric')\n", + "query.vertical_level(50000)\n", + "query.time_range(datetime(2017, 9, 5), datetime(2017, 9, 6))\n", + "query.lonlat_box(west=-110, east=-45, north=50, south=10)\n", + "\n", + "# Download data using NCSS\n", + "data = ncss.get_data(query)\n", + "\n", + "longitude = data.variables['longitude'][:]\n", + "latitude = data.variables['latitude'][:]\n", + "temp_var = data.variables['Temperature_isobaric']\n", + "height_var = data.variables['Geopotential_height_isobaric']\n", + "\n", + "# Find the correct time dimension name\n", + "for coord in ncvar.coordinates.split():\n", + " if 'time' in coord:\n", + " timevar = data.variables[coord]\n", + " break\n", + "time = num2date(timevar[:], timevar.units)\n", + "\n", + "data_projection = ccrs.PlateCarree()\n", + "time_index = 0\n", + "\n", + "# Plot using CartoPy and Matplotlib\n", + "fig = plt.figure(figsize=(12, 8))\n", + "ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal())\n", + "\n", + "contours = np.arange(5000, 6000, 80)\n", + "ax.pcolormesh(longitude, latitude, temp_var[time_index].squeeze(),\n", + " transform=data_projection, zorder=0)\n", + "ax.contour(longitude, latitude, height_var[time_index].squeeze(), contours, colors='k',\n", + " transform=data_projection, linewidths=2, zorder=1)\n", + "ax.set_title(time[time_index])\n", + "\n", + "# add some common geographic features\n", + "ax.coastlines(resolution='10m', color='black')\n", + "ax.add_feature(cfeature.STATES, edgecolor='black')\n", + "ax.add_feature(cfeature.BORDERS)\n", + "\n", + "# add some lat/lon gridlines\n", + "ax.gridlines()\n", + "```" ] }, { @@ -461,13 +508,6 @@ "skew.plot_moist_adiabats()\n", "skew.plot_mixing_lines()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/notebooks/Model_Output/solutions/model_plot.py b/notebooks/Model_Output/solutions/model_plot.py deleted file mode 100644 index 7fb21997..00000000 --- a/notebooks/Model_Output/solutions/model_plot.py +++ /dev/null @@ -1,46 +0,0 @@ -import numpy as np - -# Set up an NCSS query from thredds using siphon -query = ncss.query() -query.accept('netcdf4') -query.variables('Temperature_isobaric', 'Geopotential_height_isobaric') -query.vertical_level(50000) -query.time_range(datetime(2017, 9, 5), datetime(2017, 9, 6)) -query.lonlat_box(west=-110, east=-45, north=50, south=10) - -# Download data using NCSS -data = ncss.get_data(query) - -longitude = data.variables['longitude'][:] -latitude = data.variables['latitude'][:] -temp_var = data.variables['Temperature_isobaric'] -height_var = data.variables['Geopotential_height_isobaric'] - -# Find the correct time dimension name -for coord in ncvar.coordinates.split(): - if 'time' in coord: - timevar = data.variables[coord] - break -time = num2date(timevar[:], timevar.units) - -data_projection = ccrs.PlateCarree() -time_index = 0 - -# Plot using CartoPy and Matplotlib -fig = plt.figure(figsize=(12, 8)) -ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal()) - -contours = np.arange(5000, 6000, 80) -ax.pcolormesh(longitude, latitude, temp_var[time_index].squeeze(), - transform=data_projection, zorder=0) -ax.contour(longitude, latitude, height_var[time_index].squeeze(), contours, colors='k', - transform=data_projection, linewidths=2, zorder=1) -ax.set_title(time[time_index]) - -# add some common geographic features -ax.coastlines(resolution='10m', color='black') -ax.add_feature(cfeature.STATES, edgecolor='black') -ax.add_feature(cfeature.BORDERS) - -# add some lat/lon gridlines -ax.gridlines() diff --git a/notebooks/NumPy/Intermediate NumPy.ipynb b/notebooks/NumPy/Intermediate NumPy.ipynb index fec14930..73ab60c9 100644 --- a/notebooks/NumPy/Intermediate NumPy.ipynb +++ b/notebooks/NumPy/Intermediate NumPy.ipynb @@ -273,21 +273,29 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/average.py" + "\n", + "
\n", + "```python\n", + "data = np.array([1, 3, 5, 7, 9, 11])\n", + "out = (data[:-1] + data[1:]) / 2\n", + "print(out)\n", + "```" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/average3.py" + "\n", + "
\n", + "```python\n", + "data = np.array([1, 3, 5, 7, 9, 11])\n", + "out = (data[2:] + data[1:-1] + data[:-2]) / 3\n", + "print(out)\n", + "```" ] }, { @@ -314,12 +322,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/column_sums.py" + "\n", + "
\n", + "```python\n", + "print(data[0] + data[1] + data[2])\n", + "\n", + "# Or we can use numpy's sum and use the \"axis\" argument\n", + "print(np.sum(data, axis=0))\n", + "```" ] }, { @@ -424,12 +437,15 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/advection.py" + "\n", + "
\n", + "```python\n", + "advec = (wind_vec * -grad_vec).sum(axis=-1)\n", + "print(advec.shape)\n", + "```" ] }, { @@ -599,12 +615,35 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/heat_index.py" + "\n", + "
\n", + "```python\n", + "import numpy as np\n", + "\n", + "# Here's the \"data\"\n", + "np.random.seed(19990503) # Make sure we all have the same data\n", + "temp = (20 * np.cos(np.linspace(0, 2 * np.pi, 100)) +\n", + " 80 + 2 * np.random.randn(100))\n", + "rh = (np.abs(20 * np.cos(np.linspace(0, 4 * np.pi, 100)) +\n", + " 50 + 5 * np.random.randn(100)))\n", + "\n", + "\n", + "# Create a mask for the two conditions described above\n", + "good_heat_index = (temp >= 80) & (rh >= 0.4)\n", + "\n", + "\n", + "# Use this mask to grab the temperature and relative humidity values that together\n", + "# will give good heat index values\n", + "print(temp[good_heat_index]) \n", + "\n", + "# BONUS POINTS: Plot only the data where heat index is defined by\n", + "# inverting the mask (using `~mask`) and setting invalid values to np.nan\n", + "temp[~good_heat_index] = np.nan\n", + "plt.plot(temp, 'tab:red')\n", + "```" ] }, { @@ -727,9 +766,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:unidata-workshop]", + "display_name": "Python 3", "language": "python", - "name": "conda-env-unidata-workshop-py" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -741,7 +780,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.6.4" } }, "nbformat": 4, diff --git a/notebooks/NumPy/solutions/advection.py b/notebooks/NumPy/solutions/advection.py deleted file mode 100644 index efbff983..00000000 --- a/notebooks/NumPy/solutions/advection.py +++ /dev/null @@ -1,2 +0,0 @@ -advec = (wind_vec * -grad_vec).sum(axis=-1) -print(advec.shape) diff --git a/notebooks/NumPy/solutions/average.py b/notebooks/NumPy/solutions/average.py deleted file mode 100644 index b5155c33..00000000 --- a/notebooks/NumPy/solutions/average.py +++ /dev/null @@ -1,3 +0,0 @@ -data = np.array([1, 3, 5, 7, 9, 11]) -out = (data[:-1] + data[1:]) / 2 -print(out) diff --git a/notebooks/NumPy/solutions/average3.py b/notebooks/NumPy/solutions/average3.py deleted file mode 100644 index c0307f4c..00000000 --- a/notebooks/NumPy/solutions/average3.py +++ /dev/null @@ -1,3 +0,0 @@ -data = np.array([1, 3, 5, 7, 9, 11]) -out = (data[2:] + data[1:-1] + data[:-2]) / 3 -print(out) diff --git a/notebooks/NumPy/solutions/column_sums.py b/notebooks/NumPy/solutions/column_sums.py deleted file mode 100644 index fa01c199..00000000 --- a/notebooks/NumPy/solutions/column_sums.py +++ /dev/null @@ -1,4 +0,0 @@ -print(data[0] + data[1] + data[2]) - -# Or we can use numpy's sum and use the "axis" argument -print(np.sum(data, axis=0)) diff --git a/notebooks/NumPy/solutions/heat_index.py b/notebooks/NumPy/solutions/heat_index.py deleted file mode 100644 index f2c6ecb4..00000000 --- a/notebooks/NumPy/solutions/heat_index.py +++ /dev/null @@ -1,22 +0,0 @@ -import numpy as np - -# Here's the "data" -np.random.seed(19990503) # Make sure we all have the same data -temp = (20 * np.cos(np.linspace(0, 2 * np.pi, 100)) + - 80 + 2 * np.random.randn(100)) -rh = (np.abs(20 * np.cos(np.linspace(0, 4 * np.pi, 100)) + - 50 + 5 * np.random.randn(100))) - - -# Create a mask for the two conditions described above -good_heat_index = (temp >= 80) & (rh >= 0.4) - - -# Use this mask to grab the temperature and relative humidity values that together -# will give good heat index values -print(temp[good_heat_index]) - -# BONUS POINTS: Plot only the data where heat index is defined by -# inverting the mask (using `~mask`) and setting invalid values to np.nan -temp[~good_heat_index] = np.nan -plt.plot(temp, 'tab:red') diff --git a/notebooks/Pythonic_Data_Analysis/Advanced Pythonic Data Analysis.ipynb b/notebooks/Pythonic_Data_Analysis/Advanced Pythonic Data Analysis.ipynb index 17ae952c..a24483d0 100644 --- a/notebooks/Pythonic_Data_Analysis/Advanced Pythonic Data Analysis.ipynb +++ b/notebooks/Pythonic_Data_Analysis/Advanced Pythonic Data Analysis.ipynb @@ -327,12 +327,37 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_dictionaryupdate.py" + "\n", + "
\n", + "```python\n", + "type_styles = {'Pressure': dict(color='black'),\n", + " 'Wind': dict(linestyle='-')}\n", + "\n", + "variable_styles = {'pressure': dict(),\n", + " 'wind_speed': dict(color='tab:orange', linewidth=2),\n", + " 'wind_gust': dict(color='tab:olive', linewidth=0.5)}\n", + "\n", + "fig, axes = plt.subplots(1, len(plot_variables), sharex=True, figsize=(14, 5))\n", + "\n", + "for col, var_names in enumerate(plot_variables):\n", + " ax = axes[col]\n", + " for var_name in var_names:\n", + " title, label = format_varname(var_name)\n", + " style = type_styles[title].copy() # So the next line doesn't change the original\n", + " style.update(variable_styles[var_name])\n", + " ax.plot(df.time, df[var_name], **style)\n", + "\n", + " ax.set_ylabel(title)\n", + " ax.set_title('Buoy 41056 {}'.format(title))\n", + "\n", + " ax.grid(True)\n", + " ax.set_xlabel('Time')\n", + " ax.xaxis.set_major_formatter(DateFormatter('%m/%d'))\n", + " ax.xaxis.set_major_locator(DayLocator())\n", + "```" ] }, { @@ -469,12 +494,46 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_pressureconversion.py" + "\n", + "
\n", + "```python\n", + "def convert_pressure(a):\n", + " return a * 1e-3\n", + "\n", + "converters = {'Wind': filter_wind, 'Pressure': convert_pressure}\n", + "\n", + "type_styles = {'Pressure': dict(color='black'),\n", + " 'Wind': dict(linestyle='-')}\n", + "\n", + "variable_styles = {'pressure': dict(),\n", + " 'wind_speed': dict(color='tab:orange', linewidth=2),\n", + " 'wind_gust': dict(color='tab:olive', linewidth=0.5)}\n", + "\n", + "fig, axes = plt.subplots(1, len(plot_variables), sharex=True, figsize=(14, 5))\n", + "\n", + "for col, var_names in enumerate(plot_variables):\n", + " ax = axes[col]\n", + " for var_name in var_names:\n", + " title, label = format_varname(var_name)\n", + " \n", + " # Apply our pre-processing\n", + " var_data = converters[title](df[var_name])\n", + " \n", + " style = type_styles[title].copy() # So the next line doesn't change the original\n", + " style.update(variable_styles[var_name])\n", + " ax.plot(df.time, var_data, **style)\n", + "\n", + " ax.set_ylabel(title)\n", + " ax.set_title('Buoy 41056 {}'.format(title))\n", + "\n", + " ax.grid(True)\n", + " ax.set_xlabel('Time')\n", + " ax.xaxis.set_major_formatter(DateFormatter('%m/%d'))\n", + " ax.xaxis.set_major_locator(DayLocator())\n", + "```" ] }, { @@ -586,12 +645,43 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_bounds.py" + "\n", + "
\n", + "```python\n", + "bounds = {'Wind': (0, 30),\n", + " 'Pressure': (975, 1015)}\n", + "\n", + "type_styles = {'Pressure': dict(color='black'),\n", + " 'Wind': dict(linestyle='-')}\n", + "\n", + "variable_styles = {'pressure': dict(),\n", + " 'wind_speed': dict(color='tab:orange', linewidth=2),\n", + " 'wind_gust': dict(color='tab:olive', linewidth=0.5)}\n", + "\n", + "fig, axes = plt.subplots(len(data_files), len(plot_variables), sharex=True, figsize=(14, 10))\n", + "\n", + "for row, fname in enumerate(data_files):\n", + " df = read_buoy_data(fname)\n", + " for col, var_names in enumerate(plot_variables):\n", + " ax = axes[row, col]\n", + " for var_name in var_names:\n", + " title, label = format_varname(var_name)\n", + " style = type_styles[title].copy() # So the next line doesn't change the original\n", + " style.update(variable_styles[var_name])\n", + " ax.plot(df.time, df[var_name], **style)\n", + " ax.set_ylim(bounds[title])\n", + " \n", + " ax.set_ylabel(title)\n", + " ax.set_title('Buoy 41056 {}'.format(title))\n", + "\n", + " ax.grid(True)\n", + " ax.set_xlabel('Time')\n", + " ax.xaxis.set_major_formatter(DateFormatter('%m/%d'))\n", + " ax.xaxis.set_major_locator(DayLocator())\n", + "```" ] }, { @@ -619,7 +709,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.6.4" } }, "nbformat": 4, diff --git a/notebooks/Pythonic_Data_Analysis/Pythonic Data Analysis.ipynb b/notebooks/Pythonic_Data_Analysis/Pythonic Data Analysis.ipynb index c15b2cba..8a4eab96 100644 --- a/notebooks/Pythonic_Data_Analysis/Pythonic Data Analysis.ipynb +++ b/notebooks/Pythonic_Data_Analysis/Pythonic Data Analysis.ipynb @@ -232,12 +232,18 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_parameter_iteration.py" + "\n", + "
\n", + "```python\n", + "plot_variables = ['wind_speed', 'pressure']\n", + "plot_names = ['Windspeed', 'Atmospheric Pressure']\n", + "\n", + "for var, name in zip(plot_variables, plot_names):\n", + " print('Plotting variable', var, 'as', name)\n", + "```" ] }, { @@ -299,12 +305,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_enumeration.py" + "\n", + "
\n", + "```python\n", + "for i, item in enumerate(zip(my_list, my_other_list)):\n", + " reference, quote = item\n", + " print(i, ' - ', reference, ' - ', quote)\n", + "```" ] }, { @@ -368,12 +378,18 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_functions.py" + "\n", + "
\n", + "```python\n", + "def myfunc(exp):\n", + " return 2**exp\n", + "\n", + "for i in range(0, 25):\n", + " print(myfunc(i))\n", + "```" ] }, { @@ -552,12 +568,32 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_linestyles.py" + "\n", + "
\n", + "```python\n", + "linestyles = {'wind_speed': '-', 'wind_gust': '--', 'pressure': '-'}\n", + "\n", + "fig, axes = plt.subplots(1, len(plot_variables), sharex=True, figsize=(18, 6))\n", + "\n", + "for ax, var_names in zip(axes, plot_variables):\n", + "\n", + " for var_name in var_names:\n", + " # Grab the color from our dictionary and pass it to plot()\n", + " color = colors[var_name]\n", + " linestyle = linestyles[var_name]\n", + " ax.plot(df.time, df[var_name], color, linestyle=linestyle)\n", + "\n", + " ax.set_ylabel(var_name)\n", + " ax.set_title('Buoy {}'.format(var_name))\n", + "\n", + " ax.grid(True)\n", + " ax.set_xlabel('Time')\n", + " ax.xaxis.set_major_formatter(DateFormatter('%m/%d'))\n", + " ax.xaxis.set_major_locator(DayLocator())\n", + "```" ] }, { @@ -744,12 +780,60 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/pythonic_troubleshooting.py" + "\n", + "
\n", + "```python\n", + "def read_buoy_data(fname):\n", + " \"\"\"Handy function to read and cleanup the buoy data files.\"\"\"\n", + " col_names = ['year', 'month', 'day', 'hour', 'minute', 'wind_direction', 'wind_speed',\n", + " 'wind_gust', 'wave_height', 'dominant_wave_period', 'average_wave_period',\n", + " 'dominant_wave_direction', 'pressure', 'temperature', 'water_temperature', 'dewpoint',\n", + " 'visibility', '3hr_pressure_tendency', 'water_level_above_mean']\n", + " \n", + " widths = [4, 3, 3, 3, 3, 4, 5, 5, 6, 6, 6, 4, 7, 6, 6, 6, 5, 5, 6]\n", + " \n", + " df = pd.read_fwf(fname, skiprows=2, na_values='MM', names=col_names, widths=widths)\n", + "\n", + " df['time'] = pd.to_datetime(df[['year', 'month', 'day', 'hour', 'minute']])\n", + "\n", + " # Using inplace means the return is None and the dataframe is simply modified.\n", + " df.drop(['year', 'month', 'day', 'hour', 'minute'], axis='columns', inplace=True)\n", + " \n", + " idx = (df.time >= datetime(2017, 9, 6)) & (df.time <= datetime(2017, 9, 8))\n", + " df = df[idx]\n", + " \n", + " df.reset_index(drop=True, inplace=True)\n", + " \n", + " return df\n", + "\n", + "\n", + "files = ['41056.txt', '41052.txt']\n", + "\n", + "fig, axes = plt.subplots(len(files), len(plot_variables), sharex=True, figsize=(14, 10))\n", + "\n", + "for row, filename in enumerate(files):\n", + " df = read_buoy_data(filename)\n", + " \n", + "\n", + " for col, var_names in enumerate(plot_variables):\n", + " ax = axes[row,col]\n", + " for var_name in var_names:\n", + " title, label = format_varname(var_name)\n", + " color = colors[var_name]\n", + " linestyle = linestyles[var_name]\n", + " ax.plot(df.time, df[var_name], color, linestyle=linestyle, label=label)\n", + "\n", + " ax.set_ylabel(title)\n", + " ax.set_title('Buoy {} {}'.format(filename.split('.')[0], title))\n", + "\n", + " ax.grid(True)\n", + " ax.set_xlabel('Time')\n", + " ax.xaxis.set_major_formatter(DateFormatter('%m/%d'))\n", + " ax.xaxis.set_major_locator(DayLocator())\n", + "```" ] }, { @@ -777,7 +861,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.6.4" } }, "nbformat": 4, diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_bounds.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_bounds.py deleted file mode 100644 index 83e79087..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_bounds.py +++ /dev/null @@ -1,30 +0,0 @@ -bounds = {'Wind': (0, 30), - 'Pressure': (975, 1015)} - -type_styles = {'Pressure': dict(color='black'), - 'Wind': dict(linestyle='-')} - -variable_styles = {'pressure': dict(), - 'wind_speed': dict(color='tab:orange', linewidth=2), - 'wind_gust': dict(color='tab:olive', linewidth=0.5)} - -fig, axes = plt.subplots(len(data_files), len(plot_variables), sharex=True, figsize=(14, 10)) - -for row, fname in enumerate(data_files): - df = read_buoy_data(fname) - for col, var_names in enumerate(plot_variables): - ax = axes[row, col] - for var_name in var_names: - title, label = format_varname(var_name) - style = type_styles[title].copy() # So the next line doesn't change the original - style.update(variable_styles[var_name]) - ax.plot(df.time, df[var_name], **style) - ax.set_ylim(bounds[title]) - - ax.set_ylabel(title) - ax.set_title('Buoy 41056 {}'.format(title)) - - ax.grid(True) - ax.set_xlabel('Time') - ax.xaxis.set_major_formatter(DateFormatter('%m/%d')) - ax.xaxis.set_major_locator(DayLocator()) diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_dictionaryupdate.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_dictionaryupdate.py deleted file mode 100644 index 9f01efa9..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_dictionaryupdate.py +++ /dev/null @@ -1,24 +0,0 @@ -type_styles = {'Pressure': dict(color='black'), - 'Wind': dict(linestyle='-')} - -variable_styles = {'pressure': dict(), - 'wind_speed': dict(color='tab:orange', linewidth=2), - 'wind_gust': dict(color='tab:olive', linewidth=0.5)} - -fig, axes = plt.subplots(1, len(plot_variables), sharex=True, figsize=(14, 5)) - -for col, var_names in enumerate(plot_variables): - ax = axes[col] - for var_name in var_names: - title, label = format_varname(var_name) - style = type_styles[title].copy() # So the next line doesn't change the original - style.update(variable_styles[var_name]) - ax.plot(df.time, df[var_name], **style) - - ax.set_ylabel(title) - ax.set_title('Buoy 41056 {}'.format(title)) - - ax.grid(True) - ax.set_xlabel('Time') - ax.xaxis.set_major_formatter(DateFormatter('%m/%d')) - ax.xaxis.set_major_locator(DayLocator()) diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_enumeration.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_enumeration.py deleted file mode 100644 index 6ef67651..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_enumeration.py +++ /dev/null @@ -1,3 +0,0 @@ -for i, item in enumerate(zip(my_list, my_other_list)): - reference, quote = item - print(i, ' - ', reference, ' - ', quote) diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_functions.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_functions.py deleted file mode 100644 index 882da00d..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_functions.py +++ /dev/null @@ -1,5 +0,0 @@ -def myfunc(exp): - return 2**exp - -for i in range(0, 25): - print(myfunc(i)) diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_linestyles.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_linestyles.py deleted file mode 100644 index cc415f5d..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_linestyles.py +++ /dev/null @@ -1,19 +0,0 @@ -linestyles = {'wind_speed': '-', 'wind_gust': '--', 'pressure': '-'} - -fig, axes = plt.subplots(1, len(plot_variables), sharex=True, figsize=(18, 6)) - -for ax, var_names in zip(axes, plot_variables): - - for var_name in var_names: - # Grab the color from our dictionary and pass it to plot() - color = colors[var_name] - linestyle = linestyles[var_name] - ax.plot(df.time, df[var_name], color, linestyle=linestyle) - - ax.set_ylabel(var_name) - ax.set_title('Buoy {}'.format(var_name)) - - ax.grid(True) - ax.set_xlabel('Time') - ax.xaxis.set_major_formatter(DateFormatter('%m/%d')) - ax.xaxis.set_major_locator(DayLocator()) diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_parameter_iteration.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_parameter_iteration.py deleted file mode 100644 index 131d22df..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_parameter_iteration.py +++ /dev/null @@ -1,5 +0,0 @@ -plot_variables = ['wind_speed', 'pressure'] -plot_names = ['Windspeed', 'Atmospheric Pressure'] - -for var, name in zip(plot_variables, plot_names): - print('Plotting variable', var, 'as', name) diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_pressureconversion.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_pressureconversion.py deleted file mode 100644 index 6d9ae689..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_pressureconversion.py +++ /dev/null @@ -1,33 +0,0 @@ -def convert_pressure(a): - return a * 1e-3 - -converters = {'Wind': filter_wind, 'Pressure': convert_pressure} - -type_styles = {'Pressure': dict(color='black'), - 'Wind': dict(linestyle='-')} - -variable_styles = {'pressure': dict(), - 'wind_speed': dict(color='tab:orange', linewidth=2), - 'wind_gust': dict(color='tab:olive', linewidth=0.5)} - -fig, axes = plt.subplots(1, len(plot_variables), sharex=True, figsize=(14, 5)) - -for col, var_names in enumerate(plot_variables): - ax = axes[col] - for var_name in var_names: - title, label = format_varname(var_name) - - # Apply our pre-processing - var_data = converters[title](df[var_name]) - - style = type_styles[title].copy() # So the next line doesn't change the original - style.update(variable_styles[var_name]) - ax.plot(df.time, var_data, **style) - - ax.set_ylabel(title) - ax.set_title('Buoy 41056 {}'.format(title)) - - ax.grid(True) - ax.set_xlabel('Time') - ax.xaxis.set_major_formatter(DateFormatter('%m/%d')) - ax.xaxis.set_major_locator(DayLocator()) diff --git a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_troubleshooting.py b/notebooks/Pythonic_Data_Analysis/solutions/pythonic_troubleshooting.py deleted file mode 100644 index 64f3f268..00000000 --- a/notebooks/Pythonic_Data_Analysis/solutions/pythonic_troubleshooting.py +++ /dev/null @@ -1,47 +0,0 @@ -def read_buoy_data(fname): - """Handy function to read and cleanup the buoy data files.""" - col_names = ['year', 'month', 'day', 'hour', 'minute', 'wind_direction', 'wind_speed', - 'wind_gust', 'wave_height', 'dominant_wave_period', 'average_wave_period', - 'dominant_wave_direction', 'pressure', 'temperature', 'water_temperature', 'dewpoint', - 'visibility', '3hr_pressure_tendency', 'water_level_above_mean'] - - widths = [4, 3, 3, 3, 3, 4, 5, 5, 6, 6, 6, 4, 7, 6, 6, 6, 5, 5, 6] - - df = pd.read_fwf(fname, skiprows=2, na_values='MM', names=col_names, widths=widths) - - df['time'] = pd.to_datetime(df[['year', 'month', 'day', 'hour', 'minute']]) - - # Using inplace means the return is None and the dataframe is simply modified. - df.drop(['year', 'month', 'day', 'hour', 'minute'], axis='columns', inplace=True) - - idx = (df.time >= datetime(2017, 9, 6)) & (df.time <= datetime(2017, 9, 8)) - df = df[idx] - - df.reset_index(drop=True, inplace=True) - - return df - - -files = ['41056.txt', '41052.txt'] - -fig, axes = plt.subplots(len(files), len(plot_variables), sharex=True, figsize=(14, 10)) - -for row, filename in enumerate(files): - df = read_buoy_data(filename) - - - for col, var_names in enumerate(plot_variables): - ax = axes[row,col] - for var_name in var_names: - title, label = format_varname(var_name) - color = colors[var_name] - linestyle = linestyles[var_name] - ax.plot(df.time, df[var_name], color, linestyle=linestyle, label=label) - - ax.set_ylabel(title) - ax.set_title('Buoy {} {}'.format(filename.split('.')[0], title)) - - ax.grid(True) - ax.set_xlabel('Time') - ax.xaxis.set_major_formatter(DateFormatter('%m/%d')) - ax.xaxis.set_major_locator(DayLocator()) diff --git a/notebooks/Satellite_Data/Working with Satellite Data.ipynb b/notebooks/Satellite_Data/Working with Satellite Data.ipynb index ebae674b..b15945cf 100644 --- a/notebooks/Satellite_Data/Working with Satellite Data.ipynb +++ b/notebooks/Satellite_Data/Working with Satellite Data.ipynb @@ -130,12 +130,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/satellite_data.py" + "\n", + "
\n", + "```python\n", + "cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/casestudies/irma/goes16/Mesoscale-1/Channel09/20170910/catalog.xml')\n", + "ds = cat.datasets.filter_time_nearest(datetime(2017, 9, 10, 0))\n", + "print(ds.name)\n", + "ds = ds.remote_access(service='OPENDAP')\n", + "```" ] }, { @@ -594,12 +599,66 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/satellite_conus.py" + "\n", + "
\n", + "```python\n", + "cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/casestudies/irma/goes16/CONUS/Channel10/20170909/catalog.xml')\n", + "ds = cat.datasets.filter_time_nearest(datetime(2017, 9, 9, 6))\n", + "print(ds.name)\n", + "ds = ds.remote_access(service='OPENDAP')\n", + "timestamp = datetime.strptime(ds.start_date_time, '%Y%j%H%M%S')\n", + "data_var = ds.variables['Sectorized_CMI']\n", + "\n", + "x = ds.variables['x'][:]\n", + "y = ds.variables['y'][:]\n", + "proj_var = ds.variables[data_var.grid_mapping]\n", + "\n", + "# Create a Globe specifying a spherical earth with the correct radius\n", + "globe = ccrs.Globe(ellipse='sphere', semimajor_axis=proj_var.semi_major,\n", + " semiminor_axis=proj_var.semi_minor)\n", + "\n", + "# Select the correct projection.\n", + "\n", + "if proj_var.grid_mapping_name == 'lambert_conformal_conic':\n", + " proj = ccrs.LambertConformal(central_longitude=proj_var.longitude_of_central_meridian,\n", + " central_latitude=proj_var.latitude_of_projection_origin,\n", + " standard_parallels=[proj_var.standard_parallel],\n", + " globe=globe)\n", + "\n", + "else:\n", + " proj = ccrs.Mercator(central_longitude=proj_var.longitude_of_projection_origin, \n", + " latitude_true_scale=proj_var.standard_parallel,\n", + " globe=globe)\n", + "\n", + "wv_norm, wv_cmap = registry.get_with_range('WVCIMSS_r', 195, 265)\n", + "\n", + "fig = plt.figure(figsize=(10, 10))\n", + "ax = fig.add_subplot(1, 1, 1, projection=proj)\n", + "\n", + "im = ax.imshow(data_var[:], extent=(x.min(), x.max(), y.min(), y.max()), origin='upper',\n", + " cmap=wv_cmap, norm=wv_norm)\n", + "ax.coastlines(resolution='50m', color='black')\n", + "ax.add_feature(cfeature.STATES, linestyle=':')\n", + "ax.add_feature(cfeature.BORDERS, linewidth=2)\n", + "\n", + "# Add text (aligned to the right); save the returned object so we can manipulate it.\n", + "text_time = ax.text(0.99, 0.01, timestamp.strftime('%d %B %Y %H%MZ'),\n", + " horizontalalignment='right', transform=ax.transAxes,\n", + " color='white', fontsize='x-large', weight='bold')\n", + "\n", + "text_channel = ax.text(0.5, 0.97, 'Experimental GOES-16 Ch.{}'.format(channel),\n", + " horizontalalignment='center', transform=ax.transAxes,\n", + " color='white', fontsize='large', weight='bold')\n", + "\n", + "outline_effect = [patheffects.withStroke(linewidth=2, foreground='black')]\n", + "text_time.set_path_effects(outline_effect)\n", + "text_channel.set_path_effects(outline_effect)\n", + "\n", + "fig = add_metpy_logo(fig)\n", + "```" ] }, { diff --git a/notebooks/Satellite_Data/solutions/satellite_conus.py b/notebooks/Satellite_Data/solutions/satellite_conus.py deleted file mode 100644 index 97e8e4ea..00000000 --- a/notebooks/Satellite_Data/solutions/satellite_conus.py +++ /dev/null @@ -1,53 +0,0 @@ -cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/casestudies/irma/goes16/CONUS/Channel10/20170909/catalog.xml') -ds = cat.datasets.filter_time_nearest(datetime(2017, 9, 9, 6)) -print(ds.name) -ds = ds.remote_access(service='OPENDAP') -timestamp = datetime.strptime(ds.start_date_time, '%Y%j%H%M%S') -data_var = ds.variables['Sectorized_CMI'] - -x = ds.variables['x'][:] -y = ds.variables['y'][:] -proj_var = ds.variables[data_var.grid_mapping] - -# Create a Globe specifying a spherical earth with the correct radius -globe = ccrs.Globe(ellipse='sphere', semimajor_axis=proj_var.semi_major, - semiminor_axis=proj_var.semi_minor) - -# Select the correct projection. - -if proj_var.grid_mapping_name == 'lambert_conformal_conic': - proj = ccrs.LambertConformal(central_longitude=proj_var.longitude_of_central_meridian, - central_latitude=proj_var.latitude_of_projection_origin, - standard_parallels=[proj_var.standard_parallel], - globe=globe) - -else: - proj = ccrs.Mercator(central_longitude=proj_var.longitude_of_projection_origin, - latitude_true_scale=proj_var.standard_parallel, - globe=globe) - -wv_norm, wv_cmap = registry.get_with_range('WVCIMSS_r', 195, 265) - -fig = plt.figure(figsize=(10, 10)) -ax = fig.add_subplot(1, 1, 1, projection=proj) - -im = ax.imshow(data_var[:], extent=(x.min(), x.max(), y.min(), y.max()), origin='upper', - cmap=wv_cmap, norm=wv_norm) -ax.coastlines(resolution='50m', color='black') -ax.add_feature(cfeature.STATES, linestyle=':') -ax.add_feature(cfeature.BORDERS, linewidth=2) - -# Add text (aligned to the right); save the returned object so we can manipulate it. -text_time = ax.text(0.99, 0.01, timestamp.strftime('%d %B %Y %H%MZ'), - horizontalalignment='right', transform=ax.transAxes, - color='white', fontsize='x-large', weight='bold') - -text_channel = ax.text(0.5, 0.97, 'Experimental GOES-16 Ch.{}'.format(channel), - horizontalalignment='center', transform=ax.transAxes, - color='white', fontsize='large', weight='bold') - -outline_effect = [patheffects.withStroke(linewidth=2, foreground='black')] -text_time.set_path_effects(outline_effect) -text_channel.set_path_effects(outline_effect) - -fig = add_metpy_logo(fig) diff --git a/notebooks/Satellite_Data/solutions/satellite_data.py b/notebooks/Satellite_Data/solutions/satellite_data.py deleted file mode 100644 index 26a096d7..00000000 --- a/notebooks/Satellite_Data/solutions/satellite_data.py +++ /dev/null @@ -1,4 +0,0 @@ -cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/casestudies/irma/goes16/Mesoscale-1/Channel09/20170910/catalog.xml') -ds = cat.datasets.filter_time_nearest(datetime(2017, 9, 10, 0)) -print(ds.name) -ds = ds.remote_access(service='OPENDAP') diff --git a/notebooks/Siphon/Siphon Overview.ipynb b/notebooks/Siphon/Siphon Overview.ipynb index 3421297d..f39c9282 100644 --- a/notebooks/Siphon/Siphon Overview.ipynb +++ b/notebooks/Siphon/Siphon Overview.ipynb @@ -279,12 +279,23 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/goes_cat.py" + "\n", + "
\n", + "```python\n", + "cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/'\n", + " 'casestudies/irma/goes16/catalog.xml')\n", + "meso = cat.catalog_refs['Mesoscale-1'].follow()\n", + "channel = meso.catalog_refs['Channel02'].follow()\n", + "date_cat = channel.catalog_refs['20170906'].follow()\n", + "\n", + "date = datetime(2017, 9, 6, 21)\n", + "datasets = date_cat.datasets.filter_time_range(date - timedelta(hours=1),\n", + " date + timedelta(hours=1))\n", + "print(datasets)\n", + "```" ] }, { @@ -436,9 +447,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:unidata-workshop]", + "display_name": "Python 3", "language": "python", - "name": "conda-env-unidata-workshop-py" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/notebooks/Siphon/solutions/goes_cat.py b/notebooks/Siphon/solutions/goes_cat.py deleted file mode 100644 index b48b0dd7..00000000 --- a/notebooks/Siphon/solutions/goes_cat.py +++ /dev/null @@ -1,10 +0,0 @@ -cat = TDSCatalog('http://thredds-test.unidata.ucar.edu/thredds/catalog/' - 'casestudies/irma/goes16/catalog.xml') -meso = cat.catalog_refs['Mesoscale-1'].follow() -channel = meso.catalog_refs['Channel02'].follow() -date_cat = channel.catalog_refs['20170906'].follow() - -date = datetime(2017, 9, 6, 21) -datasets = date_cat.datasets.filter_time_range(date - timedelta(hours=1), - date + timedelta(hours=1)) -print(datasets) diff --git a/notebooks/Skew_T/Upper Air and the Skew-T Log-P.ipynb b/notebooks/Skew_T/Upper Air and the Skew-T Log-P.ipynb index a4a11153..e7e24641 100644 --- a/notebooks/Skew_T/Upper Air and the Skew-T Log-P.ipynb +++ b/notebooks/Skew_T/Upper Air and the Skew-T Log-P.ipynb @@ -151,12 +151,20 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/skewt_get_data.py" + "\n", + "
\n", + "```python\n", + "df = WyomingUpperAir.request_data(datetime(2017, 9, 10, 0), 'KEY')\n", + "\n", + "p = df['pressure'].values * units(df.units['pressure'])\n", + "T = df['temperature'].values * units(df.units['temperature'])\n", + "Td = df['dewpoint'].values * units(df.units['dewpoint'])\n", + "u = df['u_wind'].values * units(df.units['u_wind'])\n", + "v = df['v_wind'].values * units(df.units['v_wind'])\n", + "```" ] }, { @@ -288,12 +296,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/skewt_dewpoint_limits.py" + "\n", + "
\n", + "```python\n", + "skew.plot(p, Td, color='tab:green')\n", + "skew.ax.set_xlim(-40, 60)\n", + "\n", + "fig\n", + "```" ] }, { @@ -361,12 +374,26 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/skewt_lfc_el.py" + "\n", + "
\n", + "```python\n", + "# Calculate the LFC and plot it if it exists\n", + "lfc_pressure, lfc_temperature = mpcalc.lfc(p, T, Td)\n", + "\n", + "if lfc_pressure:\n", + " skew.ax.axhline(lfc_pressure, color='tab:brown')\n", + " \n", + "# Calculate the EL and plot it if it exists\n", + "el_pressure, el_temperature = mpcalc.el(p, T, Td)\n", + "\n", + "if el_pressure:\n", + " skew.ax.axhline(el_pressure, color='tab:blue')\n", + " \n", + "fig\n", + "```" ] }, { @@ -464,12 +491,14 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/skewt_mucape.py" + "\n", + "
\n", + "```python\n", + "mpcalc.most_unstable_cape_cin(p, T, Td)\n", + "```" ] }, { @@ -543,12 +572,15 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/skewt_bulk_shear.py" + "\n", + "
\n", + "```python\n", + "shr_u, shr_v = mpcalc.bulk_shear(p, u, v, depth=200 * units.hPa)\n", + "print(shr_u, shr_v)\n", + "```" ] }, { @@ -604,12 +636,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/skewt_fiducial_lines.py" + "\n", + "
\n", + "```python\n", + "skew.plot_moist_adiabats()\n", + "skew.plot_mixing_lines()\n", + "\n", + "fig\n", + "```" ] }, { @@ -745,12 +782,17 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/skewt_plot_hodograph.py" + "\n", + "
\n", + "```python\n", + "fig = plt.figure(figsize=(3, 3))\n", + "h = Hodograph()\n", + "h.plot_colormapped(u[mask], v[mask], windspeed[mask]) # Plot a line colored by wind speed\n", + "h.add_grid(increment=20)\n", + "```" ] }, { @@ -778,7 +820,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.2" + "version": "3.6.4" } }, "nbformat": 4, diff --git a/notebooks/Skew_T/solutions/skewt_bulk_shear.py b/notebooks/Skew_T/solutions/skewt_bulk_shear.py deleted file mode 100644 index 2fcfac46..00000000 --- a/notebooks/Skew_T/solutions/skewt_bulk_shear.py +++ /dev/null @@ -1,2 +0,0 @@ -shr_u, shr_v = mpcalc.bulk_shear(p, u, v, depth=200 * units.hPa) -print(shr_u, shr_v) diff --git a/notebooks/Skew_T/solutions/skewt_dewpoint_limits.py b/notebooks/Skew_T/solutions/skewt_dewpoint_limits.py deleted file mode 100644 index ff053330..00000000 --- a/notebooks/Skew_T/solutions/skewt_dewpoint_limits.py +++ /dev/null @@ -1,4 +0,0 @@ -skew.plot(p, Td, color='tab:green') -skew.ax.set_xlim(-40, 60) - -fig diff --git a/notebooks/Skew_T/solutions/skewt_fiducial_lines.py b/notebooks/Skew_T/solutions/skewt_fiducial_lines.py deleted file mode 100644 index 82fd79db..00000000 --- a/notebooks/Skew_T/solutions/skewt_fiducial_lines.py +++ /dev/null @@ -1,4 +0,0 @@ -skew.plot_moist_adiabats() -skew.plot_mixing_lines() - -fig diff --git a/notebooks/Skew_T/solutions/skewt_get_data.py b/notebooks/Skew_T/solutions/skewt_get_data.py deleted file mode 100644 index 99f5d357..00000000 --- a/notebooks/Skew_T/solutions/skewt_get_data.py +++ /dev/null @@ -1,7 +0,0 @@ -df = WyomingUpperAir.request_data(datetime(2017, 9, 10, 0), 'KEY') - -p = df['pressure'].values * units(df.units['pressure']) -T = df['temperature'].values * units(df.units['temperature']) -Td = df['dewpoint'].values * units(df.units['dewpoint']) -u = df['u_wind'].values * units(df.units['u_wind']) -v = df['v_wind'].values * units(df.units['v_wind']) diff --git a/notebooks/Skew_T/solutions/skewt_lfc_el.py b/notebooks/Skew_T/solutions/skewt_lfc_el.py deleted file mode 100644 index 4464495c..00000000 --- a/notebooks/Skew_T/solutions/skewt_lfc_el.py +++ /dev/null @@ -1,13 +0,0 @@ -# Calculate the LFC and plot it if it exists -lfc_pressure, lfc_temperature = mpcalc.lfc(p, T, Td) - -if lfc_pressure: - skew.ax.axhline(lfc_pressure, color='tab:brown') - -# Calculate the EL and plot it if it exists -el_pressure, el_temperature = mpcalc.el(p, T, Td) - -if el_pressure: - skew.ax.axhline(el_pressure, color='tab:blue') - -fig diff --git a/notebooks/Skew_T/solutions/skewt_mucape.py b/notebooks/Skew_T/solutions/skewt_mucape.py deleted file mode 100644 index d20eea52..00000000 --- a/notebooks/Skew_T/solutions/skewt_mucape.py +++ /dev/null @@ -1 +0,0 @@ -mpcalc.most_unstable_cape_cin(p, T, Td) diff --git a/notebooks/Skew_T/solutions/skewt_plot_hodograph.py b/notebooks/Skew_T/solutions/skewt_plot_hodograph.py deleted file mode 100644 index a8045a35..00000000 --- a/notebooks/Skew_T/solutions/skewt_plot_hodograph.py +++ /dev/null @@ -1,4 +0,0 @@ -fig = plt.figure(figsize=(3, 3)) -h = Hodograph() -h.plot_colormapped(u[mask], v[mask], windspeed[mask]) # Plot a line colored by wind speed -h.add_grid(increment=20) diff --git a/notebooks/Surface_Data/Surface Data with Siphon and MetPy.ipynb b/notebooks/Surface_Data/Surface Data with Siphon and MetPy.ipynb index 7e10c649..90a442ff 100644 --- a/notebooks/Surface_Data/Surface Data with Siphon and MetPy.ipynb +++ b/notebooks/Surface_Data/Surface Data with Siphon and MetPy.ipynb @@ -381,12 +381,39 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/station_plot.py\n" + "\n", + "
\n", + "```python\n", + "# Use reduce_point_density\n", + "mask = reduce_point_density(xy, 75000)\n", + "\n", + "# Set up a plot with map features\n", + "fig = plt.figure(figsize=(12, 12))\n", + "ax = fig.add_subplot(1, 1, 1, projection=proj)\n", + "ax.add_feature(cfeature.STATES, edgecolor='black')\n", + "ax.coastlines(resolution='50m')\n", + "ax.gridlines()\n", + "\n", + "# Create a station plot pointing to an Axes to draw on as well as the location of points\n", + "stationplot = StationPlot(ax, longitude[mask], latitude[mask], transform=ccrs.PlateCarree(),\n", + " fontsize=12)\n", + "stationplot.plot_parameter('NW', tair[mask], color='tab:red')\n", + "stationplot.plot_barb(u[mask], v[mask])\n", + "stationplot.plot_symbol('C', cloud_cover[mask], sky_cover)\n", + "\n", + "# Plot dewpoint\n", + "stationplot.plot_parameter('SW', dewp[mask], color='tab:green')\n", + "\n", + "# Plot altimeter setting\n", + "stationplot.plot_parameter('NE', alt[mask], color='tab:blue',\n", + " formatter=lambda v: str(int(v * 10))[-3:])\n", + "\n", + "# Plot station id\n", + "stationplot.plot_text((2, 0), station_id[mask])\n", + "```" ] }, { diff --git a/notebooks/Surface_Data/solutions/station_plot.py b/notebooks/Surface_Data/solutions/station_plot.py deleted file mode 100644 index fc82a351..00000000 --- a/notebooks/Surface_Data/solutions/station_plot.py +++ /dev/null @@ -1,26 +0,0 @@ -# Use reduce_point_density -mask = reduce_point_density(xy, 75000) - -# Set up a plot with map features -fig = plt.figure(figsize=(12, 12)) -ax = fig.add_subplot(1, 1, 1, projection=proj) -ax.add_feature(cfeature.STATES, edgecolor='black') -ax.coastlines(resolution='50m') -ax.gridlines() - -# Create a station plot pointing to an Axes to draw on as well as the location of points -stationplot = StationPlot(ax, longitude[mask], latitude[mask], transform=ccrs.PlateCarree(), - fontsize=12) -stationplot.plot_parameter('NW', tair[mask], color='tab:red') -stationplot.plot_barb(u[mask], v[mask]) -stationplot.plot_symbol('C', cloud_cover[mask], sky_cover) - -# Plot dewpoint -stationplot.plot_parameter('SW', dewp[mask], color='tab:green') - -# Plot altimeter setting -stationplot.plot_parameter('NE', alt[mask], color='tab:blue', - formatter=lambda v: str(int(v * 10))[-3:]) - -# Plot station id -stationplot.plot_text((2, 0), station_id[mask]) diff --git a/notebooks/Time_Series/Basic Time Series Plotting.ipynb b/notebooks/Time_Series/Basic Time Series Plotting.ipynb index 3df4f985..743c50d2 100644 --- a/notebooks/Time_Series/Basic Time Series Plotting.ipynb +++ b/notebooks/Time_Series/Basic Time Series Plotting.ipynb @@ -197,12 +197,21 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/timeseries_parse_dates.py" + "\n", + "
\n", + "```python\n", + "df = pd.read_fwf(fname, skiprows=2, na_values='MM', names=col_names)\n", + "\n", + "df['time'] = pd.to_datetime(df[['year', 'month', 'day', 'hour', 'minute']])\n", + "\n", + "# Using inplace means the return is None and the dataframe is simply modified.\n", + "df.drop(['year', 'month', 'day', 'hour', 'minute'], axis='columns', inplace=True)\n", + "\n", + "df.head()\n", + "```" ] }, { @@ -359,14 +368,23 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { "scrolled": true }, - "outputs": [], "source": [ - "# %load solutions/timeseries_gustplot.py" + "\n", + "
\n", + "```python\n", + "ax.plot(df.time, df.wind_gust, color='tab:olive', linestyle='--',\n", + " label='Wind Gust')\n", + "\n", + "ax.xaxis.set_major_formatter(DateFormatter('%b %d'))\n", + "\n", + "ax.legend(loc='upper left')\n", + "\n", + "fig\n", + "```" ] }, { @@ -503,12 +521,38 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# %load solutions/timeseries_basicfinalplot.py" + "\n", + "
\n", + "```python\n", + "fig, ax = plt.subplots(figsize=(10, 6))\n", + "axb = ax.twinx()\n", + "\n", + "# Same as above\n", + "ax.set_xlabel('Time')\n", + "ax.set_ylabel('Wave Height')\n", + "ax.set_title('Buoy 41056 Data')\n", + "ax.grid(True)\n", + "ax.legend(loc='upper left')\n", + "\n", + "# Plotting on the first y-axis\n", + "ax.plot(df.time, df.wave_height, color='tab:blue', label='Waveheight',\n", + " linestyle='None', marker='o')\n", + "\n", + "# Plotting on the second y-axis\n", + "axb.set_ylabel('Windspeed')\n", + "axb.plot(df.time, df.wind_speed, color='tab:green', label='Windspeed')\n", + "\n", + "ax.xaxis.set_major_locator(DayLocator())\n", + "ax.xaxis.set_major_formatter(DateFormatter('%b %d'))\n", + "\n", + "# Handling of getting lines and labels from all axes for a single legend\n", + "lines, labels = ax.get_legend_handles_labels()\n", + "lines2, labels2 = axb.get_legend_handles_labels()\n", + "axb.legend(lines + lines2, labels + labels2, loc='upper left')\n", + "```" ] }, { @@ -536,7 +580,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.6.4" } }, "nbformat": 4, diff --git a/notebooks/Time_Series/solutions/timeseries_basicfinalplot.py b/notebooks/Time_Series/solutions/timeseries_basicfinalplot.py deleted file mode 100644 index 2948a8c2..00000000 --- a/notebooks/Time_Series/solutions/timeseries_basicfinalplot.py +++ /dev/null @@ -1,25 +0,0 @@ -fig, ax = plt.subplots(figsize=(10, 6)) -axb = ax.twinx() - -# Same as above -ax.set_xlabel('Time') -ax.set_ylabel('Wave Height') -ax.set_title('Buoy 41056 Data') -ax.grid(True) -ax.legend(loc='upper left') - -# Plotting on the first y-axis -ax.plot(df.time, df.wave_height, color='tab:blue', label='Waveheight', - linestyle='None', marker='o') - -# Plotting on the second y-axis -axb.set_ylabel('Windspeed') -axb.plot(df.time, df.wind_speed, color='tab:green', label='Windspeed') - -ax.xaxis.set_major_locator(DayLocator()) -ax.xaxis.set_major_formatter(DateFormatter('%b %d')) - -# Handling of getting lines and labels from all axes for a single legend -lines, labels = ax.get_legend_handles_labels() -lines2, labels2 = axb.get_legend_handles_labels() -axb.legend(lines + lines2, labels + labels2, loc='upper left') diff --git a/notebooks/Time_Series/solutions/timeseries_gustplot.py b/notebooks/Time_Series/solutions/timeseries_gustplot.py deleted file mode 100644 index 95128f79..00000000 --- a/notebooks/Time_Series/solutions/timeseries_gustplot.py +++ /dev/null @@ -1,8 +0,0 @@ -ax.plot(df.time, df.wind_gust, color='tab:olive', linestyle='--', - label='Wind Gust') - -ax.xaxis.set_major_formatter(DateFormatter('%b %d')) - -ax.legend(loc='upper left') - -fig diff --git a/notebooks/Time_Series/solutions/timeseries_parse_dates.py b/notebooks/Time_Series/solutions/timeseries_parse_dates.py deleted file mode 100644 index 12b1aafd..00000000 --- a/notebooks/Time_Series/solutions/timeseries_parse_dates.py +++ /dev/null @@ -1,8 +0,0 @@ -df = pd.read_fwf(fname, skiprows=2, na_values='MM', names=col_names) - -df['time'] = pd.to_datetime(df[['year', 'month', 'day', 'hour', 'minute']]) - -# Using inplace means the return is None and the dataframe is simply modified. -df.drop(['year', 'month', 'day', 'hour', 'minute'], axis='columns', inplace=True) - -df.head() From 3542d6db1c50bf5103d639aa46b68138d0f36ade Mon Sep 17 00:00:00 2001 From: John Leeman Date: Tue, 20 Mar 2018 11:10:43 -0600 Subject: [PATCH 2/2] Modify notebook preprocessor for embedded solutions. --- notebooks_preprocess.py | 58 ++++++++++++----------------------------- 1 file changed, 17 insertions(+), 41 deletions(-) diff --git a/notebooks_preprocess.py b/notebooks_preprocess.py index 584d5f5d..3ed859d3 100644 --- a/notebooks_preprocess.py +++ b/notebooks_preprocess.py @@ -4,55 +4,31 @@ import re from pathlib import Path - -def format_script_for_cell(path): - """Read and format a .py file to be inserted into the json for a cell.""" - header = '\n# Cell content replaced by load magic replacement.\n' - with open(str(path), encoding='utf8') as f: - solution = f.read() - if not solution: - raise RuntimeError('Solution {} has no content.'.format(path)) - return header + solution - - -def find_load_magics_in_cell(cell): - """Find the load magics in a cell and return them as a list.""" - load_magics = [] - for cell_source_line in cell['source']: - m = re.match('#\s?%load.*', cell_source_line) - if m: - load_magics.append(m.group()) - return load_magics - - def get_cell_content_as_string(cell): """Return the cells source as a single string.""" return ''.join(cell['source']) + '\n' -def find_extra_content(cell_text): - """Find and non load magic or blank lines in a solution cell.""" - for line in cell_text.split('\n'): - m = re.match('#\s?%load.*', line) - if not m and line: - raise RuntimeError('Solution cell has extra content: {}'.format(cell_text)) - - def process_cell(path, cell): - """Append the data from the load magics into the cell content.""" + """Replace the solution button with the solution code.""" modified = False - # See if there are any load magics used - load_magics = find_load_magics_in_cell(cell) - # Replace the load magics with content from their recpective files - for magic_string in load_magics: - path = Path(path) - script_path = path.parent / magic_string.split('load ')[1] - formatted_script = format_script_for_cell(script_path) - cell_str = get_cell_content_as_string(cell) - find_extra_content(cell_str) - cell['source'] = cell_str + formatted_script - modified = True + # See if there is a solution div in the cell + for cell_source_line in cell['source']: + m = re.match('