sinfo_boltzmann.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 * E.S.O. - VLT project
00021 *
00022 *
00023 *
00024 * who       when      what
00025 * --------  --------  ----------------------------------------------
00026 * schreib  27/02/01  created
00027 */
00028 
00029 /************************************************************************
00030 *   NAME
00031 *        new_boltzmann.c -
00032 *        routines to determine the absolute positions of the slitlets out
00033 *        of an emission line frame
00034 *
00035 *   SYNOPSIS
00036 *   #include "absolute.h"
00037 *
00038 *   1) float sinfo_new_boltz ( float * xdat, float * parlist )
00039 *   2) void sinfo_new_boltz_deriv( float * xdat, float * parlist, 
00040                                    float * dervs )
00041 *   3) static int sinfo_new_inv_mat (void)
00042 *   4) static void sinfo_new_get_mat ( float * xdat,
00043 *                            int   * xdim,
00044 *                            float * ydat,
00045 *                            float * wdat,
00046 *                            int   * ndat,
00047 *                            float * fpar,
00048 *                            float * epar,
00049 *                            int   * npar )
00050 *   5) static int sinfo_new_get_vec ( float * xdat,
00051 *                           int   * xdim,
00052 *                           float * ydat,
00053 *                           float * wdat,
00054 *                           int   * ndat,
00055 *                           float * fpar,
00056 *                           float * epar,
00057 *                           int   * npar )
00058 *   6) int sinfo_new_lsqfit ( float * xdat,
00059 *                   int   * xdim,
00060 *                   float * ydat,
00061 *                   float * wdat,
00062 *                   int   * ndat,
00063 *                   float * fpar,
00064 *                   float * epar,
00065 *                   int   * mpar,
00066 *                   int   * npar,
00067 *                   float * tol ,
00068 *                   int   * its ,
00069 *                   float * lab  )
00070 *   7) int sinfo_new_fit_slits_boltz( cpl_image   * lineImage, 
00071 *                         FitParams ** par,
00072 *                         float     ** slit_pos,
00073 *                         int          box_length,
00074 *                         float        y_box,
00075 *                         float        diff_tol )
00076 *   8) int sinfo_new_fit_slits_boltz_single_line ( cpl_image   * lineImage, 
00077 *                                    float     ** slit_pos,
00078 *                                    int          box_length,
00079 *                                    float        y_box,
00080 *                                int          low_pos,
00081 *                                    int          high_pos )
00082 *   9) int sinfo_new_fit_slits_boltz_with_estimate ( cpl_image   * lineImage, 
00083 *                                      float     ** slit_pos,
00084 *                                      int          box_length,
00085 *                                      float        y_box,
00086 *                                      float        diff_tol,
00087 *                                      int          low_pos,
00088 *                           int          high_pos )
00089 *
00090 *   DESCRIPTION
00091 *   1) calculates the value of a Boltzmann function with parameters 
00092 *      parlist at the position xdat 
00093 *   2) calculates the partial derivatives for a Boltzmann function with
00094 *      parameters parlist at position xdat 
00095 *   3) calculates the inverse of matrix2. The algorithm used 
00096 *      is the Gauss-Jordan algorithm described in Stoer,
00097 *      Numerische Mathematik, 1. Teil.
00098 *   4) builds the sinfo_matrix 
00099 *   5) calculates the correction sinfo_vector. The sinfo_matrix has been
00100 *      built by get_mat(), we only have to rescale it for the 
00101 *      current value of labda. The sinfo_matrix is rescaled so that
00102 *      the diagonal gets the value 1 + labda.
00103 *      Next we calculate the inverse of the sinfo_matrix and then
00104 *      the correction sinfo_vector.
00105 *   6) this is a routine for making a least-squares fit of a
00106 *      function to a set of data points. The method used is
00107 *      described in: Marquardt, J.Soc.Ind.Appl.Math. 11. 431 (1963).
00108 *      This method is a mixture of the steepest descent method 
00109 *      and the Taylor method.
00110 *   7) fits the beginning and end position of the slitlets
00111 *      by using non-linear least square fitting of Boltzmann function
00112 *      fits a Boltzmann function to the slitlet edges exposed and indicated
00113 *      by the brightest emission lines. To achieve this, the fit
00114 *      parameters are used to find the brightest emission line
00115 *      and to get its position for each column.
00116 *      The least squares fit is done by using a box smaller than
00117 *      the size of two slitlets
00118 *   8) fits the beginning and end position of the slitlets
00119 *      by using non-linear least square fitting of a Boltzmann function
00120 *      fits a Boltzmann function to the slitlet edges exposed and indicated
00121 *      by the brightest emission lines. The slitlet is searched within
00122 *      user given positions.
00123 *      The least squares fit is done by using a box smaller than
00124 *      the size of two slitlets 
00125 *   9) fits the beginning and end position of the slitlets
00126 *      by using non-linear least square fitting of a Boltzmann function
00127 *      fits a Boltzmann function to the slitlet edges exposed and indicated
00128 *      by the brightest emission lines. The slitlet is searched within
00129 *      user given positions.
00130 *      The least squares fit is done by using a box smaller than
00131 *      the size of two slitlets 
00132 *
00133 *   FILES
00134 *
00135 *   ENVIRONMENT
00136 *
00137 *   RETURN VALUES
00138 *
00139 *   CAUTIONS
00140 *
00141 *   EXAMPLES
00142 *
00143 *   SEE ALSO
00144 *
00145 *   BUGS
00146 *
00147 *------------------------------------------------------------------------
00148 */
00149 
00150 #ifdef HAVE_CONFIG_H
00151 #  include <config.h>
00152 #endif
00153 #include "sinfo_vltPort.h"
00154 
00155 /*
00156  * System Headers
00157  */
00158 
00159 /*
00160  * Local Headers
00161  */
00162 
00163 #include "sinfo_absolute.h"
00164 #include "sinfo_recipes.h"
00165 
00166 /*----------------------------------------------------------------------------
00167  *                                 Defines
00168  *--------------------------------------------------------------------------*/
00169 
00170 #define XDIMA         1         /* dimension of the x values */
00171 #define TOLA          0.001     /* fitting tolerance */
00172 #define LABA          0.1       /* labda parameter */
00173 #define ITSA          200       /* maximum number of iterations */
00174 #define LABFACA       10.0      /* labda step factor */
00175 #define LABMAXA       1.0e+10   /* maximum value for labda */
00176 #define LABMINA       1.0e-10   /* minimum value for labda */
00177 #define NPAR          4         /* number of fit parameters */
00178 
00179 /*----------------------------------------------------------------------------
00180  *                                    Local variables
00181  *--------------------------------------------------------------------------*/
00182 
00183 static double chi1 ;                    /* old reduced chi-squared */
00184 static double chi2 ;                    /* new reduced chi-squared */
00185 static double labda ;                   /* mixing parameter */
00186 static double vec[NPAR] ;               /* correction sinfo_vector */
00187 static double matrix1[NPAR][NPAR] ;     /* original sinfo_matrix */
00188 static double matrix2[NPAR][NPAR] ;     /* inverse of matrix1 */
00189 static int    nfree ;                   /* number of free parameters */
00190 static int    parptr[NPAR] ;            /* parameter pointer */
00191 
00192 /*----------------------------------------------------------------------------
00193  *                    Functions private to this module
00194  *--------------------------------------------------------------------------*/
00195 
00196 static int sinfo_new_inv_mat (void) ;
00197 
00198 static void sinfo_new_get_mat ( float * xdat,
00199                       int   * xdim,
00200                       float * ydat,
00201                       float * wdat,
00202                       int   * ndat,
00203                       float * fpar,
00204                       float * epar/*,
00205                       int   * npar*/ ) ;
00206 
00207 static int sinfo_new_get_vec ( float * xdat,
00208                      int   * xdim,
00209                      float * ydat,
00210                      float * wdat,
00211                      int   * ndat,
00212                      float * fpar,
00213                      float * epar,
00214                      int   * npar ) ;
00222 /*----------------------------------------------------------------------------
00223  *                            Function codes
00224  *--------------------------------------------------------------------------*/
00225 
00245 float sinfo_new_boltz ( float * xdat, float * parlist )
00246 {
00247     float return_value ;
00248 
00249     /* now build the boltzman function out of the parameters */
00250     return_value = 
00251     (parlist[0] - parlist[1]) / (1 + exp(( xdat[0] - parlist[2] ) / 
00252      parlist[3])) + parlist[1] ;
00253     
00254     return return_value ;
00255 }
00256        
00278 void sinfo_new_boltz_deriv( float * xdat, float * parlist, float * dervs )
00279 {
00280     float subst ;
00281  
00282     subst = (xdat[0] - parlist[2]) / parlist[3] ;
00283 
00284     dervs[0] = 1. / ( 1. + exp(subst) ) ;
00285 
00286     dervs[1] = -1. / ( 1. + exp(subst) ) + 1. ;
00287 
00288     dervs[2] = ( (parlist[0] - parlist[1]) / parlist[3] * exp(subst) ) /
00289                ( (1. + exp(subst)) * (1. + exp(subst)) ) ;
00290 
00291     dervs[3] = ( (parlist[0] - parlist[1]) * (xdat[0] - parlist[2]) /
00292                (parlist[3]*parlist[3]) * exp(subst) ) /
00293                ( (1. + exp(subst)) * (1. + exp(subst)) ) ;
00294 }
00295 
00306 static int sinfo_new_inv_mat (void)
00307 {
00308     double even ;
00309     double hv[NPAR] ;
00310     double mjk ;
00311     double rowmax ;
00312     int evin ;
00313     int i, j, k, row ;
00314     int per[NPAR] ;
00315    
00316     /* set permutation array */
00317     for ( i = 0 ; i < nfree ; i++ )
00318     {
00319         per[i] = i ;
00320     }
00321     
00322     for ( j = 0 ; j < nfree ; j++ ) /* in j-th column */
00323     {
00324         /* determine largest element of a row */                                
00325         rowmax = fabs ( matrix2[j][j] ) ;
00326         row = j ;                         
00327 
00328         for ( i = j + 1 ; i < nfree ; i++ )
00329         {
00330             if ( fabs ( matrix2[i][j] ) > rowmax )
00331             {
00332                 rowmax = fabs( matrix2[i][j] ) ;
00333                 row = i ;
00334             }
00335         }
00336 
00337         /* determinant is zero! */
00338         if ( matrix2[row][j] == 0.0 )
00339         {
00340             return -6 ;
00341         }
00342         
00343         /* if the largest element is not on the diagonal, then permutate rows */
00344         if ( row > j )
00345         {
00346             for ( k = 0 ; k < nfree ; k++ )
00347             {
00348                 even = matrix2[j][k] ;
00349                 matrix2[j][k] = matrix2[row][k] ;
00350                 matrix2[row][k] = even ;
00351             }
00352             /* keep track of permutation */
00353             evin = per[j] ;
00354             per[j] = per[row] ;
00355             per[row] = evin ;
00356         }
00357         
00358         /* modify column */
00359         even = 1.0 / matrix2[j][j] ;
00360         for ( i = 0 ; i < nfree ; i++ )
00361         {
00362             matrix2[i][j] *= even ;
00363         }
00364         matrix2[j][j] = even ;
00365         
00366         for ( k = 0 ; k < j ; k++ )
00367         {
00368             mjk = matrix2[j][k] ;
00369             for ( i = 0 ; i < j ; i++ )
00370             {
00371                 matrix2[i][k] -= matrix2[i][j] * mjk ;
00372             }
00373             for ( i = j + 1 ; i < nfree ; i++ )
00374             {
00375                 matrix2[i][k] -= matrix2[i][j] * mjk ;
00376             }
00377             matrix2[j][k] = -even * mjk ;
00378         }
00379     
00380         for ( k = j + 1 ; k < nfree ; k++ )
00381         {
00382             mjk = matrix2[j][k] ;
00383             for ( i = 0 ; i < j ; i++ )
00384             {
00385                 matrix2[i][k]  -= matrix2[i][j] * mjk ;
00386             }
00387             for ( i = j + 1 ; i < nfree ; i++ )
00388             {
00389                 matrix2[i][k]  -= matrix2[i][j] * mjk ;
00390             }
00391             matrix2[j][k] = -even * mjk ;
00392         }
00393     }
00394     
00395     /* finally, repermute the columns */
00396     for ( i = 0 ; i < nfree ; i++ )
00397     {
00398         for ( k = 0 ; k < nfree ; k++ )
00399         {
00400             hv[per[k]] = matrix2[i][k] ;
00401         }
00402         for ( k = 0 ; k < nfree ; k++ )
00403         {
00404             matrix2[i][k] = hv[k] ;
00405         }
00406     }
00407         
00408     /* all is well */
00409     return 0 ;
00410 }
00411     
00426 static void sinfo_new_get_mat ( float * xdat,
00427                       int   * xdim,
00428                       float * ydat,
00429                       float * wdat,
00430                       int   * ndat,
00431                       float * fpar,
00432                       float * epar/*,
00433                       int   * npar*/ )
00434 {
00435     double wd ;
00436     double wn ;
00437     double yd ;
00438     int i, j, n ;
00439 
00440     for ( j = 0 ; j < nfree ; j++ )
00441     {
00442         vec[j] = 0.0 ; /* zero sinfo_vector */
00443         for ( i = 0 ; i<= j ; i++ ) /* zero sinfo_matrix only 
00444                                        on and below diagonal */
00445         {
00446             matrix1[j][i] = 0.0 ;
00447         }
00448     }
00449     chi2 = 0.0 ;  /* reset reduced chi-squared */
00450     
00451     /* loop through data points */
00452     for ( n = 0 ; n < (*ndat) ; n++ )
00453     {
00454         wn = wdat[n] ;
00455         if ( wn > 0.0 )  /* legal weight ? */
00456         {
00457             yd = ydat[n] - sinfo_new_boltz( &xdat[(*xdim) * n], fpar ) ;
00458             sinfo_new_boltz_deriv( &xdat[(*xdim) * n], fpar, epar ) ;
00459             chi2 += yd * yd * wn ; /* add to chi-squared */
00460             for ( j = 0 ; j < nfree ; j++ )
00461             {
00462                 wd = epar[parptr[j]] * wn ;  /* weighted derivative */
00463                 vec[j] += yd * wd ;       /* fill sinfo_vector */
00464                 for ( i = 0 ; i <= j ; i++ ) /* fill sinfo_matrix */
00465                 {
00466                     matrix1[j][i] += epar[parptr[i]] * wd ;
00467                 }
00468             }
00469         }
00470     }                   
00471 }  
00472                 
00473             
00495 static int sinfo_new_get_vec ( float * xdat,
00496                      int   * xdim,
00497                      float * ydat,
00498                      float * wdat,
00499                      int   * ndat,
00500                      float * fpar,
00501                      float * epar,
00502                      int   * npar )
00503 {
00504     double dj ;
00505     double dy ;
00506     double mii ;
00507     double mji ;
00508     double mjj ;
00509     double wn ;
00510     int i, j, n, r ;
00511 
00512     /* loop to modify and scale the sinfo_matrix */
00513     for ( j = 0 ; j < nfree ; j++ )
00514     {
00515         mjj = matrix1[j][j] ;
00516         if ( mjj <= 0.0 )             /* diagonal element wrong */
00517         {
00518             return -5 ;
00519         }
00520         mjj = sqrt( mjj ) ;
00521         for ( i = 0 ; i < j ; i++ )
00522         {
00523             mji = matrix1[j][i] / mjj / sqrt( matrix1[i][i] ) ;
00524             matrix2[i][j] = matrix2[j][i] = mji ;
00525         }
00526         matrix2[j][j] = 1.0 + labda ;  /* scaled value on diagonal */
00527     }    
00528     
00529     if ( (r = sinfo_new_inv_mat()) ) /* sinfo_invert sinfo_matrix inlace */
00530     {
00531         return r ;
00532     }
00533     
00534     for ( i = 0 ; i < (*npar) ; i ++ )
00535     {
00536         epar[i] = fpar[i] ;
00537     }
00538     
00539     /* loop to calculate correction sinfo_vector */
00540     for ( j = 0 ; j < nfree ; j++ )
00541     {
00542         dj = 0.0 ;
00543         mjj = matrix1[j][j] ;
00544         if ( mjj <= 0.0)               /* not allowed */
00545         {
00546             return -7 ;
00547         }
00548         mjj = sqrt ( mjj ) ;
00549         for ( i = 0 ; i < nfree ; i++ )
00550         {
00551             mii = matrix1[i][i] ;
00552             if ( mii <= 0.0 )
00553             {
00554                 return -7 ;
00555             }
00556             mii = sqrt( mii ) ;
00557             dj += vec[i] * matrix2[j][i] / mjj / mii ;
00558         }
00559         epar[parptr[j]] += dj ;       /* new parameters */
00560     }    
00561     chi1 = 0.0 ;                      /* reset reduced chi-squared */
00562  
00563     /* loop through the data points */
00564     for ( n = 0 ; n < (*ndat) ; n++ )
00565     {
00566         wn = wdat[n] ;               /* get weight */
00567         if ( wn > 0.0 )              /* legal weight */
00568         {
00569             dy = ydat[n] - sinfo_new_boltz( &xdat[(*xdim) * n], epar) ;
00570             chi1 += wdat[n] * dy * dy ;
00571         }
00572     }
00573     return 0 ;
00574 }   
00575     
00576         
00577 
00627 int sinfo_new_lsqfit ( float * xdat,
00628              int   * xdim,
00629              float * ydat,
00630              float * wdat,
00631              int   * ndat,
00632              float * fpar,
00633              float * epar,
00634              int   * mpar,
00635              int   * npar,
00636              float * tol ,
00637              int   * its ,
00638              float * lab  )
00639 {
00640     int i, n, r ;
00641     int itc ;                      /* fate of fit */
00642     int found ;                    /* fit converged: 1, not yet converged: 0 */
00643     int  nuse ;                    /* number of useable data points */
00644     double tolerance ;             /* accuracy */
00645 
00646     itc   = 0 ;                    /* fate of fit */
00647     found = 0 ;                    /* reset */
00648     nfree = 0 ;                    /* number of free parameters */
00649     nuse  = 0 ;                    /* number of legal data points */
00650 
00651     if ( *tol < (FLT_EPSILON * 10.0 ) )
00652     {
00653         tolerance = FLT_EPSILON * 10.0 ;  /* default tolerance */
00654     }
00655     else
00656     {
00657         tolerance = *tol ;                /* tolerance */
00658     }
00659     
00660     labda = fabs( *lab ) * LABFACA ;   /* start value for mixing parameter */
00661     for ( i = 0 ; i < (*npar) ; i++ )
00662     {
00663         if ( mpar[i] )
00664         {
00665             if ( nfree > NPAR )         /* too many free parameters */
00666             {
00667                 return -1 ;
00668             }
00669             parptr[nfree++] = i ;         /* a free parameter */
00670         }
00671     }
00672     
00673     if (nfree == 0)                       /* no free parameters */     
00674     {
00675         return -2 ;
00676     }
00677     
00678     for ( n = 0 ; n < (*ndat) ; n++ )
00679     {
00680         if ( wdat[n] > 0.0 )              /* legal weight */
00681         {
00682             nuse ++ ;
00683         }
00684     }
00685     
00686     if ( nfree >= nuse )
00687     {
00688         return -3 ;                       /* no degrees of freedom */
00689     }
00690     if ( labda == 0.0 )                   /* linear fit */
00691     {
00692         /* initialize fpar array */
00693         for ( i = 0 ; i < nfree ; fpar[parptr[i++]] = 0.0 ) ;  
00694         sinfo_new_get_mat(xdat,xdim,ydat,wdat,ndat,fpar,epar/*, npar*/ ) ;
00695         r =  sinfo_new_get_vec(xdat,xdim,ydat,wdat,ndat,fpar,epar,npar) ;
00696         if ( r )                         /* error */
00697         {
00698             return r ;
00699         }
00700         for ( i = 0 ; i < (*npar) ; i++ )
00701         {
00702             fpar[i] = epar[i] ;           /* save new parameters */
00703             epar[i] = 0.0 ;               /* and set errors to zero */
00704         }
00705         chi1 = sqrt( chi1 / (double) (nuse - nfree) ) ;
00706         for ( i = 0 ; i < nfree ; i++ )
00707         {
00708             if ( (matrix1[i][i] <= 0.0 ) || (matrix2[i][i] <= 0.0) )
00709             {
00710                 return -7 ;
00711             }
00712             epar[parptr[i]] = chi1 * sqrt( matrix2[i][i] ) / 
00713                                      sqrt( matrix1[i][i] ) ;
00714         }
00715     }
00716     else                                  /* non-linear fit */
00717     {
00718         /*----------------------------------------------------------------
00719          * the non-linear fit uses the steepest descent method in combination
00720          * with the Taylor method. The mixing of these methods is controlled
00721          * by labda. In the outer loop ( called the iteration loop ) we build
00722          * the sinfo_matrix and calculate the correction sinfo_vector. 
00723          * In the inner loop
00724          * (called the interpolation loop) we check whether we have obtained a
00725          * better solution than the previous one. If so, we leave the inner 
00726          * loop
00727          * else we increase labda ( give more weight to the steepest descent 
00728          * method) calculate the correction sinfo_vector and check again. 
00729          * After the inner loop
00730          * we do a final check on the goodness of the fit and if this satisfies
00731          * the tolerance we calculate the errors of the fitted parameters.
00732          */
00733         while ( !found )                  /* iteration loop */
00734         {      
00735             if ( itc++ == (*its) )        /* increase iteration counter */
00736             {
00737                 return -4 ;               
00738             }
00739             sinfo_new_get_mat(xdat,xdim,ydat,wdat,ndat,fpar,epar/*, npar */) ;
00740             
00741             /*-------------------------------------------------------------
00742              * here we decrease labda since we may assume that each iteration
00743              * brings us closer to the answer.
00744              */
00745             if ( labda > LABMINA )
00746             {
00747                 labda = labda / LABFACA ;         /* decrease labda */
00748             }
00749             r = sinfo_new_get_vec ( xdat, xdim, ydat, wdat, 
00750                                     ndat, fpar, epar, npar ) ;
00751 
00752             if ( r )                      /* error */
00753             {
00754                 return r ;
00755             }
00756 
00757             while ( chi1 >= chi2 )        /* interpolation loop */
00758             {
00759                 /*-----------------------------------------------------------
00760                  * The next statement is based on experience, not on the 
00761                  * mathematics of the problem. It is assumed that we have 
00762                  * reached convergence when the pure steepest descent method 
00763                  * does not produce a better solution.
00764                  */
00765                 if ( labda > LABMAXA )    /* assume solution found */
00766                 {
00767                     break ;
00768                 }
00769                 labda = labda * LABFACA ;  /* increase mixing parameter */
00770                 r = sinfo_new_get_vec ( xdat, xdim, ydat, wdat, 
00771                                         ndat, fpar, epar, npar ) ;
00772 
00773                 if ( r )                  /* error */
00774                 {
00775                     return r ;
00776                 }
00777             }
00778 
00779             if ( labda <= LABMAXA )        /* save old parameters */
00780             {
00781                 for ( i = 0 ; i < *npar ; i++ )
00782                 {
00783                     fpar[i] = epar[i] ;
00784                 }
00785             }
00786             if ( (fabs( chi2 - chi1 ) <= (tolerance * chi1)) || 
00787                  (labda > LABMAXA) )
00788             {
00789                 /*---------------------------------------------------------
00790                  * we have a satisfying solution, so now we need to calculate 
00791                  * the correct errors of the fitted parameters. This we do by 
00792                  * using the pure Taylor method because we are very close to 
00793                  * the real solution.
00794                  */
00795                 labda = LABMINA ;              /* for Taylor solution */
00796                 sinfo_new_get_mat(xdat,xdim,ydat,wdat,ndat,fpar,epar/*,npar*/);
00797                 r = sinfo_new_get_vec(xdat,xdim,ydat,wdat,ndat,fpar,epar,npar);
00798 
00799                 if ( r )                    /* error */
00800                 {
00801                     return r ;
00802                 }
00803                 for ( i = 0 ; i < (*npar) ; i++ )
00804                 {
00805                     epar[i] = 0.0 ;          /* set error to zero */
00806                 }
00807                 chi2 = sqrt ( chi2 / (double) (nuse - nfree) ) ;
00808 
00809                 for ( i = 0 ; i < nfree ; i++ )
00810                 {
00811                     if ( (matrix1[i][i] <= 0.0) || (matrix2[i][i] <= 0.0) )
00812                     {
00813                         return -7 ;
00814                     }
00815                     epar[parptr[i]] = chi2 * sqrt( matrix2[i][i] ) / 
00816                                              sqrt( matrix1[i][i] ) ;
00817                 }
00818                 found = 1 ;                  /* we found a solution */
00819             }
00820         }
00821     }
00822     return itc ;                             /* return number of iterations */
00823 }
00824 
00865 int sinfo_new_fit_slits_boltz ( cpl_image   * lineImage, 
00866                     FitParams ** par,
00867                     float     ** slit_pos,
00868                     int          box_length,
00869                     float        y_box,
00870                     float        diff_tol )
00871 {
00872     float* position=NULL ;
00873     int   * sinfo_edge, * edgeclean ;
00874     int   * dummyedge ;
00875     int   * pos_row, * pos_rowclean ;
00876     Vector * box_buffer ;
00877     Vector * half_buffer ;
00878     Vector * in_buffer ;
00879     float max_intensity ;
00880     float row_pos ;
00881     int   row, col ;
00882     int   i, j, k, m, n, ed ;
00883     int   found, init1 ;
00884     int   line ; 
00885     int   nel, n_right, left_right ;
00886     int   n_buf, edge_ind, shift ;
00887     int   column ;
00888     int   slit_length ;
00889     int   agreed ;
00890     int   bad_line ;
00891     int   margin ;
00892     int   iters, xdim, ndat ;
00893     int   numpar, its ;
00894     int   * mpar ;
00895     float * xdat, * wdat ;
00896     float tol, lab ;
00897     float fitpar[NPAR] ;
00898     float dervpar[NPAR] ;
00899     float minval, maxval ;
00900     float min ;
00901     float pos, last_pos ;
00902     int old_col=0;
00903     int old_pos=0;
00904     int ilx=0;
00905     int ily=0;
00906     float* pidata=NULL;
00907 
00908 
00909     slit_length = SLITLENGTH ;
00910     if ( NULL == lineImage )
00911     {
00912         sinfo_msg_error(" no line image given!" ) ;
00913         return -1 ;
00914     }
00915 
00916     if ( NULL == par )
00917     {
00918         sinfo_msg_error(" no line fit parameters given!" ) ;
00919         return -2 ;
00920     }
00921 
00922     if ( NULL == slit_pos )
00923     {
00924         sinfo_msg_error(" no position array allocated!" ) ;
00925         return -3 ;
00926     }
00927 
00928     if ( box_length <  4 ||
00929          box_length > 2*slit_length )
00930     {
00931         sinfo_msg_error(" wrong fitting box length given!" ) ;
00932         return -4 ;
00933     }
00934 
00935     if ( y_box <= 0.  || y_box > 6. )
00936     {
00937         sinfo_msg_error(" wrong y box length given!" ) ;
00938         return -5 ;
00939     }
00940 
00941     if ( diff_tol < 1. )
00942     {
00943         sinfo_msg_error(" diff_tol too small!" ) ;
00944         return -6 ;
00945     }
00946  
00947     /* allocate memory for the edges and the row positon of the slitlets */
00948     sinfo_edge         = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
00949     dummyedge    = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
00950     edgeclean    = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
00951     pos_row      = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
00952     pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
00953 
00954 
00955     /* -----------------------------------------------------------------------
00956      * go through the first image columns and the fit parameters and find the 
00957        line with the highest intensity 
00958      */
00959     agreed = -1 ;
00960     bad_line = -1 ;
00961     while( agreed == -1 )
00962     {
00963         found = -1 ;
00964         max_intensity = -FLT_MAX ;
00965         for ( col = 0 ; col < slit_length ; col++ )
00966         {
00967             for ( i = 0 ; i < par[0]->n_params ; i++ )
00968             {
00969                 if ( par[i]->column == col && par[i]->line != bad_line )
00970                 {
00971                     if ( par[i]->fit_par[0] > max_intensity )
00972                     {
00973                         if ( par[i]->fit_par[1] >= 1. && 
00974                              par[i]->fit_par[2] > 0. )
00975                         {
00976                             max_intensity = par[i]->fit_par[0] ;
00977                             found = i ;
00978                         }
00979                     }
00980                 }
00981             }  
00982         }
00983 
00984         /* --------------------------------------------------------------------
00985          * check if the found line is usable and if the neighbouring line 
00986          * have intensity on near rows in neighbouring slitlets 
00987          */
00988         line    = par[found]->line ;
00989         column  = par[found]->column ;
00990         row_pos = par[found]->fit_par[2] ;
00991         if ( found >= 0 && max_intensity > 0. )
00992         {
00993             for ( i = 0 ; i < par[0]->n_params ; i++ )
00994             {
00995                 if ( par[i]->line == line-1 && 
00996                      par[i]->column == column + slit_length )
00997                 {
00998                     if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
00999                          par[i]->fit_par[2] >= (row_pos - y_box) )
01000                     {
01001                         bad_line = line ;
01002                     } 
01003                 }
01004             }
01005             if ( bad_line != line )
01006             {
01007                 agreed = 1 ;
01008                 break ;
01009             }
01010         }
01011         else 
01012         {
01013           sinfo_msg_error("no emission line found in the first image columns") ;
01014             cpl_free( sinfo_edge ) ;
01015             cpl_free( pos_row ) ;
01016             cpl_free( edgeclean ) ;
01017             cpl_free( dummyedge ) ;
01018             cpl_free( pos_rowclean ) ;
01019             return -7 ;
01020         }    
01021     }
01022 
01023 
01024 
01025     if ( agreed == -1 )
01026     {
01027         sinfo_msg_error(" no emission line found in the first image columns") ;
01028         cpl_free( sinfo_edge ) ;
01029         cpl_free( pos_row ) ;
01030         cpl_free( edgeclean ) ;
01031         cpl_free( dummyedge ) ;
01032         cpl_free( pos_rowclean ) ;
01033         return -7 ;
01034     }    
01035 
01036     ilx=cpl_image_get_size_x(lineImage);
01037     ily=cpl_image_get_size_y(lineImage);
01038     pidata=cpl_image_get_data_float(lineImage);
01039 
01040     /* now find and store the raw sinfo_edge positions of the found slitlet */ 
01041     n  = 0 ;
01042     ed = 0 ;
01043     position=cpl_calloc(ilx,sizeof(float)) ;
01044 
01045     /* was for ( col = 0 ; col < ilx - slit_length/2 ; col++ ) */
01046     for ( col = slit_length/2 ; col < ilx - slit_length/2 ; col++ )
01047     {
01048         for ( i = 0 ; i < par[0]->n_params ; i++ )
01049       {   
01050         /*
01051               printf("p1=%f p2=%f p3=%f\n",
01052               par[i]->fit_par[0],par[i]->fit_par[1],par[i]->fit_par[2]);
01053         */
01054             if ( par[i]->column == col && par[i]->line == line )
01055             {
01056                 if ( par[i]->fit_par[0] > 0.  && 
01057                      par[i]->fit_par[1] >= 1. && 
01058                      par[i]->fit_par[2] > 0. )
01059                 {
01060                     position[n] = par[i]->fit_par[2] ;
01061                     old_pos=position[n];
01062                     if ( n > 0 && 
01063                          fabs(position[n] - position[n-1]) > y_box && 
01064                          (col-old_col) > (slit_length-SLIT_POS_ERR) )
01065                     {
01066 
01067               old_col=col;
01068               sinfo_edge[ed] = col ; 
01069               pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
01070                       /* printf("sinfo_edge[%d]=%d , pos_row=%d\n",
01071                                  ed,sinfo_edge[ed],pos_row[ed]); */ 
01072               ed++ ;
01073               if ( col >= ilx - slit_length - SLIT_POS_ERR ) {
01074               pos_row[ed] =  sinfo_new_nint( position[n] ) ;
01075               } 
01076             } else if ( ((col-old_col) > 
01077                                   (slit_length+SLIT_POS_ERR)) &&
01078                                   (col>120) ) {
01079               old_col=col;
01080               sinfo_edge[ed] = col ; 
01081               pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
01082                       sinfo_msg_warning("add1 slitlet edge[%d]=%d, pos_row=%d",
01083                      ed,sinfo_edge[ed],pos_row[ed]);
01084               ed++ ;
01085               if ( col >= ilx - slit_length - SLIT_POS_ERR ) {
01086               pos_row[ed] =  sinfo_new_nint( position[n] ) ;
01087               } 
01088             }
01089                     n++ ;
01090                 }
01091             } else if ( ((col-old_col) > (slit_length+SLIT_POS_ERR)) && 
01092                         (col>120) ) {
01093           /*
01094               printf("check col=%d col-old_col=%d check=%d\n",
01095                      col,(col-old_col),(slit_length+SLIT_POS_ERR));
01096           */
01097           position[n] = old_pos ;
01098              
01099           old_col+=slit_length;
01100           sinfo_edge[ed] = old_col; ; 
01101           pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
01102 
01103 
01104           sinfo_msg_warning("added2 slitlet sinfo_edge[%d]=%d, pos_row=%d",
01105                   ed,sinfo_edge[ed],pos_row[ed]);
01106           ed++ ;
01107           if ( old_col >= ilx - slit_length - SLIT_POS_ERR ) {
01108         pos_row[ed] =  old_pos ;
01109           }
01110           n++;
01111         }
01112         }
01113     }
01114 
01115 
01116     if ( ed < (N_SLITLETS - 1) )
01117     {
01118         sinfo_msg_error(" not enough slitlets, found: %d", ed) ;
01119         cpl_free( sinfo_edge ) ;
01120         cpl_free( pos_row ) ;
01121         cpl_free( edgeclean ) ;
01122         cpl_free( dummyedge ) ;
01123         cpl_free( pos_rowclean ) ;
01124         return -8 ;
01125     } 
01126 
01127     /* now find the clean sinfo_edge and row positions of the slitlets */
01128     /* printf("ed=%d\n",ed); */
01129     for ( i = 1 ; i <= ed ; i ++ )
01130     {
01131         if ( i == ed )
01132         {
01133             if ( (sinfo_edge[i-1] - sinfo_edge[i-2]) < 
01134                   slit_length - SLIT_LEN_ERR ||
01135                  (sinfo_edge[i-1] - sinfo_edge[i-2]) > 
01136                   slit_length + SLIT_LEN_ERR )
01137             {
01138         /* printf("e(i-1)=%d e(i-2)=%d i=%d\n",
01139                        edge[i-1], edge[i-2],i); */
01140                 dummyedge[i-1]   = -1 ;
01141             }
01142         }
01143         if (dummyedge[i-1] != -1)
01144         {
01145             dummyedge[i-1] = sinfo_edge[i-1] ;
01146         }
01147         else
01148         {
01149             continue ;
01150         }
01151         if ( i < ed )
01152         {
01153             if ( (sinfo_edge[i] - sinfo_edge[i-1]) < 
01154                   slit_length - SLIT_LEN_ERR ||
01155                  (sinfo_edge[i] - sinfo_edge[i-1]) > 
01156                   slit_length + SLIT_LEN_ERR )
01157             {
01158         /* printf("e(i)=%d e(i-1)=%d i=%d\n",edge[i], edge[i-1],i); */
01159                 dummyedge[i]   = -1 ;
01160             }
01161         }
01162         if ( i+1 < ed && dummyedge[i] != -1 )
01163         {
01164             if ( (sinfo_edge[i+1] - sinfo_edge[i]) < 
01165                   slit_length - SLIT_LEN_ERR ||
01166                  (sinfo_edge[i+1] - sinfo_edge[i]) > 
01167                   slit_length + SLIT_LEN_ERR )
01168             {
01169         /* printf("e(i+1)=%d e(i)=%d i=%d\n",edge[i+1], edge[i],i); */
01170                 dummyedge[i+1] = -1 ; 
01171             }
01172         }
01173     }
01174 
01175     k = 0 ;
01176     for ( i = 0 ; i < ed ; i++ )
01177     {
01178         if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
01179         {
01180             edgeclean[k] = dummyedge[i] ;
01181             pos_rowclean[k] = pos_row[i] ;
01182             k++ ;
01183             if( edgeclean[k-1] > (ilx - slit_length -2*SLIT_LEN_ERR ) )
01184             {
01185                 pos_rowclean[k] = pos_row[ed] ;
01186             } 
01187         }
01188     }
01189     /*
01190     for ( i = 0 ; i < k ; i++ )
01191     {
01192       sinfo_msg_warning("%d %d", edgeclean[i], pos_rowclean[i]);
01193     }
01194     */
01195     if ( k != N_SLITLETS - 1 )
01196     {
01197         sinfo_msg_error(" wrong number of clean slitlets found: %d", k+1) ;
01198         cpl_free( sinfo_edge ) ;
01199         cpl_free( pos_row ) ;
01200         cpl_free( edgeclean ) ;
01201         cpl_free( dummyedge ) ;
01202         cpl_free( pos_rowclean ) ;
01203         return -7 ;
01204     } 
01205 
01206     /* determine the margins of the fitting box outside the slitlets */
01207     margin = box_length / 2 ;
01208 
01209     /* ----------------------------------------------------------------------
01210      * now go through the slitlets, search along each column within a box with 
01211      * half width y_box the maximum value and store these found values 
01212      * in a buffer
01213      */
01214      if(
01215          ( (pos_rowclean[0]-sinfo_new_nint(y_box)) < 0 ) ||
01216          ( (pos_rowclean[0]+sinfo_new_nint(y_box)) >ily )
01217        ) {
01218 
01219              sinfo_msg_error("pos_rowclean[0] <0 something wrong!") ;
01220              cpl_free( sinfo_edge ) ;
01221              cpl_free( pos_row ) ;
01222              cpl_free( edgeclean ) ;
01223              cpl_free( dummyedge ) ;
01224              cpl_free( pos_rowclean ) ;
01225              return -7 ;
01226 
01227     }
01228 
01229     for ( j = 0 ; j <= k ; j++ )
01230     {
01231         m = 0 ;
01232         if ( j == 0 )
01233         {
01234             box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
01235             for( col = 0 ; col < edgeclean[0] + margin ; col++ )
01236             {
01237                 maxval = -FLT_MAX ;
01238                 for ( row = pos_rowclean[0] - sinfo_new_nint(y_box) ; 
01239                       row <= pos_rowclean[0] + sinfo_new_nint(y_box) ; row++ )
01240                 {
01241                     if ( maxval < pidata[col + ilx*row] )
01242                     {
01243                         maxval = pidata[col + ilx*row] ;
01244                     }
01245                 }
01246                 box_buffer->data[m] = maxval ;
01247                 m++ ;
01248             }
01249         }
01250         else if ( j < k )
01251         {
01252             box_buffer = sinfo_new_vector( edgeclean[j] - 
01253                                            edgeclean[j-1] + 2*margin ) ;
01254             for ( col = edgeclean[j - 1] - margin ; 
01255                   col < edgeclean[j] + margin ; col++ )
01256             {
01257                 maxval = -FLT_MAX ;
01258                 for ( row = pos_rowclean[j] - sinfo_new_nint(y_box) ; 
01259                       row <= pos_rowclean[j] + sinfo_new_nint(y_box) ; row++ )
01260                 {
01261                     if ( maxval < pidata[col + ilx*row] )
01262                     {
01263                         maxval = pidata[col + ilx*row] ;
01264                     }
01265                 }
01266                 box_buffer->data[m] = maxval ;
01267                 m++ ;
01268             }
01269         }
01270         else 
01271         {
01272             box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
01273             for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
01274             {
01275                 maxval = -FLT_MAX ;
01276                 for ( row = pos_rowclean[k-2] - sinfo_new_nint(y_box) ; 
01277                       row <= pos_rowclean[k-2] + sinfo_new_nint(y_box) ; row++ )
01278                 {
01279                     if ( maxval < pidata[col + ilx*row] )
01280                     {
01281                         maxval = pidata[col + ilx*row] ;
01282                     }
01283                 }
01284                 if(maxval>0) box_buffer->data[m] = maxval ;
01285         else box_buffer->data[m] = 0;
01286         m++ ;
01287             }
01288         }
01289 
01290         /* determine the minimum value in the box to get background1 
01291            value for the sinfo_edge slitlets */
01292         min = FLT_MAX ;
01293         for ( i = 0 ; i < box_buffer->n_elements ; i++ )
01294         {
01295             if ( box_buffer -> data[i] < min )
01296             {
01297                 min = box_buffer -> data[i] ;
01298             }
01299         }
01300 
01301         for ( left_right = 0 ; left_right <= 1 ; left_right++ )
01302         { 
01303             nel = 0 ;
01304             if ( left_right == 0 )
01305             {
01306                 nel = box_buffer -> n_elements / 2 ;
01307             }
01308             else
01309             {
01310                 if ( box_buffer -> n_elements % 2 == 0 )
01311                 {
01312                     nel = box_buffer -> n_elements / 2 ;
01313                 }
01314                 else
01315                 {
01316                     nel = box_buffer -> n_elements / 2 + 1 ;
01317                 }
01318             }
01319 
01320             /* now split the buffer in the midth in a left and right 
01321                part for fitting */
01322             half_buffer = sinfo_new_vector( nel ) ;
01323             if ( left_right == 0 )
01324             {
01325                 for ( i = 0 ; i < nel ; i++ )
01326                 {
01327                     half_buffer -> data[i] = box_buffer -> data[i] ;
01328                 }
01329             }
01330             else
01331             {
01332                 n_right = 0 ;
01333                 for ( i = box_buffer -> n_elements - 1 ; 
01334                       i >= box_buffer -> n_elements - nel ; i-- )
01335                 {
01336                     half_buffer -> data[n_right] = box_buffer -> data[i] ;
01337                     n_right++ ;
01338                 }
01339             }
01340 
01341             xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
01342             wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
01343             mpar = (int *)   cpl_calloc( NPAR, sizeof (int) ) ;
01344 
01345             /* set initial values for the fitting routine */
01346             minval =  FLT_MAX ;
01347             maxval = -FLT_MAX ;
01348             for ( i = 0 ; i < nel ; i++ )
01349             {
01350                 xdat[i] = i ;
01351                 wdat[i] = 1.0 ;
01352                 if ( half_buffer -> data[i] < minval )
01353                 {
01354                     minval = half_buffer -> data[i] ;
01355                 }
01356                 if ( half_buffer -> data[i] > maxval )
01357                 {
01358                     maxval = half_buffer -> data[i] ;
01359                 }
01360             }
01361 
01362             fitpar[0] = minval ;
01363             fitpar[1] = maxval ; 
01364 
01365             /* search for both positions of the half intensity 
01366                of the hat within the buffer */
01367             init1 = -1 ; 
01368             for ( i = 0 ; i < nel ; i++ )
01369             {
01370                 if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
01371                 {
01372                     init1 = i ;
01373                     break ;
01374                 }
01375             }
01376 
01377             /*----------------------------------------------------------------
01378              * if we have too few left background values (at the image edges)
01379              * the left margin of the buffer to fit is filled with the minimal
01380              * values in order to get a good fit
01381              */
01382               
01383             edge_ind = 0 ;
01384             if ( init1 < 3 )
01385             {
01386                 n_buf = half_buffer->n_elements + margin ;
01387                 in_buffer = sinfo_new_vector( n_buf ) ;     
01388                 for ( i = 0 ; i < margin ; i++ )
01389                 {
01390                     in_buffer -> data[i] = min ;
01391                 }
01392                 shift = 0 ;
01393                 for ( i = margin ; i < n_buf ; i++ )
01394                 {
01395                     in_buffer -> data[i] = half_buffer -> data[shift] ;
01396                     shift++ ;
01397                 }
01398                 sinfo_new_destroy_vector ( half_buffer ) ;
01399                 half_buffer = sinfo_new_vector ( n_buf ) ;
01400                 for ( i = 0 ; i < n_buf ; i++ )
01401                 {
01402                     half_buffer -> data[i] = in_buffer -> data[i] ;
01403                 }
01404                 edge_ind = 1 ;
01405                 init1 += margin ;
01406                 sinfo_new_destroy_vector ( in_buffer ) ;
01407             }
01408 
01409             /* determine the initial positions from the found values */
01410             if ( init1 != -1 )
01411             {
01412                 fitpar[2] = (float)init1 ;
01413             }
01414             fitpar[3] = 1. ;
01415 
01416             for ( i = 0 ; i < NPAR ; i++ )
01417             {
01418                 mpar[i] = 1 ;
01419                 dervpar[i] = 0. ;
01420             }
01421       
01422             xdim     = XDIMA ;
01423             ndat     = nel ;
01424             numpar   = NPAR ;
01425             tol      = TOLA ;
01426             lab      = LABA ;
01427             its      = ITSA ;
01428          
01429             /* finally, do the least squares fit over the buffer data */
01430             if ( 0 > ( iters = sinfo_new_lsqfit( xdat, &xdim, 
01431                                                  half_buffer -> data, 
01432                                                  wdat, &ndat, fitpar,
01433                                                  dervpar, mpar, &numpar, 
01434                                                  &tol, &its, &lab )) )
01435             { 
01436                 /* if the fit doesn't succeed the initial values are taken */
01437                 sinfo_msg_warning (" least squares fit failed,"
01438                                    " error no.: %d in slitlet: %d", iters, j) ;
01439                 fitpar[2] = (float)init1 ;
01440             }
01441 
01442             pos = fitpar[2] ;
01443             if ( edge_ind == 1 )
01444             {
01445                 pos -= (float)margin ;
01446             }
01447 
01448             /*---------------------------------------------------------------- 
01449              * now discern the left and the right sinfo_edge fit of the 
01450              * slitlets and associate the fit results with the absolute 
01451              * positions in the image consider the difference of the fitted 
01452              * slit position to the expected position and decide wether the 
01453              * fit is taken or the expected value is taken.
01454              */
01455             if ( left_right == 0 )
01456             {
01457                 /* take care of the column position of the fit boxes to get 
01458                    the absolute positions */
01459                 if ( j == 0 )
01460                 {
01461                     if ( fabs(pos - ((float)edgeclean[0] - 1. - 
01462                                      (float)slit_length)) < diff_tol )
01463                     {
01464                         slit_pos[0][0] = pos ;
01465                     }
01466                     else
01467                     {
01468                         sinfo_msg_warning("something wrong with fitted "
01469                                           "left position of slitlet 0") ;
01470                         if ( (float) edgeclean[0] - 1. - 
01471                              (float)slit_length < 0. )
01472                         {
01473                             slit_pos[0][0] = 0. ;
01474                         }
01475                         else
01476                         {
01477                             slit_pos[0][0] = (float)edgeclean[0] - 1. - 
01478                                              (float)slit_length ;
01479                         }
01480                     }
01481                 }
01482                 else if ( j < k )
01483                 {
01484                     if ( fabs( pos - (float)margin ) < diff_tol )
01485                     {
01486                         slit_pos[j][0] = pos + (float)edgeclean[j-1] - 
01487                                                (float)margin ;
01488                     }
01489                     else
01490                     {
01491                         sinfo_msg_warning("something wrong with fitted "
01492                                           "left position of slitlet %d", j) ;
01493                         slit_pos[j][0] = (float)edgeclean[j-1] - 1. ;
01494                     }
01495                 }
01496                 else
01497                 {
01498                     if ( fabs( pos - (float)margin ) < diff_tol )
01499                     {
01500                         slit_pos[k][0] = pos + (float)edgeclean[k-1] - 
01501                                                (float)margin ;
01502                     }
01503                     else
01504                     {
01505                         sinfo_msg_warning("something wrong with fitted "
01506                                           "left position of slitlet %d", j) ;
01507                         slit_pos[k][0] = (float)edgeclean[k-1] - 1. ;
01508                     }
01509                 }
01510             }
01511             else
01512             {
01513                 /* take care of the column position of the fit boxes to 
01514                    get the absolute positions */
01515                 if ( j == 0 )
01516                 {
01517                     if ( fabs( (float)box_buffer->n_elements - pos - 
01518                                (float)edgeclean[0] ) < diff_tol )
01519                     {
01520                         slit_pos[0][1] = (float)(box_buffer->n_elements - 1) - 
01521                                          pos ;
01522                     }
01523                     else
01524                     {
01525                         sinfo_msg_warning("something wrong with fitted "
01526                                           "right position of slitlet 0") ;
01527                         slit_pos[0][1] = (float)edgeclean[0] - 1. ;
01528                     }
01529                 }
01530                 else if ( j < k )
01531                 {
01532                     if ( fabs( (float)box_buffer->n_elements - pos
01533                              + (float)edgeclean[j-1] - (float)margin - 
01534                                (float)edgeclean[j] ) < diff_tol )
01535                     {
01536                         slit_pos[j][1] = (float)(box_buffer->n_elements - 1) - 
01537                                          pos
01538                                        + (float)edgeclean[j-1] - (float)margin ;
01539                     }
01540                     else
01541                     {
01542                         sinfo_msg_warning("something wrong with fitted "
01543                                           "right position of slitlet %d", j) ;
01544                         slit_pos[j][1] = (float)edgeclean[j] - 1. ;
01545                     }
01546                 }
01547                 else
01548                 {
01549                     if ( edgeclean[k-1] + slit_length > ilx )
01550                     {
01551                         last_pos = (float)(ilx - 1) ;
01552                     }
01553                     else
01554                     {
01555                         last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
01556                     }
01557                     if ( fabs( (float)(box_buffer->n_elements - 1) - pos
01558                              + (float)edgeclean[k-1] - (float)margin - 
01559                                last_pos ) < diff_tol )
01560                     {
01561                         slit_pos[k][1] = (float)(box_buffer->n_elements - 1) - 
01562                                          pos
01563                                        + (float)edgeclean[k-1] - (float)margin ;
01564                     }
01565                     else
01566                     {
01567                         sinfo_msg_warning("something wrong with fitted "
01568                                           "right position of slitlet %d", j) ;
01569                         slit_pos[k][1] = last_pos ;
01570                     }
01571                 }
01572             }
01573 
01574             sinfo_new_destroy_vector ( half_buffer ) ;
01575             cpl_free( xdat ) ;
01576             cpl_free( wdat ) ;
01577             cpl_free( mpar ) ;
01578         }
01579         sinfo_new_destroy_vector ( box_buffer ) ;
01580     }
01581      
01582 
01583     cpl_free( sinfo_edge ) ;
01584     cpl_free( pos_row ) ;
01585     cpl_free( edgeclean ) ;
01586     cpl_free( dummyedge ) ;
01587     cpl_free( pos_rowclean ) ;
01588     cpl_free( position);
01589     return 0 ;
01590 }
01591 
01619 int 
01620 sinfo_new_fit_slits_boltz_single_line ( cpl_image   * lineImage, 
01621                               float     ** slit_pos,
01622                               int          box_length,
01623                               float        y_box,
01624                   int          low_pos,
01625                   int          high_pos )
01626 {
01627     int*     position=NULL ;
01628     int   * sinfo_edge, * edgeclean ;
01629     int   * dummyedge ;
01630     int   * pos_row, * pos_rowclean ;
01631     Vector * box_buffer ;
01632     Vector * half_buffer ;
01633     Vector * in_buffer ;
01634     int   found_row ;
01635     int   row, col ;
01636     int   i, j, k, m, ed ;
01637     int   init1 ;
01638     int   nel, n_right, left_right ;
01639     int   n_buf, edge_ind, shift ;
01640     int   slit_length ;
01641     int   margin ;
01642     int   iters, xdim, ndat ;
01643     int   numpar, its ;
01644     int   * mpar ;
01645     float * xdat, * wdat ;
01646     float tol, lab ;
01647     float fitpar[NPAR] ;
01648     float dervpar[NPAR] ;
01649     float minval, maxval ;
01650     float min ;
01651     float pos, last_pos ;
01652     int ilx=0;
01653     int ily=0;
01654     float* pidata=NULL;
01655 
01656     slit_length = SLITLENGTH ;
01657 
01658     if ( NULL == lineImage )
01659     {
01660         sinfo_msg_error(" no line image given!" ) ;
01661         return -1 ;
01662     }
01663 
01664     if ( NULL == slit_pos )
01665     {
01666         sinfo_msg_error(" no position array allocated!" ) ;
01667         return -1 ;
01668     }
01669 
01670     if ( box_length <  4 ||
01671          box_length >  2*slit_length )
01672     {
01673         sinfo_msg_error(" wrong fitting box length given!" ) ;
01674         return -1 ;
01675     }
01676 
01677     if ( y_box <= 0. || y_box > 6. )
01678     {
01679         sinfo_msg_error(" wrong y box length given!" ) ;
01680         return -1 ;
01681     }
01682 
01683     ilx=cpl_image_get_size_x(lineImage);
01684     ily=cpl_image_get_size_y(lineImage);
01685     pidata=cpl_image_get_data_float(lineImage);
01686 
01687     if ( low_pos >= high_pos || low_pos < 0 || 
01688          high_pos <= 0 || high_pos >= ilx )
01689     {
01690         sinfo_msg_error(" wrong user given search positions!" ) ;
01691         return -1 ;
01692     }
01693 
01694     /* allocate memory for the edges and the row position of the slitlets */
01695     sinfo_edge         = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
01696     dummyedge    = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
01697     edgeclean    = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
01698     pos_row      = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
01699     pos_rowclean = (int*) cpl_calloc( ilx/2, sizeof(int) ) ;
01700 
01701     /* now search for the maximum between the given positions for each col */
01702     position=cpl_calloc(ilx,sizeof(int)); ;
01703 
01704     for ( col = 0 ; col < ilx ; col++ )
01705     {
01706         found_row = -1 ;
01707         maxval = -FLT_MAX ;
01708     for ( row = low_pos ; row <= high_pos ; row++ )
01709     {
01710         if ( maxval < pidata[col+row*ilx] )
01711             {
01712         maxval = pidata[col+row*ilx] ;
01713                 found_row = row ;
01714         }
01715     }
01716     if ( maxval > -FLT_MAX && found_row > low_pos )
01717     {
01718             position[col] = found_row ;
01719         }
01720     else
01721     {
01722         position[col] = 0 ;
01723         }
01724     }
01725 
01726     /* now find and store the raw sinfo_edge positions of the found slitlet */ 
01727     ed = 0 ;
01728     for ( col = 0 ; col < (ilx) - 1 ; col++ )
01729     {
01730         if ( position[col] > 0 && position[col+1] > 0 &&
01731          abs(position[col+1] - position[col]) > 10 ) 
01732         {
01733             sinfo_edge[ed] = col ; 
01734             pos_row[ed] = position[col] ;
01735             ed++ ;
01736         }
01737 
01738     }
01739     if (ed <= 1)
01740     {
01741         sinfo_msg_error(" no slitlets found!" ) ;
01742         cpl_free( sinfo_edge ) ;
01743         cpl_free( pos_row ) ;
01744         cpl_free( edgeclean ) ;
01745         cpl_free( dummyedge ) ;
01746         cpl_free( pos_rowclean ) ;
01747         return -1 ;
01748     }
01749 
01750     /* now find the clean sinfo_edge and row positions of the slitlets */
01751     for ( i = 1 ; i <= ed ; i ++ )
01752     {
01753         if ( i == ed )
01754         {
01755             if ( (sinfo_edge[i-1] - sinfo_edge[i-2]) < 
01756                   slit_length - SLIT_LEN_ERR ||
01757                  (sinfo_edge[i-1] - sinfo_edge[i-2]) > 
01758                   slit_length + SLIT_LEN_ERR )
01759             {
01760                 dummyedge[i-1]   = -1 ;
01761             }
01762         }
01763         if (dummyedge[i-1] != -1)
01764         {
01765             dummyedge[i-1] = sinfo_edge[i-1] ;
01766         }
01767         else
01768         {
01769             continue ;
01770         }
01771         if ( i < ed )
01772         {
01773             if ( (sinfo_edge[i] - sinfo_edge[i-1]) < 
01774                   slit_length - SLIT_LEN_ERR ||
01775                  (sinfo_edge[i] - sinfo_edge[i-1]) > 
01776                   slit_length + SLIT_LEN_ERR )
01777             {
01778                 dummyedge[i]   = -1 ;
01779             }
01780         }
01781         if ( i+1 < ed && dummyedge[i] != -1 )
01782         {
01783             if ( (sinfo_edge[i+1] - sinfo_edge[i]) < 
01784                   slit_length - SLIT_LEN_ERR ||
01785                  (sinfo_edge[i+1] - sinfo_edge[i]) > 
01786                   slit_length + SLIT_LEN_ERR )
01787             {
01788                 dummyedge[i+1] = -1 ; 
01789             }
01790         }
01791     }
01792     
01793     k = 0 ;
01794     for ( i = 0 ; i < ed ; i++ )
01795     {
01796         if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
01797         {
01798             edgeclean[k] = dummyedge[i] ;
01799             pos_rowclean[k] = pos_row[i] ;
01800             k++ ;
01801             if( edgeclean[k-1] > (ilx - slit_length - 2*SLIT_LEN_ERR ) )
01802             {
01803                 pos_rowclean[k] = pos_row[ed] ;
01804             }
01805         }
01806     }
01807 
01808     /* determine the margins of the fitting box outside the slitlets */
01809     margin = box_length / 2 ;
01810 
01811     /* ------------------------------------------------------------------------
01812      * now go through the slitlets, search along each column within a box with 
01813      * half width y_box the maximum value and store these found values in a 
01814      * buffer
01815      */
01816     for ( j = 0 ; j <= k ; j++ )
01817     {
01818         m = 0 ;
01819         if ( j == 0 )
01820         {
01821             box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
01822             for( col = 0 ; col < edgeclean[0] + margin ; col++ )
01823             {
01824                 maxval = -FLT_MAX ;
01825                 for ( row = pos_rowclean[0] - sinfo_new_nint(y_box) ; 
01826                       row <= pos_rowclean[0] + sinfo_new_nint(y_box) ; row++ )
01827                 {
01828                     if ( maxval < pidata[col + ilx*row] )
01829                     {
01830                         maxval = pidata[col + ilx*row] ;
01831                     }
01832                 }
01833                 box_buffer->data[m] = maxval ;
01834                 m++ ;
01835             }
01836         }
01837         else if ( j < k )
01838         {
01839             box_buffer = sinfo_new_vector( edgeclean[j] - 
01840                                            edgeclean[j-1] + 2*margin ) ;
01841             for ( col = edgeclean[j - 1] - margin ; 
01842                   col < edgeclean[j] + margin ; col++ )
01843             {
01844                 maxval = -FLT_MAX ;
01845                 for ( row = pos_rowclean[j] - sinfo_new_nint(y_box) ; 
01846                       row <= pos_rowclean[j] + sinfo_new_nint(y_box) ; row++ )
01847                 {
01848                     if ( maxval < pidata[col + ilx*row] )
01849                     {
01850                         maxval = pidata[col + ilx*row] ;
01851                     }
01852                 }
01853                 box_buffer->data[m] = maxval ;
01854                 m++ ;
01855             }
01856         }
01857         else 
01858         {
01859             box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
01860             for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
01861             {
01862         if ( col < 0 )
01863         {
01864             col = 0 ;
01865                 }
01866 
01867                 maxval = -FLT_MAX ;
01868                 for ( row = pos_rowclean[k] - sinfo_new_nint(y_box) ; 
01869                       row <= pos_rowclean[k] + sinfo_new_nint(y_box) ; row++ )
01870                 {
01871             if ( row < 0 )
01872                     {
01873             continue ;
01874                     }
01875                     if ( maxval < pidata[col + row * ilx] )
01876                     {
01877                         maxval = pidata[col + row * ilx] ;
01878                     }
01879                 }
01880                 box_buffer->data[m] = maxval ;
01881                 m++ ;
01882             }
01883         }
01884 
01885         /* determine the minimum value in the box to get background1 
01886            value for the sinfo_edge slitlets */
01887         min = FLT_MAX ;
01888         for ( i = 0 ; i < box_buffer->n_elements ; i++ )
01889         {
01890             if ( box_buffer -> data[i] < min )
01891             {
01892                 min = box_buffer -> data[i] ;
01893             }
01894         }
01895 
01896         for ( left_right = 0 ; left_right <= 1 ; left_right++ )
01897         { 
01898             nel = 0 ;
01899             if ( left_right == 0 )
01900             {
01901                 nel = box_buffer -> n_elements / 2 ;
01902             }
01903             else
01904             {
01905                 if ( box_buffer -> n_elements % 2 == 0 )
01906                 {
01907                     nel = box_buffer -> n_elements / 2 ;
01908                 }
01909                 else
01910                 {
01911                     nel = box_buffer -> n_elements / 2 + 1 ;
01912                 }
01913             }
01914 
01915             /* now split the buffer in the midth in a left and 
01916                right part for fitting */
01917             half_buffer = sinfo_new_vector( nel ) ;
01918             if ( left_right == 0 )
01919             {
01920                 for ( i = 0 ; i < nel ; i++ )
01921                 {
01922                     half_buffer -> data[i] = box_buffer -> data[i] ;
01923                 }
01924             }
01925             else
01926             {
01927                 n_right = 0 ;
01928                 for ( i = box_buffer -> n_elements - 1 ; 
01929                       i >= box_buffer -> n_elements - nel ; i-- )
01930                 {
01931                     half_buffer -> data[n_right] = box_buffer -> data[i] ;
01932                     n_right++ ;
01933                 }
01934             }
01935 
01936             xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
01937             wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
01938             mpar = (int *)   cpl_calloc( NPAR, sizeof (int) ) ;
01939 
01940             /* set initial values for the fitting routine */
01941             minval =  FLT_MAX ;
01942             maxval = -FLT_MAX ;
01943             for ( i = 0 ; i < nel ; i++ )
01944             {
01945                 xdat[i] = i ;
01946                 wdat[i] = 1.0 ;
01947                 if ( half_buffer -> data[i] < minval )
01948                 {
01949                     minval = half_buffer -> data[i] ;
01950                 }
01951                 if ( half_buffer -> data[i] > maxval )
01952                 {
01953                     maxval = half_buffer -> data[i] ;
01954                 }
01955             }
01956             fitpar[0] = minval ;
01957             fitpar[1] = maxval ; 
01958 
01959             /* search for both positions of the half intensity of 
01960                the hat within the buffer */
01961             init1 = -1 ; 
01962             for ( i = 0 ; i < nel ; i++ )
01963             {
01964                 if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
01965                 {
01966                     init1 = i ;
01967                     break ;
01968                 }
01969             }
01970 
01971             /*---------------------------------------------------------------
01972              * if we have too few left background values (at the image edges)
01973              * the left margin of the buffer to fit is filled with the minimal
01974              * values in order to get a good fit
01975              */
01976               
01977             edge_ind = 0 ;
01978             if ( init1 < 3 )
01979             {
01980                 n_buf = half_buffer->n_elements + margin ;
01981                 in_buffer = sinfo_new_vector( n_buf ) ;     
01982                 for ( i = 0 ; i < margin ; i++ )
01983                 {
01984                     in_buffer -> data[i] = min ;
01985                 }
01986                 shift = 0 ;
01987                 for ( i = margin ; i < n_buf ; i++ )
01988                 {
01989                     in_buffer -> data[i] = half_buffer -> data[shift] ;
01990                     shift++ ;
01991                 }
01992                 sinfo_new_destroy_vector ( half_buffer ) ;
01993                 half_buffer = sinfo_new_vector ( n_buf ) ;
01994                 for ( i = 0 ; i < n_buf ; i++ )
01995                 {
01996                     half_buffer -> data[i] = in_buffer -> data[i] ;
01997                 }
01998                 edge_ind = 1 ;
01999                 init1 += margin ;
02000                 sinfo_new_destroy_vector ( in_buffer ) ;
02001             }
02002 
02003             /* determine the initial positions from the found values */
02004             if ( init1 != -1 )
02005             {
02006                 fitpar[2] = (float)init1 ;
02007             }
02008             fitpar[3] = 1. ;
02009 
02010             for ( i = 0 ; i < NPAR ; i++ )
02011             {
02012                 mpar[i] = 1 ;
02013                 dervpar[i] = 0. ;
02014             }
02015       
02016             xdim     = XDIMA ;
02017             ndat     = nel ;
02018             numpar   = NPAR ;
02019             tol      = TOLA ;
02020             lab      = LABA ;
02021             its      = ITSA ;
02022          
02023             /* finally, do the least squares fit over the buffer data */
02024             if ( 0 > ( iters = sinfo_new_lsqfit( xdat, &xdim, 
02025                                                  half_buffer -> data, 
02026                                                  wdat, &ndat, fitpar,
02027                                                  dervpar, mpar, &numpar, 
02028                                                  &tol, &its, &lab )) )
02029             { 
02030                 sinfo_msg_warning (" least squares fit failed, error "
02031                                    "no.: %d in slitlet: %d", iters, j) ;
02032                 fitpar[2] = 0. ;
02033             }
02034         if ( fitpar[3] <=0. )
02035             { 
02036                 sinfo_msg_warning(" fit failed due to negative width"
02037                                   " of boltzmann function in slitlet: %d", j) ;
02038                 fitpar[2] = 0. ;
02039             }
02040 
02041             pos = fitpar[2] ;
02042             if ( edge_ind == 1 )
02043             {
02044                 pos -= (float)margin ;
02045             }
02046 
02047             /*------------------------------------------------------------- 
02048              * now discern the left and the right sinfo_edge fit of the 
02049              * slitlets and associate the fit results with the absolute 
02050              * positions in the image consider the difference of the fitted 
02051              * slit position to the expected position and decide wether the 
02052              * fit is taken or the expected value is taken.
02053              */
02054             if ( left_right == 0 )
02055             {
02056                 /* take care of the column position of the fit boxes to 
02057                    get the absolute positions */
02058                 if ( j == 0 )
02059                 {
02060                     slit_pos[0][0] = pos ;
02061             if ( slit_pos[0][0] - (int) slit_pos[0][0] == 0.)
02062             {
02063                         slit_pos[0][0] = 0. ;
02064                     }
02065                 }
02066                 else if ( j < k )
02067                 {
02068                     slit_pos[j][0] = pos + (float)edgeclean[j-1] - 
02069                                            (float)margin ;
02070             if ( slit_pos[j][0] - (int) slit_pos[j][0] == 0.)
02071             {
02072                         slit_pos[j][0] = 0. ;
02073                     }
02074                 }
02075                 else
02076                 {
02077                     slit_pos[k][0] = pos + (float)edgeclean[k-1] - 
02078                                            (float)margin ;
02079             if ( slit_pos[k][0] - (int) slit_pos[k][0] == 0.)
02080             {
02081                         slit_pos[k][0] = 0. ;
02082                     }
02083                 }
02084             }
02085             else
02086             {
02087                 /* take care of the column position of the fit boxes to 
02088                    get the absolute positions */
02089                 if ( j == 0 )
02090                 {
02091                     slit_pos[0][1] = (float)(box_buffer->n_elements - 1) - pos;
02092             if ( slit_pos[0][1] - (int) slit_pos[0][1] == 0.)
02093             {
02094                         slit_pos[0][1] = 0. ;
02095                     }
02096                 }
02097                 else if ( j < k )
02098                 {
02099                     slit_pos[j][1] = (float)(box_buffer->n_elements - 1) - pos
02100                                      + (float)edgeclean[j-1] - (float)margin ;
02101             if ( slit_pos[j][1] - (int) slit_pos[j][1] == 0.)
02102             {
02103                         slit_pos[j][1] = 0. ;
02104                     }
02105                 }
02106                 else
02107                 {
02108                     last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
02109                     slit_pos[k][1] = (float)(box_buffer->n_elements - 1) - pos
02110                                      + (float)edgeclean[k-1] - (float)margin ;
02111             if ( slit_pos[k][1] - (int) slit_pos[k][1] == 0.)
02112             {
02113                         slit_pos[k][1] = 0. ;
02114                     }
02115                 }
02116             }
02117 
02118             sinfo_new_destroy_vector ( half_buffer ) ;
02119             cpl_free( xdat ) ;
02120             cpl_free( wdat ) ;
02121             cpl_free( mpar ) ;
02122         }
02123         sinfo_new_destroy_vector ( box_buffer ) ;
02124     }
02125         
02126     cpl_free( sinfo_edge ) ;
02127     cpl_free( pos_row ) ;
02128     cpl_free( edgeclean ) ;
02129     cpl_free( dummyedge ) ;
02130     cpl_free( pos_rowclean ) ;
02131     cpl_free( position );
02132     return 0 ;
02133 }
02134 
02163 int 
02164 sinfo_new_fit_slits_boltz_with_estimate ( cpl_image   * lineImage, 
02165                                 float     ** slit_pos,
02166                                 int          box_length,
02167                                 float        y_box,
02168                                 float        diff_tol,
02169                     int          low_pos,
02170                     int          high_pos )
02171 {
02172     int*     position=NULL ;
02173     Vector * box_buffer ;
02174     Vector * in_buffer ;
02175     int   found_row ;
02176     int   row, col ;
02177     int   col_first, col_last ;
02178     int   row_first, row_last ;
02179     int   i, j, m, n ;
02180     int   init1 ;
02181     int   left_right ;
02182     int   n_buf, shift ;
02183     int   slit_length ;
02184     int   iters, xdim, ndat ;
02185     int   numpar, its ;
02186     int   * mpar ;
02187     float * xdat, * wdat ;
02188     float tol, lab ;
02189     float fitpar[NPAR] ;
02190     float dervpar[NPAR] ;
02191     float minval, maxval ;
02192     float pos ;
02193     float new_pos ;
02194     int   slitposition[SLITLENGTH] ;
02195     pixelvalue rowpos[SLITLENGTH] ;
02196 
02197     int ilx=0;
02198     int ily=0;
02199     float* pidata=NULL;
02200 
02201     slit_length = SLITLENGTH ; /* this setting is too much 64 */
02202     slit_length = N_SLITLETS ; /* this setting is better: 32 */
02203 
02204     if ( NULL == lineImage )
02205     {
02206         sinfo_msg_error(" no line image given!" ) ;
02207         return -1 ;
02208     }
02209 
02210     if ( NULL == slit_pos )
02211     {
02212         sinfo_msg_error(" no position array allocated!" ) ;
02213         return -1 ;
02214     }
02215 
02216     if ( box_length < 4 ||
02217          box_length > 2*slit_length )
02218     {
02219         sinfo_msg_error(" wrong fitting box length given!" ) ;
02220         return -1 ;
02221     }
02222 
02223     if ( y_box <= 0. || y_box > 6. )
02224     {
02225         sinfo_msg_error(" wrong y box length given!" ) ;
02226         return -1 ;
02227     }
02228     if ( diff_tol <= 0. )
02229     {
02230         sinfo_msg_error(" wrong diff_tol given!" ) ;
02231         return -1 ;
02232     }
02233 
02234     ilx=cpl_image_get_size_x(lineImage);
02235     ily=cpl_image_get_size_y(lineImage);
02236     pidata=cpl_image_get_data_float(lineImage);
02237 
02238     if ( low_pos >= high_pos || low_pos < 0 || 
02239          high_pos <= 0 || high_pos > ily )
02240     {
02241         sinfo_msg_error(" wrong user given search positions!" ) ;
02242         return -1 ;
02243     }
02244 
02245     /* now search for the maximum between the given positions for each col */
02246     position=cpl_calloc(ilx,sizeof(int)) ;
02247     for ( col = 0 ; col < ilx ; col++ )
02248     {
02249         found_row = -1 ;
02250         maxval = -FLT_MAX ;
02251     for ( row = low_pos ; row <= high_pos ; row++ )
02252     {
02253         if ( maxval < pidata[col+row*ilx] )
02254             {
02255         maxval = pidata[col+row*ilx] ;
02256                 found_row = row ;
02257         }
02258     }
02259     if ( maxval > -FLT_MAX && found_row > low_pos )
02260     {
02261             position[col] = found_row ;
02262         }
02263     else
02264     {
02265         position[col] = 0 ;
02266         }
02267     }
02268     
02269     /* ------------------------------------------------------------------------
02270      * now go through the slitlets, search along each column within a box with 
02271      * half width y_box the maximum value and store these found values in a 
02272      * buffer
02273      */
02274     for ( j = 0 ; j < slit_length ; j++ )
02275     {
02276         /* now go through the columns and determine the slitlet positions by
02277          * calculating the median of the found positions 
02278          */
02279         n = 0 ;
02280         
02281         for ( col = sinfo_new_nint(slit_pos[j][0])+ 1 ; 
02282               col < sinfo_new_nint(slit_pos[j][1]) -1 ; col++ )
02283         {
02284             rowpos[n] = (pixelvalue)position[col] ;
02285             n++ ;
02286         }
02287 
02288         slitposition[j] = (int)sinfo_new_median(rowpos, n) ;
02289         for ( left_right = 0 ; left_right <= 1 ; left_right++ )
02290         {
02291             init1 = 0 ;
02292             col_first = sinfo_new_nint( slit_pos[j][left_right] ) - 
02293                                         box_length/2 ;
02294             col_last  = sinfo_new_nint( slit_pos[j][left_right] ) + 
02295                                         box_length/2 ;
02296             if ( col_first < 0 )
02297             {
02298                 col_first = 0 ;
02299                 init1 = 1 ;
02300             }
02301             if ( col_last > ilx )
02302             {
02303                 col_last = ilx ;
02304                 init1 = 1 ;
02305             }
02306             if ( col_last - col_first <= 0 )
02307             {
02308                 sinfo_msg_error(" first and last column wrong!" ) ;
02309                 return -1 ;
02310             }
02311             box_buffer = sinfo_new_vector( col_last - col_first ) ;
02312             m = 0 ;
02313 
02314 
02315             if ( left_right == 0 )
02316             {
02317                 for( col = col_first ; col < col_last ; col++ )
02318                 {
02319                     row_first = slitposition[j] - sinfo_new_nint(y_box) ;
02320                     row_last  = slitposition[j] + sinfo_new_nint(y_box) ;
02321                     if ( row_first < 0 )
02322                     {
02323                         row_first = 0 ;
02324                     }
02325                     if ( row_last >= ily  )
02326                     {
02327                         row_last = ily - 1 ;
02328                     }
02329                     maxval = -FLT_MAX ;
02330                     for ( row = row_first ; row <= row_last ; row++ )
02331                     {
02332                         if ( maxval < pidata[col + ilx*row] )
02333                         {
02334                             maxval = pidata[col + ilx*row] ;
02335                         }
02336                     }
02337                     box_buffer->data[m] = maxval ;
02338                     m++ ;
02339                 }
02340 
02341             }
02342             else 
02343             {
02344 
02345                 for( col = col_last-1 ; col >= col_first ; col-- )
02346                 {
02347                     row_first = slitposition[j] - sinfo_new_nint(y_box) ;
02348                     row_last  = slitposition[j] + sinfo_new_nint(y_box) ;
02349                     if ( row_first < 0 )
02350                     {
02351                         row_first = 0 ;
02352                     }
02353                     if ( row_last >= ily  )
02354                     {
02355                         row_last = ily - 1 ;
02356                     }
02357                     maxval = -FLT_MAX ;
02358                     for ( row = row_first ; row <= row_last ; row++ )
02359                     {
02360                         if ( maxval < pidata[col + ilx*row] )
02361                         {
02362                             maxval = pidata[col + ilx*row] ;
02363                         }
02364                     }
02365                     box_buffer->data[m] = maxval ;
02366                     m++ ;
02367                 }
02368 
02369             }
02370 
02371             xdat=(float *) cpl_calloc(box_buffer->n_elements, sizeof (float) );
02372             wdat=(float *) cpl_calloc(box_buffer->n_elements, sizeof (float) );
02373             mpar=(int *)   cpl_calloc(NPAR, sizeof (int) ) ;
02374 
02375             /* set initial values for the fitting routine */
02376             minval =  FLT_MAX ;
02377             maxval = -FLT_MAX ;
02378 
02379             for ( i = 0 ; i < box_buffer->n_elements ; i++ )
02380             {
02381                 xdat[i] = i ;
02382                 wdat[i] = 1.0 ;
02383                 if ( box_buffer -> data[i] < minval )
02384                 {
02385                     minval = box_buffer -> data[i] ;
02386                 }
02387                 if ( box_buffer -> data[i] > maxval )
02388                 {
02389                     maxval = box_buffer -> data[i] ;
02390                 }
02391             }
02392             fitpar[0] = minval ;
02393             fitpar[1] = maxval ; 
02394 
02395             /*-----------------------------------------------------------------
02396              * if we have too few left background values (at the image edges)
02397              * the left margin of the buffer to fit is filled with the minimal
02398              * values in order to get a good fit
02399              */
02400             
02401   
02402             if ( init1 == 1 )
02403             {
02404                 n_buf = box_buffer->n_elements + box_length/2 ;
02405                 in_buffer = sinfo_new_vector( n_buf ) ;     
02406                 for ( i = 0 ; i < box_length/2 ; i++ )
02407                 {
02408                     in_buffer -> data[i] = minval ;
02409                 }
02410                 shift = 0 ;
02411                 for ( i = box_length/2 ; i < n_buf ; i++ )
02412                 {
02413                     in_buffer -> data[i] = box_buffer -> data[shift] ;
02414                     shift++ ;
02415                 }
02416                 sinfo_new_destroy_vector ( box_buffer ) ;
02417                 box_buffer = sinfo_new_vector ( n_buf ) ;
02418                 for ( i = 0 ; i < n_buf ; i++ )
02419                 {
02420                     box_buffer -> data[i] = in_buffer -> data[i] ;
02421                 }
02422                 sinfo_new_destroy_vector ( in_buffer ) ;
02423             }
02424 
02425             /* determine the initial positions from the found values */
02426             fitpar[2] = (float)box_buffer->n_elements/2.  ;
02427             fitpar[3] = 1. ;
02428 
02429             for ( i = 0 ; i < NPAR ; i++ )
02430             {
02431                 mpar[i] = 1 ;
02432                 dervpar[i] = 0. ;
02433             }
02434       
02435             xdim     = XDIMA ;
02436             ndat     = box_buffer->n_elements ;
02437             numpar   = NPAR ;
02438             tol      = TOLA ;
02439             lab      = LABA ;
02440             its      = ITSA ;
02441          
02442             /* finally, do the least squares fit over the buffer data */
02443             if ( 0 > ( iters = sinfo_new_lsqfit( xdat, &xdim, 
02444                                                  box_buffer -> data, 
02445                                                  wdat, &ndat, fitpar,
02446                                                  dervpar, mpar, &numpar, 
02447                                                  &tol, &its, &lab )) )
02448             { 
02449                 sinfo_msg_warning ("least squares fit failed, error "
02450                                    "no.: %d in slitlet: %d\n", iters, j) ;
02451                 sinfo_new_destroy_vector(box_buffer) ;
02452                 cpl_free( xdat ) ;
02453                 cpl_free( wdat ) ;
02454                 cpl_free( mpar ) ;
02455                 continue ;
02456             }
02457 
02458         if ( fitpar[3] <=0. )
02459             { 
02460                 sinfo_msg_warning ("fit failed due to negative width of "
02461                                    "boltzmann function in slitlet: %d\n", j) ;
02462                 sinfo_new_destroy_vector(box_buffer) ;
02463                 cpl_free( xdat ) ;
02464                 cpl_free( wdat ) ;
02465                 cpl_free( mpar ) ;
02466                 continue ;
02467             }
02468             pos = fitpar[2] ;
02469             if ( init1 == 1 )
02470             {
02471                 pos -= (float)box_length/2. ;
02472             }
02473 
02474             /*-------------------------------------------------------------
02475              * now compute the real slit positions using the guess positions
02476              * if the fit did not work the guess positions are taken
02477              * the same is done if the deviations are too big.
02478              */
02479             if ( pos != 0. )  
02480             {
02481                 if ( left_right == 0 )
02482                 {
02483                     new_pos = (float)col_first + pos ;
02484                 }
02485                 else
02486                 {
02487                     new_pos = (float)col_last-1 - pos ;
02488                 }
02489                 if ( fabs(new_pos - slit_pos[j][left_right]) < diff_tol )
02490                 {
02491                     slit_pos[j][left_right] = new_pos ;
02492                 }
02493                 else
02494                 {
02495                     sinfo_msg_warning (" deviation bigger than tolerance,"
02496                                        " take the estimated slitlet position "
02497                                        " in slitlet: %d\n", j) ;
02498                 }
02499             }
02500 
02501             cpl_free( xdat ) ;
02502             cpl_free( wdat ) ;
02503             cpl_free( mpar ) ;
02504             sinfo_new_destroy_vector ( box_buffer ) ;
02505 
02506         }
02507     }
02508     cpl_free(position);
02509     return 0 ;
02510 }
02511                               
02512 /*--------------------------------------------------------------------------*/

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