/************************************************************************/ /* SimpleResp: Generates Simplified Response From Database /************************************************************************/ /* Author: Stephane Zuzlewski UC Berkeley Seismological Laboratory stephane@seismo.berkeley.edu Purpose: Modification History: Date Ver Who What --------------------------------------------------------------------- 2002/05/13 1.0 SMZ Initial coding. 2003/01/02 1.0 SMZ Added # sign on header line /************************************************************************/ #ifndef lint static char sccsid[] = "%W% %G% %U%"; #endif #include #include #include #include #include #define CONNECT_STRING "user/passwd@db" #define END_OF_QUERY 1403 #define VERSION "1.0" char *syntax[] = { "%s version " VERSION " -- Generates Simplified Response From Database.", "%s [-h] [-v] [-p] []", " where:", " -h Help - prints syntax message.", " -v Debugging Mode.", " -p Population Mode.", NULL }; #define info stdout #define LINELEN 255 EXEC SQL INCLUDE sqlca.h; typedef char asciz[20]; typedef char vc2_arr[11]; EXEC SQL BEGIN DECLARE SECTION; char user_pwd[80]; short ind1; /* Indicator */ short ind2; /* Indicator */ char sta[7]; /* Station code */ char net[9]; /* Network code */ char usernet[9]; /* User Network Code */ char seedchan[4]; /* SEED channel code */ char location[3]; /* Location code */ char ondate[20]; /* Start date */ char offdate[20]; /* Off date */ int data_id; /* Datalogger identifier */ int data_nb; /* Datalogger number */ int data_pchannel_nb; /* Datalogger physical channel number */ int board_nb; /* Datalogger board number */ int digi_nb; /* Digitizer number */ int digi_pchannel_nb; /* Digitizer physical channel number */ int digi_channel; /* Digitizer channel */ char serial_nb[81]; /* Digitizer serial number */ double digi_sens; /* Digitizer sensitivity */ int filamp_id; /* Filter-Amplifier identifier */ int filamp_nb; /* Filter-Amplifier number */ int filamp_pchannel_nb; /* Filter-Amplifier physical channel number */ int sensor_id; /* Sensor identifier */ char name[81]; /* Sensor name */ int sensor_nb; /* Sensor number */ int component_nb; /* Sensor component number */ double sensor_sens; /* Sensor sensitivity */ int seqresp_id; /* Sequence of responses identifier */ int fseqresp_id; /* Filter-Amplifier Sequence of responses identifier */ double hp_filter; /* Corner frequency of high-pass filter */ double lp_filter; /* Corner frequency of low-pass filter */ double nat_freq; /* Sensor natural frequency */ double damping; /* Fraction of critical damping */ int hp_id; /* High-pass filter identifier */ int lp_id; /* Low-pass filter identifier */ double dip; /* Dip */ double azimuth; /* Azimuth */ int unit; /* Units */ char unitname[80]; /* Units Name */ double overall_gain; /* Overall Gain */ double samprate; /* Sampling Rate */ double ml_corr; /* Ml Correction */ char ml_flag; /* Ml Flag */ char gain_units[21]; /* Units of gain */ char SQL_Command[1024]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE sql_stmt STATEMENT; /************************************************************************/ /* External variables and symbols. */ /************************************************************************/ char *cmdname; /* program name from command line. */ long SQLCODE; void sql_error(); /* Handles unrecoverable errors */ int Nbmlcorr = 26; char *mlcorr[][2] = { "BK.ARC", "0.147", "BK.BDM", "0.080", "BK.BKS", "0.094", "BK.BRIB", "0.141", "BK.BRK", "0.264", "BK.CMB", "0.250", "BK.CVS", "0.212", "BK.FARB", "0.296", "BK.HOPS", "0.304", "BK.JCC", "0.181", "BK.JRSC", "0.142", "BK.KCC", "0.314", "BK.MHC", "0.094", "BK.MIN", "-0.140", "BK.MOD", "0.067", "BK.ORV", "0.374", "BK.PKD", "0.093", "BK.PKD1", "-0.201", "BK.POTR", "-0.137", "BK.SAO", "0.318", "BK.STAN", "-0.171", "BK.WDC", "0.385", "BK.WENL", "-0.019", "BK.YBH", "0.477", "BK.CMSB", "-0.410", "BK.CRQB", "-1.150", }; /************************************************************************/ /* print_syntax: */ /* Print the syntax description of program. */ /************************************************************************/ int print_syntax (char *cmd, /* program name. */ char *syntax[], /* syntax array. */ FILE *fp) /* FILE ptr for output. */ { int i; for (i=0; syntax[i] != NULL; i++) { fprintf (fp, syntax[i], cmd); fprintf (fp, "\n"); } return (0); } /************************************************************************/ /* GetMlCorr: /* Function that returns the Ml Correction for a station /************************************************************************/ double GetMlCorr (char sta[7], char net[9]) { char netsta[20]; int i; sprintf (netsta, "%s.%s", net, sta); for (i=0;i < Nbmlcorr;i++) if (!strcmp (mlcorr[i][0], netsta)) return (atof (mlcorr[i][1])); return (0.0); } /************************************************************************/ /* Remove_Blank: /* /* Removes trailing blanks in a string. /* Returns new string /************************************************************************/ char* Remove_Blank (char *s) { char *p = s + strlen (s); while (--p >= s) if (*p == ' ') *p = '\0'; else break; return (s); } /************************************************************************/ /* Convert_Date: /* /* Function to convert a julian date to a Oracle date /************************************************************************/ char* Convert_Date (char d[20]) { EXEC SQL BEGIN DECLARE SECTION; static char nd[20]; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT TO_CHAR (TO_DATE (:d, 'YYYY/MM/DD HH24:mi:ss'), 'YYYY.DDD.HH24:mi:ss') INTO :nd FROM DUAL; Remove_Blank (nd); return (nd); } /************************************************************************/ /* Main function /************************************************************************/ main (int argc, char *argv[]) { int Flag, FlagNet; char nondate[20], noffdate[20]; int FlagVerbose = 0; int FlagPopulation = 0; FILE* fout; /* Variables needed for getopt. */ extern char *optarg; extern int optind, opterr; int c; char *p; cmdname = ((p = strrchr(*argv,'/')) != NULL) ? ++p : *argv; /* Parse command line options. */ while ( (c = getopt(argc,argv,"hvp")) != -1) switch (c) { case '?': case 'h': print_syntax(cmdname,syntax,info); exit(0); break; case 'v': FlagVerbose = 1; break; case 'p': FlagPopulation = 1; break; default: fprintf (info, "Unknown option: -%c\n", c); exit(1); } /* Skip over all options and their arguments. */ argv = &(argv[optind]); argc -= optind; /* Reading Arguments */ if (argc == 1) FlagNet = 0; else if (argc == 2) { FlagNet = 1; strcpy (usernet, argv[1]); } else { print_syntax(cmdname,syntax,info); exit (1); } /* Opening output file */ if ((fout = fopen (argv[0], "w+t")) == NULL) { printf ("Error: Couldn't open file %s\n", argv[0]); exit (-1); } /* Connect to ORACLE. */ strcpy (user_pwd, CONNECT_STRING); EXEC SQL CONNECT :user_pwd; EXEC SQL WHENEVER SQLERROR DO sql_error(); /* Delete all Rows from Simple_Response and StaCorrections Tables */ if (FlagPopulation) { EXEC SQL DELETE FROM SIMPLE_RESPONSE; EXEC SQL DELETE FROM STACORRECTIONS; } fprintf (fout, "#Net Sta Cha Loc Ondate Offdate Natural Freq. HP Corner LP Corner Damping Gain Azi Dip Units\n"); /* Database Query */ if (FlagNet == 0) strcpy (SQL_Command, "SELECT STA, NET, SEEDCHAN, LOCATION, ONDATE, OFFDATE, UNIT_SIGNAL, SAMPRATE FROM NCEDCDBA.STATION_DATALOGGER_LCHANNEL WHERE NET IN ('BK','BP','NN','NC','CI') ORDER BY NET, STA, SEEDCHAN, LOCATION, ONDATE"); else sprintf (SQL_Command, "SELECT STA, NET, SEEDCHAN, LOCATION, ONDATE, OFFDATE, UNIT_SIGNAL, SAMPRATE FROM NCEDCDBA.STATION_DATALOGGER_LCHANNEL WHERE NET = '%s' ORDER BY NET, STA, SEEDCHAN, LOCATION, ONDATE", usernet); /* Declaring cursor */ EXEC SQL PREPARE sql_stmt FROM :SQL_Command; EXEC SQL DECLARE chacursor CURSOR FOR sql_stmt; /* Opening cursor */ EXEC SQL OPEN chacursor; EXEC SQL FETCH chacursor INTO :sta, :net, :seedchan, :location, :ondate, :offdate, :unit, :samprate; while (sqlca.sqlcode != END_OF_QUERY) { Flag = 1; Remove_Blank (sta); Remove_Blank (net); Remove_Blank (seedchan); Remove_Blank (ondate); Remove_Blank (offdate); if (FlagVerbose) printf ("%s %s %s %s %s\n", net, sta, seedchan, ondate, offdate); EXEC SQL SELECT NAME INTO :unitname FROM NCEDCDBA.D_UNIT WHERE ID = :unit; Remove_Blank (unitname); if (samprate < 0.) samprate = (-1.)/samprate; if ((!strcmp (unitname, "M/S")) || (!strcmp (unitname, "M/S**2"))) { /* Declaring cursor */ EXEC SQL DECLARE channel_cursor CURSOR FOR SELECT DATA_NB, PCHANNEL_NB FROM NCEDCDBA.STATION_DATALOGGER_LCHANNEL WHERE STA = :sta AND NET = :net AND SEEDCHAN = :seedchan AND LOCATION = :location AND ONDATE = :ondate; /* Opening cursor */ EXEC SQL OPEN channel_cursor; EXEC SQL FETCH channel_cursor INTO :data_nb, :data_pchannel_nb; while (sqlca.sqlcode != END_OF_QUERY) { if (FlagVerbose) printf ("\t DATA_NB = %d -- PCHANNEL_NB = %d\n", data_nb, data_pchannel_nb); /* Retrieving datalogger identifier */ data_id = 0; EXEC SQL SELECT DATA_ID INTO :data_id FROM NCEDCDBA.STATION_DATALOGGER WHERE STA = :sta AND NET = :net AND DATA_NB = :data_nb AND ONDATE = :ondate; if (FlagVerbose) printf ("\t DATA_ID = %d\n", data_id); if (data_id == 0) { printf ("Error: Problem with datalogger identifier.\n"); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Retrieving digitizer links */ digi_nb = 0; digi_pchannel_nb = 0; EXEC SQL SELECT digi_nb, pchannel_nb, digi_channel INTO :digi_nb, :digi_pchannel_nb, :digi_channel FROM NCEDCDBA.STATION_DIGITIZER_PCHANNEL WHERE STA = :sta AND NET = :net AND DATA_NB = :data_nb AND DATA_PCHANNEL = :data_pchannel_nb AND ONDATE = :ondate; if (FlagVerbose) printf ("\t DIGI_NB = %d -- PCHANNEL_NB = %d -- DIGI_CHANNEL = %d\n", digi_nb, digi_pchannel_nb, digi_channel); if ((digi_nb == 0) || (digi_pchannel_nb == 0)) Flag = 0; else { /* Retrieving ditigizer serial number */ strcpy (serial_nb, ""); EXEC SQL SELECT SERIAL_NB INTO :serial_nb FROM NCEDCDBA.STATION_DIGITIZER WHERE STA = :sta AND NET = :net AND DIGI_NB = :digi_nb AND ONDATE = :ondate; Remove_Blank (serial_nb); if (FlagVerbose) printf ("\t SERIAL_NB = %s\n", serial_nb); if (strlen (serial_nb) == 0) { printf ("Error: Problem with digitizer serial number.\n"); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Retrieving board number */ board_nb = 0; EXEC SQL SELECT BOARD_NB INTO :board_nb FROM NCEDCDBA.DATALOGGER_BOARD WHERE SERIAL_NB = :serial_nb AND DATA_ID = :data_id; if (FlagVerbose) printf ("\t BOARD_NB = %d\n", board_nb); if (board_nb == 0) { printf ("Error: Problem with datalogger board.\n"); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Retrieving digitizer sensitivity */ digi_sens = -1.; EXEC SQL SELECT SENSITIVITY INTO :digi_sens FROM NCEDCDBA.DATALOGGER_MODULE WHERE DATA_ID = :data_id AND BOARD_NB = :board_nb AND MODULE_NB = :digi_channel; if (FlagVerbose) printf ("\t SENSITIVITY = %f\n", digi_sens); if (digi_sens == (-1.)) { printf ("Error: Problem with digitizer sensitivity.\n"); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Testing if filter/amplifier is present */ filamp_nb = 0; filamp_pchannel_nb = 0; EXEC SQL SELECT FILAMP_NB, PCHANNEL_NB INTO :filamp_nb, :filamp_pchannel_nb FROM NCEDCDBA.STATION_FILAMP_PCHANNEL WHERE STA = :sta AND NET = :net AND ONDATE = :ondate AND NEXT_HARD_TYPE = 'D' AND NEXT_HARD_NB = :digi_nb AND NEXT_HARD_PCHANNEL = :digi_pchannel_nb; if (FlagVerbose) printf ("\t FILAMP_NB = %d -- PCHANNEL_NB = %d\n", filamp_nb, filamp_pchannel_nb); /* Retrieving filter-amplifier and/or sensor information */ if (filamp_nb == 0) { EXEC SQL SELECT SENSOR_NB, COMPONENT_NB, DIP, AZIMUTH INTO :sensor_nb, :component_nb, :dip, :azimuth FROM NCEDCDBA.STATION_SENSOR_COMPONENT WHERE STA = :sta AND NET = :net AND ONDATE = :ondate AND NEXT_HARD_TYPE = 'D' AND NEXT_HARD_NB = :digi_nb AND NEXT_HARD_PCHANNEL = :digi_pchannel_nb; } else { EXEC SQL SELECT SENSOR_NB, COMPONENT_NB, DIP, AZIMUTH INTO :sensor_nb, :component_nb, :dip, :azimuth FROM NCEDCDBA.STATION_SENSOR_COMPONENT WHERE STA = :sta AND NET = :net AND ONDATE = :ondate AND NEXT_HARD_TYPE = 'F' AND NEXT_HARD_NB = :filamp_nb AND NEXT_HARD_PCHANNEL = :filamp_pchannel_nb; EXEC SQL SELECT FILAMP_ID INTO :filamp_id FROM NCEDCDBA.STATION_FILAMP WHERE STA = :sta AND NET = :net AND ONDATE = :ondate AND FILAMP_NB = :filamp_nb; } if (FlagVerbose) printf ("\t SENSOR_NB = %d -- COMPONENT_NB = %d\n", sensor_nb, component_nb); /* Retrieving sensor identifier */ sensor_id = 0; EXEC SQL SELECT SENSOR_ID INTO :sensor_id FROM NCEDCDBA.STATION_SENSOR WHERE STA = :sta AND NET = :net AND ONDATE = :ondate AND SENSOR_NB = :sensor_nb; if (FlagVerbose) printf ("\t SENSOR_ID = %d\n", sensor_id); if (sensor_id == 0) { printf ("Error: Problem with sensor identifier. [%s / %s / %s / %d]\n", sta, net, ondate, sensor_nb); EXEC SQL COMMIT WORK RELEASE; exit (0); } /* Retrieving sensor name */ EXEC SQL SELECT name INTO :name FROM NCEDCDBA.SENSOR WHERE SENSOR_ID = :sensor_id; Remove_Blank (name); /* Retrieving sensor response and sensitivity */ EXEC SQL SELECT SEQRESP_ID, SENSITIVITY INTO :seqresp_id, :sensor_sens FROM NCEDCDBA.SENSOR_COMPONENT WHERE SENSOR_ID = :sensor_id AND COMPONENT_NB = :component_nb; /* Retrieving sensor natural frequency and damping */ if (!strcmp (unitname, "M/S")) { EXEC SQL DECLARE nfd1 CURSOR FOR SELECT CORNER_FREQ, DAMPING_VALUE FROM NCEDCDBA.RESPONSE_HP WHERE HP_ID IN (SELECT RESP_ID FROM NCEDCDBA.RESPONSE WHERE SEQRESP_ID = :seqresp_id AND RESP_TYPE = 'H'); EXEC SQL OPEN nfd1; EXEC SQL FETCH nfd1 INTO nat_freq:ind1, damping:ind2; if ((ind1 == (-1)) || (ind2 == (-1))) printf ("[WARNING: %d %d]\n", ind1, ind2); EXEC SQL CLOSE nfd1; } else { EXEC SQL DECLARE nfd2 CURSOR FOR SELECT CORNER_FREQ, DAMPING_VALUE FROM NCEDCDBA.RESPONSE_LP WHERE LP_ID IN (SELECT RESP_ID FROM NCEDCDBA.RESPONSE WHERE SEQRESP_ID = :seqresp_id AND RESP_TYPE = 'L'); EXEC SQL OPEN nfd2; EXEC SQL FETCH nfd2 INTO nat_freq:ind1, damping:ind2; if ((ind1 == (-1)) || (ind2 == (-1))) printf ("[WARNING: %d %d]\n", ind1, ind2); EXEC SQL CLOSE nfd2; } /* Testing if period */ if (nat_freq < 0) nat_freq = (-1.)/nat_freq; /* Testing FIR anti-aliasing cut-off frequency */ if ( ((samprate * .4) < nat_freq) && (!strcmp (unitname, "M/S")) ) lp_filter = hp_filter = samprate * .4; else { /* Retrieving low-pass filter corner frequency */ if (!strcmp (unitname, "M/S")) lp_filter = nat_freq; else { if (strstr (name, "Wilcoxon 731") == NULL) lp_filter = 0.; else { EXEC SQL SELECT SEQRESP_ID INTO :fseqresp_id FROM NCEDCDBA.FILAMP_PCHANNEL WHERE FILAMP_ID = :filamp_id AND PCHANNEL_NB = :filamp_pchannel_nb; EXEC SQL SELECT CORNER_FREQ INTO :lp_filter FROM NCEDCDBA.RESPONSE_HP WHERE HP_ID IN ( SELECT RESP_ID FROM NCEDCDBA.RESPONSE WHERE SEQRESP_ID = :fseqresp_id AND RESP_TYPE = 'H'); /* Testing if period */ if (lp_filter < 0) lp_filter = (-1.)/lp_filter; } } /* Retrieving high-pass filter corner frequency */ if (!strcmp (unitname, "M/S")) { if (strstr (name, "STS-1") == NULL) hp_filter = samprate * .4; else { EXEC SQL SELECT MIN(CORNER_FREQ) INTO :hp_filter:ind1 FROM NCEDCDBA.RESPONSE_LP WHERE LP_ID IN ( SELECT RESP_ID FROM NCEDCDBA.RESPONSE WHERE SEQRESP_ID = :seqresp_id AND RESP_TYPE = 'L'); if (ind1 == (-1)) printf ("\n[WARNING: %d]\n", ind1); /* Testing if period */ if (hp_filter < 0) hp_filter = (-1.)/hp_filter; if (hp_filter > (samprate * .4)) hp_filter = samprate * .4; } } else hp_filter = samprate * .4; } /* Retrieving Overall Gain */ EXEC SQL SELECT SENSITIVITY INTO :overall_gain FROM NCEDCDBA.SENSITIVITY WHERE STA = :sta AND NET = :net AND SEEDCHAN = :seedchan AND LOCATION = :location AND ONDATE = :ondate AND STAGE_SEQ = 0; } /* Fetching cursor channel */ EXEC SQL FETCH channel_cursor INTO :data_nb, :data_pchannel_nb; } /* Closing cursor */ EXEC SQL CLOSE channel_cursor; if ((!strcmp (location, " ")) || (!strcmp (location, ""))) strcpy (location, "--"); if (Flag) { strcpy (nondate , Convert_Date (ondate)); strcpy (noffdate, Convert_Date (offdate)); fprintf (fout, "%-3s %-5s %-3s %-2s %-s %-s\t%-8.6f\t%8.6f\t%8.6f\t%8.6f\t%7.5E\t%7.2f\t%7.2f\tDU/%-s\n", net, sta, seedchan, location, nondate, noffdate, nat_freq, lp_filter, hp_filter, damping, overall_gain, azimuth, dip, unitname); /* Populating Simple_Response Table */ sprintf (gain_units, "DU/%s", unitname); if (!strcmp (location, "--")) strcpy (location, " "); if (FlagPopulation) { EXEC SQL INSERT INTO Simple_Response (net, sta, seedchan, channel, channelsrc, location, natural_frequency, damping_constant, gain ,gain_units, low_freq_corner, high_freq_corner, ondate, offdate, lddate, dlogsens) VALUES (:net, :sta, :seedchan, :seedchan, 'SEED', :location, :nat_freq, :damping, :overall_gain, :gain_units, :lp_filter, :hp_filter, :ondate, :offdate, SYSDATE, :digi_sens); } /* Populating StaCorrections Table */ ml_corr = GetMlCorr (sta, net); if (ml_corr == 0.) ml_flag = 'D'; else ml_flag = 'F'; if (FlagPopulation) { EXEC SQL INSERT INTO StaCorrections (net, sta, seedchan, channel, channelsrc, location, auth, corr, corr_flag, corr_type, ondate, offdate, lddate) VALUES (:net, :sta, :seedchan, :seedchan, 'SEED', :location, 'NC', :ml_corr, :ml_flag, 'ml', :ondate, :offdate, SYSDATE); } } } EXEC SQL FETCH chacursor INTO :sta, :net, :seedchan, :location, :ondate, :offdate, :unit, :samprate; } EXEC SQL CLOSE chacursor; fclose (fout); /* Disconnect from the database. */ EXEC SQL COMMIT WORK RELEASE; exit(0); } /************************************************************************/ /* sql_error: /* Handle errors. Exit on any error /************************************************************************/ void sql_error() { char msg[512]; size_t buf_len, msg_len; EXEC SQL WHENEVER SQLERROR CONTINUE; buf_len = sizeof(msg); sqlglm (msg, &buf_len, &msg_len); printf ("\nORACLE error detected:"); printf ("\n%.*s \n", msg_len, msg); EXEC SQL ROLLBACK WORK RELEASE; exit(1); }