/* * Routines for filtering the data. * filter_data is the top-level routine, which handles all * the steps necessary. */ #include #include #include #include #include #include "filter.h" static int NINT(double t); static void adjustend ( double x[], double y[], int n, int cutoff, float *a, float *b ); static double part( int n, double x ); #define TWOPI 6.283185307 #define MAX_PARAM 30 static int numpt, numhm, numpm; /************************************************************************/ void filter_data ( double x[], /* Input - array containing sample dates */ double y[], /* Input - array containing measurement values */ double sig[], /* Input - array containing uncertainties of measurements */ int n0, /* Input - number of points in x, y, sig */ int cutoff1, /* Input - short term cutoff value in days */ int cutoff2, /* Input - long term cutoff value in days */ float interval, /* Input - regularly spaced sample interval in days */ int numpoly, /* Input - number of polynomial terms in function fit */ int numharm, /* Input - number of harmonic terms in function fit */ float pm[], /* Output - array containing coefficients of function fit */ double **covar, /* Output - array containing covariance matrix */ int *numparam, /* Output - Total number of parameters in pm */ double xfilt[], /* Output - dates of filtered data points */ double smooth[], /* Output - measurement values of filtered data */ double trend[], /* Output - Filter results of residuals using long term cutoff */ double deriv[], /* Output - derivative of trend + polynomial, i.e. growth rate */ int *nfilt, /* Output - number of points in xfilt, smooth, trend, deriv */ float *varf1, /* Output - variance of filter with short term cutoff */ float *varf2, /* Output - variance of filter with long term cutoff */ float *chisq, /* Output - chi squared value of function fit */ float *rsd1 /* Output - residual standard deviation of points about the function */ ) { float rinterval, cutoff, rmean, ca, cb; double dp, p; int i, j; double *work1, *work2; numpt = numpoly; numhm = numharm; numpm = numpoly + 2*numharm; *numparam = numpm; work1 = (double *) calloc (n0, sizeof(double)); work2 = (double *) calloc (MAXSIZE, sizeof(double)); #ifdef DEBUG printf ("Inside filter_data. n0 = %d Interval = %f\n", n0, interval); printf ("Cutoff 1 = %d, Cutoff 2 = %d\n",cutoff1,cutoff2); printf ("Numpoly = %d, Numharm = %d\n", numpoly,numharm); printf ("First point = %e,%e\n", x[0], y[0]); printf ("Last point = %e,%e\n",x[n0-1], y[n0-1]); #endif /* * Fit the function to the data */ if (numpm > 0) { lfit (x, y, sig, n0, pm, covar, numpm, chisq, partial); } #ifdef DEBUG printf ("Finished lfit\n"); for (i=0; i< numpm; i++) { printf ("pm[%d] = %e\n", i, pm[i]); } #endif /* * calculate residuals from fit */ for (i=0; i 0) { for (i=0; i< *nfilt; i++) { dp = 0.0; p = pm[numpoly-1]; for (j=numpoly-2; j>=0; j--) { dp = dp*xfilt[i] + p; p = p*xfilt[i] + pm[j]; } deriv[i] += dp; } } free (work1); free (work2); #ifdef DEBUG printf ("Finished derivative. Returning ...\n"); #endif return; } /************************************************************************/ void spline_f (x, y, n, domain, func, deriv, narg) double x[]; /* Input - array containing x values */ double y[]; /* Input - array containing y values */ int n; /* Input - Number of points in x, y */ double domain[]; /* Input - where to compute interpolated values along x axis */ double func[]; /* Output - the interpolated values */ double deriv[]; /* Output - the derivative of the interpolated values */ int narg; /* Input - the number of points in domain, func, deriv */ { double *y2; int i; #ifdef DEBUG printf ("inside spline, n = %d, narg = %d\n", n, narg); #endif y2 = (double *) calloc (n, sizeof(double)); spline (x, y, n, y2); for (i=0; i= 0; j--) { p = p*x + pm[j]; } return (p); } /************************************************************************/ double yearharmonic (pm, x, numpt, numh) float pm[]; /* Input - array of parameters from function fit */ double x; /* Input - Value at which to calculate polynomial */ int numpt; /* Input - Number of polynomial terms in pm[] */ int numh; /* Input - Number of harmonic terms in pm[] */ { double s, twopix; int i, ix; s = 0.0; twopix = TWOPI*x; for (i=0; i 1) { *sdev = sqrt ((sumsq - (sum*sum)/(float) n) / ((float) (n-1))); } return; } /************************************************************************/ double varnce (covar, n, x) double **covar; /* Input - array of covariances of parameters found by 'lfit' */ int n; /* Input - number of parameters */ double x; /* Input - time value at which to calculate variance */ { double s, s2, p, p2; int i, j; s = 0.0; s2 = 0.0; if (n == 0) return (0.0); for (i=0; i= x[n-1]-c)) { xp[k] = x[i]; yp[k] = y[i]; k++; } } fit (xp, yp, k, a, b, &siga, &sigb, &chi2); for (i=0; i= np that is a power of 2 */ n2 = 1; while (*np > n2) { n2 = n2<<1; } if (n2 > MAX_OBS) { fprintf (stderr, "Error: Too many data points to filter.\n"); fprintf (stderr, "Maybe try using larger interval size.\n"); exit(1); } /* * * zero pad to get 2**p points * n3 - number of zeros at front end of data * in order to remember where real data starts in filt[*] */ numzer = n2 - *np; inzhalf = numzer/2; for (i=0; i= x[i]) { i++; if (i >= (n-1)) break; } i--; /* If we are past the last actual data point, and the last two points were a pair, then the x data points will be the same, making w infinite. So instead of extrapolating, just set the point to 0 (which means assume it is equal to the function value at that time). */ if (x1[j] > x[n-1]) { filt[j+n3] = 0.0; } else { h = x1[j] - x[i]; w = (y[i+1]-y[i])/(x[i+1]-x[i]); filt[j+n3] = w*h + y[i]; } } /* * Transform the data (time >> frequency) */ realft (filt-1, n2, 1); #ifdef DEBUG printf ("Finished forward fft\n"); #endif /* * filter the data by multiplying the frequency domain data * with the response of a low pass filter. * b - frequency step size * dmaxfreq - nyquist frequency */ b = 1.0/(n2*dinterv); dmaxfreq = 1.0/(2*dinterv); cutoff2 = 1.0/cutoff; for (i=2; i> time) */ realft (filt-1, n2, -1); #ifdef DEBUG printf ("Finished inverse fft\n"); #endif /* * remove zero padding */ for (i=0; i< *np; i++) { filt[i] = filt[n3+i]; } #ifdef DEBUG printf ("Finished removing zero padding\n"); #endif return; } /**********************************************************************/ float fnfilt (float freq, float sigma, int power) { float z, f; /* Watch out for underflow */ z = pow ((double) freq/sigma, (double) power); if (z > 20.0) { f = 1e-10; } else { f = 1.0/(pow (2.0, (double) z)); } return (f); } /*****************************************/ static int NINT(double t) { if (t<0.0) { return ((int) t-.5); } else { if ((t+.5) > (double) (INT_MAX)) return ((INT_MAX)); else return ((int) (t+.5)); } }