Tbl * dbschema2sqlcreate( Dbptr db, long flags ) { Tbl *sql; char *cmd; Tbl *tables; char *table; long itable; sql = newtbl( 0 ); if( db.table >= 0 ) { cmd = generate_sqltable_create( db, flags ); pushtbl( sql, cmd ); } else { dbquery( db, dbSCHEMA_TABLES, &tables ); for( itable = 0; itable < maxtbl( tables ); itable++ ) { table = gettbl( tables, itable ); db = dblookup( db, "", table, "", "" ); cmd = generate_sqltable_create( db, flags ); pushtbl( sql, cmd ); } } return sql; }
/* This small function parses an input string made up of a comma seperated list of integer ranges returning a Tbl of ints after expanding the full range defined by the string. An example will make this clearer: if *gstr is "1,2,4-6" The output Tbl list will be 1,2,4,5,6. No test is made for overlapping integer ranges. Author: Gary Pavlis Written: Sept 2000 */ Tbl *parse_gridlist_string(char *gstr) { Tbl *t; char *sp; char *sie; int is,ie,i; t = newtbl(0); sp = strtok(gstr,","); do { if( (sie=strchr(sp,'-')) == NULL) { is = atoi(sp); ie = is; } else { *sie = '\0'; ++sie; is = atoi(sp); ie = atoi(sie); } for(i=is;i<=ie;++i) { pushtbl(t,(void *)i); } } while((sp = strtok(NULL,","))!=NULL); return(t); }
int db2sqldelete( Dbptr db, char *sync, Tbl **tbl, long flags ) { void *stk = 0; char *table; char *cmd; if( *tbl == (Tbl *) NULL ) { *tbl = newtbl( 0 ); } dbquery( db, dbTABLE_NAME, &table ); pushstr( &stk, "DELETE from `" ); pushstr( &stk, table ); pushstr( &stk, "` WHERE " ); pushstr( &stk, " `" ); pushstr( &stk, Db2sql_syncfield_name ); pushstr( &stk, "` = '" ); pushstr( &stk, sync ); pushstr( &stk, "'" ); pushstr( &stk, ";\n" ); cmd = popstr( &stk, 1 ); pushtbl( *tbl, cmd ); return 1; }
void mexFunction ( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { double delta; double depth; char **phases = 0; double *slowness = 0; double *pr; long narrivals; Tbl *phasetbl; long i; if( nrhs != 2 ) { antelope_mexUsageMsgTxt ( USAGE ); return; } else if( ! get_scalar( prhs[0], &delta ) ) { antelope_mexUsageMsgTxt ( USAGE ); return; } else if( ! get_scalar( prhs[1], &depth ) ) { antelope_mexUsageMsgTxt ( USAGE ); return; } narrivals = arr_slowness( delta, depth, &phases, &slowness ); if( narrivals <= 0 ) { return; } phasetbl = newtbl( narrivals ); for( i = 0; i < narrivals; i++ ) { pushtbl( phasetbl, phases[i] ); } plhs[0] = mxCreateDoubleMatrix( narrivals, 1, mxREAL ); pr = mxGetPr( plhs[0] ); for( i = 0; i < narrivals; i++ ) { pr[i] = slowness[i]; } plhs[1] = stringtbl2cellstr( phasetbl ); freetbl( phasetbl, 0 ); }
RYO2orbPacket * new_RYO2orbPacket() { RYO2orbPacket *r2opkt; allot( RYO2orbPacket *, r2opkt, 1 ); memset( r2opkt, '\0', sizeof( RYO2orbPacket ) ); r2opkt->satellites = newtbl( 0 ); return r2opkt; }
/* This is the translation routine similar to dbload_arrival_table and load_arrival_table in libgenloc. Arguments: hyp - input structure stations - associative array of station structures arrphase - associate array of phase handles. Function returns tbl of Arrival objects used by genloc routines. Author: G Pavlis written: january 30, 1998 */ Tbl *orbhypo_to_genloc(ORB_Hypocenter *hyp, Arr *arrphase, Arr *stations) { Arrival *a; Tbl *t; int i; t = newtbl(0); for(i=0;i<hyp->nass;++i) { a = (Arrival *) malloc(sizeof(Arrival)); if(a == NULL) elog_die(1,"orbhypo_to_genloc cannot malloc Arrival structure\n"); a->sta = (Station *) getarr(stations,hyp->assocs[i].sta); if(a->sta == NULL) { elog_complain(1,"Cannot find coordinates for station %s\n%s phase arrival for this station skipped\n", hyp->assocs[i].sta, hyp->assocs[i].iphase); free(a); continue; } a->arid = hyp->assocs[i].arid; a->time = hyp->assocs[i].time; a->phase = (Phase_handle *) getarr(arrphase, hyp->assocs[i].iphase); if(a->phase == NULL) { if ( strcmp(hyp->assocs[i].iphase, "D") != 0 ) { elog_complain(1,"Don't know how to handle phase '%s'" " -- Arrival at %s at time %lf skipped\n", hyp->assocs[i].iphase,hyp->assocs[i].sta, hyp->assocs[i].time); } free(a); continue; } /* the current real-time system has no uncertainty estimate on the picks so we always use the default */ a->deltat = (double)a->phase->deltat0; pushtbl(t,a); } return(t); }
static long generate_sqltable_insert( Dbptr db, Tbl **tbl, char *(*createsync)(Dbptr db), long flags ) { char *cmd; long nrecs; if( *tbl == (Tbl *) NULL ) { *tbl = newtbl( 0 ); } dbquery( db, dbRECORD_COUNT, &nrecs ); for( db.record = 0; db.record < nrecs; db.record++ ) { cmd = generate_sqlrow_insert( db, createsync, flags ); pushtbl( *tbl, cmd ); } return nrecs; }
/* Recursively removes pf instances from the pf object and returns the * objects' contents in an entirely new structure so that no memory is reused. * Requires the caller have some knowledge about the structure of the data. */ void * pf_collapse( Pf * pf ) { Arr * currarr; Tbl * currtbl; char * key; void * value; int i; int size; if ( pf == NULL ) return NULL; switch( pf->type ) { case PFARR: currtbl = keysarr( pf->value.arr ); size = maxtbl( currtbl ); /* currarr = newarr( pf->value.arr->rb_comp ); */ currarr = newarr( strcmp ); for ( i = 0; i < size; i++ ) { key = poptbl( currtbl ); value = pf_collapse( getarr( pf->value.arr, key ) ); setarr( currarr, key, value ); } freetbl( currtbl, 0 ); return currarr; case PFTBL: size = maxtbl( pf->value.tbl ); currtbl = newtbl( size ); for ( i = 0; i < size; i++ ) settbl( currtbl, i, pf_collapse( gettbl( pf->value.tbl, i ) ) ); return currtbl; default: return strdup( pf->value.s ); } }
void compute_location(Location_options o, RTlocate_Options rtopts, Arr *stations, Arr *arrays, Arr *phases, Pf *pf, Dbptr master_db, Dbptr dbtmp, ORB_Hypocenter hyp, int orbout) { Tbl *ta,*tu; /* Arrival and slowness tables respectively */ Hypocenter h0; int ret_code; Tbl *converge_history,*reason_converged,*residual; Hypocenter *hypo; int niterations; char *vmodel; int i; char *s; int orid; Point origin; double delta, seaz; double **C; float *emodel; int nass; initialize_hypocenter(&h0); /* It is inefficient to reread these from the parameter space on each entry, but preferable to a burdensome argument list */ origin.lat = pfget_double(pf,"center_latitude"); origin.lon = pfget_double(pf,"center_longitude"); origin.z = 0.0; /* This routine translates hyp structure to return tbl of arrival object pointers */ ta = orbhypo_to_genloc(&hyp,phases,stations); /* this is a pure place holder */ tu = newtbl(0); vmodel = pfget_string(pf,"velocity_model_name"); /* By default we use the location transmitted by orbassoc. This can be overriden in the parameter file by using the other options allowed in genloc*/ s=pfget_string(pf,"initial_location_method"); h0.lat = hyp.lat; h0.lon = hyp.lon; h0.z = hyp.depth; h0.time = hyp.time; /* this strange logic is to allow this parameter to be defaulted. If the "initial_location_method" is not defined, or set to "manual", we use the location given by orbassoc. Otherwise we utilize genlocs suite of initial locate options. */ if(s != NULL) if(strcmp(s,"manual")) h0 = initial_locate(ta, tu, o, pf); /* Now compute distance from origin, and process only if the event falls in the specified range */ dist(rad(origin.lat),rad(origin.lon),rad(h0.lat),rad(h0.lon), &delta,&seaz); delta = deg(delta); /* this is the distance sifting test to ignore things outside specified distance range */ if( ((delta>=rtopts.minimum_distance) && (delta <= rtopts.maximum_distance)) ) { /* Location with Generic Gauss_Newton code */ orid = -1; nass = maxtbl(ta); ret_code = ggnloc(h0,ta,tu,o, &converge_history,&reason_converged,&residual); if(ret_code < 0) { elog_notify (0,"ggnloc failed to produce a solution for evid %d\n",hyp.evid); } else { if(ret_code > 0) elog_notify(0,"Warning: %d travel time calculator failures in ggnloc\nSolution ok for evid %d\n", ret_code,hyp.evid); C = dmatrix(0,3,0,3); emodel = (float *) calloc(4,sizeof(float)); if((emodel == NULL) || (*C == NULL) ) elog_die(0,"Malloc error for error arrays\n"); niterations = maxtbl(converge_history); hypo = (Hypocenter *)gettbl(converge_history, niterations-1); predicted_errors(*hypo, ta, tu, o, C, emodel); orid = save_origin(nass,hyp.evid,master_db, dbtmp,*hypo,o,orbout); save_origerr(orid,*hypo,C,dbtmp,orbout); save_assoc(ta, tu, orid, vmodel, *hypo, dbtmp,orbout); elog_notify(0,"orid %d converged in %d iterations\n", orid,niterations); elog_notify(0,"Reason(s) for convergence: \n"); for(i=0;i<maxtbl(reason_converged);++i) elog_notify(0,"%s",gettbl(reason_converged,i)); elog_notify(0,"\n"); s=format_hypo(hypo); elog_notify(0,"%s\n",s); free(emodel); free_matrix((char **)C,0,3,0); free(s); } write_to_logfile(rtopts, orid, hyp.evid, pf, converge_history, reason_converged,residual); 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(ta, tu); return; }
/* This little routine dumps the parameter space of pf and the output tbls of ggnloc to a log file tagged by orid. Note, however, that if ggnloc failed for some reason, it is assumed that orid will be set to a NEGATIVE number. When this occurs, the results are written to a "failures" directory defined in rtopts. IMPORTANT: multiple instances of orbgenloc should arrange to write in seperate failure directories or they can collide. */ int write_to_logfile(RTlocate_Options rtopts, int orid, int evid, Pf *pf, Tbl *converge_history, Tbl *reason_converged,Tbl *residual) { char fname[256]; FILE *fp; /* We write the logfile output as a pf object copying code from sgnloc */ Pf *pflog; Tbl *t; /* formatted output tbl of hypo convergence history */ char *line; int i; Hypocenter *hypos; /* This can fail for very long directory entries, but it isn't worth messing with in my mind. Note switch for orid */ if(orid > 0) { sprintf(fname,"%s/orid%d.pf",rtopts.logdir,orid); } else { sprintf(fname,"%s/%s/evid%d.pf",rtopts.logdir, rtopts.failure_sdir,evid); } pfwrite(fname,pf); /* Here we encapsulate the convergence history information into a second pf object, and write this onto the same pf file */ t = newtbl(maxtbl(converge_history)); for(i=0;i<maxtbl(converge_history);++i) { hypos = (Hypocenter *)gettbl(converge_history,i); line = format_hypo(hypos); pushtbl(t,line); } pflog = pfnew(PFFILE); pfput_tbl(pflog,"convergence_history",t); printf("Reasons for convergence:\n"); for(i=0;i<maxtbl(reason_converged);++i) printf("%s\n",gettbl(reason_converged,i)); pfput_tbl(pflog,"convergence_criteria",reason_converged); pfput_tbl(pflog,"residuals",residual); /* We use pf2string rather than pfwrite since I'm not sure what pfwrite will do when the file already exists. Here we just append the new pf info to the end of the stuff written above. */ if((fp=fopen(fname,"a")) == NULL) { elog_complain(1,"Cannot open log file %s\n",fname); return(1); } fseek(fp,0L,SEEK_END); line = pf2string(pflog); fwrite(line,1,strlen(line),fp); fclose(fp); free(line); pffree(pflog); freetbl(t,free); return(0); }
/* This function adds a list of attributes stored in one row of a datascope database to a pf. What attributes are extracted and converted is controlled by the Attribute_map list stored in t. Arguments: db - row of database to use to extract info to create or update pf. t - Tbl containing pointers to Attribute_map objects that define which attributes to extract and possible renaming in pf pf - destination pf object. Returns: The routine returns a Tbl list of attribute names that were null on this database row. This is used in dryrun mode to flag database problems. IMPORTANT: a valid Tbl is always returned. The caller must free this list. A test for now errors is maxtbl()==0. Author: Gary L. Pavlis Written: September 2002 Modified: march 2003 Used to return only an int. It now returns a Tbl described above. */ Tbl *db2pf(Dbptr db, Tbl *t, Pf *pf) { int i; char *nullvalue; int iattrib, inull; double dattrib, dnull; char sattrib[128]; Attribute_map *m; Dbptr dbf; char *bad_attrib; Tbl *error_list=newtbl(0); for(i=0;i<maxtbl(t);++i) { m = (Attribute_map *)gettbl(t,i); dbf=dblookup(db,0,0,m->dbname,0); dbquery(dbf,dbNULL,&nullvalue); switch(m->type) { case DBREAL: if(dbgetv(db,0,m->dbname,&dattrib,0)==dbINVALID) { elog_die(0,"dbgetv error for %s\n", m->dbname); } dnull=atof(nullvalue); if(dattrib==dnull) { bad_attrib=strdup(m->dbname); pushtbl(error_list,bad_attrib); break; } pfput_double(pf,m->pfname,dattrib); break; case DBTIME: if(dbgetv(db,0,m->dbname,&dattrib,0)==dbINVALID) { elog_die(0,"dbgetv error for %s\n", m->dbname); } dnull=atof(nullvalue); if(dattrib==dnull) { bad_attrib=strdup(m->dbname); pushtbl(error_list,bad_attrib); break; } pfput_time(pf,m->pfname,dattrib); break; case DBINT: if(dbgetv(db,0,m->dbname,&iattrib,0)==dbINVALID) { elog_die(0,"dbgetv error for %s\n", m->dbname); } inull=atoi(nullvalue); if(iattrib==inull) { bad_attrib=strdup(m->dbname); pushtbl(error_list,bad_attrib); break; } pfput_int(pf,m->pfname,iattrib); break; case DBSTR: default: if(dbgetv(db,0,m->dbname,sattrib,0)==dbINVALID) { elog_die(0,"dbgetv error for %s\n", m->dbname); } /*conversion not necessary here since dbNULL query returns a string for null value*/ if(!strcmp(sattrib,nullvalue)) { bad_attrib=strdup(m->dbname); pushtbl(error_list,bad_attrib); break; } pfput_string(pf,m->pfname,sattrib); } } return(error_list); }
static Tbl * get_fieldnames( Dbptr db, int flags ) { Tbl *fieldnames; Tbl *view_tables; Tbl *table_fields; char *tablename; char *fieldname; char afield[STRSZ]; Dbvalue result; int itable; int ifield; static Hook *hook = 0; int start; int nchars; int is_view; fieldnames = newtbl( 0 ); view_tables = newtbl( 0 ); dbquery( db, dbTABLE_IS_VIEW, &is_view ); if( is_view ) { dbquery( db, dbVIEW_TABLES, &view_tables ); view_tables = duptbl( view_tables, (void *(*)(void *)) strdup ); } else { dbquery( db, dbTABLE_NAME, &result ); view_tables = strtbl( strdup( result.t ), 0 ); } for( itable = 0; itable < maxtbl( view_tables ); itable++ ) { tablename = gettbl( view_tables, itable ); db = dblookup( db, "", tablename, "", "" ); if( flags & DBXML_PRIMARY ) { dbquery( db, dbPRIMARY_KEY, &table_fields ); } else { dbquery( db, dbTABLE_FIELDS, &table_fields ); } for( ifield = 0; ifield < maxtbl( table_fields ); ifield++ ) { fieldname = gettbl( table_fields, ifield ); if( strcontains( fieldname, "::", &hook, &start, &nchars ) ) { strcpy( afield, fieldname ); afield[start] = '\0'; fprintf( stderr, "SCAFFOLD: adding %s\n", afield); add_fieldname( fieldnames, tablename, afield ); strcpy( afield, fieldname + start + 2 ); fprintf( stderr, "SCAFFOLD: adding %s\n", afield); add_fieldname( fieldnames, tablename, afield ); } else { add_fieldname( fieldnames, tablename, fieldname ); } } } freetbl( view_tables, free ); return fieldnames; }
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*/ long nevents; /* db row variables */ long evid; long 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; Hypocenter h0; Hypocenter *hypos; long niterations; char *vmodel; int ret_code; /* ggnloc return code */ double **C; /* covariance matrix*/ float emodel[4]; /* entries for S-P feature */ long 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) elog_die(1,"Unable to open input database %s\n",dbin); if(dbopen(dbout,"r+",&dbo) == dbINVALID) elog_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) elog_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) elog_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) elog_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) elog_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) elog_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) elog_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) elog_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\ %ld total picks, %ld 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,"arrival.time"); dbv = dbsort(dbv,sortkeys,0,0); if(dbv.record == dbINVALID) elog_die(1,"dbsort on evid,orid,arrival.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) elog_die(1,"dbgroup by origin failed\n"); dbquery(dborigin_group,dbRECORD_COUNT,&nevents); elog_notify(0,"Attempting to relocate %ld 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) elog_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; long is, ie; long orid; /* orid assigned relocated event in output db */ if(dbgetv(dborigin_group,0,"evid", &evid, "bundle", &db_bundle,NULL ) == dbINVALID) elog_complain(1,"dbgetv error for row %ld 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,NULL ); 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) { elog_complain(1,"ggnloc failed to produce a solution\n"); } else { if(ret_code > 0) elog_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,"%ld %ld %lf %lf %lf %lf %g %g %g %d %d %ld\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 main(int argc, char **argv) { SEGYBinaryFileHeader reel; SEGYTraceHeader *header; char *dbin; char *outfile; FILE *fp; Pf *pf; Arr *channels; /* channel order list */ Arr *table_list; /* array of valid tables */ int nchan; char *stest; float **traces; char text_file_header[SEGY_TEXT_HEADER_SIZE]; Dbptr db, trdb, dbj; Dbptr trdbss; int nsamp0; double time0, endtime0, samprate0; long int nsamp; double samprate; int i,j; char stime[30],etime[30]; char s[128]; double tlength; double phi, theta; char *newchan_standard[3]={"X1","X2","X3"}; char *trsubset="chan=~/X./"; char *newchan[3]={"R","T","Z"}; Tbl *sortkeys=newtbl(0); char sta[10],chan[10]; double lat, lon, elev, dnorth, deast, edepth; char segtype; char refsta[10]; int total_traces=0; char *time_str; long int evid,shotid=1; int rotate=0; long int ntraces; int ichan; int map_to_cdp; /* logical switch to output data like cdp stacked data */ char *fmt="%Y %j %H %M %S %s"; char *pfname; int Verbose=0; /* New features added 2009 */ /* this is a boolean. If true (nonzero) it is assumed stdin will contain four numbers: time,lat, lon, elev. If false, only the time field is read and remainder of any input on each line is dropped.*/ int input_source_coordinates; /* scale factor for source coordinates. Needed because segy uses an int to store source coordinates. Sensible choices are 3600 for arc seconds and 10000 for a pseudodecimal. Note this parameter is ignored unless input_source_coordinates is true.*/ int coordScale; /* If true use passcal 32 bit extension num_samps as record length. SEGY standard uses a 16 bit entry that easily overflows with large shots at long offset. In this ase assume the 16 bit quantity is meaningless. */ int use_32bit_nsamp; /* This is switched on by argument switch. When set to a nonzero (default) the reel headers are written. When 0 ` the reel headers will not be written -- used by seismic unix and passcal*/ int write_reel_headers=1; /* SEG-Y version to output. Default is original 1975 spec (rev 0) */ int16_t segy_format = SEGY_FORMAT_REV_0; /* dbsubset query string */ char *substr=NULL; /* text_header_description is a buffer holding a user-supplied description * to be placed in the 3200-byte text header block. It is controlled by * the parameter file value text_header_description or by the -d command * line option, with the latter taking precedence */ char* text_header_description=NULL; if(argc < 3) usage(); dbin = argv[1]; outfile = argv[2]; pfname = NULL; for(i=3;i<argc;++i) { if(!strcmp(argv[i],"-pf")) { ++i; pfname = argv[i]; } else if(!strcmp(argv[i],"-SU")) { write_reel_headers=0; } else if(!strcmp(argv[i],"-v")) { Verbose=1; } else if(!strcmp(argv[i],"-d")) { ++i; text_header_description = strdup(argv[i]); } else if(!strcmp(argv[i],"-ss")) { ++i; substr=argv[i]; } else if(!strcmp(argv[i],"-V")) { ++i; if (!strcmp(argv[i],"0")) {segy_format = SEGY_FORMAT_REV_0;} else if(!strcmp(argv[i],"1")) {segy_format = SEGY_FORMAT_REV_1_0;} else if(!strcmp(argv[i],"SU")) { segy_format = SEGY_FORMAT_SU; write_reel_headers=0; } else { elog_complain(0, "SEG-Y Version must be either 1 or 0"); usage(); } } else { usage(); } } /* Command-line parameter sanity checking */ if (write_reel_headers==0 && segy_format != SEGY_FORMAT_SU){ complain(0, "The SU option cannot be used with the -V option"); usage(); } if(pfname == NULL) pfname = strdup("db2segy"); elog_init(argc, argv); if(pfread(pfname,&pf)) { elog_die(0,"pfread error for pf file %s.pf\n",argv[0]); } /* Read the text_header_description if we weren't passed the -d option */ if (!text_header_description) { text_header_description=pfget_string(pf, "text_header_description"); } /* rotation parameters */ rotate=pfget_boolean(pf,"rotate"); if(rotate) { phi = pfget_double(pf,"phi"); theta = pfget_double(pf,"theta"); } /* This function creates the channel order list keyed by station channel names */ channels = build_stachan_list(pf,&nchan,Verbose); map_to_cdp = pfget_boolean(pf,"map_to_cdp"); if(map_to_cdp && Verbose) elog_notify(0,"Casting data as CDP stacked section\n"); if(dbopen(dbin,"r",&db) == dbINVALID) { elog_complain(1,"Cannot open db %s\n", dbin); usage(); } /* We grab the sample rate and trace length (in seconds) and use this to define global sample rates for the data. SEG-Y REV0 REQUIRES fixed length records and sample rates, so irregular sample rates will cause this program to die. One could add a decimate/interpolate function, but this is not currently implemented */ samprate0 = pfget_double(pf,"sample_rate"); tlength = pfget_double(pf,"trace_length"); nsamp0 = (int)(tlength*samprate0); use_32bit_nsamp=pfget_boolean(pf,"use_32bit_nsamp"); if (ntohs(segy_format) >= 0x0100 && use_32bit_nsamp) { elog_complain(0,"The 32-bit extension field is incompatible with SEG-Y REV 1. Ignoring 'use_32bit_nsamp' from the parameter file"); use_32bit_nsamp=0; } /* nsamp in segy is a 16 bit field. Handling depends on setting of use_32bit_nsamp boolean */ if(nsamp0 > SEGY_MAX_NSAMP) { if(use_32bit_nsamp) { elog_notify(0,"Warning: segy uses a 16 bit entity to store number of samples\nThat field is garbage. Using the 32 bit extension field."); } else { elog_complain(0, "Warning: segy uses a 16 bit entity to store number of samples. Requested %d samples per trace. Trucated to %d", nsamp0, SEGY_MAX_NSAMP); nsamp0 = SEGY_MAX_NSAMP; } } /* boolean. When nonzero set coordinates as geographic arc seconds values */ int use_geo_coordinates=pfget_boolean(pf,"use_geo_coordinates"); /* boolean. When nonzero, output decimal degrees instead of arcseconds if * the requested output format supports it (rev1 only) */ int prefer_decimal_degrees=pfget_boolean(pf, "prefer_decimal_degrees"); /* We now have enough information to decide the coordUnits for all traces */ int coordUnits = 0; if (!use_geo_coordinates) { coordUnits=SEGY_TRACE_COORDUNITS_LENGTH; } else if (ntohs(segy_format) >= 0x0100 && prefer_decimal_degrees) { coordUnits=SEGY_TRACE_COORDUNITS_DECIMAL_DEGREES; } else { coordUnits=SEGY_TRACE_COORDUNITS_ARCSECONDS; } /* We should have set our coordinate units now */ assert(coordUnits!=0); input_source_coordinates=pfget_boolean(pf,"input_source_coordinates"); if(input_source_coordinates) { coordScale=pfget_int(pf,"coordinate_scale_factor"); } else if (coordUnits==SEGY_TRACE_COORDUNITS_DECIMAL_DEGREES) { /* Use a sane scalar for decimal degrees. 10000 gives four decimal * places of accuracy, which matches the CSS3.0 spec for lat and lon */ coordScale=10000; } else { coordScale=1; } /* Print a diagnostic message if the user gave a sub-optimal value for the * coordScale */ if (coordUnits == SEGY_TRACE_COORDUNITS_DECIMAL_DEGREES && coordScale < 10000) { elog_alert(0, "The supplied parameter 'coordinate_scale_factor' value of %d is less than 10000, and will cause loss of precision for decimal degree coordinates.", coordScale); } else if (coordUnits == SEGY_TRACE_COORDUNITS_ARCSECONDS) { if (coordScale > 1000) { elog_alert(0, "The supplied parameter 'coordinate_scale_factor' value of %d is greater than 1000, and will cause loss of precision for arcsecond coordinates.", coordScale); } } /* trace_gain_type: signed int */ int16_t trace_gain_type = pfget_int(pf,"trace_gain_type"); if (trace_gain_type < 0) { die(0, "The trace_gain_type must be zero or greater"); } else { trace_gain_type=htons(trace_gain_type); } /* check list of tables defined in pf. Return array of logicals that define which tables are valid and join tables. */ table_list = check_tables(db,pf); check_for_required_tables(table_list); dbj = join_tables(db,pf,table_list); if(dbj.record == dbINVALID) elog_die(0,"dbjoin error\n"); if(substr!=NULL) dbj=dbsubset(dbj,substr,0); long int ndbrows; dbquery(dbj,dbRECORD_COUNT,&ndbrows); if(ndbrows<=0) { elog_complain(1,"Working database view is empty\n"); if(substr!=NULL) elog_complain(0,"Subset condtion =%s a likely problem\n", substr); usage(); } fp = fopen(outfile,"w"); if(fp == NULL) { elog_complain(0,"Cannot open output file %s\n",outfile); usage(); } /* These are needed for sort below */ pushtbl(sortkeys,"sta"); pushtbl(sortkeys,"chan"); /* Set up and write the Textual File Header */ initialize_text_header(text_file_header, segy_format, text_header_description); if(write_reel_headers){ if ( fwrite(text_file_header,1,SEGY_TEXT_HEADER_SIZE,fp) \ != SEGY_TEXT_HEADER_SIZE ) { elog_die(1,"An error occurred writing the textual file header"); } } /* memory allocation for trace data. This is a large matrix that is cleared for each event. This model works because of segy's fixed length format.*/ traces = calloc(nchan, sizeof(float*)); if(traces == NULL) elog_die(1,"out of memory"); for (int r = 0; r < nchan; r++) { traces[r] = calloc(nsamp0, sizeof(float)); if(traces[r] == NULL) elog_die(1,"out of memory"); } header = (SEGYTraceHeader *)calloc((size_t)nchan,sizeof(SEGYTraceHeader)); if(header == NULL) elog_die(0,"Cannot alloc memory for %d segy header workspace\n",nchan); if(write_reel_headers) { if (Verbose) { elog_debug(0,"Binary Headers - Using segy_format code 0x%04X\n", ntohs(segy_format)); } initialize_binary_file_header(&reel, segy_format); /* now fill in the binary reel header and write it */ reel.kjob = htonl(1); reel.kline = htonl(1); reel.kreel = htonl(1); reel.kntr = htons((int16_t)nchan); reel.knaux = htons(0); reel.sr = htons((int16_t)(1000000.0/samprate0)); reel.kfldsr = reel.sr; reel.knsamp = htons((int16_t)nsamp0); reel.kfsamp = htons((int16_t)nsamp0); reel.dsfc = htons(5); /* This is ieee floats*/ reel.kmfold = htons(0); if(map_to_cdp) reel.ksort = htons(2); else reel.ksort = htons(1); reel.kunits = htons(1); /* This sets units to always be meters */ if(fwrite((void *)(&reel),sizeof(SEGYBinaryFileHeader),1,fp) != 1) { elog_die(1,"Write error for binary reel header"); } } /* Now we enter a loop over stdin reading start times. Program will blindly ask for data from each start time to time+tlength. The trace buffer will be initialized to zeros at the top of the loop always. If nothing is found only zeros will be written to output. */ while((stest=fgets(s,80,stdin)) != NULL) { double slat,slon,selev; /* Used when reading source location*/ if(Verbose) elog_notify(0,"Processing: %s\n",s); for(i=0;i<nchan;++i) { initialize_trace_header(&(header[i]), segy_format); header[i].gainType = trace_gain_type; header[i].lineSeq = htonl(total_traces + i + 1); header[i].reelSeq = header[i].lineSeq; if(map_to_cdp) { header[i].cdpEns = htonl(i + 1); header[i].traceInEnsemble = htonl(1);/* 1 trace per cdp faked */ } else { header[i].channel_number = htonl(i + 1); } header[i].event_number = htonl(shotid); header[i].energySourcePt = htonl(shotid); for(j=0;j<nsamp0;++j) traces[i][j] = htonf((Trsample)0.0); } if(input_source_coordinates) { char stmp[40]; sscanf(s,"%s%ld%lf%lf%lf",stmp,&shotid,&slon,&slat,&selev); time0=str2epoch(stmp); if(coordUnits == SEGY_TRACE_COORDUNITS_ARCSECONDS) { slat*=3600.0; slon*=3600.0; } slat *= (double)coordScale; slon *= (double)coordScale; } else { time0 = str2epoch(s); } endtime0 = time0 + tlength; sprintf(stime,"%20.4f",time0); sprintf(etime,"%20.4f",endtime0); trdb.database = -1; if(trload_css(dbj,stime,etime,&trdb,0, 0) < 0) { if(Verbose) { elog_notify(0,"trload_css failed for shotid=%ld",shotid); elog_notify(0," No data in time range %s to %s\n", strtime(time0),strtime(endtime0) ); elog_notify(0,"No data written for this shotid block."); elog_notify(0," Handle this carefully in geometry definitions.\n"); } continue; } /* This does gap processing */ repair_gaps(trdb); trapply_calib(trdb); if(rotate) { if(rotate_to_standard(trdb,newchan_standard)) elog_notify(0,"Data loss in rotate_to_standard for event %s to %s\n", stime, etime); /* This is need to prevent collisions of channel names */ trdbss = dbsubset(trdb,trsubset,0); if(trrotate(trdbss,phi,theta,newchan)) elog_notify(0,"Data loss in trrotate for event %s to %s\n", stime, etime); } if(Verbose) elog_notify(0,"Station chan_name chan_number seq_number shotid evid\n"); trdb = dbsort(trdb,sortkeys,0,0); dbquery(trdb,dbRECORD_COUNT,&ntraces); if(Verbose) elog_debug(0,"Read %ld traces for event at time%s\n", ntraces,strtime(time0)); for(trdb.record=0;trdb.record<ntraces;++trdb.record) { Trsample *trdata; if(dbgetv(trdb,0, "evid",&evid, "sta",sta, "chan",chan, "nsamp", &nsamp, "samprate",&samprate, "data",&trdata, "lat", &lat, "lon", &lon, "elev",&elev, "refsta",refsta, "dnorth",&dnorth, "deast",&deast, "edepth",&edepth, "segtype",&segtype, NULL) == dbINVALID) { elog_complain(0," dbgetv error reading record %ld. Trace will be skipped for station %s and channel %s", trdb.record,sta,chan); continue; } /* Allow 1 percent samprate error before killing */ double fsrskew=fabs((samprate-samprate0)/samprate0); double frskewcut=0.01; if(fsrskew>frskewcut) { elog_complain(0,"%s:%s sample rate %f is significantly different from base sample rate of %f. Trace skipped -- segy requires fixed sample rates", sta,chan,samprate,samprate0); continue; } if(nsamp > nsamp0) { elog_complain(0,"%s:%s trace has extra samples=%ld. Truncated to length %d", sta, chan, nsamp, nsamp0); nsamp = nsamp0; } else if(nsamp < nsamp0) { elog_complain(0,"%s:%s trace is shorter than expected %d samples. Zero padded after sample %ld", sta, chan, nsamp0, nsamp); } ichan = get_channel_index(channels,sta,chan); if(ichan > nchan) { elog_die(0,"Channel index %d outside limit of %d. Cannot continue", ichan, nchan); } if(ichan >= 0) { if(Verbose) elog_debug(0,"%s:%s\t%-d\t%-d\t%-ld\t%-ld\n", sta,chan,ichan+1, ntohl(header[ichan].reelSeq), shotid, evid); header[ichan].traceID = get_trace_id_code_from_segtype(segtype); for(j=0;j<nsamp;++j) { traces[ichan][j] = htonf((float)trdata[j]); } /* header fields coming from trace table */ header[ichan].samp_rate = htonl( (int32_t) (1000000.0/samprate0)); /* according to the behavior specified in the man page: * if use_geo_coordinates is false: * - coordUnits is length (meters) * - therefore, we use deast for X and dnorth for Y * if use_geo_coordinates is true: * - we're using either arcseconds or decimal degrees * - and therefore, we use lon for X and lat for Y * * coordUnits is based on use_arcseconds and the requested * version of segY */ /* set the coordinate units in the trace header */ header[ichan].coordUnits = coordUnits; /* Pick the source db fields for our receiver X and Y */ double recLongOrX = 0; double recLatOrY = 0; if (coordUnits == SEGY_TRACE_COORDUNITS_LENGTH) { /* Use deast and dnorth * CSS3.0 Schema specifies deast and dnorth are in KM. * SEG-Y specifies easting and northing as meters, * hence the 1000.0 multiplier here. */ recLongOrX = deast * 1000.0; recLatOrY = dnorth * 1000.0; } else if (coordUnits == SEGY_TRACE_COORDUNITS_ARCSECONDS){ /* Use lat and lon, converted to arcseconds */ recLongOrX = lon * 3600.0; recLatOrY = lat * 3600.0; } else { /* Default case, which covers decimal degrees */ recLongOrX = lon; recLatOrY = lat; } /* Apply our coordScale - the user can specify negative numbers, * but they are treated as inverting the value, not as a divisor * as in the SEG-Y field usage. See below where we always treat * the scalar as a divisor in the SEG-Y field */ recLongOrX *= (double)coordScale; recLatOrY *= (double)coordScale; /* Set the coordScale in the header. * Note negative here. This is a oddity of segy that - means * divide by this to get actual. Always make this negative in * case user inputs a negative number. * Don't set it -1 for cosmetic reasons */ if (abs(coordScale) == 1) { header[ichan].coordScale = htons(1); } else { header[ichan].coordScale = htons(-abs(coordScale)); } /* Finally, write out the X and Y */ header[ichan].recLongOrX = htonl((int32_t)recLongOrX); header[ichan].recLatOrY = htonl((int32_t)recLatOrY); /* CSS3.0 specfies elev as being in km, SEG-Y wants it in m */ header[ichan].recElevation = htonl((int32_t)(elev*1000.0)); header[ichan].deltaSample = htons( (int16_t) (1000000.0/samprate0)); header[ichan].sampleLength = htons((int16_t)nsamp0); if (ntohs(segy_format)<0x0100) { header[ichan].num_samps = htonl((int32_t)nsamp0); } /* This cracks the time fields */ time_str = epoch2str(time0,fmt); int16_t hyear, hday, hhour, hminute, hsecond, hm_secs; hyear=hday=hhour=hminute=hsecond=hm_secs=0; sscanf(time_str,"%hd %hd %hd %hd %hd %hd", &hyear, &hday, &hhour, &hminute, &hsecond, &hm_secs); header[ichan].year = htons(hyear); header[ichan].day = htons(hday); header[ichan].hour = htons(hhour); header[ichan].minute = htons(hminute); header[ichan].second = htons(hsecond); header[ichan].m_secs = htons(hm_secs); if (ntohs(segy_format)<0x0100) { /* These are IRIS-PASSCAL extensions */ header[ichan].trigyear = header[ichan].year; header[ichan].trigday = header[ichan].day; header[ichan].trighour = header[ichan].hour; header[ichan].trigminute = header[ichan].minute; header[ichan].trigsecond = header[ichan].second; } free(time_str); if(input_source_coordinates) { /* Write out our pre-scaled and optionally * arcsecond-converted source lat/lon plus our elevation */ header[ichan].sourceLongOrX = htonl((int32_t)slon); header[ichan].sourceLatOrY = htonl((int32_t)slat); header[ichan].sourceSurfaceElevation = htonl((int32_t)selev); /* No easy way to specify both elev and depth*/ header[ichan].sourceDepth=htonl(0); } else if(map_to_cdp) { /* When faking CDP data we make this look like a zero offset, single fold data set */ header[ichan].sourceLongOrX = header[ichan].recLongOrX; header[ichan].sourceLatOrY = header[ichan].recLatOrY; header[ichan].sourceSurfaceElevation = header[ichan].recElevation; header[ichan].sourceDepth = htonl(0); header[ichan].sourceToRecDist = htonl(0); } else { /* This is the mechanism for adding other information with added tables. The one table currently supported is a "shot" table that holds shot coordinates. If other tables were added new functions could be added with a similar calling sequence. This procedure silently does nothing if a shot table is not present.*/ set_shot_variable(db,table_list, evid,&header[ichan]); } } else { if(Verbose) elog_notify(0,"Station %s and channel %s skipped\n", sta,chan); } } /* Now we write the data */ for(i=0;i<nchan;++i) { if(fwrite((void *)(&(header[i])),sizeof(SEGYTraceHeader),1,fp) != 1) elog_die(0,"Write error on header for trace %d\n",total_traces+i); if(fwrite((void *)traces[i],sizeof(float), (size_t)nsamp0,fp) != nsamp0) elog_die(0,"Write error while writing data for trace %d\n", total_traces+i); } total_traces += nchan; trdestroy(&trdb); if(!input_source_coordinates) ++shotid; } return 0 ; }
void mexFunction ( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { Dbptr db; Tbl *tbl; char **sortfields; char errmsg[STRSZ]; int i, arg_index, nvarargs; int flags = 0; int rc; if( nrhs < 1 ) { antelope_mexUsageMsgTxt ( USAGE ); return; } else if( ! get_dbptr( prhs[0], &db ) ) { antelope_mexUsageMsgTxt ( USAGE ); return; } nvarargs = nrhs - 1; for( i = 0; i<nvarargs; i++) { arg_index = i + 1; if( mxGetClassID( prhs[arg_index] ) != mxCHAR_CLASS ) { antelope_mexUsageMsgTxt ( USAGE ); return; } } if( nvarargs > 0 ) { tbl = newtbl( nvarargs ); sortfields = (char **) mxCalloc( nvarargs, sizeof( char * ) ); for( i = 0; i < nvarargs; i++ ) { arg_index = i + 1; get_malloced_string( prhs[arg_index], &sortfields[i] ); if( STREQ( sortfields[i], "dbSORT_UNIQUE" ) ) { flags |= dbSORT_UNIQUE; } else if( STREQ( sortfields[i], "dbSORT_REVERSE" ) ) { flags |= dbSORT_REVERSE; } else { pushtbl( tbl, sortfields[i] ); } } } else { rc = dbquery ( db, dbPRIMARY_KEY, &tbl ); antelope_mex_clear_register( 1 ); if( rc == dbINVALID ) { mexErrMsgTxt( "dbsort: query for primary keys failed" ); } } db = dbsort ( db, tbl, flags, 0) ; antelope_mex_clear_register( 1 ); if( nvarargs > 0 ) { for( i = 0; i < nvarargs; i++ ) { mxFree( sortfields[i] ); } mxFree( sortfields ); freetbl( tbl, 0 ); } if( db.table == dbINVALID ) { mexErrMsgTxt( "dbsort failed" ); } plhs[0] = CreateDbptrStructFromDbptr( db ); if( plhs[0] == NULL ) { sprintf( errmsg, "dbsort: failed to create database-pointer " ); strcat( errmsg, "structure for result" ); mexErrMsgTxt( errmsg ); } }
int read_dec_files (Tbl *decdef, int *dec_fac, Tbl **decimators) { int i, j, n; Response *rsp; char string[512]; FILE *file; FIR_decimation *decptr; Response *resp; resp = (Response *) new_response (); if(*decimators == NULL) *decimators = newtbl(0); if (resp == NULL) { elog_die(0, "read_dec_files: Malloc error on decimation response structure.\n"); return (0); } for (i=0,(*dec_fac)=1; i<maxtbl(decdef); i++) { int ok; char *decfile; decfile = gettbl(decdef,i); if(!strcmp(decfile,"none") ) { *dec_fac = 1.0; decptr = (FIR_decimation *) malloc(sizeof(FIR_decimation)); if(decptr == NULL) { elog_notify(0,"Cannot malloc decimation structure for stage %d\n", i); return(0); } decptr->decfac = 1.0; decptr->ncoefs = 0; decptr->coefs=NULL; pushtbl(*decimators,decptr); return(2); } file = fopen(decfile, "r"); if (file == NULL) { elog_notify(0, "read_dec_files: Unable to open response stage file '%s'.\n", decfile); return (0); } if (read_response (file, &rsp)) { elog_clear_register(1); elog_notify(0, "read_dec_files: read_response() error on stage file '%s'.\n", decfile); return (0); } fclose (file); get_response_nstages (rsp, &n); for (j=0,ok=0; j<n; j++) { int dec_factor, nnum, nden; double srate; get_response_stage_type (rsp, j, string); if (strcmp(string, "fir")) continue; get_response_stage_fir_ncoefs (rsp, j, &srate, &dec_factor, &nnum, &nden); if (nden > 1) { elog_notify(0, "read_dec_files: Dont know how to do IIR filters (%s).\n", decfile); return (0); } if (nnum < 1) { elog_notify(0, "read_dec_files: No numerator terms (%s).\n", decfile); return (0); } ok=1; (*dec_fac) *= dec_factor; } if (!ok) { elog_notify(0, "read_dec_files: no fir stage on file '%s'.\n", decfile); return (0); } for (j=0; j<n; j++) { Response_group *gpi; get_response_stage_type (rsp, j, string); if (strcmp(string, "fir")) continue; gpi = rsp->groups + j; if (copy_response_group (gpi, (resp), -1) < 0) { elog_notify(0, "read_dec_files: copy_response_group() error.\n"); return (0); } } free_response (rsp); } get_response_nstages ((resp), &n); for (i=0; i<n; i++) { Response_group *gpi; int dec_factor, nnum, nden; double srate; double *coefsi, *coefs_err; double *coefdi, *coefd_err; decptr = (FIR_decimation *) malloc(sizeof(FIR_decimation)); if(decptr == NULL) { elog_notify(0,"Cannot malloc decimation structure for stage %d\n", i); return(0); } gpi = (resp)->groups + i; get_response_stage_fir_ncoefs ((resp), i, &srate, &dec_factor, &nnum, &nden); get_response_stage_fir_coefs ((resp), i, &nnum, &coefsi, &coefs_err, &nden, &coefdi, &coefd_err); for (j=0; j<nnum/2; j++) if (coefsi[j] != coefsi[nnum-j-1]) break; if (j < nnum/2) { elog_notify(0, "read_dec_files: Can only do symetrical FIR filters.\n"); return (0); } decptr->ncoefs = nnum; decptr->decfac = dec_factor; decptr->coefs = calloc(nnum,sizeof(float)); if((decptr->coefs) == NULL) elog_die(0,"read_dec_files: can't alloc filter coef array of length %d\n",nnum); for(j=0; j<nnum; j++) decptr->coefs[j] = coefsi[j]; pushtbl(*decimators,decptr); } return (1); }
int main (int argc, char **argv) { int c; int errflg = 0; Dbptr db; char *database; int verbose = 0; int primary = 0; Pf pf; char *xmlstring = 0; char *rootname = 0; char *rowname = 0; Tbl *fields = 0; Tbl *expressions = 0; elog_init( argc, argv ) ; while ((c = getopt (argc, argv, "pd:r:v")) != -1) { switch (c) { case 'v': verbose++; break; case 'd': rootname = strdup( optarg ); break; case 'p': primary++; break; case 'r': rowname = strdup( optarg ); break; default: errflg++; break ; } } if( errflg || argc - optind < 1 || (((argc-optind) % 2) != 1)) { usage (); } database = argv[optind++]; if( dbopen_table( database, "r+", &db ) < 0 ) { die( 0, "Can't open database %s\n", database ); } if( argc - optind > 0 ) { fields = newtbl( 20 ); expressions = newtbl( 20 ); while( argc - optind > 0 ) { pushtbl( fields, argv[optind++] ); pushtbl( expressions, argv[optind++] ); } if( primary ) { complain( 1, "Useless use of '-p' with specified expressions\n" ); } } else if( primary ) { dbquery( db, dbPRIMARY_KEY, (Dbvalue *) &fields ); } db2ptolemy( db, fields, expressions, (void **) &xmlstring, 0 ); if( xmlstring != NULL ) { fwrite( xmlstring, sizeof(char), strlen( xmlstring ), stdout ); free( xmlstring ); } return 0; }
int main (int argc, char **argv) { int c; int errflg = 0; Dbptr db; char *database; int verbose = 0; int primary = 0; Pf *pf = NULL; char *xmlstring = NULL; char *rootname = NULL; char *rowname = NULL; char *stylesheet = NULL; char xslt_processor[STRSZ]; char command[STRSZ]; char tempfile[FILENAME_MAX]; FILE *tempfs = NULL; Tbl *fields = 0; Tbl *expressions = 0; int rc; int flags = 0; elog_init( argc, argv ) ; while ((c = getopt (argc, argv, "pd:r:t:v")) != -1) { switch (c) { case 'v': verbose++; break; case 't': stylesheet = strdup( optarg ); break; case 'd': rootname = strdup( optarg ); break; case 'p': primary++; break; case 'r': rowname = strdup( optarg ); break; default: errflg++; break ; } } if( errflg || argc - optind < 1 || (((argc-optind) % 2) != 1)) { usage (); } pfread( "db2xml", &pf ); database = argv[optind++]; if( dbopen_table( database, "r+", &db ) < 0 ) { elog_die( 0, "Can't open database %s\n", database ); } if( argc - optind > 0 ) { fields = newtbl( 20 ); expressions = newtbl( 20 ); while( argc - optind > 0 ) { pushtbl( fields, argv[optind++] ); pushtbl( expressions, argv[optind++] ); } if( primary ) { elog_complain( 1, "Useless use of '-p' with specified expressions, ignoring\n" ); } } else if( primary ) { flags |= DBXML_PRIMARY; } rc = db2xml( db, rootname, rowname, fields, expressions, (void **) &xmlstring, flags ); if( rc < 0 || xmlstring == NULL ) { elog_clear_register( 1 ); elog_die( 0, "db2xml failed\n" ); } else if( stylesheet != NULL ) { sprintf( tempfile, "/tmp/db2xml_%d_%d.xml", getuid(), getpid() ); tempfs = fopen( tempfile, "w" ); fwrite( xmlstring, sizeof(char), strlen( xmlstring ), tempfs ); fclose( tempfs ); sprintf( xslt_processor, "%s", pfget_string( pf, "xslt_processor" ) ); strsub( xslt_processor, "STYLESHEET", stylesheet, xslt_processor ); strsub( xslt_processor, "XMLFILE", tempfile, command ); system( command ); unlink( tempfile ); } else { fwrite( xmlstring, sizeof(char), strlen( xmlstring ), stdout ); } free( xmlstring ); return 0; }
int main(int argc, char **argv) { SegyReel reel; SegyHead *header; char *dbin; char *outfile; FILE *fp; Pf *pf; Arr *channels; /* channel order list */ Arr *table_list; /* array of valid tables */ int nchan; char *stest; float **traces; char reel1[3200]; Dbptr db, trdb, dbj; Dbptr trdbss; int nsamp0; double time0, endtime0, samprate0; long int nsamp; double samprate; int i,j; char stime[30],etime[30]; char s[128]; double tlength; double phi, theta; char *newchan_standard[3]={"X1","X2","X3"}; char *trsubset="chan=~/X./"; char *newchan[3]={"R","T","Z"}; Tbl *sortkeys=newtbl(0); char sta[10],chan[10]; double lat, lon, elev, dnorth, deast, edepth; char refsta[10]; int total_traces=0; char *time_str; long int evid,shotid=1; int rotate=0; long int ntraces; int ichan; int map_to_cdp; /* logical switch to output data like cdp stacked data */ char *fmt="%Y %j %H %M %S %s"; char *pfname; int Verbose=0; /* New features added 2009 */ /* this is a boolean. If true (nonzero) it is assumed stdin will contain four numbers: time,lat, lon, elev. If false, only the time field is read and remainder of any input on each line is dropped.*/ int input_source_coordinates; /* scale factor for source coordinates. Needed because segy uses an int to store source coordinates. Sensible choices are 3600 for arc seconds and 10000 for a pseudodecimal. Note this parameter is ignored unless input_source_coordinates is true.*/ int coordScale; /* If true use passcal 32 bit extension num_samps as record length. SEGY standard uses a 16 bit entry that easily overflows with large shots at long offset. In this ase assume the 16 bit quantity is meaningless. */ int use_32bit_nsamp; /* This is switched on by argument switch. When set to a nonzero (default) the reel headers are written. When 0 ` the reel heades will not be written -- used by seismic unix r and passcal*/ int write_reel_headers=1; char *substr=NULL; if(argc < 3) usage(); dbin = argv[1]; outfile = argv[2]; pfname = NULL; for(i=3;i<argc;++i) { if(!strcmp(argv[i],"-pf")) { ++i; pfname = argv[i]; } else if(!strcmp(argv[i],"-SU")) { write_reel_headers=0; } else if(!strcmp(argv[i],"-v")) { Verbose=1; } else if(!strcmp(argv[i],"-ss")) { ++i; substr=argv[i]; } else { usage(); } } if(pfname == NULL) pfname = strdup("db2segy"); elog_init(argc, argv); if(pfread(pfname,&pf)) elog_die(0,"pfread error for pf file %s.pf\n",argv[0]); /* rotation parameters */ rotate=pfget_boolean(pf,"rotate"); if(rotate) { phi = pfget_double(pf,"phi"); theta = pfget_double(pf,"theta"); } /* This function creates the channel order list keyed by station channel names */ channels = build_stachan_list(pf,&nchan,Verbose); map_to_cdp = pfget_boolean(pf,"map_to_cdp"); if(map_to_cdp && Verbose) fprintf(stdout,"Casting data as CDP stacked section\n"); if(dbopen(dbin,"r",&db) == dbINVALID) { fprintf(stderr,"Cannot open db %s\n", dbin); usage(); } /* We grab the sample rate and trace length (in seconds) and use this to define global sample rates for the data. segy REQUIRES fixed length records and sample rates, so irregular sample rates will cause this program to die. One could add a decimate/interpolate function, but this is not currently implemented */ samprate0 = pfget_double(pf,"sample_rate"); tlength = pfget_double(pf,"trace_length"); nsamp0 = (int)(tlength*samprate0); use_32bit_nsamp=pfget_boolean(pf,"use_32bit_nsamp"); /* nsamp in segy is a 16 bit field. Handling depends on setting of use_32bit_nsamp boolean */ if(nsamp0 > 32767) { if(use_32bit_nsamp) { elog_notify(0,"Warning: segy ues a 16 bit entity to store number of samples\nThat field is garbage. Using the 32 bit extension field.\n"); } else { elog_complain(0, "Warning: segy uses a 16 bit entity to store number of samples\nRequested %d samples per trace. Trucated to 32767\n",nsamp0); nsamp0 = 32767; } } input_source_coordinates=pfget_boolean(pf,"input_source_coordinates"); if(input_source_coordinates) { coordScale=pfget_int(pf,"coordinate_scale_factor"); } else { coordScale=1; } /* boolean. When nonzero set coordinates as geographic arc seconds values */ int use_geo_coordinates=pfget_boolean(pf,"use_geo_coordinates"); /* check list of tables defined in pf. Return array of logicals that define which tables are valid and join tables. */ table_list = check_tables(db,pf); check_for_required_tables(table_list); dbj = join_tables(db,pf,table_list); if(dbj.record == dbINVALID) elog_die(0,"dbjoin error\n"); if(substr!=NULL) dbj=dbsubset(dbj,substr,0); long int ndbrows; dbquery(dbj,dbRECORD_COUNT,&ndbrows); if(ndbrows<=0) { fprintf(stderr,"Working database view is empty\n"); if(substr!=NULL) fprintf(stderr,"Subset condtion =%s a likely problem\n", substr); usage(); } fp = fopen(outfile,"w"); if(fp == NULL) { fprintf(stderr,"Cannot open output file %s\n",outfile); usage(); } /* These are needed for sort below */ pushtbl(sortkeys,"sta"); pushtbl(sortkeys,"chan"); /*The reel1 header in true blue segy is ebcdic. We are goingto just fill it with nulls and hope for the best */ for(i=0;i<3200;i++) reel1[i] = '\0'; /* Just blindly write this turkey. Bad form, but tough*/ if(write_reel_headers) fwrite(reel1,1,3200,fp); /* memory allocation for trace data. This is a large matrix that is cleared for each event. This model works because of segy's fixed length format. This routine is a descendent of numerical recipes routine found in libgenloc. This is not the most efficient way to do this, but it simplifies the algorithm a lot. */ traces = matrix(0,nchan,0,nsamp0); if(traces == NULL) elog_die(0,"Cannot alloc trace data matrix work space of size %d by %d\n", nchan, nsamp0); header = (SegyHead *)calloc((size_t)nchan,sizeof(SegyHead)); if(header == NULL) elog_die(0,"Cannot alloc memory for %d segy header workspace\n",nchan); if(write_reel_headers) { /* now fill in the binary reel header and write it */ reel.kjob = 1; reel.kline = 1; reel.kreel = 1; reel.kntr = (int16_t)nchan; reel.knaux = 0; reel.sr = (int16_t)(1000000.0/samprate0); reel.kfldsr = reel.sr; reel.knsamp = (int16_t)nsamp0; reel.kfsamp = (int16_t)nsamp0; reel.dsfc=5; /* This is ieee floats*/ reel.kmfold = 0; if(map_to_cdp) reel.ksort = 2; else reel.ksort = 1; reel.kunits = 1; /* This sets units to always be meters */ for(i=0;i<344;++i)reel.unused2[i]='\0'; if(fwrite((void *)(&reel),sizeof(SegyReel),1,fp) != 1) { fprintf(stderr,"Write error for binary reel header\n"); exit(-2); } } /* Now we enter a loop over stdin reading start times. Program will blindly ask for data from each start time to time+tlength. The trace buffer will be initialized to zeros at the top of the loop always. If nothing is found only zeros will be written to output. */ while((stest=fgets(s,80,stdin)) != NULL) { double slat,slon,selev; /* Used when reading source location*/ if(Verbose) fprintf(stdout,"Processing: %s\n",s); for(i=0;i<nchan;++i) { initialize_header(&(header[i])); header[i].lineSeq = total_traces + i + 1; header[i].reelSeq = header[i].lineSeq; if(map_to_cdp) { header[i].cdpEns = i + 1; header[i].traceInEnsemble = 1; /* 1 trace per cdp faked */ } else { header[i].channel_number = i + 1; } header[i].event_number = shotid; header[i].energySourcePt=shotid; for(j=0;j<nsamp0;++j) traces[i][j] = (Trsample)0.0; } if(input_source_coordinates) { char stmp[40]; sscanf(s,"%s%ld%lf%lf%lf",stmp,&shotid,&slon,&slat,&selev); time0=str2epoch(stmp); } else { time0 = str2epoch(s); } endtime0 = time0 + tlength; sprintf(stime,"%20.4f",time0); sprintf(etime,"%20.4f",endtime0); trdb.database = -1; if(trload_css(dbj,stime,etime,&trdb,0, 0) < 0) { if(Verbose) { fprintf(stdout,"trload_css failed for shotid=%ld",shotid); fprintf(stdout," No data in time range %s to %s\n", strtime(time0),strtime(endtime0) ); fprintf(stdout,"No data written for this shotid block."); fprintf(stdout," Handle this carefully in geometry definitions.\n"); } continue; } /* This does gap processing */ repair_gaps(trdb); trapply_calib(trdb); if(rotate) { if(rotate_to_standard(trdb,newchan_standard)) elog_notify(0,"Data loss in rotate_to_standard for event %s to %s\n", stime, etime); /* This is need to prevent collisions of channel names */ trdbss = dbsubset(trdb,trsubset,0); if(trrotate(trdbss,phi,theta,newchan)) elog_notify(0,"Data loss in trrotate for event %s to %s\n", stime, etime); } if(Verbose) fprintf(stdout,"Station chan_name chan_number seq_number shotid evid\n"); trdb = dbsort(trdb,sortkeys,0,0); dbquery(trdb,dbRECORD_COUNT,&ntraces); if(Verbose) fprintf(stdout,"Read %ld traces for event at time%s\n", ntraces,strtime(time0)); for(trdb.record=0;trdb.record<ntraces;++trdb.record) { Trsample *trdata; if(dbgetv(trdb,0, "evid",&evid, "sta",sta, "chan",chan, "nsamp", &nsamp, "samprate",&samprate, "data",&trdata, "lat", &lat, "lon", &lon, "elev",&elev, "refsta",refsta, "dnorth",&dnorth, "deast",&deast, "edepth",&edepth, NULL) == dbINVALID) { elog_complain(0," dbgetv error reading record %ld\nTrace will be skipped for station %s and channel %s\n", trdb.record,sta,chan); continue; } /* Allow 1 percent samprate error before killing */ double fsrskew=fabs((samprate-samprate0)/samprate0); double frskewcut=0.01; if(fsrskew>frskewcut) { elog_complain(0,"%s:%s sample rate %f is significantly different from base sample rate of %f\nTrace skipped -- segy requires fixed sample rates\n", sta,chan,samprate,samprate0); continue; } if(nsamp > nsamp0) { elog_complain(0,"%s:%s trace has extra samples=%ld\nTruncated to length %d\n", sta, chan, nsamp, nsamp0); nsamp = nsamp0; } else if(nsamp < nsamp0) { elog_complain(0,"%s:%s trace is shorter than expected %d samples\nZero padded after sample %ld\n", sta, chan, nsamp0, nsamp); } ichan = get_channel_index(channels,sta,chan); if(ichan > nchan) elog_die(0,"Channel index %d outside limit of %d\nCannot continue\n", ichan, nchan); if(ichan >= 0) { if(Verbose) fprintf(stdout,"%s:%s\t%-d\t%-d\t%-ld\t%-ld\n", sta,chan,ichan+1, header[ichan].reelSeq, shotid, evid); header[ichan].traceID = 1; for(j=0;j<nsamp;++j) traces[ichan][j] = (float)trdata[j]; /* header fields coming from trace table */ header[ichan].samp_rate = (int32_t) (1000000.0/samprate0); if(!use_geo_coordinates && ( coordScale==1)) { header[ichan].recLongOrX = (int32_t)(deast*1000.0); header[ichan].recLatOrY = (int32_t)(dnorth*1000.0); } else { /* Note negative here. This is a oddity of segy that - means divide by this to get actual. Always make this negative in case user inputs a negative number. */ header[ichan].coordScale=-abs(coordScale); /* Force 2 = geographic coordinates. Standard says when this is so units are arc seconds, hence we multiply deg by 3600*coordScale */ if(use_geo_coordinates) { header[ichan].coordUnits=2; header[ichan].recLongOrX =(int32_t)(lon*3600.0*(double)coordScale); header[ichan].recLatOrY =(int32_t)(lat*3600.0*(double)coordScale); } else { header[ichan].recLongOrX =(int32_t)(lon*(double)coordScale); header[ichan].recLatOrY =(int32_t)(lat*(double)coordScale); } } header[ichan].recElevation = (int32_t)(elev*1000.0); header[ichan].deltaSample = (int16_t) (1000000.0/samprate0); header[ichan].sampleLength = (int16_t)nsamp0; header[ichan].num_samps = (int32_t)nsamp0; /* This cracks the time fields */ time_str = epoch2str(time0,fmt); sscanf(time_str,"%hd %hd %hd %hd %hd %hd", &header[ichan].year, &header[ichan].day, &header[ichan].hour, &header[ichan].minute, &header[ichan].second, &header[ichan].m_secs); /* These are PASSCAL extensions, but we'll go ahead and set them anyway.*/ header[ichan].trigyear = header[ichan].year; header[ichan].trigday = header[ichan].day; header[ichan].trighour = header[ichan].hour; header[ichan].trigminute = header[ichan].minute; header[ichan].trigsecond = header[ichan].second; free(time_str); if(input_source_coordinates) { if(use_geo_coordinates) { slat*=3600.0; slon*=3600.0; } header[ichan].sourceLongOrX =(int32_t)(slon*(double)coordScale); header[ichan].sourceLatOrY =(int32_t)(slat*(double)coordScale); header[ichan].sourceSurfaceElevation =(int32_t)selev; /* No easy way to specify both elev and depth*/ header[ichan].sourceDepth=0; } else if(map_to_cdp) { /* When faking CDP data we make this look like a zero offset, single fold data set */ header[ichan].sourceLongOrX = header[ichan].recLongOrX; header[ichan].sourceLatOrY = header[ichan].recLatOrY; header[ichan].sourceSurfaceElevation = header[ichan].recElevation; header[ichan].sourceDepth = 0; header[ichan].sourceToRecDist = 0; } else { /* This is the mechanism for adding other information with added tables. The one table currently supported is a "shot" table that holds shot coordinates. If other tables were added new functions could be added with a similar calling sequence. This procedure silently does nothing if a shot table is not present.*/ set_shot_variable(db,table_list, evid,&header[ichan]); } } else { if(Verbose) fprintf(stdout,"Station %s and channel %s skipped\n", sta,chan); } } /* Now we write the data */ for(i=0;i<nchan;++i) { if(fwrite((void *)(&(header[i])),sizeof(SegyHead),1,fp) != 1) elog_die(0,"Write error on header for trace %d\n",total_traces+i); if(fwrite((void *)traces[i],sizeof(float), (size_t)nsamp0,fp) != nsamp0) elog_die(0,"Write error while writing data for trace %d\n", total_traces+i); } total_traces += nchan; trdestroy(&trdb); if(!input_source_coordinates) ++shotid; } return 0 ; }
Tbl *dbload_arrival_table(Dbptr db,int row_start,int row_end, Arr *stations, Arr *arrphase) { Arrival *a; char *prog="dbform_arrival_table"; Tbl *t; /* Values set by dbgetv from row of view */ char staname[12]; double time, deltat; char phase_name[10]; char timedef[2]; t = newtbl(0); for(db.record=row_start;db.record<row_end;++db.record) { a = (Arrival *) malloc(sizeof(Arrival)); if(a == NULL) die(1,"%s: Cannot malloc Arrival structure\n", prog); if((dbgetv( db, 0, "arid",&(a->arid), "sta",staname, "assoc.phase",phase_name, "arrival.time",&time, "arrival.deltim",&deltat, "timedef",timedef, NULL )) == dbINVALID) die(1,"%s: dbgetv error\n",prog); /* Added to skip arrivals with timedef set to turn off */ if(!strcmp(timedef,"n")) { free(a); continue; } a->sta = (Station *) getarr(stations,staname); /* This error would be fatal for the relocate program, but this function might be used for other interfaces to this code so we only make it a warning */ if(a->sta == NULL) { complain(1,"%s: Cannot find coordinates for station %s\n%s phase arrival for this station skipped\n", prog, staname, phase_name); free(a); continue; } a->time = time; a->phase = (Phase_handle *) getarr(arrphase,phase_name); if(a->phase == NULL) { complain(1,"%s: Don't know how to handle phase %s\nArrival at %s at time %f skipped\n", prog,phase_name,staname,time); free(a); continue; } /* This assumes nonset values of the uncertainty in an arrival table are returned as a negative number. Because how one defines a nonset value in a database is variable, this could produce problems if this were changed */ a->deltat = deltat; if( (a->deltat) <= 0.0 ) a->deltat = (double)a->phase->deltat0; pushtbl(t,a); } return(t); }
/* 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 {
static int autodrm_response (Dbptr db) { Dbptr dbstage; static Hook *hook = 0; char sta[MAX_STA_SIZE], chan[MAX_CHAN_SIZE]; double time, endtime; long stageid; char *s; Response *response; Response_group *group; char iunits[96], ounits[96]; char gtype[100]; long i, j; Paz *paz; Fir *fir; Fap *fap; Fap2 *fap2; FILE *file; double samprate, gnom, gcalib; double calper=0.0; long decifac; char dir[100], dfile[100]; char filename[STRSZ]; long nmatches; int errors = 0; Tbl *tbl, *stbl; double mintime=0, maxtime=0; char segtype; static Tbl *keys1 = 0, *keys2 = 0; if (keys1 == 0) { keys1 = strtbl ("sta", "chan", "time", NULL); keys2 = strtbl ("sta", "chan", "time::endtime", NULL); } dbstage = dblookup (db, 0, "stage", 0, 0); nmatches = dbmatches (db, dbstage, &keys1, &keys2, &hook, &tbl); switch (nmatches) { case dbINVALID: case 0: dbgetv (db, 0, "sta", sta, "chan", chan, "time", &time, NULL); complain (0, "Can't match record for %s:%s @ %s in stage table", sta, chan, s = strydtime (time)); free (s); errors++; break; default: stbl = newtbl (maxtbl (tbl)); for (i = 0; i < nmatches; i++) { dbstage.record = (long) gettbl (tbl, i); dbgetv (dbstage, 0, "stageid", &stageid, "time", &time, "endtime", &endtime, NULL); if (i == 0) { mintime = time; maxtime = endtime; } else { mintime = MAX (time, mintime); maxtime = MIN (endtime, maxtime); } settbl (stbl, stageid - 1, (char *) i); } if (maxtbl (tbl) != maxtbl (stbl)) { dbgetv (db, 0, "sta", sta, "chan", chan, "time", &time, NULL); complain (0, "stageid numbers for %s:%s @ %s don't add up.", sta, chan, s = strydtime (time)); free (s); errors++; } else { errors += write_cal2 (db, mintime, maxtime, &calper); for (i = 0; i < nmatches; i++) { j = (long) gettbl (stbl, i); dbstage.record = (long) gettbl (tbl, j); dbgetv (dbstage, 0, "sta", sta, "chan", chan, "time", &time, "endtime", &endtime, "stageid", &stageid, "decifac", &decifac, "samprate", &samprate, "gnom", &gnom, "gcalib", &gcalib, "dir", dir, "dfile", dfile, "gtype", gtype, "iunits", iunits, "ounits", ounits, NULL); if (gcalib > 0.0) { gnom *= gcalib; } else if (gcalib < 0.0) { complain (0, "gcalib = %10.3f < 0. is invalid for %s:%s @ %s.\n", gcalib, sta, chan, s = strydtime (time)); free (s); errors++; } if (*dir != '-' || *dfile != '-') { long mark; dbextfile (dbstage, "stage", filename); mark = elog_mark (); elog_log (0, "response file is '%s'", filename); if ((file = fopen (filename, "r")) == 0 || read_response (file, &response) < 0) { register_error (0, "Can't read response file %s for %s_%s @ %s", filename, sta, chan, s = strydtime (time)); free (s); fclose (file); errors++; } else { fclose (file); if (response->ngroups > 1) { register_error (0, "stage response file %s has %d stages, not 1", filename, response->ngroups); errors++; } else { group = response->groups; switch (group->id) { case PAZ: /* The normalization frequency chosen in the * response file may not necessarily be the * same as the one chosen by calibration * table for insertion into the seed volumes. * Consequently, we have to adjust the * specified gnom to be correct for the seed * normalization frequency. Since the gain * is * * G(f) = gnom_db * A_response_file * P(f) = * gnom_seed * A_seed * P(f) * * We have * * gnom_seed = gnom_db * A_response_file / * A_seed * * gnom_db is just the gnom from the stage * table. A_response_file is the * normalization from the response file, left * in the stage structure. Below, we * calculate A_seed by setting * A_response_file to 1.0. * */ paz = (Paz *) group->pvt; for (j = 0; j < strlen (iunits); j++) { iunits[j] = tolower (iunits[j]); } s = getarr (Segtype, iunits); if (s == 0) { segtype = 'D'; } else { segtype = *s; } adwrite_paz (stageid, 0, gnom, segtype, ounits, paz); break; case IIR: paz = (Paz *) group->pvt; for (j = 0; j < strlen (iunits); j++) { iunits[j] = tolower (iunits[j]); } s = getarr (Segtype, iunits); if (s == 0) { segtype = 'D'; } else { segtype = *s; } adwrite_paz (stageid, 1, gnom, segtype, ounits, paz); break; case FIR: fir = (Fir *) group->pvt; errors += adwrite_fir (stageid, gnom, fir); break; case FAP: fap = (Fap *) group->pvt; errors += adwrite_fap (stageid, ounits, fap); break; case FAP2: fap2 = (Fap2 *) group->pvt; errors += adwrite_fap2 (stageid, ounits, fap2); break; default: complain (0, "Unknown filter type %d in response file %s\n", group->id, filename); errors++; break; } } } elog_flush (mark, 0); } else { char *desc = ""; if (gcalib > 0.0) { gnom *= gcalib; } else if (gcalib < 0.0) { complain (0, "gcalib = %10.3f < 0. is an invalid value.\n", gcalib); errors++; } if (strcmp (gtype, "digitizer") == 0 /* following hack for psd2db */ || strcmp (gtype, "sensor") == 0) { fprintf (stdout, "DIG2 %2ld %15.8e %11.5f %s\n", stageid, gnom, samprate, desc); } else if (strcmp (gtype, "amplifier") == 0) { /* no corners */ fprintf (stdout, "GEN2 %2ld %c %15.8e %7.3f 0 %s\n", stageid, *ounits, gnom, calper, desc); } else { complain (0, "Unrecognized gtype='%s' for %s:%s @ %s", gtype, sta, chan, s = strydtime (time)); free (s); errors++; } } } } freetbl (stbl, 0); break; } freetbl (tbl, 0); return errors; }
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); }
long db2sqlinsert( Dbptr db, Tbl **tbl, char *(*createsync)(Dbptr db), long flags ) { char *cmd; long ncmds = 0; long table_is_view = 0; Tbl *tables; char *table; long itable; if( *tbl == (Tbl *) NULL ) { *tbl = newtbl( 0 ); } if( db.database == dbINVALID || db.table == dbINVALID ) { return 0; } else if( db.table == dbALL ) { dbquery( db, dbSCHEMA_TABLES, &tables ); for( itable = 0; itable < maxtbl( tables ); itable++ ) { table = gettbl( tables, itable ); db = dblookup( db, "", table, "", "" ); ncmds += generate_sqltable_insert( db, tbl, createsync, flags ); } } else if( db.table >= 0 ) { dbquery( db, dbTABLE_IS_VIEW, &table_is_view ); if( table_is_view ) { elog_complain( 0, "db2sqlinsert does not support non-base-table views\n" ); return 0; } else { if( db.record == dbSCRATCH || db.record == dbNULL || db.record >= 0 ) { cmd = generate_sqlrow_insert( db, createsync, flags ); pushtbl( *tbl, cmd ); ncmds++; } else { ncmds += generate_sqltable_insert( db, tbl, createsync, flags ); } } } return ncmds; }
Tbl *dbload_slowness_table(Dbptr db,int row_start,int row_end, Arr *arrays, Arr *arrphase) { Slowness_vector *u; char *prog="dbform_slowness_table"; Tbl *t; /* Values set by dbgetv from row of view */ char staname[14]; double slow,azimuth; double delslo; char phase_name[10]; long arid; t = newtbl(0); for(db.record=row_start;db.record<row_end;++db.record) { int retcode; char slodef[2],azdef[2]; /* First make sure def is set for slowness vectors */ retcode=dbgetv(db,0,"slodef",slodef,"azdef",azdef,NULL ); if(retcode==dbINVALID) die(1,"%s: dbgetv error in read_slowness_vector\n",prog); /* don't load data unless slowness vector is defined */ if( (!strcmp(slodef,"d")) && (!strcmp(azdef,"d")) ) { /* I (glp) am inserting a prejudice here. Uncertainties in azimuth are hard to convert to a useable form in genloc because of the exclusive use of cartesian components rather than the polar form. The approach here is to use the value of delslo, when set, and use the same value for both components. This is reasonable for most arrays with a nearly round beam pattern, but will be quite wrong in colored noise.*/ retcode=dbgetv( db, 0, "arid",&arid, "sta",staname, "phase",phase_name, "slow",&slow, "delslo",&delslo, "azimuth",&azimuth,NULL ); if(retcode==dbINVALID) die(1,"%s: dbgetv error in read_slowness_vector\n",prog); /* The current schema says slow is set to -1.0 for a null value. I'll use a safer test for >= 0 since negative slowness is always meaningless. */ if(slow >= 0.0 ) { u = (Slowness_vector *) malloc(sizeof(Slowness_vector)); if(u == NULL) die(1,"%s: Cannot malloc Slowness_vector structure\n", prog); u->arid=arid; u->array = (Seismic_Array *) getarr(arrays,staname); /* This error would be fatal for the relocate program, but this function might be used for other interfaces to this code so we only make it a warning */ if(u->array == NULL) { complain(1,"%s: Cannot find coordinates for station %s\n%s phase arrival for this station skipped\n", prog, staname, phase_name); free(u); continue; } u->phase = (Phase_handle *) getarr(arrphase,phase_name); if(u->phase == NULL) { complain(1,"Warning (%s): No phase handle for phase name %s\nSlowness vector for array %s skipped\n", prog,phase_name,staname); free(u); continue; } /* CSS3.0 records slowness vectors in polar form with the magnitude measured in second/degree and azimuth in degrees. genloc uses only components internally in units of seconds/km. We now convert the slow, azimuth values to ux and uy in s/km. Oh, another possible confusion. For all the data I've seen, azimuth is really the receiver backazimuth which points 180 degrees away from the propagation direction. Internally I use the azimuth, so this formula makes that conversion too through the negative sign on each component.*/ slow /= KMPERDEG; u->ux = -slow*sin(azimuth*M_PI/180.0); u->uy = -slow*cos(azimuth*M_PI/180.0); /* her we set the uncertainties equal to delslo as noted above */ if(delslo > 0.0) { u->deltaux = delslo/KMPERDEG; u->deltauy = delslo/KMPERDEG; } else { u->deltaux = (double)u->phase->deltau0; u->deltauy = (double)u->phase->deltau0; } pushtbl(t,u); } } } return(t); }
double compute_ema (Slowness_vector *u, Slowness_Function_Output *ucalc, Dbptr db, char *vmodel) { Dbptr dbm, dbsv; static Tbl *matches; static Tbl *kmatch; /* Used to hold keys for dbmatches. */ char *key; double velocity; static Hook *hook=0; long nmatches; char cphase; /* store last char of phase name here */ int name_len; int i; double utotal, ema; dbsv = dblookup(db,0,"stavel",0,0); dbm = dblookup(db,0,"stavel",0,"dbSCRATCH"); dbputv(dbm,0,"sta",u->array->name,"phase",u->phase->name,"vmodel",vmodel,NULL ); /* It seems to be necessary to explicitly define the match keys. Using natural keys defined with null patterns for dbmatches did not work correctly. */ kmatch = newtbl(0); key = strdup("sta"); pushtbl(kmatch,key); key = strdup("phase"); pushtbl(kmatch,key); key = strdup("vmodel"); pushtbl(kmatch,key); dbmatches(dbm,dbsv,&kmatch,&kmatch,&hook,&matches); freetbl(kmatch,free); nmatches = maxtbl(matches); if(nmatches >= 1) { if(nmatches > 1) elog_log(0,"warning(compute_ema): multiple records found in stavel table with same primary key\n"); dbsv.record = (long) gettbl(matches,0); dbgetv(dbsv,0,"velocity",&velocity,NULL ); } else { /* No matches are found when we end up here. Revert to default and decide to us P or S velocity by hunting backward from the string looking for the first occurence of P or S*/ if(!strcmp(u->phase->name,"Lg")) velocity = DEFAULT_VS; else { name_len = strlen(u->phase->name); velocity = DEFAULT_VS; /* This is the default default */ for(i=name_len-1;i>=0;i--) { cphase = u->phase->name[i]; if(cphase == 'S'){ velocity = DEFAULT_VS; break; } else if(cphase == 'P'){ velocity = DEFAULT_VP; break; } } elog_log(0,"compute_ema: no matching entry found in stavel table for station/phase/vmodel = %s/%s/%s\n" "Reverting to default surface velocity of %f\n", u->array->name,u->phase->name,vmodel,velocity); } freetbl(matches,0); } /* now the actual computation is pretty trivial */ utotal = hypot(ucalc->ux,ucalc->uy); ema = asin(utotal*velocity); return(deg(ema)); }
int main (int argc, char **argv) { int c, verbose = 0, errflg = 0; char *dbinname=malloc(1024); char *dboutname=malloc(1024); Point *poly; double lat,lon; char *subset_expr=NULL; char *name=malloc(100); long nregions, nvertices; Tbl *sortkeys; Dbptr dbin,dbout,dbi,dbo,dbs; long i,from,to,nv; long vertex; elog_init ( argc, argv ) ; while ((c = getopt (argc, argv, "s:vV")) != -1) { switch (c) { case 's': subset_expr=optarg; break; case 'v': verbose++ ; break; case 'V': usage (); break; case '?': errflg++; break ; } } if ((errflg) || argc < 3) usage (); dbinname = argv[optind++]; dboutname= argv[optind++]; if (dbopen(dbinname,"r",&dbin)) { elog_die(1,"cannot open database %s",dbinname); } dbi=dblookup(dbin,0,"polygon",0,0); if (subset_expr) { dbi=dbsubset(dbi,subset_expr,NULL); } sortkeys=newtbl(1); pushtbl(sortkeys,"pname"); dbs=dbsort(dbi,sortkeys,0,"sorted"); dbquery(dbs,dbRECORD_COUNT,&nregions); if (nregions <1) { elog_die(0,"table regions seems to be empty (or not present)"); } if (verbose) elog_notify(0,"creating database descriptor %s",dboutname); if (dbcreate(dboutname,"places1.2",0,0,0)) { elog_die(1,"cannot create database %s",dboutname); } dbopen(dboutname,"r+",&dbout); dbo=dblookup(dbout,0,"regions",0,0); for (i=0; i< nregions; i++) { dbs.record=i; dbgetv(dbs,0,"pname",name,NULL ); nvertices=readPolygon(dbs,&poly); for (nv=0;nv < nvertices;nv++) { lat=poly[nv].lat; lon=poly[nv].lon; dbaddv(dbo,0, "regname",name, "vertex",nv, "lat",lat,"lon",lon, NULL ); } free(poly); } dbclose(dbo); /* */ return 0; }
/* 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); }
int main (int argc, char **argv) { int c, verbose = 0, errflg = 0; char *dbinname=malloc(1024); char *dboutname=malloc(1024); Point *poly; double lat,lon; char *auth=strdup("regions2polygon"); char *ptype= strdup("rp"); char *dir=strdup("."); char *dfile=strdup("polygons"); int ftype=polyFLOAT; char *name; int nregions, nvertices; Tbl *sortkeys, *groupkeys; Dbptr dbin,dbout,dbi,dbo,dbg,dbb; int i,from,to,nv; int vertex; elog_init ( argc, argv ) ; while ((c = getopt (argc, argv, "vV")) != -1) { switch (c) { case 'v': verbose++ ; break; case 'V': usage (); break; case '?': errflg++; break ; } } if ((errflg) || argc < 3) usage (); dbinname = argv[optind++]; dboutname= argv[optind++]; if (dbopen(dbinname,"r",&dbin)) { elog_die(1,"cannot open database %s",dbinname); } dbi=dblookup(dbin,0,"regions",0,0); sortkeys=newtbl(2); pushtbl(sortkeys,"regname"); pushtbl(sortkeys,"vertex"); groupkeys=newtbl(1); pushtbl(groupkeys,"regname"); dbi=dbsort(dbi,sortkeys,0,"regions.sorted"); dbg=dbgroup(dbi,groupkeys,0,0); dbquery(dbg,dbRECORD_COUNT,&nregions); if (nregions <1) { elog_die(0,"table regions seems to be empty (or not present)"); } if (verbose) elog_notify(0,"creating database descriptor %s",dboutname); if (dbcreate(dboutname,"polygon1.2",0,0,0)) { elog_die(1,"cannot create database %s",dboutname); } dbopen(dboutname,"r+",&dbout); dbo=dblookup(dbout,0,"polygon",0,0); for (i=0; i< nregions; i++) { dbg.record=i; dbgetv(dbg,0,"regname",name,"bundle",&dbb,0); dbget_range(dbb,&from,&to); nvertices= to - from; if (verbose) elog_notify(0,"%s (%i nvertices)",name,nvertices); poly=malloc(2 * nvertices * sizeof(double)); nv=0; for (dbi.record=from; dbi.record<to; dbi.record++) { dbgetv(dbi,0, "regname",name, "vertex",&vertex, "lat",&lat,"lon",&lon, 0); poly[nv].lat=lat; poly[nv].lon=lon; nv++; } writePolygonData(dbo,poly,nv,name,1,0,ptype,auth,dir,dfile,ftype); free(poly); } /* */ return 0; }
void main(int argc, char **argv) { Dbptr db, dbv, dbge, dbgg; /*ensemble_mode is primary grouping, grouping_on set if secondary on*/ int ensemble_mode,grouping_on; Tbl *ensemble_keys; Tbl *group_keys; int i; char *pfi=NULL; Pf *pf,*pfo_head,*pfo_total; Tbl *process_list; int dryrun=0; char *sift_exp=NULL; int sift; /*Attributes listed in require will abort program if missing passthrough parameters will generate an error message but not cause the program to abort. Both contain pointers to Attribute_map*/ Tbl *require,*passthrough; Attribute_map *amap; FILE *fp; Tbl *error_list; char *tag; int sleep_time; DB2PFS_verbose=0; /*crack the command line*/ if(argc<3) usage(); elog_init(argc,argv); if(dbopen(argv[1],"r",&db)==dbINVALID) { elog_complain(0,"dbopen failed on database %s\n",argv[1]); usage(); } for(i=3;i<argc;++i) { if(!strcmp(argv[i],"-pf")) { ++i; if(i>argc) usage(); pfi=argv[i]; } else if(!strcmp(argv[i],"-V")) usage(); else if(!strcmp(argv[i],"-v")) DB2PFS_verbose=1; else if(!strcmp(argv[i],"-n")) dryrun=1; else if(!strcmp(argv[i],"-sift")) { ++i; if(i>argc) usage(); sift=1; sift_exp=argv[i]; } else usage(); } if(!dryrun) { fp=fopen(argv[2],"r+"); if(fp==NULL) usage(); } if(pfi==NULL) pfi=strdup("db2pfstream"); if(pfread(pfi,&pf)) elog_die(0,"Error reading parameter file %s.pf\n",pfi); sleep_time=pfget_int(pf,"sleep_time"); /* The output view gets a virtual table name that tags the overall collection of stuff. This comes from the parameter file to make this program general, BUT it must be coordinated with the reader code. */ tag = pfget_string(pf,"virtual_table_name"); if(tag==NULL)elog_die(0,"Required parameter (virtual_table_name) missing from parameter file\n"); ensemble_mode = pfget_boolean(pf,"ensemble_mode"); if(ensemble_mode) { ensemble_keys=pfget_tbl(pf,"ensemble_keys"); if(ensemble_keys==NULL) elog_die(0, "ensemble_mode is on, but no grouping keys defined\nCheck parameter file\n"); group_keys=pfget_tbl(pf,"group_keys"); if(group_keys==NULL) grouping_on = 0; else { if(maxtbl(group_keys)>0) grouping_on = 1; else grouping_on = 0; } } if(DB2PFS_verbose && ensemble_mode) { char sm[128]; char *key; strcpy(sm,"Defining ensemble with keys: "); for(i=0;i<maxtbl(ensemble_keys);++i) { key=gettbl(ensemble_keys,i); strcat(sm,key); } elog_log(0,"%s\n",sm); if(grouping_on) { strcpy(sm,"Grouping ensemble with keys: "); for(i=0;i<maxtbl(group_keys);++i) { key = gettbl(group_keys,i); strcat(sm,key); } elog_log(0,"%s\n",sm); } } /*This function calls dbprocess using a tbl from pf*/ dbv=dbform_working_view(db,pf,"dbprocess_list"); if(dbv.record==dbINVALID) elog_die(0,"dbprocess failed: check database and parameter file parameter dbprocess_list\n"); if(sift_exp!=NULL)dbv=dbsubset(dbv,sift_exp,0); /*Now we form the groupings if needed */ if(ensemble_mode) { dbge = dbgroup(dbv,ensemble_keys,"ensemble",1); if(dbge.record == dbINVALID) elog_die(0,"dbgroup with ensemble keys failed\n"); if(grouping_on) { dbgg = dbgroup(dbv,group_keys,"groups",2); if(dbgg.record == dbINVALID) elog_die(0,"dbgroup on secondary grouping keys failed\n"); } } /*This builds the maps of which attributes will be saved */ require = pfget_Attribute_map(pf,"require"); if(require==NULL) elog_die(0,"Error in parameter file for parameter require\n"); passthrough = pfget_Attribute_map(pf,"passthrough"); if(passthrough==NULL) elog_die(0,"Error in parameter file for parameter passthrough\n"); /* Unfortunately, we have two different loops for ensemble mode and single object mode */ if(ensemble_mode) { int number_ensembles; Dbptr db_bundle_1; Dbptr db_bundle_2; int is_ensemble, ie_ensemble; int isg, ieg; int number_groups; pfo_head=pfnew(0); pfput_tbl(pfo_head,"ensemble_keys",ensemble_keys); if(grouping_on) pfput_tbl(pfo_head,"group_keys",group_keys); dbquery(dbge,dbRECORD_COUNT,&number_ensembles); if(DB2PFS_verbose) elog_log(0,"database has %d ensembles\n", number_ensembles); if(grouping_on) { dbgg.record=0; dbquery(dbgg,dbRECORD_COUNT,&number_groups); if(DB2PFS_verbose) elog_log(0,"database has %d subgroups\n", number_groups); } for(dbge.record=0;dbge.record<number_ensembles; ++dbge.record) { Pf_ensemble *pfe; int nmembers; char *grp_records; Tbl *grplist; dbgetv(dbge,0,"bundle",&db_bundle_1,0); dbget_range(db_bundle_1,&is_ensemble,&ie_ensemble); nmembers = ie_ensemble-is_ensemble; /* pfe does not need to hold the group records for this application so the ngroups variable is passed as 0*/ pfe=create_Pf_ensemble(nmembers,0); /*Now loop through and load the array of pf's with parameters defined by the attribute maps*/ for(i=0,dbv.record=is_ensemble;i<nmembers; ++i,++dbv.record) { pfe->pf[i]=pfnew(PFARR); error_list=db2pf(dbv,require,pfe->pf[i]); if(maxtbl(error_list)>0) { if(dryrun) { elog_log(0,"Ensemble %d at input database view record %d lacks required attributes\n", dbge.record,dbv.record); log_error_list(error_list); } else { fprintf(fp,"%s\n",END_OF_DATA_SENTINEL); fflush(fp); elog_log(0,"FATAL ERROR: ensemble %d at input database view record %d lacks required attributes\nOUTPUT DATA STREAM TRUNCATED\n", i,dbv.record); log_error_list(error_list); exit(-1); } } freetbl(error_list,free); error_list=db2pf(dbv,passthrough,pfe->pf[i]); if(DB2PFS_verbose) { elog_log(0,"Warning: null passthrough attributes for ensemble %d at row %d\n", dbge.record,dbv.record); log_error_list(error_list); } freetbl(error_list,free); pfput_boolean(pfe->pf[i],"data_valid",1); } if(grouping_on) { grplist=newtbl(0); do { dbgetv(dbgg,0,"bundle",&db_bundle_2,0); dbget_range(db_bundle_2,&isg,&ieg); grp_records=malloc(30); sprintf(grp_records,"%d %d", isg-is_ensemble,ieg-is_ensemble-1); pushtbl(grplist,grp_records); ++dbgg.record; } while (ieg<ie_ensemble); pfput_tbl(pfo_head,"group_records",grplist); } pfo_total=build_ensemble(1,tag,pfo_head,pfe); free_Pf_ensemble(pfe); if(!dryrun) { pfout(fp,pfo_total); fprintf(fp,"%s\n",ENDPF_SENTINEL); fflush(fp); } pffree(pfo_total); if(grouping_on)freetbl(grplist,free); } } else { /*This is the simpler, single block mode */ int nrecords; Pf *pfo; dbquery(dbv,dbRECORD_COUNT,&nrecords); pfo=pfnew(PFARR); for(dbv.record=0;dbv.record<nrecords;++dbv.record) { error_list=db2pf(dbv,require,pfo); if(maxtbl(error_list)>0) { if(dryrun) { elog_log(0,"Input database view at row %d lacks required parameters\n", dbv.record); log_error_list(error_list); } else { fprintf(fp,"%s\n",END_OF_DATA_SENTINEL); fflush(fp); elog_log(0,"FATAL: input database view at row %d lacks required parameters\n", dbv.record); log_error_list(error_list); exit(-1); } } freetbl(error_list,free); error_list=db2pf(dbv,passthrough,pfo); pfput_boolean(pfo,"data_valid",1); if(DB2PFS_verbose) { elog_log(0,"Warning: null passthrough attributes for row %d of input database view\n", dbv.record); } if(!dryrun) { pfout(fp,pfo); fprintf(fp,"%s\n",ENDPF_SENTINEL); } } } if(!dryrun) { fprintf(fp,"%s\n",END_OF_DATA_SENTINEL); fflush(fp); sleep(sleep_time); fclose(fp); } exit(0); }