You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add support to write a xarray.Dataset to a GRIB file. #18
Due to the fact that the NetCDF data model is much more free and extensible than the GRIB one, it is not possible to write a generic xarray.Dataset to a GRIB file. The aim for cfgrib is to implement write support for a subset of carefully crafted datasets that fit the GRIB data model.
In particular the only coordinates that we target at the moment are the one returned by opening a GRIB with the cfgrib flavour of cfgrib.open_dataset, namely:
number, time, step, a vertical coordinate (isobaricInhPa, heightAboveGround, surface, etc), and the horizontal coordinates (for example latitude and longitude for a regular_ll grid type).
Note that all passed GRIB_ attributes are used to set keys in the output file, it is left to the user to ensure coherence among them.
Some of the keys are autodetected from the coordinates, namely:
Horizontal coordinates gridTypes:
regular: regular_ll and regular_gg
not target: projected: lambert, etc (can be controlled with GRIB_ attributes)
not target: reduced: reduced_ll and reduced_gg (can be controlled with GRIB_ attributes)
I get a problem with this GRIB file "User_Guide_Example_Data.grib". It contains 3 vertical levels, each at 2 forecast steps, and when I read it, convert to xarray, then write back to GRIB, all the values are NaN. If I filter just a single step, then it works perfectly - the only differences are those you would expect when converting from GRIB 1 to GRIB 2, e.g. bounding box coords in microdegrees instead of millidegrees, etc.
Here's the code:
import xarray as xr
from cfgrib import xarray_store
from cfgrib import xarray_to_grib
import cfgrib
dst = xarray_store.GribDataStore.from_path("User_Guide_Example_Data.grib")
ds = xr.open_dataset(dst)
print(ds)
cfgrib.to_grib(ds, 'User_Guide_Example_Data_from_cfgrib.grib')#, grib_keys={'centre': 'ecmf'})
The problem is that np.nan were not handled in cfgrib and ecCodes doesn't support them.
In master now invalid values are set to missingValue before being sent to ecCodes and as an optimisation fields entirely comprised of np.nan are not written to disk at all.
Now the saved GRIB looks like this:
$ grib_ls out.grib
edition centre date dataType gridType stepRange typeOfLevel level shortName packingType
2 consensus 19960426 af regular_ll 48 isobaricInhPa 1000 t grid_simple
2 consensus 19960428 af regular_ll 0 isobaricInhPa 1000 t grid_simple
2 consensus 19960426 af regular_ll 48 isobaricInhPa 500 t grid_simple
2 consensus 19960428 af regular_ll 0 isobaricInhPa 500 t grid_simple
2 consensus 19960426 af regular_ll 48 isobaricInhPa 100 t grid_simple
2 consensus 19960428 af regular_ll 0 isobaricInhPa 100 t grid_simple
6 of 6 grib messages in out.grib
@alexamici - thanks for the very quick response! I can confirm that the code in the master branch works perfectly for this file now, and I plotted the fields with metview to check that they look identical (they do)!
Still looking good, I'm now checking more 'awkward' subarea definitions like this one, which plots correctly:
I'm using this Metview script to do it quite easily: compare_grib_plots.py.tar.gz
Note that right now master can re-write to disk most opened GRIB files, because we use the GRIB_ attributes read in input.
Doing an operation on the resulting xr.Dataset but keeping the attributes may make them incoherent. We apply some check and autodetect the values only in the limited set of cases described in the issue text.
import cfgrib
import xarray as xr
import pandas as pd
import sys
import glob
import os
def Grib2files():
folder = input('Folder PAth:')
val = input('Variable Name:')
#latitude = input('latitude:')
longitude = input('longitude:')
data_conc=[]
files = glob.glob(rf'{folder}/*.grib2')
for file in files:
data = xr.open_dataset(
file,
engine='cfgrib',
backend_kwargs={'filter_by_keys':{'typeOfLevel': 'hybrid'}})
lon = data.variables['longitude'].values
lat = data.variables['latitude'].values
hyb = data.variables['hybrid'].values
time = pd.Timestamp(data.time.values) + pd.to_timedelta(data.step.values,'H')
X = xr.Dataset(
{'data':data[val].values,
'lon': lon,
},
coords = {
'hyb':hyb,
'lat':lat,
},
)
data_conc.append(X)
return xr.concat(data_conc, dim=['time'])
data = Grib2files()
I am trying many ways to make this data to 2 d data
hybrid with all latitudes and fixed altitude and slice over time because this data is 1 file per hour and I need to run this for a whole year
I get a problem with this GRIB file "User_Guide_Example_Data.grib". It contains 3 vertical levels, each at 2 forecast steps, and when I read it, convert to xarray, then write back to GRIB, all the values are NaN. If I filter just a single step, then it works perfectly - the only differences are those you would expect when converting from GRIB 1 to GRIB 2, e.g. bounding box coords in microdegrees instead of millidegrees, etc. Here's the code:
import xarray as xr
from cfgrib import xarray_store
from cfgrib import xarray_to_grib
import cfgrib
dst = xarray_store.GribDataStore.from_path("User_Guide_Example_Data.grib")
ds = xr.open_dataset(dst)
print(ds)
cfgrib.to_grib(ds, 'User_Guide_Example_Data_from_cfgrib.grib')#, grib_keys={'centre': 'ecmf'})
sorry to bother you, but when i run code 'dst = xarray_store.GribDataStore.from_path("User_Guide_Example_Data.grib")',the computer warns there is no attribute 'GribDataStore'. my computer is windows platform and i download xarray and cfgrib in anaconda.
Hi! I have an issue with writing grib files. Here I open two grib datasets, sum them up, and write the resulting dataset to grib file; then I open the new grib as dataset.
During the writing I get the following warning: FutureWarning: GRIB write support is experimental, DO NOT RELY ON IT! warnings.warn("GRIB write support is experimental, DO NOT RELY ON IT!", FutureWarning)
failed to set key 'endStep:int' to 0
failed to set key 'stepUnits:int' to 1
Here are the three datasets, from left to right: the original one, the resulting one, and the resulting one after writing to grib
Here you can see that after the writing:
the original coordinate heightAboveGround turns into surface and its value 2.0 - into 0.0.
the name of t2m data variable turns into t.
Why do the changes take place during the writing? When I open the newly created grib file with the viewer the temperature represents to be the surface temperature (0 altitude), while originally it is 2m temperature.
Thanks!
Now the to_grib() detects the altitude coordinate heightAboveGround and properly writes it to grib file, preserving its value, which is in my case 2.0:
The data variable name still gets changed (t2m to t), but that's no big deal. The written grib file now is being properly read via grib viewer, with t data variable represented as 2m-altitude temperature!
Activity
iainrussell commentedon Sep 20, 2018
I get a problem with this GRIB file "User_Guide_Example_Data.grib". It contains 3 vertical levels, each at 2 forecast steps, and when I read it, convert to xarray, then write back to GRIB, all the values are NaN. If I filter just a single step, then it works perfectly - the only differences are those you would expect when converting from GRIB 1 to GRIB 2, e.g. bounding box coords in microdegrees instead of millidegrees, etc.
Here's the code:
And the data is attached.
User_Guide_Example_Data.grib.tar.gz
alexamici commentedon Sep 21, 2018
@iainrussell that's an interesting GRIB file:
It contains a 48h forecast and the analysis for the date 1996-04-28T12:00:00.
The GRIB file is not a complete hypercube so cfgrib correctly fills the missing fields with
np.nan:The problem is that
np.nanwere not handled in cfgrib and ecCodes doesn't support them.In
masternow invalid values are set tomissingValuebefore being sent to ecCodes and as an optimisation fields entirely comprised ofnp.nanare not written to disk at all.Now the saved GRIB looks like this:
iainrussell commentedon Sep 21, 2018
@alexamici - thanks for the very quick response! I can confirm that the code in the master branch works perfectly for this file now, and I plotted the fields with metview to check that they look identical (they do)!
iainrussell commentedon Sep 24, 2018
Still looking good, I'm now checking more 'awkward' subarea definitions like this one, which plots correctly:

I'm using this Metview script to do it quite easily:
compare_grib_plots.py.tar.gz
alexamici commentedon Nov 12, 2018
Note that right now
mastercan re-write to disk most opened GRIB files, because we use theGRIB_attributes read in input.Doing an operation on the resulting
xr.Datasetbut keeping the attributes may make them incoherent. We apply some check and autodetect the values only in the limited set of cases described in the issue text.We consider write support in Alpha
alexamici commentedon Jan 1, 2019
Note that with 90c8106 very generic GRIB files can be written when setting the all the
GRIB_keys correctly. See #39 .AhmedMIssawi commentedon Jun 4, 2021
hi, can you help me with this code
import cfgrib
import xarray as xr
import pandas as pd
import sys
import glob
import os
def Grib2files():
data = Grib2files()
I am trying many ways to make this data to 2 d data
hybrid with all latitudes and fixed altitude and slice over time because this data is 1 file per hour and I need to run this for a whole year
xvxiuwen commentedon Jul 8, 2022
sorry to bother you, but when i run code 'dst = xarray_store.GribDataStore.from_path("User_Guide_Example_Data.grib")',the computer warns there is no attribute 'GribDataStore'. my computer is windows platform and i download xarray and cfgrib in anaconda.
xvxiuwen commentedon Jul 8, 2022
zxdawn commentedon Dec 8, 2022
Another error:
Update
We should import to_grib using the newest name.
dasarkisov commentedon Jun 4, 2024
Hi! I have an issue with writing grib files. Here I open two grib datasets, sum them up, and write the resulting dataset to grib file; then I open the new grib as dataset.
During the writing I get the following warning:
FutureWarning: GRIB write support is experimental, DO NOT RELY ON IT! warnings.warn("GRIB write support is experimental, DO NOT RELY ON IT!", FutureWarning)
failed to set key 'endStep:int' to 0
failed to set key 'stepUnits:int' to 1
Here are the three datasets, from left to right: the original one, the resulting one, and the resulting one after writing to grib

Here you can see that after the writing:
Why do the changes take place during the writing? When I open the newly created grib file with the viewer the temperature represents to be the surface temperature (0 altitude), while originally it is 2m temperature.
Thanks!
UPDATE

Okay, what I've done was adding "heightAboveGround" option in https://github.com/ecmwf/cfgrib/blob/master/cfgrib/xarray_to_grib.py:
Now the to_grib() detects the altitude coordinate heightAboveGround and properly writes it to grib file, preserving its value, which is in my case 2.0:

The data variable name still gets changed (t2m to t), but that's no big deal. The written grib file now is being properly read via grib viewer, with t data variable represented as 2m-altitude temperature!
Dependabot alerts #18: py