Skip Navigation Links weather.gov 
NOAA logo - Click to go to the NOAA homepage National Weather Service   NWS logo - Click to go to the NWS homepage
National Centers for Environmental Prediction
Navigation Bar Left Cap
Navigation Bar End Cap

NCEP Home > NCO Home > Systems Integration Branch > Decoders > BUFRLIB > BUFRLIB Table of Contents > Other Useful Subroutines
Printer image icon. Printer Friendly Version

Other Useful BUFRLIB Subroutines

First, we will discuss how to interface an application program with the BUFRLIB software in a whole new way! Specifically, the reader may recall, from our initial discussion, that the BUFRLIB software normally reads/writes BUFR messages directly from/to a BUFR file that is physically stored on the local system and interfaced to the software via logical unit number LUBFR. However, it is also possible to read/write these same BUFR messages directly from/to a memory array within the application program itself, in order to provide users with greater flexibility from an input/output perspective:

	CALL READERME  ( IBFMSG, LUBFR, CSUBSET, IDATE, IRET )

	Input argument:
	    IBFMSG	INTEGER(*)	BUFR message
	    LUBFR	INTEGER		Logical unit for BUFR file

	Output arguments:
	    CSUBSET	CHAR*(*)	Table A mnemonic for IBFMSG
	    IDATE	INTEGER		Section 1 date-time for IBFMSG
	    IRET	INTEGER		Return code:
					  0 = normal return
					 -1 = could not read IBFMSG

This subroutine looks and behaves a lot like the already-familiar READMG, except that here we have one additional input argument IBFMSG which contains the BUFR message to be read by the software. As such, READERME can be used in any context in which READMG might otherwise be used, and, further, from that point on, the application program can proceed with the usual calls to READSB (and, subsequently UFBINT, UFBREP, UFBSEQ, etc.!), just as though READMG had previously been used, so that there is no further modification required within the application program in order to use this input mechanism!

However, do note that, when using READERME, it is still necessary for the application program to have previously called subroutine OPENBF in order to associate a BUFR tables file with the messages that are being input via IBFMSG and that, therefore, it is still also necessary to pass in the relevant LUBFR value as a call argument to READERME even though, in this case, the software will not actually try to read from the associated logical unit! Note also that, for READERME, the meaning of the output argument IRET is subtly different than was the case for READMG, in that a return value of -1 now simply indicates that the particular input BUFR message in question could not be successfully read for some reason but that the interface to the BUFRLIB software remains open and, therefore, subsequent calls to READERME with new input BUFR messages may still be attempted!

Now, for the opposite case where we wish to output encoded messages from the BUFRLIB software back into the application program, we have:

	CALL WRITSA  ( LUBFR, IBFMSG, LIBFMSG )

	Input argument:
	    LUBFR	INTEGER		Logical unit for BUFR file

	Output arguments:
	    IBFMSG	INTEGER(*)	BUFR message
	    LIBFMSG	INTEGER		Length of IBFMSG
This subroutine is designed to be called in the same context as the already-familiar WRITSB, in that it indicates to the BUFRLIB software that all of the necessary data values for the current data subset have been stored via appropriate preceding calls to UFBINT, UFBREP, etc. and that, therefore, the subset is ready to be encoded and packed into the current message for the BUFR file associated with logical unit LUBFR. However, in the case of WRITSA, each completed BUFR message is passed back to the application program within the array IBFMSG, and the second output argument LIBFMSG indicates the number of array elements of IBFMSG that are occupied by the message. Furthermore, when using WRITSA, it becomes important to realize that, since the BUFRLIB software is designed to pack as many data subsets as possible into each message, not every call to WRITSA will result in a message being returned! In such cases, the second output argument LIBFMSG will contain the value 0, indicating that no message (or, more literally, a message of length 0!) was returned. In other words, only when LIBFMSG contains a value greater than 0 is there a BUFR message within array IBFMSG; otherwise, the message into which the data subset was packed remains internally within BUFRLIB so that future data subsets can be packed into it as well, and the message will eventually be returned during some other future call to WRITSA. This, however, leads to the question of what to do if we have no more data subsets to store and thus were not planning to make any more future calls to WRITSA from the application program! Put another way, how do we retrieve that last message that still remains internally within BUFRLIB before we exit our application program? The answer is to call WRITSA one last time, but in a special way. Specifically, if we call WRITSA with the input argument LUBFR set to the additive inverse of its usual value (i.e. (-1) * LUBFR), then this is a signal to WRITSA that we are not storing a new data subset but, rather, wish to forcibly retrieve the current internal BUFR message associated with logical unit LUBFR. By doing this, we are assured that all BUFR message output has been returned to the application program! Note, however, that a similar special final call is never required for WRITSB (i.e. which is used when directing output BUFR messages to a file on the local system), because, as was discussed earlier, the subsequent required call to CLOSBF for logical unit LUBFR will assure that all available BUFR output is properly flushed to that logical unit before closing the associated file! In fact, this brings up another important point, which is to say that, even when we are using WRITSA instead of WRITSB and are, therefore, receiving the output BUFR messages via a memory array within the application program, these messages are nonetheless still also being written out to the file associated with LUBFR, just like when we are using WRITSB! This rather surprising fact is due solely to the overall design of the BUFRLIB software; however, there is a way around this problem for the user who does not need or wish to allocate an actual file to hold this extra copy of the BUFR output. Specifically, the solution is to use the special input string of 'NUL' (rather than 'OUT') for the CIO call argument to OPENBF when identifying this LUBFR to the BUFRLIB software. That way, even though LUBFR must still contain a unique integer value, the BUFRLIB software will never actually try to write anything out to that logical unit number, and thus there is no need for an actual file to be associated with that LUBFR value on the local system!

As a final note, before we leave this overall discussion on interfacing BUFRLIB with a memory array in an application program, the reader may have noticed that, for both of the above subroutines, the IBFMSG call argument, whereby the BUFR message is actually passed into or out of the BUFRLIB software (depending on the case!), is an INTEGER array, rather than a CHARACTER array as might be expected. This is due solely to the way that the BUFRLIB software functions internally, but a user can easily overcome this issue, if necessary, via an appropriate EQUIVALENCE between an array of each type within the application program itself.


Now, here are some additional subroutines that might be of interest:

	CALL DATELEN  ( LEN )

	Input argument:
	    LEN		INTEGER		Length of Section 1 date-time values to
					be output by message-reading subroutines
					such as READMG, READERME, etc.
					  8 =   YYMMDDHH (i.e. 2-digit year)
					 10 = YYYYMMDDHH (i.e. 4-digit year)

This subroutine allows the user to specify the format for the IDATE output argument that is returned by each subsequent call to any of the subroutines, such as READMG or READERME, which read BUFR messages from a BUFR file that is open for input. This subroutine may be called at any time from the user's application program in order to set or reset this date-time format accordingly, and in which case the new format will then apply for all future calls to any of the message-reading subroutines (or until it is changed again via a new call to DATELEN!). Alternatively, if DATELEN is never called, then a default value of LEN = 8 (i.e. YYMMDDHH) applies.

Note that, in the case of a BUFR file that is open for output, there is no need to ever call this subroutine, because the corresponding message-writing subroutines such as OPENMB and OPENMG will automatically accept the IDATE argument in either format (i.e. YYMMDDHH or YYYYMMDDHH) without any special effort on the part of the application program!


	CALL READNS  ( LUBFR, CSUBSET, IDATE, IRET )

	IRET = IREADNS  ( LUBFR, CSUBSET, IDATE )

	Input argument:
	    LUBFR	INTEGER		Logical unit for BUFR file

	Output arguments:
	    CSUBSET	CHAR*(*)	Table A mnemonic for data subset
	    IDATE	INTEGER		Section 1 date-time for data subset
	    IRET	INTEGER		Return code:
					  0 = normal return
					 -1 = no more BUFR data subsets in LUBFR

Subroutine READNS (or its corresponding functional equivalent IREADNS) provides a handy way to combine the functionalities of READMG/IREADMG and READSB/IREADSB into one simple call. The application program needs only to make the initial call to OPENBF in order to define the BUFR file that is to be read, and then each subsequent call to READNS (or IREADNS) will read the next new BUFR data subset from that file, all the while automatically opening and closing each new BUFR message as needed, so that subsequent calls may be immediately made to the data values routines such as UFBINT, UFBSEQ, etc. At first, the concept of READNS/IREADNS may seem somewhat puzzling, since the call sequence is identical to that of READMG/IREADMG, which, as we've already seen, functions at the BUFR message level rather than the BUFR data subset level. However, the reader may also recall, from the discussion of subroutines OPENMG and OPENMB, that every BUFR data subset within a particular BUFR message must always have identical CSUBSET and IDATE values, and, in that context, it does make sense.


	CALL UFBTAB  ( LUBFR, R8ARR, MXMN, MXLV, NSUB, CMNSTR )

	Input arguments:
	    LUBFR	INTEGER		Logical unit for BUFR file
	    CMNSTR	CHAR*(*)	String of blank-separated mnemonics
					associated with R8ARR
	    MXMN	INTEGER		Size of first dimension of R8ARR
	    MXLV	INTEGER		Size of second dimension of R8ARR

	Output arguments:
	    R8ARR(*,*)	REAL*8		Data values read from BUFR file
	    NSUB	INTEGER		Number of data subsets in BUFR file

The call sequence for this subroutine looks similar to that of UFBINT, UFBREP, and UFBSEQ; however, its usage is quite different, in that UFBTAB provides a mechanism whereby a user can do a quick scan of the range of values corresponding to one or more mnemnonics amongst all data subsets for an entire BUFR file, whereas, as we have seen, UFBINT, UFBREP, and UFBSEQ only operate on one data subset at a time! More specifically, UFBTAB opens the input BUFR file connected to logical unit LUBFR (i.e. the application does not itself even have to call subroutine OPENBF!), reads through every BUFR message and data subset in the file, and, for each data subset, decodes (into the next-available row of R8ARR!) the values corresponding to the mnemonics listed within CMNSTR, so that, in the end, the number of rows of R8ARR that are filled with data values is exactly the same as the number of data subsets (i.e. NSUB) that were contained within the BUFR file! The file itself is then automatically disconnected from the BUFRLIB software via an internal call to subroutine CLOSBF; therefore, UFBTAB serves as a convenient "all-in-one" subroutine call for reading specified data values from every data subset within a BUFR file!

There are some caveats, however, so beware! First and foremost, when using UFBTAB, the input value MXLV (and corresponding second dimension of R8ARR!) must now be larger than is normally the case for use with the UFBINT, UFBREP, and UFBSEQ subroutines, since it now must be greater than or equal to the number of data subsets within the overall BUFR file, rather than just large enough to hold the maximum number of replications of any particular mnemonic within a single data subset. In addition, UFBTAB is normally not very useful whenever CMNSTR contains any mnemonic which is repeated or multiply-replicated within each data subset, since, in such cases, only the value corresponding to the first occurrence of that mnemonic will be returned. Finally, since the application program does not itself directly call subroutine OPENBF, then UFBTAB can only be used to read BUFR files which contain embedded BUFR tables information, since there is no way to specify a separate LUNDX value containing the equivalent information in an ASCII text file!

There is a special usage of UFBTAB where it just returns the number of data subsets in the BUFR file (again in NSUB) but with no data value information in the R8ARR array other than the "missing" value. This is accomplished by calling UFBTAB with the first argument LUBFR as a negative number. ABS(LUBFR) still points to the logical unit for the BUFR file, but now MXMN (and corresponding first dimension of R8ARR) and MXLV (and corresponding second dimension of R8ARR) can be set to any positive integer values, since MXMN is no longer dependent upon the number of blank-separated mnemonics in CMNSTR and MXLV is no longer dependent upon the value of NSUB. All MXMN by MXLV values of R8ARR will be filled with "missing" upon return from UFBTAB. Memory-wise, the most efficient usage of UFBTAB in this respect is to call it with MXMN and MXLV both set to 1 and CMNSTR set to a single blank character (' ').


	CALL UFDUMP  ( LUBFR, LUPRT )

	Input arguments:
	    LUBFR	INTEGER		Logical unit for BUFR file
	    LUPRT	INTEGER		Logical unit for print output

This subroutine can be used to dump a verbose print listing of the contents of a data subset from an input BUFR file. The file must already be opened for input via a previous call to subroutine OPENBF, and a data subset must have subsequently been read into the internal BUFRLIB arrays via calls to READMG/IREADMG and READSB/IREADSB (or a single call to READNS/IREADNS!), at which point a call to UFDUMP will then dump a listing of the contents of that data subset to the file pointed to by logical unit LUPRT. This listing contains each mnemonic in the data subset, accompanied by its corresponding FXY number, definition, encoded data value and other potentially useful information such the scale factor, reference value and bit width that were used to encode the value. Therefore, and especially for large BUFR files containing many data subsets, there is the potential for a lot of print output to be generated, so be forewarned! Nevertheless, UFDUMP can be a useful way to quickly look at all of the data values within a subset, especially since, for mnemonics which are replicated, it will list all of the occurrences of that mnemonic, irrespective of the type of replication that was used! Furthermore, for mnemonics whose units are "CCITT IA5", the subroutine will automatically convert the corresponding values from REAL*8 to character and print them as such, and it will even print the descriptive string "MISSING" for all values which were encoded as missing within the corresponding subset!


	CALL DXDUMP  ( LUBFR, LDXOT )

	Input arguments:
	    LUBFR	INTEGER		Logical unit for BUFR file
	    LDXOT	INTEGER		Logical unit for output BUFR tables file

This subroutine provides a handy way to view the BUFR tables information that is embedded in the first few messages of a BUFR file. The user needs only to have identified the file to the BUFRLIB software via a prior call to subroutine OPENBF, and then a subsequent call to subroutine DXDUMP will unpack the embedded tables information and write it out to the file pointed to by logical unit LDXOT. The output file is written using the same ASCII-text table format described within the document Description and Format of BUFR Tables, so it is suitable for use as subsequent input to subroutine OPENBF via the call argument LUNDX. Subroutine DXDUMP can be most useful for learning the contents of archive BUFR files.


	CALL UFBEVN  ( LUBFR, R8ARR, MXMN, MXLV, MXEV, NLV, CMNSTR )

	Input arguments:
	    LUBFR	INTEGER		Logical unit for BUFR file
	    CMNSTR	CHAR*(*)	String of blank-separated mnemonics
					associated with R8ARR
	    MXMN	INTEGER		Size of first dimension of R8ARR
	    MXLV	INTEGER		Size of second dimension of R8ARR
	    MXEV	INTEGER		Size of third dimension of R8ARR


	Output argument:
	    R8ARR(*,*,*)REAL*8		Data values read from data subset
	    NLV		INTEGER		Number of levels of data values
					read from data subset

This subroutine can be used to mimic the effect of a multiple-replication sequence within another multiple-replication sequence, because here our R8ARR array contains a third dimension, which allows for multiple replications of each data value in the otherwise two-dimensional R8ARR array that we looked at earlier during our previous discussion of UFBINT, UFBREP, and UFBSEQ. As was the case with those subroutines, the R8ARR array must be initially declared and dimensioned within the application program, and the input string CMNSTR corresponds to the values in the first dimension of R8ARR. However, there is also an important difference, in that subroutine UFBEVN can only be used when logical unit LUBFR points to a BUFR file that is open for input (i.e. reading). Therefore, the call arguments MXMN, MXLV and MXEV are always input arguments describing the actual dimensions of R8ARR. Furthermore, and despite the addition of a third dimension to the R8ARR array, note that there is no additional corresponding output argument which definitively indicates the number of third-dimension values that were read from the data subset; rather, this information must be indirectly inferred by the application program via direct inspection of the actual values returned within R8ARR.

In a BUFR tables file, the fact that a certain sequence of data values contains three dimensions (and, thus, that UFBEVN may be used to read them!) is indicated by enclosing the sequence within the special indicator characters "[ ]". An example of this is included within the sample program for decoding NCEP PREPBUFR files.


	(integer value) = IUPBS01  ( IBFMSG, S01MNEM )

	(integer value) = IUPVS01  ( LUBFR, S01MNEM )

	Input argument:
	    IBFMSG	INTEGER(*)	BUFR message
	    LUBFR	INTEGER		Logical unit for BUFR file
	    S01MNEM	CHAR*(*)	Mnemonic describing value to be decoded from
                                        within Section 0 or Section 1 of BUFR message:
                                         'LENM'  = Length (in bytes) of BUFR message
                                         'LEN0'  = Length (in bytes) of Section 0
                                         'BEN'   = BUFR edition number
                                         'LEN1'  = Length (in bytes) of Section 1
                                         'BMT'   = BUFR master table
                                         'OGCE'  = Originating center
                                         'GSES'  = Originating subcenter
                                         'USN'   = Update sequence number
                                         'ISC2'  = Flag indicating absence/presence of
                                                   (optional) Section 2 in BUFR message
                                                   0 = Section 2 absent
                                                   1 = Section 2 present
                                         'MTYP'  = Data category
                                         'MSBT'  = Data subcategory (local)
                                         'MSBTI' = Data subcategory (international)
                                         'MTV'   = Version number of master table
                                         'MTVL'  = Version number of local tables
                                         'YEAR'  = Year (4-digit)
                                         'MNTH'  = Month
                                         'DAYS'  = Day
                                         'HOUR'  = Hour
                                         'MINU'  = Minute
                                         'SECO'  = Second

	Output argument:
	    IUPBS1	INTEGER		Decoded value
                                              -1 = invalid S01MNEM input value

Either of these functions can be used to decode and return a specified value from Section 0 or Section 1 of an input BUFR message; the difference is in how the input BUFR message is provided to the function. In the case of IUPBS01, the BUFR message is directly input to the function as an integer array, with the start of the message aligned on the first 4 bytes of the array. Alternatively, IUPVS01 always operates directly on the BUFR message that was most recently read into the internal BUFRLIB arrays from logical unit LUBFR via a call to one of the routines READMG, IREADMG or READERME. In either case, the value to be decoded is specified via the descriptive mnemonic S01MNEM, whose possible values are listed above. Furthermore, either function will work correctly on any BUFR message encoded according to BUFR edition 2, 3 or 4.


	CALL PKVS01 ( S01MNEM, IVAL )

	CALL PKBS1  ( IVAL, IBFMSG, S01MNEM )

	Input argument:
	    IBFMSG	INTEGER(*)	BUFR message
	    IVAL	INTEGER		Value to be encoded within Section 0 or
                                        Section 1 of BUFR message
	    S01MNEM	CHAR*(*)	Mnemonic describing value to be encoded
                                        within Section 0 or Section 1 of BUFR message:
                                         'BEN'   = BUFR edition number
                                         'BMT'   = BUFR master table
                                         'OGCE'  = Originating center
                                         'GSES'  = Originating subcenter
                                         'USN'   = Update sequence number
                                         'MSBTI' = Data subcategory (international)
                                         'MTV'   = Version number of master table
                                         'MTVL'  = Version number of local tables
                                         'MINU'  = Minute
                                         'SECO'  = Second

These subroutines in essence function as the logical inverses of, respectively, IUPVS01 and IUPBS01, in that they allow a user to directly specify a value to be encoded into Section 0 or Section 1 of a BUFR message for output, overriding the default value stored in that same location. As was the case with IUPVS01 and IUPBS01, a descriptive mnemonic S01MNEM is used to specify the value in question, and both subroutines will work correctly on any BUFR message encoded using BUFR edition 2, 3 or 4. However, there are also some subtle differences. First of all, the list of possible values that may be overwritten using these routines (as shown above) is somewhat shorter than the list of possible values that can be decoded using the inverse routines IUPVS01 and IUPBS01. For example, the Section 1 year, month, day and hour values within a message cannot be overwritten using PKVS01 or PKBS1; rather, such values can only be specified via the IDATE call argument to OPENMG or OPENMB, as described within the previous discussion for those subroutines. Likewise, the Section 1 message category and local subcategory must always be specified using an appropriate Table A mnemonic for the message, as described within the discussion on mnemonic types.

Perhaps even more significantly, when using subroutine PKVS01, the new value IVAL actually remains in effect for all future BUFR messages output by any of the BUFRLIB subroutines such as WRITSB or WRITSA that are subsequently called from within the same application program! This means that a user can issue one call to PKVS01 at the beginning of his or her application program and have it remain in effect throughout the life of the application program (or until it is overridden by a subsequent call to PKVS01 with the same S01MNEM value!). Subroutine PKVS01 can even be called prior to the initial call to subroutine OPENBF if it is desired for the new value to also be included in any BUFR table information messages that are to be written to the beginning of the output file!


	CALL UPDS3  ( IBFMSG, CDS3, NDS3 )

	Input argument:
	    IBFMSG	INTEGER(*)	BUFR message

	Output arguments:
	    CDS3	CHARACTER*6(*)	Decoded sequence of FXY numbers
					from within Section 3 of IBFMSG
	    NDS3	INTEGER		Number of FXY numbers within CDS3

This subroutine decodes and returns the complete sequence of FXY numbers from Section 3 of the BUFR message contained within IBFMSG, and, as such, is especially useful in analyzing new or unfamiliar BUFR messages from unknown or unfamiliar sources. Specifically, the information returned by a call to UPDS3 can subsequently be used to generate a BUFR tables file in the ASCII text format required by the BUFRLIB software, and then the BUFRLIB software can itself subsequently be used to read/decode these messages! It should be noted, however, that UPDS3 does not recursively resolve FXY numbers that are themselves Table D (i.e. sequence) FXY numbers; rather, what is returned is the exact sequence of FXY numbers as it appears within Section 3. Note also that, as was the case with IUPBS01, the beginning of the BUFR message must be aligned on the first 4 bytes of the input array IBFMSG.


	CALL GETLENS  ( IBFMSG, LL, LEN0, LEN1, LEN2, LEN3, LEN4, LEN5 )

	Input argument:
	    IBFMSG	INTEGER(*)	BUFR message
            LL          INTEGER         Number of last section whose length is to
                                        be decoded

	Output arguments:
	    LEN0	INTEGER		Length of Section 0
	    LEN1	INTEGER		Length of Section 1
	    LEN2	INTEGER		Length of Section 2
	    LEN3	INTEGER		Length of Section 3
	    LEN4	INTEGER		Length of Section 4
	    LEN5	INTEGER		Length of Section 5

This subroutine takes as input a BUFR message (the start of which, as before, must be aligned on the first 4 bytes of the integer array IBFMSG) and returns the lengths of each of the individual sections of that message, up to a specified point as indicated via the additional input variable LL. For example, setting LL to a value of 3 means that all of the lengths up to and including Section 3 (i.e. Sections 0, 1, 2 and 3) will be decoded. The subroutine will work correctly on any BUFR message encoded using BUFR edition 2, 3 or 4, and any section lengths that are not requested to be decoded are returned with a default value of -1 for the corresponding output argument.


	CALL CNVED4  ( IBFMSG, LOBFMSG, OBFMSG )

	Input argument:
	    IBFMSG	INTEGER(*)	BUFR message encoded using BUFR edition 3
	    LOBFMSG	INTEGER 	Dimensioned size (in integers) of OBFMSG
                                        output array (used by the subroutine to
                                        prevent overflow of this array!)

	Output arguments:
	    OBFMSG	INTEGER(*)	BUFR message encoded using BUFR edition 4

This subroutine reads an input BUFR message encoded using BUFR edition 3 and then generates and outputs an equivalent BUFR message encoded using BUFR edition 4. When using this subroutine, IBFMSG and OBFMSG must be separate arrays. Note also that this subroutine can be very easily activated in an inline fashion for internal BUFR messages that are being generated for writing to an output BUFR file on the local system. Specifically, if subroutine PKVS01 is called with an input S01MNEM value of 'BEN' (i.e. BUFR edition number) and a corresponding input IVAL value of 4, then subroutine CNVED4 will be called internally for all future output BUFR messages written via calls to subroutine WRITSB or WRITSA within the same application program, meaning that all such output BUFR messages will be automatically encoded using BUFR edition 4.


As we touched upon briefly earlier, the BUFRLIB software has a default limit of 10000 bytes for the maximum size of any message that will be created and written to a BUFR output file; however, it is very easy for a user to override this limit:

	CALL MAXOUT  ( MXMSIZ )

	Input argument:
	    MXMSIZ	INTEGER(*)	New maximum message length (in bytes)
                                        for all future output BUFR messages

This subroutine can be called at any time after the initial call to subroutine OPENBF (which itself sets the default limit of 10000!), and it remains in effect for all future output BUFR messages associated with all output BUFR files (i.e. logical unit LUBFR values) written by the BUFRLIB software within the same application program! A user may repeatedly call MAXOUT in order to repeatedly adjust the maximum message length as desired, but it is important to note that this length is only ever just a maximum limit and that some BUFR messages that are generated may, in fact, end up being much shorter than this limit. For example, as we mentioned earlier during the discussion for subroutines OPENMG and OPENMB, the BUFRLIB software will in certain situations automatically close and flush (to logical unit LUBFR) any existing BUFR message within the internal arrays and initialize a new one. This behavior remains true for any value of MXMSIZ, even if the length of the previous internal message was still well below the maximum limit.


	CALL CMPMSG  ( CF )

	Input argument:
	    CF		CHARACTER	Flag indicating whether BUFR messages output
                                        by future calls to subroutines WRITSB/WRITSA
                                        are to be compressed:
                                         'N' = no (the default)
                                         'Y' = yes

This subroutine call provides an easy way to specify whether future BUFR messages output via calls to subroutine WRITSB or WRITSA are to be compressed using the algorithm for data subset compression prescribed within the official WMO BUFR regulations. The default is 'N' (i.e. no) if left unspecified, but this value can easily be toggled on ('Y') and off ('N') for different calls to WRITSB or WRITSA for, e.g. different output BUFR files connected to different LUBFR logical unit numbers via separate prior calls to subroutine OPENBF. Either way, once a value for CF is set via a call to subroutine CMPMSG, it remains in effect for all messages written to all logical units within the same application program, unless or until it is overridden by a subsequent call to this same subroutine with the opposite value for CF.

Note that, from a high-level standpoint, it may seem reasonable to ask why one wouldn't always want to compress BUFR output messages (and, therefore, why the default value for CF isn't 'Y')? Without going into too much detail here about the specifics of the WMO BUFR compression algorithm, suffice it to say that compression only provides a real space-saving benefit when the subsets to be compressed are devoid of delayed replication and when corresponding data values between different subsets within the same message contain minimal variation. In other words, the use of compression is often times not the best approach, and that is why it is built into the BUFRLIB software as a user-specified option rather than as a default.


Now, before we cover these last two important subroutines, a bit of historical background is in order. Specifically, when the BUFRLIB software was originally written, it was intended to be used to exchange BUFR data internally within NCEP. Because of this, and owing also to the slower computer processing speeds that were available at the time, certain non-standard "enhancements" were written into the software to provide for faster encoding and decoding. For instance, the software will normally, when writing/encoding a BUFR message, insert byte counters in front of each Section 4 data subset in order to allow subsequent reads of that same message to be faster and more efficient. Also, liberal use is made of bit padding, and Section 3 is kept as short as possible by representing the entire data subset via the use of the FXY number that is associated with the top-level Table A mnemonic and, therefore, which is itself almost invariably a local (i.e. non WMO-standard) FXY number. It should be pointed out that all of these "enhancements" are entirely legal, since local FXY numbers are permitted to be used in a BUFR message and, in fact, actually are expressly used by BUFRLIB to denote the existence of the aforementioned byte counters and bit pads! However, and quite obviously, any alternative BUFR decoding algorithm other than the NCEP BUFRLIB software would not be able to cleanly decode such messages without prior knowledge of the meaning of all such local FXY numbers and "enhancements", and, therefore, it is strongly recommended to use one of the following additional subroutines when writing/encoding BUFR messages that are intended to or could possibly be read by persons using software other than the NCEP BUFRLIB software:

	CALL STNDRD  ( LUBFR, IBFMSG, LOBFMSG, OBFMSG )

	CALL STDMSG  ( CF )

	Input arguments:
	    LUBFR	INTEGER		Logical unit for BUFR file
	    IBFMSG	INTEGER(*)	BUFR message
	    LOBFMSG	INTEGER 	Dimensioned size (in integers) of OBFMSG
                                        output array (used by the subroutine to
                                        prevent overflow of this array!)
	    CF		CHARACTER	Flag indicating whether BUFR messages output
                                        by future calls to subroutines WRITSB/WRITSA
                                        are to be standardized:
                                         'N' = no (the default)
                                         'Y' = yes

	Output arguments:
	    OBFMSG	INTEGER(*)	Standardized copy of IBFMSG

Subroutine STNDRD takes, as input, a BUFR message such as would have previously been output by, e.g. subroutine WRITSA and, using the BUFR tables information associated with logical unit LUBFR, outputs a standardized version of this same message within array OBFMSG, which must itself be a separate array from IBFMSG. This "standardization" involves removing all references to the aforementioned byte counters and bit pads from Section 4 as well as replacing the Table A FXY number from Section 3 of IBFMSG with an equivalent sequence of lower-level Table B, Table C, Table D and/or replication FXY numbers which directly constitute that Table A FXY number and which are themselves all WMO-standard. The result is that the new message within OBFMSG is now entirely and strictly standard according to the WMO BUFR regulations!

The alternative subroutine STDMSG provides an easy way to standardize messages in an inline fashion, similar to how the aforementioned subroutine CNVED4 can be called in an inline fashion via a special call to subroutine PKVS01 (see above). Specifically, if STDMSG is called with a value of 'Y', then subroutine STNDRD will be called internally for all future output BUFR messages written via calls to subroutine WRITSB or WRITSA within the same application program, meaning that all such output BUFR messages will already be automatically standardized without the user having to directly call STNDRD on his/her own from within the application program! Note however that, as was the case similarly with the aforementioned subroutine CMPMSG for compression, any call to STDMSG will likewise remain in effect for all future calls to WRITSB or WRITSA within the same application program, unless or until it is superseded by a subsequent call to STDMSG with the opposite value for CF.

In closing, note that the above subroutines STNDRD, STDMSG, CNVED4 and CMPMSG are only applicable when writing/encoding BUFR messages for output. Alternatively, when reading/decoding BUFR messages that may or may not contain standardization, compression and/or different editions of BUFR, the BUFRLIB software, via the message-reading subroutines such as READMG, READERME, etc. will automatically handle any such variations or combinations thereof, all without any special additional effort or worry on the part of the user's application program!



NOAA/ National Weather Service
National Centers for Environmental Prediction
5200 Auth Road
Camp Springs, Maryland 20746
NCEP Internet Services Team
Disclaimer
Credits
Glossary
Privacy Policy
About Us
Career Opportunities
Page last modified: Monday, 12-Mar-2007 20:37:40 UTC