/*----------------------------------------------------------------------*\ | Program to extract GEOMET data. This is the main routine in the | | extraction tool's back end. | | | | Peter N. Schweitzer (U.S. Geological Survey, Reston, VA 22092) | \*----------------------------------------------------------------------*/ #include #include #include #include #include "cvtdate.h" #include "dw.h" static char msg [128]; #ifdef MS_DOS #define SEPARATOR '\\' #else #ifdef MAC #define SEPARATOR ':' #else #define SEPARATOR '/' #endif #endif static char *month[] = { "01","02","03","04","05","06","07","08","09","10","11","12" }; typedef FILE*(*geomet_open_function)(char *name, int *order); typedef int(*geomet_output_function)(FILE *f, struct dwd *d, int *order); typedef void(*geomet_close_function)(FILE *f); extern geomet_open_function get_open_function (char *format_name); extern geomet_output_function get_output_function (char *format_name); extern geomet_close_function get_close_function (char *format_name); extern int *get_offset_list (char **selected_sensor, int number_selected); /*----------------------------------------------------------------------*\ | Current station location is not ordinarily passed to output code, so | | we provide a way to obtain it here. | \*----------------------------------------------------------------------*/ static struct location *station_location = NULL; struct location *current_station_location (void) { return (station_location); } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ void extract_geomet_data ( char *station_code, struct tm *begin_tm, struct tm *end_tm, char **selected_item, int number_selected, char *data_path, char *output_file, char *format_name, int warn_missing) { char begin_day[6], end_day[6], current_day[6]; struct tm current_tm; struct dwd dwd; struct dw_file *f; time_t tb,te; long interval; int *order; geomet_open_function open_output_file; geomet_output_function output_geomet_record; geomet_close_function close_output_file; FILE *out; /*------------------------------------------------------------------*\ | Determine whether the interval of time requested is valid (i.e. | | end_tm follows begin_tm) and is long enough to span any values. | \*------------------------------------------------------------------*/ tb = mktime (begin_tm); te = mktime (end_tm); interval = (long) (difftime (te,tb)/360.0); if (interval <= 0) { dw_error ("No data were extracted because the time interval is too small"); dw_error ("or the beginning time follows the ending time"); return; } /*------------------------------------------------------------------*\ | Create strings representing the yyddd part of the file names for | | the beginning and end of the time interval desired. | \*------------------------------------------------------------------*/ tm_to_yd (begin_day,begin_tm); tm_to_yd (end_day,end_tm); /*------------------------------------------------------------------*\ | Determine which dwd structure members are to be output and in | | what order. | \*------------------------------------------------------------------*/ if (!(order = get_offset_list (selected_item,number_selected))) return; /*------------------------------------------------------------------*\ | Determine the output format and use the right output functions | \*------------------------------------------------------------------*/ open_output_file = get_open_function (format_name); output_geomet_record = get_output_function (format_name); close_output_file = get_close_function (format_name); /*------------------------------------------------------------------*\ | Open the output file; for each input file, read records one at a | | time and write appropriate values to the output file. | \*------------------------------------------------------------------*/ if (out = open_output_file (output_file,order)) { /*--------------------------------------------------------------*\ | Keep track of the current day in a struct tm. | \*--------------------------------------------------------------*/ current_tm = *begin_tm; do { char name[FILENAME_MAX]; int is_begin_day, is_end_day; char *s,*t; int m; /*----------------------------------------------------------*\ | Compose the input file name | \*----------------------------------------------------------*/ tm_to_yd (current_day,¤t_tm); strcpy (name,data_path); s = name + strlen (name); if (*(s-1) != SEPARATOR) { *s++ = SEPARATOR; *s = 0; } strcpy (s,"data"); s += strlen ("data"); *s++ = SEPARATOR; strcpy (s,station_code); s += strlen (station_code); *s++ = SEPARATOR; t = current_day; *s++ = *t++; *s++ = *t++; *s++ = SEPARATOR; m = current_tm.tm_mon; strcpy (s,month[m]); s += strlen (month[m]); *s++ = SEPARATOR; strcpy (s,station_code); s += strlen (station_code); strcpy (s,current_day); s += strlen (current_day); strcpy (s,".dat"); /*----------------------------------------------------------*\ | If the current day is the same as the beginning day or | | the ending day, you'll need to check the time of each | | record in the input file against the time specified by | | begin_tm, end_tm, or both. But you only need to do the | | day check once per file, not once per record. | \*----------------------------------------------------------*/ is_begin_day = ~strcmp (current_day,begin_day); is_end_day = ~strcmp (current_day,end_day); /*----------------------------------------------------------*\ | Open the input file and read records one at a time, | | checking times only if necessary. Output data from a | | record if the record is between begin_tm and end_tm. | \*----------------------------------------------------------*/ if (f = dw_open (name,"rb",NULL)) { station_location = &f->where; while (dw_read (f,&dwd)) { int ok = 1; /*--------------------------------------------------*\ | Determine whether this record should be output | | (i.e. whether it represents a time between those | | given by begin_tm and end_tm. | \*--------------------------------------------------*/ if (is_begin_day) { int t0,t1; t0 = begin_tm->tm_hour * 60 + begin_tm->tm_min; t1 = dwd.hour * 60 + dwd.minute; if (t1 < t0) ok = 0; } if (is_end_day) { int t0,t1; t0 = end_tm->tm_hour * 60 + end_tm->tm_min; t1 = dwd.hour * 60 + dwd.minute; if (t1 > t0) ok = 0; } if (ok) output_geomet_record (out,&dwd,order); } dw_close (f); } else if (warn_missing) { sprintf (msg,"Warning: could not open input file %s",name); dw_warn (msg); } /*----------------------------------------------------------*\ | When done with that file, adjust current_tm by adding | | one day, and repeat until you have processed the file | | corresponding to end_tm. | \*----------------------------------------------------------*/ next_day (¤t_tm); } while (strcmp (current_day,end_day) != 0); close_output_file (out); } else { sprintf (msg,"Error: could not create output file %s",output_file); dw_error (msg); } } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/