Loading Unified Model output

For convenience, aeolus provides a way of keeping loaded and processed data within one object along with extra metadata. The object is called Run (as in “simulation run”). The code below provides an example of basic usage of Run.

[1]:
from pathlib import Path

import iris

from aeolus.core import Run

Note that you can use either a single filename or a list of filenames, each of which is either a str or (recommended) pathlib.Path object.

[2]:
sample_file = Path.cwd() / "sample_data" / "sample_t1e_2d_mean.pp"

While instantiating Run, it is possible to add a short name, a long description of the experiment; and to specify a planet configuration with relevant constants (see “Physical constants” example for more info).

[3]:
my_run = Run(
    files=sample_file,
    name="t1e_example",
    description="This is some sample data from a UM simulation of tidally-locked Trappist-1e planet.",
    planet="trap1e"  # this reads constants from a JSON file
)
[4]:
my_run
[4]:
<aeolus.core.Run at 0x7f3c39042400>

Constants that have been used in the model:

[5]:
my_run.const
[5]:
Trap1eConstants(earth_day [s], stefan_boltzmann [W m-2 K-4], molar_gas_constant [J K-1 mol-1], water_heat_vaporization [m2 s-2], water_molecular_weight [kg mol-1], gravity [m s-2], radius [m], day [s], solar_constant [W m-2], semi_major_axis [au], eccentricity [1], obliquity [degree], dry_air_spec_heat_press [m2 s-2 K-1], dry_air_molecular_weight [kg mol-1])

The loaded data are stored as a CubeList under raw attribute.

[6]:
my_run.raw
[6]:
[<iris 'Cube' of convective_rainfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of convective_snowfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of high_type_cloud_area_fraction / (1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of low_type_cloud_area_fraction / (1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of medium_type_cloud_area_fraction / (1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of stratiform_rainfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of stratiform_snowfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>]

Minimal processing of loaded data

The next step might involve some clean-up and post-processing of raw data.

This is done by creating a function that takes iris.cube.CubeList as its 1st argument and returns another iris.cube.CubeList as output. The function is then passed to Run.proc_data() and its output stored as Run.proc attribute.

For example, the function roll_cube_pm180() imported below takes a Cube and rolls its longitudes from 0…360 to -180…180.

[7]:
from aeolus.grid import roll_cube_pm180, ensure_bounds

It can then be applied to all raw cubes.

[8]:
def _prepare_cubes(cubelist):
    """Post-process data for easier analysis."""
    # Roll cubes
    r_cubes = iris.cube.CubeList()
    for cube in cubelist:
        r_c = roll_cube_pm180(cube)
        ensure_bounds(r_c)  # also, ensure that longitudes and latitudes have bounds
        r_cubes.append(r_c)

    return r_cubes
[9]:
my_run.proc_data(_prepare_cubes)
[10]:
my_run.proc
[10]:
[<iris 'Cube' of convective_rainfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of convective_snowfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of high_type_cloud_area_fraction / (1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of low_type_cloud_area_fraction / (1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of medium_type_cloud_area_fraction / (1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of stratiform_rainfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>,
<iris 'Cube' of stratiform_snowfall_flux / (kg m-2 s-1) (latitude: 90; longitude: 144)>]

Check that it did what expected.

[11]:
print(my_run.raw.extract_strict("convective_rainfall_flux").coord("longitude"))
DimCoord(array([  1.25,   3.75,   6.25,   8.75,  11.25,  13.75,  16.25,  18.75,
        21.25,  23.75,  26.25,  28.75,  31.25,  33.75,  36.25,  38.75,
        41.25,  43.75,  46.25,  48.75,  51.25,  53.75,  56.25,  58.75,
        61.25,  63.75,  66.25,  68.75,  71.25,  73.75,  76.25,  78.75,
        81.25,  83.75,  86.25,  88.75,  91.25,  93.75,  96.25,  98.75,
       101.25, 103.75, 106.25, 108.75, 111.25, 113.75, 116.25, 118.75,
       121.25, 123.75, 126.25, 128.75, 131.25, 133.75, 136.25, 138.75,
       141.25, 143.75, 146.25, 148.75, 151.25, 153.75, 156.25, 158.75,
       161.25, 163.75, 166.25, 168.75, 171.25, 173.75, 176.25, 178.75,
       181.25, 183.75, 186.25, 188.75, 191.25, 193.75, 196.25, 198.75,
       201.25, 203.75, 206.25, 208.75, 211.25, 213.75, 216.25, 218.75,
       221.25, 223.75, 226.25, 228.75, 231.25, 233.75, 236.25, 238.75,
       241.25, 243.75, 246.25, 248.75, 251.25, 253.75, 256.25, 258.75,
       261.25, 263.75, 266.25, 268.75, 271.25, 273.75, 276.25, 278.75,
       281.25, 283.75, 286.25, 288.75, 291.25, 293.75, 296.25, 298.75,
       301.25, 303.75, 306.25, 308.75, 311.25, 313.75, 316.25, 318.75,
       321.25, 323.75, 326.25, 328.75, 331.25, 333.75, 336.25, 338.75,
       341.25, 343.75, 346.25, 348.75, 351.25, 353.75, 356.25, 358.75],
      dtype=float32), standard_name='longitude', units=Unit('degrees'), coord_system=GeogCS(6371229.0), circular=True)
[12]:
print(my_run.proc.extract_strict("convective_rainfall_flux").coord("longitude"))
DimCoord(array([-178.75, -176.25, -173.75, -171.25, -168.75, -166.25, -163.75,
       -161.25, -158.75, -156.25, -153.75, -151.25, -148.75, -146.25,
       -143.75, -141.25, -138.75, -136.25, -133.75, -131.25, -128.75,
       -126.25, -123.75, -121.25, -118.75, -116.25, -113.75, -111.25,
       -108.75, -106.25, -103.75, -101.25,  -98.75,  -96.25,  -93.75,
        -91.25,  -88.75,  -86.25,  -83.75,  -81.25,  -78.75,  -76.25,
        -73.75,  -71.25,  -68.75,  -66.25,  -63.75,  -61.25,  -58.75,
        -56.25,  -53.75,  -51.25,  -48.75,  -46.25,  -43.75,  -41.25,
        -38.75,  -36.25,  -33.75,  -31.25,  -28.75,  -26.25,  -23.75,
        -21.25,  -18.75,  -16.25,  -13.75,  -11.25,   -8.75,   -6.25,
         -3.75,   -1.25,    1.25,    3.75,    6.25,    8.75,   11.25,
         13.75,   16.25,   18.75,   21.25,   23.75,   26.25,   28.75,
         31.25,   33.75,   36.25,   38.75,   41.25,   43.75,   46.25,
         48.75,   51.25,   53.75,   56.25,   58.75,   61.25,   63.75,
         66.25,   68.75,   71.25,   73.75,   76.25,   78.75,   81.25,
         83.75,   86.25,   88.75,   91.25,   93.75,   96.25,   98.75,
        101.25,  103.75,  106.25,  108.75,  111.25,  113.75,  116.25,
        118.75,  121.25,  123.75,  126.25,  128.75,  131.25,  133.75,
        136.25,  138.75,  141.25,  143.75,  146.25,  148.75,  151.25,
        153.75,  156.25,  158.75,  161.25,  163.75,  166.25,  168.75,
        171.25,  173.75,  176.25,  178.75]), bounds=array([[-180. , -177.5],
       [-177.5, -175. ],
       [-175. , -172.5],
       [-172.5, -170. ],
       [-170. , -167.5],
       [-167.5, -165. ],
       [-165. , -162.5],
       [-162.5, -160. ],
       [-160. , -157.5],
       [-157.5, -155. ],
       [-155. , -152.5],
       [-152.5, -150. ],
       [-150. , -147.5],
       [-147.5, -145. ],
       [-145. , -142.5],
       [-142.5, -140. ],
       [-140. , -137.5],
       [-137.5, -135. ],
       [-135. , -132.5],
       [-132.5, -130. ],
       [-130. , -127.5],
       [-127.5, -125. ],
       [-125. , -122.5],
       [-122.5, -120. ],
       [-120. , -117.5],
       [-117.5, -115. ],
       [-115. , -112.5],
       [-112.5, -110. ],
       [-110. , -107.5],
       [-107.5, -105. ],
       [-105. , -102.5],
       [-102.5, -100. ],
       [-100. ,  -97.5],
       [ -97.5,  -95. ],
       [ -95. ,  -92.5],
       [ -92.5,  -90. ],
       [ -90. ,  -87.5],
       [ -87.5,  -85. ],
       [ -85. ,  -82.5],
       [ -82.5,  -80. ],
       [ -80. ,  -77.5],
       [ -77.5,  -75. ],
       [ -75. ,  -72.5],
       [ -72.5,  -70. ],
       [ -70. ,  -67.5],
       [ -67.5,  -65. ],
       [ -65. ,  -62.5],
       [ -62.5,  -60. ],
       [ -60. ,  -57.5],
       [ -57.5,  -55. ],
       [ -55. ,  -52.5],
       [ -52.5,  -50. ],
       [ -50. ,  -47.5],
       [ -47.5,  -45. ],
       [ -45. ,  -42.5],
       [ -42.5,  -40. ],
       [ -40. ,  -37.5],
       [ -37.5,  -35. ],
       [ -35. ,  -32.5],
       [ -32.5,  -30. ],
       [ -30. ,  -27.5],
       [ -27.5,  -25. ],
       [ -25. ,  -22.5],
       [ -22.5,  -20. ],
       [ -20. ,  -17.5],
       [ -17.5,  -15. ],
       [ -15. ,  -12.5],
       [ -12.5,  -10. ],
       [ -10. ,   -7.5],
       [  -7.5,   -5. ],
       [  -5. ,   -2.5],
       [  -2.5,    0. ],
       [   0. ,    2.5],
       [   2.5,    5. ],
       [   5. ,    7.5],
       [   7.5,   10. ],
       [  10. ,   12.5],
       [  12.5,   15. ],
       [  15. ,   17.5],
       [  17.5,   20. ],
       [  20. ,   22.5],
       [  22.5,   25. ],
       [  25. ,   27.5],
       [  27.5,   30. ],
       [  30. ,   32.5],
       [  32.5,   35. ],
       [  35. ,   37.5],
       [  37.5,   40. ],
       [  40. ,   42.5],
       [  42.5,   45. ],
       [  45. ,   47.5],
       [  47.5,   50. ],
       [  50. ,   52.5],
       [  52.5,   55. ],
       [  55. ,   57.5],
       [  57.5,   60. ],
       [  60. ,   62.5],
       [  62.5,   65. ],
       [  65. ,   67.5],
       [  67.5,   70. ],
       [  70. ,   72.5],
       [  72.5,   75. ],
       [  75. ,   77.5],
       [  77.5,   80. ],
       [  80. ,   82.5],
       [  82.5,   85. ],
       [  85. ,   87.5],
       [  87.5,   90. ],
       [  90. ,   92.5],
       [  92.5,   95. ],
       [  95. ,   97.5],
       [  97.5,  100. ],
       [ 100. ,  102.5],
       [ 102.5,  105. ],
       [ 105. ,  107.5],
       [ 107.5,  110. ],
       [ 110. ,  112.5],
       [ 112.5,  115. ],
       [ 115. ,  117.5],
       [ 117.5,  120. ],
       [ 120. ,  122.5],
       [ 122.5,  125. ],
       [ 125. ,  127.5],
       [ 127.5,  130. ],
       [ 130. ,  132.5],
       [ 132.5,  135. ],
       [ 135. ,  137.5],
       [ 137.5,  140. ],
       [ 140. ,  142.5],
       [ 142.5,  145. ],
       [ 145. ,  147.5],
       [ 147.5,  150. ],
       [ 150. ,  152.5],
       [ 152.5,  155. ],
       [ 155. ,  157.5],
       [ 157.5,  160. ],
       [ 160. ,  162.5],
       [ 162.5,  165. ],
       [ 165. ,  167.5],
       [ 167.5,  170. ],
       [ 170. ,  172.5],
       [ 172.5,  175. ],
       [ 175. ,  177.5],
       [ 177.5,  180. ]]), standard_name='longitude', units=Unit('degrees'), coord_system=GeogCS(5804071.0), circular=True)

Note that the longitude coordinate is not only shifted by 180 degrees, but has automatically calculated bounds.

In addition, note that coord_system in proc cubes is different, because it used Run.const attribute to redefine the planet radius correctly. By default the loaded raw data has Earth radius in its coord_system, so certain calculations (e.g. grid cell areas) might be incorrect.