iris icon indicating copy to clipboard operation
iris copied to clipboard

Merge dimension mashup

Open bblay opened this issue 1 year ago • 0 comments

🐛 Bug Report

Merge is mashing two dimensions into one.

How To Reproduce

I didn't manage to reproduce this using contrived cubes, so I can only currently reproduce it from the source data, at work. Simply load the cubes and the problem occurs. I've written a script which demonstrates the problem and will paste that, and the output, below. I also have a workaround at work. I'm not yet sure if I can share it.

Expected behaviour

The data are global lat-lon octants. I believe they should be loaded into sixteen cubes. Eight of them should share a single time and forecast period, with fourteen pressure levels. The other eight should share a different time and forecast period, and have 11 pressure levels.

Actual behaviour

Instead, the data is loading into eight cubes with the third dimension having 25 points - a mashup of the pressure and time coords.

One impact of this: I'm extracting each time point and saving as netcdf. Without the workaround, it produces a file without proper knowledge of the pressure dimension. It's just called "dim1", it's in a seemingly random order, and the points are just indices 0-13. Another impact is that the coord points are a bit of a mess, as you can see in the output below.

Workaround

I've worked around this by using load_raw, and writing a function which groups by time, merging each group separately to force the pressure levels to be merged into a sensible dimension first. The workaround is specific to the data, not a generic fix.

Environment

  • OS & Version: RHEL 7.9
  • Iris Version: 3.7

Additional context

code to highlight the problem
#!/usr/bin/env python

from pathlib import Path
import sys
sys.path.append('HIDING_PATHS_HERE')

import iris
from iris.cube import CubeList

# workaround is in here
from grib_concat import load_cubes, load_cubes_controlled


if __name__ == '__main__':

    fpaths = [
        Path('HIDING_PATHS_HERE/file1'),
        Path('HIDING_PATHS_HERE/file2'),
    ]

    # normal iris loading
    iris_load_cubes = load_cubes(fpaths)
    iris_156_cubes = CubeList([c for c in iris_load_cubes if 'UNKNOWN LOCAL PARAM 156' in c.name()])

    # workaround with controlled merging
    controlled_merge_cubes = load_cubes_controlled(fpaths)
    controlled_156_cubes = CubeList([c for c in controlled_merge_cubes if 'UNKNOWN LOCAL PARAM 156' in c.name()])

    print('--- iris load ---\n')

    print(f'{len(iris_156_cubes)} cubes\n')
    for c in iris_156_cubes:
        print(repr(c))

    print('\ncube 0:\n', iris_156_cubes[0], '\n')
    print('forecast_period', iris_156_cubes[0].coord('forecast_period').points)
    print('pressure', iris_156_cubes[0].coord('pressure').points)
    print('time', iris_156_cubes[0].coord('time').points, '\n')

    print('one of the cubes after extracting fp=0:')
    iris_fp0 = iris_156_cubes.extract(iris.Constraint(forecast_period=0))[0]
    print(repr(iris_fp0))
    print('forecast_period', iris_fp0.coord('forecast_period').points)
    print('pressure', iris_fp0.coord('pressure').points)
    print('time', iris_fp0.coord('time').points, '\n')
    iris.save(iris_fp0, 'from_iris_load.nc')

    print('--- controlled merge ---\n')

    print(f'{len(controlled_156_cubes)} cubes\n')
    for c in controlled_156_cubes:
        print(repr(c))

    print('\ncube 0:\n', controlled_156_cubes[0], '\n')
    print('forecast_period', controlled_156_cubes[0].coord('forecast_period').points)
    print('pressure', controlled_156_cubes[0].coord('pressure').points)
    print('time', controlled_156_cubes[0].coord('time').points, '\n')

    print('one of the cubes after extracting fp=0:')
    controlled_fp0 = controlled_156_cubes.extract(iris.Constraint(forecast_period=0))[0]
    print(repr(controlled_fp0))
    print('forecast_period', controlled_fp0.coord('forecast_period').points)
    print('pressure', controlled_fp0.coord('pressure').points)
    print('time', controlled_fp0.coord('time').points, '\n')
    iris.save(controlled_fp0, 'from_controlled_merge.nc')

In the output below, you can first see the data loaded with iris.load, then using iris.load_raw and "controlled" merging. In both cases one cube is printed, and then cubes are extracted at forecast_period=0 with one of those printed.

output
--- iris load ---

8 cubes

<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)>

cube 0:
 UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 25; latitude: 61; longitude: 60)
    Dimension coordinates:
        latitude                            -             x              -
        longitude                           -             -              x
    Auxiliary coordinates:
        forecast_period                     x             -              -
        pressure                            x             -              -
        time                                x             -              -
    Scalar coordinates:
        originating_centre              European Centre for Medium Range Weather Forecasts
    Attributes:
        generatingProcessIdentifier     154
        indicatorOfParameter            156
        indicatorOfTypeOfLevel          'pl'
        originating_centre_id           'ecmf' 

forecast_period [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0 24 24 24 24 24 24 24 24 24 24
 24]
pressure [ 300  250  400 1000  700  925  200  850  500  100  150   50   70   30
  700  925  300  200  850 1000  100  400  500  250  150]
time [474240. 474240. 474240. 474240. 474240. 474240. 474240. 474240. 474240.
 474240. 474240. 474240. 474240. 474240. 474264. 474264. 474264. 474264.
 474264. 474264. 474264. 474264. 474264. 474264. 474264.] 

one of the cubes after extracting fp=0:
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (-- : 14; latitude: 61; longitude: 60)>
forecast_period [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
pressure [ 300  250  400 1000  700  925  200  850  500  100  150   50   70   30]
time [474240. 474240. 474240. 474240. 474240. 474240. 474240. 474240. 474240.
 474240. 474240. 474240. 474240. 474240.] 

--- controlled merge ---

16 cubes

<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 11; latitude: 61; longitude: 60)>

cube 0:
 UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)
    Dimension coordinates:
        pressure                                 x             -              -
        latitude                                 -             x              -
        longitude                                -             -              x
    Scalar coordinates:
        forecast_period                 0 hours
        originating_centre              European Centre for Medium Range Weather Forecasts
        time                            2024-02-07 00:00:00
    Attributes:
        generatingProcessIdentifier     154
        indicatorOfParameter            156
        indicatorOfTypeOfLevel          'pl'
        originating_centre_id           'ecmf' 

forecast_period [0]
pressure [  30   50   70  100  150  200  250  300  400  500  700  850  925 1000]
time [474240.] 

one of the cubes after extracting fp=0:
<iris 'Cube' of UNKNOWN LOCAL PARAM 156.128 / (unknown) (pressure: 14; latitude: 61; longitude: 60)>
forecast_period [0]
pressure [  30   50   70  100  150  200  250  300  400  500  700  850  925 1000]
time [474240.] 

bblay avatar Feb 21 '24 17:02 bblay