This note attempts to provide the required understanding to use GRIB data in GrADS.
lon,lat
) chunks of a (in most general sense) 4-D variable
(e.g.,
u comp on the wind = f(lon,lat,level,time)
). The sequence is
commonly organized in files containing all variables at a
particular time (i.e., 3-D (lon,lat,level) volume
).
Thus, "thinned" grids (non rectangular) and spectral coefficients are not supported. However, GRIB versions 1 AND 0 are supported (GRIB 0 data must be filtered to GRIB 1 for wgrib and version 1.7 of GrADS will support such non-rectilinear grids. Further, it IS possible to display "preprojected" GRIB data (e.g., polar stereo fields, see eta.ctl).
The big virtue of wgrib is that the code is written in ANSI C and runs on all the major platforms from PC's to Cray. Although wgrib was designed to support the NCEP reanalysis project, it has been extended to handle other sources of GRIB data (e.g., ECMWF) and is my tool of choice. If I can't read the data in wgrib then I change the code and feed the changes to Wesley Ebisuzaki, NCEP.
Once you have wgrib running,
wgrib ncep.reanl.mo.7901.grb
yields,
1:0:d=79010100:UGRD:kpds5=33:kpds6=100:kpds7=850: TR=113:P1=0:P2=6:TimeU=1:850
mb:anl:ave@6hr:NAve=124
2:15852:d=79010100:UGRD:kpds5=33:kpds6=100:kpds7=500: TR=113:P1=0:P2=6:TimeU=1:500
mb:anl:ave@6hr:NAve=124
3:33018:d=79010100:UGRD:kpds5=33:kpds6=100:kpds7=200: TR=113:P1=0:P2=6:TimeU=1:200
mb:anl:ave@6hr:NAve=124
4:51498:d=79010100:VGRD:kpds5=34:kpds6=100:kpds7=850: TR=113:P1=0:P2=6:TimeU=1:850
mb:anl:ave@6hr:NAve=124
5:66036:d=79010100:VGRD:kpds5=34:kpds6=100:kpds7=500: TR=113:P1=0:P2=6:TimeU=1:500
mb:anl:ave@6hr:NAve=124
6:81888:d=79010100:VGRD:kpds5=34:kpds6=100:kpds7=200: TR=113:P1=0:P2=6:TimeU=1:200
mb:anl:ave@6hr:NAve=124
7:99054:d=79010100:PRES:kpds5=1:kpds6=102:kpds7=0: TR=113:P1=0:P2=6:TimeU=1:MSL:anl:ave@6hr:NAve=124
So we see 7 fields in the file valid at 00Z1jan1979
(d=79010100
).
for,
wgrib ncep.reanl.mo.7902.grb
we find,
1:0:d=79020100:UGRD:kpds5=33:kpds6=100:kpds7=850: TR=113:P1=0:P2=6:TimeU=1:850
mb:anl:ave@6hr:NAve=112
2:15852:d=79020100:UGRD:kpds5=33:kpds6=100:kpds7=500: TR=113:P1=0:P2=6:TimeU=1:500
mb:anl:ave@6hr:NAve=112
3:33018:d=79020100:UGRD:kpds5=33:kpds6=100:kpds7=200: TR=113:P1=0:P2=6:TimeU=1:200
mb:anl:ave@6hr:NAve=112
4:50184:d=79020100:VGRD:kpds5=34:kpds6=100:kpds7=850: TR=113:P1=0:P2=6:TimeU=1:850
mb:anl:ave@6hr:NAve=112
5:64722:d=79020100:VGRD:kpds5=34:kpds6=100:kpds7=500: TR=113:P1=0:P2=6:TimeU=1:500
mb:anl:ave@6hr:NAve=112
6:80574:d=79020100:VGRD:kpds5=34:kpds6=100:kpds7=200: TR=113:P1=0:P2=6:TimeU=1:200
mb:anl:ave@6hr:NAve=112
7:96426:d=79020100:PRES:kpds5=1:kpds6=102:kpds7=0: TR=113:P1=0:P2=6:TimeU=1:MSL:anl:ave@6hr:NAve=112
or the same fields as before, except they are valid at 00z1feb1979
.
To find out about the data grid use,
wgrib -V ncep.reanl.mo.7901.grb
and for the first record you will find:
rec 1:pos 0:date 79020100 UGRD kpds5=33 kpds6=100 kpds7=850
levels=(3,82) grid=2 850 mb anl:ave@6hr:
timerange 113 P1 0 P2 6 nx 144 ny 73 GDS grid 0 num_in_ave 112 missing 0
center 7 subcenter 0 process 80
latlon: lat 90.000000 to -90.000000 by 2.500000
long 0.000000 to -2.500000 by 2.500000, (144 x 73) scan 0 bdsgrid 1
min/max data -12.29 16.86 num bits 12 BDS_Ref -1229 DecScale 2 BinScale 0
lon
) and 73
points in y (lat
). The (1,1) point is located at 90N
and 0E
.
lon,lat
) GRIB fields in a file(s) and the GrADS, 4-D, external-to-the-data,
spatio-temporal data volume (lon,lat,level,time
). In GrADS, the
GRIB-to-4-D volume relationship is defined by the data descriptor
or .ctl
file. The actual relationship is created using the GrADS
utility gribmap
which generates
an "index" or "map" between GrADS variables in the .ctl
file and
the GRIB data.
Before describing the details of gribmap
,
first consider the unix program, grb2ctl
,
written by Wesley Ebisuzaki. This program uses wgrib
to first
create a listing of fields in the GRIB data file, parses the listing for times,
variables, and levels and then outputs a suitable descriptor file.
In our example,
grb2ctl.pl ncep.reanl.mo.7901.grb
yields to standard output,
dset ^ncep.reanl.mo.7901.grb
dtype grib
options yrev
index ^ncep.reanl.mo.7901.grb.gmp
undef -9.99E+33
title ncep.reanl.mo.7901.grb
xdef 144 linear 0 2.5
ydef 73 linear -90 2.5
zdef 3 levels
850 500 200
tdef 1 linear 00Z01jan79 1mo
vars 3
PRES 0 1 ,102,0 Pressure [Pa]
UGRD 3 33 ,100 u wind [m/s]
VGRD 3 34 ,100 v wind [m/s]
endvars
How did grb2ctl
do this? First, only ONE grid was found in
the GRIB data file (defined by dset
) and the script had the
grid geometry built in. Second, variables with multiply levels (3-D or lon,lat,level
)
where DEFINED to have a "level indicator" of 100 (more below). Third, there
was only ONE time in the file and the script SET the time increment to 1mo.
These conditions will often not be present. Thus, the output from grb2ctl
will likely have to be "tweaked" by the good 'ol trial and error method.
In some cases the .ctl
file may have to built "by hand" using
the output from wgrib
, so you'll probably have to know a lot
about GRIB and how gribmap
works in many situations.
The key ingredients in the .ctl
file are:
- grid geometry (xdef,ydef)
- starting time and time increment (tdef)
- variables and "units" parameter
- variable type - "level" or 3-D (zdef) or "surface" (2-D)
The units parameter specifies the GRIB parameters of the variable in the
.ctl
to be used by gribmap
for match GrADS variables
to the fields in the GRIB files. This parameter consists of up to four,
comma-delimited numbers:
VV,LTYPE,(LEVEL),(TRI)
where,
VV
- (Required) The GRIB parameter number (33 = u comp of the
wind, table 2 in John:section 1 page 27, i.e., GRIB Edition 1 (FM 92))
LTYPE
- (Required) The level type indicator (100 = pressure
level, in Table 3 in John:section 1 Page 33)
LEVEL
- (optional) The value of the LTYPE (LTYPE 102 is
mean sea level so LEVEL is 0 for where level is located (1,102,0, 0 is
AT mean sea level)
TRI
- (optional) The "time range indicator" for special
applications (Table 5 in John:section 1 Page 37).
Coming up with the units parameter, the grid geometry and the times is the trick.
Fortunately, gribmap
can
tell us how well the .ctl
mapped the GRIB data to the higher
dimensional, GrADS data view. And, more importantly, the gribmap
process does NOT depend on how the data are actually ordered in the GRIB
file, in either level or variable.
Let's redirect output from grb2ctl.sh
to a .ctl
file, e.g.,
grb2ctl.sh on ncep.reanl.mo.7901.grb > ncep.reanl.mo.ctl
and then run gribmap
.
To reiterate, the gribmap
utility compares each field in the
GRIB file to each variable, at each level and for all times in the .ctl
file and creates an index file telling GrADS WHERE the fields are (or are
not) located in the GRIB data.
With the verbose option on,
gribmap -v -i ncep.reanl.mo.ctl
we get,
Scanning binary GRIB file(s):
ncep.reanl.mo.7901.grb
!!!!!MATCH: 1 15852 2 1 0 33 100 850 btim: 1979010100:00 tau: 0 dtim: 1979010100:00
!!!!!MATCH: 2 33018 2 1 0 33 100 500 btim: 1979010100:00 tau: 0 dtim: 1979010100:00
!!!!!MATCH: 3 51498 2 1 0 33 100 200 btim: 1979010100:00 tau: 0 dtim: 1979010100:00
!!!!!MATCH: 4 66036 2 1 0 34 100 850 btim: 1979010100:00 tau: 0 dtim: 1979010100:00
!!!!!MATCH: 5 81888 2 1 0 34 100 500 btim: 1979010100:00 tau: 0 dtim: 1979010100:00
!!!!!MATCH: 6 99054 2 1 0 34 100 200 btim: 1979010100:00 tau: 0 dtim: 1979010100:00
!!!!!MATCH: 7 116220 2 1 0 1 102 0 btim: 1979010100:00 tau: 0 dtim: 1979010100:00
Reached EOF
ncep.reanl.mo.ctl
. In the case of UGRD
,
a 3-D (lon,lat,level
) variable which we can be sliced in the
vertical with GrADS. However, failure to match will NOT stop GrADS from "working."
If the data was NOT there, GrADS will return a grid with "undefined" values
on display and this state can actually be tested...
The "tweaking" is done by adjusting the .ctl
file until we
get a !!!!! MATCH
for each GRIB field in the data file(s).
I have added a number of options that finely control the mapping process
in gribmap
for NCEP. See
the GrADS document for details (ftp://sprite.llnl.gov/grads/doc/gadoc151.*).
Finally, let's adjust the ncep.reanl.mo.ctl
file to take
advantage of the file naming convention:
dset ^ncep.reanl.mo.%y2%m2.grb
dtype grib
options yrev template
index ^ncep.reanl.mo.gmp
undef -9.99E+33
title ncep.reanl.mo.7901.grb
xdef 144 linear 0 2.5
ydef 73 linear -90 2.5
zdef 3 levels 850 500 200
tdef 2 linear 00Z01jan79 1mo
vars 3
PRES 0 1 ,102,0 Pressure [Pa]
UGRD 3 33 ,100 u wind [m/s]
VGRD 3 34 ,100 v wind [m/s]
endvars
dset ^ncep.reanl.mo.%y2%m2.grb
).
Thus, I have two (or more) data files, but only ONE .ctl
file
and I can now work with the 2-D GRIB data as if they were 4-D (lon,lat,lev,time
)
in GrADS. I also changed the name of the index file to be reflective of the
now 4-D data structure.
To summarize the process:
wgrib
(or gribscan
) to see if the data can
be worked in GrADS;
grb2ctl.sh
or the output from wgrib
to
construct a .ctl
file;
gribmap
in verbose
mode (-v
) to relate the GRIB data to the 4-D structure in
the .ctl
file, and to see how well the map worked; and
!!!! MATCH
from gribmap
.
netCDF
).
We've saved disk space and have minimized potential technical
errors (every time you touch the data you have an opportunity to
screw it up). Second, from a GrADS performance standpoint, GRIB
is nearly as fast as other binary formats -- the cost in
decompression on the fly is compensated by reduced I/O.
In the end, GRIB-to-GrADS interface gives us the advantages of
GRIB (efficient storage, self description and an open,
international format) while overcoming the disadvantages of GRIB
(2-D data and no means to organize to a higher dimension) via the
GrADS 4-D data model. We get the best of both worlds, but only
if we can make the .ctl
file. Hopefully this
document will help
you do this.