SINFONI Pipeline Reference Manual  2.6.0
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 
81 
82  if (np < poly_deg + 1) {
83  sinfo_msg_error("not enough points");
84  sinfo_msg_error("cannot fit %dth degree polynomial with %d points",
85  poly_deg, np);
86  return NULL ;
87  }
88 
89  Matrix mA = sinfo_create_mx(poly_deg + 1, np);
90  Matrix mB = sinfo_create_mx(1, np);
91  int i,k;
92  for (i = 0; i < np; i++) {
93  mA->m[i] = 1.0;
94  for (k = 1; k <= poly_deg; k++) {
95  mA->m[i + k * np] = sinfo_ipow(list[i].x, k);
96  }
97  mB->m[i] = list[i].y;
98  }
99 
100  /*
101  * Solve XA=B by a least-square solution (aka pseudo-inverse).
102  */
103  Matrix mX = sinfo_least_sq_mx(mA, mB);
104  /*
105  * Delete input matrices
106  */
107  sinfo_close_mx(mA);
108  sinfo_close_mx(mB);
109  /*
110  * Examine result
111  */
112  if (mX == NULL ) {
113  sinfo_msg_error("cannot fit: non-invertible sinfo_matrix");
114  return NULL ;
115  }
116 
117  double* c = cpl_malloc((poly_deg + 1) * sizeof(double));
118  for (i = 0; i < (poly_deg + 1); i++) {
119  c[i] = mX->m[i];
120  }
121  sinfo_close_mx(mX);
122 
123  /*
124  * If requested, compute mean squared error
125  */
126  if (mse != NULL ) {
127  double err = 0.00;
128  for (i = 0; i < np; i++) {
129  double y = c[0];
130  /*
131  * Compute the value obtained through the fit
132  */
133  double xp;
134  for (k = 1; k <= poly_deg; k++) {
135  xp = sinfo_ipow(list[i].x, k);
136  y += c[k] * xp;
137  }
138  /*
139  * Subtract from the true value, square, accumulate
140  */
141  xp = sinfo_ipow(list[i].y - y, 2);
142  err += xp;
143  }
144  /* Average the error term */
145  err /= (double) np;
146  *mse = err;
147  }
148  return c;
149 }
150 
#define sinfo_msg_error(...)
Print an error message.
Definition: sinfo_msg.h:69