GRIB: converting to NetCDF

[1]:
import earthkit.data as ekd
from earthkit.data.utils.summary import ncdump

ekd.download_example_file("tuv_pl.grib")
# we only select the temperature fields
ds = ekd.from_source("file", "tuv_pl.grib").to_fieldlist().sel({"parameter.variable": "t"})

Using to_netcdf() directly

To convert GRIB data to NetCDF first we need to convert GRIB to Xarray with to_xarray() then generate NetCDF from it with xarray.Dataset.to_netcdf(). The earthkit attributes (_earthkit) attached to each DataArray are encoded as JSON strings, so they are fully compatible with NetCDF. We can simply call to_netcdf() directly on the dataset.

[2]:
ds.to_xarray().to_netcdf("_tuv_pl.nc")
[3]:
ncdump("_tuv_pl.nc")
netcdf _tuv_pl {
dimensions:
        level = 6 ;
        latitude = 7 ;
        longitude = 12 ;
variables:
        double t(level, latitude, longitude) ;
                t:_FillValue = NaN ;
                t:standard_name = "air_temperature" ;
                t:long_name = "Temperature" ;
                t:units = "kelvin" ;
                t:level_type = "pressure" ;
                t:_earthkit = "{\"message\": {\"__bytes_b64__\": \"R1JJQgAAbAEAADSAYpX/gIJkASwSCAEMAAEAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAQECBAEwMDAxAAAAAAAgAP8AAAwABwFfkAAAAICBX5AFCRB1MHUwAAAAAAAAAAwAgAJEuX1uAAA3Nzc3\"}, \"bitsPerValue\": 4}" ;
        int64 level(level) ;
                level:standard_name = "air_pressure" ;
                level:long_name = "pressure" ;
                level:units = "hectopascal" ;
                level:positive = "down" ;
        double latitude(latitude) ;
                latitude:_FillValue = NaN ;
                latitude:units = "degrees_north" ;
                latitude:standard_name = "latitude" ;
                latitude:long_name = "latitude" ;
        double longitude(longitude) ;
                longitude:_FillValue = NaN ;
                longitude:units = "degrees_east" ;
                longitude:standard_name = "longitude" ;
                longitude:long_name = "longitude" ;

// global attributes:
                :Conventions = "CF-1.8" ;
                :institution = "ECMWF" ;
}

Using add_earthkit_attrs=False

If you prefer not to include the earthkit attributes in the NetCDF file at all, you can use the add_earthkit_attrs=False option in to_xarray(). Note that without these attributes, converting the Xarray dataset back to GRIB will not be possible.

[4]:
ds.to_xarray(add_earthkit_attrs=False).to_netcdf("_tuv_pl_1.nc")
ncdump("_tuv_pl_1.nc")
netcdf _tuv_pl_1 {
dimensions:
        level = 6 ;
        latitude = 7 ;
        longitude = 12 ;
variables:
        double t(level, latitude, longitude) ;
                t:_FillValue = NaN ;
                t:standard_name = "air_temperature" ;
                t:long_name = "Temperature" ;
                t:units = "kelvin" ;
                t:level_type = "pressure" ;
        int64 level(level) ;
                level:standard_name = "air_pressure" ;
                level:long_name = "pressure" ;
                level:units = "hectopascal" ;
                level:positive = "down" ;
        double latitude(latitude) ;
                latitude:_FillValue = NaN ;
                latitude:units = "degrees_north" ;
                latitude:standard_name = "latitude" ;
                latitude:long_name = "latitude" ;
        double longitude(longitude) ;
                longitude:_FillValue = NaN ;
                longitude:units = "degrees_east" ;
                longitude:standard_name = "longitude" ;
                longitude:long_name = "longitude" ;

// global attributes:
                :Conventions = "CF-1.8" ;
                :institution = "ECMWF" ;
}

Using to_target

We can call to_target() on the fieldlist and the Xarray conversion and writing to NetCDF will happen automatically under the hood using the default options.

[5]:
ds.to_target("file", "_tuv_pl_2.nc")
ncdump("_tuv_pl_2.nc")
netcdf _tuv_pl_2 {
dimensions:
        level = 6 ;
        latitude = 7 ;
        longitude = 12 ;
variables:
        double t(level, latitude, longitude) ;
                t:_FillValue = NaN ;
                t:standard_name = "air_temperature" ;
                t:long_name = "Temperature" ;
                t:units = "kelvin" ;
                t:level_type = "pressure" ;
                t:_earthkit = "{\"message\": {\"__bytes_b64__\": \"R1JJQgAAbAEAADSAYpX/gIJkASwSCAEMAAEAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAQECBAEwMDAxAAAAAAAgAP8AAAwABwFfkAAAAICBX5AFCRB1MHUwAAAAAAAAAAwAgAJEuX1uAAA3Nzc3\"}, \"bitsPerValue\": 4}" ;
        int64 level(level) ;
                level:standard_name = "air_pressure" ;
                level:long_name = "pressure" ;
                level:units = "hectopascal" ;
                level:positive = "down" ;
        double latitude(latitude) ;
                latitude:_FillValue = NaN ;
                latitude:units = "degrees_north" ;
                latitude:standard_name = "latitude" ;
                latitude:long_name = "latitude" ;
        double longitude(longitude) ;
                longitude:_FillValue = NaN ;
                longitude:units = "degrees_east" ;
                longitude:standard_name = "longitude" ;
                longitude:long_name = "longitude" ;

// global attributes:
                :Conventions = "CF-1.8" ;
                :institution = "ECMWF" ;
}

To control the Xarray conversion we can pass options to the earthkit Xarray engine via earthkit_to_xarray_kwargs.

[6]:
ds.to_target("file", "_tuv_pl_3.nc", earthkit_to_xarray_kwargs={"flatten_values": True})
ncdump("_tuv_pl_3.nc")
netcdf _tuv_pl_3 {
dimensions:
        level = 6 ;
        values = 84 ;
variables:
        double t(level, values) ;
                t:_FillValue = NaN ;
                t:standard_name = "air_temperature" ;
                t:long_name = "Temperature" ;
                t:units = "kelvin" ;
                t:level_type = "pressure" ;
                t:_earthkit = "{\"message\": {\"__bytes_b64__\": \"R1JJQgAAbAEAADSAYpX/gIJkASwSCAEMAAEAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAQECBAEwMDAxAAAAAAAgAP8AAAwABwFfkAAAAICBX5AFCRB1MHUwAAAAAAAAAAwAgAJEuX1uAAA3Nzc3\"}, \"bitsPerValue\": 4}" ;
                t:coordinates = "latitude longitude" ;
        int64 level(level) ;
                level:standard_name = "air_pressure" ;
                level:long_name = "pressure" ;
                level:units = "hectopascal" ;
                level:positive = "down" ;
        double latitude(values) ;
                latitude:_FillValue = NaN ;
                latitude:units = "degrees_north" ;
                latitude:standard_name = "latitude" ;
                latitude:long_name = "latitude" ;
        double longitude(values) ;
                longitude:_FillValue = NaN ;
                longitude:units = "degrees_east" ;
                longitude:standard_name = "longitude" ;
                longitude:long_name = "longitude" ;

// global attributes:
                :Conventions = "CF-1.8" ;
                :institution = "ECMWF" ;
}

[ ]: