home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)trend1d.c 2.11 4/11/95
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
- /*
- * trend1d.c [<xy[w]file>] -F<output_flags> -N[f]<n_m_parameters>[r]
- * [-C<condition_#>] [-I[<confid>]] [-V] [-W]
- *
- * where:
- * [<xy[w]file>] is an ascii file with x y in first 2 columns [or
- * x y w in first 3 columns]. Default reads from stdin.
- * -F<output_flags> is a string of at least one, up to five, in
- * and order, from the set {x y m r w}. x,y = input,
- * m = model, r = residual = y-m, and w= weight used.
- * -N[f]<n_m_parameters>[r]
- * If iterative Robust fitting desired, use append r.
- * To fit a Fourier model, use -Nf.
- * Number of terms in the model is <n_m_parameters>.
- * Example: Robust quadratic polynomial: -N2r.
- * [-C<condition_#>] Cut off eigenvalue spectrum; use only eigen-
- * values such that (lambda_max / lambda[i]) < condition_#.
- * [-I[<confid>]] Iteratively Increment the number of model parameters,
- * searching for the significant model size, up to a maximum
- * set by <n_m_parameters>. We start with a 1 parameter
- * model and then iteratively increase the number of
- * model parameters, m, while m <= <n_m_parameters> &&
- * reduction in variance from i to i+1 is significant
- * at the <confid> level according to F test. If user sets
- * -I without giving <confid> then <confid> = 0.95.
- * [-V] Verbose operation.
- * [-W] Weighted data are input. Read 3 cols and use 3rd as weight.
- *
- *
- * Read stdin or file of x y pairs, or weighted pairs as x,y w data. Fit
- * a regression model y = f(x) + e, where e are error misfits and f(x) has
- * some user-prescribed functional form. Presently available models are
- * polynomials and Fourier series. The user may choose the number of terms
- * in the model to fit, whether to seek iterative refinement robust w.r.t.
- * outliers, and whether to seek automatic discovery of the significant
- * number of model parameters.
- *
- *
- * In trend1d I chose to construct the polynomial model using Chebyshev
- * Polynomials so that the user may easily compare the sizes of the
- * coefficients (and compare with a Fourier series as well). Tn(x)
- * is an n-degree polynomial with n zero-crossings in [-1,1] and n+1
- * extrema, at which the value of Tn(x) is +/- 1. It is this property
- * which makes it easy to compare the size of the coefficients.
- *
- * During model fitting the data x coordinate is normalized into the domain
- * [-1, 1] for Chebyshev Polynomial fitting, or into the domain [-pi, pi]
- * for Fourier series fitting. Before writing out the data the coordinate
- * is rescaled to match the original input values.
- *
- * An n degree polynomial can be written with terms of the form a0 + a1*x
- * + a2*x*x + ... But it can also be written using other polynomial
- * basis functions, such as a0*P0 + a1*P1 + a2*P2..., the Legendre
- * polynomials, and a0*T0 + a1*T1 + a2*T2..., the Chebyshev polynomials.
- * (The domain of the x values has to be in [-1, 1] in order to use P or T.)
- * It is well known that the ordinary polynomial basis 1, x, x*x, ... gives
- * terribly ill- conditioned matrices. The Ps and Ts do much better.
- * This is because the ordinary basis is far from orthogonal. The Ps
- * are orthogonal on [-1,1] and the Ts are orthogonal on [-1,1] under a
- * simple weight function.
- * Because the Ps have ordinary orthogonality on [-1,1], I expected them
- * to be the best basis for a regression model; best meaning that they
- * would lead to the most balanced G'G (matrix of normal equations) with
- * the smallest condition number and the most nearly diagonal model
- * parameter covariance matrix ((G'G)inverse). It turns out, however, that
- * the G'G obtained from the Ts is very similar and usually has a smaller
- * condition number than the Ps G'G. Both of these are vastly superior to
- * the usual polynomials 1, x, x*x. In a test with 1000 equally spaced
- * data and 8 model parameters, the Chebyshev system had a condition # = 10.6,
- * Legendre = 14.8, and traditional = 54722.7. For 1000 randomly spaced data
- * and 8 model parameters, the results were C = 13.1, L = 15.6, and P = 54916.6.
- * As the number of model parameters approaches the number of data, the
- * situation still holds, although all matrices get ill-conditioned; for 8
- * random data and 8 model parameters, C = 1.8e+05, L = 2.6e+05, P = 1.1e+08.
- * I expected the Legendre polynomials to have a covariance matrix more nearly
- * diagonal than that of the Chebyshev polynomials, but on this criterion also
- * the Chebyshev turned out to do better. Only as ndata -> n_model_parameters
- * does the Legendre covariance matrix do better than the Chebyshev. So for
- * all these reasons I use Chebyshev polynomials.
- *
- * Author: W. H. F. Smith
- * Date: 25 February 1991-1995.
- * Revised: 11 June, 1991-1995 for v2.0 of GMT-SYSTEM.
- */
-
- #include "gmt.h"
-
- #define N_OUTPUT_CHOICES 5
-
- #define POLYNOMIAL 0
- #define FOURIER 1
-
- struct DATA {
- double x;
- double y;
- double m;
- double r;
- double w;
- } *data;
-
- char format[20];
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- void read_data(), write_output(), transform_x(), untransform_x(), recompute_weights();
- void allocate_array_space(), free_the_memory(), calc_m_and_r(), move_model_a_to_b();
- void load_gtg_and_gtd(), solve_system();
-
- int i, j, n_data, n_outputs, n_model, n_model_max, model_type, np, significant, rank;
- int error = FALSE, weighted_input = FALSE, weighted_output = FALSE, robust = FALSE, increment = FALSE;
-
- double c_no = 1.0e06; /* Condition number for matrix solution */
- double confid = 0.51; /* Confidence interval for significance test */
- double *gtg, *v, *gtd, *lambda, *workb, *workz, *c_model, *o_model, *w_model, *work; /* Arrays */
- double xmin, xmax, c_chisq, o_chisq, w_chisq, scale = 1.0, prob;
- double get_chisq();
-
- char output_choice[N_OUTPUT_CHOICES];
- FILE *fp = NULL;
-
- argc = gmt_begin (argc, argv);
-
- model_type = POLYNOMIAL;
- n_outputs = 0;
- n_model_max = 0;
- for (i = 0; i < N_OUTPUT_CHOICES; i++) output_choice[i] = 0;
- sprintf (format, "%s\t\0", gmtdefs.d_format);
-
- 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 'F':
- j = 2;
- while (argv[i][j]) {
- switch (argv[i][j]) {
- case 'x':
- output_choice[j-2] = 'x';
- break;
- case 'y':
- output_choice[j-2] = 'y';
- break;
- case 'm':
- output_choice[j-2] = 'm';
- break;
- case 'r':
- output_choice[j-2] = 'r';
- break;
- case 'w':
- output_choice[j-2] = 'w';
- weighted_output = TRUE;
- break;
- default:
- error = TRUE;
- fprintf (stderr, "%s: GMT SYNTAX ERROR -F option. Unrecognized output choice %c\n", gmt_program, argv[i][j]);
- }
- n_outputs++;
- j++;
- }
- break;
- case 'C':
- c_no = atof(&argv[i][2]);
- break;
- case 'I':
- increment = TRUE;
- confid = (argv[i][2]) ? atof(&argv[i][2]) : 0.51;
- break;
- case 'N':
- if (argv[i][strlen (argv[i]) - 1] == 'r') robust = TRUE;
- j = 2;
- if (argv[i][j] == 'F' || argv[i][j] == 'f') {
- model_type = FOURIER;
- j++;
- }
- else if (argv[i][j] == 'P' || argv[i][j] == 'p') {
- model_type = POLYNOMIAL;
- j++;
- }
- if (argv[i][j])
- n_model_max = atoi(&argv[i][j]);
- else {
- error = TRUE;
- fprintf (stderr, "%s: GMT SYNTAX ERROR -N option. No model specified\n", gmt_program);
- }
- break;
- case 'W':
- weighted_input = TRUE;
- break;
- default:
- error = TRUE;
- gmt_default_error (argv[i][1]);
- break;
- }
- }
- else {
- if ((fp = fopen(argv[i], "r")) == NULL) {
- fprintf (stderr, "trend1d: Could not open file %s\n", argv[i]);
- error = TRUE;
- }
- }
- }
-
- if (argc == 1 || gmt_quick) {
- fprintf(stderr,"trend1d %s - Fit a [weighted] [robust] polynomial [or Fourier] model for y = f(x) to ascii xy[w]\n\n", GMT_VERSION);
- fprintf(stderr,"usage: trend1d -F<xymrw> -N[f]<n_model>[r] [<xy[w]file>] [-C<condition_#>]\n");
- fprintf(stderr,"\t[-H] [-I[<confidence>]] [-V] [-W] [-:]\n\n");
-
- if (gmt_quick) exit (-1);
-
- fprintf(stderr,"\t-F<xymrw> Choose at least 1, up to 5, any order, of xymrw for ascii output to stdout.\n");
- fprintf(stderr,"\t\tx=x, y=y, m=model, r=residual=y-m, w=weight. w determined iteratively if robust fit used.\n");
- fprintf(stderr,"\t-N fit a Polynomial [Default] or Fourier (-Nf) model with <n_model> terms.\n");
- fprintf(stderr,"\t\tAppend r for robust model. E.g., robust quadratic = -N3r.\n");
- fprintf (stderr, "\n\tOPTIONS:\n");
- fprintf(stderr,"\t[<xy[w]file>] name of ascii file, first 2 cols = x y [3 cols = x y w]. [Default reads stdin].\n");
- fprintf(stderr,"\t-C Truncate eigenvalue spectrum so matrix has <condition_#>. [Default = 1.0e06].\n");
- explain_option ('H');
- fprintf(stderr,"\t-I Iteratively Increase # model parameters, to a max of <n_model> so long as the\n");
- fprintf(stderr,"\t\treduction in variance is significant at the <confidence> level.\n");
- fprintf(stderr,"\t\tGive -I without a number to default to 0.51 confidence level.\n");
- explain_option ('V');
- fprintf(stderr,"\t-W Weighted input given, weights in 3rd column. [Default is unweighted].\n\n");
- explain_option (':');
- exit(-1);
- }
-
- if (c_no <= 1.0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -C option. Condition number must be larger than unity\n", gmt_program);
- error++;
- }
- if (confid < 0.0 || confid > 1.0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -C option. Give 0 < confidence level < 1.0\n", gmt_program);
- error++;
- }
- if (n_outputs > N_OUTPUT_CHOICES) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -F option. Too many output columns specified (%d)\n", gmt_program, n_outputs);
- error++;
- }
- if (n_model_max <= 0.0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -N option. A positive number of terms must be specified\n", gmt_program);
- error++;
- }
-
- if (error) exit (-1);
-
- np = n_model_max; /* Row dimension for matrices gtg and v */
- allocate_array_space(np, >g, &v, >d, &lambda, &workb, &workz, &c_model, &o_model, &w_model);
-
- read_data(&data, &n_data, &xmin, &xmax, weighted_input, &work, fp);
-
- if (xmin == xmax) {
- fprintf(stderr,"trend1d: Fatal error in input data. X min = X max.\n");
- exit(-1);
- }
- if (n_data == 0) {
- fprintf(stderr,"trend1d: Fatal error. Could not read any data.\n");
- exit(-1);
- }
- if (n_data < n_model_max) fprintf(stderr,"trend1d: Warning. Ill-posed problem. n_data < n_model_max.\n");
-
- transform_x(data, n_data, model_type, xmin, xmax); /* Set domain to [-1, 1] or [-pi, pi] */
-
- if (gmtdefs.verbose) {
- fprintf(stderr,"trend1d: Read %d data with X values from %.8lg to %.8lg\n", n_data, xmin, xmax);
- fprintf(stderr,"N_model\tRank\tChi_Squared\tSignificance\n");
- }
-
- if (increment) {
- n_model = 1;
-
- /* Fit first model */
- load_gtg_and_gtd(data, n_data, gtg, gtd, workb, n_model, np, model_type);
- solve_system(gtg, gtd, c_model, n_model, np, lambda, v, workb, workz, c_no, &rank);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- c_chisq = get_chisq(data, n_data, n_model);
- if (gmtdefs.verbose) fprintf(stderr,"%d\t%d\t%.8lg\t%d\n", n_model, rank, c_chisq, 1);
- if (robust) {
- do {
- recompute_weights(data, n_data, work, &scale);
- move_model_a_to_b(c_model, w_model, n_model, &c_chisq, &w_chisq);
- load_gtg_and_gtd(data, n_data, gtg, gtd, workb, n_model, np, model_type);
- solve_system(gtg, gtd, c_model, n_model, np, lambda, v, workb, workz, c_no, &rank);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- c_chisq = get_chisq(data, n_data, n_model);
- significant = sig_f(c_chisq, n_data-n_model, w_chisq, n_data-n_model, confid, &prob);
- if (gmtdefs.verbose) fprintf(stderr,"%d\t%d\t%.8lg\t%.3lg\n", n_model, rank, c_chisq, prob);
- } while (significant);
- /* Go back to previous model only if w_chisq < c_chisq */
- if (w_chisq < c_chisq) {
- move_model_a_to_b(w_model, c_model, n_model, &w_chisq, &c_chisq);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- if (weighted_output && n_model == n_model_max) recompute_weights(data, n_data, work, &scale);
- }
- }
- /* First [robust] model has been found */
-
- significant = TRUE;
- while(n_model < n_model_max && significant) {
- move_model_a_to_b(c_model, o_model, n_model, &c_chisq, &o_chisq);
- n_model++;
-
- /* Fit next model */
- load_gtg_and_gtd(data, n_data, gtg, gtd, workb, n_model, np, model_type);
- solve_system(gtg, gtd, c_model, n_model, np, lambda, v, workb, workz, c_no, &rank);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- c_chisq = get_chisq(data, n_data, n_model);
- if (gmtdefs.verbose) fprintf(stderr,"%d\t%d\t%.8lg\t%.3lg\n", n_model, rank, c_chisq, 1.00);
- if (robust) {
- do {
- recompute_weights(data, n_data, work, &scale);
- move_model_a_to_b(c_model, w_model, n_model, &c_chisq, &w_chisq);
- load_gtg_and_gtd(data, n_data, gtg, gtd, workb, n_model, np, model_type);
- solve_system(gtg, gtd, c_model, n_model, np, lambda, v, workb, workz, c_no, &rank);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- c_chisq = get_chisq(data, n_data, n_model);
- significant = sig_f(c_chisq, n_data-n_model, w_chisq, n_data-n_model, confid, &prob);
- if (gmtdefs.verbose) fprintf(stderr,"%d\t%d\t%.8lg\t%.3lg\n", n_model, rank, c_chisq, prob);
- } while (significant);
- /* Go back to previous model only if w_chisq < c_chisq */
- if (w_chisq < c_chisq) {
- move_model_a_to_b(w_model, c_model, n_model, &w_chisq, &c_chisq);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- if (weighted_output && n_model == n_model_max) recompute_weights(data, n_data, work, &scale);
- }
- }
- /* Next [robust] model has been found */
- significant = sig_f(c_chisq, n_data-n_model, o_chisq, n_data-n_model-1, confid, &prob);
- }
-
- if (!(significant) ) { /* Go back to previous [robust] model, stored in o_model */
- n_model--;
- rank--;
- move_model_a_to_b(o_model, c_model, n_model, &o_chisq, &c_chisq);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- if (robust && weighted_output) recompute_weights(data, n_data, work, &scale);
- }
- }
- else {
- n_model = n_model_max;
- load_gtg_and_gtd(data, n_data, gtg, gtd, workb, n_model, np, model_type);
- solve_system(gtg, gtd, c_model, n_model, np, lambda, v, workb, workz, c_no, &rank);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- c_chisq = get_chisq(data, n_data, n_model);
- if (gmtdefs.verbose) fprintf(stderr,"%d\t%d\t%.8lg\t%.3lg\n", n_model, rank, c_chisq, 1.00);
- if (robust) {
- do {
- recompute_weights(data, n_data, work, &scale);
- move_model_a_to_b(c_model, w_model, n_model, &c_chisq, &w_chisq);
- load_gtg_and_gtd(data, n_data, gtg, gtd, workb, n_model, np, model_type);
- solve_system(gtg, gtd, c_model, n_model, np, lambda, v, workb, workz, c_no, &rank);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- c_chisq = get_chisq(data, n_data, n_model);
- significant = sig_f(c_chisq, n_data-n_model, w_chisq, n_data-n_model, confid, &prob);
- if (gmtdefs.verbose) fprintf(stderr,"%d\t%d\t%.8lg\t%.3lg\n", n_model, rank, c_chisq, prob);
- } while (significant);
- /* Go back to previous model only if w_chisq < c_chisq */
- if (w_chisq < c_chisq) {
- move_model_a_to_b(w_model, c_model, n_model, &w_chisq, &c_chisq);
- calc_m_and_r(data, n_data, c_model, n_model, model_type, workb);
- if (weighted_output && n_model == n_model_max) recompute_weights(data, n_data, work, &scale);
- }
- }
- }
-
- if (gmtdefs.verbose) {
- fprintf(stderr,"Final model stats: N model parameters %d. Rank %d. Chi-Squared: %.8lg\n", n_model, rank, c_chisq);
- fprintf(stderr,"Model Coefficients:");
- for (i = 0; i < n_model; i++) fprintf (stderr, format, c_model[i]);
- fprintf(stderr,"\n");
- }
-
- untransform_x(data, n_data, model_type, xmin, xmax);
-
- write_output(data, n_data, output_choice, n_outputs);
-
- free_the_memory(gtg, v, gtd, lambda, workb, workz, c_model, o_model, w_model, data, work);
-
- gmt_end (argc, argv);
- }
-
- void read_data(data, n_data, xmin, xmax, weighted_input, work, fp)
- struct DATA **data;
- int *n_data, weighted_input;
- double *xmin, *xmax, **work;
- FILE *fp;
- {
-
- int i = 0, ix, iy, n_alloc = GMT_CHUNK;
- double xy[2];
- char buffer[512];
-
- if (fp == NULL) fp = stdin;
- (*data) = (struct DATA *) memory (CNULL, n_alloc, sizeof(struct DATA), "trend1d");
-
- ix = (gmtdefs.xy_toggle) ? 1 : 0; iy = 1 - ix; /* Set up which columns have x and y */
-
- while ( (fgets (buffer, 512, fp) ) != NULL) {
-
- if ((sscanf(buffer, "%lf %lf %lf", &xy[ix], &xy[iy], &(*data)[i].w)) != (2 + weighted_input)) {
- fprintf(stderr,"trend1d: Cannot read x y [w] from line %d\n", i+1);
- continue;
- }
- (*data)[i].x = xy[0];
- (*data)[i].y = xy[1];
- if (!(weighted_input)) (*data)[i].w = 1.0;
-
- if (i) {
- if (*xmin > (*data)[i].x) *xmin = (*data)[i].x;
- if (*xmax < (*data)[i].x) *xmax = (*data)[i].x;
- }
- else {
- *xmin = (*data)[i].x;
- *xmax = (*data)[i].x;
- }
- i++;
-
- if (i == n_alloc) {
- n_alloc += GMT_CHUNK;
- *data = (struct DATA *) memory ((char *)*data, n_alloc, sizeof(struct DATA), "trend1d");
- }
- }
- if (fp != stdin) fclose(fp);
-
- *data = (struct DATA *) memory ((char *)*data, i, sizeof(struct DATA), "trend1d");
- *work = (double *) memory (CNULL, i, sizeof(double), "trend1d");
-
- *n_data = i;
- }
-
- void allocate_array_space(np, gtg, v, gtd, lambda, workb, workz, c_model, o_model, w_model)
- int np;
- double **gtg, **v, **gtd, **lambda, **workb, **workz, **c_model, **o_model, **w_model;
- {
- *gtg = (double *) memory (CNULL, np*np, sizeof(double), "trend1d");
- *v = (double *) memory (CNULL, np*np, sizeof(double), "trend1d");
- *gtd = (double *) memory (CNULL, np, sizeof(double), "trend1d");
- *lambda = (double *) memory (CNULL, np, sizeof(double), "trend1d");
- *workb = (double *) memory (CNULL, np, sizeof(double), "trend1d");
- *workz = (double *) memory (CNULL, np, sizeof(double), "trend1d");
- *c_model = (double *) memory (CNULL, np, sizeof(double), "trend1d");
- *o_model = (double *) memory (CNULL, np, sizeof(double), "trend1d");
- *w_model = (double *) memory (CNULL, np, sizeof(double), "trend1d");
- }
-
- void write_output(data, n_data, output_choice, n_outputs)
- struct DATA *data;
- int n_data, n_outputs;
- char *output_choice;
- {
- int i, j;
- char format1[20], format2[20];
-
- sprintf (format1, "%s\t\0", gmtdefs.d_format);
- sprintf (format2, "%s\n\0", gmtdefs.d_format);
-
- for (i = 0; i < n_data; i++) {
- for (j = 0; j < n_outputs-1; j++) {
- switch (output_choice[j]) {
- case 'x':
- printf(format1, data[i].x);
- break;
- case 'y':
- printf(format1, data[i].y);
- break;
- case 'm':
- printf(format1, data[i].m);
- break;
- case 'r':
- printf(format1, data[i].r);
- break;
- case 'w':
- printf(format1, data[i].w);
- break;
- }
- }
- switch (output_choice[j]) {
- case 'x':
- printf(format2, data[i].x);
- break;
- case 'y':
- printf(format2, data[i].y);
- break;
- case 'm':
- printf(format2, data[i].m);
- break;
- case 'r':
- printf(format2, data[i].r);
- break;
- case 'w':
- printf(format2, data[i].w);
- break;
- }
- }
- }
-
- void free_the_memory(gtg, v, gtd, lambda, workb, workz, c_model, o_model, w_model, data, work)
- double *gtg, *v, *gtd, *lambda, *workb, *workz, *c_model, *o_model, *w_model, *work;
- struct DATA *data;
- {
- free ( (char *)work);
- free ( (char *)data);
- free ( (char *)w_model);
- free ( (char *)o_model);
- free ( (char *)c_model);
- free ( (char *)workz);
- free ( (char *)workb);
- free ( (char *)lambda);
- free ( (char *)gtd);
- free ( (char *)v);
- free ( (char *)gtg);
- }
-
- void transform_x(data, n_data, model_type, xmin, xmax)
- struct DATA *data;
- int n_data, model_type;
- double xmin, xmax;
- {
- int i;
- double offset, scale;
-
- offset = 0.5 * (xmin + xmax); /* Mid Range */
- scale = 2.0 / (xmax - xmin); /* 1 / (1/2 Range) */
-
- if (model_type == FOURIER) { /* Set Range to 1 period */
- scale *= M_PI;
- }
-
- for (i = 0; i < n_data; i++) {
- data[i].x = (data[i].x - offset) * scale;
- }
- }
-
- void untransform_x(data, n_data, model_type, xmin, xmax)
- struct DATA *data;
- int n_data, model_type;
- double xmin, xmax;
- {
- int i;
- double offset, scale;
-
- offset = 0.5 * (xmin + xmax); /* Mid Range */
- scale = 0.5 * (xmax - xmin); /* 1/2 Range */
-
- if (model_type == FOURIER) {
- scale /= M_PI;
- }
-
- for (i = 0; i < n_data; i++) {
- data[i].x = (data[i].x * scale) + offset;
- }
- }
-
- double get_chisq(data, n_data, n_model)
- struct DATA *data;
- int n_data, n_model;
- {
- int i, nu;
- double chi = 0.0;
-
-
- for (i = 0; i < n_data; i++) { /* Weight is already squared */
- if (data[i].w == 1.0) {
- chi += (data[i].r * data[i].r);
- }
- else {
- chi += (data[i].r * data[i].r * data[i].w);
- }
- }
- nu = n_data - n_model;
- if (nu > 1) return(chi/nu);
- return(chi);
- }
-
- void recompute_weights(data, n_data, work, scale)
- struct DATA *data;
- int n_data;
- double *work, *scale;
- {
- int i;
- double k, ksq, rr;
-
- /* First find median { fabs(data[].r) },
- estimate scale from this,
- and compute chisq based on this. */
-
- for (i = 0; i < n_data; i++) {
- work[i] = fabs(data[i].r);
- }
- qsort( (char *)work, n_data, sizeof(double), comp_double_asc);
-
- if (n_data%2) {
- *scale = 1.4826 * work[n_data/2];
- }
- else {
- *scale = 0.7413 * (work[n_data/2 - 1] + work[n_data/2]);
- }
-
- k = 1.5 * (*scale); /* Huber[1964] weight; 95% efficient for Normal data */
- ksq = k * k;
-
- for (i = 0; i < n_data; i++) {
- rr = fabs(data[i].r);
- if (rr <= k) {
- data[i].w = 1.0;
- }
- else {
- data[i].w = (2*k/rr) - (ksq/(rr*rr) ); /* This is really w-squared */
- }
- }
- }
-
- void load_g_row(x, n, gr, m)
- double x; /* Current data position, appropriately normalized. */
- int n; /* Number of model parameters, and elements of gr[] */
- double gr[]; /* Elements of row of G matrix. */
- int m; /* Parameter indicating model type */
- {
- /* Routine computes the elements gr[j] in the ith row of the
- G matrix (Menke notation), where x is the ith datum's
- abcissa. */
-
- int j, k;
-
- if (n) {
-
- gr[0] = 1.0;
-
- switch (m) {
-
- case POLYNOMIAL:
- /* Create Chebyshev polynomials */
- if (n > 1) gr[1] = x;
- for (j = 2; j < n; j++) {
- gr[j] = 2 * x * gr[j-1] - gr[j-2];
- }
- break;
-
- case FOURIER:
- for (j = 1; j < n; j++) {
- k = (j + 1)/2;
- if (k > 1) {
- if (j%2) {
- gr[j] = cos(k*x);
- }
- else {
- gr[j] = sin(k*x);
- }
- }
- else {
- if (j%2) {
- gr[j] = cos(x);
- }
- else {
- gr[j] = sin(x);
- }
- }
- }
- break;
- }
- }
- }
-
- void calc_m_and_r(data, n_data, model, n_model, m_type, grow)
- struct DATA *data;
- int n_data, n_model, m_type;
- double *model, *grow;
- {
- /* model[n_model] holds solved coefficients of m_type model.
- grow[n_model] is a vector for a row of G matrix. */
-
- int i, j;
- for (i = 0; i < n_data; i++) {
- load_g_row(data[i].x, n_model, grow, m_type);
- data[i].m = 0.0;
- for (j = 0; j < n_model; j++) {
- data[i].m += model[j]*grow[j];
- }
- data[i].r = data[i].y - data[i].m;
- }
- }
-
- void move_model_a_to_b(model_a, model_b, n_model, chisq_a, chisq_b)
- double *model_a, *model_b, *chisq_a, *chisq_b;
- int n_model;
- {
- int i;
- for(i = 0; i< n_model; i++) {
- model_b[i] = model_a[i];
- }
- *chisq_b = *chisq_a;
- }
-
- void load_gtg_and_gtd(data, n_data, gtg, gtd, grow, n_model, mp, m_type)
- struct DATA *data;
- double *gtg, *gtd, *grow;
- int n_data, n_model, mp, m_type; /* mp is row dimension of gtg */
- {
-
- int i, j, k;
- double wy;
-
- /* First zero the contents for summing: */
-
- for (j = 0; j < n_model; j++) {
- for (k = 0; k < n_model; k++) {
- gtg[j + k*mp] = 0.0;
- }
- gtd[j] = 0.0;
- }
-
- /* Sum over all data */
- for (i = 0; i < n_data; i++) {
- load_g_row(data[i].x, n_model, grow, m_type);
- if (data[i].w != 1.0) {
- wy = data[i].w * data[i].y;
- for (j = 0; j < n_model; j++) {
- for (k = 0; k < n_model; k++) {
- gtg[j + k*mp] += (data[i].w * grow[j] * grow[k]);
- }
- gtd[j] += (wy * grow[j]);
- }
- }
- else {
- for (j = 0; j < n_model; j++) {
- for (k = 0; k < n_model; k++) {
- gtg[j + k*mp] += (grow[j] * grow[k]);
- }
- gtd[j] += (data[i].y * grow[j]);
- }
- }
- }
- }
-
- void solve_system(gtg, gtd, model, n_model, mp, lambda, v, b, z, c_no, ir)
- int n_model, mp, *ir;
- double *gtg, *gtd, *model, *lambda, *v, *b, *z, c_no;
-
- {
-
- int i, j, k, rank = 0, n, m, nrots;
- double c_test, temp_inverse_ij;
-
- if (n_model == 1) {
- model[0] = gtd[0] / gtg[0];
- *ir = 1;
- }
- else {
- n = n_model;
- m = mp;
- if(jacobi(gtg, &n, &m, lambda, v, b, z, &nrots)) {
- fprintf(stderr,"trend1d: Warning: Matrix Solver Convergence Failure.\n");
- }
- c_test = fabs(lambda[0])/c_no;
- while(rank < n_model && lambda[rank] > 0.0 && lambda[rank] > c_test) rank++;
- for (i = 0; i < n_model; i++) {
- model[i] = 0.0;
- for (j = 0; j < n_model; j++) {
- temp_inverse_ij = 0.0;
- for (k = 0; k < rank; k++) {
- temp_inverse_ij += (v[i + k*mp] * v[j + k*mp] / lambda[k]);
- }
- model[i] += (temp_inverse_ij * gtd[j]);
- }
- }
- *ir = rank;
- }
- }
-