Example #1
0
void mexFunction ( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
{
    Dbptr	db;
    Tbl	*groupfields = 0;
    char	errmsg[STRSZ];
    int	rhs_index;
    long	type = 1;
    double 	type_fp = 1;

    if( nrhs < 2 || nrhs > 3  )
    {
        antelope_mexUsageMsgTxt ( USAGE );
        return;
    }
    else if( ! get_dbptr( prhs[0], &db ) )
    {
        antelope_mexUsageMsgTxt ( USAGE );
        return;
    }
    else if( ! get_stringtbl( prhs[1], &groupfields ) )
    {
        antelope_mexUsageMsgTxt ( USAGE );
        return;
    }

    if( nrhs == 3 ) {

        if( ! get_scalar( prhs[2], &type_fp ) ) {

            antelope_mexUsageMsgTxt ( USAGE );
            return;

        } else {

            type = (long) type_fp;
        }
    }

    db = dbgroup( db, groupfields, NULL, type );
    antelope_mex_clear_register( 1 );

    freetbl( groupfields, 0 );

    if( db.table == dbINVALID )
    {
        mexErrMsgTxt( "dbgroup: group failed" );
    }

    plhs[0] = CreateDbptrStructFromDbptr( db );

    if( plhs[0] == NULL )
    {
        sprintf( errmsg, "dbgroup: failed to create database-pointer " );
        strcat( errmsg, "structure for result" );
        mexErrMsgTxt( errmsg );
    }
}
Example #2
0
/**
 * @brief Load a database access profile configuration from a PvlObject
 * 
 * This method loads all keywords found in the Object section of the PvlObject
 * and then searches for each Group named Profile.  Profile groups contain
 * augmentations to the object keywords to add to or replace object level access
 * specifications.  Each profile group must contain a \b Name keyword to
 * uniquely identify the (group) access parameters.
 * 
 * Profiles are loaded and stored in this object for subsequent access.
 * 
 * @param pvl A PvlObject that contains keywords and option Profile groups.
 */
void DbAccess::load(PvlObject &pvl) {

  //  Load database keywords
  loadkeys(pvl);

  //  Get all database user access profiles
  PvlObject::PvlGroupIterator group = pvl.FindGroup("Profile", 
                                                     pvl.BeginGroup(),
                                                     pvl.EndGroup());
  while (group != pvl.EndGroup()) {
    DbProfile dbgroup(*group);
    _profiles.add(dbgroup.Name(), dbgroup);
    group = pvl.FindGroup("Profile", ++group, pvl.EndGroup());
  }
  return;
}
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;
}
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);
}
Example #5
0
int grdb_sc_loadcss (Dbptr dbin, char *net_expr, char *sta_expr,
        char *chan_expr, double tstart, double tend, 
        int coords, int ir, int orient, Dbptr *dbscgr, Dbptr *dbsc)
{
	Dbptr dbout, db, dbout2;
	char string[1024];
	char string2[1024];
	char sta_wfdisc[32], chan_wfdisc[32];
	int i, j, n, sensor=0, ok;
	Tbl *pat1, *pat2;
	Tbl *sortfields, *groupfields;
	FILE *file;
	Response *resp;
	int is_view=0;
	Dbptr db_to_clear;

	/* Subset the wfdisc by station-channel-time sifters. */

	dbout = dblookup (dbin, 0, "wfdisc", 0, 0);
	strcpy (string, "");
	if (sta_expr) {
		strcpy (string, "( ");
        	sprintf (string2, "sta =~ /%s/", sta_expr);
        	strcat (string, string2);
	}
	if (chan_expr) {
		if (string[0]) strcat (string, " && ");
		else strcpy (string, "( ");
        	sprintf (string2, "chan =~ /%s/", chan_expr);
        	strcat (string, string2);
	}
	if (tstart != 0.0 || tend != 0.0) {
		if (string[0]) strcat (string, " && ");
		else strcpy (string, "( ");
        	sprintf (string2, "(time < %.5f && endtime > %.5f)", tend, tstart);
        	strcat (string, string2);
	}
	if (string[0]) {
		strcat (string, " )");
		dbout = dbsubset (dbout, string, 0);
		is_view=1;
	}
        dbquery (dbout, dbRECORD_COUNT, &n);
        if (n < 1) {
		register_error (0, "grdb_sc_loadcss: No wfdisc rows to process.\n");
		return (-1);
        }

        /* Make the necessary joins and check for completeness. */

        if (coords) {
        	db = dblookup (dbin, 0, "site", 0, 0);
		if(is_view)db_to_clear=dbout;
        	dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0);
		if(is_view) dbfree(db_to_clear);
		is_view=1;
		
        	dbquery (dbout, dbRECORD_COUNT, &n);
        	if (n < 1) {
			register_error (0, "grdb_sc_loadcss: No data rows to process.\n");
			return (-1);
        	}
        	for (dbout.record=0; dbout.record<n; dbout.record++) {
        		if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc,
        				"wfdisc.chan", chan_wfdisc,
        				"site.sta", string, 0) == dbINVALID) {
			    register_error (0, "grdb_sc_loadcss: dbgetv() error while checking site.\n");
			    return (-1);
			}
        		if (coords > 1 && strcmp(string, sta_wfdisc)) {
        			register_error (0, "grdb_sc_loadcss: Cannot find site parameters for %s %s.\n", 
        									sta_wfdisc, chan_wfdisc);
        			return (-1);
        		}
        	}
        }
        if (ir) {
        	db = dblookup (dbin, 0, "sensor", 0, 0);
		if(is_view)db_to_clear=dbout;
        	dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0);
		if(is_view) dbfree(db_to_clear);
		is_view=1;
        	dbquery (dbout, dbRECORD_COUNT, &n);
        	if (n < 1) {
			register_error (0, "grdb_sc_loadcss: No data rows to process.\n");
			return (-1);
        	}
        	for (dbout.record=0; dbout.record<n; dbout.record++) {
        		if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc,
        				"wfdisc.chan", chan_wfdisc,
        				"sensor.sta", string, 0) == dbINVALID) {
			    register_error (0, "grdb_sc_loadcss: dbgetv() error while checking sensor.\n");
			    return (-1);
			}
        		if (ir > 1 && strcmp(string, sta_wfdisc)) {
        			register_error (0, "grdb_sc_loadcss: Cannot find sensor parameters for %s %s.\n", 
        									sta_wfdisc, chan_wfdisc);
        			return (-1);
        		}
        	}
        	sensor = 1;
		if(is_view)db_to_clear=dbout;
        	db = dblookup (dbin, 0, "instrument", 0, 0);
        	dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0);
		if(is_view) dbfree(db_to_clear);
		is_view=1;
        	dbquery (dbout, dbRECORD_COUNT, &n);
        	if (n < 1) {
			register_error (0, "grdb_sc_loadcss: No data rows to process.\n");
			return (-1);
        	}
        	for (dbout.record=0; dbout.record<n; dbout.record++) {
        		if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc,
        				"wfdisc.chan", chan_wfdisc,
        				"sensor.inid", &j,
        				"instrument.insname", string2,
        				"instrument.inid", &i, 0) == dbINVALID) {
			    register_error (0, "grdb_sc_loadcss: dbgetv() error while checking instrument.\n");
			    return (-1);
			}
        		if (ir > 1 && (i != j)) {
        			register_error (0, "grdb_sc_loadcss: Cannot find instrument parameters for %s %s.\n", 
        									sta_wfdisc, chan_wfdisc);
        			return (-1);
        		}
        		if (i >= 0) {
				if (resp_arr == NULL) {
					resp_arr = newarr (0);
					if (resp_arr == NULL) {
        					register_error (0, "grdb_sc_loadcss: newarr() error.\n");
        					return (-1);
					}
				}
				dbextfile (dbout, "instrument", string);
				resp = (Response *) getarr (resp_arr, string);
				if (resp == NULL) {
					file = fopen (string, "r");
					if (file == NULL) {
						if (ir > 1) {
        						register_error (1, "grdb_sc_loadcss: fopen('%s') error.\n", string);
        						return (-1);
						}
					} else {
						if (read_response (file, &resp)) {
        						register_error (0, "grdb_sc_loadcss: read_response('%s') error.\n", string);
        						return (-1);
						}
						fclose (file);
						resp->insname = strdup(string2);
					}
					setarr (resp_arr, string, resp);
				}
			}
        	}
        }
        if (orient) {
        	ok = 1;
		if(is_view)db_to_clear=dbout;
        	db = dblookup (dbin, 0, "sitechan", 0, 0);
        	dbout2 = dbjoin (dbout, db, 0, 0, 1, 0, 0);
		is_view=1;
        	dbquery (dbout2, dbRECORD_COUNT, &n);
        	if (n < 1) {
        		ok = 0;
        	} else {
        		for (dbout2.record=0; dbout2.record<n; dbout2.record++) {
        			dbgetv (dbout2, 0, "wfdisc.sta", sta_wfdisc,
        				"wfdisc.chan", chan_wfdisc,
        				"sitechan.sta", string, 0);
        			if (strcmp(string, sta_wfdisc)) {
        				ok = 0;
        				break;
        			}
        		}
		}
		if (ok) {
			dbout = dbout2;
			if(is_view) dbfree(db_to_clear);
		} else {
			if (!sensor) {
        			db = dblookup (dbin, 0, "sensor", 0, 0);
				if(is_view)db_to_clear=dbout;
	       			dbout = dbjoin (dbout, db, 0, 0, 1, 0, 0);
				if(is_view) 
				{
					dbfree(dbout2);
					dbfree(db_to_clear);
				}
				is_view=1;
        			dbquery (dbout, dbRECORD_COUNT, &n);
        			if (n < 1) {
					register_error (0, "grdb_sc_loadcss: No data rows to process.\n");
					return (-1);
        			}
        			for (dbout.record=0; dbout.record<n; dbout.record++) {
        				if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc,
        						"wfdisc.chan", chan_wfdisc,
        						"sensor.sta", string, 0) == dbINVALID) {
			    			register_error (0, "grdb_sc_loadcss: dbgetv() error while checking sensor.\n");
			    			return (-1);
					}
        				if (orient > 1 && strcmp(string, sta_wfdisc)) {
        					register_error (0, "grdb_sc_loadcss: Cannot find sensor parameters for %s %s.\n", 
        											sta_wfdisc, chan_wfdisc);
        					return (-1);
        				}
        			}
			}
        		db = dblookup (dbin, 0, "sitechan", 0, 0);
        		pat1 = newtbl(1);
        		if (pat1 == NULL) {
        			register_error (0, "grdb_sc_loadcss: newtbl() error.\n");
        			return (-1);
        		}
        		pat2 = newtbl(1);
        		if (pat2 == NULL) {
        			register_error (0, "grdb_sc_loadcss: newtbl() error.\n");
        			return (-1);
        		}
			if(is_view)db_to_clear=dbout;
        		settbl (pat1, 0, strdup("sensor.chanid"));
        		settbl (pat2, 0, strdup("sitechan.chanid"));
        		dbout = dbjoin (dbout, db, &pat1, &pat2, 1, 0, 0);
			if(is_view) dbfree(db_to_clear);
			is_view=1;
        		freetbl (pat1, free);
        		freetbl (pat2, free);
        		dbquery (dbout, dbRECORD_COUNT, &n);
        		if (n < 1) {
				register_error (0, "grdb_sc_loadcss: No data rows to process.\n");
				return (-1);
        		} else {
        			for (dbout.record=0; dbout.record<n; dbout.record++) {
        				if (dbgetv (dbout, 0, "wfdisc.sta", sta_wfdisc,
        					"wfdisc.chan", chan_wfdisc,
        					"sitechan.sta", string, 0) == dbINVALID) {
			    		   register_error (0, "grdb_sc_loadcss: dbgetv() error while checking sitechan.\n");
			    		   return (-1);
					}
        				if (orient > 1 && strcmp(string, sta_wfdisc)) {
        					register_error (0, "grdb_sc_loadcss: Cannot find sitechan parameters for %s %s.\n", 
        											sta_wfdisc, chan_wfdisc);
        					return (-1);
        				}
        			}
			}
		}
        }

        /* Sort and group the output view. */

	if(is_view)db_to_clear=dbout;
	sortfields = newtbl (3);
	if (sortfields == NULL) {
		register_error (0, "grdb_sc_loadcss: newtbl() error.\n");
		return (-1);
	}
	settbl (sortfields, 0, strdup("wfdisc.sta"));
	settbl (sortfields, 1, strdup("wfdisc.chan"));
	settbl (sortfields, 2, strdup("wfdisc.time"));
        *dbsc = dbsort (dbout, sortfields, 0, 0);
	if(is_view) dbfree(db_to_clear);
	groupfields = newtbl (2);
	if (groupfields == NULL) {
		register_error (0, "grdb_sc_loadcss: newtbl() error.\n");
		return (-1);
	}
	settbl (groupfields, 0, strdup("sta"));
	settbl (groupfields, 1, strdup("chan"));
	*dbscgr = dbgroup (*dbsc, groupfields, 0, 1);
	freetbl (sortfields, free);
	freetbl (groupfields, free);

	/* Normal exit */

	return (0);
}
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);
}