NOAA logo - Click to go to the NOAA homepage National Weather Service NWS logo - Click to go to the NWS homepage
EMC Logo

NCEP Home > EMC Home > BUFRLIB > BUFRLIB Table of Contents > Encoding rawinsonde BUFR messages
Printer image icon. 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 ),
     +			rval

        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 )

	    END DO

	    CALL UFBINT  ( 11, r8arr, MXMN, nlvst, nlv,

	    ( 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 )
	    END IF

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 WRITSA.

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. Again, the 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 UFBINT, UFBSEQ, 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 WRITSA returns. 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 WRITSA, 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!