Skip to content

Preprocessor multimodel_statistics fails when data have no time dimension #890

@stefsmeets

Description

@stefsmeets

Describe the bug
Hi all, I'm developing some tests for the multimodel statistics using real data (#856), and I'm coming accross this bug:

Running multimodel statistics with a list of cubes with no time dimension, will result in
ValueError: Cannot guess bounds for a coordinate of length 1.

The bug can be reproduced by:

cubes = [cube[0] for cube in cubes]
multi_model_statistics(cubes, span='full', statistics=['mean'])
See the full stack trace below.
timeseries_cubes_month = [<iris 'Cube' of air_temperature / (K) (time: 14; air_pressure: 2; latitude: 3; longitude: 2)>, <iris 'Cube' of air_te... 3; longitude: 2)>, <iris 'Cube' of air_temperature / (K) (time: 14; air_pressure: 2; latitude: 3; longitude: 2)>, ...]

    @pytest.mark.functional
    # @pytest.mark.xfail('ValueError')
    def test_multimodel_no_time_dimension(timeseries_cubes_month):
        """Test statistic without time dimension using monthly data."""
        span = 'full'
        cubes = timeseries_cubes_month
        cubes = [cube[0] for cube in cubes]
        # ValueError: Cannot guess bounds for a coordinate of length 1.
>       multimodel_test(cubes, span=span, statistic='mean')

tests/functional/test_multimodel.py:227:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/functional/test_multimodel.py:125: in multimodel_test
    output = multi_model_statistics(cubes, span=span, statistics=statistics)
esmvalcore/preprocessor/_multimodel.py:439: in multi_model_statistics
    statistic_cube = _assemble_full_data(cubes, statistic)
esmvalcore/preprocessor/_multimodel.py:323: in _assemble_full_data
    time_axis = [float(fl) for fl in _monthly_t(cubes)]
esmvalcore/preprocessor/_multimodel.py:277: in _monthly_t
    days = {day for cube in cubes for day in _datetime_to_int_days(cube)}
esmvalcore/preprocessor/_multimodel.py:277: in <setcomp>
    days = {day for cube in cubes for day in _datetime_to_int_days(cube)}
esmvalcore/preprocessor/_multimodel.py:206: in _datetime_to_int_days
    cube = _align_yearly_axes(cube)
esmvalcore/preprocessor/_multimodel.py:231: in _align_yearly_axes
    return regrid_time(cube, 'yr')
esmvalcore/preprocessor/_time.py:602: in regrid_time
    cube.coord('time').guess_bounds()
../../miniconda3/envs/esmvaltool/lib/python3.8/site-packages/iris/coords.py:1564: in guess_bounds
    self.bounds = self._guess_bounds(bound_position)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = DimCoord(array([49456.]), standard_name='time', units=Unit('days since 1850-1-1 00:00:00', calendar='365_day'), long_name='time', var_name='time', attributes={'_ChunkSizes': 1})
bound_position = 0.5

    def _guess_bounds(self, bound_position=0.5):
        """
        Return bounds for this coordinate based on its points.

        Kwargs:

        * bound_position:
            The desired position of the bounds relative to the position
            of the points.

        Returns:
            A numpy array of shape (len(self.points), 2).

        .. note::

            This method only works for coordinates with ``coord.ndim == 1``.

        .. note::

            If `iris.FUTURE.clip_latitudes` is True, then this method
            will clip the coordinate bounds to the range [-90, 90] when:

            - it is a `latitude` or `grid_latitude` coordinate,
            - the units are degrees,
            - all the points are in the range [-90, 90].

        .. deprecated:: 2.0.0

            The `iris.FUTURE.clip_latitudes` option is now deprecated
            and is set to True by default. Please remove code which
            relies on coordinate bounds being outside the range
            [-90, 90].

        """
        # XXX Consider moving into DimCoord
        # ensure we have monotonic points
        if not self.is_monotonic():
            raise ValueError("Need monotonic points to generate bounds for %s"
                             % self.name())

        if self.ndim != 1:
            raise iris.exceptions.CoordinateMultiDimError(self)

        if self.shape[0] < 2:
>           raise ValueError('Cannot guess bounds for a coordinate of length '
                             '1.')
E           ValueError: Cannot guess bounds for a coordinate of length 1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpreprocessorRelated to the preprocessor

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions