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

# rw_strongmotionII.c

Go to the documentation of this file.

    00001 /*
    00002  *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
    00003  *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
    00004  *
    00005  *    $Id: rw__strongmotionII_8c-source.html 2161 2006-05-19 16:55:03Z paulf $
    00006  *
    00007  *    Revision history:
    00008  *     $Log$
    00008  *     Revision 1.1  2006/05/19 16:55:02  paulf
    00008  *     first inclusion
    00008  *
    00009  *     Revision 1.3  2001/06/19 17:26:02  dietz
    00010  *     Fixed wr_strongmotionII to print SM_NULL values properly (it had been
    00011  *     taking the absolute value of them by mistake)
    00012  *
    00013  *     Revision 1.2  2001/04/18 17:56:27  dietz
    00014  *     wr_strongmotionII: made sure pga,pgv,pgd are written as absolute values
    00015  *
    00016  *     Revision 1.1  2001/04/17 17:25:46  davidk
    00017  *     Initial revision
    00018  *
    00019  *
    00020  *
    00021  */
    00022
    00023 /* rw_strongmotionII.c
    00024  *
    00025  * Contains functions in that convert from a
    00026  * TYPE_STRONGMOTION message to a structure and visa versa.
    00027  *
    00028  * written by Lynn Dietz   October, 1999
    00029  */
    00030
    00031 #include <stdio.h>
    00032 #include <string.h>
    00033 #include <time.h>
    00034 #include <chron3.h>
    00035 #include <time_ew.h>
    00036 #include <rw_strongmotionII.h>
    00037
    00038 #define ABS(X) (((X) >= 0) ? (X) : -(X))
    00039
    00040 void logit( char *, char *, ... );   /* logit.c      sys-independent  */
    00041 static int   strappend( char *s1, int s1max, char *s2 );
    00042 static int   tokenlength( char *begtok, char c );
    00043 static char *datestr24( double t, char *pbuf, int len );
    00044 static int   addtimestr( char *buf, int buflen, double t );
    00045
    00046 static char *sNullDate = "0000/00/00 00:00:00.000";
    00047 static char *sUnknown  = "?";
    00048
    00049 /********************************************************************
    00050  * rd_strongmotionII()                                              *
    00051  * Reads an ascii TYPE_STRONGMOTION2 message and fills in a SM_INFO *
    00052  * structure.                                                       *
    00053  * Returns 0 on success, -1 on failure                              *
    00054  ********************************************************************/
    00055 int rd_strongmotionII( char *msg, int msglen, SM_INFO *sm )
    00056 {
    00057    char     *line;      /* pointer to current line in msg */
    00058    char     *nextline;  /* working pointer into msg */
    00059    char     *begtok;    /* points to the beginning of this token */
    00060    char     *endline;   /* points at end of line */
    00061    int       len;       /* length (bytes) of the next token */
    00062    int       nline;     /* number of lines read from msg so far */
    00063    int       nfreq;
    00064    int       i;
    00065    struct tm stm;       /* time structure for timestamp */
    00066    time_t    tsec;      /* timestamp in whole sec since 1970 */
    00067    int       msec;      /* thousandths of seconds field of timestamp */
    00068
    00069
    00070    memset( sm, 0, sizeof(SM_INFO) );     /* zero output structure */
    00071    nextline = msg;
    00072    nline = 0;
    00073    nfreq = 0;
    00074
    00075
    00076 /* Read next line from the message into working buffer */
    00077    while( nextline < (msg+msglen-1) )
    00078    {
    00079      line    = nextline;
    00080      len     = tokenlength( line, '\n' );
    00081      endline = line + len;
    00082      nline++;
    00083      nextline += len + 1;
    00084
    00085  /* First line = SCNL name */
    00086      if( nline == 1 )
    00087      {
    00088        if( strncmp(line,"SCNL:", 5) != 0 ) return( -1 );
    00089        begtok = line + 5;
    00090
    00091        while( begtok[0] == ' ' ) begtok++;    /* go to 1st non-blank char */
    00092        if( begtok >= endline ) return( -1 );
    00093        len = tokenlength( begtok, '.' );
    00094        if( len >= TRACE_STA_LEN ) return( -1 );
    00095        strncpy( sm->sta, begtok, len );
    00096        begtok += len + 1;
    00097
    00098        if( begtok >= endline ) return( -1 );
    00099        len = tokenlength( begtok, '.' );
    00100        if( len >= TRACE_CHAN_LEN ) return( -1 );
    00101        strncpy( sm->comp, begtok, len );
    00102        begtok += len + 1;
    00103
    00104        if( begtok >= endline ) return( -1 );
    00105        len = tokenlength( begtok, '.' );
    00106        if( len >= TRACE_NET_LEN ) return( -1 );
    00107        strncpy( sm->net, begtok, len );
    00108        begtok += len + 1;
    00109
    00110        if( begtok > endline ) return( -1 );
    00111        len = tokenlength( begtok, '\n' );
    00112        if( len >= TRACE_LOC_LEN ) return( -1 );
    00113        strncpy( sm->loc, begtok, len );
    00114      }
    00115
    00116   /* Second line = timestamp from field unit */
    00117      else if( nline == 2 )
    00118      {
    00119        memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */
    00120        if( sscanf( line, "TIME: %d/%d/%d %d:%d:%d.%d",
    00121                   &stm.tm_year, &stm.tm_mon, &stm.tm_mday, &stm.tm_hour,
    00122                   &stm.tm_min, &stm.tm_sec, &msec ) != 7 ) return( -1 );
    00123        stm.tm_year -= 1900;  /* to convert to definition of struct tm */
    00124        stm.tm_mon  -= 1;     /* to convert to definition of struct tm */
    00125        tsec  = timegm( &stm );
    00126        sm->t = (double)tsec + 0.001*(double)msec;
    00127      }
    00128
    00129   /* Third line = alternate timestamp and its code */
    00130      else if( nline == 3 )
    00131      {
    00132        memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */
    00133        if( sscanf( line, "ALT: %d/%d/%d %d:%d:%d.%d CODE: %d",
    00134                   &stm.tm_year, &stm.tm_mon, &stm.tm_mday, &stm.tm_hour,
    00135                   &stm.tm_min, &stm.tm_sec, &msec, &(sm->altcode) ) != 8 )
    00136                   return( -1 );
    00137        if( stm.tm_year == 0 ) {
    00138          sm->talt = 0.0;
    00139        } else {
    00140          stm.tm_year -= 1900;  /* to convert to definition of struct tm */
    00141          stm.tm_mon  -= 1;     /* to convert to definition of struct tm */
    00142          tsec  = timegm( &stm );
    00143          sm->talt = (double)tsec + 0.001*(double)msec;
    00144        }
    00145      }
    00146
    00147   /* Fourth line = peak acceleration values */
    00148      else if( nline == 4 )
    00149      {
    00150        memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */
    00151        if( sscanf( line, "PGA: %lf TPGA: %d/%d/%d %d:%d:%d.%d",
    00152                   &(sm->pga), &stm.tm_year, &stm.tm_mon, &stm.tm_mday,
    00153                   &stm.tm_hour, &stm.tm_min, &stm.tm_sec, &msec ) != 8 )
    00154                   return( -1 );
    00155        if( stm.tm_year == 0 ) {
    00156          sm->tpga = 0.0;
    00157        } else {
    00158          stm.tm_year -= 1900;  /* to convert to definition of struct tm */
    00159          stm.tm_mon  -= 1;     /* to convert to definition of struct tm */
    00160          tsec  = timegm( &stm );
    00161          sm->tpga = (double)tsec + 0.001*(double)msec;
    00162        }
    00163      }
    00164
    00165   /* Fifth line = peak velocity values */
    00166      else if( nline == 5 )
    00167      {
    00168        memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */
    00169        if( sscanf( line, "PGV: %lf TPGV: %d/%d/%d %d:%d:%d.%d",
    00170                   &(sm->pgv), &stm.tm_year, &stm.tm_mon, &stm.tm_mday,
    00171                   &stm.tm_hour, &stm.tm_min, &stm.tm_sec, &msec ) != 8 )
    00172                   return( -1 );
    00173        if( stm.tm_year == 0 ) {
    00174          sm->tpgv = 0.0;
    00175        } else {
    00176          stm.tm_year -= 1900;  /* to convert to definition of struct tm */
    00177          stm.tm_mon  -= 1;     /* to convert to definition of struct tm */
    00178          tsec  = timegm( &stm );
    00179          sm->tpgv = (double)tsec + 0.001*(double)msec;
    00180        }
    00181      }
    00182
    00183   /* Sixth line = peak displacement values */
    00184      else if( nline == 6 )
    00185      {
    00186        memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */
    00187        if( sscanf( line, "PGD: %lf TPGD: %d/%d/%d %d:%d:%d.%d",
    00188                   &(sm->pgd), &stm.tm_year, &stm.tm_mon, &stm.tm_mday,
    00189                   &stm.tm_hour, &stm.tm_min, &stm.tm_sec, &msec ) != 8 )
    00190                   return( -1 );
    00191        if( stm.tm_year == 0 ) {
    00192          sm->tpgd = 0.0;
    00193        } else {
    00194          stm.tm_year -= 1900;  /* to convert to definition of struct tm */
    00195          stm.tm_mon  -= 1;     /* to convert to definition of struct tm */
    00196          tsec  = timegm( &stm );
    00197          sm->tpgd = (double)tsec + 0.001*(double)msec;
    00198        }
    00199      }
    00200
    00201   /* Seventh line = response spectral acceleration */
    00202      else if( nline == 7 )
    00203      {
    00204        if( sscanf( line, "RSA: %d", &(sm->nrsa) ) != 1 ) return( -1 );
    00205        if( sm->nrsa > SM_MAX_RSA ) return( -1 );
    00206        begtok = line;
    00207        for( i=0; i<sm->nrsa; i++ )
    00208        {
    00209          begtok += tokenlength( begtok, '/' ) + 1;
    00210          if( begtok >= endline ) return( -1 );
    00211          if( sscanf( begtok, "%lf %lf",
    00212                     &(sm->pdrsa[i]), &(sm->rsa[i]) ) != 2 ) return( -1 );
    00213        }
    00214      }
    00215
    00216   /* Eighth line = eventid and author */
    00217      else if( nline == 8 )
    00218      {
    00219        if( strncmp(line,"QID:", 4) != 0 ) return( -1 );
    00220        begtok = line + 4;
    00221
    00222        while( begtok[0] == ' ' ) begtok++;    /* go to 1st non-blank char */
    00223        if( begtok >= endline ) return( -1 );
    00224        len = tokenlength( begtok, ' ' );
    00225        if( len >= EVENTID_SIZE ) return( -1 );
    00226        strncpy( sm->qid, begtok, len );
    00227        if( strcmp( sm->qid, sUnknown ) == 0 ) sm->qid[0] = '\0';
    00228        begtok += len + 1;
    00229
    00230        while( begtok[0] == ' ' ) begtok++;    /* go to 1st non-blank char */
    00231        if( begtok >= endline ) return( -1 );
    00232        len = tokenlength( begtok, '\n' );
    00233        if( len >= AUTHOR_FIELD_SIZE ) return( -1 );
    00234        strncpy( sm->qauthor, begtok, len );
    00235        if( strcmp( sm->qauthor, sUnknown ) == 0 ) sm->qauthor[0] = '\0';
    00236      }
    00237
    00238    } /*end while*/
    00239
    00240
    00241    return( 0 );
    00242 }
    00243
    00244 /********************************************************************
    00245  * wr_strongmotionII()                                              *
    00246  * Reads a SM_INFO structure and writes an ascii TYPE_STRONGMOTION2 *
    00247  * message (null terminated)                                        *
    00248  * Returns 0 on success, -1 on failure (buffer overflow)            *
    00249  ********************************************************************/
    00250 int wr_strongmotionII( SM_INFO *sm, char *buf, int buflen )
    00251 {
    00252    char     tmp[256]; /* working buffer */
    00253    char    *qid;
    00254    char    *qauthor;
    00255    int      i;
    00256
    00257    memset( buf, 0, (size_t)buflen );    /* zero output buffer */
    00258
    00259 /* channel codes */
    00260    sprintf( buf, "SCNL: %s.%s.%s.%s",
    00261             sm->sta, sm->comp, sm->net, sm->loc );
    00262
    00263 /* field time */
    00264    if( strappend( buf, buflen, "\nTIME: " ) ) return ( -1 );
    00265    datestr24( sm->t, tmp, 256 );
    00266    if( strappend( buf, buflen, tmp ) ) return( -1 );
    00267
    00268 /* alternate time & its code */
    00269    if( strappend( buf, buflen, "\nALT: " ) ) return ( -1 );
    00270    if( addtimestr( buf, buflen, sm->talt ) ) return ( -1 );
    00271    sprintf( tmp, " CODE: %d", sm->altcode );
    00272    if( strappend( buf, buflen, tmp ) ) return( -1 );
    00273
    00274 /* Print peak acceleration value & time */
    00275    sprintf( tmp, "\nPGA: %.6lf TPGA: ", (sm->pga!=SM_NULL ? ABS(sm->pga) : sm->pga) );
    00276    if( strappend( buf, buflen, tmp ) ) return( -1 );
    00277    if( addtimestr( buf, buflen, sm->tpga ) ) return ( -1 );
    00278
    00279 /* Print peak velocity value & time */
    00280    sprintf( tmp, "\nPGV: %.6lf TPGV: ", (sm->pgv!=SM_NULL ? ABS(sm->pgv) : sm->pgv) );
    00281    if( strappend( buf, buflen, tmp ) ) return( -1 );
    00282    if( addtimestr( buf, buflen, sm->tpgv ) ) return ( -1 );
    00283
    00284 /* Print peak displacement value & time */
    00285    sprintf( tmp, "\nPGD: %.6lf TPGD: ", (sm->pgd!=SM_NULL ? ABS(sm->pgd) : sm->pgd) );
    00286    if( strappend( buf, buflen, tmp ) ) return( -1 );
    00287    if( addtimestr( buf, buflen, sm->tpgd ) ) return ( -1 );
    00288
    00289 /* Print the response spectrum */
    00290    sprintf( tmp, "\nRSA: %d", sm->nrsa );
    00291    if( strappend( buf, buflen, tmp ) ) return( -1 );
    00292    for( i=0; i<sm->nrsa; i++ )
    00293    {
    00294      sprintf( tmp, "/%.2lf %.6lf", sm->pdrsa[i], sm->rsa[i] );
    00295      if( strappend( buf, buflen, tmp ) ) return( -1 );
    00296    }
    00297
    00298 /* Print the eventid & event author */
    00299    qid     = sm->qid;
    00300    qauthor = sm->qauthor;
    00301    if( strlen(qid)     == 0 ) qid     = sUnknown;
    00302    if( strlen(qauthor) == 0 ) qauthor = sUnknown;
    00303    sprintf( tmp, "\nQID: %s %s\n", qid, qauthor );
    00304    if( strappend( buf, buflen, tmp ) ) return( -1 );
    00305
    00306    return( 0 );
    00307 }
    00308
    00309
    00310
    00311 /********************************************************************
    00312  * log_strongmotionII()                                             *
    00313  * Writes the contents of a SM_INFO structure to an Earthworm       *
    00314  * log file                                                         *
    00315  ********************************************************************/
    00316 void log_strongmotionII( SM_INFO *sm )
    00317 {
    00318    char date[30];
    00319    int  i;
    00320
    00321    logit("", "SCNL: %s.%s.%s.%s\n",
    00322            sm->sta, sm->comp, sm->net, sm->loc );
    00323
    00324 /* Log time values */
    00325    datestr24( sm->t, date, 30 );
    00326    logit("", "Time: %s  (%.3lf)\n", date, sm->t );
    00327    datestr24( sm->talt, date, 30 );
    00328    logit("", "Alt:  %s  (%.3lf)  code: %d\n",
    00329             date, sm->talt, sm->altcode );
    00330
    00331
    00332 /* Print peak acceleration values */
    00333    datestr24( sm->tpga, date, 30 );
    00334    logit("", "PGA: %.6lf  TGPA: %s (%.3lf)\n",
    00335             sm->pga, date, sm->tpga );
    00336
    00337 /* Print peak velocity values */
    00338    datestr24( sm->tpgv, date, 30 );
    00339    logit("", "PGV: %.6lf  TGPV: %s (%.3lf)\n",
    00340             sm->pgv, date, sm->tpgv );
    00341
    00342 /* Print peak displacement values */
    00343    datestr24( sm->tpgd, date, 30 );
    00344    logit("", "PGD: %.6lf  TGPD: %s (%.3lf)\n",
    00345             sm->pgd, date, sm->tpgd );
    00346
    00347
    00348 /* Print number of points in the response spectrum */
    00349    logit("","RSA: %d ", sm->nrsa );
    00350    for( i=0; i<sm->nrsa; i++ )
    00351    {
    00352       logit("", " /%.2lf %.6lf", sm->pdrsa[i], sm->rsa[i] );
    00353    }
    00354
    00355 /* Print eventid & author */
    00356    logit("","\nQID: %s %s\n", sm->qid, sm->qauthor);
    00357
    00358    return;
    00359 }
    00360
    00361
    00362 /**********************************************************
    00363  * Converts time (double, seconds since 1970:01:01) to    *
    00364  * a 23-character, null-terminated string in the form of  *
    00365  *            yyyy/mm/dd hh:mm:ss.sss                     *
    00366  * Time is displayed in UTC                               *
    00367  * Target buffer must be 24-chars long to have room for   *
    00368  * null-character                                         *
    00369  **********************************************************/
    00370 char *datestr24( double t, char *pbuf, int len )
    00371 {
    00372    time_t    tt;       /* time as time_t                  */
    00373    struct tm stm;      /* time as struct tm               */
    00374    int       t_msec;   /* milli-seconds part of time      */
    00375
    00376 /* Make sure target is big enough
    00377  ********************************/
    00378    if( len < 24 ) return( (char *)NULL );
    00379
    00380 /* Convert double time to other formats
    00381  **************************************/
    00382    t += 0.0005;  /* prepare to round to the nearest 1000th */
    00383    tt     = (time_t) t;
    00384    t_msec = (int)( (t - tt) * 1000. );
    00385    gmtime_ew( &tt, &stm );
    00386
    00387 /* Build character string
    00388  ************************/
    00389    sprintf( pbuf,
    00390            "%04d/%02d/%02d %02d:%02d:%02d.%03d",
    00391             stm.tm_year+1900,
    00392             stm.tm_mon+1,
    00393             stm.tm_mday,
    00394             stm.tm_hour,
    00395             stm.tm_min,
    00396             stm.tm_sec,
    00397             t_msec );
    00398
    00399    return( pbuf );
    00400 }
    00401
    00402
    00403 /********************************************************************
    00404  * addtimestr() append a date string to the end of existing string  *
    00405  *   Return -1 if result would overflow the target,                 *
    00406  *           0 if everything went OK                                *
    00407  ********************************************************************/
    00408 int addtimestr( char *buf, int buflen, double t )
    00409 {
    00410    char tmp[30];
    00411
    00412    if( t == 0.0 )
    00413    {
    00414      if( strappend( buf, buflen, sNullDate ) ) return( -1 );
    00415    } else {
    00416      datestr24( t, tmp, 30 );
    00417      if( strappend( buf, buflen, tmp ) ) return( -1 );
    00418    }
    00419    return( 0 );
    00420 }
    00421
    00422 /********************************************************************
    00423  * strappend() append second null-terminated character string to    *
    00424  * the first as long as there's enough room in the target buffer    *
    00425  * for both strings and the null-byte                               *
    00426  ********************************************************************/
    00427 int strappend( char *s1, int s1max, char *s2 )
    00428 {
    00429    if( (int)strlen(s1)+(int)strlen(s2)+1 > s1max ) return( -1 );
    00430    strcat( s1, s2 );
    00431    return( 0 );
    00432 }
    00433
    00434 /********************************************************************
    00435  * tokenlength() given a null-terminated character string and a     *
    00436  * character that delimits the end of a token, tokenlength returns  *
    00437  * the length (in bytes) of the next token. If the character wasn't *
    00438  * found, tokenlength returns the length of the string.             *
    00439  ********************************************************************/
    00440 int tokenlength( char *begtok, char c )
    00441 {
    00442    char    *endtok;   /* points to the end of this token */
    00443
    00444    endtok = strchr( begtok, c );
    00445    if( endtok == NULL ) return( (int)strlen(begtok) );
    00446    return( (int)(endtok-begtok) );
    00447 }
    00448
    00449
    00450 /* Sample TYPE_STRONGMOTION2 message (between ------):
    00451 ------------------------------------------------
    00452 SCNL: CMB.BHZ.BK.
    00453 TIME: 2001/02/25 02:37:00.000
    00454 ALT:  2001/02/25 02:40:40.000 CODE: 1
    00455 PGA: 6.846210 TPGA: 2001/02/25 02:37:00.000
    00456 PGV: 0.140000 TPGV: 2001/02/25 02:37:00.000
    00457 PGD: 0.000000 TPGD: 2001/02/25 02:37:00.000
    00458 RSA: 3/0.30 4.415404/1.00 0.925639/3.00 0.297907
    00459 QID: 41059467 014024003:UCB
    00460 ------------------------------------------------
    00461 */