source: trunk/src/seismic_processing/pick_ew/pick_ew.c @ 2820

Revision 2820, 19.3 KB checked in by paulf, 12 years ago (diff)

fixed another time_t printing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1
2/*
3 *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
4 *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
5 *
6 *    $Id$
7 *
8 *    Revision history:
9 *     $Log$
10 *     Revision 1.13  2007/03/13 14:42:08  paulf
11 *     fixed another time_t printing
12 *
13 *     Revision 1.12  2007/02/26 14:01:10  paulf
14 *     fixed a heartbeat fix for long casting of time_t
15 *
16 *     Revision 1.11  2007/02/26 13:44:40  paulf
17 *     fixed heartbeat sprintf() to cast time_t as long
18 *
19 *     Revision 1.10  2006/09/20 22:44:07  dietz
20 *     Modified to be able to process multiple "StaFile" commands for setting
21 *     per-channel picking parameters.
22 *
23 *     Revision 1.9  2006/03/17 18:35:57  dietz
24 *     Added message logo and sequence number information to transport error
25 *     logging.
26 *
27 *     Revision 1.8  2005/04/08 23:57:19  dietz
28 *     Added new config command "GetLogo" so pick_ew can select which logos
29 *     to process. If no "GetLogo" commands are included, the default behavior
30 *     is to process all TYPE_TRACEBUF and TYPE_TRACEBUF2 messages in InRing.
31 *
32 *     Revision 1.7  2004/05/17 19:51:59  kohler
33 *     Fixed dangling-else bug.  WMK
34 *
35 *     Revision 1.6  2004/04/30 20:45:26  dietz
36 *     oops, forgot a semicolon
37 *
38 *     Revision 1.5  2004/04/30 20:43:36  dietz
39 *     made TypeTracebuf2 the primary logo msgtype
40 *
41 *     Revision 1.4  2004/04/29 22:44:51  kohler
42 *     Pick_ew now produces new TYPE_PICK_SCNL and TYPE_CODA_SCNL messages.
43 *     The station list file now contains SCNLs, rather than SCNs.
44 *     Input waveform messages may be of either TYPE_TRACEBUF or TYPE_TRACEBUF2.
45 *     If the input waveform message is of TYPE_TRACEBUF (without a location code),
46 *     the location code is assumed to be "--".  WMK 4/29/04
47 *
48 *     Revision 1.3  2002/05/16 16:59:42  patton
49 *     Made logit changes
50 *
51 *     Revision 1.2  2001/05/09 22:40:47  dietz
52 *     Changed to shut down gracefully if the transport flag is
53 *     set to TERMINATE or myPid.
54 *
55 *     Revision 1.1  2000/02/14 19:06:49  lucky
56 *     Initial revision
57 *
58 *
59 */
60
61      /*****************************************************************
62       *                           pick_ew.c                           *
63       *                                                               *
64       *  This is the new Earthworm picker.  The program uses          *
65       *  demultiplexed waveform data with header blocks consistent    *
66       *  with those in the CSS format, used by Datascope.  This       *
67       *  program can be used with analog or digital data sources.     *
68       *                                                               *
69       *  Written by Will Kohler, January, 1997                        *
70       *  Modified to use SCNs instead of pin numbers. 3/20/98 WMK     *
71       *                                                               *
72       *  Parameter names:                                             *
73       *                                                               *
74       *  Old name   New name                                          *
75       *  --------   --------                                          *
76       *     i5       Itr1                                             *
77       *     i6       MinSmallZC                                       *
78       *     i7       MinBigZC                                         *
79       *     i8       MinPeakSize                                      *
80       *     c1       RawDataFilt                                      *
81       *     c2       CharFuncFilt                                     *
82       *     c3       StaFilt                                          *
83       *     c4       LtaFilt                                          *
84       *     c5       EventThresh                                      *
85       *     c6       DeadSta                                          *
86       *     c7       CodaTerm                                         *
87       *     c8       AltCoda                                          *
88       *     c9       PreEvent                                         *
89       *     C4       RmavFilt                                         *
90       *   MAXMINT    MaxMint                                          *
91       *    EREFS     Erefs                                            *
92       *                                                               *
93       *****************************************************************/
94
95/* Y2K changes: The new pick and coda formats are PICK2K and CODA2K.
96   The PICK2K format contains a four-digit number for pick year.
97   The CODA2K format contains the SNC of the coda. (CODA2 codas didn't
98   contain SNC) */
99
100#include <stdio.h>
101#include <stdlib.h>
102#include <string.h>
103#include <sys/types.h>
104#include <time.h>
105#include <earthworm.h>
106#include <transport.h>
107#include <trace_buf.h>
108#include <swap.h>
109#include <trheadconv.h>
110#include "pick_ew.h"
111
112/* Function prototypes
113   *******************/
114int  GetConfig( char *, GPARM * );
115void LogConfig( GPARM * );
116int  GetStaList( STATION **, int *, GPARM * );
117void LogStaList( STATION *, int );
118void PickRA( STATION *, char *, GPARM *, EWH * );
119int  CompareSCNL( const void *, const void * );
120int  Restart( STATION *, GPARM *, int, int );
121void Interpolate( STATION *, char *, int );
122int  GetEwh( EWH * );
123void Sample( long, STATION * );
124
125   
126      /***********************************************************
127       *              The main program starts here.              *
128       *                                                         *
129       *  Argument:                                              *
130       *     argv[1] = Name of picker configuration file         *
131       ***********************************************************/
132
133int main( int argc, char **argv )
134{
135   int           i;                /* Loop counter */
136   STATION       *StaArray = NULL; /* Station array */
137   char          *TraceBuf;        /* Pointer to waveform buffer */
138   TRACE_HEADER  *TraceHead;       /* Pointer to trace header w/o loc code */
139   TRACE2_HEADER *Trace2Head;      /* Pointer to header with loc code */
140   long          *TraceLong;       /* Long pointer to waveform data */
141   short         *TraceShort;      /* Short pointer to waveform data */
142   long          MsgLen;           /* Size of retrieved message */
143   MSG_LOGO      logo;             /* Logo of retrieved msg */
144   MSG_LOGO      hrtlogo;          /* Logo of outgoing heartbeats */
145   int           Nsta = 0;         /* Number of stations in list */
146   time_t        then;             /* Previous heartbeat time */
147   long          InBufl;           /* Maximum message size in bytes */
148   GPARM         Gparm;            /* Configuration file parameters */
149   EWH           Ewh;              /* Parameters from earthworm.h */
150   char          *configfile;      /* Pointer to name of config file */
151   pid_t         myPid;            /* Process id of this process */
152
153/* Check command line arguments
154   ****************************/
155   if ( argc != 2 )
156   {
157      fprintf( stderr, "Usage: pick_ew <configfile>\n" );
158      return -1;
159   }
160   configfile = argv[1];
161
162/* Initialize name of log-file & open it
163   *************************************/
164   logit_init( configfile, 0, 256, 1 );
165
166/* Get parameters from the configuration files
167   *******************************************/
168   if ( GetConfig( configfile, &Gparm ) == -1 )
169   {
170      logit( "e", "pick_ew: GetConfig() failed. Exiting.\n" );
171      return -1;
172   }
173
174/* Look up info in the earthworm.h tables
175   **************************************/
176   if ( GetEwh( &Ewh ) < 0 )
177   {
178      logit( "e", "pick_ew: GetEwh() failed. Exiting.\n" );
179      return -1;
180   }
181
182/* Specify logos of incoming waveforms and outgoing heartbeats
183   ***********************************************************/
184   if( Gparm.nGetLogo == 0 ) 
185   {
186      Gparm.nGetLogo = 2;
187      Gparm.GetLogo  = (MSG_LOGO *) calloc( Gparm.nGetLogo, sizeof(MSG_LOGO) );
188      if( Gparm.GetLogo == NULL ) {
189         logit( "e", "pick_ew: Error allocating space for GetLogo. Exiting\n" );
190         return -1;
191      }
192      Gparm.GetLogo[0].instid = Ewh.InstIdWild;
193      Gparm.GetLogo[0].mod    = Ewh.ModIdWild;
194      Gparm.GetLogo[0].type   = Ewh.TypeTracebuf2;
195
196      Gparm.GetLogo[1].instid = Ewh.InstIdWild;
197      Gparm.GetLogo[1].mod    = Ewh.ModIdWild;
198      Gparm.GetLogo[1].type   = Ewh.TypeTracebuf;
199   }
200
201   hrtlogo.instid = Ewh.MyInstId;
202   hrtlogo.mod    = Gparm.MyModId;
203   hrtlogo.type   = Ewh.TypeHeartBeat;
204
205/* Get our own pid for restart purposes
206   ************************************/
207   myPid = getpid();
208   if ( myPid == -1 )
209   {
210      logit( "e", "pick_ew: Can't get my pid. Exiting.\n" );
211      free( Gparm.GetLogo );
212      free( Gparm.StaFile );
213      return -1;
214   }
215
216/* Log the configuration parameters
217   ********************************/
218   LogConfig( &Gparm );
219
220/* Allocate the waveform buffer
221   ****************************/
222   InBufl = MAX_TRACEBUF_SIZ*2 + sizeof(long)*(Gparm.MaxGap-1);
223   TraceBuf = (char *) malloc( (size_t) InBufl );
224   if ( TraceBuf == NULL )
225   {
226      logit( "et", "pick_ew: Cannot allocate waveform buffer\n" );
227      free( Gparm.GetLogo );
228      free( Gparm.StaFile );
229      return -1;
230   }
231
232/* Point to header and data portions of waveform message
233   *****************************************************/
234   TraceHead  = (TRACE_HEADER *)TraceBuf;
235   Trace2Head = (TRACE2_HEADER *)TraceBuf;
236   TraceLong  = (long *) (TraceBuf + sizeof(TRACE_HEADER));
237   TraceShort = (short *) (TraceBuf + sizeof(TRACE_HEADER));
238
239/* Read the station list and return the number of stations found.
240   Allocate the station list array.
241   *************************************************************/
242   if ( GetStaList( &StaArray, &Nsta, &Gparm ) == -1 )
243   {
244      logit( "e", "pick_ew: GetStaList() failed. Exiting.\n" );
245      free( Gparm.GetLogo );
246      free( Gparm.StaFile );
247      free( StaArray );
248      return -1;
249   }
250
251   if ( Nsta == 0 )
252   {
253      logit( "et", "pick_ew: Empty station list(s). Exiting." );
254      free( Gparm.GetLogo );
255      free( Gparm.StaFile );
256      free( StaArray );
257      return -1;
258   }
259
260/* Sort the station list by SCNL
261   *****************************/
262   qsort( StaArray, Nsta, sizeof(STATION), CompareSCNL );
263
264/* Log the station list
265   ********************/
266   LogStaList( StaArray, Nsta );
267
268/* Attach to existing transport rings
269   **********************************/
270   if ( Gparm.OutKey != Gparm.InKey )
271   {
272      tport_attach( &Gparm.InRegion,  Gparm.InKey );
273      tport_attach( &Gparm.OutRegion, Gparm.OutKey );
274   }
275   else
276   {
277      tport_attach( &Gparm.InRegion, Gparm.InKey );
278      Gparm.OutRegion = Gparm.InRegion;
279   }
280
281/* Flush the input ring
282   ********************/
283   while ( tport_getmsg( &Gparm.InRegion, Gparm.GetLogo, (short)Gparm.nGetLogo, 
284                         &logo, &MsgLen, TraceBuf, MAX_TRACEBUF_SIZ) != 
285                         GET_NONE );
286
287/* Get the time when we start reading messages.
288   This is for issuing heartbeats.
289   *******************************************/
290   time( &then );
291
292/* Loop to read waveform messages and invoke the picker
293   ****************************************************/
294   while ( tport_getflag( &Gparm.InRegion ) != TERMINATE  &&
295           tport_getflag( &Gparm.InRegion ) != myPid )
296   {
297      char    type[3];
298      STATION key;              /* Key for binary search */
299      STATION *Sta;             /* Pointer to the station being processed */
300      int     rc;               /* Return code from tport_copyfrom() */
301      time_t  now;              /* Current time */
302      double  GapSizeD;         /* Number of missing samples (double) */
303      long    GapSize;          /* Number of missing samples (integer) */
304      unsigned char seq;        /* msg sequence number from tport_copyfrom() */
305
306/* Get tracebuf or tracebuf2 message from ring
307   *******************************************/
308      rc = tport_copyfrom( &Gparm.InRegion, Gparm.GetLogo, (short)Gparm.nGetLogo, 
309                           &logo, &MsgLen, TraceBuf, MAX_TRACEBUF_SIZ, &seq );
310
311      if ( rc == GET_NONE )
312      {
313         sleep_ew( 100 );
314         continue;
315      }
316
317      if ( rc == GET_NOTRACK )
318         logit( "et", "pick_ew: Tracking error (NTRACK_GET exceeded)\n");
319
320      if ( rc == GET_MISS_LAPPED )
321         logit( "et", "pick_ew: Missed msgs (lapped on ring) "
322                "before i:%d m:%d t:%d seq:%d\n",
323                (int)logo.instid, (int)logo.mod, (int)logo.type, (int)seq );
324
325      if ( rc == GET_MISS_SEQGAP )
326         logit( "et", "pick_ew: Gap in sequence# before i:%d m:%d t:%d seq:%d\n",
327                (int)logo.instid, (int)logo.mod, (int)logo.type, (int)seq );
328
329      if ( rc == GET_TOOBIG )
330      {
331         logit( "et", "pick_ew: Retrieved msg is too big: i:%d m:%d t:%d len:%d\n",
332                (int)logo.instid, (int)logo.mod, (int)logo.type, MsgLen );
333         continue;
334      }
335
336/* If necessary, swap bytes in tracebuf message
337   ********************************************/
338      if ( logo.type == Ewh.TypeTracebuf )
339      {
340         if ( WaveMsgMakeLocal( TraceHead ) < 0 )
341         {
342            logit( "et", "pick_ew: WaveMsgMakeLocal() error.\n" );
343            continue;
344         }
345      }
346      else
347         if ( WaveMsg2MakeLocal( Trace2Head ) < 0 )
348         {
349            logit( "et", "pick_ew: WaveMsg2MakeLocal error.\n" );
350            continue;
351         }
352
353/* Convert TYPE_TRACEBUF messages to TYPE_TRACEBUF2
354   ************************************************/
355      if ( logo.type == Ewh.TypeTracebuf )
356         Trace2Head = TrHeadConv( TraceHead );
357
358/* Look up SCNL number in the station list
359   ***************************************/
360      {
361         int j;
362         for ( j = 0; j < 5; j++ ) key.sta[j]  = Trace2Head->sta[j];
363         key.sta[5] = '\0';
364         for ( j = 0; j < 3; j++ ) key.chan[j] = Trace2Head->chan[j];
365         key.chan[3] = '\0';
366         for ( j = 0; j < 2; j++ ) key.net[j]  = Trace2Head->net[j];
367         key.net[2] = '\0';
368         for ( j = 0; j < 2; j++ ) key.loc[j]  = Trace2Head->loc[j];
369         key.loc[2] = '\0';
370      }
371
372      Sta = (STATION *) bsearch( &key, StaArray, Nsta, sizeof(STATION),
373                                 CompareSCNL );
374
375      if ( Sta == NULL )      /* SCNL not found */
376         continue;
377
378/* Do this the first time we get a message with this SCNL
379   ******************************************************/
380      if ( Sta->first == 1 )
381      {
382         Sta->endtime = Trace2Head->endtime;
383         Sta->first = 0;
384         continue;
385      }
386
387/* If the samples are shorts, make them longs
388   ******************************************/
389      strcpy( type, Trace2Head->datatype );
390
391      if ( (strcmp(type,"i2")==0) || (strcmp(type,"s2")==0) )
392      {
393         for ( i = Trace2Head->nsamp - 1; i > -1; i-- )
394            TraceLong[i] = (long)TraceShort[i];
395      }
396
397/* Compute the number of samples since the end of the previous message.
398   If (GapSize == 1), no data has been lost between messages.
399   If (1 < GapSize <= Gparm.MaxGap), data will be interpolated.
400   If (GapSize > Gparm.MaxGap), the picker will go into restart mode.
401   *******************************************************************/
402      GapSizeD = Trace2Head->samprate * (Trace2Head->starttime - Sta->endtime);
403
404      if ( GapSizeD < 0. )          /* Invalid. Time going backwards. */
405         GapSize = 0;
406      else
407         GapSize  = (long) (GapSizeD + 0.5);
408
409/* Interpolate missing samples and prepend them to the current message
410   *******************************************************************/
411      if ( (GapSize > 1) && (GapSize <= Gparm.MaxGap) )
412         Interpolate( Sta, TraceBuf, GapSize );
413
414/* Announce large sample gaps
415   **************************/
416      if ( GapSize > Gparm.MaxGap )
417      {
418         int      lineLen;
419         time_t   errTime;
420         char     errmsg[80];
421         MSG_LOGO logo;
422
423         time( &errTime );
424         sprintf( errmsg,
425               "%ld %d Found %4d sample gap. Restarting channel %s.%s.%s.%s\n",
426               (long) errTime, PK_RESTART, GapSize, Sta->sta, Sta->chan, Sta->net, Sta->loc );
427         lineLen = strlen( errmsg );
428         logo.type   = Ewh.TypeError;
429         logo.mod    = Gparm.MyModId;
430         logo.instid = Ewh.MyInstId;
431         tport_putmsg( &Gparm.OutRegion, &logo, lineLen, errmsg );
432      }
433
434/* For big gaps, enter restart mode. In restart mode, calculate
435   STAs and LTAs without picking.  Start picking again after a
436   specified number of samples has been processed.
437   *************************************************************/
438      if ( Restart( Sta, &Gparm, Trace2Head->nsamp, GapSize ) )
439      {
440         for ( i = 0; i < Trace2Head->nsamp; i++ )
441            Sample( TraceLong[i], Sta );
442      }
443      else
444         PickRA( Sta, TraceBuf, &Gparm, &Ewh );
445
446/* Save time and amplitude of the end of the current message
447   *********************************************************/
448      Sta->enddata = TraceLong[Trace2Head->nsamp - 1];
449      Sta->endtime = Trace2Head->endtime;
450
451/* Send a heartbeat to the transport ring
452   **************************************/
453      time( &now );
454      if ( (now - then) >= Gparm.HeartbeatInt )
455      {
456         int  lineLen;
457         char line[40];
458
459         then = now;
460
461         sprintf( line, "%ld %d\n", (long) now, (int) myPid );
462         lineLen = strlen( line );
463
464         if ( tport_putmsg( &Gparm.OutRegion, &hrtlogo, lineLen, line ) !=
465              PUT_OK )
466         {
467            logit( "et", "pick_ew: Error sending heartbeat. Exiting." );
468            break;
469         }
470      }
471   }
472
473/* Detach from the ring buffers
474   ****************************/
475   if ( Gparm.OutKey != Gparm.InKey )
476   {
477      tport_detach( &Gparm.InRegion );
478      tport_detach( &Gparm.OutRegion );
479   }
480   else
481      tport_detach( &Gparm.InRegion );
482
483   logit( "t", "Termination requested. Exiting.\n" );
484   free( Gparm.GetLogo );
485   free( Gparm.StaFile );
486   free( StaArray );
487   return 0;
488}
489
490
491      /*******************************************************
492       *                      GetEwh()                       *
493       *                                                     *
494       *      Get parameters from the earthworm.h file.      *
495       *******************************************************/
496
497int GetEwh( EWH *Ewh )
498{
499   if ( GetLocalInst( &Ewh->MyInstId ) != 0 )
500   {
501      logit( "e", "pick_ew: Error getting MyInstId.\n" );
502      return -1;
503   }
504
505   if ( GetInst( "INST_WILDCARD", &Ewh->InstIdWild ) != 0 )
506   {
507      logit( "e", "pick_ew: Error getting InstIdWild.\n" );
508      return -2;
509   }
510   if ( GetModId( "MOD_WILDCARD", &Ewh->ModIdWild ) != 0 )
511   {
512      logit( "e", "pick_ew: Error getting ModIdWild.\n" );
513      return -3;
514   }
515   if ( GetType( "TYPE_HEARTBEAT", &Ewh->TypeHeartBeat ) != 0 )
516   {
517      logit( "e", "pick_ew: Error getting TypeHeartbeat.\n" );
518      return -4;
519   }
520   if ( GetType( "TYPE_ERROR", &Ewh->TypeError ) != 0 )
521   {
522      logit( "e", "pick_ew: Error getting TypeError.\n" );
523      return -5;
524   }
525   if ( GetType( "TYPE_PICK_SCNL", &Ewh->TypePickScnl ) != 0 )
526   {
527      logit( "e", "pick_ew: Error getting TypePickScnl.\n" );
528      return -6;
529   }
530   if ( GetType( "TYPE_CODA_SCNL", &Ewh->TypeCodaScnl ) != 0 )
531   {
532      logit( "e", "pick_ew: Error getting TypeCodaScnl.\n" );
533      return -7;
534   }
535   if ( GetType( "TYPE_TRACEBUF", &Ewh->TypeTracebuf ) != 0 )
536   {
537      logit( "e", "pick_ew: Error getting TYPE_TRACEBUF.\n" );
538      return -8;
539   }
540   if ( GetType( "TYPE_TRACEBUF2", &Ewh->TypeTracebuf2 ) != 0 )
541   {
542      logit( "e", "pick_ew: Error getting TYPE_TRACEBUF2.\n" );
543      return -9;
544   }
545   return 0;
546}
547
Note: See TracBrowser for help on using the repository browser.