Iris 0.9

Table Of Contents

Previous topic

3. Navigating a cube

Next topic

5. Introduction to plotting in Iris

This Page

4. Reducing a Cube

The Loading Iris cubes section of the user guide showed how to load data into multidimensional Iris cubes. However it is often necessary to reduce the dimensionality of a cube down to something more appropriate.

Iris provides several ways of reducing both the amount of data and/or the number of dimensions in your cube depending on the circumstance. In all cases the subset of a valid cube is itself a valid cube.

4.1. Cube extraction

A subset of a cube can be “extracted” from a multi-dimensional cube in order to reduce its dimensionality:

filename = iris.sample_data_path('hybrid_height.pp')
cube = iris.load_strict(filename)
print cube
equator_slice = cube.extract(iris.Constraint(grid_latitude=0))
print equator_slice

In this example we start with a 3 dimensional cube, with dimensions of height, latitude and longitude, and extract every point where the latitude is 0, resulting in a 2d cube with axes of height and longitude.

Warning

Caution is required when using equality constraints with floating point coordinates such as latitude. Printing the points of a coordinate does not necessarily show the full precision of the underlying number and it is very easy return no matches to a constraint when one was expected. This can be avoided by using a function as the argument to the constraint:

def near_zero(cell):
   """Returns true if the cell is between -0.1 and 0.1."""
   return -0.1 < cell < 0.1

equator_constraint = iris.Constraint(grid_latitude=near_zero)

Often you will see this construct in shorthand using a lambda function definition:

equator_constraint = iris.Constraint(grid_latitude=lambda cell: -0.1 < cell < 0.1)

The extract method could be applied again to the equator_slice cube to get a further subset.

For example to get a model_level_number of 10 at the equator the following line extends the previous example:

equator_model_level_10_slice = equator_slice.extract(iris.Constraint(model_level_number=10))
print equator_model_level_10_slice

The two steps required to get model_level_number of 10 at the equator can be simplified into a single constraint:

filename = iris.sample_data_path('PP', 'globClim1', 'theta.pp')
cube = iris.load_strict(filename)
equator_model_level_10_slice = cube.extract(iris.Constraint(grid_latitude=0, model_level_number=10))
print equator_model_level_10_slice

As we saw in Loading Iris cubes the result of iris.load() is a CubeList. The extract method also exists on a CubeList and behaves in exactly the same way as loading with constraints:

air_temp_and_fp_6 = iris.Constraint('air_potential_temperature', forecast_period=6)
level_10 = iris.Constraint(model_level_number=10)
filename = iris.sample_data_path('uk_hires.pp')
cubes = iris.load(filename).extract(air_temp_and_fp_6 & level_10)
print cubes

4.2. Cube iteration

A useful way of dealing with a Cube in its entirety is by iterating over its layers or slices. For example, to deal with a 3 dimensional cube (z,y,x) you could iterate over all 2 dimensional slices in y and x which make up the full 3d cube.:

import iris
filename = iris.sample_data_path('hybrid_height.nc')
cube = iris.load_strict(filename)
print cube
for yx_slice in cube.slices(['grid_latitude', 'grid_longitude']):
   print repr(yx_slice)

As the original cube had the shape (15, 100, 100) there were 15 latitude longitude slices and hence the line print repr(yx_slice) was run 15 times.

Note

The order of latitude and longitude in the list is important; had they been swapped the resultant cube slices would have been transposed.

For further information see Cube.slices.

This method can handle n-dimensional slices by providing more or fewer coordinate names in the list to slices:

import iris
filename = iris.sample_data_path('hybrid_height.nc')
cube = iris.load_strict(filename)
print cube
for i, x_slice in enumerate(cube.slices(['grid_longitude'])):
   print i, repr(x_slice)

The Python function enumerate() is used in this example to provide an incrementing variable i which is printed with the summary of each cube slice. Note that there were 1500 1d longitude cubes as a result of slicing the 3 dimensional cube (15, 100, 100) by longitude (i starts at 0 and 1500 = 15 * 100).

Hint

It is often useful to get a single 2d slice from a multidimensional cube in order to develop a 2d plot function, for example. This can be achieved by using the next() method on the result of slices:

first_slice = cube.slices(['grid_latitude', 'grid_longitude']).next()

Once the your code can handle a 2d slice, it is then an easy step to loop over all 2d slices within the bigger cube using the slices method.

4.3. Cube indexing

In the same way that you would expect a numeric multidimensional array to be indexed to take a subset of your original array, you can index a Cube for the same purpose.

Here are some examples of array indexing in numpy:

import numpy
# create an array of 12 consecutive integers starting from 0
a = numpy.arange(12)
print a

print a[0]       # first element of the array

print a[-1]       # last element of the array

print a[0:4]       # first four elements of the array (this is the same as a[:4])

print a[-4:]       # last four elements of the array

print a[::-1]       # gives all of the array, but backwards

# Make a 2d array by reshaping a
b = a.reshape(3, 4)
print b

print b[0, 0]       # first element of the first and second dimensions

print b[0]       # first element of the first dimension (+ every other dimension)

# get the second element of the first dimension and all of the second dimension
# in reverse, by steps of two.
print b[1, ::-2]

Similarly, Iris cubes have indexing capability:

import iris
filename = iris.sample_data_path('hybrid_height.nc')
cube = iris.load_strict(filename)

print cube

# get the first element of the first dimension (+ every other dimension)
print cube[0]

# get the last element of the first dimension (+ every other dimension)
print cube[-1]

# get the first 4 elements of the first dimension (+ every other dimension)
print cube[0:4]

# Get the first element of the first and third dimension (+ every other dimension)
print cube[0, :, 0]

# Get the second element of the first dimension and all of the second dimension
# in reverse, by steps of two.
print cube[1, ::-2]