ecmwf / cfgrib

A Python interface to map GRIB files to the NetCDF Common Data Model following the CF Convention using ecCodes
Apache License 2.0
400 stars 77 forks source link

Why does variable names different while reading in cfgrib? #269

Closed krishnaap closed 2 years ago

krishnaap commented 2 years ago

I am trying to read GFS grib data using cfgrib and xarray, but the variable names show differently on cfgrib and on panoply. While reading surface data,

                     engine='cfgrib', 
                     backend_kwargs={'filter_by_keys': {'typeOfLevel': 'surface'}})```
it shows like 

ds2 Out[241]:

Dimensions: (latitude: 721, longitude: 1440) Coordinates: time datetime64[ns] ... step timedelta64[ns] ... surface float64 ... * latitude (latitude) float64 90.0 89.75 89.5 89.25 ... -89.5 -89.75 -90.0 * longitude (longitude) float64 0.0 0.25 0.5 0.75 ... 359.2 359.5 359.8 valid_time datetime64[ns] ... Data variables: (12/24) vis (latitude, longitude) float32 ... gust (latitude, longitude) float32 ... hindex (latitude, longitude) float32 ... sp (latitude, longitude) float32 ... orog (latitude, longitude) float32 ... t (latitude, longitude) float32 ... ... cape (latitude, longitude) float32 ... cin (latitude, longitude) float32 ... 4lftx (latitude, longitude) float32 ... hpbl (latitude, longitude) float32 ... lsm (latitude, longitude) float32 ... siconc (latitude, longitude) float32 ... Attributes: GRIB_edition: 2 GRIB_centre: kwbc GRIB_centreDescription: US National Weather Service - NCEP GRIB_subCentre: 0 Conventions: CF-1.7 institution: US National Weather Service - NCEP history: 2021-11-23T16:33 GRIB to CDM+CF via cfgrib-0.9.9... ``` When I tried to cross-check with the Panoply, it shows variable names differently, ``` netcdf file:/home/krishna/Works/2019_fl/GDAS/gd/gdas1.fnl0p25.2019081312.f00.grib2 { dimensions: lon = 1440; lat = 721; reftime = 1; time = 1; height_above_ground = 1; pressure_difference_layer = 1; isobaric = 29; altitude_above_msl = 3; height_above_ground_layer = 1; height_above_ground_layer1 = 1; isobaric1 = 1; pressure_difference_layer1 = 1; height_above_ground1 = 7; sigma_layer = 4; isobaric2 = 21; isobaric3 = 34; depth_below_surface_layer = 4; height_above_ground2 = 3; isobaric4 = 22; height_above_ground3 = 1; height_above_ground4 = 2; potential_vorticity_surface = 2; pressure_difference_layer2 = 2; isobaric5 = 31; sigma = 1; hybrid = 1; isobaric6 = 24; variables: int LatLon_Projection; :grid_mapping_name = "latitude_longitude"; :earth_radius = 6371229.0; // double float lat(lat=721); :units = "degrees_north"; float lon(lon=1440); :units = "degrees_east"; double reftime; :units = "Hour since 2019-08-13T12:00:00Z"; :standard_name = "forecast_reference_time"; :long_name = "GRIB reference time"; :calendar = "proleptic_gregorian"; double time(time=1); :units = "Hour since 2019-08-13T12:00:00Z"; :standard_name = "time"; :long_name = "GRIB forecast or observation time"; :calendar = "proleptic_gregorian"; float height_above_ground(height_above_ground=1); :units = "m"; :long_name = "Specified height level above ground"; :positive = "up"; :Grib_level_type = 103; // int :datum = "ground"; float pressure_difference_layer(pressure_difference_layer=1); :units = "Pa"; :long_name = "Level at specified pressure difference from ground to level"; :positive = "up"; :Grib_level_type = 108; // int :datum = "ground"; :bounds = "pressure_difference_layer_bounds"; float pressure_difference_layer_bounds(pressure_difference_layer=1, 2); :units = "Pa"; :long_name = "bounds for pressure_difference_layer"; float isobaric(isobaric=29); :units = "Pa"; :long_name = "Isobaric surface"; :positive = "down"; :Grib_level_type = 100; // int float altitude_above_msl(altitude_above_msl=3); :units = "m"; :long_name = "Specific altitude above mean sea level"; :positive = "up"; :Grib_level_type = 102; // int :datum = "mean sea level"; float height_above_ground_layer(height_above_ground_layer=1); :units = "m"; :long_name = "Specified height level above ground"; :positive = "up"; :Grib_level_type = 103; // int :datum = "ground"; :bounds = "height_above_ground_layer_bounds"; float height_above_ground_layer_bounds(height_above_ground_layer=1, 2); :units = "m"; :long_name = "bounds for height_above_ground_layer"; float height_above_ground_layer1(height_above_ground_layer1=1); :units = "m"; :long_name = "Specified height level above ground"; :positive = "up"; :Grib_level_type = 103; // int :datum = "ground"; :bounds = "height_above_ground_layer1_bounds"; float height_above_ground_layer1_bounds(height_above_ground_layer1=1, 2); :units = "m"; :long_name = "bounds for height_above_ground_layer1"; float isobaric1(isobaric1=1); :units = "Pa"; :long_name = "Isobaric surface"; :positive = "down"; :Grib_level_type = 100; // int float pressure_difference_layer1(pressure_difference_layer1=1); :units = "Pa"; :long_name = "Level at specified pressure difference from ground to level"; :positive = "up"; :Grib_level_type = 108; // int :datum = "ground"; :bounds = "pressure_difference_layer1_bounds"; float pressure_difference_layer1_bounds(pressure_difference_layer1=1, 2); :units = "Pa"; :long_name = "bounds for pressure_difference_layer1"; float height_above_ground1(height_above_ground1=7); :units = "m"; :long_name = "Specified height level above ground"; :positive = "up"; :Grib_level_type = 103; // int :datum = "ground"; float sigma_layer(sigma_layer=4); :units = "sigma"; :long_name = "Sigma level"; :positive = "down"; :Grib_level_type = 104; // int :bounds = "sigma_layer_bounds"; float sigma_layer_bounds(sigma_layer=4, 2); :units = "sigma"; :long_name = "bounds for sigma_layer"; float isobaric2(isobaric2=21); :units = "Pa"; :long_name = "Isobaric surface"; :positive = "down"; :Grib_level_type = 100; // int float isobaric3(isobaric3=34); :units = "Pa"; :long_name = "Isobaric surface"; :positive = "down"; :Grib_level_type = 100; // int float depth_below_surface_layer(depth_below_surface_layer=4); :units = "m"; :long_name = "Depth below land surface"; :positive = "down"; :Grib_level_type = 106; // int :datum = "land surface"; :bounds = "depth_below_surface_layer_bounds"; float depth_below_surface_layer_bounds(depth_below_surface_layer=4, 2); :units = "m"; :long_name = "bounds for depth_below_surface_layer"; float height_above_ground2(height_above_ground2=3); :units = "m"; :long_name = "Specified height level above ground"; :positive = "up"; :Grib_level_type = 103; // int :datum = "ground"; float isobaric4(isobaric4=22); :units = "Pa"; :long_name = "Isobaric surface"; :positive = "down"; :Grib_level_type = 100; // int float height_above_ground3(height_above_ground3=1); :units = "m"; :long_name = "Specified height level above ground"; :positive = "up"; :Grib_level_type = 103; // int :datum = "ground"; float height_above_ground4(height_above_ground4=2); :units = "m"; :long_name = "Specified height level above ground"; :positive = "up"; :Grib_level_type = 103; // int :datum = "ground"; float potential_vorticity_surface(potential_vorticity_surface=2); :units = "K m2 kg-1 s-1"; :long_name = "Potential vorticity surface"; :positive = "up"; :Grib_level_type = 109; // int float pressure_difference_layer2(pressure_difference_layer2=2); :units = "Pa"; :long_name = "Level at specified pressure difference from ground to level"; :positive = "up"; :Grib_level_type = 108; // int :datum = "ground"; :bounds = "pressure_difference_layer2_bounds"; float pressure_difference_layer2_bounds(pressure_difference_layer2=2, 2); :units = "Pa"; :long_name = "bounds for pressure_difference_layer2"; float isobaric5(isobaric5=31); :units = "Pa"; :long_name = "Isobaric surface"; :positive = "down"; :Grib_level_type = 100; // int float sigma(sigma=1); :units = "sigma"; :long_name = "Sigma level"; :positive = "down"; :Grib_level_type = 104; // int float hybrid(hybrid=1); :units = "sigma"; :long_name = "Hybrid level"; :positive = "down"; :Grib_level_type = 105; // int float isobaric6(isobaric6=24); :units = "Pa"; :long_name = "Isobaric surface"; :positive = "down"; :Grib_level_type = 100; // int float Absolute_vorticity_isobaric(time=1, isobaric=29, lat=721, lon=1440); :long_name = "Absolute vorticity @ Isobaric surface"; :units = "1/s"; :abbreviation = "ABSV"; :missing_value = NaNf; // float :grid_mapping = "LatLon_Projection"; :coordinates = "reftime time isobaric lat lon "; :Grib_Variable_Id = "VAR_0-2-10_L100"; :Grib2_Parameter = 0, 2, 10; // int :Grib2_Parameter_Discipline = "Meteorological products"; :Grib2_Parameter_Category = "Momentum"; :Grib2_Parameter_Name = "Absolute vorticity"; :Grib2_Level_Type = 100; // int :Grib2_Level_Desc = "Isobaric surface"; :Grib2_Generating_Process_Type = "Forecast"; :Grib2_Statistical_Process_Type = "UnknownStatType--1"; float Apparent_temperature_height_above_ground(time=1, height_above_ground3=1, lat=721, lon=1440); :long_name = "Apparent temperature @ Specified height level above ground"; :units = "K"; :abbreviation = "APTMP"; :missing_value = NaNf; // float :grid_mapping = "LatLon_Projection"; :coordinates = "reftime time height_above_ground3 lat lon "; :Grib_Variable_Id = "VAR_0-0-21_L103"; :Grib2_Parameter = 0, 0, 21; // int :Grib2_Parameter_Discipline = "Meteorological products"; :Grib2_Parameter_Category = "Temperature"; :Grib2_Parameter_Name = "Apparent temperature"; :Grib2_Level_Type = 103; // int :Grib2_Level_Desc = "Specified height level above ground"; :Grib2_Generating_Process_Type = "Forecast"; :Grib2_Statistical_Process_Type = "UnknownStatType--1"; float Cloud_mixing_ratio_isobaric(time=1, isobaric4=22, lat=721, lon=1440); :long_name = "Cloud mixing ratio @ Isobaric surface"; :units = "kg/kg"; :abbreviation = "CLWMR"; :missing_value = NaNf; // float :grid_mapping = "LatLon_Projection"; :coordinates = "reftime time isobaric4 lat lon "; :Grib_Variable_Id = "VAR_0-1-22_L100"; :Grib2_Parameter = 0, 1, 22; // int :Grib2_Parameter_Discipline = "Meteorological products"; :Grib2_Parameter_Category = "Moisture"; :Grib2_Parameter_Name = "Cloud mixing ratio"; :Grib2_Level_Type = 100; // int :Grib2_Level_Desc = "Isobaric surface"; :Grib2_Generating_Process_Type = "Forecast"; :Grib2_Statistical_Process_Type = "UnknownStatType--1"; float Cloud_mixing_ratio_hybrid(time=1, hybrid=1, lat=721, lon=1440); :long_name = "Cloud mixing ratio @ Hybrid level"; :units = "kg/kg"; :abbreviation = "CLWMR"; :missing_value = NaNf; // float :grid_mapping = "LatLon_Projection"; :coordinates = "reftime time hybrid lat lon "; :Grib_Variable_Id = "VAR_0-1-22_L105"; :Grib2_Parameter = 0, 1, 22; // int :Grib2_Parameter_Discipline = "Meteorological products"; :Grib2_Parameter_Category = "Moisture"; :Grib2_Parameter_Name = "Cloud mixing ratio"; :Grib2_Level_Type = 105; // int :Grib2_Level_Desc = "Hybrid level"; :Grib2_Generating_Process_Type = "Forecast"; :Grib2_Statistical_Process_Type = "UnknownStatType--1"; // global attributes: :Originating_or_generating_Center = "US National Weather Service, National Centres for Environmental Prediction (NCEP)"; :Originating_or_generating_Subcenter = "0"; :GRIB_table_version = "2,1"; :Type_of_generating_process = "Forecast"; :Analysis_or_forecast_generating_process_identifier_defined_by_originating_centre = "Analysis from GFS (Global Forecast System)"; :file_format = "GRIB-2"; :Conventions = "CF-1.6"; :history = "Read using CDM IOSP GribCollection v3"; :featureType = "GRID"; } ``` I think the same variable I saw on Panoply is seen in GrADS as well. I think cfgrib shows the variable names very differently from others. How to solve this issue and verify I m using the right variable?
iainrussell commented 2 years ago

Hello @krishnaap,

Panoply and cfgrib use different GRIB decoders. A GRIB field does not itself contain a human-readable description of a variable, but instead something like parameter-number=232:114. It is then up to the decoder to have tables that translate this into strings such as 'Temperature'. cfgrib uses the ecCodes decoder, which translates these parameters into two different strings - the 'name' is a long string such as 'Temperature', and 'shortName' is an abbreviation, such as 't'. We decided it was nicer to use the shortName for the variable names in cfgrib. But even the longer name does not have to match what Panoply uses - it is up to each GRIB decoder to decide the exact name for any given parameter. If you want to inspect the GRIB data further and understand better what each variable is, you can print the details like this:

print(ds2.gust)

This will also give you the 'cf' name, which might more closely match what Panoply gives.

Best regards, Iain