home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)filter1d.c 2.19 3/13/95
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
- /*
- * filter1d will read N colums of data from file/stdin and return
- * filtered output at user-selected positions. The time variable
- * can be in any specified column of the input. Several filters
- * are available, with robustness as an option.
- *
- * Filters: Boxcar, Cosine Arch, Gaussian, Median, or Mode.
- * Robust: Option replaces outliers with medians in filter.
- * Output: At input times, or from t_start to t_stop by t_int.
- * Lack: Option checks for data gaps in input series.
- * Symmetry: Option checks for asymmetry in filter window.
- * Quality: Option checks for low mean weight in window.
- *
- * Author: Walter H. F. Smith
- * Date: 13 January, 1989
- * Version: 2.0, Developmental
- */
-
- #include "gmt.h"
-
- #define BOXCAR 0
- #define COS_ARCH 1
- #define GAUSSIAN 2
- #define MEDIAN 3
- #define MODE 4
- #define N_FILTERS 5
- #define CONVOLVE 2 /* If filter_type > CONVOLVE then a MEDIAN or MODE is selected */
-
- PFD get_weight[3]; /* Selects desired weight function. */
-
- double boxcar_weight (); /* Returns the weight for a given delta_time */
- double cosine_weight ();
- double gaussian_weight ();
-
- int get_median_scale(); /* Function that sets the median and L1 scale in a data window */
- int median(); /* New routine that performs iterative search to update last median */
- int mode(); /* Searches for the mode of the array */
- int load_data_and_check_extrema (); /* Does just what it says */
- int set_up_filter (); /* Creates filter weights or reads them from file and sets start & stop */
- int do_the_filter (); /* Does the job */
- int allocate_space (), free_space (); /* Does just what it says */
- BOOLEAN lack_check (); /* Tests for lack of data condition (optional) */
-
- double *f_wt; /* Pointer for array of filter coefficients */
- double *wt_sum; /* Pointer for array of weight sums [each column] */
- double *data_sum; /* Pointer for array of data * weight sums [columns] */
- double *min_loc; /* Pointer for array of values, one per [column] */
- double *max_loc;
- double *last_loc;
- double *this_loc;
- double *min_scl;
- double *max_scl;
- double *last_scl;
- double *this_scl;
- double **work; /* Pointer to array of pointers to doubles for work */
- double **data; /* Pointer to array of pointers to doubles for data */
- double dt; /* Delta time resolution for filter computation */
- double q_factor; /* Quality level for mean weights or n in median */
- double filter_width; /* Full width of filter in user's units */
- double half_width;
- double ignore_val; /* Value to skip over in input stream */
- double t_start; /* x-value of first output point */
- double t_stop; /* x-value of last output point */
- double t_int; /* Output interval */
- double sym_coeff = 0.0; /* Symmetry coefficient */
- double lack_width = 0.0; /* Lack of data width */
-
- int *n_this_col; /* Pointer to array of counters [one per column] */
- int *n_left; /* Pointer to array of counters [one per column] */
- int *n_right; /* Pointer to array of counters [one per column] */
-
- int n_rows; /* Number of rows of input */
- int n_cols = 2; /* Number of columns of input */
- int t_col = 0; /* Column of time abscissae (independent variable) */
- int n_f_wts; /* Number of filter weights */
- int half_n_f_wts; /* Half the number of filter weights */
- int n_row_alloc = GMT_CHUNK; /* Number of rows of data to allocate */
- int n_work_alloc = GMT_CHUNK; /* Number of rows of workspace to allocate */
- int filter_type = 0; /* Flag indicating desired filter type */
-
- BOOLEAN *good_one; /* Pointer to array of logicals [one per column] */
-
- BOOLEAN use_ends = FALSE; /* True to start/stop at ends of series instead of 1/2 width inside */
- BOOLEAN check_asym = FALSE; /* TRUE to test whether the data are asymmetric about the output time */
- BOOLEAN check_lack = FALSE; /* TRUE to test for lack of data (gap) in the filter window */
- BOOLEAN check_q = FALSE; /* TRUE to test average weight or N in median */
- BOOLEAN robust = FALSE; /* Look for outliers in data when TRUE */
- BOOLEAN equidist = TRUE; /* Data is evenly sampled in t */
- BOOLEAN out_at_time = FALSE; /* TRUE when output is required at evenly spaced intervals */
- BOOLEAN ignore_test = FALSE; /* TRUE when input values that eqaul ignore_val should be discarded */
- BOOLEAN error = FALSE;
- BOOLEAN single_precision = FALSE;
- BOOLEAN b_in = FALSE;
- BOOLEAN b_out = FALSE;
-
- char buffer[512]; /* Used to scan input lines */
-
- FILE *fp_in = NULL; /* File pointer to data file or stdin */
- FILE *fp_wt = NULL; /* File pointer to custom weight coefficients (optional) */
-
- main (argc, argv)
- int argc;
- char **argv;
- {
-
- int i;
-
- argc = gmt_begin (argc, argv);
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- switch (argv[i][1]) {
-
- /* Common parameters */
-
- case 'H':
- case 'V':
- case ':':
- case '\0':
- error += get_common_args (argv[i], 0, 0, 0, 0);
- break;
-
- /* Supplemental parameters */
-
- case 'b':
- single_precision = !(argv[i][strlen(argv[i])-1] == 'd');
- if (argv[i][2] == 'i')
- b_in = TRUE;
- else if (argv[i][2] == 'o')
- b_out = TRUE;
- else
- b_in = b_out = TRUE;
- break;
-
- case 'F': /* Filter selection */
- switch (argv[i][2]) {
- case 'B':
- robust = TRUE;
- case 'b':
- filter_type = BOXCAR;
- filter_width = atof (&argv[i][3]);
- break;
- case 'C':
- robust = TRUE;
- case 'c':
- filter_type = COS_ARCH;
- filter_width = atof (&argv[i][3]);
- break;
- case 'G':
- robust = TRUE;
- case 'g':
- filter_type = GAUSSIAN;
- filter_width = atof (&argv[i][3]);
- break;
- case 'M':
- robust = TRUE;
- case 'm':
- filter_type = MEDIAN;
- filter_width = atof (&argv[i][3]);
- break;
- case 'P':
- robust = TRUE;
- case 'p':
- filter_type = MODE;
- filter_width = atof (&argv[i][3]);
- break;
- case 'F':
- robust = TRUE;
- case 'f':
- if ((fp_wt = fopen(&argv[i][3],"r")) == NULL) {
- fprintf (stderr, "filter1d: Cannot open file %s\n", &argv[i][3]);
- exit(-1);
- }
- break;
- default:
- error = TRUE;
- break;
- }
- break;
-
- case 'D':
- dt = atof (&argv[i][2]);
- equidist = FALSE;
- break;
- case 'E':
- use_ends = TRUE;
- break;
- case 'I':
- ignore_val = atof (&argv[i][2]);
- ignore_test = TRUE;
- break;
- case 'L':
- check_lack = TRUE;
- lack_width = atof (&argv[i][2]);
- break;
- case 'N':
- sscanf (&argv[i][2], "%d/%d", &n_cols, &t_col);
- break;
- case 'Q':
- q_factor = atof(&argv[i][2]);
- check_q = TRUE;
- break;
- case 'S':
- check_asym = TRUE;
- sym_coeff = atof (&argv[i][2]);
- break;
- case 'T':
- sscanf (&argv[i][2], "%lf/%lf/%lf", &t_start, &t_stop, &t_int);
- out_at_time = TRUE;
- if (t_int == 0.0) error = TRUE;
- break;
- default:
- error = TRUE;
- gmt_default_error (argv[i][1]);
- break;
- }
- }
- else {
- if ((fp_in = fopen(argv[i],"r")) == NULL) {
- fprintf (stderr, "filter1d: Cannot open file %s\n", argv[i]);
- exit(-1);
- }
- }
- }
-
- if (argc == 1 || gmt_quick) {
- fprintf (stderr, "filter1d %s - Time domain filtering of 1-D time series\n\n", GMT_VERSION);
- fprintf (stderr, "usage: filter1d [infile] -F<type><width> [-D<increment>] [-E]\n");
- fprintf (stderr, "\t[-H] [-I<ignore_val>] [-L<lack_width>] [-N<n_cols>/<t_col>]\n");
- fprintf (stderr, "\t[-Q<q_factor>] [-S<symmetry_factor>] [-T<start>/<stop>/<int>] [-V] [-b[i|o]i[d]]\n\n");
-
- if (gmt_quick) exit (-1);
-
-
- fprintf (stderr, "\tfilter1d is a general time domain filter for multiple time series data.\n");
- fprintf (stderr, "\t\tThe user specifies the number of columns of input and which column is the time.\n");
- fprintf (stderr, "\t\t(See N option below). The fastest operation occurs when the input time series are\n");
- fprintf (stderr, "\t\tequally spaced and have no gaps or outliers and the special options are not needed.\n");
- fprintf (stderr, "\t\tfilter1d has options L,Q,S for unevenly sampled data with gaps and outliers.\n\n");
-
- fprintf (stderr, "\t-F sets Filtertype, type is one of b(oxcar), c(osine arch), g(aussian), m(edian),\n");
- fprintf (stderr, "\t\tor p(maximum liklihood Probability estimator -- a mode estimator),\n");
- fprintf (stderr, "\t\tand specify full filter <width> in same units as time column,\n");
- fprintf (stderr, "\t\tOR, use Ff<name> to give the name of a one-column file of your own coefficients.\n");
- fprintf (stderr, "\t\tUpper case type B, C, G, M, P, F will use robust filter versions:\n");
- fprintf (stderr, "\t\ti.e., replace outliers (2.5 L1 scale off median) with median during filtering.\n");
- fprintf (stderr, "\n\tOPTIONS:\n");
-
- fprintf (stderr, "\t-D<increment> is used when series is NOT equidistantly sampled.\n");
- fprintf (stderr, "\t\tThen <increment> will be the abscissae resolution, i.e. all abscissae\n");
- fprintf (stderr, "\t\twill be rounded off to a multiple of <increment>.\n");
- fprintf (stderr, "\t-E include Ends of time series in output. Default loses half_width at each end.\n");
- explain_option ('H');
- fprintf (stderr, "\t-I to ignore values; If an input value == <ignore_val> it will be set to NaN.\n");
- fprintf (stderr, "\t-L<width> checks for Lack of data condition. If input data has a gap exceeding\n");
- fprintf (stderr, "\t\t<width> then no output will be given at that point. Default does not check Lack.\n");
- fprintf (stderr, "\t-N<n_cols>/<t_col> sets # columns in input and which column contains the independent\n");
- fprintf (stderr, "\t\tvariable (time). The left-most column is # 0, the right-most is # (<n_cols> - 1).\n");
- fprintf (stderr, "\t\tDefault is <n_cols> = 2, <t_col> = 0; i.e. file has t, f(t) pairs.\n");
- fprintf (stderr, "\t-Q<q_factor> assess Quality of output value by checking mean weight in convolution.\n");
- fprintf (stderr, "\t\tEnter <q_factor> between 0 and 1. If mean weight < q_factor, output is suppressed\n");
- fprintf (stderr, "\t\tat this point. Default does not check Quality.\n");
- fprintf (stderr, "\t-S<symmetry_factor> checks symmetry of data about window center. Enter a factor\n");
- fprintf (stderr, "\t\tbetween 0 and 1. If ( (abs(n_left - n_right)) / (n_left + n_right) ) > factor,\n");
- fprintf (stderr, "\t\tthen no output will be given at this point. Default does not check Symmetry.\n");
- fprintf (stderr, "\t-T make evenly spaced timesteps from <start> to <stop> by <int>. Default uses input times.\n");
- explain_option ('V');
- fprintf (stderr, "\t-b means binary (double) i/o. Append i or o if only input OR output is binary\n");
- fprintf (stderr, "\t Append d for double precision [Default is single precision].\n"); explain_option ('.');
- exit (-1);
- }
-
- /* Check arguments */
-
- if (out_at_time && (t_stop - t_start) < filter_width) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -T option: Output interval < filterwidth\n", gmt_program);
- error++;
- }
- if (check_lack && (lack_width < 0.0 || lack_width > filter_width) ) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -L option: Unreasonable lack-of-data interval\n", gmt_program);
- error++;
- }
- if (check_asym && (sym_coeff < 0.0 || sym_coeff > 1.0) ) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -S option: Enter a factor between 0 and 1\n", gmt_program);
- error++;
- }
- if (filter_type < 0 || filter_type >= N_FILTERS) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -F option. Correct syntax:\n", gmt_program);
- fprintf (stderr, "-FX<width>, X one of BbCcGgMmPpFf\n");
- error++;
- }
- if (t_col >= n_cols) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -N option. time column exceeds number of columns\n", gmt_program);
- error++;
- }
- if (check_q && q_factor < 0.0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -Q option: Enter a factor between 0 and 1\n", gmt_program);
- error++;
- }
- if (b_in && gmtdefs.io_header) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR. Binary input data cannot have header -H\n", gmt_program);
- error++;
- }
-
- if (error) exit (-1);
-
- if (filter_type > CONVOLVE) robust = FALSE;
-
- if (b_in) gmt_input = (single_precision) ? bin_float_input : bin_double_input;
- if (b_out) gmt_output = (single_precision) ? bin_float_output : bin_double_output;
-
- if (allocate_space () ) {
- fprintf(stderr,"filter1d: fatal error memory allocation.\n");
- free_space ();
- exit(-1);
- }
-
- if (load_data_and_check_extrema () ) {
- fprintf(stderr,"filter1d: fatal error during data read.\n");
- free_space ();
- exit(-1);
- }
-
- if (set_up_filter () ) {
- fprintf(stderr,"filter1d: fatal error during coefficient setup.\n");
- free_space ();
- exit(-1);
- }
-
- if (do_the_filter () ) {
- fprintf(stderr,"filter1d: fatal error in filtering routine.\n");
- free_space ();
- exit(-1);
- }
-
- free_space ();
-
- gmt_end (argc, argv);
- }
-
- int load_data_and_check_extrema ()
- {
-
- int i, more, n_fields;
- double last_time, new_time, *in;
-
- if (fp_in == NULL) fp_in = stdin;
-
- if (gmtdefs.io_header) for (i = 0; i < gmtdefs.n_header_recs; i++) {
- fgets (buffer, 512, fp_in);
- fputs (buffer, stdout);
- }
-
- n_rows = 0;
- if (robust || (filter_type == MEDIAN) ) {
- for (i = 0; i < n_cols; i++) {
- min_loc[i] = MAXDOUBLE;
- max_loc[i] = -MAXDOUBLE;
- }
- }
- last_time = -MAXDOUBLE;
-
- more = ((n_fields = gmt_input (fp_in, n_cols, &in)) == n_cols);
-
- while (more) {
-
- for (i = 0; i < n_cols; i++) {
- if (ignore_test && in[i] == ignore_val)
- data[i][n_rows] = gmt_NaN;
- else {
- data[i][n_rows] = in[i];
- if (robust || (filter_type == MEDIAN) ) {
- if (in[i] > max_loc[i]) max_loc[i] = in[i];
- if (in[i] < min_loc[i]) min_loc[i] = in[i];
- }
- }
- }
-
- if (!bad_float( (double)data[t_col][n_rows]) ) { /* Don't n_rows++ if time is bad this row */
-
- new_time = data[t_col][n_rows];
- n_rows++;
- if (new_time < last_time) {
- fprintf(stderr,"filter1d: Error! Time decreases at line # %d\n", n_rows);
- fprintf(stderr,"\tUse UNIX utility sort and then try again.\n");
- return(-1);
- }
- last_time = new_time;
- }
-
- if (n_rows == n_row_alloc) { /* Need more memory */
- n_row_alloc += GMT_CHUNK;
- allocate_more_data_space ();
- }
-
- more = ((n_fields = gmt_input (fp_in, n_cols, &in)) == n_cols);
- }
-
- if (fp_in != stdin) fclose (fp_in);
-
- if (n_fields == -1) n_fields = 0; /* Ok to get EOF */
- if (n_fields%n_cols) { /* Got garbage or multiple segment subheader */
- fprintf (stderr, "%s: Cannot read line %d, aborts\n", gmt_program, n_rows);
- exit (-1);
- }
-
- for (i = 0; i < n_cols; i++) data[i] = (double *) memory ((char *)data[i], n_rows, sizeof (double), "filter1d");
- if (gmtdefs.verbose) fprintf (stderr, "filter1d: Read %d data lines\n", n_rows);
-
- /* Initialize scale parameters and last_loc based on min and max of data */
-
- if (robust || (filter_type == MEDIAN) ) {
- for (i = 0; i < n_cols; i++) {
- min_scl[i] = 0.0;
- max_scl[i] = 0.5 * (max_loc[i] - min_loc[i]);
- last_scl[i] = 0.5 * max_scl[i];
- last_loc[i] = 0.5 * (max_loc[i] + min_loc[i]);
- }
- }
-
- return (0);
- }
-
- int set_up_filter()
- {
- int i, i1, i2;
- double t_0, t_1, time, w_sum;
- BOOLEAN normalize = FALSE;
-
-
-
- t_0 = data[t_col][0];
- t_1 = data[t_col][n_rows-1];
- if (equidist) dt = (t_1 - t_0) / (n_rows - 1);
-
-
- if (fp_wt != NULL) {
- f_wt = (double *) memory (CNULL, n_work_alloc, sizeof(double), "filter1d");
- n_f_wts = 0;
- while (fscanf (fp_wt,"%lf\n", &f_wt[n_f_wts]) != EOF) {
- n_f_wts++;
- if (n_f_wts == n_work_alloc) { /* Need more memory */
- n_work_alloc += GMT_CHUNK;
- allocate_more_work_space ();
- }
- }
- fclose (fp_wt);
- half_n_f_wts = n_f_wts / 2;
- half_width = half_n_f_wts * dt;
- f_wt = (double *) memory ((char *)f_wt, n_f_wts, sizeof (double), "filter1d");
- if (gmtdefs.verbose) fprintf (stderr, "filter1d: Read %d filter weights from file.\n", n_f_wts);
- }
- else if (filter_type <= CONVOLVE) {
-
- get_weight[BOXCAR] = (PFD)boxcar_weight;
- get_weight[COS_ARCH] = (PFD)cosine_weight;
- get_weight[GAUSSIAN] = (PFD)gaussian_weight;
- half_width = 0.5 * filter_width;
- half_n_f_wts = floor (half_width / dt);
- n_f_wts = 2 * half_n_f_wts + 1;
-
- f_wt = (double *) memory (CNULL, n_f_wts, sizeof(double), "filter1d");
- for (i = 0; i <= half_n_f_wts; i++) {
- time = i * dt;
- i1 = half_n_f_wts - i;
- i2 = half_n_f_wts + i;
- f_wt[i1] = f_wt[i2] = ( *get_weight[filter_type]) (time, half_width);
- }
- if (normalize) {
- w_sum = 0.0;
- for (i = 0; i < n_f_wts; i++) w_sum += f_wt[i];
- for (i = 0; i < n_f_wts; i++) f_wt[i] /= w_sum;
- }
- }
- else {
- half_width = 0.5 * filter_width;
- }
-
- /* Initialize start/stop time */
-
- if (out_at_time) {
-
- if (use_ends) {
- while (t_start < t_0) t_start += t_int;
- while (t_stop > t_1) t_stop -= t_int;
- }
- else {
- while ( (t_start - half_width) < t_0) t_start += t_int;
- while ( (t_stop + half_width) > t_1) t_stop -= t_int;
- }
- }
- else {
- if (use_ends) {
- t_start = t_0;
- t_stop = t_1;
- }
- else {
- for (i = 0; (data[t_col][i] - t_0) < half_width; i++);
- t_start = data[t_col][i];
- for (i = n_rows - 1; (t_1 - data[t_col][i]) < half_width; i--);
- t_stop = data[t_col][i];
- }
- }
-
- if (gmtdefs.verbose) fprintf (stderr, "F width: %lg Resolution: %lg Start: %lg Stop: %lg\n",
- filter_width, dt, t_start, t_stop);
-
- return(0);
- }
-
- int do_the_filter ()
- {
-
- int i_row, i_col, left, right, n_l, n_r, iq, i_f_wt;
- int i_t_output, n_in_filter, n_for_call, n_good_ones;
- double time, delta_time, *outval, wt, val, med, scl;
-
- outval = (double *)memory (CNULL, n_cols, sizeof (double), "filter1d");
-
- if(!out_at_time) { /* Position i_t_output at first output time */
- for(i_t_output = 0; data[t_col][i_t_output] < t_start; i_t_output++);
- }
- time = t_start;
- left = right = 0; /* Left/right end of filter window */
-
- iq = rint(q_factor);
-
- while (time <= t_stop) {
- while ((time - data[t_col][left]) > half_width) left++;
- while (right < n_rows && (data[t_col][right] - time) <= half_width) right++;
- n_in_filter = right - left;
- if ( (!(n_in_filter)) || (check_lack && ( (filter_width / n_in_filter) > lack_width) ) ) {
- if (out_at_time)
- time += t_int;
- else {
- i_t_output++;
- time = (i_t_output < n_rows) ? data[t_col][i_t_output] : t_stop + 1.0;
- }
- continue;
- }
-
- for (i_col = 0; i_col < n_cols; i_col++) {
- n_this_col[i_col] = 0;
- wt_sum[i_col] = 0.0;
- data_sum[i_col] = 0.0;
- if (i_col == t_col) {
- good_one[i_col] = FALSE;
- }
- else if (check_lack) {
- good_one[i_col] = !(lack_check(i_col, left, right));
- }
- else {
- good_one[i_col] = TRUE;
- }
- if (check_asym) {
- n_left[i_col] = 0;
- n_right[i_col] = 0;
- }
- }
-
- if (robust || filter_type > CONVOLVE) {
- if (n_in_filter > n_work_alloc) {
- n_work_alloc = n_in_filter;
- allocate_more_work_space ();
- }
- for (i_row = left; i_row < right; i_row++) {
- for (i_col = 0; i_col < n_cols; i_col++) {
- if (!(good_one[i_col])) continue;
- if (!bad_float( (double)data[i_col][i_row])) {
- work[i_col][n_this_col[i_col]] = data[i_col][i_row];
- n_this_col[i_col]++;
- if (check_asym) {
- if (data[t_col][i_row] < time) n_left[i_col]++;
- if (data[t_col][i_row] > time) n_right[i_col]++;
- }
- }
- }
- }
- if (check_asym) {
- for (i_col = 0; i_col < n_cols; i_col++) {
- if (!(good_one[i_col])) continue;
- n_l = n_left[i_col];
- n_r = n_right[i_col];
- if ((((double)abs(n_l - n_r))/(n_l + n_r)) > sym_coeff) good_one[i_col] = FALSE;
- }
- }
- if ( (filter_type > CONVOLVE) && check_q) {
- for (i_col = 0; i_col < n_cols; i_col++) {
- if (n_this_col[i_col] < iq) good_one[i_col] = FALSE;
- }
- }
-
- for (i_col = 0; i_col < n_cols; i_col++) {
- if (good_one[i_col]) {
- n_for_call = n_this_col[i_col];
- get_robust_estimates (i_col, n_for_call, robust);
- }
- }
-
- } /* That's it for the robust work */
-
- if (filter_type > CONVOLVE) {
-
- /* Need to count how many good ones; use data_sum area */
-
- n_good_ones = 0;
- for (i_col = 0; i_col < n_cols; i_col++) {
- if (i_col == t_col) {
- data_sum[i_col] = time;
- }
- else if (good_one[i_col]) {
- data_sum[i_col] = this_loc[i_col];
- n_good_ones++;
- }
- else {
- data_sum[i_col] = gmt_NaN;
- }
- }
- if (n_good_ones) gmt_output (stdout, n_cols, data_sum);
- }
-
- else {
-
- if (robust) for (i_col = 0; i_col < n_cols; i_col++) n_this_col[i_col] = 0;
-
- for (i_row = left; i_row < right; i_row++) {
- delta_time = time - data[t_col][i_row];
- i_f_wt = half_n_f_wts + floor(0.5 + delta_time/dt);
- if ( (i_f_wt < 0) || (i_f_wt >= n_f_wts) ) continue;
-
- for(i_col = 0; i_col < n_cols; i_col++) {
- if ( !(good_one[i_col]) ) continue;
- if (!bad_float( (double)data[i_col][i_row])) {
- wt = f_wt[i_f_wt];
- val = data[i_col][i_row];
- if (robust) {
- med = this_loc[i_col];
- scl = this_scl[i_col];
- val = ((fabs(val-med)) > (2.5 * scl)) ? med : val;
- }
- else if (check_asym) { /* This wasn't already done */
- if (data[t_col][i_row] < time) n_left[i_col]++;
- if (data[t_col][i_row] > time) n_right[i_col]++;
- }
- wt_sum[i_col] += wt;
- data_sum[i_col] += (wt * val);
- n_this_col[i_col]++;
- }
- }
- }
- n_good_ones = 0;
- for (i_col = 0; i_col < n_cols; i_col++) {
- if ( !(good_one[i_col]) ) continue;
- if ( !(n_this_col[i_col]) ) {
- good_one[i_col] = FALSE;
- continue;
- }
- if (check_asym && !(robust) ) {
- n_l = n_left[i_col];
- n_r = n_right[i_col];
- if ((((double)abs(n_l - n_r))/(n_l + n_r)) > sym_coeff) {
- good_one[i_col] = FALSE;
- continue;
- }
- }
- if (check_q && ((wt_sum[i_col] / n_this_col[i_col]) < q_factor)) {
- good_one[i_col] = FALSE;
- continue;
- }
- n_good_ones++;
- }
- if (n_good_ones) {
- for (i_col = 0; i_col < n_cols; i_col++) {
- if (i_col == t_col)
- outval[i_col] = time;
- else if (good_one[i_col])
- outval[i_col] = data_sum[i_col] / wt_sum[i_col];
- else
- outval[i_col] = gmt_NaN;
- }
- gmt_output (stdout, n_cols, outval);
- }
- }
-
- /* Go to next output time */
-
- if (out_at_time)
- time += t_int;
- else {
- i_t_output++;
- time = (i_t_output < n_rows) ? data[t_col][i_t_output] : t_stop + 1.0;
- }
- }
-
- free ((char *)outval);
-
- return(0);
- }
-
- int allocate_space ()
- {
-
- int i;
-
- data = (double **) memory (CNULL, n_cols, sizeof(double *), "filter1d");
- for (i = 0; i < n_cols; i++) data[i] = (double *) memory (CNULL, n_row_alloc, sizeof(double), "filter1d");
-
- wt_sum = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- data_sum = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- n_this_col = (int *) memory (CNULL, n_cols, sizeof(int), "filter1d");
- good_one = (int *) memory (CNULL, n_cols, sizeof(int), "filter1d");
-
- if (check_asym) n_left = (int *) memory (CNULL, n_cols, sizeof(int), "filter1d");
- if (check_asym) n_right = (int *) memory (CNULL, n_cols, sizeof(int), "filter1d");
-
- if (robust || (filter_type > CONVOLVE) ) { /* Then we need workspace */
-
- work = (double **) memory (CNULL, n_cols, sizeof(double *), "filter1d");
- for (i = 0; i < n_cols; i++) work[i] = (double *) memory (CNULL, n_work_alloc, sizeof(double), "filter1d");
- min_loc = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- max_loc = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- last_loc = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- this_loc = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- min_scl = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- max_scl = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- this_scl = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- last_scl = (double *) memory (CNULL, n_cols, sizeof(double), "filter1d");
- }
- return (0);
- }
-
- int allocate_more_data_space ()
- {
- int i;
-
- for (i = 0; i < n_cols; i++) data[i] = (double *) memory ((char *)data[i], n_row_alloc, sizeof(double), "filter1d");
-
- return (0);
- }
-
- int allocate_more_work_space ()
- {
- int i;
-
- for (i = 0; i < n_cols; i++) work[i] = (double *) memory ((char *)work[i], n_work_alloc, sizeof(double), "filter1d");
-
- return (0);
- }
-
-
- int free_space ()
- {
- free( (char *)data);
- free( (char *)wt_sum);
- free( (char *)data_sum);
- free( (char *)n_this_col);
- free( (char *)good_one);
- free( (char *)n_left);
- free( (char *)n_right);
- free( (char *)work);
- free( (char *)min_loc);
- free( (char *)max_loc);
- free( (char *)last_loc);
- free( (char *)this_loc);
- free( (char *)min_scl);
- free( (char *)max_scl);
- free( (char *)last_scl);
- free( (char *)this_scl);
- return (0);
- }
-
- BOOLEAN lack_check (i_col, left, right)
- int i_col, left, right;
- {
-
- int last_row, this_row;
- BOOLEAN lacking = FALSE;
- double last_t;
-
- last_row = left;
- while (!(bad_float( (double)data[i_col][last_row])) && last_row < (right - 1)) last_row++;
-
- last_t = data[t_col][last_row];
- this_row = last_row + 1;
- while ( !(lacking) && this_row < (right - 1)) {
- while (!(bad_float( (double)data[i_col][this_row])) && this_row < (right - 1)) this_row++;
-
- if ( (data[t_col][this_row] - last_t) > lack_width)
- lacking = TRUE;
- else {
- last_t = data[t_col][this_row];
- last_row = this_row;
- this_row++;
- }
- }
- return (lacking);
- }
-
- int get_robust_estimates (j, n, both)
- int j, n, both;
- {
- int i, n_smooth, sort_me = TRUE;
- double low, high, last, temp;
-
- if (filter_type == MODE) {
-
- n_smooth = n / 2;
-
- mode(work[j], n, n_smooth, sort_me, &temp);
- }
- else {
-
- low = min_loc[j];
- high = max_loc[j];
- last = last_loc[j];
-
- median(work[j], n, low, high, last, &temp);
- }
-
- last_loc[j] = this_loc[j] = temp;
-
- if (both) {
- for (i = 0; i < n; i++)
- work[j][i] = fabs(work[j][i] - this_loc[j]);
- low = min_scl[j];
- high = max_scl[j];
- last = last_scl[j];
- median(work[j], n, low, high, last, &temp);
- last_scl[j] = this_scl[j] = temp;
- }
- return(0);
- }
-
- double boxcar_weight (radius, half_width)
- double radius, half_width;
- {
- double weight;
-
- if (radius > half_width)
- weight = 0.0;
- else
- weight = 1.0;
-
- return (weight);
- }
-
- double cosine_weight (radius, half_width)
- double radius, half_width;
- {
- double weight, cosine_constant;
- cosine_constant = M_PI / half_width;
- if (radius > half_width)
- weight = 0.0;
- else
- weight = 1.0 + cos (radius * cosine_constant);
-
- return (weight);
- }
-
- double gaussian_weight (radius, half_width)
- double radius, half_width;
- {
- double weight, gauss_constant;
- gauss_constant = -4.5 / (half_width * half_width);
- if (radius > half_width)
- weight = 0.0;
- else
- weight = exp (radius * radius * gauss_constant);
-
- return (weight);
- }
-