[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 20040324: ncdump dates (fwd)



Hi Russ,

     Here's an updated version of read.ncdump.c (attached) that shouldn't
elicit complaints from most compilers (or at least reduce the number of
major complaints).  I could have corrected my mistakes a while back, but
better late than never, I suppose.

Cheers,
Rick Danielson


On Thu, 25 Mar 2004, Russ Rew wrote:

> >To: address@hidden
> >From: <address@hidden>
> >Subject: ncdump dates (fwd)
> >Organization: CMC
> >Keywords: 200403241452.i2OEqsrV029902 ncdump
> 
> Hi Rick,
> 
> >      Earlier in the month I sent the message below directly to the
> > netcdfgroup.  I don't usually submit to the group, and perhaps I should
> > have sent it to support instead.  Anyway, I'll re-send, just in case I
> > goofed:
> 
> I didn't see it on the netcdfgroup mailing list, so maybe it got
> filtered out for some reason (such as having an attachment), or you
> sent it from a different email address than used for you on the
> netcdfgroup mailing list.
> 
> >      A version of ncdump at the CDC used to convert udunits dates into
> > dates that can be read easily.  I lost that functionality recently (and
> > CDC ncdump was hard to compile using a newer version of netCDF), and wrote
> > a short program to replace it.  The idea is to filter the output of ncdump
> > and replace the dates using udunits.  It seems to work for NCEP Reanalysis
> > data files.  I've included a perl script below that illustrates how it
> > could be used on multiple netCDF files, for example.  The "read.ncdump.c"
> > program is attached, in case there are others in the same boat (I doubt
> > it's COARDS compliant, but that could be changed).
> > 
> > Cheers,
> > Rick Danielson
> > 
> > #!/usr/bin/perl -w
> > for ($a = 0; $a < scalar(@ARGV); $a++) {
> >   $command = "ncdump -c $ARGV[$a] | read.ncdump\n";
> >   system($command);
> > }
> 
> Thanks for contributing this!  I copied it to our contributed netCDF
> software directory:
> 
>   ftp://ftp.unidata.ucar.edu/pub/netcdf/contrib/read.ncdump.c
> 
> and added an entry about it in our contributed software catalog:
> 
>   http://www.unidata.ucar.edu/packages/netcdf/Contrib.html
> 
> that says:
> 
>   read.ncdump.c
>     Rick Danielson's filter for ncdump output that replaces udunits
>     times with the corresponding date and time in a more readable
>     form YYYY-MM-DD hh:mm:ss.
> 
> If you want to change this, just let me know.  It still might be
> worthwhile to announce this on the netcdfgroup mailing list, as there
> might be others who would like to know about your filter.
> 
> --Russ
> 
> _____________________________________________________________________
> 
> Russ Rew                                         UCAR Unidata Program
> address@hidden          http://www.unidata.ucar.edu/staff/russ
> 
>   
> 
/*
 * filter the result of ncdump to output time information - RD February 2004
 *
 * Use the output of ncdump as the input to this program.  For example, this 
perl script 
 * could be used on multiple netCDF files to replace dates with something more 
readable:
 *
 *  #!/usr/bin/perl -w
 *  for ($a = 0; $a < scalar(@ARGV); $a++) {
 *    $command = "ncdump -c $ARGV[$a] | read.ncdump\n";
 *    system($command);
 *  }
 *
 */

#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include "/home/danielsonr/soft/udunits/include/udunits.h"

#define LEN     99
/*
 * Please note that a "segmentation error" may occur owing to a
 * liberal use of memory here.  If this occurs, a reduction of
 * LOTS(=9999 or so) may be in order.
 */
#define LOTS    33333
#define DIMS    0
#define VARS    1
#define DATA    2

void datestr(char date[], int yr, int mo, int dy, int hr, int mn, int sc);

int main(int argc, char *argv[])
{
    FILE *fpa, *fpb, *fopen();
    int a, b, c, d, year, month, day, hour, minute, section;
    char line[LOTS], date[LEN], times[LOTS][LEN], valstr[LEN];
    float second;

    char udunita[LEN], udunitb[LEN];                                          
/* udunits declarations */
    utUnit utunita, utunitb;
    float value;

    if (argc != 1) {
      printf("Usage: %s\n",argv[0]);
      exit(1);
    }

    if (utInit("") != 0) {
      printf("couldn't initialize Unidata units library\n");
      exit(2);
    }

    while (fgets(line,LOTS,stdin) != NULL) {                                  
/* for each ncdump output line */
      if (strstr(line,"dimensions:") != NULL) section = DIMS;                 
/* note the section being printed */
      if (strstr(line,"variables:")  != NULL) section = VARS;
      if (strstr(line,"data:")       != NULL) section = DATA;

      if (section == VARS && strstr(line,"time:units") != NULL) {
        printf("%s",line);
        strtok(line,"\"");
        strcpy(udunita,(char *)strtok(NULL,"\""));
        utScan(udunita,&utunita);
      }
      else if (section == VARS && strstr(line,"time:actual_range") != NULL) {
        strtok(line,"=,;");
        strcpy(valstr,(char *)strtok(NULL,"=,;"));
        sscanf(valstr,"%f",&value);
        utCalendar(value,&utunita,&year,&month,&day,&hour,&minute,&second);
        datestr(date,year,month,day,hour,minute,second);
        printf("%s= \"%s, ",line,date);
        strcpy(valstr,(char *)strtok(NULL,"=,;"));
        sscanf(valstr,"%f",&value);
        utCalendar(value,&utunita,&year,&month,&day,&hour,&minute,&second);
        datestr(date,year,month,day,hour,minute,second);
        printf("%s\"\n",date);
      }
      else if (section == VARS && strstr(line,"time:ltm_range") != NULL) {
        strtok(line,"=,;");
        strcpy(valstr,(char *)strtok(NULL,"=,;"));
        sscanf(valstr,"%f",&value);
        utCalendar(value,&utunita,&year,&month,&day,&hour,&minute,&second);
        datestr(date,year,month,day,hour,minute,second);
        printf("%s= \"%s, ",line,date);
        strcpy(valstr,(char *)strtok(NULL,"=,;"));
        sscanf(valstr,"%f",&value);
        utCalendar(value,&utunita,&year,&month,&day,&hour,&minute,&second);
        datestr(date,year,month,day,hour,minute,second);
        printf("%s\"\n",date);
      }
      else if (section == DATA && strstr(line,"time =") != NULL) {
        while (strstr(line,";") == NULL) {
          fgets(valstr,LEN,stdin);
          strcat(line,valstr);
        }
        strcpy(valstr,(char *)strtok(line,"=,"));
        a = 0;
        while (strstr(valstr,";") == NULL) {
          strcpy(valstr,(char *)strtok(NULL,"=,"));
          sscanf(valstr,"%f",&value);
          utCalendar(value,&utunita,&year,&month,&day,&hour,&minute,&second);
          datestr(date,year,month,day,hour,minute,second);
          strcpy(times[a],date);
          a++;
        }
        printf(" time = ");
        b = c = 0;
        while (b < a) {
          printf("%s",times[b]);
          if (b == a-1)
            printf(" ;\n");
          else if (c == 2) {
            printf(",\n        ");
            c = -1;
          }
          else
            printf(", ");
          b++; c++;
        }
      }
      else {
        printf("%s",line);
      }
    }
    fclose(fpa);
    return(0);
}

void datestr(char date[], int yr, int mo, int dy, int hr, int mn, int sc)
{
    char num[LEN];

    sprintf(num,"%d",yr);
    if (yr < 10)        strcpy(date,"000");
    else if (yr < 100)  strcpy(date,"00");
    else if (yr < 1000) strcpy(date,"0");
    else                strcpy(date,"");
    strcat(date,num);
    strcat(date,"-");

    sprintf(num,"%d",mo);
    if (mo < 10)        strcat(date,"0");
    strcat(date,num);
    strcat(date,"-");

    sprintf(num,"%d",dy);
    if (dy < 10)        strcat(date,"0");
    strcat(date,num);
    strcat(date," ");

    sprintf(num,"%d",hr);
    if (hr < 10)        strcat(date,"0");
    strcat(date,num);
    strcat(date,":");

    sprintf(num,"%d",mn);
    if (mn < 10)        strcat(date,"0");
    strcat(date,num);
    strcat(date,":");

    sprintf(num,"%d",sc);
    if (sc < 10)        strcat(date,"0");
    strcat(date,num);
}