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

Revision 3194, 19.5 KB checked in by paulf, 11 years ago (diff)

fixed an improper use of long for 4 byte sample data, some OS have long as 8bytes.

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