00001 /* 00002 * This file is part of the ESO SINFONI Pipeline 00003 * Copyright (C) 2004,2005 European Southern Observatory 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA 00018 */ 00019 /*--------------------------------------------------------------------------- 00020 00021 File name : fit_curve.c 00022 Author : N. Devillard 00023 Created on : July 1998 00024 Description : 1d and 2d fit related routines 00025 00026 ---------------------------------------------------------------------------*/ 00027 /* 00028 $Id: sinfo_fit_curve.c,v 1.3 2007/06/06 07:10:45 amodigli Exp $ 00029 $Author: amodigli $ 00030 $Date: 2007/06/06 07:10:45 $ 00031 $Revision: 1.3 $ 00032 */ 00033 #ifdef HAVE_CONFIG_H 00034 # include <config.h> 00035 #endif 00036 /*--------------------------------------------------------------------------- 00037 Includes 00038 ---------------------------------------------------------------------------*/ 00039 #include <math.h> 00040 #include "sinfo_fit_curve.h" 00041 #include "sinfo_ipow.h" 00050 /*--------------------------------------------------------------------------- 00051 Private functions 00052 ---------------------------------------------------------------------------*/ 00053 /*--------------------------------------------------------------------------- 00054 Function codes 00055 ---------------------------------------------------------------------------*/ 00078 double * 00079 sinfo_fit_1d_poly( 00080 int poly_deg, 00081 dpoint * list, 00082 int np, 00083 double * mse 00084 ) 00085 { 00086 int i, k ; 00087 Matrix mA, mB, mX ; 00088 double * c ; 00089 double err ; 00090 double xp, y ; 00091 00092 if (np<poly_deg+1) { 00093 sinfo_msg_error("not enough points") ; 00094 sinfo_msg_error("cannot fit %dth degree polynomial with %d points", 00095 poly_deg, np); 00096 return NULL; 00097 } 00098 00099 mA = sinfo_create_mx(poly_deg+1, np) ; 00100 mB = sinfo_create_mx(1, np) ; 00101 00102 for (i=0 ; i<np ; i++) { 00103 mA->m[i] = 1.0 ; 00104 for (k=1 ; k<=poly_deg ; k++) { 00105 mA->m[i+k*np] = sinfo_ipow(list[i].x, k) ; 00106 } 00107 mB->m[i] = list[i].y ; 00108 } 00109 00110 /* 00111 * Solve XA=B by a least-square solution (aka pseudo-inverse). 00112 */ 00113 mX = sinfo_least_sq_mx(mA,mB) ; 00114 /* 00115 * Delete input matrices 00116 */ 00117 sinfo_close_mx(mA) ; 00118 sinfo_close_mx(mB) ; 00119 /* 00120 * Examine result 00121 */ 00122 if (mX==NULL) { 00123 sinfo_msg_error("cannot fit: non-invertible sinfo_matrix") ; 00124 return NULL ; 00125 } 00126 00127 c = cpl_malloc((poly_deg+1)*sizeof(double)) ; 00128 for (i=0 ; i<(poly_deg+1) ; i++) { 00129 c[i] = mX->m[i] ; 00130 } 00131 sinfo_close_mx(mX) ; 00132 00133 /* 00134 * If requested, compute mean squared error 00135 */ 00136 if (mse != NULL) { 00137 err = 0.00 ; 00138 for (i=0 ; i<np ; i++) { 00139 y = c[0] ; 00140 /* 00141 * Compute the value obtained through the fit 00142 */ 00143 for (k=1 ; k<=poly_deg ; k++) { 00144 xp = sinfo_ipow(list[i].x, k) ; 00145 y += c[k] * xp ; 00146 } 00147 /* 00148 * Subtract from the true value, square, accumulate 00149 */ 00150 xp = sinfo_ipow(list[i].y - y, 2) ; 00151 err += xp ; 00152 } 00153 /* Average the error term */ 00154 err /= (double)np ; 00155 *mse = err ; 00156 } 00157 return c ; 00158 } 00159 00160