Functions to load CRUTEMΒΆ

# Functions to load the CRUTEM data

# Loading the data month-by-month is too slow, so we load a decade at a time and cache it

import iris
import numpy as np

import iris.coord_systems
import iris.fileformats

coord_s = iris.coord_systems.GeogCS(iris.fileformats.pp.EARTH_RADIUS)

from utilities.utils import rng

# I don't want warnings about sub-second time precision
iris.FUTURE.date_microseconds = True

current_decade = None
decadal = None
cached_grid = None


# Need a land mask - masks out ocean-only grid cells - keep cells with a small island.
def get_land_mask(new_grid=None):
    lm = iris.load_cube(
        "/data/users/hadobs/cma_datasets/hadcrut5/hadobs-release/HadCRUT.5.0.2.0-202502/analysis/HadCRUT.5.0.2.0.land_fraction.nc"
    )
    lm.coord("latitude").coord_system = coord_s
    lm.coord("longitude").coord_system = coord_s
    if new_grid is not None:
        lm = lm.regrid(new_grid, iris.analysis.Nearest())
    lm.data = np.ma.MaskedArray(
        lm.data.data, lm.data.data == 0.0
    )  # Mask out land fraction of 0
    return lm


# Load the data for a decade
def load_decade(year, new_grid=None):
    m = iris.load_cube(
        "/data/users/hadobs/cma_datasets/crutem4/release_data/current/gridded_fields/"
        + "CRUTEM.4.6.0.0.anomalies.pp",
        iris.Constraint(
            time=lambda cell: cell.point.year >= year and cell.point.year < year + 10
        ),
    )
    m.coord("latitude").coord_system = coord_s
    m.coord("longitude").coord_system = coord_s
    m.data.data[m.data.mask] = np.nan  # Mask the data
    if new_grid is not None:
        m = m.regrid(new_grid, iris.analysis.Nearest())
    return m


# Load the data for a month
def load_month(year, month, new_grid=None):

    global current_decade
    global decadal
    global cached_grid
    # If the decade has changed, or the grid has changed, reload the decade
    try:
        if (
            current_decade is None
            or year < current_decade
            or year >= current_decade + 10
            or cached_grid != new_grid
        ):
            cached_grid = new_grid
            current_decade = year - (year % 10)
            decadal = load_decade(current_decade, new_grid=new_grid)
        m = decadal.extract(
            iris.Constraint(
                time=lambda cell: cell.point.year == year and cell.point.month == month
            ),
        )
    except (iris.exceptions.ConstraintMismatchError, AttributeError) as e:
        return new_grid
    if m is None:
        return new_grid
    return m