SINFONI Pipeline Reference Manual  2.5.2
sinfo_fit_curve.c
1 /*
2  * This file is part of the ESO SINFONI Pipeline
3  * Copyright (C) 2004,2005 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18  */
19 /*---------------------------------------------------------------------------
20 
21  File name : fit_curve.c
22  Author : N. Devillard
23  Created on : July 1998
24  Description : 1d and 2d fit related routines
25 
26  ---------------------------------------------------------------------------*/
27 /*
28  $Id: sinfo_fit_curve.c,v 1.4 2012-03-02 08:42:20 amodigli Exp $
29  $Author: amodigli $
30  $Date: 2012-03-02 08:42:20 $
31  $Revision: 1.4 $
32  */
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
36 /*---------------------------------------------------------------------------
37  Includes
38  ---------------------------------------------------------------------------*/
39 #include <math.h>
40 #include "sinfo_fit_curve.h"
41 #include "sinfo_ipow.h"
49 /*---------------------------------------------------------------------------
50  Private functions
51  ---------------------------------------------------------------------------*/
52 /*---------------------------------------------------------------------------
53  Function codes
54  ---------------------------------------------------------------------------*/
77 double *
78 sinfo_fit_1d_poly(int poly_deg, dpoint * list, int np, double * mse)
79 {
80  int i, k;
81  Matrix mA, mB, mX;
82  double * c;
83  double err;
84  double xp, y;
85 
86  if (np < poly_deg + 1) {
87  sinfo_msg_error("not enough points");
88  sinfo_msg_error("cannot fit %dth degree polynomial with %d points",
89  poly_deg, np);
90  return NULL ;
91  }
92 
93  mA = sinfo_create_mx(poly_deg + 1, np);
94  mB = sinfo_create_mx(1, np);
95 
96  for (i = 0; i < np; i++) {
97  mA->m[i] = 1.0;
98  for (k = 1; k <= poly_deg; k++) {
99  mA->m[i + k * np] = sinfo_ipow(list[i].x, k);
100  }
101  mB->m[i] = list[i].y;
102  }
103 
104  /*
105  * Solve XA=B by a least-square solution (aka pseudo-inverse).
106  */
107  mX = sinfo_least_sq_mx(mA, mB);
108  /*
109  * Delete input matrices
110  */
111  sinfo_close_mx(mA);
112  sinfo_close_mx(mB);
113  /*
114  * Examine result
115  */
116  if (mX == NULL ) {
117  sinfo_msg_error("cannot fit: non-invertible sinfo_matrix");
118  return NULL ;
119  }
120 
121  c = cpl_malloc((poly_deg + 1) * sizeof(double));
122  for (i = 0; i < (poly_deg + 1); i++) {
123  c[i] = mX->m[i];
124  }
125  sinfo_close_mx(mX);
126 
127  /*
128  * If requested, compute mean squared error
129  */
130  if (mse != NULL ) {
131  err = 0.00;
132  for (i = 0; i < np; i++) {
133  y = c[0];
134  /*
135  * Compute the value obtained through the fit
136  */
137  for (k = 1; k <= poly_deg; k++) {
138  xp = sinfo_ipow(list[i].x, k);
139  y += c[k] * xp;
140  }
141  /*
142  * Subtract from the true value, square, accumulate
143  */
144  xp = sinfo_ipow(list[i].y - y, 2);
145  err += xp;
146  }
147  /* Average the error term */
148  err /= (double) np;
149  *mse = err;
150  }
151  return c;
152 }
153