SciTools / iris-grib

GRIB interface for Iris.
https://iris-grib.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
23 stars 43 forks source link

typeOfFirstFixedSurface decode issues #372

Open ColemanTom opened 10 months ago

ColemanTom commented 10 months ago

I am having issues with fields with typeOfFirstFixedSurface=101, they are not decoding correctly.

I have attached a file, a.zip, which contains a grib2 file to assist in debugging/testing.

With iris-grib v0.18.0, printing this cube out, I get

air_pressure_at_sea_level / (Pa)    (latitude: 42; longitude: 28)
    Dimension coordinates:
        latitude                             x              -
        longitude                            -              x
    Scalar coordinates:
        forecast_period             12 hours
        forecast_reference_time     2019-04-05 00:00:00
        time                        2019-04-05 12:00:00
    Attributes:
        GRIB_PARAM                  GRIB2:d000c003n001

Printing the same cube out with iris-grib v0.19.0, I get

air_pressure_at_sea_level / (Pa)    (latitude: 42; longitude: 28)
    Dimension coordinates:
        latitude                             x              -
        longitude                            -              x
    Scalar coordinates:
        forecast_period             12 hours
        forecast_reference_time     2019-04-05 00:00:00
        time                        2019-04-05 12:00:00
        unknown                     0.0
    Attributes:
        GRIB_PARAM                  GRIB2:d000c003n001

See the new "unknown" attribute.

I'm guessing this relates to changes in the _load_convert.py file, but I've not been able to quickly come up with a solution.

trexfeathers commented 10 months ago

Hi @ColemanTom, thanks for getting in touch, and thanks for including an example file which always help isolate things faster.

You're right that _load_convert.py was recently changed to load any fixed surface, even if not fully supported - #318. This has allowed iris-grib to load many more coordinates than previously, even if we have never seen them before, or have not coded for them due to difficulties representing them within CF.

The two fixed surfaces that iris-grib fully recognises are these:

https://github.com/SciTools/iris-grib/blob/831ea257d82c3f0d7ec6a840f57654de9979b0a6/iris_grib/_load_convert.py#L96-L100

Everything else will be loaded with no standard_name, long_name, or units, which leads to them being shown as unknown on a Cube printout.

We can potentially add to the above _FIXED_SURFACE dictionary with help from our users. A combination of limited test cases and under-specified GRIB documentation means we usually need someone downstream to tell us if a change is delivering the desired effect. If you think you can help, by all means make a suggestion or even a pull request ❤

ColemanTom commented 9 months ago

Could it be a bit smarter perhaps? For example, pseudocode

surface = _FIXED_SURFACE.get(typeOfFixedSurface, deriveFixedSurface(grib_message_gid))

...
def deriveFixedSurface(gid):
    long_name = codes_get_string(gid, 'nameOfFirstFixedSurface').replace(' ', '_').lower()
    short_name = codes_get_string(gid', 'typeOfFirstFixedSurface').replace(' ', '_').lower()
    unit = codes_get_string(gid, 'unitOfFirstFixedSurface')
    return FixedSurface(short_name, long_name, unit)

Obviously, I've hardcoded First in the example method, but is that sort of what is trying to be accomplished?

Default to the custom defined ones (else you would have isobaric_surface for pressure for example.

trexfeathers commented 9 months ago

With the long_name potentially. However Iris's data model is based on the CF Conventions, which define many aspects of what is valid, including standard_name, and units. It is likely that taking these directly from the GRIB file will mostly result in ValueErrors when trying to create Cubes or Coords with what are considered to be invalid inputs.

We so far don't have a sophisticated way to translate from GRIB to CF, other than rote-translation (as well as the table above, we have _grib_cf_map.py for many more examples). This is obviously more clunky, but the best way to fit GRIB to the CF data model.