05. Working with Gridded Datasets

Many datasets in science and engineering consist of n-dimensional data. Gridded datasets usually represent observations of some continuous variable across multiple dimensions---a monochrome image representing luminance values across a 2D surface, volumetric 3D data, an RGB image sequence over time, or any other multi-dimensional parameter space. This type of data is particularly common in research areas that make use of spatial imaging or modeling, such as climatology, biology, and astronomy, but can also be used to represent any arbitrary data that varies over multiple dimensions.

xarray is a convenient way of working with and representing labelled n-dimensional arrays, like pandas for labelled n-D arrays:


In [ ]:
import numpy as np
import pandas as pd
import holoviews as hv
hv.extension('bokeh', 'matplotlib')

Load the data


In [ ]:
import xarray as xr
mri_xr = xr.open_dataset('../data/mri.nc')
mri_xr

The data here represents volumetric data from an MRI scan, with three coordinate dimensions 'x', 'y' and 'z'. In this simple example these coordinates are integers, but they are not required to be. Instead of volumetric data, we could imagine the data could be 2D spatial data that evolves over time, as is common in climatology and many other fields.

Declaring the dataset

In a gridded dataset the dimensions are typically alreay declared unambiguously, with coordinates (i.e. key dimensions) and data variables (i.e. value dimensions) that HoloViews can determine automatically:


In [ ]:
mri = hv.Dataset(mri_xr)
mri

Displaying the data

Just as we saw in the previous tutorial, we can group the data by one or more dimensions. Since we are dealing with volumetric data but have only a 2D display device, we can take slices along each axis. Here we will slice along the sagittal plane corresponding to the z-dimension:


In [ ]:
mri.to(hv.Image, groupby='z', dynamic=True)

In [ ]:
# Exercise: Display transverse or frontal sections of the data by declaring the kdims in the .to method

Slice and dice across n-dimensions

We can use .to to slice the cube along all three axes separately:


In [ ]:
%%opts Image {+axiswise} [xaxis=None yaxis=None width=225 height=225]
(mri.to(hv.Image, ['z', 'y'], dynamic=True) +
 mri.to(hv.Image, ['z', 'x'], dynamic=True) +
 mri.to(hv.Image, ['x', 'y'], dynamic=True)).redim.range(MR=(0, 255))

Aggregation

We can also easily compute aggregates across one or more dimensions. Previously we used the aggregate method for this purpose, but when working with gridded datasets it often makes more sense to think of aggregation as a reduce operation. We can for example reduce the z dimension using np.mean and display the resulting averaged 2D array as an Image:


In [ ]:
hv.Image(mri.reduce(z=np.mean))

In [ ]:
# Exercise: Recreate the plot above using the aggregate method
# Hint: The aggregate and reduce methods are inverses of each other
# Try typing "hv.Image(mri.aggregate(" to see the signature of `aggregate`.

As you can see, it is straightforward to work with the additional dimensions of data available in gridded datasets, as explained in more detail in the user guide.

Onwards

The previous sections focused on displaying plots that provide certain standard types of interactivity, whether widget-based (to select values along a dimension) or within each plot (for panning, zooming, etc.). A wide range of additional types of interactivity can also be defined by the user for working with specific types of data, as outlined in the next section.