Main Page Class Hierarchy Compound List File List Compound Members File Members

# seiputaway.c

Go to the documentation of this file.

    00001 /******************************************************************
    00002  * seiputaway.c - routines to enable Seisan data to be stored from
    00003  *                Earthworm
    00004  *
    00005  * S. Flower, Feb 2001
    00006  *
    00007  * Modified 11 Oct 2001 - instead of writing direct to the output
    00008  * file we write to a temporary file and rename it when it is
    00009  * complete - this ensures that the file can be read OK as soon
    00010  * as it is available
    00011  *
    00012  * Modified 26 Oct 2001 - fixed bug that puts gaps at wrong end
    00013  * of output traces
    00014  *
    00015  * Modified 26 Oct 2001 - seisan file writing routines moved to a
    00016  * sparate file because of complexity of doing seisan writes
    00017  * with the Earthworm putaway structure
    00018  *
    00019  * Modified 31st Jan 2002 - new routines to make dealing with
    00020  * earthworm data structures easier to follow (pa_find_data())
    00021  ******************************************************************/
    00022
    00023 #include <stdio.h>
    00024 #include <time.h>
    00025 #include <stdlib.h>
    00026 #include <string.h>
    00027 #include <errno.h>
    00028 #include <math.h>
    00029 #include <float.h>
    00030 #if defined (_WINNT)
    00031 #include <io.h>
    00032 #endif
    00033
    00034 #include <sys/types.h>
    00035 #include <sys/stat.h>
    00036
    00037 #include "earthworm.h"
    00038 #include "trace_buf.h"
    00039 #include "swap.h"
    00040 #include "ws_clientII.h"
    00041 #include "site.h"
    00042 #include "time_ew.h"
    00043
    00044 #include "seihead.h"
    00045
    00046
    00047 /* private global variables */
    00048 static int output_native_numbers;
    00049
    00050
    00051 /**********************************************************************
    00052  * SEIPA_init
    00053  *
    00054  * Description: initialise SEIsan put away routines
    00055  *
    00056  * Input parameters: output_dir - the directory to be used for Seisan
    00057  *                                output files
    00058  *                   output_format - "intel" or "sparc" for byte ordering
    00059  *                   debug - flag for debugging output
    00060  * Output parameters: none
    00061  * Returns: EW_SUCCESS or EW_FAILURE
    00062  *
    00063  * Comments:
    00064  *
    00065  ***********************************************************************/
    00066 int SEIPA_init (char *output_dir, char *output_format, int debug)
    00067
    00068 {
    00069
    00070   /* make sure that the output directory exists */
    00071   if (CreateDir (output_dir) != EW_SUCCESS)
    00072   {
    00073     logit ("e", "SEIPA_init: Call to CreateDir failed\n");
    00074     return EW_FAILURE;
    00075   }
    00076
    00077 #if defined (_INTEL)
    00078   if (! strcmp (output_format, "intel"))
    00079     output_native_numbers = TRUE;
    00080   else if (! strcmp (output_format, "sparc"))
    00081     output_native_numbers = FALSE;
    00082   else
    00083   {
    00084     logit ("e", "SEIPA_init: can't recognise OutputFormat (%s)\n", output_format);
    00085     return EW_FAILURE;
    00086   }
    00087 #elif defined (_SPARC)
    00088   if (! strcmp (output_format, "sparc"))
    00089     output_native_numbers = TRUE;
    00090   else if (! strcmp (output_format, "intel"))
    00091     output_native_numbers = FALSE;
    00092   else
    00093   {
    00094     logit ("e", "SEIPA_init: can't recognise OutputFormat (%s)\n", output_format);
    00095     return EW_FAILURE;
    00096   }
    00097 #else
    00098 #error "_INTEL or _SPARC must be set before compiling"
    00099 #endif
    00100
    00101   return EW_SUCCESS;
    00102
    00103 }
    00104
    00105 /****************************************************************************
    00106  * SEIPA_next_ev
    00107  *
    00108  * Description: called when a snippet has been received,
    00109  *              before it is processed
    00110  *
    00111  * Input parameters: trace_req - array of trace request structures
    00112  *                   n_reqs - size of array
    00113  *                   output_dir - output directory
    00114  *                   e_date, e_time - event time in the form
    00115  *                                    'ccyymmdd' and 'hhmmss.ff'
    00116  *                   debug - flag for debugging output
    00117  * Output parameters: none
    00118  * Returns: EW_SUCCESS or EW_FAILURE
    00119  *
    00120  * Comments:
    00121  *
    00122  ***********************************************************************/
    00123 int SEIPA_next_ev (TRACE_REQ *trace_req, int n_reqs, char *output_dir,
    00124                    char *e_date, char *e_time, char *subnet, int debug)
    00125 {
    00126
    00127   int count;
    00128   double min_start_time, max_end_time;
    00129   TRACE_REQ *trace_req_ptr;
    00130
    00131
    00132   if (debug)
    00133   {
    00134     logit ("e", "Entering SEIPA_next_ev, date/time: %s %s\n", e_date, e_time);
    00135   }
    00136
    00137   /* calculate overall duration of all traces */
    00138   min_start_time = DBL_MAX;
    00139   max_end_time = 0.0;
    00140   for (count=0; count<n_reqs; count++)
    00141   {
    00142     trace_req_ptr = trace_req + count;
    00143     if (trace_req_ptr->reqStarttime < min_start_time)
    00144       min_start_time = trace_req_ptr->reqStarttime;
    00145     if (trace_req_ptr->reqEndtime > max_end_time)
    00146       max_end_time = trace_req_ptr->reqEndtime;
    00147   }
    00148   if (debug)
    00149   {
    00150     logit ("e", "Request details: %lf-%lf %s\n", min_start_time, max_end_time, trace_req->net);
    00151   }
    00152
    00153   /* open the SEIsan file */
    00154   /* changed by CJB 3/20/2002 to use subnet name if one exists */
    00155   if (subnet[0] != '\0')
    00156   {
    00157         if (! open_seisan_file (output_dir, subnet, min_start_time,
    00158                                       max_end_time - min_start_time, output_native_numbers))
    00159         {
    00160                 logit ("e", "SEIPA_init: unable to open Seisan output file\n");
    00161                 return EW_FAILURE;
    00162         }
    00163   }
    00164   else
    00165   {
    00166         if (! open_seisan_file (output_dir, trace_req->net, min_start_time,
    00167                                       max_end_time - min_start_time, output_native_numbers))
    00168         {
    00169                 logit ("e", "SEIPA_init: unable to open Seisan output file\n");
    00170                 return EW_FAILURE;
    00171         }
    00172   }
    00173
    00174   /* write the seisan event file headers */
    00175   for (count=0; count<n_reqs; count++)
    00176   {
    00177     trace_req_ptr = trace_req + count;
    00178     if (! add_seisan_channel (trace_req_ptr->sta, trace_req_ptr->chan))
    00179     {
    00180       logit ("e", "SEIPA_init: error writing to Seisan output file\n");
    00181       return EW_FAILURE;
    00182     }
    00183     if (debug)
    00184     {
    00185       logit ("e", "Channel %d/%d, %s %s %lf %lf\n",
    00186              count, n_reqs, trace_req->sta,
    00187              trace_req_ptr->chan, min_start_time,
    00188              trace_req_ptr->reqStarttime);
    00189     }
    00190   }
    00191
    00192   return EW_SUCCESS;
    00193
    00194 }
    00195
    00196 /*****************************************************************************
    00197  * SEIPA_next
    00198  *
    00199  * Description: called once for each trace to be put away
    00200  *
    00201  * Input parameters: trace_req - the data to be stored
    00202  *                   gap_thresh - size of any gap in seconds
    00203  *                   debug - flag for debugging output
    00204  * Output parameters: none
    00205  * Returns: EW_SUCCESS or EW_FAILURE
    00206  *
    00207  * Comments: see pa_find_data()
    00208  *
    00209  *****************************************************************************/
    00210 int SEIPA_next (TRACE_REQ *trace_req, double gap_thresh, int debug)
    00211
    00212 {
    00213
    00214   int status, loop_count;
    00215   short short_val;
    00216   long value, count;
    00217   float float_val;
    00218   double sample_time, double_val, data_end_time;
    00219   char *data_ptr;
    00220   struct Found_data data;
    00221
    00222
    00223   if (debug) logit ("e", "Entering SEIPA_next\n");
    00224
    00225   /* loop over the requested times for the data - the test for n_samples==0
    00226    * is an emergency condition that could happen with very bad floating point
    00227    * rounding errors (very unlikely though) */
    00228   data.n_samples = 1;
    00229   for (sample_time = trace_req->reqStarttime, loop_count = 0;
    00230        (sample_time < trace_req->reqEndtime) && (data.n_samples > 0);
    00231            sample_time += ((double) data.n_samples / data.sample_rate), loop_count ++)
    00232   {
    00233     /* get the data for this time */
    00234     status = pa_find_data (trace_req, sample_time, &data);
    00235     switch (status)
    00236         {
    00237     case FD_FOUND_REQUESTED:
    00238     case FD_FOUND_GAP:
    00239           break;
    00240     case FD_NO_MORE_DATA:
    00241       /* if no data has been found on previous calls, then exit
    00242            * so that no data will be recorded for this channel */
    00243           if (sample_time == trace_req->reqStarttime) return EW_SUCCESS;
    00244
    00245           /* otherwise calculate the size of the gap to the end of requested data */
    00246           data.n_samples = (long) (data.sample_rate * (trace_req->reqEndtime - sample_time));
    00247           break;
    00248
    00249     case FD_BAD_DATATYPE:
    00250       logit("e", "SEIPA_next: unrecognised data type code, skipping this scn: %s.%s.%s\n",
    00251             trace_req->sta, trace_req->chan, trace_req->net);
    00252       return EW_FAILURE;
    00253
    00254     case FD_CHANGED_SRATE:
    00255       logit("e", "SEIPA_next: bad sample rate, skipping this scn: %s.%s.%s\n",
    00256             trace_req->sta, trace_req->chan, trace_req->net);
    00257       return EW_FAILURE;
    00258         }
    00259
    00260     /* adjust the number of samples to ensure it doesn't go beyond the end time */
    00261         data_end_time = sample_time + ((double) data.n_samples / data.sample_rate);
    00262         if (data_end_time > trace_req->reqEndtime)
    00263           data.n_samples = (long) (data.sample_rate * (trace_req->reqEndtime - sample_time));
    00264     if (debug) logit ("e", "Loop %d: %s %ld @ %.1lfHz, time %.3lf\n",
    00265                       loop_count, status == FD_FOUND_REQUESTED ? "samples" : "gap",
    00266                                           data.n_samples, data.sample_rate, sample_time);
    00267
    00268     /* on the first time write the seisan channel header */
    00269     if (sample_time == trace_req->reqStarttime)
    00270         {
    00271       if (! start_seisan_channel (trace_req->sta, trace_req->chan,
    00272                                   sample_time, data.sample_rate,
    00273                                   (long) (data.sample_rate * (trace_req->reqEndtime - trace_req->reqStarttime))))
    00274           {
    00275         logit ("e", "SEIPA_next: error starting new Seisan channel\n");
    00276         return EW_FAILURE;
    00277           }
    00278         }
    00279
    00280         /* write the data */
    00281         value = SEISAN_MISSING_DATA_FLAG;
    00282         data_ptr = data.data;
    00283         for (count=0; count<data.n_samples; count++)
    00284         {
    00285           if (status == FD_FOUND_REQUESTED)
    00286           {
    00287                 switch (data.data_type_code)
    00288                 {
    00289                 /* write all values into longs regardless of input type */
    00290                 case FD_SHORT_INT:
    00291                   short_val = *((short *) data_ptr);
    00292           value = (long) short_val;
    00293                   data_ptr += sizeof (short);
    00294                   break;
    00295                 case FD_LONG_INT:
    00296                   value = *((long *) data_ptr);
    00297                   data_ptr += sizeof (long);
    00298                   break;
    00299                 case FD_FLOAT:
    00300                   float_val = *((float *) data_ptr);
    00301           value = (long) float_val;
    00302                   data_ptr += sizeof (float);
    00303                   break;
    00304                 case FD_DOUBLE:
    00305                   double_val = *((double *) data_ptr);
    00306           value = (long) double_val;
    00307                   data_ptr += sizeof (double);
    00308                   break;
    00309                 }
    00310           }
    00311       add_seisan_channel_data (1, &value);
    00312         }
    00313   }
    00314
    00315   /* stop writing on this channel and fill in any gap at the end of the data */
    00316   end_seisan_channel ();
    00317
    00318   if (debug)
    00319   {
    00320     logit ("e", "Successful completion of SEIPA_next\n");
    00321   }
    00322   return EW_SUCCESS;
    00323
    00324 }
    00325
    00326
    00327 /************************************************************************
    00328  * SEIPA_end_ev
    00329  *
    00330  * Description: called when an event has been completely processed
    00331  *
    00332  * Input parameters: debug - flag for debugging output
    00333  * Output parameters: none
    00334  * Returns: EW_SUCCESS or EW_FAILURE
    00335  *
    00336  * Comments:
    00337  *
    00338  *****************************************************************************/
    00339 int SEIPA_end_ev (int debug)
    00340
    00341 {
    00342
    00343   int ret_val;
    00344
    00345
    00346   if (debug)
    00347   {
    00348     logit ("e", "Entering SEIPA_end_ev\n");
    00349   }
    00350   ret_val = EW_SUCCESS;
    00351
    00352   /* check and close the Seisan file */
    00353   if (! close_seisan_file ())
    00354   {
    00355     logit ("e", "SEIPA_end_ev: error writing to Seisan file\n");
    00356     ret_val = EW_FAILURE;
    00357   }
    00358
    00359   return ret_val;
    00360
    00361 }
    00362
    00363 /************************************************************************
    00364  * SEIPA_close
    00365  *
    00366  * Description: called at program shutdown
    00367  *
    00368  * Input parameters: debug - flag for debugging output
    00369  * Output parameters: none
    00370  * Returns: EW_SUCCESS or EW_FAILURE
    00371  *
    00372  * Comments:
    00373  *
    00374  *****************************************************************************/
    00375 int SEIPA_close (int debug)
    00376 {
    00377
    00378   if (debug)
    00379   {
    00380     logit ("e", "Entering SEIPA_close\n");
    00381   }
    00382
    00383   return EW_SUCCESS;
    00384
    00385 }
    00386
    00387
    00388
    00389