forked from CubeBrowser/cube-explorer
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Colocated_cube_pair example notebook
- Loading branch information
Showing
1 changed file
with
370 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,370 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"This notebook is based on the user story described in [Issue #7](https://github.com/CubeBrowser/cube-explorer/issues/7) where the main objective is as follows:\n", | ||
"\n", | ||
"> Co-located cubes shall be rendered as sets, with shared sliders across non-plot dimensions ...\n", | ||
"\n", | ||
"The material presented here is inspired by the code example given in the issue and this example visualization:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from IPython.display import Image as IPImage\n", | ||
"IPImage(url=\"http://www.wetterzentrale.de/wz/pics/Recm1201.gif\", width=500)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"import iris\n", | ||
"import numpy as np\n", | ||
"import holoviews as hv\n", | ||
"import holocube as hc\n", | ||
"from cartopy import crs\n", | ||
"from cartopy import feature as cf\n", | ||
"hv.notebook_extension()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"iris.FUTURE.strict_grib_load = True\n", | ||
"%output widgets='live' max_frames=1000 # Plot data on request\n", | ||
"%opts Image {+framewise} Contours {+framewise} " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"In this notebook we will work with the following 900MB file:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"ls -lh files/*.pp" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"cubelist = iris.load('files/prodm_op_ukv_20160207_21_022.pp')\n", | ||
"print \"%d cubes have been loaded\" % len(cubelist)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Here is the summary of the first cube containing data:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"print cubelist[1].summary()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"First guess the bounds for all cubes:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"for c in cubelist:\n", | ||
" c.coord('grid_longitude').guess_bounds()\n", | ||
" c.coord('grid_latitude').guess_bounds()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"In a similar way, we can now load up the other cubes that contain data to display:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"cubes = {cb.vdims[0].name:cb for cb in [hc.HoloCube(c) for c in cubelist]} # Load cubes into dictionary\n", | ||
"cubes = {k:v for k,v in cubes.items() if k!='unknown'} # Filter as desired" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Note that this uses simple dictionary but you could use a HoloViews ``Layout`` which would offer tab-completion access. We can can view the dictionary keys as follows:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"print \"Available model variables:\\n %s\" % ',\\n '.join(cubes.keys())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# A Simple example" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Here is a very simple example of viewing the ``specific_humidity`` cube as a ``HoloMap`` of ``Image`` elements:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"cubes['specific_humidity'].to.image(['grid_longitude', 'grid_latitude'])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Note that the time slider does work but there are only two time values in the cube (try dragging the slider through the full range). Here is how you can view the values of time in the cube via the HoloViews API:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"cubes['specific_humidity'].dimension_values('time')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"We can easily view the data in two cubes side-by-side. Here the ``specific_humidity`` cube is visualized next to the ``air_pressure`` cube:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"( cubes['specific_humidity'].to.image(['grid_longitude', 'grid_latitude']) \n", | ||
" + cubes['air_pressure'].to.image(['grid_longitude', 'grid_latitude']))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Here is an example of four types of variable plotted as a layout without using the ``+`` operator:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%opts Layout [fig_inches=(8, 6)]\n", | ||
"keys = ['specific_humidity', 'air_temperature', 'surface_air_pressure', 'cloud_volume_fraction_in_atmosphere_layer']\n", | ||
"hv.Layout([cubes[k].to.image(['grid_longitude', 'grid_latitude']).relabel(group=k) for k in keys]).cols(2).display('all')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Overlaying data and normalization" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Lets view the specific humidity data together with the UK coastline:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%output size=400" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Let's use a fairly high resolution map:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"cf.COASTLINE.scale='50m'" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%opts Image [projection=crs.Geostationary()] (cmap='Greens')\n", | ||
"cubes['specific_humidity'].to.image(['grid_longitude', 'grid_latitude']) * hc.GeoFeature(cf.COASTLINE)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Notice that every frame uses the full dynamic range of the Greens color map. This is because normalization is set to ``+framewise`` at the top of the notebook which means every frame is normalized independently. We can specify a fixed normalization range as follows:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%opts Image [projection=crs.Geostationary()] (cmap='Greens')\n", | ||
"# Declare a humidity dimension with a range from 0 to 0.01\n", | ||
"humidity_dim = hv.Dimension('specific_humidity', range=(0,0.01))\n", | ||
"# Use it to declare the value dimension of a HoloCube\n", | ||
"(hc.HoloCube(cubes['specific_humidity'], vdims=[humidity_dim]).to.image(['grid_longitude', 'grid_latitude'])\n", | ||
" * hc.GeoFeature(cf.COASTLINE))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"With the fixed normalization we can see that as the ``model_level_number`` increases, the specific humidity also increases. Using a fixed normalization helps us view specific humidity changes over time but can mean we lose the ability to see the variation in humidity at a specific time if only a small fraction of the available range is used." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Lastly, here is a demo of a conversion from cloud volume fraction to ``Contours``:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"%%opts Contours [levels=10]\n", | ||
"(hc.GeoFeature(cf.COASTLINE) \n", | ||
" * cubes['cloud_volume_fraction_in_atmosphere_layer'].to.contours(['grid_longitude', 'grid_latitude']))" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 2", | ||
"language": "python", | ||
"name": "python2" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 2 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython2", | ||
"version": "2.7.11" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 0 | ||
} |