Gridded Datasets II#

import numpy as np
import xarray as xr
import holoviews as hv
import geoviews as gv
import geoviews.feature as gf

from geoviews import opts
from cartopy import crs as ccrs

gv.extension('matplotlib', 'bokeh')

gv.output(size=200)

The main strength of HoloViews and its extensions (like GeoViews) is the ability to quickly explore complex datasets by declaring lower-dimensional views into a higher-dimensional space. In HoloViews we refer to the interface that allows you to do this as the conversion API. To begin with we will load a multi-dimensional dataset of surface temperatures for different “realizations” (modelling parameters) using XArray:

xr_ensembles = xr.open_dataset('../data/ensembles.nc')
xr_ensembles
<xarray.Dataset> Size: 9MB
Dimensions:                  (realization: 13, time: 6, latitude: 145,
                              longitude: 192, bnds: 2)
Coordinates:
  * realization              (realization) int32 52B 0 1 2 3 4 ... 9 10 11 12 13
  * time                     (time) datetime64[ns] 48B 2011-08-16T12:00:00 .....
  * latitude                 (latitude) float32 580B -90.0 -88.75 ... 88.75 90.0
  * longitude                (longitude) float32 768B 0.0 1.875 ... 356.2 358.1
    forecast_reference_time  (realization, time) datetime64[ns] 624B ...
Dimensions without coordinates: bnds
Data variables:
    surface_temperature      (realization, time, latitude, longitude) float32 9MB ...
    latitude_longitude       int32 4B ...
    time_bnds                (time, bnds) datetime64[ns] 96B ...
Attributes:
    source:       Data from Met Office Unified Model
    um_version:   7.6
    Conventions:  CF-1.5

As we saw in the Gridded Datasets I Tutorial we can easily wrap this xarray data structure as a HoloViews Dataset:

dataset = gv.Dataset(xr_ensembles, vdims='surface_temperature')
dataset
:Dataset   [realization,time,latitude,longitude]   (surface_temperature)

From the repr we can immediately see the list of key dimensions (time, realization, longitude and latitude) and the value dimension of the cube (surface_temperature). However, unlike most other HoloViews Elements, the Dataset Element does not display itself visually. This is because it can be n-dimensional and therefore does not have any specific straightforward visual representation on a 2D display. To view the cube, we first have to transform it into individually visualizable chunks. Before doing so, we will want to supply a custom value formatter for the time dimension so that it is readable by humans:

hv.Dimension.type_formatters[np.datetime64] = '%Y-%m-%d'

Conversions#

A HoloViews Dataset is a wrapper around a complex multi-dimensional datastructure which allows the user to convert their data into individually visualizable views, each usually of lower dimensionality. This is done by grouping the data by some dimension and then casting it to a specific Element type, which visualizes itself.

The dataset.to interface makes this especially easy. To use it, you supply the Element type that you want to view the data as and the key dimensions of that view and it will figure out the rest. Depending on the type of Element, you can specify one or more dimensions to be displayed. GeoViews provides a set of GeoElements that allow you to display geographic data on a cartographic projection, but you can use any Elements from HoloViews for non-geographic plots.

Recall that the cube we are working with has 4 coordinate dimensions (or key dimensions as they are known in HoloViews) – time, realization, longitude, and latitude. For our purposes, a geographic plot is defined as a plot that has longitude along the x axis and latitude along the y axis. To declare a two-dimensional geographic plot, we therefore simply request a gv.Image plot with longitude and latitude as key dimensions. There is one value dimension (vdim) available, surface_temperature, and any remaining key dimensions (time and realization in this case) are assigned to a HoloMap data structure by default. The resulting HoloMap gives you widgets automatically to allow you to explore the data across the two “remaining” key dimensions (those not mapped onto axes of the image):

geo_dims = ['longitude', 'latitude']
(dataset.to(gv.Image, geo_dims) * gf.coastline)[::5, ::5]