static void handleClient(SOCKET sock) { byte buffer[64]; int read; const int rxBufferSize = 1024; // max size of unfamed package const struct timeval timeout = {0, 50 * 1000}; // 50 milliseconds timeout for select() const int noDelay = 1; const int streamBufferSize = 128; fd_set fdset; int fdsReady; ClientInfo client; // allocate large objects on the heap GlowReader *pReader = newobj(GlowReader); byte *pRxBuffer = newarr(byte, rxBufferSize); byte *pStreamBuffer = newarr(byte, streamBufferSize); srand((unsigned int)time(NULL)); // turn off nagle algorithm for ppm data setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&noDelay, sizeof(noDelay)); bzero(client); client.sock = sock; // only handle parameters and commands glowReader_init(pReader, NULL, onParameter, onCommand, NULL, (voidptr)&client, pRxBuffer, rxBufferSize); pReader->onPackageReceived = onPackageReceived; while(true) { FD_ZERO(&fdset); FD_SET(sock, &fdset); // wait for input, if none received -> send ppm data fdsReady = select(1, &fdset, NULL, NULL, &timeout); if(fdsReady == 1) // socket is ready to read { if(FD_ISSET(sock, &fdset)) { read = recv(sock, (char *)buffer, sizeof(buffer), 0); printf_s("received %d bytes\n", read); if(read > 0) glowReader_readBytes(pReader, buffer, read); else break; } } else if(fdsReady == 0) // timeout { // generate some random ppm data for this sample. usually, ppm data is delivered by some ppm driver collectPpmData(); sendPpmStreams(sock, pStreamBuffer, streamBufferSize, &client); } else { break; } } closesocket(sock); glowReader_free(pReader); freeMemory(pStreamBuffer); freeMemory(pRxBuffer); freeMemory(pReader); }
int main( int argc, char **argv ) { int c; int errflag = 0; int orb; int stop = 0; long nrecs; char *match = ".*/pf/st"; char *from = 0; char *statefile = 0; char *pfname = "orb2rrdc"; char *orbname; char *dbcache; char *rrdtool; char command[STRSZ]; char net[STRSZ]; char sta[STRSZ]; char rrdvar[STRSZ]; char key[STRSZ]; char path[FILENAME_MAX]; Dbptr db; Dbptr dbt; Pf *pf; char *Default_network; Tbl *dlslines; Arr *Dls_vars_dsparams; Arr *Dls_vars_rras; Tbl *Dls_vars_keys; char *line; char *dls_var; char *dsparams; Tbl *rras; int i; int j; OrbreapThr *ort; int pktid; char srcname[ORBSRCNAME_SIZE]; double time = 0; char *packet = 0; int nbytes = 0; int bufsize = 0; Packet *pkt = 0; int rc; char *s; Pf *dlspf; Tbl *dlspfkeys; char *element; Tbl *parts; double val; Pf *pfval = 0; elog_init( argc, argv ); while( ( c = getopt( argc, argv, "vVd:s:p:m:f:" ) ) != -1 ) { switch( c ) { case 'd': CacheDaemon = optarg; break; case 'f': from = optarg; break; case 'm': match = optarg; break; case 'p': pfname = optarg; break; case 's': statefile = optarg; break; case 'v': Verbose++; break; case 'V': VeryVerbose++; Verbose++; break; default: elog_complain( 0, "Unknown option '%c'\n", c ); errflag++; break; } } if( errflag || argc - optind != 2 ) { usage(); } if( Verbose ) { elog_notify( 0, "Starting at %s (%s $Revision$ $Date$)\n", zepoch2str( str2epoch( "now" ), "%D %T %Z", "" ), Program_Name ); } orbname = argv[optind++]; dbcache = argv[optind++]; pfread( pfname, &pf ); rrdtool = pfget_string( pf, "rrdtool" ); if( rrdtool == NULL || ! strcmp( rrdtool, "" ) ) { elog_die( 0, "Error: no rrdtool executable name specified in parameter file\n" ); } else if( ( rrdtool[0] == '/' && ! is_present( rrdtool ) ) || ( rrdtool[0] != '/' && ! datafile( "PATH", rrdtool ) ) ) { elog_die( 0, "Error: can't find rrdtool executable by name of '%s' (check PATH environment " "variable, or absolute path name if given)\n", rrdtool ); } else if( rrdtool[0] == '/' ) { sprintf( command, "%s -", rrdtool ); } else { sprintf( command, "rrdtool -" ); } Suppress_egrep = pfget_string( pf, "suppress_egrep" ); if( Suppress_egrep != NULL && strcmp( Suppress_egrep, "" ) ) { if( ! datafile( "PATH", "egrep" ) ) { elog_complain( 0, "Ignoring suppress_egrep parameter: can't find egrep on path\n" ); } else { sprintf( command, "%s 2>&1 | egrep -v '%s'", command, Suppress_egrep ); } } if( VeryVerbose ) { elog_notify( 0, "Executing command: %s\n", command ); } Rrdfp = popen( command, "w" ); if( Rrdfp == (FILE *) NULL ) { elog_die( 0, "Failed to open socket to rrdtool command\n" ); } orb = orbopen( orbname, "r&" ); if( orb < 0 ) { elog_die( 0, "Failed to open orb '%s' for reading. Bye.\n", orbname ); } orbselect( orb, match ); if( from != NULL && statefile == NULL ) { pktid = orbposition( orb, from ); if( Verbose ) { elog_notify( 0, "Positioned to packet %d\n", pktid ); } } else if( from != NULL ) { elog_complain( 0, "Ignoring -f in favor of existing state file\n" ); } if( statefile != NULL ) { stop = 0; exhume( statefile, &stop, 15, 0 ); orbresurrect( orb, &pktid, &time ); if( Verbose ) { elog_notify( 0, "Resurrecting state to pktid %d, time %s\n", pktid, s = strtime( time ) ); free( s ); } orbseek( orb, pktid ); } dbopen( dbcache, "r+", &db ); if( db.database < 0 ) { elog_die( 0, "Failed to open cache database '%s'. Bye.\n", dbcache ); } else { db = dblookup( db, "", "rrdcache", "", "" ); if( db.table < 0 ) { elog_die( 0, "Failed to lookup 'rrdcache' table in '%s'. Bye.\n", dbcache ); } } dbcrunch( db ); dbt = dbsubset( db, "endtime == NULL", NULL ); Rrd_files = newarr( 0 ); dbquery( dbt, dbRECORD_COUNT, &nrecs ); for( dbt.record = 0; dbt.record < nrecs; dbt.record++ ) { dbgetv( dbt, 0, "net", &net, "sta", &sta, "rrdvar", &rrdvar, NULL ); dbfilename( dbt, (char *) &path ); sprintf( key, "%s:%s:%s", net, sta, rrdvar ); if( ! is_present( path ) ) { elog_complain( 0, "WARNING: rrd file '%s', listed in database, does not exist. " "Removing database entry.\n", path ); dbmark( dbt ); } else { setarr( Rrd_files, key, strdup( path ) ); if( VeryVerbose ) { elog_notify( 0, "Re-using rrd file '%s' for '%s'\n", path, key ); } } } Rrdfile_pattern = pfget_string( pf, "rrdfile_pattern" ); Status_stepsize_sec = pfget_double( pf, "status_stepsize_sec" ); Default_network = pfget_string( pf, "default_network" ); dlslines = pfget_tbl( pf, "dls_vars" ); Dls_vars_dsparams = newarr( 0 ); Dls_vars_rras = newarr( 0 ); for( i = 0; i < maxtbl( dlslines ); i++ ) { line = gettbl( dlslines, i ); strtr( line, "\t", " " ); rras = split( line, ' ' ); dls_var = shifttbl( rras ); dsparams = shifttbl( rras ); setarr( Dls_vars_dsparams, dls_var, dsparams ); setarr( Dls_vars_rras, dls_var, rras ); } ort = orbreapthr_new( orb, -1., 0 ); for( ; stop == 0; ) { orbreapthr_get( ort, &pktid, srcname, &time, &packet, &nbytes, &bufsize ); if( statefile ) { rc = bury(); if( rc < 0 ) { elog_complain( 0, "Unexpected failure of bury command! " "(are there two orb2rrdc's running with the same state" "file?)\n" ); clear_register( 1 ); } } rc = unstuffPkt( srcname, time, packet, nbytes, &pkt ); if( rc == Pkt_pf ) { if( VeryVerbose ) { /* Parameter files generally too big for elog */ fprintf( stderr, "Received a parameter-file '%s' at %s\n%s\n\n", srcname, s = strtime( time ), pf2string( pkt->pf ) ); free( s ); } else if( Verbose ) { elog_notify( 0, "Received a parameter-file '%s' at %s\n", srcname, s = strtime( time ) ); free( s ); } pfmorph( pkt->pf ); if( VeryVerbose ) { fprintf( stderr, "Morphed parameter-file '%s' to interpret 'opt':\n%s\n\n", srcname, pf2string( pkt->pf ) ); } pfget( pkt->pf, "dls", (void **) &dlspf ); dlspfkeys = pfkeys( dlspf ); Dls_vars_keys = keysarr( Dls_vars_dsparams ); for( i = 0; i < maxtbl( dlspfkeys ); i++ ) { element = gettbl( dlspfkeys, i ); if( strcontains( element, "_", 0, 0, 0 ) ) { parts = split( (s = strdup( element )), '_' ); sprintf( net, "%s", (char *) gettbl( parts, 0 ) ); sprintf( sta, "%s", (char *) gettbl( parts, 1 ) ); free( s ); freetbl( parts, 0 ); } else { sprintf( net, "%s", Default_network ); sprintf( sta, "%s", element ); } for( j = 0; j < maxtbl( Dls_vars_keys ); j++ ) { dls_var = gettbl( Dls_vars_keys, j ); sprintf( key, "%s{%s}", element, dls_var ); if( pfresolve( dlspf, key, 0, &pfval ) < 0 ) { elog_complain( 0, "Unable to extract variable '%s' " "(not present or wrong type) from element '%s' " "in packet from '%s', timestamped '%s'; Skipping\n", key, element, srcname, s = strtime( time ) ); free( s ); pfval = 0; continue; } else if( pfval != (Pf *) NULL && pfval->value.s != (char *) NULL && ! strcmp( pfval->value.s, "-" ) ) { if( VeryVerbose ) { elog_notify( 0, "Non-floating point value '-' in variable '%s', " "in packet from '%s', timestamped '%s'; Skipping data point\n", key, srcname, s = strtime( time ) ); free( s ); } continue; } else { val = pfget_double( dlspf, key ); } archive_dlsvar( db, net, sta, dls_var, (char *) getarr( Dls_vars_dsparams, dls_var ), (Tbl *) getarr( Dls_vars_rras, dls_var ), time, val ); } } freetbl( dlspfkeys, 0 ); freetbl( Dls_vars_keys, 0 ); } else if( rc == Pkt_stash ) { ; /* Do nothing */ } else { if( Verbose ) { elog_notify( 0, "Received a packet that's not a parameter file " "(type '%d' from unstuffPkt); skipping\n", rc ); } } } }
static void onCommand(const GlowCommand *pCommand, const berint *pPath, int pathLength, voidptr state) { int bufferSize = 512; byte *pBuffer; GlowOutput output; ClientInfo *pClientInfo = (ClientInfo *)state; berint *pOutPath; int nodeIndex; SampleNode *pCurrent; SampleNode *pCursor = findNode(&_root, pPath, &pathLength); SOCKET sock = pClientInfo->sock; int fields; if(pCommand->number == GlowCommandType_GetDirectory) { pOutPath = newarr(berint, GLOW_MAX_TREE_DEPTH); memcpy(pOutPath, pPath, pathLength * sizeof(berint)); pBuffer = newarr(byte, bufferSize); glowOutput_init(&output, pBuffer, bufferSize, 0); if(pCursor->isParameter) { // parameter - send single complete parameter fields = pCursor->fields & pCommand->options.dirFieldMask; glowOutput_beginPackage(&output, true); glow_writeQualifiedParameter(&output, &pCursor->param, (GlowFieldFlags)fields, pOutPath, pathLength); send(sock, (char *)pBuffer, glowOutput_finishPackage(&output), 0); } else if(pCursor->childrenCount == 0) { // leaf node - send single empty node fields = 0; glowOutput_beginPackage(&output, true); glow_writeQualifiedNode(&output, &pCursor->node, (GlowFieldFlags)fields, pOutPath, pathLength); send(sock, (char *)pBuffer, glowOutput_finishPackage(&output), 0); } else { // node - send children for(nodeIndex = 0; nodeIndex < pCursor->childrenCount; nodeIndex++) { pCurrent = pCursor->children[nodeIndex]; if(pCurrent != NULL) { glowOutput_beginPackage(&output, nodeIndex == pCursor->childrenCount - 1); pOutPath[pathLength] = nodeIndex; fields = pCurrent->fields & pCommand->options.dirFieldMask; if(pCurrent->isParameter) glow_writeQualifiedParameter(&output, &pCurrent->param, (GlowFieldFlags)fields, pOutPath, pathLength + 1); else glow_writeQualifiedNode(&output, &pCurrent->node, (GlowFieldFlags)fields, pOutPath, pathLength + 1); send(sock, (char *)pBuffer, glowOutput_finishPackage(&output), 0); } } } freeMemory(pBuffer); freeMemory(pOutPath); } else if(pCommand->number == GlowCommandType_Subscribe) { if(pCursor->isParameter && pCursor->param.streamIdentifier >= 0 && pCursor->param.streamIdentifier < STREAMS_COUNT) pClientInfo->streamSubscriptions[pCursor->param.streamIdentifier]++; } else if(pCommand->number == GlowCommandType_Unsubscribe) { if(pCursor->isParameter && pCursor->param.streamIdentifier >= 0 && pCursor->param.streamIdentifier < STREAMS_COUNT) pClientInfo->streamSubscriptions[pCursor->param.streamIdentifier]--; } }
void save_assoc(Dbptr dbi, int is, int ie, int orid, char *vmodel, Tbl *residual,Hypocenter h, Dbptr dbo) { /* These fields are copied from input assoc table */ int arid; char sta[8]; char phase[10]; double belief; /* These fields are set here */ double delta; double seaz; double esaz; double timeres; double azres; double slores; double lddate; double wgt; char timedef[2],slodef[2], azdef[2]; /* intentionally ignored: emares, commid */ /* passed through arg list; orid*/ /* We use this to produce a keyed arr list of the residual list passed into here as a Tbl */ Arr *residual_array; int i; char key[40]; double r, w, reswt,uxresid, uyresid; double stalat, stalon; double ux, uy, azimuth; double u,phi; /* polar form of measured slowness vector */ double duphi; dbo = dblookup(dbo,0,"assoc",0,0); lddate = now(); /* We build an associate array for the residual tbl keying each entry with a sta/phase/type key where type is set in ggnloc as time, ux, or uy. This complication is needed to sort out array residuals. */ residual_array = newarr(0); for(i=0;i<maxtbl(residual);++i) { char *s; char keysta[10], keyphase[10], keytype[5]; s = (char *)gettbl(residual,i); sscanf(s,"%s %s %s",keysta,keyphase,keytype); /* handle S-P case by having the same residual mapped to each half of - phase pair */ if(strchr(keyphase,'-')) { char *phase1,*phase2; /* algorithm to split phase names cloned from dbgenloc */ phase1 = strdup(keyphase); phase2= strchr(phase1,'-'); *phase2 = '\0'; ++phase2; sprintf(key,"%s %s %s",keysta,phase1,keytype); setarr(residual_array,key,s); sprintf(key,"%s %s %s",keysta,phase2,keytype); setarr(residual_array,key,s); free(phase1); } else { /* normal phases are one to one */ sprintf(key,"%s %s %s",keysta,keyphase,keytype); setarr(residual_array,key,s); } } for(dbi.record=is;dbi.record < ie;++dbi.record) { char *time_residual_record; char *ux_residual_record,*uy_residual_record; if( dbgetv(dbi,0, "assoc.arid",&arid, "assoc.sta",sta, "assoc.phase",phase, "assoc.belief",&belief, 0) == dbINVALID) { die(1,"save_assoc: dbgetv error reading assoc fields of input view at record %d\n", dbi.record); } if( dbgetv(dbi,0, "site.lat",&stalat, "site.lon",&stalon, 0) == dbINVALID) { die(1,"save_assoc: dbgetv error reading site fields of input view at record %d\n", dbi.record); } /* Find the time residual record for this arrival */ sprintf(key,"%s %s time",sta,phase); time_residual_record = (char *)getarr(residual_array,key); if(time_residual_record == NULL) { complain(1,"save_assoc: getarr mismatch for key %s\nCannot set residual\n",key); timeres = TIMENULL; wgt = 0.0; strcpy(timedef,"n"); } else { /* Changed by JN to avoid gcc warning */ /* sscanf(time_residual_record,"%*s%*s%*s%*lg%lg%lg%lg", */ sscanf(time_residual_record,"%*s%*s%*s%*g%lg%lg%lg", &r,&w,&reswt); timeres = r; wgt = w*reswt; strcpy(timedef,"d"); } sprintf(key,"%s %s ux",sta,phase); ux_residual_record = (char *)getarr(residual_array,key); sprintf(key,"%s %s uy",sta,phase); uy_residual_record = (char *)getarr(residual_array,key); /* Corrected by JN if( (ux_residual_record == NULL) || (ux_residual_record == NULL)) */ if( (ux_residual_record == NULL) || (uy_residual_record == NULL)) { /* This trick is not documented. By setting the record filed to dbNULL, and then calling dbgetv each of the fields will be set to their NULL value */ dbo.record = dbNULL; dbgetv(dbo,0,"azres",&azres,"slores",&slores,0); strcpy(azdef,"n"); strcpy(slodef,"n"); } else { /* This gets nasty because we have to convert to polar coordinates from ux, uy components */ sscanf(ux_residual_record,"%*s%*s%*s%*g%lg",&uxresid); sscanf(uy_residual_record,"%*s%*s%*s%*g%lg",&uyresid); /* We fetch the measured slowness vector to convert */ if( dbgetv(dbi,0, "arrival.slow",&u, "arrival.azimuth",&phi, 0) == dbINVALID) { die(1,"save_assoc: dbgetv error reading arrival fields of input view at record %d\n", dbi.record); } /* css stores slowness in s/deg, but we use s/km internally here so we have to convert */ slores = sqrt(uxresid*uxresid+uyresid*uyresid); slores *= KMPERDEG; /* this is the azimuth term */ u /= KMPERDEG; duphi = ux*cos(rad(azimuth)) - uy*sin(rad(azimuth)); duphi /= u; azres = deg(duphi); strcpy(azdef,"d"); strcpy(slodef,"d"); } dist(rad(h.lat),rad(h.lon),rad(stalat),rad(stalon), &delta,&esaz); dist(rad(stalat),rad(stalon),rad(h.lat),rad(h.lon), &delta,&seaz); delta = deg(delta); seaz = deg(seaz); esaz = deg(esaz); if(dbaddv(dbo,0, "arid",arid, "orid",orid, "sta",sta, "phase",phase, "belief",belief, "delta",delta, "seaz",seaz, "esaz",esaz, "timeres",timeres, "timedef",timedef, "azres",azres, "azdef",azdef, "slores",slores, "slodef",slodef, "wgt",wgt, "vmodel",vmodel, "lddate",lddate, 0) == dbINVALID) { die(1,"save_assoc: dbaddv error writing assoc record for arid %d\n", arid); } } freearr(residual_array,0); }
int main(int argc, char **argv) { char *dbin; /* Input db name */ char *dbout; /* output db name */ Dbptr db; /* input db pointer */ Dbptr dbo; /* base output db pointer */ Dbptr dbv; /* set to view formed by join */ char *pfin=NULL; /* input parameter file */ char *sift_exp; /* sift expression for subset */ int sift = 0; /* default is no sift. */ Tbl *sortkeys; Tbl *joinkey1, *joinkey2; /*Pointers to views returned by dbgroup (keyed to origin and event respectively */ Dbptr dborigin_group; Tbl *origin_group; /* relation keys used in grouping*/ int nevents; /* db row variables */ int rows_in_view; int evid,orid,prefor; int nrows, nrows_raw; int useold=0; Pf *pf; Tbl *ta,*tu; Tbl *reason_converged, *residual; Location_options o; Arr *arr_phase; int i; Tbl *converge_history; char *line; Hypocenter h0; Hypocenter *hypos; int niterations; char *vmodel; int ret_code; /* ggnloc return code */ double **C; /* covariance matrix*/ float emodel[4]; /* entries for S-P feature */ int nbcs; Arr *badclocks; /* need global setting of this to handle fixed depth solutions*/ int global_fix_depth; C=dmatrix(0,3,0,3); if(argc < 3) usage(); dbin = argv[1]; dbout = argv[2]; for(i=3;i<argc;++i) { if(!strcmp(argv[i],"-pf")) { ++i; if(i>=argc) usage(); pfin = argv[i]; } else if(!strcmp(argv[i],"-sift")) { ++i; if(i>=argc) usage(); sift_exp = argv[i]; sift = 1; } else if(!strcmp(argv[i],"-useold")) useold = 1; else usage(); } /* set default this way*/ if(pfin == NULL) pfin = strdup("relocate"); /* Initialize the error log and write a version notice */ elog_init (argc, argv) ; cbanner("Version $Revision$ $Date$\n", "relocate inputdb outputdb [-pf pf -sift expression -useold]\n", "Gary Pavlis", "Indiana University", "*****@*****.**"); /* Alway join assoc, arrival, and site. We join site to make sure station table is properly dynamic to account for time changes. With this setup, the stations can even move around and this should still work.*/ if(dbopen(dbin,"r",&db) == dbINVALID) die(1,"Unable to open input database %s\n",dbin); if(dbopen(dbout,"r+",&dbo) == dbINVALID) die(1,"Unable to open output database %s\n",dbout); dbv = dbjoin ( dblookup(db,0,"event",0,0), dblookup(db,0,"origin",0,0), 0,0,0,0,0); if(dbv.table == dbINVALID) die(1,"event->origin join failed\n"); dbv = dbjoin ( dbv, dblookup(db,0,"assoc",0,0), 0,0,0,0,0); if(dbv.table == dbINVALID) die(1,"event->origin->assoc join failed\n"); dbv = dbjoin ( dbv, dblookup(db,0,"arrival",0,0), 0,0,0,0,0); if(dbv.table == dbINVALID) die(1,"event->origin->assoc->arrival join failed\n"); /* We will explicitly set the keys for this join because it was found to fail sometimes */ joinkey1 = newtbl(0); joinkey2 = newtbl(0); pushtbl(joinkey1,"arrival.sta"); pushtbl(joinkey1,"arrival.time"); pushtbl(joinkey2,"sta"); pushtbl(joinkey2,"ondate::offdate"); dbv = dbjoin ( dbv, dblookup(db,0,"site",0,0), &joinkey1,&joinkey2,0,0,0); if(dbv.table == dbINVALID) die(1,"event->origin->assoc->arrival->site join failed\n"); /* Subset using sift_key if requested */ if(sift) { dbv = dbsubset(dbv,sift_exp,0); if(dbv.record == dbINVALID) die(1,"dbsubset of %s with expression %s failed\n", dbin, sift_exp); } /* This keeps only the prefered origin records intact */ dbv = dbsubset(dbv,"orid == prefor", 0); if(dbv.record == dbINVALID) die(1,"Subset to preferred origin records failed\n"); /* First we have to run a unique key sort in the following order to remove redundant picks made on multiple channels. We will issue a warning if the record count changes. */ dbquery(dbv, dbRECORD_COUNT, &nrows_raw); sortkeys = newtbl(0); pushtbl(sortkeys,"evid"); pushtbl(sortkeys,"sta"); pushtbl(sortkeys,"phase"); dbv = dbsort(dbv,sortkeys,UNIQUE,0); dbquery(dbv, dbRECORD_COUNT, &nrows); if(nrows != nrows_raw) complain(0,"Input database has duplicate picks of one or more phases on multiple channels\n\ Which picks will be used here is unpredictable\n\ %d total picks, %d unique\nContinuing\n", nrows_raw, nrows); /* This sort is the required one for the grouping that follows*/ sortkeys = newtbl(3); pushtbl(sortkeys,"evid"); pushtbl(sortkeys,"orid"); pushtbl(sortkeys,"time"); dbv = dbsort(dbv,sortkeys,0,0); if(dbv.record == dbINVALID) die(1,"dbsort on evid,orig,time failed\n"); /* Set up grouping by events */ origin_group = newtbl(0); pushtbl(origin_group, "evid"); dborigin_group = dbgroup(dbv, origin_group, "origin_group",1); if(dborigin_group.record == dbINVALID) die(1,"dbgroup by origin failed\n"); dbquery(dborigin_group,dbRECORD_COUNT,&nevents); elog_notify(0,"Attempting to relocate %d events in subsetted database\n", nevents); /* DB is now set up correctly, now we turn to the parameter files */ i = pfread(pfin,&pf); if(i != 0) die(1,"Pfread error\n"); o = parse_options_pf (pf); global_fix_depth=o.fix[2]; arr_phase = parse_phase_parameter_file(pf); vmodel = pfget_string(pf,"velocity_model_name"); /* set up minus phase for bad clock problems */ badclocks = newarr(0); if(db_badclock_definition(db,pf,badclocks)) elog_complain(0,"Warning: problems in database definitions of bad clock time periods\n"); pfget_badclocks(pf,badclocks); nbcs = cntarr(badclocks); if(nbcs>0) fprintf(stdout,"relocate: bad clock feature enabled\n\n"); /* Change by JN to output evid and orid. */ /* fprintf(stdout,"lat lon depth time rms wrms interquartile ndata ndgf iterations\n"); */ fprintf(stdout,"evid orid lat lon depth time rms wrms interquartile ndata ndgf iterations\n"); /* Main loop. We utilize the group views and loop through by events */ for(dborigin_group.record=0; dborigin_group.record< nevents;++dborigin_group.record) { Dbptr db_bundle; /* db pointer returned from bundle field of dborigin_group for current event */ Arr *station_table; Arr *array_table; int is, ie; int orid; /* orid assigned relocated event in output db */ if(dbgetv(dborigin_group,0,"evid", &evid, "bundle", &db_bundle,0) == dbINVALID) complain(1,"dbgetv error for row %d of event group\n", dborigin_group.record); dbget_range(db_bundle,&is,&ie); station_table = dbload_station_table(dbv, is,ie,pf); array_table = dbload_array_table(dbv, is,ie,pf); ta = dbload_arrival_table(dbv, is,ie,station_table, arr_phase); tu = dbload_slowness_table(dbv, is,ie,array_table, arr_phase); /* this actually sets up the minus phase feature for bad clocks*/ if(nbcs) { if(minus_phases_arrival_edit(ta,arr_phase,badclocks)) elog_complain(0,"Warning(relocate): problems in minus_phase_arrival_edit function\n"); } if(useold) { char dtype[2]; h0 = db_load_initial(dbv,is); /* keep fixed depth if done before. setting dbv.record here is a bit of a potential maintenance problem */ dbv.record=is; dbgetv(dbv,0,"dtype",dtype,0); if( (!strcmp(dtype,"g")) || (!strcmp(dtype,"r")) ) o.fix[2]=1; } else h0 = initial_locate(ta, tu, o, pf); ret_code = ggnloc(h0,ta,tu,o, &converge_history,&reason_converged,&residual); if(ret_code < 0) { complain(1,"ggnloc failed to produce a solution\n"); } else { if(ret_code > 0) complain(1,"%d travel time calculator failures in ggnloc\nSolution ok\n", ret_code); niterations = maxtbl(converge_history); hypos = (Hypocenter *)gettbl(converge_history, niterations-1); predicted_errors(*hypos,ta,tu,o,C,emodel); /* Next 3 calls changed by JN to output evid, orid and number_data */ orid = save_origin(dbv,is,ie,o.fix[3],*hypos,dbo); evid = save_event(dbv,is,ie,orid,dbo); fprintf(stdout,"%d %d %lf %lf %lf %lf %g %g %g %d %d %d\n", evid, orid, hypos->lat,hypos->lon,hypos->z,hypos->time, hypos->rms_raw, hypos->rms_weighted, hypos->interquartile, hypos->number_data, hypos->degrees_of_freedom, niterations); save_origerr(orid,*hypos,C,dbo); save_assoc(dbv,is,ie,orid,vmodel,residual,*hypos,dbo); /* These save genloc add on tables */ save_emodel(orid,emodel,dbo); save_predarr(dbo,ta,tu,*hypos,orid,vmodel); } o.fix[2]=global_fix_depth; if(maxtbl(converge_history)>0)freetbl(converge_history,free); if(maxtbl(reason_converged)>0)freetbl(reason_converged,free); if(maxtbl(residual)>0)freetbl(residual,free); destroy_data_tables(tu, ta); destroy_network_geometry_tables(station_table,array_table); } return(0); }
int grdb_sc_loadcss (Dbptr dbin, char *net_expr, char *sta_expr, char *chan_expr, double tstart, double tend, int coords, int ir, int orient, Dbptr *dbscgr, Dbptr *dbsc) { Dbptr dbout, db, dbout2; char string[1024]; char string2[1024]; char sta_wfdisc[32], chan_wfdisc[32]; int i, j, n, sensor=0, ok; Tbl *pat1, *pat2; Tbl *sortfields, *groupfields; FILE *file; Response *resp; int is_view=0; Dbptr db_to_clear; /* Subset the wfdisc by station-channel-time sifters. */ dbout = dblookup (dbin, 0, "wfdisc", 0, 0); strcpy (string, ""); if (sta_expr) { strcpy (string, "( "); sprintf (string2, "sta =~ /%s/", sta_expr); strcat (string, string2); } if (chan_expr) { if (string[0]) strcat (string, " && "); else strcpy (string, "( "); sprintf (string2, "chan =~ /%s/", chan_expr); strcat (string, string2); } if (tstart != 0.0 || tend != 0.0) { if (string[0]) strcat (string, " && "); else strcpy (string, "( "); sprintf (string2, "(time < %.5f && endtime > %.5f)", tend, tstart); strcat (string, string2); } if (string[0]) { strcat (string, " )"); dbout = dbsubset (dbout, string, 0); is_view=1; } dbquery (dbout, dbRECORD_COUNT, &n); if (n < 1) { register_error (0, "grdb_sc_loadcss: No wfdisc rows to process.\n"); return (-1); } /* Make the necessary joins and check for completeness. */ if (coords) { db = dblookup (dbin, 0, "site", 0, 0); if(is_view)db_to_clear=dbout; dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0); if(is_view) dbfree(db_to_clear); is_view=1; dbquery (dbout, dbRECORD_COUNT, &n); if (n < 1) { register_error (0, "grdb_sc_loadcss: No data rows to process.\n"); return (-1); } for (dbout.record=0; dbout.record<n; dbout.record++) { if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc, "wfdisc.chan", chan_wfdisc, "site.sta", string, 0) == dbINVALID) { register_error (0, "grdb_sc_loadcss: dbgetv() error while checking site.\n"); return (-1); } if (coords > 1 && strcmp(string, sta_wfdisc)) { register_error (0, "grdb_sc_loadcss: Cannot find site parameters for %s %s.\n", sta_wfdisc, chan_wfdisc); return (-1); } } } if (ir) { db = dblookup (dbin, 0, "sensor", 0, 0); if(is_view)db_to_clear=dbout; dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0); if(is_view) dbfree(db_to_clear); is_view=1; dbquery (dbout, dbRECORD_COUNT, &n); if (n < 1) { register_error (0, "grdb_sc_loadcss: No data rows to process.\n"); return (-1); } for (dbout.record=0; dbout.record<n; dbout.record++) { if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc, "wfdisc.chan", chan_wfdisc, "sensor.sta", string, 0) == dbINVALID) { register_error (0, "grdb_sc_loadcss: dbgetv() error while checking sensor.\n"); return (-1); } if (ir > 1 && strcmp(string, sta_wfdisc)) { register_error (0, "grdb_sc_loadcss: Cannot find sensor parameters for %s %s.\n", sta_wfdisc, chan_wfdisc); return (-1); } } sensor = 1; if(is_view)db_to_clear=dbout; db = dblookup (dbin, 0, "instrument", 0, 0); dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0); if(is_view) dbfree(db_to_clear); is_view=1; dbquery (dbout, dbRECORD_COUNT, &n); if (n < 1) { register_error (0, "grdb_sc_loadcss: No data rows to process.\n"); return (-1); } for (dbout.record=0; dbout.record<n; dbout.record++) { if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc, "wfdisc.chan", chan_wfdisc, "sensor.inid", &j, "instrument.insname", string2, "instrument.inid", &i, 0) == dbINVALID) { register_error (0, "grdb_sc_loadcss: dbgetv() error while checking instrument.\n"); return (-1); } if (ir > 1 && (i != j)) { register_error (0, "grdb_sc_loadcss: Cannot find instrument parameters for %s %s.\n", sta_wfdisc, chan_wfdisc); return (-1); } if (i >= 0) { if (resp_arr == NULL) { resp_arr = newarr (0); if (resp_arr == NULL) { register_error (0, "grdb_sc_loadcss: newarr() error.\n"); return (-1); } } dbextfile (dbout, "instrument", string); resp = (Response *) getarr (resp_arr, string); if (resp == NULL) { file = fopen (string, "r"); if (file == NULL) { if (ir > 1) { register_error (1, "grdb_sc_loadcss: fopen('%s') error.\n", string); return (-1); } } else { if (read_response (file, &resp)) { register_error (0, "grdb_sc_loadcss: read_response('%s') error.\n", string); return (-1); } fclose (file); resp->insname = strdup(string2); } setarr (resp_arr, string, resp); } } } } if (orient) { ok = 1; if(is_view)db_to_clear=dbout; db = dblookup (dbin, 0, "sitechan", 0, 0); dbout2 = dbjoin (dbout, db, 0, 0, 1, 0, 0); is_view=1; dbquery (dbout2, dbRECORD_COUNT, &n); if (n < 1) { ok = 0; } else { for (dbout2.record=0; dbout2.record<n; dbout2.record++) { dbgetv (dbout2, 0, "wfdisc.sta", sta_wfdisc, "wfdisc.chan", chan_wfdisc, "sitechan.sta", string, 0); if (strcmp(string, sta_wfdisc)) { ok = 0; break; } } } if (ok) { dbout = dbout2; if(is_view) dbfree(db_to_clear); } else { if (!sensor) { db = dblookup (dbin, 0, "sensor", 0, 0); if(is_view)db_to_clear=dbout; dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0); if(is_view) { dbfree(dbout2); dbfree(db_to_clear); } is_view=1; dbquery (dbout, dbRECORD_COUNT, &n); if (n < 1) { register_error (0, "grdb_sc_loadcss: No data rows to process.\n"); return (-1); } for (dbout.record=0; dbout.record<n; dbout.record++) { if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc, "wfdisc.chan", chan_wfdisc, "sensor.sta", string, 0) == dbINVALID) { register_error (0, "grdb_sc_loadcss: dbgetv() error while checking sensor.\n"); return (-1); } if (orient > 1 && strcmp(string, sta_wfdisc)) { register_error (0, "grdb_sc_loadcss: Cannot find sensor parameters for %s %s.\n", sta_wfdisc, chan_wfdisc); return (-1); } } } db = dblookup (dbin, 0, "sitechan", 0, 0); pat1 = newtbl(1); if (pat1 == NULL) { register_error (0, "grdb_sc_loadcss: newtbl() error.\n"); return (-1); } pat2 = newtbl(1); if (pat2 == NULL) { register_error (0, "grdb_sc_loadcss: newtbl() error.\n"); return (-1); } if(is_view)db_to_clear=dbout; settbl (pat1, 0, strdup("sensor.chanid")); settbl (pat2, 0, strdup("sitechan.chanid")); dbout = dbjoin (dbout, db, &pat1, &pat2, 1, 0, 0); if(is_view) dbfree(db_to_clear); is_view=1; freetbl (pat1, free); freetbl (pat2, free); dbquery (dbout, dbRECORD_COUNT, &n); if (n < 1) { register_error (0, "grdb_sc_loadcss: No data rows to process.\n"); return (-1); } else { for (dbout.record=0; dbout.record<n; dbout.record++) { if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc, "wfdisc.chan", chan_wfdisc, "sitechan.sta", string, 0) == dbINVALID) { register_error (0, "grdb_sc_loadcss: dbgetv() error while checking sitechan.\n"); return (-1); } if (orient > 1 && strcmp(string, sta_wfdisc)) { register_error (0, "grdb_sc_loadcss: Cannot find sitechan parameters for %s %s.\n", sta_wfdisc, chan_wfdisc); return (-1); } } } } } /* Sort and group the output view. */ if(is_view)db_to_clear=dbout; sortfields = newtbl (3); if (sortfields == NULL) { register_error (0, "grdb_sc_loadcss: newtbl() error.\n"); return (-1); } settbl (sortfields, 0, strdup("wfdisc.sta")); settbl (sortfields, 1, strdup("wfdisc.chan")); settbl (sortfields, 2, strdup("wfdisc.time")); *dbsc = dbsort (dbout, sortfields, 0, 0); if(is_view) dbfree(db_to_clear); groupfields = newtbl (2); if (groupfields == NULL) { register_error (0, "grdb_sc_loadcss: newtbl() error.\n"); return (-1); } settbl (groupfields, 0, strdup("sta")); settbl (groupfields, 1, strdup("chan")); *dbscgr = dbgroup (*dbsc, groupfields, 0, 1); freetbl (sortfields, free); freetbl (groupfields, free); /* Normal exit */ return (0); }
/* This function computes theoretical arrival times and a slowness vector (at the reference station for an array) based on a model and method defined in a parameter file and using the generic travel time interface of datascope/antelope. Arguments: ///inputs//// stations - Associative array of MWstation objects used in multiwavelet programs refsta - name of reference station to use. The slowness vector is computed based on a source location accessed through the db pointer (see below) and the location of the reference station. If the refsta is not found in the stations array the first element of the sorted list of stations will be used in an attempt to recover. For most arrays this would be a minor error. phase - name of seismic phase to compute theoretical times and slowness vector for. db - This db pointer MUST point to a single row of a db view with the origin table joined as part of the view. The hypocenter information is read with dbgetv passing this db pointer directly. pf - parameter space pointer. We search for model and method fields from pf to get the interface right. ///outputs/// times - associative array keyed by station name of theoretical arrival times (stored as double * s). If there are problems computing any travel times they will be absent from this array. When this array is used, be aware you can't assume all the times are filled. slow - theoretical slowness vector. If the slowness vector calculation fails this is set to 0 and the refsta field is set to "BAD". This allows the use of the slowness vector without errors in a less than ideal way. The BAD condition should be trapped. Return codes: 0 = normal return, no problems > 0 = count of travel time failures < 0 = nothing was computed. Both slowness and times should be assumed invalid. Author: Gary Pavlis Written: December 2000 */ static Hook *hook=0; /*Used by ttcalc */ int MWget_model_tt_slow(Arr *stations, char *refsta, char *phase, Dbptr db, Pf *pf, Arr **times, MWSlowness_vector *slow) { Tbl *t; /* used to hold keys with keysarr */ char *key; /* key returned from Tbl *t */ int i; MWstation *s, *s0; char *model; char *method; TTGeometry geometry; TTTime *atime; TTSlow *u0,*u; Tbl *treturn=NULL,*ureturn=NULL; int error_count=0; double *twork; s0 = (MWstation *)getarr(stations,refsta); if(s0 == NULL) elog_complain(0,"MWget_model_tt_slow: cannot find reference station %s\nWill arbitarily pick first station found as refererence for computing model based time and slowness\n",refsta); if(dbgetv(db,0,"origin.lat",&(geometry.source.lat), "origin.lon",&(geometry.source.lon), "origin.depth",&(geometry.source.z), "origin.time",&(geometry.source.time),0) == dbINVALID) { elog_complain(0,"MWget_model_tt_slow: dbgetv error reading origin data\nCannot compute theoretical arrival times and slowness\n"); return(-1); } model = pfget_string(pf,"TTmodel"); method = pfget_string(pf,"TTmethod"); if( (model == NULL) || (method == NULL) ) { elog_complain(0,"MWget_model_tt_slow: TTmodel or TTmethod missing from parameter file\nCannot compute theoretical travel times and slowness vector\n"); return(-1); } t = keysarr(stations); if(maxtbl(t)<=0) { elog_complain(0,"MWget_model_tt_slow: no data to process\n"); return(-1); } /* recover from reference station error */ if(s0==NULL) { key = gettbl(t,0); elog_log(0,"Setting reference station to %s for travel time computation\n", key); } /* We now compute the slowness vector estimated for the reference station location at 0 elevation. */ strcpy(geometry.receiver.name,s0->sta); geometry.receiver.lat = s0->lat; geometry.receiver.lon = s0->lon; geometry.receiver.z = 0.0; if(slow->refsta == NULL) slow->refsta = strdup(refsta); if(ucalc(method,model,phase,0,&geometry,&ureturn,&hook)) { elog_complain(0,"MWget_model_tt_slow: slowness vector calculation failed for reference station %s\nSetting model slowness vector to zero and attempting to continue.\n", s0->sta); slow->ux = 0.0; slow->uy = 0.0; } else { u0 = (TTSlow *)gettbl(ureturn,0); slow->ux = u0->ux; slow->uy = u0->uy; } /* If the output times array is not empty we have to free it up and start fresh. Otherwise we will have a memory leak or access old values stored there. This probably should be handled externally, but better to be redundant.*/ if(*times != NULL) freearr(*times,free); *times = newarr(0); /* Look through the station list */ for(i=0;i<maxtbl(t);i++) { double estatic; key = gettbl(t,i); s = (MWstation *)getarr(stations,key); strcpy(geometry.receiver.name,s->sta); geometry.receiver.lat = s->lat; geometry.receiver.lon = s->lon; geometry.receiver.z = 0.0; if(ttcalc(method,model,phase,0,&geometry,&treturn,&hook)) { elog_complain(0,"MWget_model_tt_slow: Travel time computation failed computing travel time for station %s\nCannot compute residuals\n", s->sta); ++error_count; } else { atime = (TTTime *)gettbl(treturn,0); estatic = compute_elevation_static(s,*slow,0.0,phase); allot(double *,twork,1); *twork = geometry.source.time + (atime->value) + estatic; setarr(*times,key,twork); } } freetbl(ureturn,0); freetbl(treturn,0); return(error_count); }
void save_assoc(Tbl *ta, Tbl *tu, int orid, char *vmodel, Hypocenter hypo, Dbptr db, int orb) { double delta; double seaz; double esaz; double azres; double slores; Arr *u_arr; char key_arid[20]; Tbl *udregs; int i,n; double ux, uy, azimuth; double duphi; Arrival *a; Slowness_vector *u; /* We build an associative array keyed to arid for all the slowness vector measurements. Then in the loop below we can efficiently find any slowness vectors associated with the same arid as an Arrival. The overhead in this is significant, but it makes it completely general and open ended. */ n = maxtbl(tu); u_arr = newarr(0); for(i=0;i<n;i++) { Slowness_vector *utmp; utmp = (Slowness_vector *)gettbl(tu,i); sprintf(key_arid,"%d",utmp->arid); setarr(u_arr,key_arid,utmp); } db = dblookup(db,0,"assoc",0,0); db.record = dbSCRATCH; n=maxtbl(ta); for(i=0;i<n;i++) { a=(Arrival*)gettbl(ta,i); dist(rad(hypo.lat),rad(hypo.lon), rad(a->sta->lat),rad(a->sta->lon),&delta,&esaz); dist(rad(a->sta->lat),rad(a->sta->lon), rad(hypo.lat),rad(hypo.lon),&delta,&seaz); sprintf(key_arid,"%d",a->arid); u = (Slowness_vector *) getarr(u_arr,key_arid); if(u == NULL) { if(dbputv(db,0, "orid",orid, "arid",a->arid, "sta",a->sta->name, "phase",a->phase->name, "delta",deg(delta), "seaz",deg(seaz), "esaz",deg(esaz), "timeres",(double)a->res.raw_residual, "timedef","d", "vmodel",vmodel, "wgt",(double)a->res.residual_weight, 0)<0) { elog_complain(0, "Can't add assoc record for station %s arid = %d orid = %d to working db scratch record\nRecord skipped and not saved anywhere\n", a->sta->name,a->arid,orid); continue; } } else { slores = deg2km(sqrt(sqr(u->xres.raw_residual) + sqr(u->yres.raw_residual))); azimuth = atan2 ( u->uy, u->ux ) ; duphi = (u->ux*cos(azimuth) - u->uy*sin(azimuth)) / sqrt(sqr(u->ux)+ sqr(u->uy)) ; azres = deg(duphi); if(dbputv(db,"assoc", "orid",orid, "arid",a->arid, "sta",a->sta->name, "phase",a->phase->name, "delta",deg(delta), "seaz",deg(seaz), "esaz",deg(esaz), "timeres",(double)a->res.raw_residual, "timedef","d", "vmodel",vmodel, "slores",slores, "slodef","d", "azres",azres, "azdef","d", "wgt",(double)a->res.residual_weight, 0)<0) { elog_complain(0, "Can't add assoc record for station %s arid = %d orid = %d to working db scratch record\nRecord skipped and not saved anywhere\n", a->sta->name,a->arid,orid); delarr(u_arr,key_arid); continue; } /* We delete this entry from u_arr, then we can scan below for the dregs easily */ delarr(u_arr,key_arid); } if(save_dbrecord(db,orb)) elog_complain(0,"Error saving assoc record for arid %d\n", a->arid); } /* Since it is possible that slowness vectors can be measured with no arrival time, we need to take care of that possibility. We do that by checking for dregs in u_arr not removed with delarr calls above */ udregs = keysarr(u_arr); n = maxtbl(udregs); for(i=0;i<n;i++) { char *key; key = gettbl(udregs,i); u = (Slowness_vector *) getarr(u_arr,key); dist(rad(hypo.lat),rad(hypo.lon), rad(u->array->lat),rad(u->array->lon),&delta,&esaz); dist(rad(u->array->lat),rad(u->array->lon), rad(hypo.lat),rad(hypo.lon),&delta,&seaz); slores = deg2km(sqrt(sqr(u->xres.raw_residual) + sqr(u->yres.raw_residual))); azimuth = atan2 ( u->uy, u->ux ) ; duphi = (u->ux*cos(azimuth) - u->uy*sin(azimuth)) / sqrt(sqr(u->ux)+ sqr(u->uy)) ; azres = deg(duphi); /* The residual weight extraction from the ux component is not ideal here because it could be wrong. It is unavoidable due to polar-cartesian conversion */ if(dbputv(db,"assoc", "orid",orid, "arid",u->arid, "sta",u->array->name, "phase",u->phase->name, "delta",deg(delta), "seaz",deg(seaz), "esaz",deg(esaz), "timedef","n", "vmodel",vmodel, "slores",slores, "slodef","d", "azres",azres, "azdef","d", "wgt",(double)u->xres.residual_weight, 0)<0) { elog_complain(0,"Can't add assoc record for array slowness vector with %s arid = %d and orid = %d to working db scratch record\nNothing saved\n", u->array->name,u->arid,orid); continue; } if(save_dbrecord(db,orb)) elog_complain(0,"Error saving assoc record for arid %d\n", u->arid); } /* We must not use regular free here, or later we could try to free the same area twice. That is, u_tmp contains keyed version of the pointers stored in tu. This releases only the Arr structures, but leaves the pointers to be freed later. I've never seen a better example of the need for a decent garbage collection system. */ freetbl(udregs,free_nothing); freearr(u_arr,free_nothing); }
/* Modified Dec. 2006: added two new Tbls for resid and slowness to compute residuals only=tapro and tupro. */ int load_observations ( Pf *pf, Dbptr db, Arr *arr_phase, Arr **stationsp, Arr **arraysp, Tbl **tap, Tbl **tup , Tbl **tapro, Tbl **tupro) { Station *station ; Seismic_Array *array ; Arrival *a ; Tbl *ta, *tu ,*taro, *turo; Dbptr dbarr, dbsite ; static Hook *hook = 0 ; static Tbl *matching ; Tbl *arrival_tbl ; Arr *stations ; Arr *arrays ; int i, narr ; char sta[32], iphase[32], timedef[16], azdef[16], slodef[16] ; double time, deltim, azimuth, delaz, slow, delslo ; int arid ; Phase_handle *phase ; Slowness_vector *u ; int nobs = 0 ; if ( *stationsp == 0 ) { *stationsp = newarr(0) ; *arraysp = newarr(0) ; } stations = *stationsp ; arrays = *arraysp ; ta = *tap = newtbl(0) ; tu = *tup = newtbl(0) ; taro = *tapro = newtbl(0) ; turo = *tupro = newtbl(0) ; dbarr = dblookup ( db, 0, "arrival", 0, "dbSCRATCH" ) ; dbsite = dblookup ( db, 0, "site", 0, 0 ) ; arrival_tbl = pfget_tbl(pf, "arrival_table"); narr = maxtbl(arrival_tbl); for (i = 0; i < narr; i++) { sscanf(gettbl(arrival_tbl, i), "%d %s %s %lf %lf %s %lf %lf %s %lf %lf %s", &arid, sta, iphase, &time, &deltim, timedef, &azimuth, &delaz, azdef, &slow, &delslo, slodef ); if ( (station = getarr ( stations, sta ) ) == 0 ) { dbputv ( dbarr, 0, "sta", sta, "time", time, NULL ) ; dbmatches ( dbarr, dbsite, 0, 0, &hook, &matching ) ; if ( maxtbl(matching) < 1 ) { char *t ; complain ( 0, "No site table record for %s at time %s\n", sta, t=strtime(time)); free(t) ; continue ; } dbsite.record = (long) gettbl(matching, 0) ; freetbl(matching,0) ; allot ( Station *, station, 1 ) ; allot ( Seismic_Array *, array, 1 ) ; dbgetv ( dbsite, 0, "sta", station->name, "lat", &station->lat, "lon", &station->lon, "elev", &station->elev, NULL ) ; dbgetv ( dbsite, 0, "sta", array->name, "lat", &array->lat, "lon", &array->lon, "elev", &array->elev, NULL ) ; setarr (stations, sta, station ) ; setarr (arrays, sta, array ) ; } else {
/*This is an important function that sets the set of base station corrections used as the bias term in pmel. These base station corrections are computed as the difference between travel times computed by a 3D calculator (This program actually has no concept of this directly. It just uses the 3D model as a reference.) and a reference model (presumably generally a 1D model like iasp91, but it could itself be 3D really). Note that if the 3D model has any station corrections set they will be applied. For the reference model (1D) the station corrections are set by this function. This allows testing or application with a global set of station corrections used as the 3D equivalent, but allowing the results to be space variable when used with dbpmel. i.e. you can, if desired, use the same travel time calculator for the 1D and 3D case, but if station corrections are defined for the 3D handle they will be used as a global bias term. Similarly, if this same process is done with no station corrections one can produce a "unbiased estimate" meaning the bias term is always forced to 0 everywhere. Experience has shown that although this might be conceptually appealing it generally is a bad idea unless the reference model is very good to start with. Arguments: pha - associative array of phase handles for 1D reference model calculator (station correction of these handles are set here). pha3D - same as pha, but for the 3D (bias) model calculator sa - associative array of Station objects with station location information (keyed by sta name). hc - hypocentroid location. Returns: 0 - normal, aok > 0 - count of failures in computing travel times < 0 - total failure */ int initialize_station_corrections(Arr *pha,Arr *pha3D, Arr *sa,Hypocenter *hc) { int i,j; Phase_handle *p,*p3D; Tbl *keys; char *phase; Station *s; Tbl *stakeys; char *sta; int nsc_fail=0; Ray_Endpoints x; Travel_Time_Function_Output t,t3D; double *sc,*sc3D; keys = keysarr(pha); stakeys = keysarr(sa); x.slat = hc->lat; x.slon = hc->lon; x.sz = hc->z; for(i=0;i<maxtbl(keys);++i) { phase = gettbl(keys,i); p = (Phase_handle *)getarr(pha,phase); p3D = (Phase_handle *)getarr(pha3D,phase); if(pha3D == NULL) { elog_notify(0,"No handle for 3d (bias correction) for phase %s\nBias contribution set to 0 for this phase\n", phase); nsc_fail += cntarr(sa); /* Emptying the arr is a simple way to create the equivalent of all 0s*/ if(cntarr(p->time_station_corrections)>0) { freearr(p->time_station_corrections,free); p->time_station_corrections=newarr(0); } continue; } for(j=0;j<maxtbl(stakeys);++j) { sta = gettbl(stakeys,j); s = (Station *)getarr(sa,sta); x.sta = s->name; x.rlat = s->lat; x.rlon = s->lon; x.rz = -(s->elev); /* Get a pointer to hold the new station correction. If it doesn't exist yet, create it and enter it into the associative array. Note because these are direct pointers we don't have set the entry in the arr below*/ sc = (double *)getarr(p->time_station_corrections,sta); if(sc == NULL) { allot(double *,sc,1); setarr(p->time_station_corrections,sta,sc); } t3D = p3D->ttcalc(x,phase,RESIDUALS_ONLY); t = p->ttcalc(x,phase,RESIDUALS_ONLY); if( (t.time == TIME_INVALID) || (t3D.time == TIME_INVALID) ) { elog_notify(0,"Travel time failure for phase %s computing reference corrections for station %s\nCorrection set to 0.0\n", phase,sta); *sc = 0.0; ++nsc_fail; } else { *sc = t3D.time - t.time; sc3D = (double *) getarr(p3D->time_station_corrections,sta); if(sc3D != NULL) *sc += *sc3D; } } }
void initpf( char *pf ) { double epoch, sec; Pf *Param; Tbl *Inputs; Arr *pfarr; DIR *dirp; struct dirent *direntp; char *istr; char *path, exten[132], name[132], *pfile; int getone = 0; int yr, day, hr, min; int i, n, ninputs; if( (pfile = (char *) malloc(256)) == NULL) elog_die( 1, "initpf(): malloc error\n"); /* Get today's time */ if( pf == NULL ) { epoch = now(); e2h(epoch, &yr, &day, &hr, &min, &sec); /* Get List of Parameter Files */ if( (path = getenv("DASPF_PATH") ) == NULL || (int) strlen(path) <= 0 ) { DASPF = "pkt"; } else { sprintf( pfile, "%04d%03d%02d%02d\0", yr, day, hr, min); dirp = opendir(path); if(dirp == NULL) elog_die(1, "initIP():Can't open %s directory.\n", path); pfarr = newarr( 0 ); while ( (direntp = readdir(dirp)) != NULL ) { istr = direntp->d_name; fexten( istr, exten); if( strncmp( exten, "pf", strlen("pf")) == 0) setarr( pfarr, direntp->d_name, "Y" ); } /* Get the most recent PF name */ Inputs = keysarr( pfarr ); ninputs = maxtbl( Inputs ); for( i = 0; i < ninputs; i++ ) { istr = ( char *) gettbl( Inputs, i ); if( strcmp( istr, pfile ) == 0 ) { sprintf( pfile, "%s/%s\0", path, istr); getone = 1; break; } else if( strcmp( istr, pfile ) > 0 ) { if( i == 0 ) istr = ( char *) gettbl( Inputs, (0)); else istr = ( char *) gettbl( Inputs, (i -1)); strncpy( name, istr, strlen(istr)); name[strlen(istr)-strlen(".pf")] = '\0'; for(n = 0; n < (int) strlen(name); n++) if(!isdigit(name[n])) break; if( n == (int) strlen(name)) sprintf( pfile, "%s/%s\0",path, istr); else sprintf( pfile, "pkt.pf" ); getone = 1; break; } } /* end for */ if( !getone ) { istr = ( char *) gettbl( Inputs, (ninputs -1)); sprintf( pfile, "%s/%s\0",path, istr); } /* Read configuration file */ pfile[strlen(pfile)-strlen(".pf")] = '\0'; DASPF = pfile; freearr( pfarr, 0 ); closedir( dirp ); } } else { /* Read configuration file */ fexten( pf, exten); if( strncmp( exten, "pf", strlen("pf")) == 0) pf[strlen(pf) - strlen(".pf")] = '\0'; DASPF = pf; } }
/* Init function for uniform table. phase = phase name to tag this table with pf = input parameter file object to be parsed. The following keys are required to be found in pf: int: nx, nz scalar double: dx, dz &Tbl: uniform_grid_time_slowness_table The later contains the actual tables. They are ascii tables make up of nx*nz lines (x varies most rapidly) of the following format: time, slowness, slowness derivative wrt distance, branch The "branch" variable is a character key defined in location.h Optional parameters with defaults: scalar double: x0, y0 coordinates of first point in table (default = (0,0)) strings: Notice that this routine requires mixed units. dx, dz, x0, and y0 must all be specified in degrees. Everything else has units derived from km and s. That is, time is is in seconds, slowness (p) is assumed to be in s/km, and dpdx (slowness derivative) is (s/km)/km. This was done because the input tables are ascii, and these numbers are scaled to units that make sense to most of us. This format is connected to a related program called taup_convert that writes ttables in this format using the tau-p library. Returns 0 if no problems are encountered. REturns 1 if a serious error occurred that rendered setup impossible for this phase. In the later case, register_error is always called and should be handled by calling program. There are some fatal errors that lead to die being called here from things like malloc failures. */ int uniform_table_interpolate_init(char *phase, Pf *pf) { XZ_table_uniform *ttable, *utable; Tbl *t; /* pfget_tbl return to hold strings of prototables stored in the pf structure. */ int i,j,k; GenlocVerbose = verbose_exists() ; if(time_tables_uniform==NULL) time_tables_uniform = newarr(0); if(slow_tables_uniform==NULL) slow_tables_uniform = newarr(0); ttable = (XZ_table_uniform *)malloc(sizeof(XZ_table_uniform)); utable = (XZ_table_uniform *)malloc(sizeof(XZ_table_uniform)); if( (ttable == NULL) || (utable == NULL) ) elog_die(1,"Can't alloc memory in uniform_table_interpolate_init\n"); /* This version requires t and u tables to be parallel. This restriction would not be necessary, but it simplifies things greatly and we only have to store times in the values matrix and the slowness values in the slopes matrix. */ ttable->nx = pfget_int(pf, "nx"); ttable->nz = pfget_int(pf, "nz"); utable->nx = ttable->nx; utable->nz = ttable->nz; ttable->dx = pfget_double(pf, "dx"); ttable->dz = pfget_double(pf, "dz"); utable->dx = ttable->dx; utable->dz = ttable->dz; /* These parameters default to 0 */ if(pfget_string(pf,"x0")==NULL) { ttable->x0 = 0.0; utable->x0 = 0.0; } else { ttable->x0 = pfget_double(pf,"x0"); utable->x0 = ttable->x0; } if(pfget_string(pf,"z0")==NULL) { ttable->z0 = 0.0; utable->z0 = 0.0; } else { ttable->z0 = pfget_double(pf,"z0"); utable->z0 = ttable->z0; } /* IMPORTANT WARNING: notice I only alloc one space for the slowness values array, although it gets placed in two different places -> values section of utable and slopes section of ttable This leaves a nasty dependency if this space is to be freed, but saves a lot of memory. p.s I did the same thing with velocity, but not with the branch array (see below) */ ttable->values = dmatrix(0,(ttable->nx)-1,0,(ttable->nz)-1); if(ttable->values == NULL) elog_die(1,"Cannot alloc memory for travel time table of size %d by %d for phase %s\n", ttable->nx, ttable->nz, phase); ttable->slopes = dmatrix(0,(ttable->nx)-1,0,(ttable->nz)-1); if(ttable->slopes == NULL) elog_die(1,"Cannot alloc memory for slowness table of size %d by %d for phase %s\n", ttable->nx, ttable->nz, phase); ttable->branch = cmatrix(0,(ttable->nx)-1,0,(ttable->nz)-1); if(ttable->branch == NULL) elog_die(1,"Cannot alloc memory for time branch table for phase %s\n", phase); utable->branch = cmatrix(0,(utable->nx)-1,0,(utable->nz)-1); if(utable->branch == NULL) elog_die(1,"Cannot alloc memory for slowness branch table for phase %s\n", phase); ttable->velocity = (double *) calloc(ttable->nz,sizeof(double)); if(ttable->velocity == NULL) elog_die(1,"Cannot alloc memory for velocity model for phase %s\n", phase); utable->slopes = dmatrix(0,(utable->nx)-1,0,(utable->nz)-1); if(utable->slopes == NULL) elog_die(1,"Cannot alloc memory for dudr table of size %d by %d for phase %s\n", utable->nx, utable->nz, phase); /* here is where we set the redundant pointers */ utable->values = ttable->slopes; utable->velocity = ttable->velocity; /* Now it is time to actually parse the tables. We assume the table is entered as a pf &Tbl, and table is scanned with x varying most rapidly. (i.e. you get the tables for x=x0 first, then x=x0+dx, etc. Note we read three entries for each grid point: time, slowness, branch_code */ t = pfget_tbl(pf,"uniform_grid_time_slowness_table"); if(t == NULL) { elog_log(1,"Can't find travel time-slowness table for phase %s\n", phase); free_uniform_table(ttable, utable); return(1); } if( maxtbl(t) != ( (ttable->nx)*(ttable->nz) ) ) { elog_log(1,"Table size mismatch for phase %s\nTable should have %d rows\nFound %ld\n", phase, (ttable->nx)*(ttable->nz), maxtbl(t)); free_uniform_table(ttable, utable); return(1); } for(j=0,k=0; j<ttable->nz; ++j) { for(i=0; i<ttable->nx; ++i) { char *s; int nitems; double tt,u,dudx; char b; s = gettbl(t,k); nitems = sscanf(s,"%lf%lf%lf%1s", &tt, &u, &dudx,&b); if(nitems !=4) { elog_log(1,"Syntax error reading table for phase %s, Problem read value for i=%d, j=%d\n", phase,i,j); free_uniform_table(ttable, utable); return(1); } ttable->values[i][j] = tt; ttable->slopes[i][j] = u; utable->slopes[i][j] = dudx; ttable->branch[i][j] = b; ++k; } } /* In order to utilize a common set of interpolation routines, scan the time->branch matrix. Mark the crossover points for time as jump discontinuities for slowness (which they are) */ for(j=0; j<ttable->nz; ++j) for(i=0; i<ttable->nx; ++i) if(ttable->branch[i][j] == CROSSOVER) utable->branch[i][j] = JUMP; else utable->branch[i][j] = ttable->branch[i][j]; /* An error check is needed here so we don't have to worry about it later. Other than a blunder, this can happen if x0 is anything other than 0, so we need to watch for this. We could try to repair this automatically, but because it mostly likely indicates a serious blunder we abort */ for(j=0; j<ttable->nz; ++j) if( (utable->branch[0][j] == CROSSOVER) || (ttable->branch[0][j] == CROSSOVER) || (utable->branch[0][j] == JUMP) || (ttable->branch[0][j] == JUMP) ) { elog_log(1, "Error in travel time table for phase %s\nFirst point cannot be marked as a crossover or jump discontinuity\n",phase); free_uniform_table(ttable, utable); return(1); } /* Now we read the velocity model parameters */ t = pfget_tbl(pf,"velocities"); if((ttable->nz) != maxtbl(t)) { elog_log(1,"Error in phase parameter file. \ Mismatch between velocity entries and table entries\n\ Tables have %d depth entries, but velocity vector is of length %ld\n", ttable->nz, maxtbl(t)); free_uniform_table(ttable,utable); return(1); } for(i=0; i<maxtbl(t); ++i) { char *s; s = gettbl(t,i); sscanf(s,"%lf", &(ttable->velocity[i])); } setarr(time_tables_uniform,phase,ttable); setarr(slow_tables_uniform,phase,utable); return(0); }
int set_sinfo_limits( Arr * sinfo, orbinfo * oi, char * pkttype ) { int i, j; int size, size2; int numalerts; Arr * alert_ranges; Arr* ranges; Arr * oldval; Pf * newfieldlist; Arr * field; Pf * thresholds; Pf * thresh; double high; double low; double * val; Tbl* levels; Tbl* byfield; Tbl* fields; char* level; char * name; int priority = 0; /* Find the alert thresholds applicable to this packet type. If packet type not mentioned by name, use the default values. */ if ( !( ranges = getarr( oi->alert_ranges, pkttype) ) ) if ( !( ranges = getarr( oi->alert_ranges, "all") ) ) return 0; thresholds = pfnew( PFARR ); thresholds->value.arr = newarr( strcmp ); oldval = setarr( sinfo, THRESHOLD, thresholds ); /* if ( oldval ) freearr( oldval, recurse_free_pf ); */ /* First grab the list of alert levels for this packet type. */ levels = keysarr( ranges ); numalerts = maxtbl( levels ); for ( i =0; i < numalerts; i++ ) { level = poptbl( levels ); byfield = (Tbl*) getarr( ranges, level ); newfieldlist = create_pf ( newarr( strcmp ), PFARR ); setarr( thresholds->value.arr, level, newfieldlist ); priority = get_priority( level, oi ); /* Next, get the thresholds for this current alert level. */ size = maxtbl( byfield ); for ( j = 0; j < size; j++ ) { /* From this, examine each field. */ field = (Arr*) gettbl( byfield, j ); thresh = create_pf( newarr( strcmp ), PFARR ); setarr ( thresh->value.arr, HIGH, create_pf( strdup( getarr( field, HIGH ) ), PFSTRING) ); setarr ( thresh->value.arr, LOW, create_pf( strdup( getarr( field, LOW ) ), PFSTRING) ); setarr ( thresh->value.arr, PRIORITY, create_pf( itoa( priority ), PFSTRING)); name = getarr( field, NAME ); if ( name == NULL ) continue; oldval = setarr( newfieldlist->value.arr, name, thresh ); if ( oldval ) free( oldval ); } } freetbl( levels, 0 ); return 1; }
/* This is the main processing function for this program. Arguments: dbv - db pointer to a complex view of the database to be processed. That is, it has these properties: 1. It is a join of: event->origin->assoc->arrival 2. subset to single arrival name AND orid==prefor 3. sorted by evid/sta pf - input parameter space The main processing loop here keys on the grouping defined in the view passed as dbgrp. That is, seismograms for each event group are processed as a complete gather. After that, are nested loops to do the multiwavelet processing as described in Bear and Pavlis (1999a,b). Author: Gary Pavlis Date: March 1999+ */ #define LAG_ERROR -100000 /* Computed lags smaller than this returned by compute_optimal_lag are treated as an error condition. Should probably be in an include file*/ void mwap_process(Dbptr dbv,char *phase, Pf *pf) { int nevents; /* number of events=number of groups in dbgrp */ MWbasis *mw; /* Multiwavelet basis functions */ Tbl **decimators; /* List of loaded decimators used to construct multiwavelet transforms in lower bands */ Tbl **dec_objects; /*Actual decimation filter objects */ /* Note: mw and dec_objects define the multiwavelet transform */ int nwavelets,nbands; /* sets coherence mode used to determine optimal lag */ int coherence_type; Arr *stations; /* This associative array holds MWstation objects that contain header like data that is station dependent */ Arr *badclocks; /* associative array keyed by sta name holding list of time intervals with bad timing */ char *refsta; /* Name of reference station */ double refelev; /* reference elevation from parameter file */ int nsta; /* number of stations */ int ntest; Dbptr db; /* generic db lookup parameter */ Dbptr dbgrp; /* evid group db pointer */ Dbptr tr; /* trace database */ Dbptr dbmps; /* mwpredslow table */ Tbl *sortkeys,*sortkeys2; /* used because different tr routines require different sort orders */ int *pad; /* vector of length nbands holding computed time padding lengths for each band in samples */ int tpad; /*time pad actually used (max of *pad) */ Time_Window *swin, *nwin; /* arrays defining time windows for signal and noise respectively (relative to arrival)*/ Time_Window swinall, nwinall; /*define read time intervals (extracted from swin and nwin arrays */ int *decfac; /* array of decimation factors needed at times */ Arr *mwarr; /* Holds indexed multiwavelet transformed trace objects*/ /* We keep three copies of arrival time information. arrival0 = original times read from db (never altered) arrivals = current working copy arrival_new = new estimate obtained from "arrivals" */ Arr *arrival0,*arrivals,*arrival_new; Arr *static_result; /* Holds error statistics for static estimates */ MWSlowness_vector u0,u; int i,j; double avgamp, amperr; int ampndgf; int iterations; double ucovariance[9]; char *array_name; int accumulate; /* These are channel code names used in trace library rotation functions rotate_to_standard and trrotate. */ char *stdchans[3]={ EW, NS , VERTICAL }; char *pcchans[3]={"R","T","ZL"}; Arr *mwsig_arr,*mwnoise_arr; /* these index pointers to mw transformed signal and noise series */ Arr **sn_ratios; /* vector of Arr pointers of length nbands indexing signal to noise ratio estimates (stored in a structure) for every station */ Spherical_Coordinate polarization0,polarization; Spherical_Coordinate polarz={1.0,0.0,0.0}; Arr *model_times=NULL; MWSlowness_vector model_slow; double rctm[9]; /*ray coordinate transformation matrix*/ double timeref; /* time reference at reference station */ double time; double t0,twin; double si; double fc,fwin; int evid; int lag; /* optimal lab computed by coherence measure */ double peakcm; /*Peak value of coherence measure */ /* For a given gather we set moveout computed moveout time in seconds relative to the reference station. This time includes the combined current static estimates. This is a vector workspace that is recycled for every gather. It is alloced soon as we know the number of stations in the site table. */ double *moveout; MWgather **gathers; Particle_Motion_Ellipse *avgpm; Particle_Motion_Error *avgerr; char *pmtype_to_use; /* type of particle motion estimate to use for polarization */ Arr *pm_arr,*pmerr_arr; Arr *pmarray,*errarray; /* This vector defines the "up" direction. For P waves this initialization is correct. For S it may not be appropriate, but this is something to repair later */ double up[3]={0.0,0.0,1.0}; int bankid; /* mutliwavelet group id */ int band_exit = 0; /* name of parameter file produced by GUI to control this program */ char *guipf; int stack_alignment; Pf *pfcontrol; int loopback; int numberpasses=0; /* These define the relative time window used for stack and particle motion. s denotes stack, ts0 etc are pm */ double sts0,ste0; /* we don't need the equivalent of ts1 and te1 */ double ts0,ts1,te1,te0; /* This is essential or copy_arrival_array can produce garbage */ arrival0=NULL; arrivals = NULL; arrival_new=NULL; pm_arr = NULL; pmerr_arr = NULL; pmarray = NULL; errarray = NULL; si = pfget_double(pf,"sample_interval"); /* First we need to load the multiwavelet functions and the associated decimators for the transform. Each of these routines will die if serious problems occur and have no error returns. Wavelet functions can be loaded from a parameter file or a db. */ if(pfget_boolean(pf,"get_wavelets_from_database")) { mw = load_multiwavelets_db(dbv,pf,&nwavelets,&bankid); } else { mw = load_multiwavelets_pf(pf,&nwavelets); bankid = pfget_int(pf,"bankid"); } decimators = define_decimation(pf,&nbands); allot(int *,decfac,nbands); dec_objects = build_decimation_objects(decimators,nbands,decfac); print_band_info(mw,decfac,pf); /* This creates the station objects. The time extracted here is needed to sort out the ontime:endtime key in the site table. This is done is a less than bombproof fashion by randomly grabbing the time in the first record view. Because of the way the site table works this will always work in some fashion. It will only matter if a station ever moves and then we have a bad problem anyway. */ dbv.record = 0; dbgetv(dbv,0,"time",&time,0); stations = build_station_objects(dbv,pf,time); refsta = get_refsta(stations); array_name = pfget_string(pf,"array_name"); if(array_name == NULL) { elog_complain(0,"WARNING: array_name not defined in parameter file. Set to default of ARRAY\n"); array_name = strdup("ARRAY"); } refelev = pfget_double(pf,"reference_elevation"); /* This loads a definition of bad clocks from an extension table called timing. This comes from libgenloc where it is used to handle automatic switching to S-P times. */ badclocks=newarr(0); if(db_badclock_definition(dbv,pf,badclocks)) { elog_notify(0,"Problems in setting up table of stations with timing problems\n"); } /* This function can define stations as always having bad timing based on a parameter Tbl list of station names keyed by bad_clock.*/ pfget_badclocks(pf,badclocks); pmtype_to_use = pfget_string(pf,"array_particle_motion_to_use"); if(pmtype_to_use==NULL) pmtype_to_use=strdup(PMOTION_BEAM); /* this used to be a variable, but we no longer have a choice.*/ coherence_type=USE_COHERENCE; /* This variable sets if we should reset the arrival estimates to starting values for each band. When true the results accumulate from band to band. That is we keep adding corrections from previous band to progressively higher frequency.*/ accumulate = pfget_boolean(pf,"accumulate_statics"); /* compute time pad lengths for each band of the mw transforms */ pad = compute_tpad(dec_objects, mw, stations,pf); /* These routine parses the parameter file for noise and analysis time window information respectively returning arrays of Time_Window structures of length nbands*/ decfac = get_decimation_factors(dec_objects, pf); swin = get_signal_windows(decfac,pad,pf); nwin = get_noise_windows(decfac,pad,pf); print_window_data(decfac,nbands,swin,nwin,pf); /* This gets time windows for signal and noise needed for reading data (i.e. largest time ranges needed) */ swinall = compute_time_window(swin,decfac,nbands); nwinall = compute_time_window(nwin,decfac,nbands); guipf = pfget_string(pf,"mwapcontrol"); /* better safe than sorry */ if(guipf==NULL) { elog_die(0,"Missing required parameter mwapcontrol"); } /* We can create these works spaces now for efficiency so we don't have to constantly recreate them dynamically below */ allot(double *,moveout,cntarr(stations)); allot(MWgather **,gathers,nwavelets); /* This associative array holds indexed pointers to multiwavelet transformed traces. We create it here, but it is repeatedly freed and cleared below */ mwarr = newarr(0); /* This one has to be initialized*/ static_result=newarr(0); /* We need this table repeatedly below so we avoid constant lookups */ dbmps = dblookup(dbv,0,"mwpredslow",0,0); if(dbmps.record == dbINVALID) elog_die(0,"db lookup failed for mwpredslow table\nMWavelet schema extensions are required\n"); /* Now we loop through the outer loop event by event. This is structured here by using a dbgroup defined db pointer that is passed through the argument list. The db pointer is incremented and then the bundle is taken apart to crack apart each group of traces (the gather). Note we use a defined name to look up the evid grouped table. */ dbgrp = dblookup(dbv,0,EVIDBDLNAME,0,0); if (dbgrp.record == dbINVALID) elog_die(0,"Error in dblookup for named evid group table = %s\n", EVIDBDLNAME); dbquery(dbgrp,dbRECORD_COUNT,&nevents); fprintf(stdout,"Processing begins for %d events\n",nevents); sortkeys = newtbl(0); pushtbl(sortkeys,"sta"); pushtbl(sortkeys,"chan"); pushtbl(sortkeys,"time"); sortkeys2 = newtbl(0); pushtbl(sortkeys2,"time"); pushtbl(sortkeys2,"sta"); pushtbl(sortkeys2,"chan"); for(dbgrp.record=0;dbgrp.record<nevents;++dbgrp.record) { Dbptr db_bundle; int evid; int is, ie; int ierr; double modaz; if(dbgetv(dbgrp,0,"evid", &evid, "bundle", &db_bundle,0) == dbINVALID) { elog_complain(1,"dbgetv error for row %d of event group\nAttempting to continue by skipping to next event\n", dbgrp.record); continue; } dbget_range(db_bundle,&is,&ie); if(ie-is<3) { elog_complain(0,"Insufficient data to process for evid %d\nNeed at least three station -- found only %d\n", evid,ie-is); continue; } /* We utilize what we call plane wave statics here to approximately correct for wavefront curvature. We set the record number to is so we can access the correct origin information from the db. Because we used a join allrows of this group should have the same origin data. */ ierr = set_pwstatics(stations,refsta,phase,db_bundle,pf); if(ierr)elog_complain(0,"%d errors computing %d plane wave statics for evid %d\n", ierr,ie-is,evid); /* This routine loads an Arr of arrival times from the input db to be used to compute initial slowness vector and initial statics. */ arrival0 = get_arrivals(db_bundle); /* We edit the MWstation array to flag stations with bad timing in this function */ MWcheck_timing(arrival0,stations,badclocks); /* Save these times */ copy_arrival_array(arrival0,&arrivals); /* Initialize slowness vector to 0 and then estimate it from data using current arrival times */ u0.ux = 0.0; u0.uy = 0.0; u0.refsta = refsta; timeref = compute_time_reference(stations,arrivals,refsta,u0); /* for the first pass we use weights defined for the lowest frequency band. This is done because it asssumed that if frequency dependent weighting is actually used the lowest band would have the widest effective aperture. */ ierr = estimate_slowness_vector(u0,arrivals,stations, refsta, refelev, timeref, phase, nbands-1,&u); /* It is necessary to reset the time reference to handle the case correctly when the reference station does not actually record this event. This function uses a moveout correction that depends upon the slowness vector, so it can float about a bit in that situation */ if(ierr>0) elog_notify(0,"%d nonfatal errors in estimate_slowness_vetor for evid %d\n",ierr,evid); else if(ierr < 0) { elog_complain(0,"estimate_slowness_vector failed for initial slowness estimate for evid %d\nData for this event will be skipped\n", evid); continue; } /* This routine returns the slowness vector and an arr of estimated arrival times. The slowness vector is saved in the mwpredslow table immediately below. Arrival times are used to compute residuals later. */ ierr = MWget_model_tt_slow(stations, refsta, phase, db_bundle, pf, &model_times, &model_slow); timeref = compute_time_reference(stations,arrivals,refsta,u); polarization0=estimate_initial_polarization(model_slow,stations, refsta,phase); modaz = atan2(model_slow.ux,model_slow.uy); if(dbaddv(dbmps,0,"sta",array_name, "evid",evid, "phase",phase, "time",timeref, "slo",hypot(model_slow.ux,model_slow.uy), "azimuth",deg(modaz), "majoraz",deg(polarization0.phi), "majorema",deg(polarization0.theta), "vmodel",pfget_string(pf,"TTmodel"),0) == dbINVALID) { elog_complain(0,"dbaddv error for evid %d on mwpredslow table\n", evid); } /* This function reads in the trace data for this event using time windows defined above */ tr = mwap_readdata(dbgrp,arrivals,swinall, nwinall); if(tr.record == dbINVALID) { elog_complain(0,"Serious problems reading data for evid %d -- no data processed for this event\n",evid); continue; } tr = dblookup(tr,0,"trace",0,0); /* We first glue together any possible recording break generated entries -- common with continuous data. This also seems to require a resort because of the way data was read in. */ /* tr = dbsort(tr,sortkeys,0,0); */ trsplice(tr,0.1,0,0); /* We run trsplit to break up waveform segments at real gaps. I'm not sure later code will work correctly if it isn't an all or nothing situations (e.g. gap in Z component, but not in N or E). In any case, we have to deal with potential multiple segments later. */ trsplit(tr,0,0); trapply_calib(tr); trdemean_seg(tr); /* Now we have reorder the traces or this will not work correctly*/ tr = dbsort(tr,sortkeys2,0,0); ierr = rotate_to_standard(tr,stdchans); if(ierr<0) { elog_complain(0,"rotate_to_standard failed processing evid %d -- no data processed for this event\n", evid); continue; } if(ierr>0)elog_complain(0,"rotate_to_standard failed for %d stations\n", ierr); /* This releases the space held by the raw data traces keeping only the rotate_to_standard outputs */ free_noncardinal_traces(tr); elog_log(0,"Computing multiwavelet transform: be\ patient as this can take a while with many channels\n"); /* This function computes the multiwavelet transform of all traces currently in tr for signals around arrival*/ mwsig_arr = tr_mwtransform(tr,arrivals,swin,decfac,dec_objects, nbands,mw,nwavelets); /* We repeat the same thing for noise windows */ mwnoise_arr = tr_mwtransform(tr,arrivals,nwin,decfac, dec_objects,nbands,mw,nwavelets); /* Now compute signal to noise ratio figures for all nbands storing the structures that define the results in an Arr keyed by station. Note this is actually a vector of Arr pointers of length nbands. Further note the following function creates this complicated object, and it must be freed after each event is processed. */ sn_ratios=compute_signal_to_noise(mwsig_arr,mwnoise_arr, stations,arrivals,swin,nwin, nbands,nwavelets); /* Now we get to the heart of this program. This is the outer loop over frequency. Note the loop goes backward because the lowest frequencies are the final row of the mw transform matrices of pointers */ copy_MWslowness_vector(&u,&u0); if(numberpasses>0) { fprintf(MWpout,"NEWEVENT %d\n",evid); } for(i=nbands-1;i>=0;--i) { if(!accumulate) copy_arrival_array(arrival0,&arrivals); copy_arrival_array(arrivals,&arrival_new); fc = (mw[i].f0)/(2.0*si*decfac[i]); fwin = (mw[i].fw)/(2.0*si*decfac[i]); fprintf(stdout,"Processing begins on band %d with center frequency %lf\nWait for -Hit Accept button when ready- prompt\n", i,fc); /* This builds the basic working gathers for each wavelet and builds a shortcut of pointers to MWtraces that are related */ for(j=0;j<nwavelets;++j) { gathers[j] = build_MWgather(i,j, mwsig_arr,stations, sn_ratios[i],pf); } fprintf(stdout,"Working gather for this band has %d stations\n", gathers[0]->nsta); /* Testing band 0 should be sufficient. The signal-to-noise is averaged overall wavelets so the same stations should be deleted in all wavelet of the group */ if(gathers[0]->nsta < 3) { elog_notify(0,"Insufficient data in band %d to passed signal-to-noise cutoff defined for this band for evid %d\nSkipping to next frequency band\n", i,evid); continue; } /* This may not be necessary, but it is certainly important for debugging. We check that all the gathers in the group have the same length. If they aren't, we are in trouble because we use a single vector to hold moveout information */ check_gather_consistency(gathers,nwavelets); /* Now we compute the moveout information assuming stations are in the same order in the gather for each wavelet */ if(compute_total_moveout(*gathers,stations,refsta, u,refelev,phase,moveout)) { elog_die(0,"Cannot find reference station to compute moveout: Should not happen unless program overwrites itself\n"); } if(numberpasses>0) { fprintf(MWpout,"NEWBAND %d\n",i); fflush(MWpout); } else { char ctmp[40]; fprintf(stdout,"Starting processing of first event\nSelect and options and press the Start button when ready\n"); fprintf(MWpout,"STARTUP %d %d\n", evid,i); fflush(MWpout); fgets(ctmp,40,MWpin); } ++numberpasses; /* This is placed here to allow changing the alignment options on the fly. Choice may depend on data. */ pfread(guipf,&pfcontrol); stack_alignment=get_stack_align_mode(pfcontrol); pffree(pfcontrol); /* kind of a odd loop construct here made necessary by differences in stackalignment options. If we align with theoretical value or use the vertical we do not need to repeat this loop and we fall out the bottom. If we use the pm estimate, however, we have to realign the stack rotated to the new major ellipse estimate. In that case we have to repeat the whole procedure.*/ loopback=2; do { MWstack *stack; switch(stack_alignment) { case PMTHEORY: copy_polarization(&polarization0,&polarization); loopback=0; break; case PMZ: copy_polarization(&polarz,&polarization); loopback=0; break; case PMESTIMATE: default: /* This uses theoretical version for the first pass then the estimate on the second */ if(loopback==2) copy_polarization(&polarization0, &polarization); } stack=MWcompute_arrival_times(gathers, nwavelets,timeref,moveout, polarization,swin[i], sn_ratios[i],guipf, &arrival_new,&static_result, &avgamp, &err, &ndgf); if(stack==NULL) { /* I use a flag to avoid an evil goto here */ band_exit = 1; /* This is strange but necessary to stop string of bogus errors from copy_arrival_array function when this loops back */ if(arrival_new!=NULL) freearr(arrival_new,free); arrival_new = NULL; break; } /* Note this routine updates residual static values to new values relative to the new slowness vector estimate */ ierr = estimate_slowness_vector(u0, arrival_new,stations, refsta, refelev, timeref, phase, i, &u); /* We need to recompute the moveout to now be relative to the new slowness vector estimate. We then use this for particle motion analysis which can change the polarization vector */ compute_total_moveout(*gathers,stations,refsta, u,refelev,phase,moveout); /* This segment converts particle motions for 3-c arrays. */ if(gathers[0]->ncomponents==3) { MWstack *spm; Time_Window pmtwindow; double *timeweight; /* We extract the time window from a control parameter file which is assumed to be created by a GUI with tcl/tk */ pfread(guipf,&pfcontrol); ts0=pfget_double(pfcontrol,"pm_ts0"); ts1=pfget_double(pfcontrol,"pm_ts1"); te1=pfget_double(pfcontrol,"pm_te1"); te0=pfget_double(pfcontrol,"pm_te0"); /* we need these below, not here */ sts0=pfget_double(pfcontrol,"stack_ts0"); ste0=pfget_double(pfcontrol,"stack_te0"); twin = ste0-sts0; pffree(pfcontrol); pmtwindow.tstart = nint(ts0/(stack->dt)); pmtwindow.tend = nint(te0/(stack->dt)); spm = MWextract_stack_window(stack, &pmtwindow); if(spm==NULL) elog_die(0, "Fatal error in MWextract_stack_window\n"); /* Sets time weight function for a trapezoidal window */ timeweight=MWstack_set_trapezoidal_window(spm->tstart, spm->dt,spm->nt, ts0,ts1,te1,te0); dcopy(spm->nt,timeweight,1,spm->timeweight,1); free(timeweight); MWstack_apply_timeweight(spm); if(MWcompute_array_particle_motion(gathers, nwavelets,spm,timeref,moveout, up,&pmarray,&errarray, &pm_arr,&pmerr_arr) ) { elog_complain(0,"Errors in MWcompute_array_particle_motion\n"); } avgpm = (Particle_Motion_Ellipse *)getarr(pmarray,pmtype_to_use); avgerr = (Particle_Motion_Error *)getarr(pmarray,pmtype_to_use); polarization =unit_vector_to_spherical(avgpm->major); destroy_MWstack(spm); } peakcm=stack->coherence[idamax( stack->nt, stack->coherence,1)]; copy_arrival_array(arrival_new,&arrivals); freearr(arrival_new,free); arrival_new = NULL; destroy_MWstack(stack); if(stack_alignment==PMESTIMATE) --loopback; }while(loopback>0); if(band_exit) { band_exit = 0; continue; } /* This routine computes the covariance of the estimated slowness vector */ if(compute_slowness_covariance(stations,static_result, ucovariance) ) elog_complain(0,"Problems computing slowness vector covariance estimate for evid %d and band %d\n", evid, i); /* routines below save a time window. We compute the lag corrected start time at the reference station here as t0 to simplify this in functions that need this.*/ t0 = timeref + sts0; /* This series of functions save results in a set of css3.0 extension tables. */ /* ampndgf+1 here is a cheap solution to the number of stations used in a solution. This confusion is necessary because autoediting reduces the data set. Poor planning caused me to not force this to be saved explicitly, but ampndgf is an exact surrogate. The +1 is needed because the calculation uses number_used - 1 since the average amplitude is extracted as a free parameter. */ if(MWdb_save_slowness_vector(phase,&u,t0,twin, array_name,evid,bankid,fc,fwin, ucovariance,ampndgf+1,3, coherence_type,peakcm,dbv)) dbsave_error("mwslow",evid,i); if(MWdb_save_avgamp(array_name, evid, bankid, phase, fc, t0, twin, avgamp,amperr,ampndgf, dbv) ) dbsave_error("mwavgamp",evid,i); if(MWdb_save_statics(evid, bankid, phase, fc, t0, twin,refelev,*gathers,moveout,static_result, stations,sn_ratios[i], arrivals, model_times,dbv)) dbsave_error("mwtstatic:mwastatic:mwsnr",evid,i); t0=timeref+ts0; twin = te0-ts0; if(MWdb_save_pm(array_name,evid,bankid,phase,fc,t0, twin,*gathers,moveout,pm_arr,pmerr_arr, avgpm,avgerr,dbv) ) dbsave_error("mwpm",evid,i); /* We have to release the memory held in these associative arrays. In the earlier loop the function that creates them always clears them before continuing when they are not null. The explicit NULL set after the free is done to make sure in looping back the particle motion routine clears these correctly. */ freearr(pm_arr,free); pm_arr = NULL; freearr(pmerr_arr,free); pmerr_arr = NULL; /* same for static arr */ freearr(static_result,free); static_result = NULL; } /*release main work spaces with this series of complicated free routines. Here is where you really wish C had garbage collection */ free_sn_ratios_arr(sn_ratios,nbands); free_MWtransform_arr(mwsig_arr,nbands,nwavelets); free_MWtransform_arr(mwnoise_arr,nbands,nwavelets); trdestroy(&tr); freearr(arrival0,free); freearr(arrivals,free); /* This may not be necessary, but better safe than sorry */ arrivals = NULL; arrival0 = NULL; arrival_new = NULL; } free(moveout); free(swin); free(nwin); free(refsta); }
Tbl * get_frametbl( char *block_name, char *RTtype ) { static Arr *frametables = 0; Pf *pf; Tbl *frames; Tbl *siterows; siteinfo *sinfo[6]; char key[STRSZ]; int i; sprintf( key, "%s:%s", block_name, RTtype ); if( frametables == 0 ) { frametables = newarr( 0 ); } else if( ( frames = (Tbl *) getarr( frametables, key ) ) != 0 ) { return frames; } pf = get_pf( block_name ); siterows = pfget_tbl( pf, RTtype ); frames = sitetbl2frametbl( siterows ); freetbl( siterows, 0 ); setarr( frametables, key, (void *) frames ); sorttbl( frames, cmp_sinfo_order, 0 ); if( STREQ( RTtype, "LPRT" ) ) { if( maxtbl( frames ) % 3 != 0 ) { fprintf( stderr, "Wrong # of components in LPRT table\n" ); return 0; } for( i=0; i < maxtbl( frames ); i += 3 ) { sinfo[0] = (siteinfo *) gettbl( frames, 0 ); sinfo[1] = (siteinfo *) gettbl( frames, 1 ); sinfo[2] = (siteinfo *) gettbl( frames, 2 ); if( ! ( STREQ( sinfo[0]->sta, sinfo[1]->sta ) && STREQ( sinfo[1]->sta, sinfo[2]->sta ) ) ) { fprintf( stderr, "Unexpected order in LPRT table\n" ); return 0; } } } else if( STREQ( RTtype, "BBRT" ) ) { if( maxtbl( frames ) % 6 != 0 ) { fprintf( stderr, "Wrong # of components in BBRT table\n" ); return 0; } for( i=0; i < maxtbl( frames ); i += 6 ) { sinfo[0] = (siteinfo *) gettbl( frames, 0 ); sinfo[1] = (siteinfo *) gettbl( frames, 1 ); sinfo[2] = (siteinfo *) gettbl( frames, 2 ); sinfo[3] = (siteinfo *) gettbl( frames, 3 ); sinfo[4] = (siteinfo *) gettbl( frames, 4 ); sinfo[5] = (siteinfo *) gettbl( frames, 5 ); if( ! ( STREQ( sinfo[0]->sta, sinfo[1]->sta ) && STREQ( sinfo[1]->sta, sinfo[2]->sta ) && STREQ( sinfo[2]->sta, sinfo[3]->sta ) && STREQ( sinfo[3]->sta, sinfo[4]->sta ) && STREQ( sinfo[4]->sta, sinfo[5]->sta ) ) ) { fprintf( stderr, "Unexpected order in BBRT table\n" ); return 0; } } } return frames; }
Arr *get_freezearr(enum FREEZE_METHOD fm, Hypocenter *h0, int *evid, Tbl **ta, int nevents) { int i; /* loop counter */ char *fixstr; int minrmsevid, maxdataevid; double rmsmin,thisrms; int maxarrivals; minrmsevid=evid[0]; maxdataevid=evid[0]; maxarrivals=maxtbl(ta[0]); rmsmin=h0[0].rms_weighted; if(rmsmin<=0.0) rmsmin=-1.0; /* slighly inefficient to compute both of these measures all the time, but the effort is so trivial it should not matter much. More importantly, it allows a fallback in case the rms fields are not set. When that is true the maxarrival method are used and a warning is posted. */ for(i=1;i<nevents;++i) { int thismaxarr; thismaxarr=maxtbl(ta[i]); if(thismaxarr>maxarrivals) { maxdataevid=evid[i]; maxarrivals=thismaxarr; } thisrms=h0[i].rms_weighted; if(thisrms>0.0) { if(rmsmin>0.0) { if(thisrms<rmsmin) minrmsevid=evid[i]; } else { rmsmin=thisrms; minrmsevid=evid[i]; } } } int evid_to_freeze; switch(fm) { case DEPTH_MINRMS: case ALLSPACE_MINRMS: case ALL_MINRMS: /* Tricky logic. if minrms is null (0 or negative), this implicitly defaults to arrival count metric */ if(minrmsevid>0.0) { evid_to_freeze=minrmsevid; break; } else elog_log(0,"pmel warning: freeze mode could not use rms measure to select event to fix\nrms field was null in all hypocenters in this group\n"); case DEPTH_MAXARRIVALS: case ALLSPACE_MAXARRIVALS: case ALL_MAXARRIVALS: case NOTSET: default: evid_to_freeze=maxdataevid; } switch(fm) { case DEPTH_MAXARRIVALS: case DEPTH_MINRMS: fixstr=strdup("z"); break; break; case ALL_MAXARRIVALS: case ALL_MINRMS: fixstr=strdup("xyzt"); case ALLSPACE_MAXARRIVALS: case ALLSPACE_MINRMS: case NOTSET: default: fixstr=strdup("xyz"); } char *key=make_evid_key(evid_to_freeze); Arr *result=newarr(0); setarr(result,key,fixstr); return(result); }