iris icon indicating copy to clipboard operation
iris copied to clipboard

loading cubes with differing units for time and time_bounds

Open andreas-h opened this issue 10 years ago • 5 comments

I have a .nc file where the time variable has different units from time_bnds:

ncdump -h 2008001.nc
netcdf \2008001 {
dimensions:
    bnds = 2 ;
    time = 1 ;
    longitude = 7200 ;
    latitude = 3600 ;
    wavelength = 1 ;
variables:
    int bnds(bnds) ;
    double time_bnds(bnds) ;
        time_bnds:units = "days since 2008-01-01 00:00:00" ;
        time_bnds:calendar = "proleptic_gregorian" ;
    double time(time) ;
        time:bounds = "time_bnds" ;
        time:standard_name = "time" ;
        time:units = "days since 2008-01-09 00:00:00" ;
        time:calendar = "proleptic_gregorian" ;

When I load this cube in Iris 1.8.1, the time coord is wrong:

In [3]: c = iris.load('2008001.nc')[0]

In [4]: c.coord('time')
Out[4]: DimCoord(array([ 0.]), bounds=array([[  0.,  16.]]), standard_name=u'time', units=Unit('days since 2008-01-09 00:00:00', calendar='proleptic_gregorian'), var_name='time')

In [5]: print c.coord('time')
DimCoord([2008-01-09 00:00:00], bounds=[[2008-01-09 00:00:00, 2008-01-25 00:00:00]], standard_name=u'time', calendar=u'proleptic_gregorian', var_name='time')

It seems like the units of the time_bnds variable are applied to both time and time_bnds points.

andreas-h avatar Sep 29 '15 08:09 andreas-h

Hi @andreas-h. Interesting. The CF spec states:

7.1. Cell Boundaries To represent cells we add the attribute bounds to the appropriate coordinate variable(s). The value of bounds is the name of the variable that contains the vertices of the cell boundaries. We refer to this type of variable as a "boundary variable." A boundary variable will have one more dimension than its associated coordinate or auxiliary coordinate variable. The additional dimension should be the most rapidly varying one, and its size is the maximum number of cell vertices. Since a boundary variable is considered to be part of a coordinate variable's metadata, it is not necessary to provide it with attributes such as long_name and units .

So whilst it doesn't explicitly rule them out (the word "necessary" is ambiguous), it is not a usecase we've needed to handle before. Is this something that is a one-off? If so, I think you should be able to use a callback to convert the bound units. Something like:

def normalise_time_bnds_units(cube, variable, fname):
    time_bnds = variable.cf_group['time'].cf_group['time_bnds']

    bnd_units = iris.unit.Unit(time_bnds.units)
    t = cube.coord('time')
    # Convert to the correct units.
    t.bounds = t.units.date2num(bnd_units.num2date(t.bounds))

cubes = iris.load(fname, callback=normalise_time_bnds_units)

pelson avatar Sep 29 '15 08:09 pelson

thanks, @pelson

Yes, it's a one-off thing, and actually, I forgot the way to prevent this issue from occurring in the first place (in case you're interested, see https://github.com/xray/xray/issues/540).

andreas-h avatar Sep 29 '15 09:09 andreas-h

maybe raising a warning/exception in iris when the units of a coord and its bounds don't match would be useful, though.

andreas-h avatar Sep 29 '15 09:09 andreas-h

This situation does now seem to have been ruled out in the CF conventions:

Boundary variable attributes which determine the coordinate type (units, standard_name, axis and positive) or those which affect the interpretation of the array values (units, calendar, leap_month, leap_year and month_lengths) must always agree exactly with the same attributes of its associated coordinate, scalar coordinate or auxiliary coordinate variable. To avoid duplication, however, it is recommended that these are not provided to a boundary variable.

rcomer avatar Jul 16 '21 23:07 rcomer

This situation does now seem to have been ruled out in the CF conventions:

Boundary variable attributes which determine the coordinate type (units, standard_name, axis and positive) or those which affect the interpretation of the array values (units, calendar, leap_month, leap_year and month_lengths) must always agree exactly with the same attributes of its associated coordinate, scalar coordinate or auxiliary coordinate variable. To avoid duplication, however, it is recommended that these are not provided to a boundary variable.

Thanks @rcomer! Based on this, @SciTools/peloton have agreed that we should raise an Exception during loading if the bounds units differ from the coordinate units.

Perhaps ditto with other bounds attributes, too.

trexfeathers avatar Aug 24 '22 09:08 trexfeathers

@SciTools/peloton think this could be tolerant. If you can convert_units() then do that, otherwise it really would be an error

Similar idea mentioned in #5020

pp-mo avatar Nov 23 '22 10:11 pp-mo

We'll aim to get this into 3.8 with the approach suggested by @pp-mo along with a warning.

stephenworsley avatar Oct 19 '23 13:10 stephenworsley