In [ ]:
%matplotlib inline

Iris introduction course

4. Joining Cubes Together

Learning outcome: by the end of this section, you will be able to apply Iris functionality to combine multiple Iris cubes into a new larger cube.

Duration: 30 minutes

Overview:
4.1 Merge
4.2 Concatenate
4.3 Exercise
4.4 Summary of the Section

Setup


In [ ]:
import iris
import numpy as np

4.1 Merge

When Iris loads data it tries to reduce the number of cubes returned by collecting together multiple fields with shared metadata into a single multidimensional cube. In Iris, this is known as merging.

In order to merge two cubes, they must be identical in everything but a scalar dimension, which goes on to become a new data dimension.

The diagram below shows how three 2D cubes, which have the same x and y coordinates but different z coordinates, are merged together to create a single 3D cube.

The iris.load_raw function can be used as a diagnostic tool to load the individual "fields" that Iris identifies in a given set of filenames before any merge takes place.

Let's compare the behaviour of iris.load_raw and the behaviour of the general purpose loading function, iris.load

First, we load in a file using iris.load:


In [ ]:
fname = iris.sample_data_path('GloSea4', 'ensemble_008.pp')
cubes = iris.load(fname)

print(cubes)

As you can see iris.load returns a CubeList containing a single 3D cube.

Now let's try loading in the file using iris.load_raw:


In [ ]:
fname = iris.sample_data_path('GloSea4', 'ensemble_008.pp')
raw_cubes = iris.load_raw(fname)

print(raw_cubes)

This time, iris has returned six 2D cubes.

PP files usually contain multiple 2D fields. iris.load_raw has returned a 2D cube for each of these fields, whereas iris.load has merged the cubes together then returned the resulting 3D cube.

When we look in detail at the raw 2D cubes, we find that they are identical in every coordinate except for the scalar forecast_period and time coordinates:


In [ ]:
print(raw_cubes[0])
print('--' * 40)
print(raw_cubes[1])

To merge a CubeList, we can use the merge or merge_cube methods.

The merge method will try to merge together the cubes in the CubeList in order to return a CubeList of as few cubes as possible.

The merge_cube method will do the same as merge but will return a single Cube. If the initial CubeList cannot be merged into a single Cube, merge_cube will raise an error, giving a helpful message explaining why the cubes cannot be merged.

Let's merge the raw 2D cubes we previously loaded in:


In [ ]:
merged_cubelist = raw_cubes.merge()
print(merged_cubelist)

merge has returned a cubelist of a single 3D cube.


In [ ]:
merged_cube = merged_cubelist[0]
print(merged_cube)
Exercise:

Try merging raw_cubes using the merge_cube method.


In [ ]:
#
# edit space for user code ...
#

When we look in more detail at our merged cube, we can see that the time coordinate has become a new dimension, as well as gaining another forecast_period auxiliary coordinate:


In [ ]:
print(merged_cube.coord('time'))
print(merged_cube.coord('forecast_period'))

Identifying Merge Problems

In order to avoid the Iris merge functionality making inappropriate assumptions about the data, merge is strict with regards to the uniformity of the incoming cubes.

For example, if we load the fields from two ensemble members from the GloSea4 model sample data, we see we have 12 fields before any merge takes place:


In [ ]:
fname = iris.sample_data_path('GloSea4', 'ensemble_00[34].pp')
cubes = iris.load_raw(fname, 'surface_temperature')
print(len(cubes))

If we try to merge these 12 cubes we get 2 cubes rather than one:


In [ ]:
incomplete_cubes = cubes.merge()
print(incomplete_cubes)

When we look in more detail at these two cubes, what is different between the two? (Hint: One value changes, another is completely missing)


In [ ]:
print(incomplete_cubes[0])
print('--' * 40)
print(incomplete_cubes[1])

As mentioned earlier, if merge_cube cannot merge the given CubeList to return a single Cube, it will raise a helpful error message identifying the cause of the failiure.

Exercise:

Try merging the loaded cubes using merge_cube rather than merge.


In [ ]:
#
# edit space for user code ...
#

By inspecting the cubes themselves or using the error message raised when using merge_cube we can see that some cubes are missing the realization coordinate.

By adding the missing coordinate, we can trigger a merge of the 12 cubes into a single cube, as expected:


In [ ]:
for cube in cubes:
    if not cube.coords('realization'):
        cube.add_aux_coord(iris.coords.DimCoord(np.int32(3),
                                                'realization'))

merged_cube = cubes.merge_cube()
print(merged_cube)

4.2 Concatenate

We have seen that merge combines a list of cubes with a common scalar coordinate to produce a single cube with a new dimension created from these scalar values.

But what happens if you try to combine cubes along a common dimension.

Let's create a CubeList with two cubes that have been indexed along the time dimension of the original cube.


In [ ]:
fname = iris.sample_data_path('A1B_north_america.nc')
cube = iris.load_cube(fname)

cube_1 = cube[:10]
cube_2 = cube[10:20]
cubes = iris.cube.CubeList([cube_1, cube_2])
print(cubes)

These cubes should be able to be joined together; after all, they have both come from the same original cube!

However, merge returns two cubes, suggesting that these two cubes cannot be merged:


In [ ]:
print(cubes.merge())

Merge cannot be used to combine common non-scalar coordinates. Instead we must use concatenate.

Concatenate joins together ("concatenates") common non-scalar coordinates to produce a single cube with the common dimension extended.

In the below diagram, we see how three 3D cubes are concatenated together to produce a 3D cube with an extended t dimension.

To concatenate a CubeList, we can use the concatenate or concatenate_cube methods.

Similar to merging, concatenate will return a CubeList of as few cubes as possible, whereas concatenate_cube will attempt to return a cube, raising an error with a helpful message where this is not possible.

If we apply concatenate to our cubelist, we will see that it returns a CubeList with a single Cube:


In [ ]:
print(cubes.concatenate())
Exercise:

Try concatenating cubes using the concatenate_cube method.


In [ ]:
#
# edit space for user code ...
#

4.3 Section Review Exercise

The following exercise is designed to give you experience of solving issues that prevent a merge or concatenate from taking place.

Part 1

Identify and resolve the issue preventing the air_potential_temperature cubes from the resources/merge_exercise.1.*.nc files from being joined together into a single cube.

a) Use iris.load_raw to load in the air_potential_temperature cubes from the files 'resources/merge_exercise.1.*.nc'. Store the cubes in a variable called raw_cubes.

Hint: Constraints can be given to the load_raw function as you would with the other load functions.


In [ ]:
# EDIT for user code ...

In [ ]:
# SAMPLE SOLUTION :  Un-comment and execute the following to see a possible solution ...
# %load solutions/iris_exercise_4.3.1a

b) Try merging the loaded cubes into a single cube. Why does this raise an error?


In [ ]:
# user code ...

In [ ]:
# SAMPLE SOLUTION
# %load solutions/iris_exercise_4.3.1b

c) Fix the cubes such that they can be merged into a single cube.

Hint: You can use del to remove an item from a dictionary.


In [ ]:
# user code ...

In [ ]:
# SAMPLE SOLUTION
# %load solutions/iris_exercise_4.3.1c

Part 2

Identify and resolve the issue preventing the air_potential_temperature cubes from the resources/merge_exercise.5.*.nc files from being joined together into a single cube.

a) Use iris.load_raw to load in the air_potential_temperature cubes from the files 'resources/merge_exercise.5.*.nc'. Store the cubes in a variable called raw_cubes.


In [ ]:
# user code ...

In [ ]:
# SAMPLE SOLUTION
# %load solutions/iris_exercise_4.3.2a

b) Join the cubes together into a single cube. Should these cubes be merged or concatenated?


In [ ]:
# user code ...

In [ ]:
# SAMPLE SOLUTION
# %load solutions/iris_exercise_4.3.2b

4.4 Section Summary: Joining Cubes Together

In this section we learnt:

  • Merging and Concatenating can be used to join cubes into a larger combined dataset
  • Merging combines cubes along a dimension to produce a cube with an extra data dimension
  • Concatenating produces a cube with the same dimensionality as the input cubes