NCEP Home > NCO Home > Systems Integration Branch > Decoders > BUFRLIB > BUFRLIB Table of Contents > Encoding rawinsonde BUFR messages|
Printer Friendly Version
Example Program: Encoding rawinsonde BUFR messages
In this example, we will be encoding (i.e. writing) BUFR messages according
to the "RAWINSONDE - FIXED LAND" format listed within our
sample DX BUFR tables file.
In effect, this means that we will be writing data subsets that are
described by the Table A mnemonic "NC002001".
However, rather than getting
bogged down in the details of actual rawinsonde data values from actual
past archive cases, we will
instead provide a rough "framework" for how such an encoding program might
be structured and, in turn, provide comments and other clarification where
such particulars would likely prove most useful.
Further, we will also use subroutine WRITSA
in order to demonstrate the interfacing of the BUFRLIB software with
an array in memory, whereby encoded BUFR messages are passed back to the
application program for specialized output or other purposes:
PARAMETER ( MXMN = 15 )
PARAMETER ( MXLV = 255 )
REAL*8 r8arr ( MXMN, MXLV ),
PARAMETER ( MXBF = 16000 )
PARAMETER ( MXBFD4 = MXBF / 4 )
INTEGER ibfmsg ( MXBFD4 )
EQUIVALENCE ( cval, rval )
C* Open the BUFR messages file.
OPEN ( UNIT = 11, FILE = 'bufrmsgs.out' )
C* Open the BUFR tables file.
OPEN ( UNIT = 12, FILE = 'bufrtab.example' )
C* Associate the tables file with the messages file, and identify
C* the latter to the BUFRLIB software.
CALL OPENBF ( 11, 'OUT', 12 )
DO WHILE ( there are rawinsonde reports to be encoded )
idate = ( ( year of report ) * 1000000 ) +
+ ( ( month of report ) * 10000 ) +
+ ( ( day of report ) * 100 ) +
+ ( hour of report )
C* Open a rawinsonde BUFR message in order to store the new
C* data subset (i.e. report).
CALL OPENMB ( 11, 'NC002001', idate )
C* Store the report date-time within the data subset.
r8arr (1,1) = ( year of report )
r8arr (2,1) = ( month of report )
r8arr (3,1) = ( day of report )
r8arr (4,1) = ( hour of report )
CALL UFBSEQ ( 11, r8arr, MXMN, 1, nlv, 'UARTM' )
C* Store the station identification information within the
C* data subset.
cval = ( station ID, e.g. '72403', 'DBBH', etc.)
r8arr (1,1) = rval
r8arr (2,1) = ( station latitude )
r8arr (3,1) = ( station longitude )
r8arr (4,1) = ( station elevation )
CALL UFBINT ( 11, r8arr, MXMN, 1, nlv,
+ 'RPID CLAT CLON SELV' )
C* Store the level data within the data subset.
nlvst = ( number of data levels to be stored)
DO jj = 1, nlvst
r8arr (1,jj) = ( vertical significance for level jj )
r8arr (2,jj) = ( pressure, in Pascals, for level jj )
r8arr (3,jj) = ( geopotential for level jj )
r8arr (4,jj) = ( temperature, in K, for level jj )
r8arr (5,jj) = ( dew point, in K, for level jj )
r8arr (6,jj) = ( wind direction for level jj )
r8arr (7,jj) = ( wind speed, in m/s, for level jj )
CALL UFBINT ( 11, r8arr, MXMN, nlvst, nlv,
+ 'VSIG PRLC GP10 TMDB TMDP WDIR WSPD' )
( store any other available values in a similar manner )
C* Once all data values have been stored for this data subset,
C* we are now ready to store the data subset into the message.
CALL WRITSA ( 11, MXBFD4, ibfmsg, libf )
IF ( libf .gt. 0 ) THEN
( write BUFR message ibfmsg (1,2,...,libf) to local system )
C* Forcibly flush the last BUFR message, if any, from the
C* BUFRLIB software.
CALL WRITSA ( -11, MXBFD4, ibfmsg, libf )
IF ( libf .gt. 0 ) THEN
( write BUFR message ibfmsg (1,2,...,libf) to local system )
CALL CLOSBF ( 11 )
( perform any other necessary local shutdown tasks )
In the above program example, the first thing that is done is to associate
logical unit numbers with our BUFR messages and tables files via the FORTRAN
OPEN statement, and then a call is made to subroutine
OPENBF in order to
associate these two files. The argument 'OUT' to
OPENBF designates the
messages file (i.e. logical unit #11) as an output file, and, even though we
will be using subroutine
WRITSA to return the encoded BUFR messages back to
the application program, copies of these same messages will nonetheless still
be written to this file! If, on the other hand, we had wanted for the file
associated with logical unit #11 to truly be a placeholder "dummy" file, we
could have used the argument 'NUL' in place of 'OUT'. But, in either case, the
next step is to set up a looping mechanism to continuously encode each new
rawinsonde report into BUFR, until there are no more reports to encode.
For each report, the first step within this loop is to, using the date-time
associated with the report, compute the idate value
that will be stored by subroutine
OPENMB within Section 1 of the BUFR message containing
this report (i.e. BUFR data subset). Since
OPENMB will only open a new BUFR message when
the current subset has a different csubset or
idate value than the previous one,
and since csubset is always fixed as
"NC002001" in this case,
then the variability of the idate value between subsequent
data subsets will entirely determine how many data subsets are packed into each
individual BUFR message. Further, whenever a new
BUFR message is opened, the previous one will be closed and made available to
the application program upon the next subsequent call to subroutine
At any rate, once
OPENMB has been called for the data subset, the next step is
to begin storing all of the available data values that are to be encoded.
First, the report date-time information is stored directly into the subset via
a call to subroutine
UFBSEQ, and then the station identification information
is stored using subroutine
UFBINT. In either case, the order with which the
corresponding data values are stored within array r8arr
must match the order in which the respective mnemonics are listed within the final
(i.e. CMNSTR) call argument to these routines.
Further, data values must be stored in
r8arr using the units that were defined for that
corresponding mnemonic within the BUFR tables file "bufrtab.example", and, for any data
values which are desired
to be encoded as "missing" within BUFR, the value of 10.0E10 should be stored.
In particular, note that the storing of the station ID itself, which has units
"CCITT IA5" (i.e. ASCII), is done via an EQUIVALENCE to the REAL*8 value rval.
Moving on, the example then shows how the multi-level data within a rawinsonde
report might be encoded, by using a second looping mechanism to store the
pertinent data for each level
jj of the report within row
jj of r8arr.
value 10.0E10 should be stored for any value that is to be designated as
"missing" within any level of BUFR; however, note that the subsequent call to subroutine
UFBINT will only read and store the first nlvst rows of the r8arr
array (as indicated by passing in this value nlvst
as the fourth call argument!),
and, therefore, it is not necessary to pre-initialize the entire r8arr
array to the 10.0E10 "missing" value before beginning to store actual values!
At any rate, at this point more data values can be stored, if desired, for this
particular report, using similar calls to
UFBREP, etc.; however,
it is important to note that, if a data value for a particular mnemonic is
never stored using one of these routines, the BUFRLIB software will
automatically encode the corresponding value as "missing" in BUFR.
Therefore, it is not necessary to store a data value for every possible
mnemonic within a data subset; rather, the application program only ever needs
to call one of the above subroutines for mnemonics which have actual,
non-"missing" corresponding data values.
Finally, once all desired data values have been stored for a particular
data subset, a call to
WRITSA tells the BUFRLIB software that this subset is
ready to be encoded and packed into the current BUFR message within the
internal arrays, and, if a previous BUFR message is waiting to be returned
to the application program, this will be done as well when
In either case, we then go back to the top of the main loop and repeat the
process all over again for the next rawinsonde report, until there are no more
rawinsonde reports to be encoded, and in which case we then do a final call to
WRITSA to flush out the last BUFR message from the
BUFRLIB software (note the use of -11 as the first call argument!) before calling
CLOSBF and otherwise
ending the application program. Note that it would also be a good idea to make
an additional call to subroutine
STNDRD for each encoded BUFR message returned by
especially if such messages were to be later shared or exchanged with
persons and/or organizations not using the NCEP BUFRLIB software!
However, an even easier way to accomplish the same result would be to
instead add the following line of code:
CALL STDMSG ( 'Y' )
immediately following the call to OPENBF in the
above example program, and then subroutine STNDRD
would be called internally within the BUFRLIB software, meaning that the
BUFR messages subsequently output via calls to
subroutine WRITSA would already be standardized!