00001 00002 /* 00003 * THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE 00004 * CHECKED IT OUT USING THE COMMAND CHECKOUT. 00005 * 00006 * $Id: sacputaway_8c-source.html 2161 2006-05-19 16:55:03Z paulf $ 00007 * 00008 * Revision history: 00009 * $Log$ 00009 * Revision 1.1 2006/05/19 16:55:02 paulf 00009 * first inclusion 00009 * 00010 * Revision 1.24 2002/03/22 18:38:13 lucky 00011 * Fixed SACPABase_init prototype 00012 * 00013 * Revision 1.23 2002/03/22 18:25:24 lucky 00014 * Changed SACPABase_init to only create a new directory if told to do so. This way, files 00015 * can be added to a directory. 00016 * 00017 * Revision 1.22 2001/08/02 22:48:50 davidk 00018 * Added explicit float casts to 4 statements to get rid of 00019 * compiler warnings on NT. 00020 * 00021 * Revision 1.21 2001/08/02 22:42:01 lucky 00022 * *** empty log message *** 00023 * 00024 * Revision 1.20 2001/06/06 20:56:43 lucky 00025 * Fixing support for many mag types and amplitude picks 00026 * 00027 * Revision 1.19 2001/05/31 17:08:54 lucky 00028 * Added evdp for event depth - used to only write to evel. 00029 * 00030 * Revision 1.18 2001/04/12 03:47:36 lombard 00031 * Major reorganization of SACPABase_write_trace to improve efficiency 00032 * Reformatted code; cleaned up lots of comments and logit calls 00033 * Removed mapping of NC component codes (only needed at UW) 00034 * 00035 * Revision 1.17 2000/12/06 17:50:07 lucky 00036 * Added cOnset -- we keep track of the pick's onset in the fourth 00037 * character of the phase label (ka, or kt0) 00038 * 00039 * Revision 1.16 2000/11/15 17:03:27 lucky 00040 * Added SACPABase_next_ev_review which sets SacDir variable. (needed this 00041 * to write PZ files correctly). As a result, we no longer need end_ev_review, 00042 * so I removed it. 00043 * 00044 * Revision 1.15 2000/09/07 21:17:45 lucky 00045 * Final version after the Review pages have been demonstrated. 00046 * 00047 * Revision 1.14 2000/08/25 18:20:41 lucky 00048 * Fixed to work with multiple arrival types (S and P) 00049 * 00050 * Revision 1.13 2000/08/17 18:36:51 lucky 00051 * Fixed major potential bugs: Increased size of sacfile to 2*MAXTXT; 00052 * also, we now make sure that the target string is big enough for th 00053 * source and also the termination character. 00054 * 00055 * Revision 1.12 2000/07/27 15:55:59 lucky 00056 * Changed MAX_PHS_PER_EQ to DB_MAX_PHS_PER_EQ 00057 * 00058 * Revision 1.11 2000/07/03 18:26:24 lucky 00059 * Added SACPABase_end_scn_review for sac writing from inside the 00060 * review pages. This is necessary for the review applet to run. 00061 * 00062 * Revision 1.10 2000/05/24 15:58:31 lucky 00063 * Changed calls to creat/write to fopen/fwrite. The old way would not write 00064 * correct SAC files under NT. 00065 * 00066 * Revision 1.9 2000/04/13 17:12:58 lucky 00067 * Fixed several logit lines to only log to file. 00068 * 00069 * Revision 1.8 2000/04/13 17:06:01 lucky 00070 * In CreateSACSupportFiles: took out the chdir call to SacDir. Instead, the support 00071 * files are opened from the current directory by appending SacDir to the name of the 00072 * file. This was necessary in order to allow for multiple events to be processed by 00073 * the archiver. Before, we would never chdir back to the top level directory, causing 00074 * all subsequent calls to the Sac putaway routines to bomb. 00075 * 00076 * Also, fixed zCurEventIDACPABase_next_ev so that if dEventStartTime is 0 for some reason, 00077 * the directory created will have the current time. Before it would always create 00078 * a directory with 1970 date (i.e. time_t of 0). 00079 * 00080 * Revision 1.7 2000/03/31 18:26:47 davidk 00081 * *** empty log message *** 00082 * 00083 * Revision 1.6 2000/03/24 07:36:40 davidk 00084 * added code to pad the pick label field with blanks, instead of the default (-12345) 00085 * 00086 * Revision 1.5 2000/03/14 18:34:41 lucky 00087 * Fixed a bug with creation of SAC directories: they were being created 00088 * as yyyymmmm, instead of yyyymm. 00089 * 00090 * Revision 1.4 2000/03/13 21:36:05 lucky 00091 * Fixed error in SACPA_next_ev where pOrigin was used when it was 00092 * still set to NULL. 00093 * 00094 * Revision 1.3 2000/03/10 23:27:33 davidk 00095 * Redesigned the sacputaway routines so that they could also be 00096 * used to write parametric event and station data in addition to 00097 * being used for trace disposal. Moved most of the old functionality 00098 * into a SACPABase_XXX layer. Now the SACPA_XXX routines serve as 00099 * wrappers for the SACPABase_XXX routines, which do the actual SAC 00100 * header filling and file writing. Added code adapted from ora2sac 00101 * to write Origin and arrival data. Added code to write Poles and Zeroes 00102 * station signal response data. Changed the SACPA_XXX routines to 00103 * matche the new putaway interface in putaway.c 00104 * 00105 * Revision 1.1 2000/02/14 18:51:48 lucky 00106 * Initial revision 00107 * 00108 * 00109 */ 00110 00111 /* sacputaway.c 00112 00113 Wed Feb 23 XX:XX:XX PST 2000 David Kragness 00114 Modified the sacputaway routines to use an additional layer. 00115 It was desired that the same core code be used to do all 00116 data disposal into SAC, and some programs needed/wanted to 00117 write parametric data as well as trace data. In the putaway 00118 interface, there is only room for trace data. So the SACPA_XXX 00119 routines have been modified so that the guts of the original 00120 routines have gone into a layer of functions called 00121 SACPABase_XXX, and the original SACPA_XXX routines have 00122 become wrappers for those routines using the XXX_tracesave 00123 "putaway" interface. Additional functionality has been added 00124 to the SACPABase_XXX routines for writing parametric data to 00125 SAC in addition to the waveform data that was written by the 00126 original SACPA_XXX routines. 00127 00128 00129 Thu Dec 30 00:01:12 GMT 1999 Lucky Vidmar 00130 Made the fixes necessary to produce SAC files on NT which 00131 are readable on Solaris. For this, we needed to do some magic 00132 with the SAC header, so that it can be byte-swapped correctly. 00133 Namely, we now have two SAC headers floating around: one is 00134 in the local machine format, and its values are copied to the 00135 temporary header so that it can be swapped (the "problem" being 00136 that byte-swapping is done in-place). Then, once we get back 00137 a byte-swapped header, we memcpy it back to the memory that is 00138 written out along with the previously byte-swapped data. 00139 00140 Thu Jul 22 14:56:37 MDT 1999 Lucky Vidmar 00141 Major structural changes to accomodate making all putaway routines 00142 into library calls so that they can be shared between trig2disk 00143 and wave2disk. Eliminated global variables set and allocated outside 00144 of this file. We should only have static globals from now on, with 00145 everything else being passed in via the putaway.c calls. 00146 00147 00148 Tue Apr 13 13:01:23 MDT 1999 Lucky Vidmar 00149 Changed target directory names to reflect ora2sac. Also, we now 00150 create a bunch of support files (sac macros) in the target directory, 00151 much like ora2sac. As a matter of fact, most of the code which 00152 creates sac macros was modelled after ora2sac code. 00153 00154 00155 These are the routines which plug into routines in putaway.c, and cause 00156 the trace data snippets to be put away into a SAC format trace files. 00157 00158 Written by: Pete Lombard, March 1998 00159 00160 Modified by withers to work with trig2disk Sep, 1998 00161 Ported to NT withers Oct 1998 00162 00163 */ 00164 00165 /************************************/ 00167 /************************************/ 00168 #include <stdio.h> 00169 #include <stdlib.h> 00170 #include <string.h> 00171 #include <errno.h> 00172 #include <earthworm.h> 00173 #include <time.h> 00174 #include <trace_buf.h> 00175 #include <swap.h> 00176 #include <ws_clientII.h> 00177 #include <chron3.h> 00178 #include <sacputaway.h> 00179 #include <pa_subs.h> 00180 #include <time_ew.h> 00181 00182 00183 /*********************************************/ 00185 /*********************************************/ 00186 static SACFileListStruct FileList[DB_MAX_PHS_PER_EQ]; 00187 static int FileIndex; 00188 static char szCurEventID[EVENTID_SIZE+1]; 00189 static int SACPAB_Debug=0; 00190 static char SAC_szOutDir[MAXTXT]; 00191 static char SAC_szOutputFormat[20]; 00192 static double SAC_starttime; 00193 static SAC_OriginStruct SAC_Origin; 00194 00195 00196 /* use statically allocated SAC headers. It's safer and faster 00197 than dynamically mallocing them and it's not 00198 that much space (6XX bytes each) 00199 ****************************************************************/ 00200 static char default_sachead[SACHEADERSIZE]; 00201 static char sachead[SACHEADERSIZE]; 00202 00203 /* sacheadp is where the "real" representation of the header is, i.e 00204 the one that is valid on the architecture that executes the code 00205 ****************************************************************/ 00206 static struct SAChead *sacheadp=(struct SAChead *) sachead; 00207 00208 /* default_sacheadp is the default sac header image. This way we don't 00209 have to go through painful initialization each time, we just slam 00210 the default into our target header. 00211 ****************************************************************/ 00212 static struct SAChead *default_sacheadp=(struct SAChead *) default_sachead; 00213 00214 static char SacDir[2*MAXTXT + 4]; 00215 static char *SacBuffer; /* buffer for storing output before writing */ 00216 static char SAC_szSta[10], SAC_szChan[10], SAC_szNet[10]; 00217 static int BufferLen; 00218 static int bSACPABase_init=FALSE; 00219 static int bSACPABase_scn_open=FALSE; 00220 00221 00222 /************************************/ 00224 /************************************/ 00225 00226 /* supporting routines 00227 *************************************/ 00228 void sacinit (struct SAChead *); 00229 void swapsac (struct SAChead *); 00230 int SAC_Compare (const void *, const void *); 00231 int CreateSACSupportFiles (char *, SACFileListStruct *, int); 00232 int SACmac_init (void); 00233 int SACmac_quicklook (SACFileListStruct *, int); 00234 int SACmac_repick (SACFileListStruct *, int); 00235 int SAC_filelist (SACFileListStruct *, int, char *); 00236 int SAC_SwapDouble(double * pValue, char cDataType); 00237 int SAC_SwapLong(long * pValue, char cDataType); 00238 int SAC_SwapShort(short * pValue, char cDataType); 00239 00240 00241 /******************************************************************** 00242 ********************************************************************* 00243 ###################### SAC PUTAWAY ROUTINES ######################### 00244 ********************************************************************* 00245 ********************************************************************/ 00246 00247 /* Initialization function, 00248 * This is the Put Away startup intializer. This is called when * 00249 * the system first comes up. Here is a chance to look around * 00250 * and see if it's possible to do business, and to complain * 00251 * if not ,BEFORE an event has to be processed. * 00252 */ 00253 int SACPA_init(long OutBufferLen, char *OutDir, char * OutputFormat, int debug) 00254 { 00255 int rc; 00256 00257 rc=SACPABase_Debug(debug); 00258 if(rc!=EW_SUCCESS) 00259 { 00260 logit("","%s(): %s() failed returning %d.\n", 00261 "SACPA_init","SACPABase_Debug",rc); 00262 return(EW_FAILURE); 00263 } 00264 00265 rc=SACPABase_init(OutBufferLen,OutDir,TRUE,OutputFormat); 00266 if(rc!=EW_SUCCESS) 00267 { 00268 logit("","%s(): %s() failed returning %d.\n", 00269 "SACPA_init","SACPABase_init",rc); 00270 return(EW_FAILURE); 00271 } 00272 return(EW_SUCCESS); 00273 } 00274 00275 /**************************************************************************** 00276 * This is the Put Away event initializer. It's called when a snippet * 00277 * has been received, and is about to be processed. * 00278 * It gets to see the pointer to the TraceRequest array, * 00279 * and the number of loaded trace structures. * 00280 *****************************************************************************/ 00281 int SACPA_next_ev(char *EventID, TRACE_REQ *ptrReq, int nReq, 00282 char *OutDir, char *EventDate, char *EventTime, int debug) 00283 { 00284 00285 int rc; 00286 char szTime[40]; 00287 double dTime; 00288 00289 rc=SACPABase_Debug(debug); 00290 if(rc!=EW_SUCCESS) 00291 { 00292 logit("","%s(): %s() failed returning %d.\n", 00293 "SACPA_next_ev","SACPABase_Debug",rc); 00294 return(EW_FAILURE); 00295 } 00296 00297 sprintf(szTime,"%s%s",EventDate,EventTime); 00298 if(epochsec17(&dTime,szTime)) 00299 { 00300 logit("","SACPA_next_ev(): Error in epochsec17() parsing time:(%s)\n", 00301 szTime); 00302 return(EW_FAILURE); 00303 } 00304 00305 rc=SACPABase_next_ev(EventID,dTime,NULL); 00306 if(rc!=EW_SUCCESS) 00307 { 00308 logit("","%s(): %s() failed returning %d.\n", 00309 "SACPA_next_ev","SACPABase_next_ev",rc); 00310 return(EW_FAILURE); 00311 } 00312 00313 return(EW_SUCCESS); 00314 } 00315 00316 00317 /***************************************************************************** 00318 * This is the working entry point into the disposal system. This routine * 00319 * gets called for each trace snippet which has been recovered. It gets * 00320 * to see the corresponding SNIPPET structure, and the event id * 00321 *****************************************************************************/ 00322 /* Process one channel of data */ 00323 int SACPA_next(TRACE_REQ *getThis, double GapThresh, 00324 long OutBufferLen, int debug) 00325 /* 00326 * input: getThis pointer to buffer for the trace data request 00327 * eventId not used here 00328 */ 00329 00330 { 00331 int rc; 00332 00333 rc=SACPABase_Debug(debug); 00334 if(rc!=EW_SUCCESS) 00335 { 00336 logit("","%s(): %s() failed returning %d.\n", 00337 "SACPA_next","SACPABase_Debug",rc); 00338 return(EW_FAILURE); 00339 } 00340 00341 rc=SACPABase_next_scn(getThis->sta,getThis->chan,getThis->net); 00342 if(rc!=EW_SUCCESS) 00343 { 00344 logit("","%s(): %s() failed returning %d.\n", 00345 "SACPA_next","SACPABase_next_scn",rc); 00346 return(EW_FAILURE); 00347 } 00348 00349 rc=SACPABase_write_trace(getThis,GapThresh); 00350 if(rc!=EW_SUCCESS) 00351 { 00352 logit("","%s(): %s() failed returning %d.\n", 00353 "SACPA_next","SACPABase_write_trace",rc); 00354 return(EW_FAILURE); 00355 } 00356 00357 rc=SACPABase_end_scn(); 00358 if(rc!=EW_SUCCESS) 00359 { 00360 logit("","%s(): %s() failed returning %d.\n", 00361 "SACPA_next","SACPABase_end_scn()",rc); 00362 return(EW_FAILURE); 00363 } 00364 00365 return(EW_SUCCESS); 00366 } 00367 00368 00369 00370 /************************************************************************ 00371 * This is the Put Away end event routine. It's called after we've * 00372 * finished processing one event. * 00373 *************************************************************************/ 00374 int SACPA_end_ev (int debug) 00375 { 00376 int rc; 00377 00378 rc=SACPABase_Debug(debug); 00379 if(rc!=EW_SUCCESS) 00380 { 00381 logit("","%s(): %s() failed returning %d.\n", 00382 "SACPA_end_ev","SACPABase_Debug",rc); 00383 return(EW_FAILURE); 00384 } 00385 00386 rc=SACPABase_end_ev(); 00387 if(rc!=EW_SUCCESS) 00388 { 00389 logit("","%s(): %s() failed returning %d.\n", 00390 "SACPA_end_ev","SACPABase_end_ev",rc); 00391 return(EW_FAILURE); 00392 } 00393 00394 return(EW_SUCCESS); 00395 } 00396 00397 00398 /************************************************************************ 00399 * This is the Put Away close routine. It's called after when * 00400 * we're being shut down. * 00401 *************************************************************************/ 00402 int SACPA_close (int debug) 00403 { 00404 int rc; 00405 00406 rc=SACPABase_Debug(debug); 00407 if(rc!=EW_SUCCESS) 00408 { 00409 logit("","%s(): %s() failed returning %d.\n", 00410 "SACPA_close","SACPABase_Debug",rc); 00411 return(EW_FAILURE); 00412 } 00413 00414 rc=SACPABase_close(); 00415 if(rc!=EW_SUCCESS) 00416 { 00417 logit("","%s(): %s() failed returning %d.\n", 00418 "SACPA_close","SACPABase_close",rc); 00419 return(EW_FAILURE); 00420 } 00421 00422 return(EW_SUCCESS); 00423 } 00424 00425 00426 00427 /******************************************************************** 00428 ********************************************************************* 00429 #################### SAC PUTAWAY BASE ROUTINES ###################### 00430 ********************************************************************* 00431 ********************************************************************/ 00432 00433 00434 00435 00436 /******************************************************************** 00437 ********************************************************************* 00438 Function: SACPABase_Debug 00439 00440 Description: Turns debugging on/off for SACPABase 00441 functions 00442 00443 Return Value: success: EW_SUCCESS 00444 failure: EW_FAILURE 00445 others: Undefined 00446 00447 Comments: 00448 ********************************************************************* 00449 ********************************************************************/ 00450 int SACPABase_Debug(int bDebug) 00451 { 00452 SACPAB_Debug=bDebug; 00453 return(EW_SUCCESS); 00454 } 00455 00456 /******************************************************************** 00457 ********************************************************************* 00458 Function: SACPABase_SetOutputFormat 00459 00460 Description: Sets the output format for the SACPABase functions. 00461 ("intel" or "sparc") 00462 00463 Return Value: success: EW_SUCCESS 00464 failure: EW_FAILURE 00465 SACPAB_OUTPUT_FORMAT_TOO_LONG 00466 others: Undefined 00467 00468 Comments: 00469 ********************************************************************* 00470 ********************************************************************/ 00471 int SACPABase_SetOutputFormat(char * szOutputFormat) 00472 { 00473 if(strlen(szOutputFormat) > sizeof(SAC_szOutputFormat)) 00474 { 00475 logit("","SACPABase_SetOutputFormat():Error: %s output format is too long!\n", 00476 szOutputFormat); 00477 return(SACPAB_OUTPUT_FORMAT_TOO_LONG); 00478 } 00479 strcpy(SAC_szOutputFormat,szOutputFormat); 00480 return(EW_SUCCESS); 00481 } 00482 00483 /******************************************************************** 00484 ********************************************************************* 00485 Function: SACPABase_init 00486 00487 Description: SAC Putaway Base initializer. 00488 00489 Return Value: success: EW_SUCCESS 00490 failure: EW_FAILURE (unknown error) 00491 SACPAB_ALREADY_INIT (SACPABase is already 00492 initialized. Please call SACPABase_close() 00493 before calling SACPABase_init() again. 00494 00495 others: Undefined 00496 00497 Comments: This should be called when the system first comes 00498 up. It gives SACPABase a chance to look around 00499 and see if it's possible to do business, and to 00500 complain if not ,BEFORE an event has to be 00501 processed. 00502 ********************************************************************* 00503 ********************************************************************/ 00504 int SACPABase_init(int OutBufferLen, char *szOutDir, int CreateNewDir, char * szOutputFormat) 00505 { 00506 if (bSACPABase_init) 00507 { 00508 logit("","SACPABase_init() called multiple times.\n"); 00509 return(SACPAB_ALREADY_INIT); 00510 } 00511 00512 if(!(szOutDir && szOutputFormat)) 00513 { 00514 logit("","SACPABase_init(): Error: Null pointers passed.\n"); 00515 return(SACPAB_NULL_POINTERS); 00516 } 00517 00518 if(OutBufferLen > MIN_OUTBUFFER_LEN) 00519 BufferLen=OutBufferLen; 00520 else 00521 BufferLen=MIN_OUTBUFFER_LEN; 00522 00523 /* Allocate SacBuffer */ 00524 if ((SacBuffer = (char *) malloc (BufferLen * sizeof (char))) == NULL) 00525 { 00526 logit ("e", "SACPABase_init: couldn't malloc SacBuffer(%d)\n", BufferLen); 00527 return EW_FAILURE; 00528 } 00529 00530 /* set init flag here to minimize memory leaks. */ 00531 bSACPABase_init=TRUE; 00532 00533 if(strlen(szOutDir) > (sizeof(SAC_szOutDir) + 1)) 00534 { 00535 logit("e","SACPABase_init():Error: %s directory name is too long!\n", 00536 szOutDir); 00537 return(SACPAB_DIRECTORY_TOO_LONG); 00538 } 00539 strcpy(SAC_szOutDir,szOutDir); 00540 00541 /* Make sure that the top level output directory exists */ 00542 00543 if (CreateNewDir == TRUE) 00544 { 00545 if (CreateDir (SAC_szOutDir) != EW_SUCCESS) 00546 { 00547 logit ("e", "SACPABase_init: Call to CreateDir(%s) failed\n",SAC_szOutDir); 00548 return EW_FAILURE; 00549 } 00550 } 00551 00552 if(strlen(szOutputFormat) > sizeof(SAC_szOutputFormat)) 00553 { 00554 logit("e","SACPABase_init():Error: %s output format is too long!\n", 00555 szOutputFormat); 00556 return(SACPAB_OUTPUT_FORMAT_TOO_LONG); 00557 } 00558 strcpy(SAC_szOutputFormat,szOutputFormat); 00559 00560 /* Initialize all header values to SAC defaults */ 00561 sacinit(default_sacheadp); 00562 00563 /* the following sac header vars must be set, but not neccessarily 00564 here: npts,b,e,iftype,leven,delta 00565 ******************************************************************/ 00566 /* Set some header values that will never change */ 00567 default_sacheadp->idep = SAC_IUNKN; /* unknown independent data type */ 00568 default_sacheadp->iztype = SAC_IBEGINTIME; /* Reference time is Begin time */ 00569 default_sacheadp->iftype = SAC_ITIME; /* File type is time series */ 00570 default_sacheadp->leven = 1; /* evenly spaced data */ 00571 default_sacheadp->b = 0; /* beginning time relative to reference time */ 00572 strncpy(default_sacheadp->ko, "origin ", K_LEN); 00573 00574 /* Initialize CurEventID */ 00575 strcpy(szCurEventID,"-1"); 00576 00577 return(EW_SUCCESS); 00578 } 00579 00580 00581 /**************************************************************************** 00582 * This is the Put Away event initializer. It's called when a snippet * 00583 * has been received, and is about to be processed. * 00584 * It gets to see the pointer to the TraceRequest array, * 00585 * and the number of loaded trace structures. * 00586 *****************************************************************************/ 00587 int SACPABase_next_ev(char * szEventID, double dEventStartTime, 00588 SAC_OriginStruct * pOrigin) 00589 { 00590 00591 char tmpname[256]; 00592 char tmp1[256]; 00593 time_t tTemp=(int)dEventStartTime; 00594 struct tm tmTemp; 00595 00596 00597 if (dEventStartTime == 0.0) 00598 tTemp = time (NULL); 00599 00600 gmtime_ew(&tTemp,&tmTemp); 00601 00602 strncpy(szCurEventID,szEventID,EVENTID_SIZE); 00603 szCurEventID[EVENTID_SIZE]=0; 00604 00605 /* Sac files will be written into the directory structure 00606 * borrowed from ora2sac: 00607 * SacDir = OutDir/yyyymm/yyyymmdd_hhmmss-iiii/ 00608 * 00609 * If SacDir does not exist, it will be created 00610 */ 00611 00612 /* tmpname = OutDir/yyyymm */ 00613 sprintf (tmpname, "%s/%04d%02d", SAC_szOutDir, 00614 tmTemp.tm_year+1900, tmTemp.tm_mon+1); 00615 00616 if (CreateDir (tmpname) != EW_SUCCESS) 00617 { 00618 logit ("e", "SACPA_init: Call to CreateDir failed\n"); 00619 return EW_FAILURE; 00620 } 00621 00622 /* build the event directory name */ 00623 sprintf (tmp1, "%04d%02d%02d_%02d%02d%02d_%s", 00624 tmTemp.tm_year+1900, tmTemp.tm_mon+1, tmTemp.tm_mday, 00625 tmTemp.tm_hour, tmTemp.tm_min, tmTemp.tm_sec, 00626 szCurEventID 00627 ); 00628 00629 sprintf (SacDir, "%s/%s", tmpname, tmp1); 00630 00631 if (CreateDir (SacDir) != EW_SUCCESS) 00632 { 00633 logit ("e", "SACPABase_next_ev: Call to CreateDir(%s)failed\n", 00634 SacDir); 00635 return EW_FAILURE; 00636 } 00637 00638 /* reset file index to 0 (for support files) */ 00639 FileIndex = 0; 00640 00641 if(pOrigin) 00642 { 00643 memcpy(&SAC_Origin,pOrigin,sizeof(SAC_OriginStruct)); 00644 default_sacheadp->evla=(float)(pOrigin->dLat); 00645 default_sacheadp->evlo=(float)(pOrigin->dLon); 00646 default_sacheadp->evel=(float)(pOrigin->dElev); 00647 default_sacheadp->evdp=(float)(pOrigin->dElev); 00648 } 00649 else 00650 { 00651 SAC_Origin.tOrigin=dEventStartTime; 00652 } 00653 00654 return(EW_SUCCESS); 00655 } 00656 00657 /**************************************************************************** 00658 * This is the Put Away event initializer for the review system. * 00659 * It doesn't do much except for setting the SacDir variable * 00660 * which gets used a lot in the Sac putaway routines * 00661 *****************************************************************************/ 00662 int SACPABase_next_ev_review (char *EventDir, int EventID, SAC_OriginStruct *pSacOrigin) 00663 { 00664 00665 char evtid[256]; 00666 00667 if ((EventDir == NULL) || (pSacOrigin == NULL)) 00668 { 00669 logit ("", "Invalid arguments passed in.\n"); 00670 return EW_FAILURE; 00671 } 00672 00673 /* Set SacDir */ 00674 strcpy (SacDir, EventDir); 00675 00676 /* Set szCurEventID */ 00677 sprintf (evtid, "%d", EventID); 00678 strncpy (szCurEventID, evtid, EVENTID_SIZE); 00679 szCurEventID[EVENTID_SIZE] = 0; 00680 00681 00682 /* Set event parameters */ 00683 memcpy (&SAC_Origin, pSacOrigin, sizeof(SAC_OriginStruct)); 00684 default_sacheadp->evla = (float)(pSacOrigin->dLat); 00685 default_sacheadp->evlo = (float)(pSacOrigin->dLon); 00686 default_sacheadp->evel = (float)(pSacOrigin->dElev); 00687 default_sacheadp->evdp = (float)(pSacOrigin->dElev); 00688 00689 return EW_SUCCESS; 00690 00691 } 00692 00693 00694 /***************************************************************************** 00695 * This is the working entry point into the disposal system. This routine * 00696 * gets called for each trace snippet which has been recovered. It gets * 00697 * to see the corresponding SNIPPET structure, and the event id * 00698 *****************************************************************************/ 00699 /* Process one channel of data */ 00700 int SACPABase_next_scn(char *szSta, char * szChan, char * szNet) 00701 { 00702 int i; 00703 00704 if(bSACPABase_scn_open) 00705 { 00706 logit("","SACPABase_next_scn(): ERROR! SCN record is already open,\n" 00707 "please call SACPABase_scn_end() to close the existing record,\n" 00708 "before calling SACPABase_next_scn() again.\n"); 00709 return(SACPAB_SCN_ALREADY_OPEN); 00710 } 00711 00712 /* slam the default header into our working one. */ 00713 memcpy(sacheadp,default_sacheadp,SACHEADERSIZE); 00714 00715 /* Save the SCN for use by other SAC_PA routines */ 00716 strncpy(SAC_szSta,szSta,sizeof(SAC_szSta)); 00717 SAC_szSta[sizeof(SAC_szSta)-1]=0; 00718 strncpy(SAC_szChan,szChan,sizeof(SAC_szChan)); 00719 SAC_szSta[sizeof(SAC_szChan)-1]=0; 00720 strncpy(SAC_szNet,szNet,sizeof(SAC_szSta)); 00721 SAC_szSta[sizeof(SAC_szNet)-1]=0; 00722 00723 /* Copy the SCN into the header and blank bad the trailing chars */ 00724 strcpy(sacheadp->kstnm, SAC_szSta); /* station name */ 00725 for (i = strlen(SAC_szSta); i < K_LEN; ++i) 00726 sacheadp->kstnm[i] = ' '; 00727 00728 strcpy(sacheadp->kcmpnm, SAC_szChan); 00729 for (i = strlen(SAC_szChan); i < K_LEN; ++i) 00730 sacheadp->kcmpnm[i] = ' '; 00731 00732 strcpy(sacheadp->knetwk, SAC_szNet); 00733 for (i = strlen(SAC_szNet); i < K_LEN; ++i) 00734 sacheadp->knetwk[i] = ' '; 00735 00736 /* orientation of seismometer - 00737 determine the orientation based on the third character 00738 of the component name */ 00739 switch ((int) SAC_szChan[2]) 00740 { 00741 /* vertical component */ 00742 case 'Z' : 00743 case 'z' : 00744 sacheadp->cmpaz = 0; 00745 sacheadp->cmpinc = 0; 00746 break; 00747 /* north-south component */ 00748 case 'N' : 00749 case 'n' : 00750 sacheadp->cmpaz = 0; 00751 sacheadp->cmpinc = 90; 00752 break; 00753 /* east-west component */ 00754 case 'E' : 00755 case 'e' : 00756 sacheadp->cmpaz = 90; 00757 sacheadp->cmpinc = 90; 00758 break; 00759 /* anything else */ 00760 default : 00761 sacheadp->cmpaz = SACUNDEF; 00762 sacheadp->cmpinc = SACUNDEF; 00763 break; 00764 } /* switch */ 00765 00766 /* so far we have the default header, plus SCN information */ 00767 /* no time or trace info */ 00768 bSACPABase_scn_open=TRUE; 00769 00770 return(EW_SUCCESS); 00771 } 00772 00773 00774 /* 00775 * SACPABase_write_trace: transfer trace data from TRACE_REQ buffer into 00776 * SAC data section; fill in some header info. 00777 * The actual writing of the file happens in SACPABase_end_scn. 00778 */ 00779 int SACPABase_write_trace(TRACE_REQ * pTrace, double dGapThresh) 00780 /* 00781 * input: pTrace pointer to buffer for the trace data request 00782 * eventId not used here 00783 */ 00784 { 00785 TRACE_HEADER *wf; 00786 char *msg_p; /* pointer into tracebuf data */ 00787 short *s_data; 00788 long *l_data; 00789 float *f_data; 00790 float *sac_p; /* the data part of the SAC buffer */ 00791 int j; 00792 int gap_count = 0; 00793 long nsamp, nfill; 00794 long nfill_max = 0l; 00795 long nsamp_this_scn = 0l; 00796 long this_size; 00797 double starttime, endtime; /* times for current scn */ 00798 double samprate; 00799 float fill = (float)SACUNDEF; 00800 struct tm *time; 00801 time_t ltime; 00802 char datatype; /* 's' for short, 'l' for long */ 00803 00804 /* Check validity of the arguments */ 00805 if (pTrace == NULL) 00806 { 00807 logit ("e", "SACPABase_write_trace: Invalid arguments passed in\n"); 00808 return (EW_FAILURE); 00809 } 00810 00811 if ((msg_p = pTrace->pBuf) == NULL) 00812 { 00813 logit ("e", "SACPABase_write_trace: message buffer is NULL\n"); 00814 return EW_FAILURE; 00815 } 00816 00817 sac_p = (float *)(SacBuffer + SACHEADERSIZE); 00818 00819 wf = (TRACE_HEADER *) msg_p; 00820 if (WaveMsgMakeLocal(wf) < 0) 00821 { 00822 logit("e", "SACPABase_write_trace: unknown trace data type: %s\n", 00823 wf->datatype); 00824 return( EW_FAILURE ); 00825 } 00826 00827 nsamp = wf->nsamp; 00828 starttime = wf->starttime; 00829 endtime = wf->endtime; 00830 samprate = wf->samprate; 00831 if (samprate < 0.01) 00832 { 00833 logit("et", "SACPABase_write_trace: unreasonable samplerate (%f) for <%s.%s.%s>\n", 00834 samprate, SAC_szSta, SAC_szChan, SAC_szNet); 00835 return( EW_FAILURE ); 00836 } 00837 00838 SAC_starttime = starttime; 00839 datatype = 'n'; 00840 if (wf->datatype[0] == 's' || wf->datatype[0] == 'i') 00841 { 00842 if (wf->datatype[1] == '2') datatype = 's'; 00843 else if (wf->datatype[1] == '4') datatype = 'l'; 00844 } 00845 else if (wf->datatype[0] == 't' || wf->datatype[0] == 'f') 00846 { 00847 if (wf->datatype[1] == '4') datatype = 'f'; 00848 } 00849 if (datatype == 'n') 00850 { 00851 logit("et", "SACPABase_write_trace: unsupported datatype: %s\n", datatype); 00852 return( EW_FAILURE ); 00853 } 00854 00855 /* loop through all the messages for this s-c-n */ 00856 while (1) 00857 { 00858 /* advance message pointer to the data */ 00859 msg_p += sizeof(TRACE_HEADER); 00860 00861 /* check for sufficient memory in output buffer */ 00862 this_size = (nsamp_this_scn + nsamp ) * sizeof(float); 00863 00864 if ( BufferLen < (this_size + SACHEADERSIZE) ) 00865 { 00866 logit( "", "out of space for <%s.%s.%s>; saving short trace.\n", 00867 SAC_szSta, SAC_szChan, SAC_szNet); 00868 break; 00869 } 00870 00871 switch( datatype ) 00872 { 00873 case 's': 00874 s_data = (short *)msg_p; 00875 for ( j = 0; j < nsamp ; j++, nsamp_this_scn++ ) 00876 sac_p[nsamp_this_scn] = (float) s_data[j]; 00877 msg_p += sizeof(short) * nsamp; 00878 break; 00879 case 'l': 00880 l_data = (long *)msg_p; 00881 for ( j = 0; j < nsamp; j++, nsamp_this_scn++ ) 00882 sac_p[nsamp_this_scn] = (float) l_data[j]; 00883 msg_p += sizeof(long) * nsamp; 00884 break; 00885 case 'f': 00886 f_data = (float *)msg_p; 00887 for ( j = 0; j < nsamp; j++, nsamp_this_scn++ ) 00888 sac_p[nsamp_this_scn] = f_data[j]; 00889 msg_p += sizeof(float) * nsamp; 00890 break; 00891 } 00892 00893 /* End-check based on length of snippet buffer */ 00894 if ((long) msg_p >= ((long) pTrace->actLen + (long) pTrace->pBuf)) 00895 { 00896 if (SACPAB_Debug == 1) 00897 logit ("", "Setting done for <%s.%s.%s>\n", SAC_szSta, SAC_szChan, 00898 SAC_szNet); 00899 break; 00900 } 00901 00902 /* msg_p has been advanced to the next TRACE_BUF; localize bytes * 00903 * and check for gaps. */ 00904 wf = (TRACE_HEADER *) msg_p; 00905 if (WaveMsgMakeLocal(wf) < 0) 00906 { 00907 logit("e", "SACPABase_write_trace: unknown trace data type: %s\n", 00908 wf->datatype); 00909 return( EW_FAILURE ); 00910 } 00911 nsamp = wf->nsamp; 00912 starttime = wf->starttime; 00913 /* starttime is set for new packet; endtime is still set for old packet */ 00914 if ( endtime + ( 1.0/samprate ) * dGapThresh < starttime ) 00915 { 00916 /* there's a gap, so fill it */ 00917 nfill = (long) ((float)samprate * 00918 (float) (starttime - endtime) -(float) 1.0); 00919 00920 if (SACPAB_Debug == 1) 00921 logit("e", "gap in %s.%s.%s: %lf: %lf, fill with %d samples\n", 00922 SAC_szSta, SAC_szChan, SAC_szNet, 00923 endtime, starttime - endtime, nfill); 00924 00925 if ( (nsamp_this_scn + nfill) * (long)sizeof(float) > BufferLen ) 00926 { 00927 logit("e", "bogus gap (%d); skipping\n", nfill); 00928 return(EW_FAILURE); 00929 } 00930 /* do the filling */ 00931 for ( j = 0; j < nfill; j++, nsamp_this_scn ++ ) 00932 sac_p[nsamp_this_scn] = fill; 00933 /* keep track of how many gaps and the largest one */ 00934 gap_count++; 00935 if (nfill_max < nfill) 00936 nfill_max = nfill; 00937 } 00938 /* Advance endtime to the new packet; * 00939 * process this packet in the next iteration */ 00940 endtime = wf->endtime; 00941 00942 } /* while (1) */ 00943 00944 /* All trace data fed into SAC data section. Now fill in header */ 00945 sacheadp->npts = (long) nsamp_this_scn; /* samples in trace */ 00946 sacheadp->delta = (float) (1.0/samprate); /* sample period */ 00947 sacheadp->e = (float) nsamp_this_scn * sacheadp->delta; /* end time */ 00948 ltime = (time_t)SAC_starttime; 00949 /* gmttime makes juldays starting with 0 */ 00950 time = gmtime( <ime ); 00951 sacheadp->nzyear = (long)time->tm_year + 1900l; /* calendar year of reference time */ 00952 sacheadp->nzjday = (long)time->tm_yday + (long)1; /* julian day, 0 - 365 */ 00953 sacheadp->nzhour = (long)time->tm_hour; 00954 sacheadp->nzmin = (long)time->tm_min; 00955 sacheadp->nzsec = (long)time->tm_sec; 00956 sacheadp->nzmsec = (long)((SAC_starttime - (long)SAC_starttime) * 1000.0); 00957 00958 /* set the origin time */ 00959 sacheadp->o = (float)(SAC_Origin.tOrigin - SAC_starttime); 00960 00961 if (gap_count) 00962 logit("e", "%d gaps; largest %ld for <%s.%s.%s>\n", 00963 gap_count, nfill_max, SAC_szSta, SAC_szChan, SAC_szNet); 00964 00965 return(EW_SUCCESS); 00966 } 00967 00968 int SACPABase_write_parametric(SAC_ArrivalStruct * pArrival, int WaveType) 00969 { 00970 int i; 00971 00972 if (pArrival == NULL) 00973 { 00974 logit ("", "Invalid parameters passed in\n"); 00975 return EW_FAILURE; 00976 } 00977 00978 if (WaveType == PWAVE) 00979 { 00980 for (i = 0; i < K_LEN; ++i) 00981 sacheadp->ka[i] = ' '; 00982 00983 sacheadp->a = (float)(pArrival->tPhase - SAC_starttime); 00984 sacheadp->ka[0]= 'P'; 00985 sacheadp->ka[1]= pArrival->cFMotion; 00986 sacheadp->ka[2]= pArrival->iPhaseWt + '0'; 00987 sacheadp->ka[3]= pArrival->cOnset; 00988 sacheadp->f = (float)(pArrival->dCodaLen + sacheadp->a); 00989 sacheadp->dist = (float)(pArrival->dDist); 00990 sacheadp->az = (float)(pArrival->dAzm); 00991 } 00992 else if (WaveType == SWAVE) 00993 { 00994 00995 for (i = 0; i < K_LEN; ++i) 00996 sacheadp->kt0[i] = ' '; 00997 00998 sacheadp->t0 = (float)(pArrival->tPhase - SAC_starttime); 00999 sacheadp->kt0[0]= 'S'; 01000 sacheadp->kt0[1]= pArrival->cFMotion; 01001 sacheadp->kt0[2]= pArrival->iPhaseWt + '0'; 01002 sacheadp->kt0[3]= pArrival->cOnset; 01003 sacheadp->f = (float)(pArrival->dCodaLen + sacheadp->a); 01004 sacheadp->dist = (float)(pArrival->dDist); 01005 sacheadp->az = (float)(pArrival->dAzm); 01006 } 01007 else 01008 { 01009 logit ("", "Invalid WaveType %d.\n", WaveType); 01010 return EW_FAILURE; 01011 } 01012 01013 return(EW_SUCCESS); 01014 } 01015 01016 int SACPABase_write_amppicks(SAC_AmpPickStruct * pAmpPick) 01017 { 01018 01019 double tmp1, tmp2; 01020 01021 if (pAmpPick == NULL) 01022 { 01023 logit ("", "Invalid arguments passed in.\n"); 01024 return EW_FAILURE; 01025 } 01026 01027 if (pAmpPick->PickType == 0) 01028 { 01029 /* zero-to-peak case */ 01030 sacheadp->t0 = (float ) (pAmpPick->ZP_time - SAC_starttime); 01031 sacheadp->user0 = (float) (pAmpPick->ZP_amp); 01032 01033 sprintf (sacheadp->kt0, "0-P_max"); 01034 sprintf (sacheadp->kuser0, "0-P_amp"); 01035 } 01036 else if (pAmpPick->PickType == 1) 01037 { 01038 /* peak-to-peak case */ 01039 01040 tmp1 = (pAmpPick->PPmin_time - SAC_starttime); 01041 tmp2 = (pAmpPick->PPmax_time - SAC_starttime); 01042 sacheadp->t1 = (float) tmp1; 01043 sacheadp->t2 = (float) tmp2; 01044 sacheadp->user1 = (float) (pAmpPick->PP_amp); 01045 01046 sprintf (sacheadp->kt1, "P-P_min"); 01047 sprintf (sacheadp->kt2, "P-P_max"); 01048 sprintf (sacheadp->kuser1, "P-P_amp"); 01049 } 01050 else 01051 { 01052 logit ("", "Invalid PickType value: %d\n", pAmpPick->PickType); 01053 return EW_FAILURE; 01054 } 01055 01056 sprintf (sacheadp->kinst, "W_A_(mm)"); 01057 01058 return EW_SUCCESS; 01059 01060 } 01061 01062 01063 int SACPABase_write_stainfo(SAC_StationStruct * pStation) 01064 { 01065 char szPZFilename[256]; 01066 FILE * fpPZ; 01067 int i; 01068 double dist, azm; 01069 /* 01070 SAMPLE POLES AND ZEROES FILE 01071 ============================ 01072 01073 ZEROS 4 01074 -0.125 0.0 01075 -50.0 0.0 01076 POLES 4 01077 -0.13 0.0 01078 -6.02 0.0 01079 -8.66 0.0 01080 -35.2 0.0 01081 CONSTANT -394.0 01082 */ 01083 01084 sacheadp->stla=pStation->dLat; 01085 sacheadp->stlo=pStation->dLon; 01086 sacheadp->stel=pStation->dElev; 01087 01088 01089 /* 01090 * This is a good time to make sure that distance and azm get set. 01091 * Story: dist and azm are properties of Arrivals in the DB schema. 01092 * This means that they don't get set for SAC traces without picks. 01093 * This is not good. So, here we cloodge it. LV 6/2001. 01094 */ 01095 01096 if ((sacheadp->evla != (float) SACUNDEF) && (sacheadp->evlo != (float) SACUNDEF) && 01097 (sacheadp->stla != (float) SACUNDEF) && (sacheadp->stlo != (float) SACUNDEF)) 01098 { 01099 if (geo_to_km (sacheadp->evla, sacheadp->evlo, 01100 sacheadp->stla, sacheadp->stlo, &dist, &azm) != 1) 01101 { 01102 logit ("", "Call to geo_to_km failed - ignoring.\n"); 01103 } 01104 else 01105 { 01106 if (sacheadp->dist == (float) SACUNDEF) 01107 { 01108 sacheadp->dist = (float) dist; 01109 } 01110 if (sacheadp->az == (float) SACUNDEF) 01111 { 01112 sacheadp->az = (float) azm; 01113 } 01114 } 01115 } 01116 01117 if ((pStation->bResponseIsValid) && 01118 ((pStation->pResponse->iNumPoles > 0) || 01119 (pStation->pResponse->iNumZeroes > 0))) 01120 { 01121 /* create the full SAC file name for this SCN PZ file */ 01122 sprintf(szPZFilename,"%s/%s.%s.%s.pz",SacDir, SAC_szSta, SAC_szChan, 01123 SAC_szNet); 01124 fpPZ=fopen(szPZFilename,"w"); 01125 if(!fpPZ) 01126 { 01127 logit("e","SACPABase_write_stainfo(): Failed to open file: %s! Errno=%d\n", 01128 szPZFilename,errno); 01129 return(SACPAB_FOPEN_FAILED); 01130 } 01131 01132 fprintf(fpPZ,"POLES %d\n",pStation->pResponse->iNumPoles); 01133 for(i=0;i<pStation->pResponse->iNumPoles;i++) 01134 { 01135 fprintf(fpPZ,"%f %f\n",pStation->pResponse->Poles[i].dReal, 01136 pStation->pResponse->Poles[i].dImag); 01137 } 01138 01139 fprintf(fpPZ,"ZEROS %d\n",pStation->pResponse->iNumZeroes); 01140 for(i=0;i<pStation->pResponse->iNumZeroes;i++) 01141 { 01142 fprintf(fpPZ,"%f %f\n",pStation->pResponse->Zeroes[i].dReal, 01143 pStation->pResponse->Zeroes[i].dImag); 01144 } 01145 01146 fprintf(fpPZ,"CONSTANT %e\n",pStation->pResponse->dGain); 01147 01148 fclose(fpPZ); 01149 } /* end if(bResponseIsValid) */ 01150 01151 return(EW_SUCCESS); 01152 } 01153 01154 01155 01156 01157 int SACPABase_end_scn (void) 01158 { 01159 size_t towrite; /* bytes to write to SAC file */ 01160 char sacfile[2*MAXTXT]; /* the name of the sac file */ 01161 FILE *fp; /* sacfile file pointer */ 01162 long i, npts; /* number of SAC data points */ 01163 float *sac_p; 01164 01165 if(!bSACPABase_scn_open) 01166 { 01167 logit("e","SACPABase_end_scn(): ERROR! There is no open SCN record.\n"); 01168 return(SACPAB_SCN_NOT_OPEN); 01169 } 01170 01171 npts = sacheadp->npts; 01172 sac_p = (float *)(SacBuffer + SACHEADERSIZE); 01173 if (strcmp (SAC_szOutputFormat, SAC_DIFFERENT_PLATFORM) == 0) 01174 { 01175 swapsac(sacheadp); 01176 for (i = 0; i < npts; i++) 01177 SwapFloat(&sac_p[i]); 01178 } 01179 01180 /* copy the (potentially byte-swapped) SAC header 01181 into the SAC buffer and write it out. 01182 ******************************************************/ 01183 memcpy ((void *) SacBuffer, (void *) sacheadp, SACHEADERSIZE); 01184 01185 /* Update SAC file list with file name and arrival time */ 01186 sprintf (FileList[FileIndex].filename, "%s.%s.%s", SAC_szSta, SAC_szChan, 01187 SAC_szNet); 01188 FileList[FileIndex].sort_param = SAC_starttime; 01189 01190 if ((FileIndex = FileIndex + 1) > DB_MAX_PHS_PER_EQ) 01191 { 01192 logit ("e", "SACPABase_end_scn: WARNING: Maximum number of phases per " 01193 "event (%d) exceeded.\n", DB_MAX_PHS_PER_EQ); 01194 01195 FileIndex = FileIndex - 1; 01196 } 01197 01198 /* create the full SAC file name for this SCN */ 01199 sprintf(sacfile, "%s/%s", SacDir, FileList[FileIndex-1].filename); 01200 01201 01202 /* Open the sacfile */ 01203 if ((fp = fopen (sacfile, "wb")) == NULL) 01204 { 01205 logit("e", "SACPABase_next_scn: cannot open %s\n", sacfile); 01206 return(EW_FAILURE); 01207 } 01208 01209 /* Write the buffer to the sacfile */ 01210 towrite = SACHEADERSIZE + sizeof(float) * npts; 01211 if (fwrite ((const void *) SacBuffer, towrite, 1, fp) != 1) 01212 { 01213 logit("e", "SACPABase_end_scn: cannot write %s\n", sacfile); 01214 (void) unlink(sacfile); 01215 return EW_FAILURE; 01216 } 01217 fclose (fp); 01218 01219 /* mark the SCN closed */ 01220 bSACPABase_scn_open=FALSE; 01221 return(EW_SUCCESS); 01222 } 01223 01224 01225 int SACPABase_end_scn_gm (void) 01226 { 01227 size_t towrite; /* bytes to write to SAC file */ 01228 char sacfile[2*MAXTXT]; /* the name of the sac file */ 01229 FILE *fp; /* sacfile file pointer */ 01230 long i, npts; /* number of SAC data points */ 01231 float *sac_p; 01232 01233 if(!bSACPABase_scn_open) 01234 { 01235 logit("e","SACPABase_end_scn(): ERROR! There is no open SCN record.\n"); 01236 return(SACPAB_SCN_NOT_OPEN); 01237 } 01238 01239 npts = sacheadp->npts; 01240 sac_p = (float *)(SacBuffer + SACHEADERSIZE); 01241 if (strcmp (SAC_szOutputFormat, SAC_DIFFERENT_PLATFORM) == 0) 01242 { 01243 swapsac(sacheadp); 01244 for (i = 0; i < npts; i++) 01245 SwapFloat(&sac_p[i]); 01246 } 01247 01248 /* copy the (potentially byte-swapped) SAC header 01249 into the SAC buffer and write it out. 01250 ******************************************************/ 01251 memcpy ((void *) SacBuffer, (void *) sacheadp, SACHEADERSIZE); 01252 01253 01254 /* create the full SAC file name for this SCN */ 01255 sprintf(sacfile, "%s/%s.gm", SacDir, FileList[FileIndex-1].filename); 01256 01257 01258 /* Open the sacfile */ 01259 if ((fp = fopen (sacfile, "wb")) == NULL) 01260 { 01261 logit("e", "SACPABase_next_scn: cannot open %s\n", sacfile); 01262 return(EW_FAILURE); 01263 } 01264 01265 /* Write the buffer to the sacfile */ 01266 towrite = SACHEADERSIZE + sizeof(float) * npts; 01267 if (fwrite ((const void *) SacBuffer, towrite, 1, fp) != 1) 01268 { 01269 logit("e", "SACPABase_end_scn: cannot write %s\n", sacfile); 01270 (void) unlink(sacfile); 01271 return EW_FAILURE; 01272 } 01273 fclose (fp); 01274 01275 /* mark the SCN closed */ 01276 bSACPABase_scn_open=FALSE; 01277 return(EW_SUCCESS); 01278 } 01279 01280 01281 /************************************************************************ 01282 * This is the Put Away end event routine. It's called after we've * 01283 * finished processing one event. * 01284 *************************************************************************/ 01285 int SACPABase_end_ev (void) 01286 { 01287 01288 if (SACPAB_Debug == 1) 01289 logit ("", "In SACPA_end_ev\n"); 01290 01291 qsort ((void *) FileList, (size_t) FileIndex, 01292 sizeof (SACFileListStruct), SAC_Compare); 01293 01294 /* We haven't processed an event - something's fishy! */ 01295 if (!strcmp(szCurEventID,"-1")) 01296 { 01297 logit ("e", "SACPA_end_ev: CurEventId is invalid - don't know how to proceed\n"); 01298 01299 return EW_FAILURE; 01300 } 01301 01302 01303 if (CreateSACSupportFiles (szCurEventID, FileList, FileIndex) != EW_SUCCESS) 01304 { 01305 logit ("e", "SACPABase_write_trace: Call to CreateSACSupportFiles failed\n"); 01306 return EW_FAILURE; 01307 } 01308 01309 return(EW_SUCCESS); 01310 } 01311 01312 01313 /************************************************************************ 01314 * This is the Put Away close routine. It's called after when * 01315 * we're being shut down. * 01316 *************************************************************************/ 01317 int SACPABase_close (void) 01318 { 01319 01320 free ((char *) SacBuffer); 01321 if (!bSACPABase_init) 01322 { 01323 logit("","SACPABase_close(): Error, SACPABase is not initialized!\n"); 01324 return(SACPAB_NOT_INIT); 01325 } 01326 bSACPABase_init = FALSE; 01327 return EW_SUCCESS; 01328 } 01329 01330 01331 void sacinit( struct SAChead *head) 01332 { 01333 int i; 01334 struct SAChead2 *head2; /* use a simple structure here - we don't care what 01335 * the variables are - set them to 'undefined' */ 01336 01337 /* change to a simpler format */ 01338 head2 = (struct SAChead2 *) head; 01339 01340 /* set all of the floats to 'undefined' */ 01341 for (i = 0; i < NUM_FLOAT; ++i) head2->SACfloat[i] = SACUNDEF; 01342 /* set all of the ints to 'undefined' */ 01343 for (i = 0; i < MAXINT-5; ++i) head2->SACint[i] = SACUNDEF; 01344 /* except for the logical integers - set them to 1 */ 01345 for ( ; i < MAXINT; ++i) head2->SACint[i] = 1; 01346 /* set all of the strings to 'undefined' */ 01347 for (i = 0; i < MAXSTRING; ++i) (void) strncpy(head2->SACstring[i], 01348 SACSTRUNDEF,K_LEN); 01349 01350 /* SAC I.D. number */ 01351 head2->SACfloat[9] = SAC_I_D; 01352 /* header version number */ 01353 head2->SACint[6] = SACVERSION; 01354 01355 return; /* done */ 01356 } 01357 01358 /* 01359 * swapsac: swap all the numeric fields in the SAC header. 01360 */ 01361 void swapsac(struct SAChead *head) 01362 { 01363 int i; 01364 struct SAChead2 *head2; /* use a simple structure here - we don't care what 01365 * the variables are - just swap their bytes! */ 01366 01367 /* change to a simpler format */ 01368 head2 = (struct SAChead2 *) head; 01369 01370 /* swap all of the floats */ 01371 for (i = 0; i < NUM_FLOAT; ++i) 01372 SwapFloat(&head2->SACfloat[i]); 01373 01374 /* swap all of the ints */ 01375 for ( i = 0; i < MAXINT; ++i) 01376 SwapLong( &(head2->SACint[i])); 01377 01378 return; 01379 } 01380 01381 /************************************************** 01382 * SAC_Compare() compares 2 values * 01383 * This function is passed to qsort() * 01384 **************************************************/ 01385 int SAC_Compare (const void *p1, const void *p2) 01386 { 01387 SACFileListStruct *srt1 = (SACFileListStruct *) p1; 01388 SACFileListStruct *srt2 = (SACFileListStruct *) p2; 01389 01390 if (srt1->sort_param < srt2->sort_param) 01391 return (-1); 01392 01393 if (srt1->sort_param > srt2->sort_param) 01394 return (1); 01395 01396 return (0); 01397 } 01398 01399 01400 01401 01402 /* SACSupportFiles 01403 * 01404 * Write simple SAC macros to disk files in current working directory, 01405 * given a list of filenames sorted in some order. 01406 * 01407 * Also write other files necessary for relocating the event 01408 * with hypoinverse and for updating database. 01409 * July 1998, LDD 01410 */ 01411 01412 /* how many traces do we want in the quicklook macro */ 01413 #define NQUICKLOOK 10 01414 01415 /* Support file names */ 01416 #define INIT_FNAME "init" 01417 #define QUICKLOOK_FNAME "quicklook" 01418 #define REPICK_FNAME "repick" 01419 #define SACLIST_FNAME "saclist" 01420 01421 /******************************************************* 01422 * CreateSACSupportFiles() writes all the desired SAC macros 01423 * and Hypoinv files to the current working directory 01424 *******************************************************/ 01425 int CreateSACSupportFiles (char * szEventid, SACFileListStruct *pfl, int nfile) 01426 { 01427 int nlook; 01428 01429 if (SACmac_init() != EW_SUCCESS) 01430 { 01431 logit ("e", "Call to SACmac_init failed\n"); 01432 return EW_FAILURE; 01433 } 01434 01435 nlook = (nfile < NQUICKLOOK) ? nfile : NQUICKLOOK; 01436 if (SACmac_quicklook (pfl, nlook) != EW_SUCCESS) 01437 { 01438 logit ("e", "Call to SACmac_quicklook failed\n"); 01439 return EW_FAILURE; 01440 } 01441 01442 01443 if (SACmac_repick (pfl, nfile) != EW_SUCCESS) 01444 { 01445 logit ("e", "Call to SACmac_repick failed\n"); 01446 return EW_FAILURE; 01447 } 01448 01449 if (SAC_filelist (pfl, nfile, szEventid) != EW_SUCCESS) 01450 { 01451 logit ("e", "Call to SAC_filelist failed\n"); 01452 return EW_FAILURE; 01453 } 01454 01455 return (EW_SUCCESS); 01456 01457 } 01458 01459 /************************************************** 01460 * SACmac_init() writes a simple initialization * 01461 * macro to the current working directory in a * 01462 * file named "init" * 01463 **************************************************/ 01464 int SACmac_init (void) 01465 { 01466 FILE *fp; 01467 char filename[256]; 01468 01469 sprintf (filename, "%s/%s", SacDir, INIT_FNAME); 01470 01471 if ((fp = fopen (filename, "w+")) == NULL) 01472 { 01473 logit ("e", "SACmac_init: cannot open macro file %s; %s\n", 01474 filename, strerror (errno)); 01475 return (EW_FAILURE); 01476 } 01477 01478 fprintf (fp, "qdp 1000\n" 01479 "window 1 x 0 1 y 0.35 0.97\n" 01480 "bd X\n" 01481 "bw 1\n" ); 01482 fclose (fp); 01483 01484 return (EW_SUCCESS); 01485 } 01486 01487 01488 /************************************************** 01489 * SACmac_quicklook() writes a macro to bring up * 01490 * the first nlook files in the list. The list * 01491 * should be sorted before invoking this funtion * 01492 **************************************************/ 01493 int SACmac_quicklook (SACFileListStruct *pfl, int nlook) 01494 { 01495 FILE *fp; 01496 int i; 01497 char filename[256]; 01498 01499 sprintf (filename, "%s/%s", SacDir, QUICKLOOK_FNAME); 01500 01501 if ((fp = fopen (filename, "w+")) == NULL) 01502 { 01503 logit("e", "SACmac_quicklook: cannot open macro file %s; %s\n", 01504 filename, strerror (errno)); 01505 return (EW_FAILURE); 01506 } 01507 01508 fprintf (fp, "qdp 500\n" 01509 "fileid type list kevnm kstcmp\n" 01510 "r "); 01511 01512 for (i = 0; i < nlook; i++ ) 01513 fprintf (fp, "%s ", pfl[i].filename); 01514 01515 fprintf (fp, "\n" 01516 "p1\n"); 01517 01518 fclose (fp); 01519 01520 return (EW_SUCCESS); 01521 } 01522 01523 01524 /************************************************** 01525 * SACmac_repick() writes a macro to bring up * 01526 * each trace for this event to repick it * 01527 **************************************************/ 01528 int SACmac_repick (SACFileListStruct *pfl, int nfile) 01529 { 01530 FILE *fp; 01531 int i; 01532 char filename[256]; 01533 01534 sprintf (filename, "%s/%s", SacDir, REPICK_FNAME); 01535 01536 if ((fp = fopen (filename, "w+")) == NULL) 01537 { 01538 logit ("e", "SACmac_repick: cannot open macro file %s; %s\n", 01539 filename, strerror (errno)); 01540 return (EW_FAILURE); 01541 } 01542 01543 fprintf (fp, "qdp 500\n" 01544 "fileid type list kevnm kstcmp\n"); 01545 01546 fprintf (fp, "r %s\n" 01547 "ppk p off b off\n" 01548 "wh\n", 01549 pfl[0].filename); /* Turn off that darn bell! */ 01550 01551 for (i = 1; i < nfile; i++) 01552 { 01553 fprintf (fp, "r %s\n" 01554 "ppk p off\n" 01555 "wh\n", 01556 pfl[i].filename); 01557 } 01558 fclose (fp); 01559 01560 return (EW_SUCCESS); 01561 } 01562 01563 01564 /************************************************** 01565 * SAC_filelist() writes a file containing the * 01566 * names of all the SAC files in the directory * 01567 **************************************************/ 01568 int SAC_filelist (SACFileListStruct *pfl, int nfile, char * szEventid) 01569 { 01570 FILE *fp; 01571 int i; 01572 char filename[256]; 01573 01574 sprintf (filename, "%s/%s", SacDir, SACLIST_FNAME); 01575 01576 if ((fp = fopen (filename, "w+")) == NULL) 01577 { 01578 logit ("e", "SACmac_filelist: cannot open file %s; %s\n", 01579 filename, strerror (errno)); 01580 return (EW_FAILURE); 01581 } 01582 01583 fprintf (fp, "EVENTID:%s\n", szEventid); 01584 01585 for (i = 0; i < nfile; i++) 01586 { 01587 fprintf (fp, "%s\n", pfl[i].filename); 01588 } 01589 01590 fclose (fp); 01591 01592 return (EW_SUCCESS); 01593 } 01594 01595 int SAC_SwapLong(long * pValue, char cDataType) 01596 { 01597 #if defined (_SPARC) 01598 if( cDataType == 'i' || cDataType == 'f' ) 01599 SwapLong(pValue); 01600 return(EW_SUCCESS); 01601 #elif defined (_INTEL) 01602 if( cDataType == 's' || cDataType == 't' ) 01603 SwapLong(pValue); 01604 return(EW_SUCCESS); 01605 #else 01606 logit("e","SAC_SwapLong():Error! Unable to determine platform! " 01607 "Please compile w/ _INTEL or _SPARC!\n"); 01608 return(SACPAB_UNKNOWN_PLATFORM); 01609 #endif 01610 } 01611 01612 int SAC_SwapShort(short * pValue, char cDataType) 01613 { 01614 #if defined (_SPARC) 01615 if( cDataType == 'i' || cDataType == 'f' ) 01616 SwapShort(pValue); 01617 return(EW_SUCCESS); 01618 #elif defined (_INTEL) 01619 if( cDataType == 's' || cDataType == 't' ) 01620 SwapShort(pValue); 01621 return(EW_SUCCESS); 01622 #else 01623 logit("e","SAC_SwapShort():Error! Unable to determine platform! " 01624 "Please compile w/ _INTEL or _SPARC!\n"); 01625 return(SACPAB_UNKNOWN_PLATFORM); 01626 #endif 01627 } 01628 01629 int SAC_SwapDouble(double * pValue, char cDataType) 01630 { 01631 #if defined (_SPARC) 01632 if( cDataType == 'i' || cDataType == 'f' ) 01633 SwapDouble(pValue); 01634 return(EW_SUCCESS); 01635 #elif defined (_INTEL) 01636 if( cDataType == 's' || cDataType == 't' ) 01637 SwapDouble(pValue); 01638 return(EW_SUCCESS); 01639 #else 01640 logit("e","SAC_SwapDouble():Error! Unable to determine platform! " 01641 "Please compile w/ _INTEL or _SPARC!\n"); 01642 return(SACPAB_UNKNOWN_PLATFORM); 01643 #endif 01644 } 01645 01646 01647 /* Write urban hazards external info into the header */ 01648 int SACPABase_write_extinfo (SAC_ExtChanStruct *pExtChan) 01649 { 01650 01651 if (pExtChan == NULL) 01652 { 01653 logit ("", "SACPABase_write_extinfo: Invalid arguments passed in\n"); 01654 return (EW_FAILURE); 01655 } 01656 01657 01658 sacheadp->user0 = (float) pExtChan->iGain; 01659 sacheadp->user1 = (float) pExtChan->dFullscale; 01660 sacheadp->user2 = (float) pExtChan->dSensitivity; 01661 sacheadp->user3 = (float) pExtChan->dDamping; 01662 sacheadp->user4 = (float) pExtChan->dNaturalFrequency; 01663 sacheadp->user5 = (float) pExtChan->iSensorType; 01664 01665 sacheadp->cmpaz = (float) pExtChan->dAzm; 01666 sacheadp->cmpinc = (float) pExtChan->dDip; 01667 01668 return(EW_SUCCESS); 01669 01670 } 01671 01672