I am trying to save multiple GeoTIFF files from a GRIB file I have elaborated.

Before converting to raster, the GRIB file I started with is a ERA5 2m hourly temperature over 3 days:

import iris

# Load the GRIB file using iris
cubes = iris.load('download_for_et0.grib')


air_temperature / (K)               (time: 72; latitude: 20; longitude: 28)
    Dimension coordinates:
        time                             x             -              -
        latitude                         -             x              -
        longitude                        -             -              x
    Auxiliary coordinates:
        forecast_period                  x             -              -
    Scalar coordinates:
        height                      2 m
        originating_centre          European Centre for Medium Range Weather Forecasts

From this, I calculate the daily mean and save as a new GRIB file:

# 1st step: Create an auxialiary coordinate
iris.coord_categorisation.add_day_of_year(cube, "time", name="day of year")

# 2nd step: Mean over the auxiliary coordinate  
daily_Tmean = cube.aggregated_by(["day of year"], iris.analysis.MEAN)

#3rd step: Fix cell_methods   
method = iris.coords.CellMethod('mean', coords=['time'], intervals='1 day')
daily_Tmean.cell_methods = daily_Tmean.cell_methods[:-1]

# 4rd step: Remove the auxiliary coordinate
daily_Tmean.remove_coord("day of year")

air_temperature / (K)               (time: 3; latitude: 20; longitude: 28)
    Dimension coordinates:
        time                             x            -              -
        latitude                         -            x              -
        longitude                        -            -              x
    Auxiliary coordinates:
        forecast_period                  x            -              -
        forecast_reference_time          x            -              -
    Scalar coordinates:
        height                      2.0 m
    Cell methods:
        mean                        time (1 day)
        GRIB_PARAM                  GRIB2:d000c000n000

I want to save this daily_Tmean GRIB file as a series of GeoTIFF files, one per day, with %Y-%m-D% format, for example:


I've tried with iris, xarray and rioxarray with no success, I am missing something for sure.

With iris:

import iris

# Load the GRIB file
grib_file = iris.load_cubes('daily_Tmean.grib')

# Loop through the cubes in the grib_file
for cube in grib_file:
    # Check if the cube has a time coordinate
    if 'time' in cube.coords():
        # Get the time value as a string
        time_str = str(cube.coord('time').points[0])
        # Create a filename using the time value
        filename = './geotiff_' + time_str + '.tif'
        # Save the cube as a geotiff
        iris.fileformats.grib.save_grib2(cube, file_name)

with xarray:

import xarray as xr

# Open the GRIB file using xarray
ds = xr.open_dataset("daily_Tmean.grib", engine='cfgrib')

# Loop through the time variables in the dataset
for time in ds.time:
    # Extract the data for the current time variable
    data = ds.sel(time=time)
    # Save the data as a geotiff file
    data.to_netcdf("file_" + str(time) + ".tif")

# Close the GRIB file

with rioxarray:

import rioxarray

# Open the GRIB file using rioxarray
ds = rioxarray.open_rasterio("daily_Tmean.grib")

# Get the time dimension
time = ds.band

# Loop through each day in the time dimension
for day in time.dt.floor('D'):
    # Select data for the current day
    day_data = ds.sel(time=slice(day, day + np.timedelta64(1, 'D')))
    # Save the data as a separate GeoTIFF file

1 Answer 1


You didn't clearly indicate what's wrong with your code.

My guess is your GRIB file isn't georeferenced. This would mean you should add lat/lon information as a transform to your array before saving it to GeoTiff.

You have an example (for another datasource) here: https://lpdaac.usgs.gov/resources/e-learning/working-ecostress-evapotranspiration-data (look for the 2nd title)

  • I could also point to this geocoding function, also using pyresample: github.com/sertit/eoreader/blob/main/eoreader/products/optical/…
    – remi.braun
    Jan 13 at 14:32
  • @remi-braun The GRIB file has a CRS (EPSG:4326), the iris method returns nothing because the if statement is not true even if there is a "time" variable in the cube; the rioxarray method returns error at 'for day in time.dt.floor('D')' with error 'TypeError: '.dt' accessor only available for DataArray with datetime64 timedelta64 dtype or for arrays containing cftime datetime objects.'; the Jan 13 at 15:37
  • the xarray method returns this error: pastebin.com/p0fSTxn5 Jan 13 at 15:39
  • Yes it can have a CRS, but what is the result of grib.rio.transform() ?
    – remi.braun
    Jan 13 at 16:34
  • And assuming the geocoding is OK, you just have to convert your datetime to datetime.datetime to make it work. Are they in str ?
    – remi.braun
    Jan 13 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.