sinfo_fit_curve.c

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.4 2012/03/02 08:42:20 amodigli Exp $
00029     $Author: amodigli $
00030     $Date: 2012/03/02 08:42:20 $
00031     $Revision: 1.4 $
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 

Generated on 3 Mar 2013 for SINFONI Pipeline Reference Manual by  doxygen 1.6.1