sinfo_absolute.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  14/11/00  created
00027 */
00028 /*---------------------------------------------------------------------------*/
00033 /*---------------------------------------------------------------------------*/
00037 /************************************************************************
00038 *   NAME
00039 *        sinfo_absolute.c - routines to determine the absolute positions 
00040 *        of the slitlets out of an emission line frame
00041 *
00042 *   SYNOPSIS
00043 *   #include "absolute.h"
00044 *
00045 *   1) float sinfo_new_edge( float * xdat, float * parlist, 
00046                              int * npar, int * ndat )
00047 *   2) void sinfo_new_edge_deriv( float * xdat, float * parlist, 
00048                                   float * dervs, int * npar )
00049 *   3) static int sinfo_new_inv_mat_edge (void)
00050 *   4) static new_void sinfo_get_mat_edge ( float * xdat,
00051 *                                 int   * xdim,
00052 *                                 float * ydat,
00053 *                                 float * wdat,
00054 *                                 int   * ndat,
00055 *                                 float * fpar,
00056 *                                 float * epar,
00057 *                                 int   * npar )
00058 *   5) static int sinfo_new_get_vec_edge ( float * xdat,
00059 *                                int   * xdim,
00060 *                                float * ydat,
00061 *                                float * wdat,
00062 *                                int   * ndat,
00063 *                                float * fpar,
00064 *                                float * epar,
00065 *                                int   * npar )
00066 *   6) int sinfo_new_lsqfit_edge ( float * xdat,
00067 *                        int   * xdim,
00068 *                        float * ydat,
00069 *                        float * wdat,
00070 *                        int   * ndat,
00071 *                        float * fpar,
00072 *                        float * epar,
00073 *                        int   * mpar,
00074 *                        int   * npar,
00075 *                        float * tol ,
00076 *                        int   * its ,
00077 *                        float * lab  )
00078 *   7) int sinfo_new_fit_slits_edge( cpl_image   * lineImage, 
00079 *                        FitParams ** par,
00080 *                        float     ** sinfo_slit_pos,
00081 *                        int          box_length,
00082 *                        float        y_box,
00083 *                        float        diff_tol )
00084 *   8) int sinfo_new_fit_slits_edge_with_estimate ( cpl_image   * lineImage,
00085 *                                     float     ** sinfo_slit_pos,
00086 *                                     int          box_length,
00087 *                                     float        y_box,
00088 *                                     float        diff_tol,
00089 *                                     int          low_pos,
00090 *                                     int          high_pos )
00091 *
00092 *   DESCRIPTION
00093 *   1) calculates the value of a slope function with parameters 
00094 *      parlist at the position xdat 
00095 *   2) calculates the partial derivatives for a slope function with
00096 *      parameters parlist at position xdat 
00097 *   3) calculates the inverse of matrix2. The algorithm used 
00098 *      is the Gauss-Jordan algorithm described in Stoer,
00099 *      Numerische Mathematik, 1. Teil.
00100 *   4) builds the sinfo_matrix 
00101 *   5) calculates the correction sinfo_vector. The sinfo_matrix has been
00102 *      built by get_mat_edge(), we only have to rescale it for the 
00103 *      current value of labda. The sinfo_matrix is rescaled so that
00104 *      the diagonal gets the value 1 + labda.
00105 *      Next we calculate the inverse of the sinfo_matrix and then
00106 *      the correction sinfo_vector.
00107 *   6) this is a routine for making a least-squares fit of a
00108 *      function to a set of data points. The method used is
00109 *      described in: Marquardt, J.Soc.Ind.Appl.Math. 11. 431 (1963).
00110 *      This method is a mixture of the steepest descent method 
00111 *      and the Taylor method.
00112 *   7) fits the beginning and end position of the slitlets
00113 *      by using non-linear least square fitting of a step function
00114 *      fits a step function to the slitlet edges exposed and indicated
00115 *      by the brightest emission lines. To achieve this, the fit
00116 *      parameters are used to find the brightest emission line
00117 *      and to get its position for each column.
00118 *      The least squares fit is done by using a box smaller than
00119 *      the size of two slitlets
00120 *   8) fits the beginning and end position of the slitlets
00121 *      by using non-linear least square fitting of an sinfo_edge  function
00122 *      fits a linear edge function to the slitlet edges exposed and indicated
00123 *      by the brightest emission lines. The slitlet is searched within
00124 *      user given positions.
00125 *      The least squares fit is done by using a box smaller than
00126 *      the size of two slitlets 
00127 *
00128 *   FILES
00129 *
00130 *   ENVIRONMENT
00131 *
00132 *   RETURN VALUES
00133 *
00134 *   CAUTIONS
00135 *
00136 *   EXAMPLES
00137 *
00138 *   SEE ALSO
00139 *
00140 *   BUGS
00141 *
00142 *------------------------------------------------------------------------
00143 */
00144 #ifdef HAVE_CONFIG_H
00145 #  include <config.h>
00146 #endif
00147 #include "sinfo_vltPort.h"
00148 /*
00149  * System Headers
00150  */
00151 
00152 /*
00153  * Local Headers
00154  */
00155 
00156 #include "sinfo_absolute.h"
00157 #include "sinfo_recipes.h"
00158 /*----------------------------------------------------------------------------
00159  *                                 Defines
00160  *--------------------------------------------------------------------------*/
00161 static float  sqrarg ;
00162 #define SQR(a) (sqrarg = (a) , sqrarg*sqrarg)
00163 
00164 #define XDIMA         1         /* dimension of the x values */
00165 #define TOLA          0.001     /* fitting tolerance */
00166 #define LABA          0.1       /* labda parameter */
00167 #define ITSA          200       /* maximum number of iterations */
00168 #define LABFACA       10.0      /* labda step factor */
00169 #define LABMAXA       1.0e+10   /* maximum value for labda */
00170 #define LABMINA       1.0e-10   /* minimum value for labda */
00171 #define NPAR          4         /* number of fit parameters */
00172 
00173 /*----------------------------------------------------------------------------
00174  *                                    Local variables
00175  *--------------------------------------------------------------------------*/
00176 
00177 static double chi1 ;                    /* old reduced chi-squared */
00178 static double chi2 ;                    /* new reduced chi-squared */
00179 static double labda ;                   /* mixing parameter */
00180 static double vec[NPAR] ;               /* correction sinfo_vector */
00181 static double matrix1[NPAR][NPAR] ;     /* original sinfo_matrix */
00182 static double matrix2[NPAR][NPAR] ;     /* inverse of matrix1 */
00183 static int    nfree ;                   /* number of free parameters */
00184 static int    parptr[NPAR] ;            /* parameter pointer */
00185 static float  slopewidth ;              /* initial value for fit parameter 5: 
00186                                            width of linear slope */
00187 
00188 /*----------------------------------------------------------------------------
00189  *                    Functions private to this module
00190  *--------------------------------------------------------------------------*/
00191 static int sinfo_new_inv_mat_edge (void) ;
00192 
00193 static void sinfo_new_get_mat_edge ( float * xdat,
00194                            int   * xdim,
00195                            float * ydat,
00196                            float * wdat,
00197                            int   * ndat,
00198                            float * fpar,
00199                            float * epar/*,
00200                            int   * npar*/ ) ;
00201 
00202 static int sinfo_new_get_vec_edge ( float * xdat,
00203                           int   * xdim,
00204                           float * ydat,
00205                           float * wdat,
00206                           int   * ndat,
00207                           float * fpar,
00208                           float * epar,
00209                           int   * npar ) ;
00210 float 
00211 sinfo_new_hat2 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ );
00212 
00213 float 
00214 sinfo_new_hat1 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ );
00215 
00216 void 
00217 sinfo_new_hat_deriv2(float * xdat, float * parlist, 
00218                      float * dervs/*, int * npar*/ );
00219 
00220 void 
00221 sinfo_new_hat_deriv1( float * xdat, float * parlist, 
00222                       float * dervs/*, int * npar*/ );
00223 
00224 int 
00225 sinfo_new_fit_slits1( cpl_image   * lineImage, 
00226                FitParams ** par,
00227                float     ** sinfo_slit_pos,
00228                int          box_length,
00229               float        y_box );
00230 
00231 int 
00232 sinfo_new_fit_slits( cpl_image   * lineImage, 
00233               FitParams ** par,
00234               float     ** sinfo_slit_pos,
00235               int          box_length,
00236               float        y_box,
00237              float        slope_width );
00238 
00239 
00240 
00241 int 
00242 sinfo_new_fit_slits2( cpl_image   * lineImage, 
00243                FitParams ** par,
00244                float     ** sinfo_slit_pos,
00245                int          box_length,
00246                float        y_box,
00247               float        diff_tol );
00248 /*----------------------------------------------------------------------------
00249  *                            Function codes
00250  *--------------------------------------------------------------------------*/
00251 
00270 float 
00271 sinfo_new_edge ( float * xdat, float * parlist/*, int * npar, int * ndat*/ )
00272 {
00273     float return_value ;
00274     float slope1 ;
00275 
00276     /* compute the slopes */
00277     slope1 = ( parlist[3] - parlist[2] ) / ( parlist[1] - parlist[0] ) ;
00278 
00279     /* now build the hat function out of the parameters */
00280     if ( xdat[0] <= parlist[0] )
00281     {
00282         return_value = parlist[2] ;
00283     }
00284     else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
00285     {
00286         return_value = (xdat[0] - parlist[0]) * slope1 + parlist[2] ;
00287     }
00288     else if ( xdat[0] > parlist[1] )
00289     {
00290         return_value = parlist[3] ;
00291     }
00292     else
00293     {
00294         return_value = 0. ;
00295     }
00296     
00297     return return_value ;
00298 }
00299 
00329 float 
00330 sinfo_new_hat2 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ )
00331 {
00332     float return_value ;
00333     float slope1, slope2, slope3 ;
00334 
00335     /* compute the slopes */
00336     slope1 = ( parlist[6] - parlist[4] ) / ( parlist[1] - parlist[0] ) ;
00337     slope2 = ( parlist[7] - parlist[5] ) / ( parlist[3] - parlist[2] ) ;
00338     slope3 = ( parlist[7] - parlist[6] ) / ( parlist[2] - parlist[1] ) ;
00339 
00340     /* now build the hat function out of the parameters */
00341     if ( xdat[0] <= parlist[0] )
00342     {
00343         return_value = parlist[4] ;
00344     }
00345     else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
00346     {
00347         return_value = (xdat[0] - parlist[0]) * slope1 + parlist[4] ;
00348     }
00349     else if ( xdat[0] > parlist[1] && xdat[0] <= parlist[2] )
00350     {
00351         return_value = (xdat[0] - parlist[1]) * slope3 + parlist[6] ;
00352     }
00353     else if ( xdat[0] > parlist[2] && xdat[0] <= parlist[3] )
00354     {
00355         return_value = (parlist[3] - xdat[0]) * slope2 + parlist[5] ;
00356     }
00357     else if ( xdat[0] > parlist[3] )
00358     {
00359         return_value = parlist[5] ;
00360     }
00361     else
00362     {
00363         return_value = 0. ;
00364     }
00365     
00366     return return_value ;
00367 }
00368 
00369 
00399 float 
00400 sinfo_new_hat1 ( float * xdat, float * parlist/*, int * npar, int * ndat*/ )
00401 {
00402     float return_value=0 ;
00403     float slope1, slope2 ;
00404 
00405    /* take only positive values for the fit parameters */
00406 
00407     /* compute the slopes */
00408     slope1 = (parlist[4] - parlist[2]) / slopewidth ;
00409     slope2 = (parlist[4] - parlist[3]) / slopewidth ;
00410 
00411     /* now build the hat function out of the parameters */
00412     if ( xdat[0] <= parlist[0] )
00413     {
00414         return_value = parlist[2] ;
00415     }
00416     else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[0] + slopewidth )
00417     {
00418         return_value = (xdat[0] - parlist[0]) * slope1 + parlist[2] ;
00419     }
00420     else if ( xdat[0] > parlist[0] + slopewidth && 
00421               xdat[0] <= parlist[1] - slopewidth )
00422     {
00423         return_value = parlist[4] ;
00424     }
00425     else if ( xdat[0] > parlist[1] - slopewidth && xdat[0] <= parlist[1] )
00426     {
00427         return_value = (parlist[1] - xdat[0]) * slope2 + parlist[3] ;
00428     }
00429     else if ( xdat[0] > parlist[1] )
00430     {
00431         return_value = parlist[3] ;
00432     }
00433     
00434     return return_value ;
00435 }
00436        
00437 
00464 void 
00465 sinfo_new_edge_deriv( float * xdat, float * parlist, 
00466                       float * dervs/*, int * npar*/ )
00467 {
00468     float deriv1_slope1 ;
00469 
00470     /* compute the slopes */
00471     deriv1_slope1 =( parlist[3] - parlist[2] ) / SQR(parlist[1] - parlist[0]) ;
00472 
00473     /* now build the hat derivatives out of the parameters */
00474     if ( xdat[0] <= parlist[0] )
00475     {
00476         dervs[0] = 0. ;
00477         dervs[1] = 0. ;
00478         dervs[2] = 1. ;
00479         dervs[3] = 0. ;
00480     }
00481     else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
00482     {
00483         dervs[0] = ( xdat[0] - parlist[1] ) * deriv1_slope1  ;
00484         dervs[1] = ( parlist[0] - xdat[0] ) * deriv1_slope1 ;
00485         dervs[2] = ( parlist[0] - xdat[0] ) / ( parlist[1] - parlist[0] ) + 1.;
00486         dervs[3] = ( xdat[0] - parlist[0] ) / ( parlist[1] - parlist[0] ) ;
00487     }
00488     else if ( xdat[0] > parlist[1] )
00489     {
00490         dervs[0] = 0. ;
00491         dervs[1] = 0. ;
00492         dervs[2] = 0. ;
00493         dervs[3] = 1. ;
00494     }
00495 }
00530 void 
00531 sinfo_new_hat_deriv2(float * xdat, float * parlist, 
00532                      float * dervs/*, int * npar*/ )
00533 {
00534     float deriv1_slope1 ;
00535     float deriv1_slope2 ;
00536     float deriv1_slope3 ;
00537 
00538     /* compute the slopes */
00539     deriv1_slope1 = ( parlist[6] - parlist[4] ) / SQR(parlist[1] - parlist[0]);
00540     deriv1_slope2 = ( parlist[7] - parlist[5] ) / SQR(parlist[3] - parlist[2]);
00541     deriv1_slope3 = ( parlist[7] - parlist[6] ) / SQR(parlist[2] - parlist[1]);
00542 
00543     /* now build the hat derivatives out of the parameters */
00544     if ( xdat[0] <= parlist[0] )
00545     {
00546         dervs[0] = 0. ;
00547         dervs[1] = 0. ;
00548         dervs[2] = 0. ;
00549         dervs[3] = 0. ;
00550         dervs[4] = 1. ;
00551         dervs[5] = 0. ;
00552         dervs[6] = 0. ;
00553         dervs[7] = 0. ;
00554     }
00555     else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[1] )
00556     {
00557         dervs[0] = ( xdat[0] - parlist[1] ) * deriv1_slope1  ;
00558         dervs[1] = ( parlist[0] - xdat[0] ) * deriv1_slope1 ;
00559         dervs[2] = 0. ;
00560         dervs[3] = 0. ;
00561         dervs[4] = ( parlist[0] - xdat[0] ) / ( parlist[1] - parlist[0] ) + 1.;
00562         dervs[5] = 0. ;
00563         dervs[6] = ( xdat[0] - parlist[0] ) / ( parlist[1] - parlist[0] ) ;
00564         dervs[7] = 0. ;
00565     }
00566     else if ( xdat[0] > parlist[1] && xdat[0] <= parlist[2] )
00567     {
00568         dervs[0] = 0. ;
00569         dervs[1] = (xdat[0] - parlist[2]) * deriv1_slope3 ;
00570         dervs[2] = (parlist[1] - xdat[0]) * deriv1_slope3 ;
00571         dervs[3] = 0. ;
00572         dervs[4] = 0. ;
00573         dervs[5] = 0. ;
00574         dervs[6] = (parlist[1] - xdat[0]) / (parlist[2] - parlist[1]) + 1. ;
00575         dervs[7] = (xdat[0] - parlist[1]) / (parlist[2] - parlist[1]) ;
00576     }
00577     else if ( xdat[0] > parlist[2] && xdat[0] <= parlist[3] )
00578     {
00579         dervs[0] = 0. ;
00580         dervs[1] = 0. ;
00581         dervs[2] = ( parlist[3] - xdat[0] ) * deriv1_slope2 ;
00582         dervs[3] = ( xdat[0] - parlist[2] ) * deriv1_slope2 ;
00583         dervs[4] = 0. ; 
00584         dervs[5] = ( xdat[0] - parlist[3] ) / ( parlist[3] - parlist[2] ) + 1.;
00585         dervs[6] = 0. ;
00586         dervs[7] = ( parlist[3] - xdat[0] ) / ( parlist[3] - parlist[2] ) ;
00587     }
00588     else if ( xdat[0] > parlist[3] )
00589     {
00590         dervs[0] = 0. ;
00591         dervs[1] = 0. ;
00592         dervs[2] = 0. ;
00593         dervs[3] = 0. ;
00594         dervs[4] = 0. ;
00595         dervs[5] = 1. ;
00596         dervs[6] = 0. ;
00597         dervs[7] = 0. ;
00598     }
00599 }
00600 
00629 void 
00630 sinfo_new_hat_deriv1( float * xdat, float * parlist, 
00631                       float * dervs/*, int * npar*/ )
00632 {
00633     /* now build the hat derivatives out of the parameters */
00634     if ( xdat[0] <= parlist[0] )
00635     {
00636         dervs[0] = 0. ;
00637         dervs[1] = 0. ;
00638         dervs[2] = 1. ;
00639         dervs[3] = 0. ;
00640         dervs[4] = 0. ;
00641     }
00642     else if ( xdat[0] > parlist[0] && xdat[0] <= parlist[0] + slopewidth )
00643     {
00644         dervs[0] = ( parlist[2] - parlist[4] ) / slopewidth ;
00645         dervs[1] = 0. ;
00646         dervs[2] = (( parlist[0] - xdat[0] ) / slopewidth ) + 1. ;
00647         dervs[3] = 0. ;
00648         dervs[4] = ( xdat[0] - parlist[0] ) / slopewidth ;
00649     }
00650     else if ( xdat[0] > parlist[0] + slopewidth && xdat[0] <= 
00651               parlist[1] - slopewidth )
00652     {
00653         dervs[0] = 0. ;
00654         dervs[1] = 0. ;
00655         dervs[2] = 0. ;
00656         dervs[3] = 0. ;
00657         dervs[4] = 1. ;
00658     }
00659     else if ( xdat[0] > parlist[1] - slopewidth && xdat[0] <= parlist[1] )
00660     {
00661         dervs[0] = 0. ;
00662         dervs[1] = ( parlist[4] - parlist[3] ) / slopewidth ;
00663         dervs[2] = 0. ;
00664         dervs[3] = (( xdat[0] - parlist[1] ) / slopewidth ) + 1. ;
00665         dervs[4] = ( parlist[1] - xdat[0] ) / slopewidth ; 
00666     }
00667     else if ( xdat[0] > parlist[1] )
00668     {
00669         dervs[0] = 0. ;
00670         dervs[1] = 0. ;
00671         dervs[2] = 0. ;
00672         dervs[3] = 1. ;
00673         dervs[4] = 0. ;
00674     }
00675 }
00676    
00688 static int 
00689 sinfo_new_inv_mat_edge (void)
00690 {
00691     double even ;
00692     double hv[NPAR] ;
00693     double mjk ;
00694     double rowmax ;
00695     int evin ;
00696     int i, j, k, row ;
00697     int per[NPAR] ;
00698    
00699     /* set permutation array */
00700     for ( i = 0 ; i < nfree ; i++ )
00701     {
00702         per[i] = i ;
00703     }
00704     
00705     for ( j = 0 ; j < nfree ; j++ ) /* in j-th column */
00706     {
00707         /* determine largest element of a row */                           
00708         rowmax = fabs ( matrix2[j][j] ) ;
00709         row = j ;                         
00710 
00711         for ( i = j + 1 ; i < nfree ; i++ )
00712         {
00713             if ( fabs ( matrix2[i][j] ) > rowmax )
00714             {
00715                 rowmax = fabs( matrix2[i][j] ) ;
00716                 row = i ;
00717             }
00718         }
00719 
00720         /* determinant is zero! */
00721         if ( matrix2[row][j] == 0.0 )
00722         {
00723             return -6 ;
00724         }
00725         
00726         /* if the largest element is not on the diagonal, then permutate rows */
00727         if ( row > j )
00728         {
00729             for ( k = 0 ; k < nfree ; k++ )
00730             {
00731                 even = matrix2[j][k] ;
00732                 matrix2[j][k] = matrix2[row][k] ;
00733                 matrix2[row][k] = even ;
00734             }
00735             /* keep track of permutation */
00736             evin = per[j] ;
00737             per[j] = per[row] ;
00738             per[row] = evin ;
00739         }
00740         
00741         /* modify column */
00742         even = 1.0 / matrix2[j][j] ;
00743         for ( i = 0 ; i < nfree ; i++ )
00744         {
00745             matrix2[i][j] *= even ;
00746         }
00747         matrix2[j][j] = even ;
00748         
00749         for ( k = 0 ; k < j ; k++ )
00750         {
00751             mjk = matrix2[j][k] ;
00752             for ( i = 0 ; i < j ; i++ )
00753             {
00754                 matrix2[i][k] -= matrix2[i][j] * mjk ;
00755             }
00756             for ( i = j + 1 ; i < nfree ; i++ )
00757             {
00758                 matrix2[i][k] -= matrix2[i][j] * mjk ;
00759             }
00760             matrix2[j][k] = -even * mjk ;
00761         }
00762     
00763         for ( k = j + 1 ; k < nfree ; k++ )
00764         {
00765             mjk = matrix2[j][k] ;
00766             for ( i = 0 ; i < j ; i++ )
00767             {
00768                 matrix2[i][k]  -= matrix2[i][j] * mjk ;
00769             }
00770             for ( i = j + 1 ; i < nfree ; i++ )
00771             {
00772                 matrix2[i][k]  -= matrix2[i][j] * mjk ;
00773             }
00774             matrix2[j][k] = -even * mjk ;
00775         }
00776     }
00777     
00778     /* finally, repermute the columns */
00779     for ( i = 0 ; i < nfree ; i++ )
00780     {
00781         for ( k = 0 ; k < nfree ; k++ )
00782         {
00783             hv[per[k]] = matrix2[i][k] ;
00784         }
00785         for ( k = 0 ; k < nfree ; k++ )
00786         {
00787             matrix2[i][k] = hv[k] ;
00788         }
00789     }
00790         
00791     /* all is well */
00792     return 0 ;
00793 }
00794     
00813 static void 
00814 sinfo_new_get_mat_edge ( float * xdat,
00815                            int   * xdim,
00816                            float * ydat,
00817                            float * wdat,
00818                            int   * ndat,
00819                            float * fpar,
00820                            float * epar/*,
00821                            int   * npar*/ )
00822 {
00823     double wd ;
00824     double wn ;
00825     double yd ;
00826     int i, j, n ;
00827 
00828     for ( j = 0 ; j < nfree ; j++ )
00829     {
00830         vec[j] = 0.0 ; /* zero sinfo_vector */
00831         for ( i = 0 ; i<= j ; i++ )   /* zero matrix only on and 
00832                                          below diagonal */
00833         {
00834             matrix1[j][i] = 0.0 ;
00835         }
00836     }
00837     chi2 = 0.0 ;  /* reset reduced chi-squared */
00838     
00839     /* loop through data points */
00840     for ( n = 0 ; n < (*ndat) ; n++ )
00841     {
00842         wn = wdat[n] ;
00843         if ( wn > 0.0 )  /* legal weight ? */
00844         {
00845             yd = ydat[n] - sinfo_new_edge( &xdat[(*xdim) * n], 
00846                                            fpar/*, npar, ndat*/ ) ;
00847             sinfo_new_edge_deriv( &xdat[(*xdim) * n], fpar, epar/*, npar */) ;
00848             chi2 += yd * yd * wn ; /* add to chi-squared */
00849             for ( j = 0 ; j < nfree ; j++ )
00850             {
00851                 wd = epar[parptr[j]] * wn ;  /* weighted derivative */
00852                 vec[j] += yd * wd ;       /* fill sinfo_vector */
00853                 for ( i = 0 ; i <= j ; i++ ) /* fill sinfo_matrix */
00854                 {
00855                     matrix1[j][i] += epar[parptr[i]] * wd ;
00856                 }
00857             }
00858         }
00859     }                   
00860 }  
00861                 
00862             
00863 
00893 static int 
00894 sinfo_new_get_vec_edge ( float * xdat,
00895                           int   * xdim,
00896                           float * ydat,
00897                           float * wdat,
00898                           int   * ndat,
00899                           float * fpar,
00900                           float * epar,
00901                           int   * npar )
00902 {
00903     double dj ;
00904     double dy ;
00905     double mii ;
00906     double mji ;
00907     double mjj ;
00908     double wn ;
00909     int i, j, n, r ;
00910 
00911     /* loop to modify and scale the sinfo_matrix */
00912     for ( j = 0 ; j < nfree ; j++ )
00913     {
00914         mjj = matrix1[j][j] ;
00915         if ( mjj <= 0.0 )             /* diagonal element wrong */
00916         {
00917             return -5 ;
00918         }
00919         mjj = sqrt( mjj ) ;
00920         for ( i = 0 ; i < j ; i++ )
00921         {
00922             mji = matrix1[j][i] / mjj / sqrt( matrix1[i][i] ) ;
00923             matrix2[i][j] = matrix2[j][i] = mji ;
00924         }
00925         matrix2[j][j] = 1.0 + labda ;  /* scaled value on diagonal */
00926     }    
00927     
00928     if ( (r = sinfo_new_inv_mat_edge()) ) /* sinfo_invert sinfo_matrix inlace */
00929     {
00930         return r ;
00931     }
00932     
00933     for ( i = 0 ; i < (*npar) ; i ++ )
00934     {
00935         epar[i] = fpar[i] ;
00936     }
00937     
00938     /* loop to calculate correction sinfo_vector */
00939     for ( j = 0 ; j < nfree ; j++ )
00940     {
00941         dj = 0.0 ;
00942         mjj = matrix1[j][j] ;
00943         if ( mjj <= 0.0)               /* not allowed */
00944         {
00945             return -7 ;
00946         }
00947         mjj = sqrt ( mjj ) ;
00948         for ( i = 0 ; i < nfree ; i++ )
00949         {
00950             mii = matrix1[i][i] ;
00951             if ( mii <= 0.0 )
00952             {
00953                 return -7 ;
00954             }
00955             mii = sqrt( mii ) ;
00956             dj += vec[i] * matrix2[j][i] / mjj / mii ;
00957         }
00958         epar[parptr[j]] += dj ;       /* new parameters */
00959     }    
00960     chi1 = 0.0 ;                      /* reset reduced chi-squared */
00961  
00962     /* loop through the data points */
00963     for ( n = 0 ; n < (*ndat) ; n++ )
00964     {
00965         wn = wdat[n] ;               /* get weight */
00966         if ( wn > 0.0 )              /* legal weight */
00967         {
00968             dy = ydat[n] - sinfo_new_edge( &xdat[(*xdim) * n], epar
00969                                                 /*, npar, ndat*/) ;
00970             chi1 += wdat[n] * dy * dy ;
00971         }
00972     }
00973     return 0 ;
00974 }   
00975     
00976         
01030 int 
01031 sinfo_new_lsqfit_edge ( float * xdat,
01032                   int   * xdim,
01033                   float * ydat,
01034                   float * wdat,
01035                   int   * ndat,
01036                   float * fpar,
01037                   float * epar,
01038                   int   * mpar,
01039                   int   * npar,
01040                   float * tol ,
01041                   int   * its ,
01042                   float * lab  )
01043 {
01044     int i, n, r ;
01045     int itc ;                      /* fate of fit */
01046     int found ;                    /* fit converged: 1, not yet converged: 0 */
01047     int  nuse ;                    /* number of useable data points */
01048     double tolerance ;             /* accuracy */
01049 
01050     itc   = 0 ;                    /* fate of fit */
01051     found = 0 ;                    /* reset */
01052     nfree = 0 ;                    /* number of free parameters */
01053     nuse  = 0 ;                    /* number of legal data points */
01054 
01055     if ( *tol < (FLT_EPSILON * 10.0 ) )
01056     {
01057         tolerance = FLT_EPSILON * 10.0 ;  /* default tolerance */
01058     }
01059     else
01060     {
01061         tolerance = *tol ;                /* tolerance */
01062     }
01063     
01064     labda = fabs( *lab ) * LABFACA ;      /* start value for mixing parameter */
01065     for ( i = 0 ; i < (*npar) ; i++ )
01066     {
01067         if ( mpar[i] )
01068         {
01069             if ( nfree > NPAR )         /* too many free parameters */
01070             {
01071                 return -1 ;
01072             }
01073             parptr[nfree++] = i ;         /* a free parameter */
01074         }
01075     }
01076     
01077     if (nfree == 0)                       /* no free parameters */     
01078     {
01079         return -2 ;
01080     }
01081     
01082     for ( n = 0 ; n < (*ndat) ; n++ )
01083     {
01084         if ( wdat[n] > 0.0 )              /* legal weight */
01085         {
01086             nuse ++ ;
01087         }
01088     }
01089     
01090     if ( nfree >= nuse )
01091     {
01092         return -3 ;                       /* no degrees of freedom */
01093     }
01094     if ( labda == 0.0 )                   /* linear fit */
01095     {
01096         /* initialize fpar array */
01097         for ( i = 0 ; i < nfree ; fpar[parptr[i++]] = 0.0 ) ; 
01098         sinfo_new_get_mat_edge(xdat,xdim,ydat,wdat,ndat,fpar,epar/*, npar */) ;
01099         r =  sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat, ndat, 
01100                                       fpar, epar, npar ) ;
01101         if ( r )                         /* error */
01102         {
01103             return r ;
01104         }
01105         for ( i = 0 ; i < (*npar) ; i++ )
01106         {
01107             fpar[i] = epar[i] ;           /* save new parameters */
01108             epar[i] = 0.0 ;               /* and set errors to zero */
01109         }
01110         chi1 = sqrt( chi1 / (double) (nuse - nfree) ) ;
01111         for ( i = 0 ; i < nfree ; i++ )
01112         {
01113             if ( (matrix1[i][i] <= 0.0 ) || (matrix2[i][i] <= 0.0) )
01114             {
01115                 return -7 ;
01116             }
01117             epar[parptr[i]] = chi1 * sqrt( matrix2[i][i] ) / 
01118                                      sqrt( matrix1[i][i] ) ;
01119         }
01120     }
01121     else                                  /* non-linear fit */
01122     {
01123         /*----------------------------------------------------------------
01124          * the non-linear fit uses the steepest descent method in combination
01125          * with the Taylor method. The mixing of these methods is controlled
01126          * by labda. In the outer loop ( called the iteration loop ) we build
01127          * the sinfo_matrix and calculate the correction sinfo_vector. In the 
01128          * inner loop
01129          * (called the interpolation loop) we check whether we have obtained a
01130          * better solution than the previous one. If so, we leave the inner loop
01131          * else we increase labda ( give more weight to the steepest descent 
01132          * method) calculate the correction sinfo_vector and check again. 
01133          * After the inner loop
01134          * we do a final check on the goodness of the fit and if this satisfies
01135          * the tolerance we calculate the errors of the fitted parameters.
01136          */
01137         while ( !found )                  /* iteration loop */
01138         {      
01139             if ( itc++ == (*its) )        /* increase iteration counter */
01140             {
01141                 return -4 ;               
01142             }
01143             sinfo_new_get_mat_edge( xdat, xdim, ydat, wdat, ndat, 
01144                                     fpar, epar/*, npar*/ ) ;
01145             
01146             /*-------------------------------------------------------------
01147              * here we decrease labda since we may assume that each iteration
01148              * brings us closer to the answer.
01149              */
01150             if ( labda > LABMINA )
01151             {
01152                 labda = labda / LABFACA ;         /* decrease labda */
01153             }
01154             r = sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat, ndat, 
01155                                          fpar, epar, npar ) ;
01156             if ( (int)fpar[1] - (int)fpar[0] <= 0 && fpar[1] / fpar[0] > 0. )
01157             {
01158                 fpar[1] += 1. ;
01159                 continue ;
01160             } 
01161             if ( r )                      /* error */
01162             {
01163                 return r ;
01164             }
01165 
01166             while ( chi1 >= chi2 )        /* interpolation loop */
01167             {
01168                 /*-----------------------------------------------------------
01169                  * The next statement is based on experience, not on the 
01170                  * mathematics of the problem. It is assumed that we have 
01171                  * reached convergence when the pure steepest descent method 
01172                  * does not produce a better solution.
01173                  */
01174                 if ( labda > LABMAXA )    /* assume solution found */
01175                 {
01176                     break ;
01177                 }
01178                 labda = labda * LABFACA ;   /* increase mixing parameter */
01179                 r = sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat, 
01180                                              ndat, fpar, epar, npar ) ;
01181                 if ( (int)fpar[1] - (int)fpar[0] <= 0 && 
01182                      fpar[1] / fpar[0] > 0. )
01183                 {
01184                     fpar[1] += 1. ;
01185                     continue ;
01186                 } 
01187                 if ( r )                  /* error */
01188                 {
01189                     return r ;
01190                 }
01191             }
01192 
01193             if ( labda <= LABMAXA )        /* save old parameters */
01194             {
01195                 for ( i = 0 ; i < *npar ; i++ )
01196                 {
01197                     fpar[i] = epar[i] ;
01198                 }
01199             }
01200             if ( (fabs( chi2 - chi1 ) <= (tolerance * chi1)) || 
01201                   (labda > LABMAXA) )
01202             {
01203                 /*------------------------------------------------------------
01204                  * we have a satisfying solution, so now we need to calculate 
01205                  * the correct errors of the fitted parameters. This we do by 
01206                  * using the pure Taylor method because we are very close to 
01207                  * the real solution.
01208                  */
01209                 labda = LABMINA ;              /* for Taylor solution */
01210                 sinfo_new_get_mat_edge ( xdat, xdim, ydat, wdat, ndat, 
01211                                          fpar, epar/*, npar */) ;
01212                 r = sinfo_new_get_vec_edge ( xdat, xdim, ydat, wdat, 
01213                                              ndat, fpar, epar, npar ) ;
01214 
01215                 if ( r )                    /* error */
01216                 {
01217                     return r ;
01218                 }
01219                 for ( i = 0 ; i < (*npar) ; i++ )
01220                 {
01221                     epar[i] = 0.0 ;          /* set error to zero */
01222                 }
01223                 chi2 = sqrt ( chi2 / (double) (nuse - nfree) ) ;
01224 
01225                 for ( i = 0 ; i < nfree ; i++ )
01226                 {
01227                     if ( (matrix1[i][i] <= 0.0) || (matrix2[i][i] <= 0.0) )
01228                     {
01229                         return -7 ;
01230                     }
01231                     epar[parptr[i]] = chi2 * sqrt( matrix2[i][i] ) / 
01232                                              sqrt( matrix1[i][i] ) ;
01233                 }
01234                 found = 1 ;                  /* we found a solution */
01235             }
01236         }
01237     }
01238     return itc ;                             /* return number of iterations */
01239 }
01268 int 
01269 sinfo_new_fit_slits1( cpl_image   * lineImage, 
01270                FitParams ** par,
01271                float     ** sinfo_slit_pos,
01272                int          box_length,
01273                float        y_box )
01274 {
01275     float* position=NULL ;
01276     int   * sinfo_edge, * edgeclean ;
01277     int   * dummyedge ;
01278     int   * pos_row, * pos_rowclean ;
01279     Vector * box_buffer ;
01280     float max_intensity ;
01281     float row_pos ;
01282     int   col ;
01283     int   i, j, k, m, n, ed ;
01284     int   found, init1, init2 ;
01285     int   line ; 
01286     int   column ;
01287     int   slit_length ;
01288     int   agreed ;
01289     int   bad_line ;
01290     int   margin ;
01291     int   iters, xdim, ndat ;
01292     int   numpar, its ;
01293     int   * mpar ;
01294     float * xdat, * wdat ;
01295     float tol, lab ;
01296     float fitpar[NPAR] ;
01297     float dervpar[NPAR] ;
01298     float minval, maxval ;
01299     int ilx=0;
01300     int ily=0;
01301     float* pidata=NULL;
01302 
01303 
01304     if ( NULL == lineImage )
01305     {
01306         sinfo_msg_error("no line image given!" ) ;
01307         return -1 ;
01308     }
01309     ilx=cpl_image_get_size_x(lineImage);
01310     ily=cpl_image_get_size_y(lineImage);
01311     pidata=cpl_image_get_data_float(lineImage);
01312 
01313     slit_length = (int) sqrt (ilx) ;
01314     if ( NULL == par )
01315     {
01316         sinfo_msg_error("no line fit parameters given!") ;
01317         return -2 ;
01318     }
01319 
01320     if ( NULL == sinfo_slit_pos )
01321     {
01322         sinfo_msg_error("no position array allocated!") ;
01323         return -3 ;
01324     }
01325 
01326     if ( box_length <  slit_length ||
01327          box_length >= 3*slit_length )
01328     {
01329         sinfo_msg_error("wrong fitting box length given!" ) ;
01330         return -4 ;
01331     }
01332 
01333     if ( y_box <= 0.  || y_box > 3. )
01334     {
01335         sinfo_msg_error("wrong y box length given!" ) ;
01336         return -5 ;
01337     }
01338 
01339     /* allocate memory for the edges and the row positon of the slitlets */
01340     sinfo_edge         = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
01341     dummyedge    = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
01342     edgeclean    = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
01343     pos_row      = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
01344     pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
01345 
01346     /* ------------------------------------------------------------------------
01347      * go through the first image columns and the fit parameters and find 
01348      *  the line with the highest intensity 
01349      */
01350     agreed = -1 ;
01351     bad_line = -1 ;
01352     while( agreed == -1 )
01353     {
01354         found = -1 ;
01355         max_intensity = -FLT_MAX ;
01356         for ( col = 0 ; col < box_length ; col++ )
01357         {
01358             for ( i = 0 ; i < par[0]->n_params ; i++ )
01359             {
01360                 if ( par[i]->column == col && par[i]->line != bad_line )
01361                 {
01362                     if ( par[i]->fit_par[0] > max_intensity )
01363                     {
01364                         if ( par[i]->fit_par[1] > 0. )
01365                         {
01366                             max_intensity = par[i]->fit_par[0] ;
01367                             found = i ;
01368                         }
01369                     }
01370                 }
01371             }  
01372         }
01373 
01374         /* --------------------------------------------------------------------
01375          * check if the found line is usable and if the neighbouring line 
01376          * have intensity on near rows in neighbouring slitlets 
01377          */
01378         line    = par[found]->line ;
01379         column  = par[found]->column ;
01380         row_pos = par[found]->fit_par[2] ;
01381         if ( found >= 0 && max_intensity > 0. )
01382         {
01383             for ( i = 0 ; i < par[0]->n_params ; i++ )
01384             {
01385                 if ( par[i]->line == line-1 && 
01386                      par[i]->column == column + slit_length )
01387                 {
01388                     if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
01389                          par[i]->fit_par[2] >= (row_pos - y_box) )
01390                     {
01391                         bad_line = line ;
01392                     } 
01393                 }
01394             }
01395             if ( bad_line != line )
01396             {
01397                 agreed = 1 ;
01398                 break ;
01399             }
01400         }
01401         else 
01402         {
01403           sinfo_msg_error("no emission line found in the first image columns");
01404           return -6 ;
01405         }    
01406     }
01407 
01408  
01409     if ( agreed == -1 )
01410     {
01411         sinfo_msg_error("no emission line found in the first image columns") ;
01412         return -6 ;
01413     }    
01414  
01415     /* now find and store the raw sinfo_edge positions of the found slitlet */ 
01416     n  = 0 ;
01417     ed = 0 ;
01418   
01419 
01420     position=cpl_calloc(ilx,sizeof(float));
01421     for ( col = 0 ; col < ilx ; col++ )
01422     {
01423         for ( i = 0 ; i < par[0]->n_params ; i++ )
01424         {
01425             if ( par[i]->column == col && par[i] -> line == line )
01426             {
01427                 if ( par[i]->fit_par[0] > 0. && par[i]->fit_par[1] > 0. )
01428                 {
01429                     position[n] = par[i]->fit_par[2] ;
01430                     if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
01431                     {
01432                         sinfo_edge[ed] = col ; 
01433                         pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
01434                         ed++ ;
01435                         if ( col >= ilx - slit_length - 5 ) 
01436                         {
01437                             pos_row[ed] =  sinfo_new_nint( position[n] ) ;
01438                         }
01439                     }
01440                     n++ ;
01441                 }
01442             }
01443         }
01444     }
01445     if ( ed < (slit_length - 1) )
01446     {
01447         sinfo_msg_error("not enough slitlets found") ;
01448         return -7 ;
01449     } 
01450 
01451     /* now find the clean sinfo_edge and row positions of the slitlets */
01452     for ( i = 1 ; i <= ed ; i ++ )
01453     {
01454         if (dummyedge[i-1] != -1)
01455         {
01456             dummyedge[i-1] = sinfo_edge[i-1] ;
01457         }
01458         if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
01459              (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
01460         {
01461             dummyedge[i]   = -1 ;
01462         }
01463         if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
01464              (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
01465         {
01466             dummyedge[i+1] = -1 ; 
01467         }
01468     }
01469     
01470     k = 0 ;
01471     for ( i = 0 ; i < ed ; i++ )
01472     {
01473         if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
01474         {
01475             edgeclean[k] = dummyedge[i] ;
01476             pos_rowclean[k] = pos_row[i] ;
01477             k++ ;
01478             if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
01479             {
01480                 pos_rowclean[k] = pos_row[ed] ;
01481             }
01482         }
01483     }
01484 
01485     if ( k != slit_length - 1 )
01486     {
01487         sinfo_msg_error("not enough clean slitlets found") ;
01488         return -7 ;
01489     } 
01490 
01491     /* determine the margins of the fitting box outside the slitlets */
01492     margin = ( box_length - slit_length ) / 2 ;
01493 
01494     /* now go through the slitlets and store the intensity in a 
01495        buffer sinfo_vector */
01496     for ( j = 0 ; j < k ; j++ )
01497     {
01498         m = 0 ;
01499         if ( j == 0 )
01500         {
01501             box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
01502             for( col = 0 ; col < edgeclean[0] + margin ; col++ )
01503             {
01504                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[0]] ;
01505                 m++ ;
01506             }
01507             fitpar[0] = 3. ;
01508             fitpar[1] = 5. ;
01509             fitpar[2] = (float) edgeclean[0] - 1. ;
01510             fitpar[3] = (float) edgeclean[0] + 1. ;
01511           
01512         }
01513         else if ( j < k - 1 )
01514         {
01515             box_buffer = sinfo_new_vector( edgeclean[j] - 
01516                                            edgeclean[j-1] + 2*margin ) ;
01517             for ( col = edgeclean[j - 1] - margin ; 
01518                   col < edgeclean[j] + margin ; col++ )
01519             {
01520                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[j]] ;
01521                 m++ ;
01522             }
01523             fitpar[0] = (float) margin - 1. ;
01524             fitpar[1] = (float) margin + 1. ;
01525             fitpar[2] = (float) (edgeclean[j] - edgeclean[j-1] + margin) - 1. ;
01526             fitpar[3] = (float) (edgeclean[j] - edgeclean[j-1] + margin) + 1. ;
01527         }
01528         /*else if ( j == k - 1 )*/
01529         else
01530         {
01531             box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
01532             for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
01533             {
01534                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[k]] ;
01535                 m++ ;
01536             }
01537             fitpar[0] = (float) margin - 1. ;
01538             fitpar[1] = (float) margin + 1. ;
01539             fitpar[2] = (float) (ilx - edgeclean[k-1] + margin) - 3. ;
01540             fitpar[3] = (float) (ilx - edgeclean[k-1] + margin) - 1. ;
01541         }
01542 
01543         xdat = (float *) cpl_calloc(box_buffer -> n_elements,sizeof (float) ) ;
01544         wdat = (float *) cpl_calloc(box_buffer -> n_elements,sizeof (float) ) ;
01545         mpar = (int *)   cpl_calloc(NPAR, sizeof (int) ) ;
01546 
01547         /* set initial values for the fitting routine */
01548         minval =  FLT_MAX ;
01549         maxval = -FLT_MAX ;
01550         for ( i = 0 ; i < box_buffer->n_elements ; i++ )
01551         {
01552             xdat[i] = i ;
01553             wdat[i] = 1.0 ;
01554             if ( box_buffer -> data[i] < minval )
01555             {
01556                 minval = box_buffer -> data[i] ;
01557             }
01558             if ( box_buffer -> data[i] > maxval )
01559             {
01560                 maxval = box_buffer -> data[i] ;
01561             }
01562         }
01563 
01564         fitpar[4] = minval ;
01565         fitpar[5] = minval ;
01566         fitpar[6] = maxval ; 
01567         fitpar[7] = maxval ;
01568 
01569         /* search for both positions of the half intensity of the 
01570            hat within the buffer */
01571         init1 = -1 ; 
01572         init2 = -1 ;
01573         for ( i = 0 ; i < box_buffer->n_elements ; i++ )
01574         {
01575             if ( box_buffer -> data[i] >= ( maxval - minval ) / 2. )
01576             {
01577                 init1 = i ;
01578                 break ;
01579             }
01580         }
01581 
01582         for ( i = box_buffer->n_elements - 1 ; i >= 0  ; i-- )
01583         {
01584             if ( box_buffer -> data[i] >= ( maxval + minval ) / 2. )
01585             {
01586                 init2 = i ;
01587                 break ;
01588             }
01589         }
01590   
01591         /* determine the initial positions from the found values */
01592       /*  if ( init1 != -1 )
01593         {
01594             fitpar[0] = init1 - 1. ;
01595             fitpar[1] = init1 + 1. ;
01596         }
01597         if ( init2 != -1 )
01598         {
01599             fitpar[2] = init2 - 1. ;
01600             fitpar[3] = init2 + 1. ;
01601         } */
01602 
01603         for ( i = 0 ; i < NPAR ; i++ )
01604         {
01605             mpar[i] = 1 ;
01606             dervpar[i] = 0. ;
01607         }
01608      
01609         xdim     = XDIMA ;
01610         ndat     = box_buffer -> n_elements ;
01611         numpar   = NPAR ;
01612         tol      = TOLA ;
01613         lab      = LABA ;
01614         its      = ITSA ;
01615         
01616         /* finally, do the least squares fit over the buffer data */
01617         if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim, 
01618                                                   box_buffer -> data, 
01619                                                   wdat, &ndat, fitpar,
01620                                                   dervpar, mpar, 
01621                                                   &numpar, &tol, 
01622                                                   &its, &lab )) )
01623         {
01624             sinfo_msg_warning("least squares fit failed, error no.: %d", 
01625                   iters) ;
01626             return -8 ;
01627         }
01628 
01629 
01630         /* take care of the column position of the fit boxes to get 
01631            the absolute positions */
01632         if ( j == 0 )
01633         {
01634             sinfo_slit_pos[0][0] = (fitpar[0] + fitpar[1]) / 2. ;
01635             sinfo_slit_pos[0][1] = (fitpar[2] + fitpar[3]) / 2. ;
01636         }
01637         else
01638         {
01639             sinfo_slit_pos[j][0] = (fitpar[0] + fitpar[1]) / 2. + 
01640                                    (float)edgeclean[j-1] - (float)margin ;
01641             sinfo_slit_pos[j][1] = (fitpar[2] + fitpar[3]) / 2. + 
01642                                    (float)edgeclean[j-1] - (float)margin ;
01643         }
01644      
01645         sinfo_slit_pos[k][0] = (fitpar[0] + fitpar[1]) / 2.  + 
01646                                (float)edgeclean[k-1] - (float)margin ;
01647         sinfo_slit_pos[k][1] = (fitpar[2] + fitpar[3]) / 2. + 
01648                                (float)edgeclean[k-1] - (float)margin ;
01649 
01650         sinfo_new_destroy_vector ( box_buffer ) ;
01651         cpl_free( xdat ) ;
01652         cpl_free( wdat ) ;
01653         cpl_free( mpar ) ;
01654     }
01655         
01656     cpl_free( sinfo_edge ) ;
01657     cpl_free( pos_row ) ;
01658     cpl_free( edgeclean ) ;
01659     cpl_free( dummyedge ) ;
01660     cpl_free( pos_rowclean ) ;
01661     cpl_free( position );
01662 
01663     return 0 ;
01664 }
01665                               
01697 int 
01698 sinfo_new_fit_slits( cpl_image   * lineImage, 
01699               FitParams ** par,
01700               float     ** sinfo_slit_pos,
01701               int          box_length,
01702               float        y_box,
01703               float        slope_width )
01704 {
01705     float* position=NULL ;
01706 
01707     int   * sinfo_edge, * edgeclean ;
01708     int   * dummyedge ;
01709     int   * pos_row, * pos_rowclean ;
01710     Vector * box_buffer ;
01711     float max_intensity ;
01712     float row_pos ;
01713     int   col ;
01714     int   i, j, k, m, n, ed ;
01715     int   found ;
01716     int   line ; 
01717     int   column ;
01718     int   slit_length ;
01719     int   agreed ;
01720     int   bad_line ;
01721     int   margin ;
01722     int   iters, xdim, ndat ;
01723     int   numpar, its ;
01724     int   * mpar ;
01725     float * xdat, * wdat ;
01726     float tol, lab ;
01727     float fitpar[NPAR] ;
01728     float dervpar[NPAR] ;
01729     float minval, maxval ;
01730     int ilx=0;
01731     int ily=0;
01732     float* pidata=NULL;
01733 
01734 
01735     if ( NULL == lineImage )
01736     {
01737         sinfo_msg_error("no line image given!" ) ;
01738         return -1 ;
01739     }
01740     ilx=cpl_image_get_size_x(lineImage);
01741     ily=cpl_image_get_size_y(lineImage);
01742     pidata=cpl_image_get_data_float(lineImage);
01743 
01744     slit_length = (int) sqrt (ilx) ;
01745     if ( NULL == par )
01746     {
01747         sinfo_msg_error("no line fit parameters given!" ) ;
01748         return -2 ;
01749     }
01750 
01751     if ( NULL == sinfo_slit_pos )
01752     {
01753         sinfo_msg_error("no position array allocated!" ) ;
01754         return -3 ;
01755     }
01756 
01757     if ( box_length <  slit_length ||
01758          box_length >= 3*slit_length )
01759     {
01760         sinfo_msg_error("wrong fitting box length given!" ) ;
01761         return -4 ;
01762     }
01763 
01764     if ( y_box <= 0.  || y_box > 3. )
01765     {
01766         sinfo_msg_error("wrong y box length given!" ) ;
01767         return -5 ;
01768     }
01769 
01770     if ( slope_width <= 0. )
01771     {
01772         sinfo_msg_error("wrong width of linear slope given!") ;
01773         return -6 ;
01774     }
01775 
01776     /* initialize module global variable slopewidth */
01777     slopewidth = slope_width ;
01778 
01779     /* allocate memory for the edges and the row positon of the slitlets */
01780     sinfo_edge         = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
01781     dummyedge    = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
01782     edgeclean    = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
01783     pos_row      = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
01784     pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
01785 
01786     /* ------------------------------------------------------------------------
01787      * go through the first image columns and the fit parameters and find 
01788      * the line with the highest intensity 
01789      */
01790     agreed = -1 ;
01791     bad_line = -1 ;
01792     while( agreed == -1 )
01793     {
01794         found = -1 ;
01795         max_intensity = -FLT_MAX ;
01796         for ( col = 0 ; col < box_length ; col++ )
01797         {
01798             for ( i = 0 ; i < par[0]->n_params ; i++ )
01799             {
01800                 if ( par[i]->column == col && par[i]->line != bad_line )
01801                 {
01802                     if ( par[i]->fit_par[0] > max_intensity )
01803                     {
01804                         if ( par[i]->fit_par[1] > 0. )
01805                         {
01806                             max_intensity = par[i]->fit_par[0] ;
01807                             found = i ;
01808                         }
01809                     }
01810                 }
01811             }  
01812         }
01813 
01814         /* --------------------------------------------------------------------
01815          * check if the found line is usable and if the neighbouring line 
01816          * have intensity on near rows in neighbouring slitlets 
01817          */
01818         line    = par[found]->line ;
01819         column  = par[found]->column ;
01820         row_pos = par[found]->fit_par[2] ;
01821         if ( found >= 0 && max_intensity > 0. )
01822         {
01823             for ( i = 0 ; i < par[0]->n_params ; i++ )
01824             {
01825                 if ( par[i]->line == line-1 && 
01826                      par[i]->column == column + slit_length )
01827                 {
01828                     if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
01829                          par[i]->fit_par[2] >= (row_pos - y_box) )
01830                     {
01831                         bad_line = line ;
01832                     } 
01833                 }
01834             }
01835             if ( bad_line != line )
01836             {
01837                 agreed = 1 ;
01838                 break ;
01839             }
01840         }
01841         else 
01842         {
01843           sinfo_msg_error("no emission line found in the first image columns");
01844           return -7 ;
01845         }    
01846     }
01847 
01848  
01849     if ( agreed == -1 )
01850     {
01851         sinfo_msg_error("no emission line found in the first image columns") ;
01852         return -7 ;
01853     }    
01854  
01855     /* now find and store the raw sinfo_edge positions of the found slitlet */ 
01856     n  = 0 ;
01857     ed = 0 ;
01858     position=cpl_calloc(ilx,sizeof(float)) ;
01859 
01860     for ( col = 0 ; col < ilx ; col++ )
01861     {
01862         for ( i = 0 ; i < par[0]->n_params ; i++ )
01863         {
01864             if ( par[i]->column == col && par[i] -> line == line )
01865             {
01866                 if ( par[i]->fit_par[0] > 0. && par[i]->fit_par[1] > 0. )
01867                 {
01868                     position[n] = par[i]->fit_par[2] ;
01869                     if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
01870                     {
01871                         sinfo_edge[ed] = col ; 
01872                         pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
01873                         ed++ ;
01874                         if ( col >= ilx - slit_length - 5 ) 
01875                         {
01876                             pos_row[ed] =  sinfo_new_nint( position[n] ) ;
01877                         }
01878                     }
01879                     n++ ;
01880                 }
01881             }
01882         }
01883     }
01884     if ( ed < (slit_length - 1) )
01885     {
01886         sinfo_msg_error("not enough slitlets found") ;
01887         return -8 ;
01888     } 
01889 
01890     /* now find the clean sinfo_edge and row positions of the slitlets */
01891     for ( i = 1 ; i <= ed ; i ++ )
01892     {
01893         if (dummyedge[i-1] != -1)
01894         {
01895             dummyedge[i-1] = sinfo_edge[i-1] ;
01896         }
01897         if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
01898              (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
01899         {
01900             dummyedge[i]   = -1 ;
01901         }
01902         if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
01903              (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
01904         {
01905             dummyedge[i+1] = -1 ; 
01906         }
01907     }
01908     
01909     k = 0 ;
01910     for ( i = 0 ; i < ed ; i++ )
01911     {
01912         if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
01913         {
01914             edgeclean[k] = dummyedge[i] ;
01915             pos_rowclean[k] = pos_row[i] ;
01916             k++ ;
01917             if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
01918             {
01919                 pos_rowclean[k] = pos_row[ed] ;
01920             }
01921         }
01922     }
01923 
01924     if ( k != slit_length - 1 )
01925     {
01926         sinfo_msg_error ("not enough clean slitlets found") ;
01927         return -7 ;
01928     } 
01929 
01930     /* determine the margins of the fitting box outside the slitlets */
01931     margin = ( box_length - slit_length ) / 2 ;
01932 
01933     /* now go through the slitlets and store the intensity in a buffer 
01934        sinfo_vector */
01935     for ( j = 0 ; j < k ; j++ )
01936     {
01937         m = 0 ;
01938         if ( j == 0 )
01939         {
01940             box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
01941             for( col = 0 ; col < edgeclean[0] + margin ; col++ )
01942             {
01943                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[0]] ;
01944                 m++ ;
01945             }
01946             /* initial values for the fitted positions */
01947             fitpar[0] = 1. ;
01948             fitpar[1] = (float)edgeclean[0] ;
01949           
01950         }
01951         else if ( j < k - 1 )
01952         {
01953             box_buffer = sinfo_new_vector( edgeclean[j] - 
01954                                            edgeclean[j-1] + 2*margin ) ;
01955             for ( col = edgeclean[j - 1] - margin ; 
01956                   col < edgeclean[j] + margin ; col++ )
01957             {
01958                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[j]] ;
01959                 m++ ;
01960             }
01961             /* initial values for the fitted positions */
01962             fitpar[0] = (float)margin ;
01963             fitpar[1] = (float)(edgeclean[j] - edgeclean[j-1] + margin ) ;
01964         }
01965         /*else if ( j == k - 1 )*/
01966         else
01967         {
01968             box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
01969             for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
01970             {
01971                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[k]] ;
01972                 m++ ;
01973             }
01974             /* initial values for the fitted positions */
01975             fitpar[0] = (float)margin ;
01976             fitpar[1] = (float)(m - 1) ;
01977         }
01978 
01979         xdat=(float *) cpl_calloc( box_buffer -> n_elements, sizeof (float) ) ;
01980         wdat=(float *) cpl_calloc( box_buffer -> n_elements, sizeof (float) ) ;
01981         mpar=(int *)   cpl_calloc( NPAR, sizeof (int) ) ;
01982 
01983         /* set initial values for the fitting routine */
01984         minval =  FLT_MAX ;
01985         maxval = -FLT_MAX ;
01986         for ( i = 0 ; i < box_buffer->n_elements ; i++ )
01987         {
01988             xdat[i] = i ;
01989             wdat[i] = 1.0 ;
01990             if ( box_buffer -> data[i] < minval )
01991             {
01992                 minval = box_buffer -> data[i] ;
01993             }
01994             if ( box_buffer -> data[i] > maxval )
01995             {
01996                 maxval = box_buffer -> data[i] ;
01997             }
01998         }
01999 
02000         for ( i = 0 ; i < NPAR ; i++ )
02001         {
02002             mpar[i] = 1 ;
02003             dervpar[i] = 0. ;
02004         }
02005      
02006         xdim     = XDIMA ;
02007         ndat     = box_buffer -> n_elements ;
02008         numpar   = NPAR ;
02009         tol      = TOLA ;
02010         lab      = LABA ;
02011         its      = ITSA ;
02012         
02013         fitpar[2] = minval ;
02014         fitpar[3] = minval ;
02015         fitpar[4] = maxval ;
02016 
02017         /* finally, do the least squares fit over the buffer data */
02018         if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim, 
02019                                                   box_buffer -> data, 
02020                                                   wdat, &ndat, fitpar,
02021                                                   dervpar, mpar, &numpar, 
02022                                                   &tol, &its, &lab )) )
02023         {
02024             sinfo_msg_warning("least squares fit failed, error no.: %d", 
02025                   iters) ;
02026             return -9 ;
02027         }
02028 
02029 
02030         /* take care of the column position of the fit boxes 
02031            to get the absolute positions */
02032         if ( j == 0 )
02033         {
02034             sinfo_slit_pos[0][0] = fitpar[0] + slopewidth/2. ;
02035             sinfo_slit_pos[0][1] = fitpar[1] - slopewidth/2. ;
02036         }
02037         else
02038         {
02039             sinfo_slit_pos[j][0] = fitpar[0] + slopewidth/2. + 
02040                                    (float)edgeclean[j-1] - (float)margin ;
02041             sinfo_slit_pos[j][1] = fitpar[1] - slopewidth/2. + 
02042                                    (float)edgeclean[j-1] - (float)margin ;
02043         }
02044 
02045         sinfo_slit_pos[k][0] = fitpar[0] + slopewidth/2. + 
02046                                (float)edgeclean[k-1] - (float)margin ;
02047         sinfo_slit_pos[k][1] = fitpar[1] - slopewidth/2. + 
02048                                (float)edgeclean[k-1] - (float)margin ;
02049      
02050         sinfo_new_destroy_vector ( box_buffer ) ;
02051         cpl_free( xdat ) ;
02052         cpl_free( wdat ) ;
02053         cpl_free( mpar ) ;
02054     }
02055         
02056 
02057     cpl_free( sinfo_edge ) ;
02058     cpl_free( pos_row ) ;
02059     cpl_free( edgeclean ) ;
02060     cpl_free( dummyedge ) ;
02061     cpl_free( pos_rowclean ) ;
02062     cpl_free( position );
02063     return 0 ;
02064 }
02065                               
02110 int 
02111 sinfo_new_fit_slits2( cpl_image   * lineImage, 
02112                FitParams ** par,
02113                float     ** sinfo_slit_pos,
02114                int          box_length,
02115                float        y_box,
02116                float        diff_tol )
02117 {
02118     float* position=NULL ;
02119     int   * sinfo_edge, * edgeclean ;
02120     int   * dummyedge ;
02121     int   * pos_row, * pos_rowclean ;
02122     Vector * box_buffer ;
02123     Vector * half_buffer ;
02124     float max_intensity ;
02125     float row_pos ;
02126     int   col ;
02127     int   i, j, k, m, n, ed ;
02128     int   found, init1 ;
02129     int   line ; 
02130     int   nel, n_right, left_right ;
02131     int   column ;
02132     int   slit_length ;
02133     int   agreed ;
02134     int   bad_line ;
02135     int   margin ;
02136     int   iters, xdim, ndat ;
02137     int   numpar, its ;
02138     int   * mpar ;
02139     float * xdat, * wdat ;
02140     float tol, lab ;
02141     float fitpar[NPAR] ;
02142     float dervpar[NPAR] ;
02143     float minval, maxval ;
02144     float pos, last_pos ;
02145     int ilx=0;
02146     int ily=0;
02147     float* pidata=NULL;
02148 
02149 
02150     if ( NULL == lineImage )
02151     {
02152         sinfo_msg_error("no line image given!" ) ;
02153         return -1 ;
02154     }
02155     ilx=cpl_image_get_size_x(lineImage);
02156     ily=cpl_image_get_size_y(lineImage);
02157     pidata=cpl_image_get_data_float(lineImage);
02158 
02159     slit_length = (int) sqrt (ilx) ;
02160 
02161     if ( NULL == par )
02162     {
02163         sinfo_msg_error("no line fit parameters given!" ) ;
02164         return -2 ;
02165     }
02166 
02167     if ( NULL == sinfo_slit_pos )
02168     {
02169         sinfo_msg_error("no position array allocated!" ) ;
02170         return -3 ;
02171     }
02172 
02173     if ( box_length <  slit_length ||
02174          box_length >= 3*slit_length )
02175     {
02176         sinfo_msg_error("wrong fitting box length given!" ) ;
02177         return -4 ;
02178     }
02179 
02180     if ( y_box <= 0.  || y_box > 3. )
02181     {
02182         sinfo_msg_error("wrong y box length given!" ) ;
02183         return -5 ;
02184     }
02185 
02186     if ( diff_tol < 1. )
02187     {
02188         sinfo_msg_error("diff_tol too small!" ) ;
02189         return -6 ;
02190     }
02191 
02192     /* allocate memory for the edges and the row positon of the slitlets */
02193     sinfo_edge         = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
02194     dummyedge    = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
02195     edgeclean    = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
02196     pos_row      = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
02197     pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
02198 
02199     /* ------------------------------------------------------------------------
02200      * go through the first image columns and the fit parameters and find 
02201      * the line with the highest intensity 
02202      */
02203     agreed = -1 ;
02204     bad_line = -1 ;
02205     while( agreed == -1 )
02206     {
02207         found = -1 ;
02208         max_intensity = -FLT_MAX ;
02209         for ( col = 0 ; col < box_length ; col++ )
02210         {
02211             for ( i = 0 ; i < par[0]->n_params ; i++ )
02212             {
02213                 if ( par[i]->column == col && par[i]->line != bad_line )
02214                 {
02215                     if ( par[i]->fit_par[0] > max_intensity )
02216                     {
02217                         if ( par[i]->fit_par[1] > 0. )
02218                         {
02219                             max_intensity = par[i]->fit_par[0] ;
02220                             found = i ;
02221                         }
02222                     }
02223                 }
02224             }  
02225         }
02226 
02227         /* --------------------------------------------------------------------
02228          * check if the found line is usable and if the neighbouring line 
02229          * have intensity on near rows in neighbouring slitlets 
02230          */
02231         line    = par[found]->line ;
02232         column  = par[found]->column ;
02233         row_pos = par[found]->fit_par[2] ;
02234         if ( found >= 0 && max_intensity > 0. )
02235         {
02236             for ( i = 0 ; i < par[0]->n_params ; i++ )
02237             {
02238                 if ( par[i]->line == line-1 && 
02239                      par[i]->column == column + slit_length )
02240                 {
02241                     if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
02242                          par[i]->fit_par[2] >= (row_pos - y_box) )
02243                     {
02244                         bad_line = line ;
02245                     } 
02246                 }
02247             }
02248             if ( bad_line != line )
02249             {
02250                 agreed = 1 ;
02251                 break ;
02252             }
02253         }
02254         else 
02255         {
02256           sinfo_msg_error("no emission line found in the first image columns");
02257           return -7 ;
02258         }    
02259     }
02260 
02261  
02262     if ( agreed == -1 )
02263     {
02264         sinfo_msg_error("no emission line found in the first image columns") ;
02265         return -7 ;
02266     }    
02267  
02268     /* now find and store the raw sinfo_edge positions of the found slitlet */ 
02269     n  = 0 ;
02270     ed = 0 ;
02271     position=cpl_calloc(ilx,sizeof(float)) ;
02272 
02273     for ( col = 0 ; col < ilx ; col++ )
02274     {
02275         for ( i = 0 ; i < par[0]->n_params ; i++ )
02276         {
02277             if ( par[i]->column == col && par[i]->line == line )
02278             {
02279                 if ( par[i]->fit_par[0] > 0. && par[i]->fit_par[1] > 0. )
02280                 {
02281                     position[n] = par[i]->fit_par[2] ;
02282                     if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
02283                     {
02284                         sinfo_edge[ed] = col ; 
02285                         pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
02286                         ed++ ;
02287                         if ( col >= ilx - slit_length - 5 ) 
02288                         {
02289                             pos_row[ed] =  sinfo_new_nint( position[n] ) ;
02290                         }
02291                     }
02292                     n++ ;
02293                 }
02294             }
02295         }
02296     }
02297     if ( ed < (slit_length - 1) )
02298     {
02299         sinfo_msg_error("not enough slitlets found") ;
02300         return -8 ;
02301     } 
02302 
02303     /* now find the clean sinfo_edge and row positions of the slitlets */
02304     for ( i = 1 ; i <= ed ; i ++ )
02305     {
02306         if (dummyedge[i-1] != -1)
02307         {
02308             dummyedge[i-1] = sinfo_edge[i-1] ;
02309         }
02310         if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
02311              (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
02312         {
02313             dummyedge[i]   = -1 ;
02314         }
02315         if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
02316              (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
02317         {
02318             dummyedge[i+1] = -1 ; 
02319         }
02320     }
02321     
02322     k = 0 ;
02323     for ( i = 0 ; i < ed ; i++ )
02324     {
02325         if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
02326         {
02327             edgeclean[k] = dummyedge[i] ;
02328             pos_rowclean[k] = pos_row[i] ;
02329             k++ ;
02330             if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
02331             {
02332                 pos_rowclean[k] = pos_row[ed] ;
02333             }
02334         }
02335     }
02336 
02337     if ( k != slit_length - 1 )
02338     {
02339         sinfo_msg_error("not enough clean slitlets found") ;
02340         return -7 ;
02341     } 
02342 
02343     /* determine the margins of the fitting box outside the slitlets */
02344     margin = ( box_length - slit_length ) / 2 ;
02345 
02346     /* now go through the slitlets and store the intensity in a 
02347        buffer sinfo_vector */
02348     for ( j = 0 ; j <= k ; j++ )
02349     {
02350         m = 0 ;
02351         if ( j == 0 )
02352         {
02353             box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
02354             for( col = 0 ; col < edgeclean[0] + margin ; col++ )
02355             {
02356                 box_buffer->data[m] = pidata[col +ilx*pos_rowclean[0]] ;
02357                 m++ ;
02358             }
02359         }
02360         else if ( j < k )
02361         {
02362             box_buffer = sinfo_new_vector( edgeclean[j] - 
02363                                            edgeclean[j-1] + 2*margin ) ;
02364             for ( col = edgeclean[j - 1] - margin ; 
02365                   col < edgeclean[j] + margin ; col++ )
02366             {
02367                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[j]] ;
02368                 m++ ;
02369             }
02370         }
02371         else 
02372         {
02373             box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
02374             for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
02375             {
02376                 box_buffer->data[m] = pidata[col + ilx*pos_rowclean[k]] ;
02377                 m++ ;
02378             }
02379         }
02380 
02381         for ( left_right = 0 ; left_right <= 1 ; left_right++ )
02382         { 
02383             nel = 0 ;
02384             if ( left_right == 0 )
02385             {
02386                 nel = box_buffer -> n_elements / 2 ;
02387             }
02388             else
02389             {
02390                 if ( box_buffer -> n_elements % 2 == 0 )
02391                 {
02392                     nel = box_buffer -> n_elements / 2 ;
02393                 }
02394                 else
02395                 {
02396                     nel = box_buffer -> n_elements / 2 + 1 ;
02397                 }
02398             }
02399 
02400             /* now split the buffer in the midth in a left and right 
02401                part for fitting */
02402             half_buffer = sinfo_new_vector( nel ) ;
02403             if ( left_right == 0 )
02404             {
02405                 for ( i = 0 ; i < nel ; i++ )
02406                 {
02407                     half_buffer -> data[i] = box_buffer -> data[i] ;
02408                 }
02409             }
02410             else
02411             {
02412                 n_right = 0 ;
02413                 for ( i = box_buffer -> n_elements - 1 ; 
02414                       i >= box_buffer -> n_elements - nel ; i-- )
02415                 {
02416                     half_buffer -> data[n_right] = box_buffer -> data[i] ;
02417                     n_right++ ;
02418                 }
02419             }
02420 
02421             xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
02422             wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
02423             mpar = (int *)   cpl_calloc( NPAR, sizeof (int) ) ;
02424 
02425             /* set initial values for the fitting routine */
02426             minval =  FLT_MAX ;
02427             maxval = -FLT_MAX ;
02428             for ( i = 0 ; i < nel ; i++ )
02429             {
02430                 xdat[i] = i ;
02431                 wdat[i] = 1.0 ;
02432                 if ( half_buffer -> data[i] < minval )
02433                 {
02434                     minval = half_buffer -> data[i] ;
02435                 }
02436                 if ( half_buffer -> data[i] > maxval )
02437                 {
02438                     maxval = half_buffer -> data[i] ;
02439                 }
02440             }
02441 
02442             fitpar[2] = minval ;
02443             fitpar[3] = maxval ; 
02444 
02445             /* search for both positions of the half intensity of 
02446                the hat within the buffer */
02447             init1 = -1 ; 
02448             for ( i = 0 ; i < nel ; i++ )
02449             {
02450                 if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
02451                 {
02452                     init1 = i ;
02453                     break ;
02454                 }
02455             }
02456 
02457             /* determine the initial positions from the found values */
02458             if ( init1 != -1 )
02459             {
02460                 fitpar[0] = ((float)init1 - 1.) ;
02461                 fitpar[1] = ((float)init1 + 1.) ;
02462             }
02463 
02464             for ( i = 0 ; i < NPAR ; i++ )
02465             {
02466                 mpar[i] = 1 ;
02467                 dervpar[i] = 0. ;
02468             }
02469       
02470             xdim     = XDIMA ;
02471             ndat     = nel ;
02472             numpar   = NPAR ;
02473             tol      = TOLA ;
02474             lab      = LABA ;
02475             its      = ITSA ;
02476          
02477             /* finally, do the least squares fit over the buffer data */
02478             if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim, 
02479                                                       half_buffer -> data, 
02480                                                       wdat, &ndat, fitpar,
02481                                                       dervpar, mpar, &numpar, 
02482                                                       &tol, &its, &lab )) )
02483             { 
02484                 /* if the fit doesn't succeed the initial values are taken */
02485                 sinfo_msg_warning (" least squares fit failed, error"
02486                                    " no.: %d in slitlet: %d\n", iters, j) ;
02487                 fitpar[0] = ((float)init1 - 1.) ;
02488                 fitpar[1] = ((float)init1 + 1.) ;
02489             }
02490 
02491             pos = (fitpar[0] + fitpar[1]) / 2. ;
02492 
02493             /*---------------------------------------------------------------- 
02494              * now discern the left and the right sinfo_edge fit of the 
02495              * slitlets and associate the fit results with the absolute 
02496              * positions in the image consider the difference of the fitted 
02497              * slit position to the expected position and decide wether the 
02498              * fit is taken or the expected value is taken.
02499              */
02500             if ( left_right == 0 )
02501             {
02502                 /* take care of the column position of the fit boxes 
02503                    to get the absolute positions */
02504                 if ( j == 0 )
02505                 {
02506                     if ( fabs(pos - ((float)edgeclean[0] - 1. - 
02507                          (float)slit_length)) < diff_tol )
02508                     {
02509                         sinfo_slit_pos[0][0] = pos ;
02510                     }
02511                     else
02512                     {
02513                         sinfo_msg_warning("something wrong with fitted left"
02514                                           " position of slitlet 0") ;
02515                         if ( (float) edgeclean[0] - 1. - 
02516                              (float)slit_length < 0. )
02517                         {
02518                             sinfo_slit_pos[0][0] = 0. ;
02519                         }
02520                         else
02521                         {
02522                             sinfo_slit_pos[0][0] = (float)edgeclean[0] - 1. - 
02523                             (float)slit_length ;
02524                         }
02525                     }
02526                 }
02527                 else if ( j < k )
02528                 {
02529                     if ( fabs( pos - (float)margin ) < diff_tol )
02530                     {
02531                         sinfo_slit_pos[j][0] = pos + (float)edgeclean[j-1] - 
02532                                                (float)margin ;
02533                     }
02534                     else
02535                     {
02536                         sinfo_msg_warning("something wrong with fitted left"
02537                                           " position of slitlet %d", j) ;
02538                         sinfo_slit_pos[j][0] = (float)edgeclean[j-1] - 1. ;
02539                     }
02540                 }
02541                 else
02542                 {
02543                     if ( fabs( pos - (float)margin ) < diff_tol )
02544                     {
02545                         sinfo_slit_pos[k][0] = pos + (float)edgeclean[k-1] - 
02546                                                (float)margin ;
02547                     }
02548                     else
02549                     {
02550                         sinfo_msg_warning("something wrong with fitted left"
02551                                           " position of slitlet %d", j) ;
02552                         sinfo_slit_pos[k][0] = (float)edgeclean[k-1] - 1. ;
02553                     }
02554                 }
02555             }
02556             else
02557             {
02558                 /* take care of the column position of the fit boxes 
02559                    to get the absolute positions */
02560                 if ( j == 0 )
02561                 {
02562                     if ( fabs( (float)box_buffer->n_elements - pos - 
02563                                (float)edgeclean[0] ) < diff_tol )
02564                     {
02565                         sinfo_slit_pos[0][1] = (float)(box_buffer->n_elements - 
02566                                                 1) - pos ;
02567                     }
02568                     else
02569                     {
02570                         sinfo_msg_warning("something wrong with fitted "
02571                                           "right position of slitlet 0") ;
02572                         sinfo_slit_pos[0][1] = (float)edgeclean[0] - 1. ;
02573                     }
02574                 }
02575                 else if ( j < k )
02576                 {
02577                     if ( fabs( (float)box_buffer->n_elements - pos
02578                              + (float)edgeclean[j-1] - (float)margin - 
02579                                (float)edgeclean[j] ) < diff_tol )
02580                     {
02581                         sinfo_slit_pos[j][1] = (float)(box_buffer->n_elements -
02582                                         1) - pos
02583                                        + (float)edgeclean[j-1] - (float)margin ;
02584                     }
02585                     else
02586                     {
02587                         sinfo_msg_warning("something wrong with fitted right "
02588                                           "position of slitlet %d", j) ;
02589                         sinfo_slit_pos[j][1] = (float)edgeclean[j] - 1. ;
02590                     }
02591                 }
02592                 else
02593                 {
02594                     if ( edgeclean[k-1] + slit_length > ilx )
02595                     {
02596                         last_pos = (float)(ilx - 1) ;
02597                     }
02598                     else
02599                     {
02600                         last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
02601                     }
02602                     if ( fabs( (float)(box_buffer->n_elements - 1) - pos
02603                              + (float)edgeclean[k-1] - (float)margin - 
02604                                last_pos ) < diff_tol )
02605                     {
02606                         sinfo_slit_pos[k][1] = (float)(box_buffer->n_elements -
02607                                                1) - pos
02608                                        + (float)edgeclean[k-1] - (float)margin ;
02609                     }
02610                     else
02611                     {
02612                         sinfo_msg_warning("something wrong with fitted right "
02613                                           "position of slitlet %d\n", j) ;
02614                         sinfo_slit_pos[k][1] = last_pos ;
02615                     }
02616                 }
02617             }
02618 
02619             sinfo_new_destroy_vector ( half_buffer ) ;
02620             cpl_free( xdat ) ;
02621             cpl_free( wdat ) ;
02622             cpl_free( mpar ) ;
02623         }
02624         sinfo_new_destroy_vector ( box_buffer ) ;
02625     }
02626         
02627     cpl_free( sinfo_edge ) ;
02628     cpl_free( pos_row ) ;
02629     cpl_free( edgeclean ) ;
02630     cpl_free( dummyedge ) ;
02631     cpl_free( pos_rowclean ) ;
02632     cpl_free(position);
02633     return 0 ;
02634 }
02635                               
02670 int 
02671 sinfo_new_fit_slits_edge( cpl_image   * lineImage, 
02672                   FitParams ** par,
02673                   float     ** sinfo_slit_pos,
02674                   int          box_length,
02675                   float        y_box,
02676                   float        diff_tol )
02677 {
02678     float* position=NULL ;
02679     int   * sinfo_edge, * edgeclean ;
02680     int   * dummyedge ;
02681     int   * pos_row, * pos_rowclean ;
02682     Vector * box_buffer ;
02683     Vector * half_buffer ;
02684     float max_intensity ;
02685     float row_pos ;
02686     int   row, col ;
02687     int   i, j, k, m, n, ed ;
02688     int   found, init1 ;
02689     int   line ; 
02690     int   nel, n_right, left_right ;
02691     int   column ;
02692     int   slit_length ;
02693     int   agreed ;
02694     int   bad_line ;
02695     int   margin ;
02696     int   iters, xdim, ndat ;
02697     int   numpar, its ;
02698     int   * mpar ;
02699     float * xdat, * wdat ;
02700     float tol, lab ;
02701     float fitpar[NPAR] ;
02702     float dervpar[NPAR] ;
02703     float minval, maxval ;
02704     float pos, last_pos ;
02705     int ilx=0;
02706     int ily=0;
02707     float* pidata=NULL;
02708 
02709 
02710     if ( NULL == lineImage )
02711     {
02712         sinfo_msg_error(" no line image given!" ) ;
02713         return -1 ;
02714     }
02715     ilx=cpl_image_get_size_x(lineImage);
02716     ily=cpl_image_get_size_y(lineImage);
02717     pidata=cpl_image_get_data_float(lineImage);
02718 
02719     slit_length = (int) sqrt (ilx) ;
02720 
02721     if ( NULL == par )
02722     {
02723         sinfo_msg_error(" no line fit parameters given!" ) ;
02724         return -2 ;
02725     }
02726 
02727     if ( NULL == sinfo_slit_pos )
02728     {
02729         sinfo_msg_error(" no position array allocated!" ) ;
02730         return -3 ;
02731     }
02732 
02733     if ( box_length <  4 ||
02734          box_length >= 2*slit_length )
02735     {
02736         sinfo_msg_error(" wrong fitting box length given!" ) ;
02737         sinfo_msg_error(" Must be 4 <= box_length < %d ",2*slit_length ) ;
02738         sinfo_msg_error(" You have chosen box_length = %d ",box_length);
02739         return -4 ;
02740     }
02741 
02742     if ( y_box <= 0.  || y_box > 3. )
02743     {
02744         sinfo_msg_error(" wrong y box length given!" ) ;
02745         sinfo_msg_error(" y_box=%f not in range (0,3]!",y_box);
02746         return -5 ;
02747     }
02748 
02749     if ( diff_tol < 1. )
02750     {
02751         sinfo_msg_error(" diff_tol too small!" ) ;
02752         return -6 ;
02753     }
02754 
02755     /* allocate memory for the edges and the row positon of the slitlets */
02756     sinfo_edge         = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
02757     dummyedge    = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
02758     edgeclean    = (int*) cpl_calloc( slit_length-1, sizeof(int) ) ;
02759     pos_row      = (int*) cpl_calloc( 3*slit_length, sizeof(int) ) ;
02760     pos_rowclean = (int*) cpl_calloc( slit_length, sizeof(int) ) ;
02761 
02762     /* ------------------------------------------------------------------------
02763      * go through the first image columns and the fit parameters and find 
02764      * the line with the highest intensity 
02765      */
02766     agreed = -1 ;
02767     bad_line = -1 ;
02768     while( agreed == -1 )
02769     {
02770         found = -1 ;
02771         max_intensity = -FLT_MAX ;
02772         for ( col = 0 ; col < slit_length ; col++ )
02773         {
02774             for ( i = 0 ; i < par[0]->n_params ; i++ )
02775             {
02776                 if ( par[i]->column == col && par[i] -> line != bad_line )
02777                 {
02778                     if ( par[i]->fit_par[0] > max_intensity )
02779                     {
02780                         if ( par[i]->fit_par[1] >= 1. && 
02781                              par[i]->fit_par[2] > 0. )
02782                         {
02783                             max_intensity = par[i]->fit_par[0] ;
02784                             found = i ;
02785                         }
02786                     }
02787                 }
02788             }  
02789         }
02790 
02791         /* --------------------------------------------------------------------
02792          * check if the found line is usable and if the neighbouring line 
02793          * have intensity on near rows in neighbouring slitlets 
02794          */
02795         line    = par[found]->line ;
02796         column  = par[found]->column ;
02797         row_pos = par[found]->fit_par[2] ;
02798         if ( found >= 0 && max_intensity > 0. )
02799         {
02800             for ( i = 0 ; i < par[0]->n_params ; i++ )
02801             {
02802                 if ( par[i]->line == line-1 && 
02803                      par[i]->column == column + slit_length )
02804                 {
02805                     if ( par[i]->fit_par[2] <= (row_pos + y_box) &&
02806                          par[i]->fit_par[2] >= (row_pos - y_box) )
02807                     {
02808                         bad_line = line ;
02809                     } 
02810                 }
02811             }
02812             if ( bad_line != line )
02813             {
02814                 agreed = 1 ;
02815                 break ;
02816             }
02817         }
02818         else 
02819         {
02820             sinfo_msg_error("no emission line found in "
02821                             "the first image columns") ;
02822             cpl_free( sinfo_edge ) ;
02823             cpl_free( pos_row ) ;
02824             cpl_free( edgeclean ) ;
02825             cpl_free( dummyedge ) ;
02826             cpl_free( pos_rowclean ) ;
02827             return -7 ;
02828         }    
02829     }
02830 
02831  
02832     if ( agreed == -1 )
02833     {
02834         sinfo_msg_error(" no emission line found in the first image columns") ;
02835         cpl_free( sinfo_edge ) ;
02836         cpl_free( pos_row ) ;
02837         cpl_free( edgeclean ) ;
02838         cpl_free( dummyedge ) ;
02839         cpl_free( pos_rowclean ) ;
02840         return -7 ;
02841     }    
02842  
02843     /* now find and store the raw sinfo_edge positions of the found slitlet */ 
02844     n  = 0 ;
02845     ed = 0 ;
02846     position=cpl_calloc(ilx,sizeof(float)) ;
02847 
02848     for ( col = 0 ; col < ilx ; col++ )
02849     {
02850         for ( i = 0 ; i < par[0]->n_params ; i++ )
02851         {
02852             if ( par[i]->column == col && par[i]->line == line )
02853             {
02854                 if ( par[i]->fit_par[0] > 0. && 
02855                      par[i]->fit_par[1] >= 1.  && 
02856                      par[i]->fit_par[2] > 0. )
02857                 {
02858                     position[n] = par[i]->fit_par[2] ;
02859                     if ( n > 0 && fabs(position[n] - position[n-1]) > y_box )
02860                     {
02861                         sinfo_edge[ed] = col ; 
02862                         pos_row[ed] = sinfo_new_nint( position[n-1] ) ;
02863                         ed++ ;
02864                         if ( col >= ilx - slit_length - 5 ) 
02865                         {
02866                             pos_row[ed] =  sinfo_new_nint( position[n] ) ;
02867                         }
02868                     }
02869                     n++ ;
02870                 }
02871             }
02872         }
02873     }
02874     if ( ed < (slit_length - 1) )
02875     {
02876         sinfo_msg_error(" not enough slitlets found") ;
02877         cpl_free( sinfo_edge ) ;
02878         cpl_free( pos_row ) ;
02879         cpl_free( edgeclean ) ;
02880         cpl_free( dummyedge ) ;
02881         cpl_free( pos_rowclean ) ;
02882         return -8 ;
02883     } 
02884 
02885     /* now find the clean sinfo_edge and row positions of the slitlets */
02886     for ( i = 1 ; i <= ed ; i ++ )
02887     {
02888         if ( i == ed )
02889         {
02890             if ( (sinfo_edge[i-1] - sinfo_edge[i-2]) < slit_length - 3 ||
02891                  (sinfo_edge[i-1] - sinfo_edge[i-2]) > slit_length + 3 )
02892             {
02893                 dummyedge[i-1]   = -1 ;
02894             }
02895             
02896         }
02897         if (dummyedge[i-1] != -1)
02898         {
02899             dummyedge[i-1] = sinfo_edge[i-1] ;
02900         }
02901         else
02902         {
02903             continue ;
02904         }
02905         if ( i < ed )
02906         {
02907             if ( (sinfo_edge[i] - sinfo_edge[i-1]) < slit_length - 3 ||
02908                  (sinfo_edge[i] - sinfo_edge[i-1]) > slit_length + 3 )
02909             {
02910                 dummyedge[i]   = -1 ;
02911             }
02912         }
02913         if ( i + 1 < ed && dummyedge[i] != -1 )
02914         {
02915             if ( (sinfo_edge[i+1] - sinfo_edge[i]) < slit_length - 3 ||
02916                  (sinfo_edge[i+1] - sinfo_edge[i]) > slit_length + 3 )
02917             {
02918                 dummyedge[i+1] = -1 ; 
02919             }
02920         }
02921     }
02922     
02923     k = 0 ;
02924     for ( i = 0 ; i < ed ; i++ )
02925     {
02926         if ( dummyedge[i] != -1 && dummyedge[i] != 0 )
02927         {
02928             edgeclean[k] = dummyedge[i] ;
02929             pos_rowclean[k] = pos_row[i] ;
02930             k++ ;
02931             if( edgeclean[k-1] > (ilx - slit_length - 6 ) )
02932             {
02933                 pos_rowclean[k] = pos_row[ed] ;
02934             }
02935         }
02936     }
02937 
02938     if ( k != slit_length - 1 )
02939     {
02940         sinfo_msg_error(" not enough clean slitlets found") ;
02941         cpl_free( sinfo_edge ) ;
02942         cpl_free( pos_row ) ;
02943         cpl_free( edgeclean ) ;
02944         cpl_free( dummyedge ) ;
02945         cpl_free( pos_rowclean ) ;
02946         return -8 ;
02947     } 
02948 
02949     /* determine the margins of the fitting box outside the slitlets */
02950     margin = box_length / 2 ;
02951 
02952     /* ------------------------------------------------------------------------
02953      * now go through the slitlets, search along each column within a box with 
02954      * half width y_box the maximum value and store these found values in a 
02955      * buffer
02956      */
02957     for ( j = 0 ; j <= k ; j++ )
02958     {
02959         m = 0 ;
02960         if ( j == 0 )
02961         {
02962             box_buffer = sinfo_new_vector( edgeclean[0] + margin ) ;
02963             for( col = 0 ; col < edgeclean[0] + margin ; col++ )
02964             {
02965                 maxval = -FLT_MAX ;
02966                 for ( row = pos_rowclean[0] - sinfo_new_nint(y_box) ; 
02967                       row <= pos_rowclean[0] + sinfo_new_nint(y_box) ; row++ )
02968                 {
02969                     if ( maxval < pidata[col + ilx*row] )
02970                     {
02971                         maxval = pidata[col + ilx*row] ;
02972                     }
02973                 }
02974                 box_buffer->data[m] = maxval ;
02975                 m++ ;
02976             }
02977         }
02978         else if ( j < k )
02979         {
02980             box_buffer = sinfo_new_vector( edgeclean[j] - 
02981                                            edgeclean[j-1] + 2*margin ) ;
02982             for ( col = edgeclean[j - 1] - margin ; 
02983                   col < edgeclean[j] + margin ; col++ )
02984             {
02985                 maxval = -FLT_MAX ;
02986                 for ( row = pos_rowclean[j] - sinfo_new_nint(y_box) ; 
02987                       row <= pos_rowclean[j] + sinfo_new_nint(y_box) ; row++ )
02988                 {
02989                     if ( maxval < pidata[col + ilx*row] )
02990                     {
02991                         maxval = pidata[col + ilx*row] ;
02992                     }
02993                 }
02994                 box_buffer->data[m] = maxval ;
02995                 m++ ;
02996             }
02997         }
02998         else 
02999         {
03000             box_buffer = sinfo_new_vector( ilx - edgeclean[k-1] + margin ) ;
03001             for ( col = edgeclean[k - 1] - margin ; col < ilx ; col++ )
03002             {
03003                 maxval = -FLT_MAX ;
03004                 for ( row = pos_rowclean[k] - sinfo_new_nint(y_box) ; 
03005                       row <= pos_rowclean[k] + sinfo_new_nint(y_box) ; row++ )
03006                 {
03007                     if ( maxval < pidata[col + ilx*row] )
03008                     {
03009                         maxval = pidata[col + ilx*row] ;
03010                     }
03011                 }
03012                 box_buffer->data[m] = maxval ;
03013                 m++ ;
03014             }
03015         }
03016 
03017         for ( left_right = 0 ; left_right <= 1 ; left_right++ )
03018         { 
03019             nel = 0 ;
03020             if ( left_right == 0 )
03021             {
03022                 nel = box_buffer -> n_elements / 2 ;
03023             }
03024             else
03025             {
03026                 if ( box_buffer -> n_elements % 2 == 0 )
03027                 {
03028                     nel = box_buffer -> n_elements / 2 ;
03029                 }
03030                 else
03031                 {
03032                     nel = box_buffer -> n_elements / 2 + 1 ;
03033                 }
03034             }
03035 
03036             /* now split the buffer in the midth in a left and right 
03037                part for fitting */
03038             half_buffer = sinfo_new_vector( nel ) ;
03039             if ( left_right == 0 )
03040             {
03041                 for ( i = 0 ; i < nel ; i++ )
03042                 {
03043                     half_buffer -> data[i] = box_buffer -> data[i] ;
03044                 }
03045             }
03046             else
03047             {
03048                 n_right = 0 ;
03049                 for ( i = box_buffer -> n_elements - 1 ; 
03050                       i >= box_buffer -> n_elements - nel ; i-- )
03051                 {
03052                     half_buffer -> data[n_right] = box_buffer -> data[i] ;
03053                     n_right++ ;
03054                 }
03055             }
03056 
03057             xdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
03058             wdat = (float *) cpl_calloc( nel, sizeof (float) ) ;
03059             mpar = (int *)   cpl_calloc( NPAR, sizeof (int) ) ;
03060 
03061             /* set initial values for the fitting routine */
03062             minval =  FLT_MAX ;
03063             maxval = -FLT_MAX ;
03064             for ( i = 0 ; i < nel ; i++ )
03065             {
03066                 xdat[i] = i ;
03067                 wdat[i] = 1.0 ;
03068                 if ( half_buffer -> data[i] < minval )
03069                 {
03070                     minval = half_buffer -> data[i] ;
03071                 }
03072                 if ( half_buffer -> data[i] > maxval )
03073                 {
03074                     maxval = half_buffer -> data[i] ;
03075                 }
03076             }
03077 
03078             fitpar[2] = minval ;
03079             fitpar[3] = maxval ; 
03080 
03081             /* search for both positions of the half intensity of 
03082                the hat within the buffer */
03083             init1 = -1 ; 
03084             for ( i = 0 ; i < nel ; i++ )
03085             {
03086                 if ( half_buffer -> data[i] >= ( maxval + minval ) / 2. )
03087                 {
03088                     init1 = i ;
03089                     break ;
03090                 }
03091             }
03092 
03093             /* determine the initial positions from the found values */
03094             if ( init1 != -1 )
03095             {
03096                 fitpar[0] = ((float)init1 - 1.) ;
03097                 fitpar[1] = ((float)init1 + 1.) ;
03098             }
03099 
03100             for ( i = 0 ; i < NPAR ; i++ )
03101             {
03102                 mpar[i] = 1 ;
03103                 dervpar[i] = 0. ;
03104             }
03105       
03106             xdim     = XDIMA ;
03107             ndat     = nel ;
03108             numpar   = NPAR ;
03109             tol      = TOLA ;
03110             lab      = LABA ;
03111             its      = ITSA ;
03112          
03113             /* finally, do the least squares fit over the buffer data */
03114             if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim, 
03115                                                       half_buffer -> data, 
03116                                                       wdat, &ndat, fitpar,
03117                                                       dervpar, mpar, &numpar, 
03118                                                       &tol, &its, &lab )) )
03119             { 
03120                 /* if the fit doesn't succeed the initial values are taken */
03121                 sinfo_msg_warning ("least squares fit failed, error "
03122                                    "no.: %d in slitlet: %d", iters, j) ;
03123                 fitpar[0] = ((float)init1 - 1.) ;
03124                 fitpar[1] = ((float)init1 + 1.) ;
03125             }
03126 
03127             pos = (fitpar[0] + fitpar[1]) / 2. ;
03128 
03129             /*----------------------------------------------------------------- 
03130              * now discern the left and the right sinfo_edge fit of the 
03131              * slitlets and associate the fit results with the absolute 
03132              * positions in the image consider the difference of the fitted 
03133              * slit position to the expected position and decide wether the 
03134              * fit is taken or the expected value is taken.
03135              */
03136             if ( left_right == 0 )
03137             {
03138                 /* take care of the column position of the fit boxes to get 
03139                    the absolute positions */
03140                 if ( j == 0 )
03141                 {
03142                     if ( fabs(pos - ((float)edgeclean[0] - 1. - 
03143                          (float)slit_length)) < diff_tol )
03144                     {
03145                         sinfo_slit_pos[0][0] = pos ;
03146                     }
03147                     else
03148                     {
03149                         sinfo_msg_warning("something wrong with fitted "
03150                                           "left position of slitlet 0") ;
03151                         if ((float) edgeclean[0] - 1. - 
03152                             (float)slit_length < 0. )
03153                         {
03154                             sinfo_slit_pos[0][0] = 0. ;
03155                         }
03156                         else
03157                         {
03158                             sinfo_slit_pos[0][0] = (float)edgeclean[0] - 1. - 
03159                                                    (float)slit_length ;
03160                         }
03161                     }
03162                 }
03163                 else if ( j < k )
03164                 {
03165                     if ( fabs( pos - (float)margin ) < diff_tol )
03166                     {
03167                         sinfo_slit_pos[j][0] = pos + (float)edgeclean[j-1] - 
03168                                                      (float)margin ;
03169                     }
03170                     else
03171                     {
03172                         sinfo_msg_warning("something wrong with fitted "
03173                                           "left position of slitlet %d", j) ;
03174                         sinfo_slit_pos[j][0] = (float)edgeclean[j-1] - 1. ;
03175                     }
03176                 }
03177                 else
03178                 {
03179                     if ( fabs( pos - (float)margin ) < diff_tol )
03180                     {
03181                         sinfo_slit_pos[k][0] = pos + (float)edgeclean[k-1] - 
03182                                                      (float)margin ;
03183                     }
03184                     else
03185                     {
03186                         sinfo_msg_warning("something wrong with fitted left "
03187                                           "position of slitlet %d", j) ;
03188                         sinfo_slit_pos[k][0] = (float)edgeclean[k-1] - 1. ;
03189                     }
03190                 }
03191             }
03192             else
03193             {
03194                 /* take care of the column position of the fit boxes to 
03195                    get the absolute positions */
03196                 if ( j == 0 )
03197                 {
03198                     if ( fabs( (float)box_buffer->n_elements - pos - 
03199                                (float)edgeclean[0] ) < diff_tol )
03200                     {
03201                        sinfo_slit_pos[0][1] = (float)(box_buffer->n_elements - 
03202                                                1) - pos ;
03203                     }
03204                     else
03205                     {
03206                         sinfo_msg_warning("something wrong with fitted "
03207                                           "right position of slitlet 0") ;
03208                         sinfo_slit_pos[0][1] = (float)edgeclean[0] - 1. ;
03209                     }
03210                 }
03211                 else if ( j < k )
03212                 {
03213                     if ( fabs( (float)box_buffer->n_elements - pos
03214                              + (float)edgeclean[j-1] - (float)margin - 
03215                                (float)edgeclean[j] ) < diff_tol )
03216                     {
03217                         sinfo_slit_pos[j][1] = (float)(box_buffer->n_elements -
03218                                                1) - pos
03219                                        + (float)edgeclean[j-1] - (float)margin;
03220                     }
03221                     else
03222                     {
03223                         sinfo_msg_warning("something wrong with fitted "
03224                                           "right position of slitlet %d", j) ;
03225                         sinfo_slit_pos[j][1] = (float)edgeclean[j] - 1. ;
03226                     }
03227                 }
03228                 else
03229                 {
03230                     if ( edgeclean[k-1] + slit_length > ilx )
03231                     {
03232                         last_pos = (float)(ilx - 1) ;
03233                     }
03234                     else
03235                     {
03236                         last_pos = (float)(edgeclean[k-1] - 1 + slit_length) ;
03237                     }
03238                     if ( fabs( (float)(box_buffer->n_elements - 1) - pos
03239                              + (float)edgeclean[k-1] - (float)margin - 
03240                                last_pos ) < diff_tol )
03241                     {
03242                         sinfo_slit_pos[k][1] = (float)(box_buffer->n_elements -
03243                                                1) - pos
03244                                        + (float)edgeclean[k-1] - (float)margin ;
03245                     }
03246                     else
03247                     {
03248                         sinfo_msg_warning("something wrong with fitted "
03249                                           "right position of slitlet %d", j) ;
03250                         sinfo_slit_pos[k][1] = last_pos ;
03251                     }
03252                 }
03253             }
03254 
03255             sinfo_new_destroy_vector ( half_buffer ) ;
03256             cpl_free( xdat ) ;
03257             cpl_free( wdat ) ;
03258             cpl_free( mpar ) ;
03259         }
03260         sinfo_new_destroy_vector ( box_buffer ) ;
03261     }
03262         
03263     cpl_free( sinfo_edge ) ;
03264     cpl_free( pos_row ) ;
03265     cpl_free( edgeclean ) ;
03266     cpl_free( dummyedge ) ;
03267     cpl_free( pos_rowclean ) ;
03268     cpl_free( position );
03269     return 0 ;
03270 }
03271 
03294 int 
03295 sinfo_new_fit_slits_edge_with_estimate ( cpl_image   * lineImage,
03296                                float     ** sinfo_slit_pos,
03297                                int          box_length,
03298                                float        y_box,
03299                                float        diff_tol,
03300                                int          low_pos,
03301                                int          high_pos )
03302 {
03303     int*   position=NULL ;
03304     Vector * box_buffer ;
03305     Vector * in_buffer ;
03306     int   found_row ;
03307     int   row, col ;
03308     int   col_first, col_last ;
03309     int   row_first, row_last ;
03310     int   i, j, m, n ;
03311     int   init1 ;
03312     int   left_right ;
03313     int   n_buf, shift ;
03314     int   slit_length ;
03315     int   iters, xdim, ndat ;
03316     int   numpar, its ;
03317     int   * mpar ;
03318     float * xdat, * wdat ;
03319     float tol, lab ;
03320     float fitpar[NPAR] ;
03321     float dervpar[NPAR] ;
03322     float minval, maxval ;
03323     float pos ;
03324     float new_pos ;
03325     int   slitposition[SLITLENGTH] ;
03326     pixelvalue rowpos[SLITLENGTH] ;
03327     int ilx=0;
03328     int ily=0;
03329     float* pidata=NULL;
03330 
03331     slit_length = SLITLENGTH ; /* this is too high: 64 */
03332     slit_length = N_SLITLETS ; /* this is better: 32 */
03333 
03334 
03335     if ( NULL == lineImage )
03336     {
03337         sinfo_msg_error(" no line image given!" ) ;
03338         return -1 ;
03339     }
03340     ilx=cpl_image_get_size_x(lineImage);
03341     ily=cpl_image_get_size_y(lineImage);
03342     pidata=cpl_image_get_data_float(lineImage);
03343 
03344     if ( NULL == sinfo_slit_pos )
03345     {
03346         sinfo_msg_error(" no position array allocated!" ) ;
03347         return -1 ;
03348     }
03349 
03350     if ( box_length < 4 ||
03351          box_length > 2*slit_length )
03352     {
03353         sinfo_msg_error(" wrong fitting box length given!" ) ;
03354         sinfo_msg_error(" Must be 4 <= box_length < %d ",2*slit_length ) ;
03355         sinfo_msg_error(" You have chosen box_length = %d",box_length);
03356 
03357 
03358         return -1 ;
03359     }
03360 
03361     if ( y_box <= 0. || y_box > 6. )
03362     {
03363         sinfo_msg_error("wrong y box length given!" ) ;
03364         sinfo_msg_error("You have chosen y_box=%f not in range (0,6]!",y_box);
03365         return -1 ;
03366     }
03367     if ( diff_tol <= 0. )
03368     {
03369         sinfo_msg_error(" wrong diff_tol given!" ) ;
03370         return -1 ;
03371     }
03372 
03373         if ( low_pos >= high_pos || low_pos < 0 || 
03374              high_pos <= 0 || high_pos > ily )
03375     {
03376         sinfo_msg_error(" wrong user given search positions!" ) ;
03377         return -1 ;
03378     }
03379 
03380     /* now search for the maximum between the given positions for each col */
03381     position=cpl_calloc(ilx,sizeof(int)) ;
03382 
03383     for ( col = 0 ; col < ilx ; col++ )
03384     {
03385         found_row = -1 ;
03386         maxval = -FLT_MAX ;
03387         for ( row = low_pos ; row <= high_pos ; row++ )
03388         {
03389             if ( maxval < pidata[col+row*ilx] )
03390             {
03391                 maxval = pidata[col+row*ilx] ;
03392                 found_row = row ;
03393             }
03394         }
03395         if ( maxval > -FLT_MAX && found_row > low_pos )
03396         {
03397             position[col] = found_row ;
03398         }
03399         else
03400         {
03401             position[col] = 0 ;
03402         }
03403     }
03404 
03405     /* ------------------------------------------------------------------------
03406      * now go through the slitlets, search along each column within a box with
03407      * half width y_box the maximum value and store these found values in a 
03408      * buffer
03409      */
03410     for ( j = 0 ; j < slit_length ; j++ )
03411     {
03412         /* now go through the columns and determine the slitlet positions by
03413          * calculating the sinfo_median of the found positions
03414          */
03415         n = 0 ;
03416         for ( col = sinfo_new_nint(sinfo_slit_pos[j][0])+ 1 ; 
03417               col < sinfo_new_nint(sinfo_slit_pos[j][1]) -1 ; col++ )
03418         {
03419             rowpos[n] = (pixelvalue)position[col] ;
03420             n++ ;
03421         }
03422         slitposition[j] = (int)sinfo_new_median(rowpos, n) ;
03423         for ( left_right = 0 ; left_right <= 1 ; left_right++ )
03424 
03425         {
03426             init1 = 0 ;
03427             col_first = sinfo_new_nint( sinfo_slit_pos[j][left_right] ) - 
03428                                         box_length/2 ;
03429             col_last  = sinfo_new_nint( sinfo_slit_pos[j][left_right] ) + 
03430                         box_length/2 ;
03431             if ( col_first < 0 )
03432             {
03433                 col_first = 0 ;
03434                 init1 = 1 ;
03435             }
03436             if ( col_last > ilx )
03437             {
03438                 col_last = ilx ;
03439                 init1 = 1 ;
03440             }
03441             if ( col_last - col_first <= 0 )
03442             {
03443                 sinfo_msg_error(" first and last column wrong!" ) ;
03444                 return -1 ;
03445             }
03446             box_buffer = sinfo_new_vector( col_last - col_first ) ;
03447             m = 0 ;
03448             if ( left_right == 0 )
03449             {
03450                 for( col = col_first ; col < col_last ; col++ )
03451                 {
03452                     row_first = slitposition[j] - sinfo_new_nint(y_box) ;
03453                     row_last  = slitposition[j] + sinfo_new_nint(y_box) ;
03454                     if ( row_first < 0 )
03455                     {
03456                         row_first = 0 ;
03457                     }
03458                     if ( row_last >= ily  )
03459                     {
03460                         row_last = ily - 1 ;
03461                     }
03462                     maxval = -FLT_MAX ;
03463                     for ( row = row_first ; row <= row_last ; row++ )
03464                     {
03465                         if ( maxval < pidata[col + ilx*row] )
03466                         {
03467                             maxval = pidata[col + ilx*row] ;
03468                         }
03469                     }
03470                     box_buffer->data[m] = maxval ;
03471                     m++ ;
03472                 }
03473             }
03474             else
03475             {
03476                 for( col = col_last-1 ; col >= col_first ; col-- )
03477                 {
03478                     row_first = slitposition[j] - sinfo_new_nint(y_box) ;
03479                     row_last  = slitposition[j] + sinfo_new_nint(y_box) ;
03480                     if ( row_first < 0 )
03481                     {
03482                         row_first = 0 ;
03483                     }
03484                     if ( row_last >= ily  )
03485                     {
03486                         row_last = ily - 1 ;
03487                     }
03488                     maxval = -FLT_MAX ;
03489                     for ( row = row_first ; row <= row_last ; row++ )
03490                     {
03491                         if ( maxval < pidata[col + ilx*row] )
03492                         {
03493                             maxval = pidata[col + ilx*row] ;
03494                         }
03495                     }
03496                     box_buffer->data[m] = maxval ;
03497                     m++ ;
03498                 }
03499             }
03500 
03501             xdat=(float *)cpl_calloc( box_buffer->n_elements, sizeof (float));
03502             wdat=(float *)cpl_calloc( box_buffer->n_elements, sizeof (float));
03503             mpar=(int *)  cpl_calloc( NPAR, sizeof (int) ) ;
03504 
03505             /* set initial values for the fitting routine */
03506             minval =  FLT_MAX ;
03507             maxval = -FLT_MAX ;
03508             for ( i = 0 ; i < box_buffer->n_elements ; i++ )
03509             {
03510                 xdat[i] = i ;
03511                 wdat[i] = 1.0 ;
03512                 if ( box_buffer -> data[i] < minval )
03513                 {
03514                     minval = box_buffer -> data[i] ;
03515                 }
03516                 if ( box_buffer -> data[i] > maxval )
03517                 {
03518                     maxval = box_buffer -> data[i] ;
03519                 }
03520             }
03521             fitpar[2] = minval ;
03522             fitpar[3] = maxval ;
03523             /*----------------------------------------------------------------
03524              * if we have too few left background values (at the image edges)
03525              * the left margin of the buffer to fit is filled with the minimal
03526              * values in order to get a good fit
03527              */
03528 
03529             if ( init1 == 1 )
03530             {
03531                 n_buf = box_buffer->n_elements + box_length/2 ;
03532                 in_buffer = sinfo_new_vector( n_buf ) ;
03533                 for ( i = 0 ; i < box_length/2 ; i++ )
03534                 {
03535                     in_buffer -> data[i] = minval ;
03536                 }
03537                 shift = 0 ;
03538                 for ( i = box_length/2 ; i < n_buf ; i++ )
03539                 {
03540                     in_buffer -> data[i] = box_buffer -> data[shift] ;
03541                     shift++ ;
03542                 }
03543                 sinfo_new_destroy_vector ( box_buffer ) ;
03544                 box_buffer = sinfo_new_vector ( n_buf ) ;
03545                 for ( i = 0 ; i < n_buf ; i++ )
03546                 {
03547                     box_buffer -> data[i] = in_buffer -> data[i] ;
03548                 }
03549                 sinfo_new_destroy_vector ( in_buffer ) ;
03550             }
03551             /* determine the initial positions from the found values */
03552             fitpar[0] = (float)box_buffer->n_elements/2. - 1. ;
03553             fitpar[1] = (float)box_buffer->n_elements/2. + 1. ;
03554 
03555             for ( i = 0 ; i < NPAR ; i++ )
03556             {
03557                 mpar[i] = 1 ;
03558                 dervpar[i] = 0. ;
03559             }
03560 
03561             xdim     = XDIMA ;
03562             ndat     = box_buffer->n_elements ;
03563             numpar   = NPAR ;
03564             tol      = TOLA ;
03565             lab      = LABA ;
03566             its      = ITSA ;
03567 
03568             /* finally, do the least squares fit over the buffer data */
03569             if ( 0 > ( iters = sinfo_new_lsqfit_edge( xdat, &xdim, 
03570                                                       box_buffer -> data, 
03571                                                       wdat, &ndat, fitpar,
03572                                                       dervpar, mpar, &numpar, 
03573                                                       &tol, &its, &lab )) )
03574             {
03575                 sinfo_msg_warning (" least squares fit failed, error "
03576                                    "no.: %d in slitlet: %d\n", iters, j) ;
03577                 sinfo_new_destroy_vector(box_buffer) ;
03578                 cpl_free( xdat ) ;
03579                 cpl_free( wdat ) ;
03580                 cpl_free( mpar ) ;
03581                 continue ;
03582             }
03583             if ( fitpar[1] <= fitpar[0] )
03584             {
03585                 sinfo_msg_warning ("fit failed due to negative slope of "
03586                                    "sinfo_new_edge function in slitlet: %d",j);
03587                 sinfo_new_destroy_vector(box_buffer) ;
03588                 cpl_free( xdat ) ;
03589                 cpl_free( wdat ) ;
03590                 cpl_free( mpar ) ;
03591                 continue ;
03592             }
03593 
03594             pos = (fitpar[0] + fitpar[1])/2. ;
03595             if ( init1 == 1 )
03596             {
03597                 pos -= (float)box_length/2. ;
03598             }
03599 
03600             /*-------------------------------------------------------------
03601              * now compute the real slit positions using the guess positions
03602              * if the fit did not work the guess positions are taken
03603              * the same is done if the deviations are too big.
03604              */
03605             if ( pos != 0. )
03606             {
03607                 if ( left_right == 0 )
03608                 {
03609                     new_pos = (float)col_first + pos ;
03610                 }
03611                 else
03612                 {
03613                     new_pos = (float)col_last-1 - pos ;
03614                 }
03615                 if ( fabs(new_pos - sinfo_slit_pos[j][left_right]) < diff_tol )
03616                 {
03617                     sinfo_slit_pos[j][left_right] = new_pos ;
03618                 }
03619                 else
03620                 {
03621                     sinfo_msg_warning (" deviation bigger than tolerance,"
03622                                        " take the estimated slitlet positiona"
03623                                        " in slitlet: %d\n", j) ;
03624                 }
03625             }
03626 
03627             cpl_free( xdat ) ;
03628             cpl_free( wdat ) ;
03629             cpl_free( mpar ) ;
03630             sinfo_new_destroy_vector ( box_buffer ) ;
03631         }
03632     }
03633     cpl_free(position);
03634     return 0 ;
03635 }
03636 
03637 

Generated on 8 Mar 2011 for SINFONI Pipeline Reference Manual by  doxygen 1.6.1