wgrib2: -rpn
Introduction
The -rpn option runs a reverse polish notation
(RPN)
calculator. Having a built-in calculator is quite handy. We use it to convert
units (ex. geopotential to geopotential meters, accumulations to rates),
compute simple quantities (net flux from downward and upward fluxes),
and even the plant hardiness index from the 2 m temperatures. The goal
of the calculator is to reduce the need to write simple fortran programs that
handle grib2 files.
The "hardware" of the rpn calculator consists of 10 registers
and a stack (10 entries deep). Each register and stack entry is
an array which is the same size as the current grid size being
processed. So the main difference between the
e -rpn calculator and a store-bought calculator
is that you are working with arrays and the top of the stack is initialized
with the array of grid values from the current grib message.
The 10 registers (0..9) are initialized when wgrib2 is started.
The stack is different, it gets initialized every time
the -rpn option is run. First the stack is cleared
and the grid values (originally from currently processed grib message)
is pushed onto the top of the stack. At the end of the
the -rpn option, the top of the stack is saved
in the grid values unless the stack has been emptied. To save the
calculations, you can save them in a register or write them out
by -grib_out, -bin, -ieee, -text, etc.
Uses
- change of units when importing data (gribifying data)
- computations: ex, U,V -> wind speed, wind direction, potential temperature
- merging data
- complex masking of data
- changing units before writing text/ieee files
- removing extreme data values
- finding min and max values
Usage
-rpn "A:B:C:..."
A,B,C,.. = number, function, or operator
Operators and Functions:
Pop X, Push Fn(X)
- abs: absolute value
- acos: arc cos, [0, pi] radians
- alt_x_scan: changes alternate x scanning to regular x scanning and vice versa
- asin: arc sin, [-pi/2, pi/2] radians
- atan: arc tan, [-pi/2, pi/2] radians, see atan2
- abs: absolute value
- ceil: smallest integer >= X
- cos: cosine
- exp: e^X
- floor: largest integer <= X
- ln: natural logorithm
- sin: sine
- sq: X*X
- sqrt: square root
- tan: tangent
- yrev: for nx-ny grids, changes we:sn to we:ns and vice versa
- 1/x: 1/X
Pop Y, Pop X, push Fn(X,Y)
- +: push X+Y
- -: push X-Y
- *: push X*Y
- /: push X/Y
- <: push X < Y (1/0 if true/false)
- <=: push X <= Y (1/0 if true/false)
- ==: push X == Y (1/0 if true/false)
- !=: push X != Y (1/0 if true/false)
- >=: push X >= Y (1/0 if true/false)
- >: push X > Y (1/0 if true/false)
- atan2: push arctan(X/Y), [-pi, pi] radians, see atan
- pow: push X**Y (X^Y)
- mask: if (Y != 0) push(X) else push(UNDEFINED)
- max: push max(X,Y)
- merge: if (Y != UNDEFINED) push(Y) else push(X)
- min: push min(X,Y)
Note: an operation involving an UNDEFINED is UNDEFINED
Stack Operators:
- clr, clear the stack
- dup, duplicate the top of the stack
- pop, remove the top of the stack
- exc/swap, exchange the top 2 stack entries
Register Operators:
- clr_I, clear register I, I=0,1..,9
- rcl_I, push register I on top of stack, I=0,1..,9
- sto_I, save top of stack in register I, I=0,1..,9
- rcl_lat, push latitudes onto the top of the stack
- rcl_lon, push longitudes onto the top of the stack
Variables and Constants: put on the top of the stack
- number number = floating point or integer number like 0, 10.1, -1.23e-4
- days_in_ref_month number of days in the month for the reference date (conversion between monthly acc. and rates)
- days_in_verf_month number of days in the month for the verification time (conversion betwee monthly acc. and rates)
- pi 3.1415....
- rand random number uniformly distributed between 0 and 1, each grid point has a different random number
Printing Operators:
- print_corr, write cosine weighted spatial correlation
- print_max, print_min
- print_rms, write cosine weighted RMS
Examples
The standard units of grib temperature is K but you want the text output in Celcius.
$ wgrib2 a.grb -match ":TMP:850 mb:" -rpn "273.15:-" -text C.dat
Fahrenheit is easy too (F = (K-273.15)*9/5+32).
$ wgrib2 a.grb -match ":TMP:850 mb:" -rpn "273.15:-:9:*:5:/:32:+" -text F.dat
Suppose you want to limit the relative humidity values to 100. This example only
affect the RH fields. All submessages will be converted into messages.
$ wgrib2 a.grb -if ":RH:" -rpn "100:min" -fi -grib_out out.grb -not_if ":RH:" -grib out.grb
Write out the 500 mb wind speed.
$ wgrib2 a.grb -match ":[UV]grd:500 mb:" \
-if ":UGRD:" -rpn "sto_1" -fi \
-if ":VGRD:" -rpn "sto_2" -fi \
-if_reg 1:2 \
-rpn "rcl_1:sq:rcl_2:sq:+:sqrt:clr_1:clr_2" \
-set_var WIND \
-grib_out out.grb
line 1: only process the U and V at 500 mb
line 2: store U 500mb in register 1
line 3: store V 500mb in register 2
line 4: if (register 1 and register 2 have values then
line 5: calculate the wind speed: sqrt(reg_1**2 + reg_2**2)
line 6: set variable time to WIND (wind speed)
line 7: write out the WIND data to a grib file
Note: this is a very simple script and that doesn't check the matching
date code, grid type, etc.
Note: there are options to calculate wind speed and wind direction
Suppose someone made a mistake and the latent heat flux (LHTFL) had the wrong sign. RPN to the rescue.
$ wgrib2 a.grb -match ":LHTFL:" -rpn "-1:*" -grib_out new_lhtfl.grb
You could fix the entire file by
$ wgrib2 a.grb -if ":LHTFL:" -rpn "-1:*" -fi -grib_out new.grb
It would be faster if you only compressed the LHTFL fields. (-grib uses the
original compressed data and -grib_out uses the "data" register.)
$ wgrib2 a.grb -set_grib_type jpeg \
-not_if ":LHTFL:" -grib new.grb -if ":LHTFL:" -grib_out new.grb
If both the latent and sensible heat fluxes needed a sign reversal, you could do,
$ wgrib2 a.grb -if ":(LHTFL|SHTFL):" -rpn "-1:*" -fi -grib_out new.grb
If you want to set certain values to undefined, you define a mask and then
apply the mask. In this example, values below 20 are set to undefined.
$ wgrib2 a.grb -rpn "dup:20:>=:mask" -grib_out -set_grib_type c3 new.grb
The RPN calculator is used:
dup the data is duplicated
20 20 is pushed on the stack
>= test data >= 20, top of stack is 1/0 depending on test >= 20
mask apply mask to the data
-set_grib_type c3 sets the grib compression to complex3
-grib_out new.grb writes a grib message using the decoded data
Don't forget to enclose the argument to rpn in quotes because the shell can do unexpect things.
Printing operators
print_corr write cosine weighted spatial correlation R(TOP-1), R(TOP)
print_max write max(R(TOP)) to stdout
print_min write min(R(TOP)) to stdout
print_rms write cosine weighted RMS(R(TOP-1)-R(TOP))
Comments
Warning: Reverse Polish notation can cause headaches if you try something
too complicated.
The -rpn option is a piece of easy to
understand and modify code (RPN.c). If you want to add
a specialized function (ex. wind chill calculation), you many
consider adding it to the RPN calculator. Then you could do
something like
$ wgrib2 IN.GRB -if ":ARG1:" -rpn "sto_1:*" -fi \
-if ":ARG2:" -rpn sto_2 -fi \
-if ":ARG3:" -rpn sto_3 -fi \
-if_reg 1:2:3 -rpn NEW_FUNCTION:clr_1:clr_2:clr_3: -set_var VAR \
-set_lev LEV -quit -grib_out OUT.GRB
NEW_FUNCTION would be a new rpn function that uses data in register 1, 2 and 3
and leaves the result on the top of the stack.
See also:
-if_reg,
-grib_out,
|