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 */