Skip to content
This repository has been archived by the owner on Jan 9, 2020. It is now read-only.

Commit

Permalink
Merge pull request #254 from jrleeman/Improve_Solution_Checks
Browse files Browse the repository at this point in the history
Improve Solution Automation
  • Loading branch information
jrleeman authored Nov 15, 2017
2 parents 3d9e9f3 + 6f1ff28 commit 93f18ec
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 85 deletions.
51 changes: 3 additions & 48 deletions notebooks/Animation/Creating Animations.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -476,52 +476,7 @@
"metadata": {},
"outputs": [],
"source": [
"# %load solutions/animation.py\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"
"# %load solutions/animation.py"
]
},
{
Expand All @@ -535,9 +490,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": {
Expand Down
25 changes: 3 additions & 22 deletions notebooks/CartoPy/CartoPy.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -396,34 +396,15 @@
"metadata": {},
"outputs": [],
"source": [
"# %load solutions/map.py\n",
"fig = plt.figure(figsize=(10, 8))\n",
"ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator())\n",
"\n",
"ax.add_feature(cfeat.COASTLINE)\n",
"ax.add_feature(cfeat.LAND, facecolor='tab:brown')\n",
"ax.add_feature(cfeat.OCEAN, facecolor='tab:cyan')\n",
"ax.add_feature(cfeat.BORDERS, linewidth=2)\n",
"ax.add_feature(state_borders, 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])"
"# %load solutions/map.py"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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": {
Expand Down
23 changes: 9 additions & 14 deletions notebooks/Satellite_Data/Working with Satellite Data.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"metadata": {},
"outputs": [],
"source": [
"list(cat.datasets)[-5:]"
"cat.datasets[-5:]"
]
},
{
Expand All @@ -115,7 +115,7 @@
"<div class=\"alert alert-success\">\n",
" <b>EXERCISE</b>:\n",
" <ul>\n",
" <li>Using the link to the Hurricane Irma archive above, get data from September 10, 2017 at 15Z for the mid-level water vapor channel (9) in the Mesoscale-1 sector. You could search through the datasets list manually, but instead try the `cat.datasets.filter_time_nearest` functinoality!</li>\n",
" <li>Using the link to the Hurricane Irma archive above, get data from September 10, 2017 at 15Z for the mid-level water vapor channel (9) in the Mesoscale-1 sector. You could search through the datasets list manually, but instead try the `cat.datasets.filter_time_nearest` functionality!</li>\n",
" </ul>\n",
"</div>"
]
Expand All @@ -135,11 +135,7 @@
"metadata": {},
"outputs": [],
"source": [
"# %load solutions/satellite_data.py\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')"
"# %load solutions/satellite_data.py"
]
},
{
Expand Down Expand Up @@ -175,7 +171,7 @@
"source": [
"Our goal is to plot the imagery, so we'll be using the `Sectorized_CMI` variable from the `.variables` dictionary.\n",
"Rather than just giving back the raw array of data, this gives back a `Variable` object; from here not only\n",
"can we get the raw data values, but there is useful metadata as well. We can see just what additional information\n",
"can we get the raw data values, but there are useful metadata as well. We can see just what additional information\n",
"is present by printing out the `Variable` object:"
]
},
Expand Down Expand Up @@ -342,7 +338,7 @@
"metadata": {},
"source": [
"Now that we know how to properly reference the imagery data, we can plot\n",
"the data. CartoPy's projections are designed to interface with matplotlib, so they can just be passed as the `projection` keyword argument when creating an `Axes` using the `add_subplot` method. Since the x and y coordinates, as well as the image data, are referenced in the lambert conformal projection, we can pass all of them directly to plotting methods (such as `imshow`) with no additional information. The `extent` keyword argument to `imshow` is used to specify the bounds of the image data being plotted. It is **especially important** to specify that the `origin` is at the the upper left of the image (standard practice in imagery). If your forget this, your image will be flipped. Try it!"
"the data. CartoPy's projections are designed to interface with matplotlib, so they can just be passed as the `projection` keyword argument when creating an `Axes` using the `add_subplot` method. Since the x and y coordinates, as well as the image data, are referenced in the lambert conformal projection, we can pass all of them directly to plotting methods (such as `imshow`) with no additional information. The `extent` keyword argument to `imshow` is used to specify the bounds of the image data being plotted. It is **especially important** to specify that the `origin` is at the upper left of the image (standard practice in imagery). If your forget this, your image will be flipped. Try it!"
]
},
{
Expand Down Expand Up @@ -370,7 +366,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a nice start, but it would be nice to have better geographic references for the image. For example, where are the states? Cartopy's `feature` module has support for adding geographic features to plots ,with many features are built in. The `BORDERS` built-in feature contains country borders. There is also support for creating \"custom\" features from the [Natural Earth](http://www.naturalearthdata.com/) set of free vector and raster map data (CartoPy will automatically download the necessary data and cache it locally). Here we create a feature for states/provinces."
"This is a nice start, but it would be nice to have better geographic references for the image. For example, where are the states? Cartopy's `feature` module has support for adding geographic features to plots, with many features are built in. The `BORDERS` built-in feature contains country borders. There is also support for creating \"custom\" features from the [Natural Earth](http://www.naturalearthdata.com/) set of free vector and raster map data (CartoPy will automatically download the necessary data and cache it locally). Here we create a feature for states/provinces."
]
},
{
Expand Down Expand Up @@ -552,8 +548,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Well, that's a good idea, but the text is invisible in some places! White text and black text have issues, but we can outline the text using matplotlib's [path effects](http://matplotlib.org/users/patheffects_guide.html). More details on path effects can be found in the [documentation](http://matplotlib.org/users/patheffects_guide.html) if you want to know more.\n",
"\n"
"Well, that's a good idea, but the text is invisible in some places! White text and black text have issues, but we can outline the text using matplotlib's [path effects](http://matplotlib.org/users/patheffects_guide.html). More details on path effects can be found in the [documentation](http://matplotlib.org/users/patheffects_guide.html) if you want to know more."
]
},
{
Expand Down Expand Up @@ -649,7 +644,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"First we'll import the animation support from matplotlib. We also tell it that we want it to render the animations to HTML using the HTML5 video tag:"
"First, we'll import the animation support from matplotlib. We also tell it that we want it to render the animations to HTML using the HTML5 video tag:"
]
},
{
Expand Down Expand Up @@ -690,7 +685,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Then we loop over a bunch of the datasets. For each one we pull out the data and plot both the timestamp and the image. The `ArtistAnimation` class takes the `Figure` instance and a list as required arguments. The contents of this list is a collection of matplotlib artists for each frame of the animation. In the loop below, we populate this list with the `Text` instance created when adding the timestamp as well as the image that results from plotting the data."
"Then we loop over a bunch of the datasets. For each one we pull out the data and plot both the timestamp and the image. The `ArtistAnimation` class takes the `Figure` instance and a list as required arguments. The contents of this list are a collection of matplotlib artists for each frame of the animation. In the loop below, we populate this list with the `Text` instance created when adding the timestamp as well as the image that results from plotting the data."
]
},
{
Expand Down
2 changes: 2 additions & 0 deletions notebooks/Skew_T/solutions/skewt_bulk_shear.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
shr_u, shr_v = mpcalc.bulk_shear(p, u, v, depth=200 * units.hPa)
print(shr_u, shr_v)
14 changes: 13 additions & 1 deletion notebooks_preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ 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:
return header + f.read()
solution = f.read()
if not solution:
raise RuntimeError('Solution {} has no content.'.format(path))
return header + solution


def find_load_magics_in_cell(cell):
Expand All @@ -27,6 +30,14 @@ def get_cell_content_as_string(cell):
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."""
modified = False
Expand All @@ -39,6 +50,7 @@ def process_cell(path, cell):
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
return modified
Expand Down

0 comments on commit 93f18ec

Please sign in to comment.