This notebook is based on the user story described in Issue #7 where the main objective is as follows:

Co-located cubes shall be rendered as sets, with shared sliders across non-plot dimensions ...

The material presented here is inspired by the code example given in the issue and this example visualization:


In [ ]:
from IPython.display import Image as IPImage
IPImage(url="http://www.wetterzentrale.de/wz/pics/Recm1201.gif", width=500)

In [ ]:
import iris
import numpy as np
import holoviews as hv
import holocube as hc
from cartopy import crs
from cartopy import feature as cf
hv.notebook_extension()

In [ ]:
iris.FUTURE.strict_grib_load = True
%output widgets='live' max_frames=1000   # Plot data on request
%opts Image {+framewise} Contours {+framewise}

In this notebook we will work with the following 900MB file:


In [ ]:
ls -lh files/*.pp

In [ ]:
cubelist = iris.load('files/prodm_op_ukv_20160207_21_022.pp')
print "%d cubes have been loaded" % len(cubelist)

Here is the summary of the first cube containing data:


In [ ]:
print cubelist[1].summary()

First guess the bounds for all cubes:


In [ ]:
for c in cubelist:
    c.coord('grid_longitude').guess_bounds()
    c.coord('grid_latitude').guess_bounds()

In a similar way, we can now load up the other cubes that contain data to display:


In [ ]:
cubes = {cb.vdims[0].name:cb for cb in [hc.HoloCube(c) for c in cubelist]} # Load cubes into dictionary
cubes = {k:v for k,v in cubes.items() if k!='unknown'}  # Filter as desired

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:


In [ ]:
print "Available model variables:\n   %s" % ',\n   '.join(cubes.keys())

A Simple example

Here is a very simple example of viewing the specific_humidity cube as a HoloMap of Image elements:


In [ ]:
cubes['specific_humidity'].to.image(['grid_longitude', 'grid_latitude'])

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:


In [ ]:
cubes['specific_humidity'].dimension_values('time')

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:


In [ ]:
(  cubes['specific_humidity'].to.image(['grid_longitude', 'grid_latitude']) 
 + cubes['air_pressure'].to.image(['grid_longitude', 'grid_latitude']))

Here is an example of four types of variable plotted as a layout without using the + operator:


In [ ]:
%%opts Layout [fig_inches=(8, 6)]
keys = ['specific_humidity', 'air_temperature', 'surface_air_pressure', 'cloud_volume_fraction_in_atmosphere_layer']
hv.Layout([cubes[k].to.image(['grid_longitude', 'grid_latitude']).relabel(group=k) for k in keys]).cols(2).display('all')

Overlaying data and normalization

Lets view the specific humidity data together with the UK coastline:


In [ ]:
%output size=400

Let's use a fairly high resolution map:


In [ ]:
cf.COASTLINE.scale='50m'

In [ ]:
%%opts Image [projection=crs.Geostationary()] (cmap='Greens')
cubes['specific_humidity'].to.image(['grid_longitude', 'grid_latitude']) * hc.GeoFeature(cf.COASTLINE)

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:


In [ ]:
%%opts Image [projection=crs.Geostationary()] (cmap='Greens')
# Declare a humidity dimension with a range from 0 to 0.01
humidity_dim = hv.Dimension('specific_humidity', range=(0,0.01))
# Use it to declare the value dimension of a HoloCube
(hc.HoloCube(cubes['specific_humidity'], vdims=[humidity_dim]).to.image(['grid_longitude', 'grid_latitude'])
 * hc.GeoFeature(cf.COASTLINE))

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.

Lastly, here is a demo of a conversion from cloud volume fraction to Contours:


In [ ]:
%%opts Contours [levels=10]
(hc.GeoFeature(cf.COASTLINE) 
 * cubes['cloud_volume_fraction_in_atmosphere_layer'].to.contours(['grid_longitude', 'grid_latitude']))