Ejemplo n.º 1
0
/* 1) find lwlf coresponding x1,y1, and uprt corresponding x2,y2
 * 2) create a new gds based on old one, but shifted with lwlf in bottom
 *    left, and uprt in upper right.
 * 3) Shift data around on grid? create new grid and copy data?
 */
int computeSubGrid (LatLon *lwlf, int *x1, int *y1, LatLon *uprt, int *x2,
                    int *y2, gdsType *gds, gdsType *newGds)
{
   myMaparam map;       /* Used to compute the grid lat/lon points. */
   double x, y;

   /* Check that gds is valid before setting up map projection. */
   if (GDSValid (gds) != 0) {
      preErrSprintf ("ERROR: gds was not Valid.\n");
      return -1;
   }

   /* Validate that lwlf < uprt */
   if (lwlf->lat > uprt->lat) {
      x = lwlf->lat;
      lwlf->lat = uprt->lat;
      uprt->lat = x;
   }
   if (lwlf->lon > uprt->lon) {
      x = lwlf->lon;
      lwlf->lon = uprt->lon;
      uprt->lon = x;
   }

   /* Set up the map projection. */
   SetMapParamGDS (&map, gds);
   myCll2xy (&map, lwlf->lat, lwlf->lon, &x, &y);
   *x1 = (int) floor (x);
   *y1 = (int) floor (y);
   myCll2xy (&map, uprt->lat, uprt->lon, &x, &y);
   *x2 = (int) ceil (x);
   *y2 = (int) ceil (y);
   if ((*x1 >= *x2) || (*y1 >= *y2)) {
      errSprintf ("ERROR: subgrid is not at least one cell wide/high\n");
      return -1;
   }

   myAssert ((gds->projType == GS3_LATLON) || (gds->projType == GS3_POLAR) ||
             (gds->projType == GS3_LAMBERT) ||
             (gds->projType == GS3_MERCATOR));
   memcpy (newGds, gds, sizeof (gdsType));
   newGds->Nx = *x2 - *x1 + 1;
   newGds->Ny = *y2 - *y1 + 1;
   newGds->numPts = (newGds->Nx * newGds->Ny);
   myCxy2ll (&map, (double) (*x1), (double) (*y1), &(newGds->lat1),
             &(newGds->lon1));
   if (gds->projType == GS3_LATLON) {
      myCxy2ll (&map, (double) (*x2), (double) (*y2), &(newGds->lat2),
                &(newGds->lon2));
   }
   return 0;
}
Ejemplo n.º 2
0
/*****************************************************************************
 * FindGRIBMsg() -- Review 12/2002
 *
 * Arthur Taylor / MDL
 *
 * PURPOSE
 *   Jumps through a GRIB2 file looking for a specific message.  Currently
 * that message is determined by msgNum which is in the range of 1..n.
 *   In the future we may be searching based on projection or date.
 *
 * ARGUMENTS
 *      fp = The current GRIB2 file to look through. (Input)
 *  msgNum = Which message to look for. (Input)
 *  offset = Where in the file the message starts (this is before the
 *           wmo ASCII part if there is one.) (Output)
 *  curMsg = The current # of messages we have looked through. (In/Out) 
 *
 * FILES/DATABASES:
 *   An already opened "GRIB2" File
 *
 * RETURNS: int (could use errSprintf())
 *  0 = OK
 * -1 = Problems reading Section 0.
 * -2 = Ran out of file.
 *
 * HISTORY
 *  11/2002 Arthur Taylor (MDL/RSIS): Created.
 *  12/2002 (TK,AC,TB,&MS): Code Review.
 *   6/2003 Matthew T. Kallio ([email protected]):
 *          "wmo" dimension increased to WMO_HEADER_LEN + 1 (for '\0' char)
 *   8/2003 AAT: Removed dependence on offset and fileLen.
 *
 * NOTES
 *****************************************************************************
 */
int FindGRIBMsg (DataSource &fp, int msgNum, sInt4 *offset, int *curMsg)
{
   int cnt;             /* The current message we are looking at. */
   char *buff;          /* Holds the info between records. */
   uInt4 buffLen;       /* Length of info between records. */
   sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
   uInt4 gribLen;       /* Length of the current GRIB message. */
   int version;         /* Which version of GRIB is in this message. */
   int c;               /* Determine if end of the file without fileLen. */
   sInt4 jump;          /* How far to jump to get to past GRIB message. */

   cnt = *curMsg + 1;
   buff = NULL;
   buffLen = 0;
   while ((c = fp.DataSourceFgetc()) != EOF) {
      fp.DataSourceUngetc(c);
      if (cnt >= msgNum) {
         /* 12/1/2004 version 1.63 forgot to free buff */
         free (buff);
         *curMsg = cnt;
         return 0;
      }
      /* Read section 0 to find gribLen and wmoLen. */
      if (ReadSECT0 (fp, &buff, &buffLen, GRIB_LIMIT, sect0, &gribLen,
                     &version) < 0) {
         preErrSprintf ("Inside FindGRIBMsg\n");
         free (buff);
         return -1;
      }
      myAssert ((version == 1) || (version == 2) || (version == -1));
      /* Continue on to the next grib message. */
      if ((version == 1) || (version == -1)) {
         jump = gribLen - 8;
      } else {
         jump = gribLen - 16;
      }
      fp.DataSourceFseek(jump, SEEK_CUR);
      *offset = *offset + gribLen + buffLen;
      cnt++;
   }
   free (buff);
   *curMsg = cnt - 1;
   /* Return -2 since we reached the end of file. This may not be an error
    * (multiple file option). */
   return -2;
/*
   errSprintf ("ERROR: Ran out of file looking for msgNum %d.\n", msgNum);
   errSprintf ("       Current msgNum %d\n", cnt);
*/
}
Ejemplo n.º 3
0
/*****************************************************************************
 * gribDraw() --
 *
 * Arthur Taylor / MDL
 *
 * PURPOSE
 *   This use GD to create an image based on the grid and a control file.
 *
 * ARGUMENTS
 *   Filename = Name of file to save to. (Input)
 *  grib_Data = The grib2 data to write. (Input)
 * mapIniFile = Name of the mapIni file to control the draws. (Input)
 *       meta = Meta Data about the grid. (Input)
 *        usr = User specified options. (Input)
 *
 * RETURNS: int (could use errSprintf())
 *  0 = OK
 *
 * HISTORY
 *  10/2005 Arthur Taylor (MDL): Created.
 *
 * NOTES
 *****************************************************************************
 */
int drawGrib (const char *Filename, double *grib_Data,
              const char *mapIniFile, const char *mapIniOptions,
              gdsType *gds, double Min, double Max, sChar f_missing,
              double missing, grib_MetaData *meta, userType *usr)
{
   mapIniType mapIni;
   myMaparam map;       /* Used to compute the grid lat/lon points. */
#ifdef TESTING
   double lat, lon;
#endif
   size_t nameLen = strlen (Filename);
   double orientLon;
   FILE *fp;
   int i;

#ifdef DEBUG
   printf ("start drawGrib. %f\n", clock () / (double) (CLOCKS_PER_SEC));
#endif

   if (nameLen < 4) {
      errSprintf ("ERROR: File %s is too short in length (it may need an "
                  "extension?)", Filename);
      return -2;
   }

   /* Set up map projection. */
   if (GDSValid (gds) != 0) {
      preErrSprintf ("ERROR: Grid Definition Section was not Valid.\n");
      return -1;
   }
   SetMapParamGDS (&map, gds);

   InitMapIni (&mapIni);
   if (mapIniFile != NULL) {
      if ((fp = fopen (mapIniFile, "rt")) == NULL) {
         errSprintf ("Couldn't open %s for read\n", mapIniFile);
         FreeMapIni (&mapIni);
         return -1;
      }
      if (ParseMapIniFile (&mapIni, mapIniOptions, fp) != 0) {
         FreeMapIni (&mapIni);
         return 0;
      }
      fclose (fp);
   } else {
      /* Set default background color. */
      mapIni.all.bg.f_null = 1;
      mapIni.all.bg.r = 255;
      mapIni.all.bg.g = 255;
      mapIni.all.bg.b = 255;
   }

   /* Set defaults for zoom. */
   if (mapIni.zoom.f_flag == 0) {
      if (map.f_latlon == 1) {
         mapIni.zoom.lat1 = map.lat1;
         mapIni.zoom.lon1 = map.lon1;
         mapIni.zoom.lat2 = map.latN;
         mapIni.zoom.lon2 = map.lonN;
      } else {
         myCxy2ll (&map, .5, .5, &(mapIni.zoom.lat1), &(mapIni.zoom.lon1));
         myCxy2ll (&map, gds->Nx + .5, gds->Ny + .5, &(mapIni.zoom.lat2),
                   &(mapIni.zoom.lon2));
#ifdef TESTING
         myCxy2ll (&map, .5, .5, &lat, &lon);
         printf ("%f %f\n", lat, lon);
         mapIni.zoom.lat1 = mapIni.zoom.lat2 = lat;
         mapIni.zoom.lon1 = mapIni.zoom.lon2 = lon;
         myCxy2ll (&map, .5, gds->Ny + .5, &lat, &lon);
         printf ("%f %f\n", lat, lon);
         if (lat < mapIni.zoom.lat1)
            mapIni.zoom.lat1 = lat;
         if (lat > mapIni.zoom.lat2)
            mapIni.zoom.lat2 = lat;
         if (lon < mapIni.zoom.lon1)
            mapIni.zoom.lon1 = lon;
         if (lon > mapIni.zoom.lon2)
            mapIni.zoom.lon2 = lon;
         myCxy2ll (&map, gds->Nx + .5, gds->Ny + .5, &lat, &lon);
         printf ("%f %f\n", lat, lon);
         if (lat < mapIni.zoom.lat1)
            mapIni.zoom.lat1 = lat;
         if (lat > mapIni.zoom.lat2)
            mapIni.zoom.lat2 = lat;
         if (lon < mapIni.zoom.lon1)
            mapIni.zoom.lon1 = lon;
         if (lon > mapIni.zoom.lon2)
            mapIni.zoom.lon2 = lon;
         myCxy2ll (&map, gds->Nx + .5, .5, &lat, &lon);
         printf ("%f %f\n", lat, lon);
         if (lat < mapIni.zoom.lat1)
            mapIni.zoom.lat1 = lat;
         if (lat > mapIni.zoom.lat2)
            mapIni.zoom.lat2 = lat;
         if (lon < mapIni.zoom.lon1)
            mapIni.zoom.lon1 = lon;
         if (lon > mapIni.zoom.lon2)
            mapIni.zoom.lon2 = lon;
         printf ("%f %f\n", lat, lon);
         printf ("%f %f %f %f\n", mapIni.zoom.lat1, mapIni.zoom.lon1,
                 mapIni.zoom.lat2, mapIni.zoom.lon2);
#endif
      }
      mapIni.zoom.f_flag = 15;
   }

   /* Set defaults for projection section. */
   if ((mapIni.proj.f_flag1 != 31) || (mapIni.proj.f_flag2 != 31)) {
      mapIni.proj.type = gds->projType;
      mapIni.proj.minEarth = gds->minEarth;
      mapIni.proj.majEarth = gds->majEarth;
      mapIni.proj.lat1 = gds->lat1;
      mapIni.proj.lon1 = gds->lon1;
      mapIni.proj.f_flag1 = 31;
      mapIni.proj.mesh = gds->Dx;
      orientLon = gds->orientLon;
      if (orientLon > 180) {
         orientLon -= 360;
      }
      if (orientLon < -180) {
         orientLon += 360;
      }
      mapIni.proj.orientLon = orientLon;
      mapIni.proj.meshLat = gds->meshLat;
      mapIni.proj.scaleLat1 = gds->scaleLat1;
      mapIni.proj.scaleLat2 = gds->scaleLat2;
      mapIni.proj.f_flag2 = 31;
   }

   if (mapIni.all.numLayer == 0) {
      mapIni.all.numLayer = 1;
      mapIni.all.layers = (layerType *) malloc (mapIni.all.numLayer *
                                                sizeof (layerType));
      InitLayer (&(mapIni.all.layers[0]));
      mapIni.all.layers[0].type = GRID;
      mapIni.all.layers[0].shpType = MEMORY;
      mapIni.all.layers[0].ramp.numColors = 0;
      mapIni.all.layers[0].ramp.colors = NULL;
      mapIni.all.layers[0].ramp.numLab = 0;
      mapIni.all.layers[0].ramp.labRay = NULL;
      mapIni.all.layers[0].ramp.labJust = NULL;
      mapIni.all.layers[0].ramp.label = NULL;
      mapIni.all.layers[0].ramp.f_missing = 0;
      mapIni.all.layers[0].ramp.thick = 0;
   }
   for (i = 0; i < mapIni.all.numLayer; i++) {
      if (mapIni.all.layers[i].shpType == MEMORY) {
         mapIni.all.layers[i].gridData = grib_Data;
         mapIni.all.layers[i].gridNx = gds->Nx;
         mapIni.all.layers[i].gridNy = gds->Ny;
         mapIni.all.layers[i].gridProj.type = gds->projType;
         mapIni.all.layers[i].gridProj.minEarth = gds->minEarth;
         mapIni.all.layers[i].gridProj.majEarth = gds->majEarth;
         mapIni.all.layers[i].gridProj.lat1 = gds->lat1;
         mapIni.all.layers[i].gridProj.lon1 = gds->lon1;
         mapIni.all.layers[i].gridProj.f_flag1 = 31;
         mapIni.all.layers[i].gridProj.mesh = gds->Dx;
         orientLon = gds->orientLon;
         if (orientLon > 180) {
            orientLon -= 360;
         }
         if (orientLon < -180) {
            orientLon += 360;
         }
         mapIni.all.layers[i].gridProj.orientLon = orientLon;
         mapIni.all.layers[i].gridProj.meshLat = gds->meshLat;
         mapIni.all.layers[i].gridProj.scaleLat1 = gds->scaleLat1;
         mapIni.all.layers[i].gridProj.scaleLat2 = gds->scaleLat2;
         mapIni.all.layers[i].gridProj.f_flag2 = 31;
         if (mapIni.all.layers[i].ramp.numColors == 0) {
            SetGridRamp (&(mapIni.all.layers[i]), Min, Max, f_missing,
                         missing);
         } else {
            if (f_missing) {
               mapIni.all.layers[i].ramp.missValue = missing;
               mapIni.all.layers[i].ramp.f_missing = f_missing;
            }
         }
      }
   }

   /* Set defaults for output. */
   if (mapIni.out.f_flag != 3) {
      mapIni.out.X_Size = 520;
      mapIni.out.Y_Size = 420;
      mapIni.out.f_flag = 3;
   }

   if (mapIni.out.numOutputs == 0) {
      mapIni.out.numOutputs = 1;
      mapIni.out.outputs = (outputType *) malloc (mapIni.out.numOutputs *
                                                  sizeof (outputType));
      mapIni.out.outputs[0].numActive = 1;
      mapIni.out.outputs[0].active =
            (int *) malloc (mapIni.out.outputs[0].numActive * sizeof (int));
      mapIni.out.outputs[0].active[0] = 1;
      mapIni.out.outputs[0].filename = NULL;
   }

   for (i = 0; i < mapIni.out.numOutputs; i++) {
      if (mapIni.out.outputs[i].filename == NULL) {
         mapIni.out.outputs[i].filename =
               (char *) malloc (nameLen + 1 * sizeof (char));
         strncpy (mapIni.out.outputs[i].filename, Filename, nameLen - 3);
         strncpy (mapIni.out.outputs[i].filename + nameLen - 3, "png", 3);
         mapIni.out.outputs[i].filename[nameLen] = '\0';
      }
   }

   if (ValidateMapIni (&mapIni) != 0) {
      printf ("MapINI was invalid \n");
      FreeMapIni (&mapIni);
      return 0;
   }
#ifdef DEBUG
   printf ("Before ControlDraw. %f\n", clock () / (double) (CLOCKS_PER_SEC));
#endif
   ControlDraw (&mapIni);
#ifdef DEBUG
   printf ("after ControlDraw. %f\n", clock () / (double) (CLOCKS_PER_SEC));
#endif

   FreeMapIni (&mapIni);
   return 0;
}
Ejemplo n.º 4
0
/*****************************************************************************
 * GRIB2Inventory() -- Review 12/2002
 *
 * Arthur Taylor / MDL
 *
 * PURPOSE
 *   Fills out an inventory structure for each GRIB message in a GRIB file,
 * without calling the FORTRAN routines to unpack the message.  It returns
 * the number of messages it found, or a negative number signifying an error.
 *
 * ARGUMENTS
 * filename = File to do the inventory of. (Input)
 *      Inv = The resultant array of inventories. (Output)
 *   LenInv = Length of the Array Inv (Output)
 *   numMsg = # of messages to inventory (0 = all, 1 = just first) (In)
 *   msgNum = MsgNum to start with, MsgNum of last message (Input/Output)
 *
 * FILES/DATABASES:
 *    Opens a GRIB2 file for reading given its filename.
 *
 * RETURNS: int (could use errSprintf())
 * +# = number of GRIB2 messages in the file.
 * -1 = Problems opening file for read.
 * -2 = Problems in section 0
 * -3 = Ran out of file.
 * -4 = Problems Reading in section 1
 * -5 = Problems Reading in section 2 or 3
 * -6 = Problems Reading in section 3
 * -7 = Problems Reading in section 4
 * -8 = Problems Parsing section 4.
 * -9 = Problems Reading in section 5
 * -10 = Problems Reading in section 6
 * -11 = Problems Reading in section 7
 * -12 = Problems inventory'ing a GRIB1 record
 * -13 = Problems inventory'ing a TDLP record
 *
 * HISTORY
 *   9/2002 Arthur Taylor (MDL/RSIS): Created.
 *  11/2002 AAT: Revised.
 *  12/2002 (TK,AC,TB,&MS): Code Review.
 *   3/2003 AAT: Corrected some satellite type mistakes.
 *   3/2003 AAT: Implemented multiple grid inventories in the same GRIB2
 *          message.
 *   4/2003 AAT: Started adding GRIB1 support
 *   6/2003 Matthew T. Kallio ([email protected]):
 *          "wmo" dimension increased to WMO_HEADER_LEN + 1 (for '\0' char)
 *   7/2003 AAT: Added numMsg so we can quickly find the reference time for
 *          a file by inventorying just the first message.
 *   8/2003 AAT: Adjusted use of GRIB_LIMIT to only affect the first message
 *          after we know we have a GRIB file, we don't want "trailing" bytes
 *          to break the program.
 *   8/2003 AAT: switched fileLen to only be computed for an error message.
 *   8/2003 AAT: curTot no longer serves a purpose.
 *   5/2004 AAT: Added a check for section number 2..8 for the repeated
 *          section (otherwise error)
 *  10/2004 AAT: Added ability to inventory TDLP records.
 *
 * NOTES
 *****************************************************************************
 */
int GRIB2Inventory (DataSource &fp, inventoryType **Inv, uInt4 *LenInv,
                    int numMsg, int *MsgNum)
{
   //FileDataSource fp (filename);            /* The opened GRIB2 file. */
   sInt4 offset = 0;    /* Where we are in the file. */
   sInt4 msgNum;        /* Which GRIB2 message we are on. */
   uInt4 gribLen;       /* Length of the current GRIB message. */
   uInt4 secLen;        /* Length of current section. */
   sChar sectNum;       /* Which section we are reading. */
   char *buff;          /* Holds the info between records. */
   uInt4 buffLen;       /* Length of info between records. */
   sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
   char *buffer = NULL; /* Holds a given section. */
   uInt4 bufferLen = 0; /* Size of buffer. */
   inventoryType *inv;  /* Local ptr to Inv to reduce ptr confusion. */
   inventoryType *lastInv; /* Used to point to last inventory record when
                            * there are multiple grids in the same message. */
   wordType word;       /* Used to parse the prodType out of Sect 0. */
   int ans;             /* The return error code of ReadSect0. */
   char *msg;           /* Used to pop messages off the error Stack. */
   int version;         /* Which version of GRIB is in this message. */
   uChar prodType;      /* Which GRIB2 type of product, 0 is meteo, 1 is
                         * hydro, 2 is land, 3 is space, 10 is oceanographic. 
                         */
   int grib_limit;      /* How many bytes to look for before the first "GRIB" 
                         * in the file.  If not found, is not a GRIB file. */
   int c;               /* Determine if end of the file without fileLen. */
   sInt4 fileLen;       /* Length of the GRIB2 file. */
   unsigned short int center, subcenter; /* Who produced it. */
   // char *ptr;           /* used to find the file extension. */

   grib_limit = GRIB_LIMIT;
	 /*
   if (filename != NULL) {
      //if ((fp = fopen (filename, "rb")) == NULL) {
      //   errSprintf ("ERROR: Problems opening %s for read.", filename);
      //   return -1;
      //}
		  //fp = FileDataSource(filename);
      ptr = strrchr (filename, '.');
      if (ptr != NULL) {
         if (strcmp (ptr, ".tar") == 0) {
            grib_limit = 5000;
         }
      }
   } else {
      //fp = stdin; // TODO!!
   }
	 */
   msgNum = *MsgNum;

   buff = NULL;
   buffLen = 0;
   while ((c = fp.DataSourceFgetc()) != EOF) {
		 fp.DataSourceUngetc(c);
      // ungetc (c, fp);
      /* msgNum++ done first so any error messages range from 1..n, instead
       * of 0.. n-1. Note msgNum should end up as n not (n-1) */
      msgNum++;
/* Used when testing inventory of large TDLPack files. */
/*
#ifdef DEBUG
      myAssert (msgNum < 32500L);
      if (msgNum % 10 == 0) {
         printf ("%ld :: %f\n", msgNum, clock () / (double) CLOCKS_PER_SEC);
      }
#endif
*/
      /* Make it so the second, third, etc messages have no limit to finding
       * the "GRIB" keyword. */
      if (msgNum > 1) {
         grib_limit = -1;
      }
      /* Read in the wmo header and sect0. */
      if (ReadSECT0 (fp, &buff, &buffLen, grib_limit, sect0, &gribLen,
                     &version) < 0) {
         if (msgNum == 1) {
            /* Handle case where we couldn't find 'GRIB' in the message. */
            preErrSprintf ("Inside GRIB2Inventory, Message # %d\n", msgNum);
            free (buffer);
            free (buff);
            //fclose (fp);
            return -2;
         } else {
            /* Handle case where there are trailing bytes. */
            msg = errSprintf (NULL);
            printf ("Warning: Inside GRIB2Inventory, Message # %d\n",
                    msgNum);
            printf ("%s", msg);
            free (msg);
            /* find out how big the file is. */
            fp.DataSourceFseek (0L, SEEK_END);
            fileLen = static_cast<int>(fp.DataSourceFtell());
            /* fseek (fp, 0L, SEEK_SET); */
            printf ("There were %d trailing bytes in the file.\n",
                    fileLen - offset);
            free (buffer);
            free (buff);
            //fclose (fp);
            return msgNum;
         }
      }

      /* Make room for this GRIB message in the inventory list. */
      *LenInv = *LenInv + 1;
      *Inv = (inventoryType *) realloc ((void *) *Inv,
                                        *LenInv * sizeof (inventoryType));
      inv = *Inv + (*LenInv - 1);

      /* Start parsing the message. */
      inv->GribVersion = version;
      inv->msgNum = msgNum;
      inv->subgNum = 0;
      inv->start = offset;
      inv->element = NULL;
      inv->comment = NULL;
      inv->unitName = NULL;
      inv->shortFstLevel = NULL;
      inv->longFstLevel = NULL;

      if (version == 1) {
         if (GRIB1_Inventory (fp, gribLen, inv) != 0) {
            preErrSprintf ("Inside GRIB2Inventory \n");
            free (buffer);
            free (buff);
            //fclose (fp);
            return -12;
         }
      } else if (version == -1) {
         if (TDLP_Inventory (fp, gribLen, inv) != 0) {
            preErrSprintf ("Inside GRIB2Inventory \n");
            free (buffer);
            free (buff);
            //fclose (fp);
            return -13;
         }
      } else {
         word.li = sect0[1];
         prodType = word.buffer[2];

         /* Read section 1 into buffer. */
         sectNum = 1;
         if (GRIB2SectToBuffer (fp, gribLen, &sectNum, &secLen, &bufferLen,
                                &buffer) != 0) {
            errSprintf ("ERROR: Problems with section 1\n");
            free (buffer);
            free (buff);
            //fclose (fp);
            return -4;
         }
         /* Parse the interesting data out of sect 1. */
         InventoryParseTime (buffer + 13 - 5, &(inv->refTime));
         MEMCPY_BIG (&center, buffer + 6 - 5, sizeof (short int));
         MEMCPY_BIG (&subcenter, buffer + 8 - 5, sizeof (short int));

         sectNum = 2;
         do {
            /* Look at sections 2 to 7 */
            if ((ans = GRIB2Inventory2to7 (sectNum, fp, gribLen, &bufferLen,
                                           &buffer, inv, prodType, center,
                                           subcenter)) != 0) {
               //fclose (fp);
               free (buffer);
               free (buff);
               return ans;
            }
            /* Try to read section 8. If it is "7777" = 926365495 regardless
             * of endian'ness then we have a simple message, otherwise it is
             * complex, and we need to read more. */
            if (FREAD_BIG (&secLen, sizeof (sInt4), 1, fp) != 1) {
               errSprintf ("ERROR: Ran out of file looking for Sect 8.\n");
               free (buffer);
               free (buff);
               // fclose (fp);
               return -4;
            }
            if (secLen == 926365495L) {
               sectNum = 8;
            } else {
               if (fp.DataSourceFread (&sectNum, sizeof (char), 1) != 1) {
                  errSprintf ("ERROR: Ran out of file looking for "
                              "subMessage.\n");
                  free (buffer);
                  free (buff);
                  //fclose (fp);
                  return -4;
               }
               if ((sectNum < 2) || (sectNum > 7)) {
                  errSprintf ("ERROR (GRIB2Inventory): Couldn't find the end"
                              " of message\n");
                  errSprintf ("and it doesn't appear to repeat sections.\n");
                  errSprintf ("so it is probably an ASCII / binary bug\n");
                  free (buffer);
                  free (buff);
                  //fclose (fp);
                  return -4;
               }
               fp.DataSourceFseek (-5, SEEK_CUR);
               /* Make room for the next part of this GRIB message in the
                * inventory list.  This is for when we have sub-grids. */
               *LenInv = *LenInv + 1;
               *Inv = (inventoryType *) realloc ((void *) *Inv,
                                                 *LenInv *
                                                 sizeof (inventoryType));
               inv = *Inv + (*LenInv - 1);
               lastInv = *Inv + (*LenInv - 2);

               inv->GribVersion = version;
               inv->msgNum = msgNum;
               inv->subgNum = lastInv->subgNum + 1;
               inv->start = offset;
               inv->element = NULL;
               inv->comment = NULL;
               inv->unitName = NULL;
               inv->shortFstLevel = NULL;
               inv->longFstLevel = NULL;

               word.li = sect0[1];
               prodType = word.buffer[2];
               inv->refTime = lastInv->refTime;
            }
         } while (sectNum != 8);
      }

      /* added to inventory either first msgNum messages, or all messages */
      if (numMsg == msgNum) {
         break;
      }
      /* Continue on to the next GRIB2 message. */
      if (version == -1) {
         /* TDLPack uses 4 bytes for FORTRAN record size, then another 8
          * bytes for the size of the record (so FORTRAN can see it), then
          * the data rounded up to an 8 byte boundary, then a trailing 4
          * bytes for a final FORTRAN record size.  However it only stores
          * in_ the gribLen the non-rounded amount, so we need to take care
          * of the rounding, and the trailing 4 bytes here. */
         offset += buffLen + ((sInt4) ceil (gribLen / 8.0)) * 8 + 4;
      } else {
         offset += buffLen + gribLen;
      }
      fp.DataSourceFseek (offset, SEEK_SET);
   }
   free (buffer);
   free (buff);
   //fclose (fp);
   *MsgNum = msgNum;
   return msgNum;
}
Ejemplo n.º 5
0
int GRIB2RefTime (char *filename, double *refTime)
{
   FileDataSource fp (filename);            /* The opened GRIB2 file. */
   sInt4 offset = 0;    /* Where we are in the file. */
   sInt4 msgNum;        /* Which GRIB2 message we are on. */
   uInt4 gribLen;       /* Length of the current GRIB message. */
   uInt4 secLen;        /* Length of current section. */
   sChar sectNum;       /* Which section we are reading. */
   char *buff;          /* Holds the info between records. */
   uInt4 buffLen;       /* Length of info between records. */
   sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
   char *buffer = NULL; /* Holds a given section. */
   uInt4 bufferLen = 0; /* Size of buffer. */
   /* wordType word; */       /* Used to parse the prodType out of Sect 0. */
   int ans;             /* The return error code of ReadSect0. */
   char *msg;           /* Used to pop messages off the error Stack. */
   int version;         /* Which version of GRIB is in this message. */
   /* uChar prodType; */      /* Which GRIB2 type of product, 0 is meteo, 1 is
                         * hydro, 2 is land, 3 is space, 10 is oceanographic. 
                         */
   int grib_limit;      /* How many bytes to look for before the first "GRIB" 
                         * in the file.  If not found, is not a GRIB file. */
   int c;               /* Determine if end of the file without fileLen. */
   sInt4 fileLen;       /* Length of the GRIB2 file. */
   char *ptr;           /* used to find the file extension. */
   double refTime1;

   grib_limit = GRIB_LIMIT;
   if (filename != NULL) {
      //if ((fp = fopen (filename, "rb")) == NULL) {
      //   errSprintf ("ERROR: Problems opening %s for read.", filename);
      //   return -1;
      //}
		  //fp = DataSource(filename);
      ptr = strrchr (filename, '.');
      if (ptr != NULL) {
         if (strcmp (ptr, ".tar") == 0) {
            grib_limit = 5000;
         }
      }
   } else {
      // fp = stdin; // TODO!!
   }
   msgNum = 0;

   buff = NULL;
   buffLen = 0;
   while ((c = fp.DataSourceFgetc()) != EOF) {
		 fp.DataSourceUngetc(c);
      /* msgNum++ done first so any error messages range from 1..n, instead
       * of 0.. n-1. Note msgNum should end up as n not (n-1) */
      msgNum++;
      /* Make it so the second, third, etc messages have no limit to finding
       * the "GRIB" keyword. */
      if (msgNum > 1) {
         grib_limit = -1;
      }
      /* Read in the wmo header and sect0. */
      if ((ans = ReadSECT0 (fp, &buff, &buffLen, grib_limit, sect0, &gribLen,
                            &version)) < 0) {
         if (msgNum == 1) {
            /* Handle case where we couldn't find 'GRIB' in the message. */
            preErrSprintf ("Inside GRIB2RefTime, Message # %d\n", msgNum);
            free (buffer);
            free (buff);
            //fclose (fp);
            return -2;
         } else {
            /* Handle case where there are trailing bytes. */
            msg = errSprintf (NULL);
            printf ("Warning: Inside GRIB2RefTime, Message # %d\n", msgNum);
            printf ("%s", msg);
            free (msg);
            /* find out how big the file is. */
            fp.DataSourceFseek (0L, SEEK_END);
            fileLen = static_cast<int>(fp.DataSourceFtell());
            /* fseek (fp, 0L, SEEK_SET); */
            printf ("There were %d trailing bytes in the file.\n",
                    fileLen - offset);
            free (buffer);
            free (buff);
            //fclose (fp);
            return msgNum;
         }
      }

      if (version == 1) {
         if (GRIB1_RefTime (fp, gribLen, &(refTime1)) != 0) {
            preErrSprintf ("Inside GRIB1_RefTime\n");
            free (buffer);
            free (buff);
            //fclose (fp);
            return -12;
         }
      } else if (version == -1) {
         if (TDLP_RefTime (fp, gribLen, &(refTime1)) != 0) {
            preErrSprintf ("Inside TDLP_RefTime\n");
            free (buffer);
            free (buff);
            //fclose (fp);
            return -13;
         }
      } else {
          /* word.li = sect0[1]; */
         /* prodType = word.buffer[2]; */

         /* Read section 1 into buffer. */
         sectNum = 1;
         if (GRIB2SectToBuffer (fp, gribLen, &sectNum, &secLen, &bufferLen,
                                &buffer) != 0) {
            errSprintf ("ERROR: Problems with section 1\n");
            free (buffer);
            //fclose (fp);
            return -4;
         }
         /* Parse the interesting data out of sect 1. */
         InventoryParseTime (buffer + 13 - 5, &(refTime1));
      }
      if (msgNum == 1) {
         *refTime = refTime1;
      } else {
         if (*refTime > refTime1) {
            *refTime = refTime1;
         }
      }

      /* Continue on to the next GRIB2 message. */
      offset += gribLen + buffLen;
      fp.DataSourceFseek (offset, SEEK_SET);
   }
   free (buffer);
   free (buff);
   //fclose (fp);
   return 0;
}
Ejemplo n.º 6
0
int ReadGrib2Record (DataSource &fp, sChar f_unit, double **Grib_Data,
                     uInt4 *grib_DataLen, grib_MetaData *meta,
                     IS_dataType *IS, int subgNum, double majEarth,
                     double minEarth, int simpVer, sInt4 *f_endMsg,
                     CPL_UNUSED LatLon *lwlf, CPL_UNUSED LatLon *uprt)
{
   sInt4 l3264b;        /* Number of bits in a sInt4.  Needed by FORTRAN
                         * unpack library to determine if system has a 4
                         * byte_ sInt4 or an 8 byte sInt4. */
   char *buff;          /* Holds the info between records. */
   uInt4 buffLen;       /* Length of info between records. */
   sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
   uInt4 gribLen;       /* Length of the current GRIB message. */
   sInt4 nd5;           /* Size of grib message rounded up to the nearest
                         * sInt4. */
   char *c_ipack;       /* A char ptr to the message stored in IS->ipack */
   sInt4 local_ns[8];   /* Local copy of section lengths. */
   sInt4 nd2x3;         /* Total number of grid points. */
   short int table50;   /* Type of packing used. (See code table 5.0)
                         * (GS5_SIMPLE==0, GS5_CMPLX==2, GS5_CMPLXSEC==3) */
   sInt4 nidat;         /* Size of section 2 if it contains integer data. */
   sInt4 nrdat;         /* Size of section 2 if it contains float data. */
   sInt4 inew;          /* 1 if this is the first grid we are reading. 0 if
                         * this is the second or later grid from the same
                         * GRIB message. */
   sInt4 iclean = 0;    /* 0 embed the missing values, 1 don't. */
   int j;               /* Counter used to find the desired subgrid. */
   sInt4 kfildo = 5;    /* FORTRAN Unit number for diagnostic info. Ignored,
                         * unless library is compiled a particular way. */
   sInt4 ibitmap;       /* 0 means no bitmap returned, otherwise 1. */
   float xmissp;        /* The primary missing value.  If iclean = 0, this
                         * value is embeded in grid, otherwise it is the
                         * value returned from the GRIB message. */
   float xmisss;        /* The secondary missing value.  If iclean = 0, this
                         * value is embeded in grid, otherwise it is the
                         * value returned from the GRIB message. */
   sInt4 jer[UNPK_NUM_ERRORS * 2]; /* Any Error codes along with their *
                                    * severity levels generated using the *
                                    * unpack GRIB2 library. */
   sInt4 ndjer = UNPK_NUM_ERRORS; /* The number of rows in JER( ). */
   sInt4 kjer;          /* The actual number of errors returned in JER. */
   size_t i;            /* counter as we loop through jer. */
   double unitM, unitB; /* values in y = m x + b used for unit conversion. */
   char unitName[15];   /* Holds the string name of the current unit. */
   int unitLen;         /* String length of string name of current unit. */
   int version;         /* Which version of GRIB is in this message. */
   sInt4 cnt;           /* Used to help compact the weather table. */
   int x1, y1;          /* The original grid coordinates of the lower left
                         * corner of the subgrid. */
   int x2, y2;          /* The original grid coordinates of the upper right
                         * corner of the subgrid. */
   uChar f_subGrid;     /* True if we have a subgrid. */
   sInt4 Nx, Ny;        /* original size of the data. */

   /*
    * f_endMsg is 1 if in the past we either completed reading a message,
    * or we haven't read any messages.  In either case we need to read the
    * next message from file.
    * If f_endMsg is false, then there is more to read from IS->ipack, so we
    * don't want to throw it out, nor have to re-read ipack from disk.
    */
   l3264b = sizeof (sInt4) * 8;
   buff = NULL;
   buffLen = 0;
   if (*f_endMsg == 1) {
      if (ReadSECT0 (fp, &buff, &buffLen, -1, sect0, &gribLen, &version) < 0) {
         preErrSprintf ("Inside ReadGrib2Record\n");
         free (buff);
         return -1;
      }
      meta->GribVersion = version;
      if (version == 1) {
         if (ReadGrib1Record (fp, f_unit, Grib_Data, grib_DataLen, meta, IS,
                              sect0, gribLen, majEarth, minEarth) != 0) {
            preErrSprintf ("Problems with ReadGrib1Record called by "
                           "ReadGrib2Record\n");
            free (buff);
            return -1;
         }
         *f_endMsg = 1;
         free (buff);
         return 0;
      } else if (version == -1) {
         if (ReadTDLPRecord (fp, Grib_Data, grib_DataLen, meta, IS,
                             sect0, gribLen, majEarth, minEarth) != 0) {
            preErrSprintf ("Problems with ReadGrib1Record called by "
                           "ReadGrib2Record\n");
            free (buff);
            return -1;
         }
         free (buff);
         return 0;
      }

      /*
       * Make room for entire message, and read it in.
       */
      /* nd5 needs to be gribLen in (sInt4) units rounded up. */
      nd5 = (gribLen + 3) / 4;
      if (nd5 > IS->ipackLen) {
         IS->ipackLen = nd5;
         IS->ipack = (sInt4 *) realloc ((void *) (IS->ipack),
                                        (IS->ipackLen) * sizeof (sInt4));
      }
      c_ipack = (char *) IS->ipack;
      /* Init last sInt4 to 0, to make sure that the padded bytes are 0. */
      IS->ipack[nd5 - 1] = 0;
      /* Init first 4 sInt4 to sect0. */
      memcpy (c_ipack, sect0, SECT0LEN_WORD * 4);
      /* Read in the rest of the message. */
      if (fp.DataSourceFread (c_ipack + SECT0LEN_WORD * 4, sizeof (char),
                 (gribLen - SECT0LEN_WORD * 4)) != (gribLen - SECT0LEN_WORD * 4)) {
         errSprintf ("GribLen = %ld, SECT0Len_WORD = %d\n", gribLen,
                     SECT0LEN_WORD);
         errSprintf ("Ran out of file\n");
         free (buff);
         return -1;
      }

      /*
       * Make sure the arrays are large enough for call to unpacker library.
       */
      /* FindSectLen Does not want (ipack / c_ipack) word swapped, because
       * that would make it much more confusing to find bytes in c_ipack. */
      if (FindSectLen (c_ipack, gribLen, local_ns, &nd2x3, &table50) < 0) {
         preErrSprintf ("Inside ReadGrib2Record.. Calling FindSectLen\n");
         free (buff);
         return -2;
      }

      /* Make sure all 'is' arrays except ns[7] are MAX (IS.ns[] ,
       * local_ns[]). See note 1 for reason to exclude ns[7] from MAX (). */
      for (i = 0; i < 7; i++) {
         if (local_ns[i] > IS->ns[i]) {
            IS->ns[i] = local_ns[i];
            IS->is[i] = (sInt4 *) realloc ((void *) (IS->is[i]),
                                           IS->ns[i] * sizeof (sInt4));
         }
      }

      /* Allocate room for sect 2. If local_ns[2] = -1 there is no sect 2. */
      if (local_ns[2] == -1) {
         nidat = 10;
         nrdat = 10;
      } else {
         /*
          * See note 2) We have a section 2, so use:
          *     MAX (32 * local_ns[2],SECT2_INTSIZE)
          * and MAX (32 * local_ns[2],SECT2_FLOATSIZE)
          * for size of section 2 unpacked.
          */
         nidat = (32 * local_ns[2] < SECT2_INIT_SIZE) ? SECT2_INIT_SIZE :
               32 * local_ns[2];
         nrdat = nidat;
      }
      if (nidat > IS->nidat) {
         IS->nidat = nidat;
         IS->idat = (sInt4 *) realloc ((void *) IS->idat,
                                       IS->nidat * sizeof (sInt4));
      }
      if (nrdat > IS->nrdat) {
         IS->nrdat = nrdat;
         IS->rdat = (float *) realloc ((void *) IS->rdat,
                                       IS->nrdat * sizeof (float));
      }
      /* Make sure we have room for the GRID part of the output. */
      if (nd2x3 > IS->nd2x3) {
         IS->nd2x3 = nd2x3;
         IS->iain = (sInt4 *) realloc ((void *) IS->iain,
                                       IS->nd2x3 * sizeof (sInt4));
         IS->ib = (sInt4 *) realloc ((void *) IS->ib,
                                     IS->nd2x3 * sizeof (sInt4));
      }
      /* See note 3) If table50 == 3, unpacker library needs nd5 >= nd2x3. */
      if ((table50 == 3) || (table50 == 0)) {
         if (nd5 < nd2x3) {
            nd5 = nd2x3;
            if (nd5 > IS->ipackLen) {
               IS->ipackLen = nd5;
               IS->ipack = (sInt4 *) realloc ((void *) (IS->ipack),
                                              IS->ipackLen * sizeof (sInt4));
            }
            /* Don't need to do the following, but we do in case code
             * changes. */
            c_ipack = (char *) IS->ipack;
         }
      }
      IS->nd5 = nd5;
      /* Unpacker library requires ipack to be MSB. */
/*
#ifdef DEBUG
      if (1==1) {
         FILE *fp = fopen ("test.bin", "wb");
         fwrite (IS->ipack, sizeof (sInt4), IS->nd5, fp);
         fclose (fp);
      }
#endif
*/
#ifdef LITTLE_ENDIAN
      memswp (IS->ipack, sizeof (sInt4), IS->nd5);
#endif
   } else {
      gribLen = IS->ipack[3];
   }
   free (buff);

   /* Loop through the grib message looking for the subgNum grid.  subgNum
    * goes from 0 to n-1. */
   for (j = 0; j <= subgNum; j++) {
      if (j == 0) {
         inew = 1;
      } else {
         inew = 0;
      }

      /* Note we are getting data back either as a float or an int, but not
       * both, so we don't need to allocated room for both. */
      unpk_grib2 (&kfildo, (float *) (IS->iain), IS->iain, &(IS->nd2x3),
                  IS->idat, &(IS->nidat), IS->rdat, &(IS->nrdat), IS->is[0],
                  &(IS->ns[0]), IS->is[1], &(IS->ns[1]), IS->is[2],
                  &(IS->ns[2]), IS->is[3], &(IS->ns[3]), IS->is[4],
                  &(IS->ns[4]), IS->is[5], &(IS->ns[5]), IS->is[6],
                  &(IS->ns[6]), IS->is[7], &(IS->ns[7]), IS->ib, &ibitmap,
                  IS->ipack, &(IS->nd5), &xmissp, &xmisss, &inew, &iclean,
                  &l3264b, f_endMsg, jer, &ndjer, &kjer);
      /*
       * Check for error messages...
       *   If we get an error message, print it, and return.
       */
      for (i = 0; i < (uInt4) kjer; i++) {
         if (jer[ndjer + i] == 0) {
            /* no error. */
         } else if (jer[ndjer + i] == 1) {
            /* Warning. */
#ifdef DEBUG
            printf ("Warning: Unpack library warning code (%d %d)\n",
                    jer[i], jer[ndjer + i]);
#endif
         } else {
            /* BAD Error. */
            errSprintf ("ERROR: Unpack library error code (%ld %ld)\n",
                        jer[i], jer[ndjer + i]);
            return -3;
         }
      }
   }

   /* Parse the meta data out. */
   if (MetaParse (meta, IS->is[0], IS->ns[0], IS->is[1], IS->ns[1],
                  IS->is[2], IS->ns[2], IS->rdat, IS->nrdat, IS->idat,
                  IS->nidat, IS->is[3], IS->ns[3], IS->is[4], IS->ns[4],
                  IS->is[5], IS->ns[5], gribLen, xmissp, xmisss, simpVer)
       != 0) {
#ifdef DEBUG
      FILE *fp;
      if ((fp = fopen ("dump.is0", "wt")) != NULL) {
         for (i = 0; i < 8; i++) {
            fprintf (fp, "---Section %d---\n", (int) i);
            for (j = 1; j <= IS->ns[i]; j++) {
               fprintf (fp, "IS%d Item %d = %d\n", (int) i, (int) j, IS->is[i][j - 1]);
            }
         }
         fclose (fp);
      }
#endif
      preErrSprintf ("Inside ReadGrib2Record.. Problems in MetaParse\n");
      return -4;
   }

   if ((majEarth > 6000) && (majEarth < 7000)) {
      if ((minEarth > 6000) && (minEarth < 7000)) {
         meta->gds.f_sphere = 0;
         meta->gds.majEarth = majEarth;
         meta->gds.minEarth = minEarth;
      } else {
         meta->gds.f_sphere = 1;
         meta->gds.majEarth = majEarth;
         meta->gds.minEarth = majEarth;
      }
   }

   /* Figure out an equation to pass to ParseGrid to convert the units for
    * this grid. */
/*
   if (ComputeUnit (meta->pds2.prodType, meta->pds2.sect4.templat,
                    meta->pds2.sect4.cat, meta->pds2.sect4.subcat, f_unit,
                    &unitM, &unitB, unitName) == 0) {
*/
   if (ComputeUnit (meta->convert, meta->unitName, f_unit, &unitM, &unitB,
                    unitName) == 0) {
      unitLen = strlen (unitName);
      meta->unitName = (char *) realloc ((void *) (meta->unitName),
                                         1 + unitLen * sizeof (char));
      strncpy (meta->unitName, unitName, unitLen);
      meta->unitName[unitLen] = '\0';
   }

   /* compute the subgrid. */
   /*
   if ((lwlf->lat != -100) && (uprt->lat != -100)) {
      Nx = meta->gds.Nx;
      Ny = meta->gds.Ny;
      if (computeSubGrid (lwlf, &x1, &y1, uprt, &x2, &y2, &(meta->gds),
                          &newGds) != 0) {
         preErrSprintf ("ERROR: In compute subgrid.\n");
         return 1;
      }
      // I couldn't decide if I should "permanently" change the GDS or not.
      // when I wrote computeSubGrid.  If next line stays, really should
      // rewrite computeSubGrid.
      memcpy (&(meta->gds), &newGds, sizeof (gdsType));
      f_subGrid = 1;
   } else {
      Nx = meta->gds.Nx;
      Ny = meta->gds.Ny;
      x1 = 1;
      x2 = Nx;
      y1 = 1;
      y2 = Ny;
      f_subGrid = 0;
   }
   */
   Nx = meta->gds.Nx;
   Ny = meta->gds.Ny;
   x1 = 1;
   x2 = Nx;
   y1 = 1;
   y2 = Ny;
   f_subGrid = 0;

   /* Figure out if we need iain or ain, and set it to Grib_Data.  At the
    * same time handle any bitmaps, and compute some statistics. */
   if ((f_subGrid) && (meta->gds.scan != 64)) {
      errSprintf ("Can not do a subgrid of non scanmode 64 grid yet.\n");
      return -3;
   }

   if (strcmp (meta->element, "Wx") != 0) {
      ParseGrid (&(meta->gridAttrib), Grib_Data, grib_DataLen, Nx, Ny,
                 meta->gds.scan, IS->iain, ibitmap, IS->ib, unitM, unitB, 0,
                 NULL, f_subGrid, x1, y1, x2, y2);
   } else {
      /* Handle weather grid.  ParseGrid looks up the values... If they are
       * "<Invalid>" it sets it to missing (or creates one).  If the table
       * entry is used it sets f_valid to 2. */
      ParseGrid (&(meta->gridAttrib), Grib_Data, grib_DataLen, Nx, Ny,
                 meta->gds.scan, IS->iain, ibitmap, IS->ib, unitM, unitB, 1,
                 (sect2_WxType *) &(meta->pds2.sect2.wx), f_subGrid, x1, y1,
                 x2, y2);

      /* compact the table to only those which are actually used. */
      cnt = 0;
      for (i = 0; i < meta->pds2.sect2.wx.dataLen; i++) {
         if (meta->pds2.sect2.wx.ugly[i].f_valid == 2) {
            meta->pds2.sect2.wx.ugly[i].validIndex = cnt;
            cnt++;
         } else if (meta->pds2.sect2.wx.ugly[i].f_valid == 3) {
            meta->pds2.sect2.wx.ugly[i].f_valid = 0;
            meta->pds2.sect2.wx.ugly[i].validIndex = cnt;
            cnt++;
         } else {
            meta->pds2.sect2.wx.ugly[i].validIndex = -1;
         }
      }
   }

   /* Figure out some other non-section oriented meta data. */
/*   strftime (meta->refTime, 20, "%Y%m%d%H%M",
             gmtime (&(meta->pds2.refTime)));
*/
   Clock_Print (meta->refTime, 20, meta->pds2.refTime, "%Y%m%d%H%M", 0);
/*
   strftime (meta->validTime, 20, "%Y%m%d%H%M",
             gmtime (&(meta->pds2.sect4.validTime)));
*/
   Clock_Print (meta->validTime, 20, meta->pds2.sect4.validTime,
                "%Y%m%d%H%M", 0);

   meta->deltTime = (sInt4) (meta->pds2.sect4.validTime - meta->pds2.refTime);

   return 0;
}
Ejemplo n.º 7
0
/*****************************************************************************
 * GRIB2Split() --
 *
 * Arthur Taylor / MDL
 *
 * PURPOSE
 *   Splits a file into its component GRIB messages (doesn't break up
 * subgrids).
 *
 * ARGUMENTS
 * filename = File to split. (Input)
 *   msgNum = Which message to look for (0 all, value otherwise). (Input)
 *   curMsg = Number of messages we've already looked at.
 *            In the procedured is the current message we are on. (Input)
 *
 * FILES/DATABASES:
 *    Opens a GRIB2 file for reading given its filename.
 *
 * RETURNS: int
 * +# = number of GRIB2 messages in the file.
 * -1 = Problems opening file for read.
 *
 * HISTORY
 *   5/2010 Arthur Taylor (MDL): Created.
 *
 * NOTES
 *****************************************************************************
 */
int GRIB2Split (char *filename, int msgNum, int curMsg)
{
   int grib_limit;      /* How many bytes to look for before the first "GRIB"
                         * in the file.  If not found, is not a GRIB file. */
   FILE *fp;            /* The opened GRIB2 file. */
   sInt4 offset = 0;    /* Where we are in the file. */
   char *ptr;           /* used to find the file extension. */
   char *buff;          /* Holds the info between records. */
   uInt4 buffLen;       /* Length of info between records. */
   int c;               /* Determine if end of the file without fileLen. */
   sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
   uInt4 gribLen;       /* Length of the current GRIB message. */
   int version;         /* Which version of GRIB is in this message. */
   char *msg;           /* Used to pop messages off the error Stack. */
   sInt4 fileLen;       /* Length of the GRIB2 file. */
   char *outName = NULL; /* Name of the output file. */
   FILE *op;            /* The opened output file. */
   int i;               /* loop counter while writing bytes to output file. */

   grib_limit = GRIB_LIMIT;
   if (filename != NULL) {
      if ((fp = fopen (filename, "rb")) == NULL) {
         errSprintf ("ERROR: Problems opening %s for read.", filename);
         return -1;
      }
      ptr = strrchr (filename, '.');
      if (ptr != NULL) {
         if (strcmp (ptr, ".tar") == 0) {
            grib_limit = 5000;
         }
      }
      outName = (char *) malloc (strlen (filename) + 1 + 11);
   } else {
      fp = stdin;
      outName = (char *) malloc (strlen ("split.grb") + 1 + 11);
   }

   buff = NULL;
   buffLen = 0;
   while ((c = fgetc (fp)) != EOF) {
      ungetc (c, fp);
      /* curMsg++ done first so any error messages range from 1..n, instead
       * of 0.. n-1. Note curMsg should end up as n not (n-1) */
      curMsg++;
      /* Allow  2nd, 3rd, etc messages to have no limit to finding "GRIB". */
      if (curMsg > 1) {
         grib_limit = -1;
      }
      /* Read in the wmo header and sect0. */
      if (ReadSECT0 (fp, &buff, &buffLen, grib_limit, sect0, &gribLen,
                     &version) < 0) {
         if (curMsg == 1) {
            /* Handle case where we couldn't find 'GRIB' in the message. */
            preErrSprintf ("Inside GRIB2Split, Message # %d\n", curMsg);

            free (buff);
            free (outName);
            fclose (fp);
            return -2;
         } else {
            /* Handle case where there are trailing bytes. */
            msg = errSprintf (NULL);
            printf ("Warning: Inside GRIB2Split, Message # %d\n",
                    curMsg);
            printf ("%s", msg);
            free (msg);
            /* find out how big the file is. */
            fseek (fp, 0L, SEEK_END);
            fileLen = ftell (fp);
            /* fseek (fp, 0L, SEEK_SET); */
            printf ("There were %ld trailing bytes in the file.\n",
                    fileLen - offset);
            curMsg --;

            free (buff);
            free (outName);
            fclose (fp);
            return curMsg;
         }
      }

      if (version == -1) {
         /* TDLPack uses 4 bytes for FORTRAN record size, then another 8
          * bytes for the size of the record (so FORTRAN can see it), then
          * the data rounded up to an 8 byte boundary, then a trailing 4
          * bytes for a final FORTRAN record size.  However it only stores
          * in_ the gribLen the non-rounded amount, so we need to take care
          * of the rounding, and the trailing 4 bytes here. */
         gribLen = ((sInt4) ceil (gribLen / 8.0)) * 8 + 4;
      }

      /* Write to file from buffLen to buffLen + gribLen bytes. */
      if ((msgNum == 0) || (curMsg == msgNum)) {
         if (filename != NULL) {
            sprintf (outName, "%s.%d", filename, curMsg);
         } else {
            sprintf (outName, "split.grb.%d", curMsg);
         }
         if ((op = fopen (outName, "wb")) == NULL) {
            errSprintf ("ERROR: Problems opening %s for write.", outName);

            free (buff);
            free (outName);
            fclose (fp);
            return -1;
         }
         fseek (fp, offset + buffLen, SEEK_SET);
         for (i = 0; i < gribLen; i++) {
            if ((c = getc(fp)) == EOF) {
               errSprintf ("ERROR: Reached end of file too soon?");

               free (buff);
               free (outName);
               fclose (fp);
               return -1;
            }
            putc (c, op);
         }
         fclose (op);
      }

      /* Continue on to the next GRIB2 message. */
      offset += buffLen + gribLen;
      fseek (fp, offset, SEEK_SET);
   }

   free (buff);
   free (outName);
   fclose (fp);
   return curMsg;
}