awips2/nativeLib/rary.cots.g2clib/g2_getfld.c
Bryan Kowal c76c856340 Merge branch 'master_14.1.1' into omaha_14.1.1
Conflicts:
	nativeLib/files.native/files.native.ecl
	nativeLib/ncep_grib2module/.cproject
	nativeLib/rary.cots.g2clib/.project
	nativeLib/rary.cots.g2clib/g2_unpack3.c
	rpms/awips2.core/Installer.python/component.spec
	rpms/awips2.core/Installer.python/nativeLib/x86_64/grib2.so
	rpms/awips2.core/Installer.python/nativeLib/x86_64/libjasper.so
	rpms/awips2.core/Installer.python/nativeLib/x86_64/libjasper.so.1

Former-commit-id: 412bcb0f21b7385a170d14b3a88dd67c91a301a2
2013-10-31 15:23:08 -05:00

551 lines
23 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include "grib2.h"
g2int g2_unpack1(unsigned char *,g2int *,g2int **,g2int *);
g2int g2_unpack2(unsigned char *,g2int *,g2int *,unsigned char **);
g2int g2_unpack3(unsigned char *,g2int *,g2int **,g2int **,
g2int *,g2int **,g2int *);
g2int g2_unpack4(unsigned char *,g2int *,g2int *,g2int **,
g2int *,g2float **,g2int *);
g2int g2_unpack5(unsigned char *,g2int *,g2int *,g2int *, g2int **,g2int *);
g2int g2_unpack6(unsigned char *,g2int *,g2int ,g2int *, g2int **);
g2int g2_unpack7(unsigned char *,g2int *,g2int ,g2int *,
g2int ,g2int *,g2int ,g2float **);
g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
gribfield **gfld)
//$$$ SUBPROGRAM DOCUMENTATION BLOCK
// . . . .
// SUBPROGRAM: g2_getfld
// PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-10-28
//
// ABSTRACT: This subroutine returns all the metadata, template values,
// Bit-map ( if applicable ), and the unpacked data for a given data
// field. All of the information returned is stored in a gribfield
// structure, which is defined in file grib2.h.
// Users of this routine will need to include "grib2.h" in their source
// code that calls this routine. Each component of the gribfield
// struct is also described in the OUTPUT ARGUMENTS section below.
//
// Since there can be multiple data fields packed into a GRIB2
// message, the calling routine indicates which field is being requested
// with the ifldnum argument.
//
// PROGRAM HISTORY LOG:
// 2002-10-28 Gilbert
//
// USAGE: #include "grib2.h"
// int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,
// g2int expand,gribfield **gfld)
// INPUT ARGUMENTS:
// cgrib - Character pointer to the GRIB2 message
// ifldnum - Specifies which field in the GRIB2 message to return.
// unpack - Boolean value indicating whether to unpack bitmap/data field
// 1 = unpack bitmap (if present) and data values
// 0 = do not unpack bitmap and data values
// expand - Boolean value indicating whether the data points should be
// expanded to the correspond grid, if a bit-map is present.
// 1 = if possible, expand data field to grid, inserting zero
// values at gridpoints that are bitmapped out.
// (SEE REMARKS2)
// 0 = do not expand data field, leaving it an array of
// consecutive data points for each "1" in the bitmap.
// This argument is ignored if unpack == 0 OR if the
// returned field does not contain a bit-map.
//
// OUTPUT ARGUMENT:
// gribfield gfld; - pointer to structure gribfield containing
// all decoded data for the data field.
//
// gfld->version = GRIB edition number ( currently 2 )
// gfld->discipline = Message Discipline ( see Code Table 0.0 )
// gfld->idsect = Contains the entries in the Identification
// Section ( Section 1 )
// This element is a pointer to an array
// that holds the data.
// gfld->idsect[0] = Identification of originating Centre
// ( see Common Code Table C-1 )
// 7 - US National Weather Service
// gfld->idsect[1] = Identification of originating Sub-centre
// gfld->idsect[2] = GRIB Master Tables Version Number
// ( see Code Table 1.0 )
// 0 - Experimental
// 1 - Initial operational version number
// gfld->idsect[3] = GRIB Local Tables Version Number
// ( see Code Table 1.1 )
// 0 - Local tables not used
// 1-254 - Number of local tables version used
// gfld->idsect[4] = Significance of Reference Time (Code Table 1.2)
// 0 - Analysis
// 1 - Start of forecast
// 2 - Verifying time of forecast
// 3 - Observation time
// gfld->idsect[5] = Year ( 4 digits )
// gfld->idsect[6] = Month
// gfld->idsect[7) = Day
// gfld->idsect[8] = Hour
// gfld->idsect[9] = Minute
// gfld->idsect[10] = Second
// gfld->idsect[11] = Production status of processed data
// ( see Code Table 1.3 )
// 0 - Operational products
// 1 - Operational test products
// 2 - Research products
// 3 - Re-analysis products
// gfld->idsect[12] = Type of processed data ( see Code Table 1.4 )
// 0 - Analysis products
// 1 - Forecast products
// 2 - Analysis and forecast products
// 3 - Control forecast products
// 4 - Perturbed forecast products
// 5 - Control and perturbed forecast products
// 6 - Processed satellite observations
// 7 - Processed radar observations
// gfld->idsectlen = Number of elements in gfld->idsect[].
// gfld->local = Pointer to character array containing contents
// of Local Section 2, if included
// gfld->locallen = length of array gfld->local[]
// gfld->ifldnum = field number within GRIB message
// gfld->griddef = Source of grid definition (see Code Table 3.0)
// 0 - Specified in Code table 3.1
// 1 - Predetermined grid Defined by originating centre
// gfld->ngrdpts = Number of grid points in the defined grid.
// gfld->numoct_opt = Number of octets needed for each
// additional grid points definition.
// Used to define number of
// points in each row ( or column ) for
// non-regular grids.
// = 0, if using regular grid.
// gfld->interp_opt = Interpretation of list for optional points
// definition. (Code Table 3.11)
// gfld->igdtnum = Grid Definition Template Number (Code Table 3.1)
// gfld->igdtmpl = Contains the data values for the specified Grid
// Definition Template ( NN=gfld->igdtnum ). Each
// element of this integer array contains an entry (in
// the order specified) of Grid Defintion Template 3.NN
// This element is a pointer to an array
// that holds the data.
// gfld->igdtlen = Number of elements in gfld->igdtmpl[]. i.e. number of
// entries in Grid Defintion Template 3.NN
// ( NN=gfld->igdtnum ).
// gfld->list_opt = (Used if gfld->numoct_opt .ne. 0) This array
// contains the number of grid points contained in
// each row ( or column ). (part of Section 3)
// This element is a pointer to an array
// that holds the data. This pointer is nullified
// if gfld->numoct_opt=0.
// gfld->num_opt = (Used if gfld->numoct_opt .ne. 0)
// The number of entries
// in array ideflist. i.e. number of rows ( or columns )
// for which optional grid points are defined. This value
// is set to zero, if gfld->numoct_opt=0.
// gfdl->ipdtnum = Product Definition Template Number(see Code Table 4.0)
// gfld->ipdtmpl = Contains the data values for the specified Product
// Definition Template ( N=gfdl->ipdtnum ). Each element
// of this integer array contains an entry (in the
// order specified) of Product Defintion Template 4.N.
// This element is a pointer to an array
// that holds the data.
// gfld->ipdtlen = Number of elements in gfld->ipdtmpl[]. i.e. number of
// entries in Product Defintion Template 4.N
// ( N=gfdl->ipdtnum ).
// gfld->coord_list = Real array containing floating point values
// intended to document the vertical discretisation
// associated to model data on hybrid coordinate
// vertical levels. (part of Section 4)
// This element is a pointer to an array
// that holds the data.
// gfld->num_coord = number of values in array gfld->coord_list[].
// gfld->ndpts = Number of data points unpacked and returned.
// gfld->idrtnum = Data Representation Template Number
// ( see Code Table 5.0)
// gfld->idrtmpl = Contains the data values for the specified Data
// Representation Template ( N=gfld->idrtnum ). Each
// element of this integer array contains an entry
// (in the order specified) of Product Defintion
// Template 5.N.
// This element is a pointer to an array
// that holds the data.
// gfld->idrtlen = Number of elements in gfld->idrtmpl[]. i.e. number
// of entries in Data Representation Template 5.N
// ( N=gfld->idrtnum ).
// gfld->unpacked = logical value indicating whether the bitmap and
// data values were unpacked. If false,
// gfld->bmap and gfld->fld pointers are nullified.
// gfld->expanded = Logical value indicating whether the data field
// was expanded to the grid in the case where a
// bit-map is present. If true, the data points in
// gfld->fld match the grid points and zeros were
// inserted at grid points where data was bit-mapped
// out. If false, the data values in gfld->fld were
// not expanded to the grid and are just a consecutive
// array of data points corresponding to each value of
// "1" in gfld->bmap.
// gfld->ibmap = Bitmap indicator ( see Code Table 6.0 )
// 0 = bitmap applies and is included in Section 6.
// 1-253 = Predefined bitmap applies
// 254 = Previously defined bitmap applies to this field
// 255 = Bit map does not apply to this product.
// gfld->bmap = integer array containing decoded bitmap,
// if gfld->ibmap=0 or gfld->ibap=254. Otherwise nullified
// This element is a pointer to an array
// that holds the data.
// gfld->fld = Array of gfld->ndpts unpacked data points.
// This element is a pointer to an array
// that holds the data.
//
//
// RETURN VALUES:
// ierr - Error return code.
// 0 = no error
// 1 = Beginning characters "GRIB" not found.
// 2 = GRIB message is not Edition 2.
// 3 = The data field request number was not positive.
// 4 = End string "7777" found, but not where expected.
// 6 = GRIB message did not contain the requested number of
// data fields.
// 7 = End string "7777" not found at end of message.
// 8 = Unrecognized Section encountered.
// 9 = Data Representation Template 5.NN not yet implemented.
// 15 = Error unpacking Section 1.
// 16 = Error unpacking Section 2.
// 10 = Error unpacking Section 3.
// 11 = Error unpacking Section 4.
// 12 = Error unpacking Section 5.
// 13 = Error unpacking Section 6.
// 14 = Error unpacking Section 7.
// 17 = Previous bitmap specified, yet none exists.
//
// REMARKS: Note that struct gribfield is allocated by this routine and it
// also contains pointers to many arrays of data that were allocated
// during decoding. Users are encouraged to free up this memory,
// when it is no longer needed, by an explicit call to routine g2_free.
// EXAMPLE:
// #include "grib2.h"
// gribfield *gfld;
// ret=g2_getfld(cgrib,1,1,1,&gfld);
// ...
// g2_free(gfld);
//
// Routine g2_info can be used to first determine
// how many data fields exist in a given GRIB message.
//
// REMARKS2: It may not always be possible to expand a bit-mapped data field.
// If a pre-defined bit-map is used and not included in the GRIB2
// message itself, this routine would not have the necessary
// information to expand the data. In this case, gfld->expanded would
// would be set to 0 (false), regardless of the value of input
// argument expand.
//
// ATTRIBUTES:
// LANGUAGE: C
// MACHINE:
//
//$$$
{
g2int have3,have4,have5,have6,have7,ierr,jerr;
g2int numfld,j,n,istart,iofst,ipos;
g2int disc,ver,lensec0,lengrib,lensec,isecnum;
g2int *igds;
g2int *bmpsave;
g2float *newfld;
gribfield *lgfld;
have3=0;
have4=0;
have5=0;
have6=0;
have7=0;
ierr=0;
numfld=0;
lgfld=(gribfield *)malloc(sizeof(gribfield));
*gfld=lgfld;
lgfld->locallen=0;
lgfld->idsect=0;
lgfld->local=0;
lgfld->list_opt=0;
lgfld->igdtmpl=0;
lgfld->ipdtmpl=0;
lgfld->idrtmpl=0;
lgfld->coord_list=0;
lgfld->bmap=0;
lgfld->fld=0;
//
// Check for valid request number
//
if (ifldnum <= 0) {
printf("g2_getfld: Request for field number must be positive.\n");
ierr=3;
return(ierr);
}
//
// Check for beginning of GRIB message in the first 100 bytes
//
istart=-1;
for (j=0;j<100;j++) {
if (cgrib[j]=='G' && cgrib[j+1]=='R' &&cgrib[j+2]=='I' &&
cgrib[j+3]=='B') {
istart=j;
break;
}
}
if (istart == -1) {
printf("g2_getfld: Beginning characters GRIB not found.\n");
ierr=1;
return(ierr);
}
//
// Unpack Section 0 - Indicator Section
//
iofst=8*(istart+6);
gbit(cgrib,&disc,iofst,8); // Discipline
iofst=iofst+8;
gbit(cgrib,&ver,iofst,8); // GRIB edition number
iofst=iofst+8;
iofst=iofst+32;
gbit(cgrib,&lengrib,iofst,32); // Length of GRIB message
iofst=iofst+32;
lensec0=16;
ipos=istart+lensec0;
//
// Currently handles only GRIB Edition 2.
//
if (ver != 2) {
printf("g2_getfld: can only decode GRIB edition 2.\n");
ierr=2;
return(ierr);
}
//
// Loop through the remaining sections keeping track of the
// length of each. Also keep the latest Grid Definition Section info.
// Unpack the requested field number.
//
for (;;) {
// Check to see if we are at end of GRIB message
if (cgrib[ipos]=='7' && cgrib[ipos+1]=='7' && cgrib[ipos+2]=='7' &&
cgrib[ipos+3]=='7') {
ipos=ipos+4;
// If end of GRIB message not where expected, issue error
if (ipos != (istart+lengrib)) {
printf("g2_getfld: '7777' found, but not where expected.\n");
ierr=4;
return(ierr);
}
break;
}
// Get length of Section and Section number
iofst=(ipos-1)*8;
iofst=ipos*8;
gbit(cgrib,&lensec,iofst,32); // Get Length of Section
iofst=iofst+32;
gbit(cgrib,&isecnum,iofst,8); // Get Section number
iofst=iofst+8;
//printf(" lensec= %ld secnum= %ld \n",lensec,isecnum);
//
// Check to see if section number is valid
//
if ( isecnum<1 || isecnum>7 ) {
printf("g2_getfld: Unrecognized Section Encountered=%ld\n",isecnum);
ierr=8;
return(ierr);
}
//
// If found Section 1, decode elements in Identification Section
//
if (isecnum == 1) {
iofst=iofst-40; // reset offset to beginning of section
jerr=g2_unpack1(cgrib,&iofst,&lgfld->idsect,&lgfld->idsectlen);
if (jerr !=0 ) {
ierr=15;
return(ierr);
}
}
//
// If found Section 2, Grab local section
// Save in case this is the latest one before the requested field.
//
if (isecnum == 2) {
iofst=iofst-40; // reset offset to beginning of section
if (lgfld->local!=0) free(lgfld->local);
jerr=g2_unpack2(cgrib,&iofst,&lgfld->locallen,&lgfld->local);
if (jerr != 0) {
ierr=16;
return(ierr);
}
}
//
// If found Section 3, unpack the GDS info using the
// appropriate template. Save in case this is the latest
// grid before the requested field.
//
if (isecnum == 3) {
iofst=iofst-40; // reset offset to beginning of section
if (lgfld->igdtmpl!=0) free(lgfld->igdtmpl);
if (lgfld->list_opt!=0) free(lgfld->list_opt);
jerr=g2_unpack3(cgrib,&iofst,&igds,&lgfld->igdtmpl,
&lgfld->igdtlen,&lgfld->list_opt,&lgfld->num_opt);
if (jerr == 0) {
have3=1;
lgfld->griddef=igds[0];
lgfld->ngrdpts=igds[1];
lgfld->numoct_opt=igds[2];
lgfld->interp_opt=igds[3];
lgfld->igdtnum=igds[4];
free(igds);
}
else {
ierr=10;
return(ierr);
}
}
//
// If found Section 4, check to see if this field is the
// one requested.
//
if (isecnum == 4) {
numfld=numfld+1;
if (numfld == ifldnum) {
lgfld->discipline=disc;
lgfld->version=ver;
lgfld->ifldnum=ifldnum;
lgfld->unpacked=unpack;
lgfld->expanded=0;
iofst=iofst-40; // reset offset to beginning of section
jerr=g2_unpack4(cgrib,&iofst,&lgfld->ipdtnum,
&lgfld->ipdtmpl,&lgfld->ipdtlen,&lgfld->coord_list,
&lgfld->num_coord);
if (jerr == 0)
have4=1;
else {
ierr=11;
return(ierr);
}
}
}
//
// If found Section 5, check to see if this field is the
// one requested.
//
if (isecnum == 5 && numfld == ifldnum) {
iofst=iofst-40; // reset offset to beginning of section
jerr=g2_unpack5(cgrib,&iofst,&lgfld->ndpts,&lgfld->idrtnum,
&lgfld->idrtmpl,&lgfld->idrtlen);
if (jerr == 0)
have5=1;
else {
ierr=12;
return(ierr);
}
}
//
// If found Section 6, Unpack bitmap.
// Save in case this is the latest
// bitmap before the requested field.
//
if (isecnum == 6) {
if (unpack) { // unpack bitmap
iofst=iofst-40; // reset offset to beginning of section
bmpsave=lgfld->bmap; // save pointer to previous bitmap
jerr=g2_unpack6(cgrib,&iofst,lgfld->ngrdpts,&lgfld->ibmap,
&lgfld->bmap);
if (jerr == 0) {
have6=1;
if (lgfld->ibmap == 254) // use previously specified bitmap
if( bmpsave!=0 )
lgfld->bmap=bmpsave;
else {
printf("g2_getfld: Prev bit-map specified, but none exist.\n");
ierr=17;
return(ierr);
}
else // get rid of it
if( bmpsave!=0 ) free(bmpsave);
}
else {
ierr=13;
return(ierr);
}
}
else { // do not unpack bitmap
gbit(cgrib,&lgfld->ibmap,iofst,8); // Get BitMap Indicator
have6=1;
}
}
//
// If found Section 7, check to see if this field is the
// one requested.
//
if (isecnum==7 && numfld==ifldnum && unpack) {
iofst=iofst-40; // reset offset to beginning of section
jerr=g2_unpack7(cgrib,&iofst,lgfld->igdtnum,lgfld->igdtmpl,
lgfld->idrtnum,lgfld->idrtmpl,lgfld->ndpts,
&lgfld->fld);
if (jerr == 0) {
have7=1;
// If bitmap is used with this field, expand data field
// to grid, if possible.
if ( lgfld->ibmap != 255 && lgfld->bmap != 0 ) {
if ( expand == 1 ) {
n=0;
newfld=(g2float *)calloc(lgfld->ngrdpts,sizeof(g2float));
for (j=0;j<lgfld->ngrdpts;j++) {
if (lgfld->bmap[j]==1) newfld[j]=lgfld->fld[n++];
}
free(lgfld->fld);
lgfld->fld=newfld;
lgfld->expanded=1;
}
else {
lgfld->expanded=0;
}
}
else {
lgfld->expanded=1;
}
}
else {
printf("g2_getfld: return from g2_unpack7 = %d \n",(int)jerr);
ierr=14;
return(ierr);
}
}
//
// Check to see if we read pass the end of the GRIB
// message and missed the terminator string '7777'.
//
ipos=ipos+lensec; // Update beginning of section pointer
if (ipos > (istart+lengrib)) {
printf("g2_getfld: '7777' not found at end of GRIB message.\n");
ierr=7;
return(ierr);
}
//
// If unpacking requested, return when all sections have been
// processed
//
if (unpack && have3 && have4 && have5 && have6 && have7)
return(ierr);
//
// If unpacking is not requested, return when sections
// 3 through 6 have been processed
//
if ((! unpack) && have3 && have4 && have5 && have6)
return(ierr);
}
//
// If exited from above loop, the end of the GRIB message was reached
// before the requested field was found.
//
printf("g2_getfld: GRIB message contained %ld different fields.\n",numfld);
printf("g2_getfld: The request was for field %ld.\n",ifldnum);
ierr=6;
return(ierr);
}