sinfo_wave_calibration.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  13/07/00  created
00027 */
00028 
00029 /************************************************************************
00030 *   NAME
00031 *     sinfo_wave_calibration.c -
00032 *     routines needed for wavelength calibration
00033 *
00034 *   SYNOPSIS
00035 * 
00036 *   1) FitParams ** sinfo_new_fit_params( int n_params )
00037 *
00038 *   2) void sinfo_new_destroy_fit_params ( FitParams ** params )
00039 *
00040 *   3) void sinfo_new_dump_fit_params_to_ascii(FitParams ** params,
00041                                                const char * filename )
00042 *
00043 *   4) void sinfo_new_dump_ascii_to_fit_params ( FitParams ** params, 
00044                                                  char * filename )
00045 *
00046 *   5) int sinfo_new_find_lines(cpl_image * lineImage, 
00047 *                     float    * wave_position, 
00048 *                     float    * wave_intensity,
00049 *                     int        n_lines, 
00050 *                     int     ** row_clean,
00051 *                     float   ** wavelength_clean,
00052 *                     float      beginWave, 
00053 *                     float      dispersion,
00054 *                     float      mindiff, 
00055 *                     int        halfWidth,
00056 *                     int      * n_found_lines,
00057 *                     float      sigma,
00058 *                     int      * sum_lines )
00059 *
00060 *   6) int sinfo_new_read_list( char * listname, 
00061                                 float * lineCenter, 
00062                                 float * lineIntensity )
00063 *
00064 *
00065 *   7) int sinfo_new_line_fit ( cpl_image  *  mergedImage, 
00066 *                    FitParams *  par,
00067 *                    float        fwhm,
00068 *                    int          lineInd,
00069 *                    int          column, 
00070 *                    int          halfWidth, 
00071 *                    int          lineRow,
00072 *                    float        min_amplitude )
00073 *
00074 *   8) int sinfo_new_fit_lines ( cpl_image  *  line_image, 
00075 *                     FitParams ** allParams,
00076 *                     float        fwhm,
00077 *                     int       *  n_lines, 
00078 *                     int       ** row,
00079 *                     float     ** wavelength, 
00080 *                     int          width,
00081 *                     float        min_amplitude ) 
00082 *
00083 *   9) float sinfo_new_polyfit( FitParams ** par, 
00084 *                     int          column,
00085 *                     int          n_lines,
00086 *                     int          n_rows,
00087 *                     float        dispersion,
00088 *                     float        max_residual,
00089 *                     float *      acoefs, 
00090 *                     float *      dacoefs, 
00091 *                     int   *      n_reject,
00092 *                     int          n_fitcoefs )
00093 *
00094 *   10) float sinfo_new_coefs_cross_fit ( int      n_columns,
00095 *                            float *  acoefs,
00096 *                            float *  dacoefs, 
00097 *                            float *  bcoefs,
00098 *                            int      n_fitcoefs,
00099 *                            float    sigma_factor )
00100 *
00101 *
00102 *  11) cpl_image * sinfo_new_wave_map( cpl_image * lineImage,
00103 *                          float   ** bcoefs,
00104 *                          int        n_a_fitcoefs,
00105 *                          int        n_b_fitcoefs,
00106 *                          float    * wavelength,
00107 *                          float    * intensity,
00108 *                          int        n_lines,
00109 *                          int        magFactor,
00110 *                          int      * bad_column_mask,
00111 *                          int        n_bad_columns )
00112 *
00113 *  12) int sinfo_new_wavelength_calibration( cpl_image   * image, 
00114 *                                 FitParams ** par ,
00115 *                                 float     ** bcoefs,
00116 *                                 float      * wave,
00117 *                                 int          n_lines,
00118 *                                 int       ** row_clean,
00119 *                                 float     ** wavelength_clean,
00120 *                                 int        * n_found_lines,
00121 *                                 float        dispersion,
00122 *                                 int          halfWidth,
00123 *                                 float        minAmplitude,
00124 *                                 float        max_residual,
00125 *                                 float        fwhm,
00126 *                                 int          n_a_fitcoefs,
00127 *                                 int          n_b_fitcoefs,
00128 *                                 float        sigmaFactor )
00129 *
00130 *  13) cpl_image * sinfo_new_convolve_image_by_gauss( cpl_image * lineImage,
00131 *                                       int        hw )
00132 *
00133 *  14) cpl_image * sinfo_new_defined_resampling( cpl_image * image,
00134 *                                    cpl_image * calimage,
00135 *                                    int        n_params,
00136 *                                    int        n_rows,
00137 *                                    double   * dispersion,
00138 *                                    float    * minval,
00139 *                                    float    * maxval,
00140 *                                    double   * centralLambda,
00141 *                                    int      * centralpix )
00142 *
00143 *   DESCRIPTION
00144 *
00145 *   1) allocates memory for a new sinfo_vector of 
00146 *      FitParams data structures
00147 *   2) frees memory of a sinfo_vector of FitParams data structures
00148 *   3) dumps the fit parameters to an ASCII file
00149 *   4) dumps ASCII information to an allocated FitParams data structure
00150 *   5) determines the pixel shift between the line list 
00151 *      and the real image by using the beginning wavelength
00152 *      on the detector and the dispersion estimate.
00153 *   6) reads the line data of the calibration lamps
00154 *   7) fits a sinfo_gaussian to a 1-dimensional slice of an image, 
00155 *      this routine uses the routine sinfo_new_lsqfit_c as a non-linear
00156 *      least square fit method (Levenberg-Marquardt).               
00157 *   8) calculates and stores the fit parameters of the neon 
00158 *      emission lines of a neon frame by using the sinfo_linefit 
00159 *      routine.
00160 *   9) fits a second order polynom 
00161 *      lambda[i] = a1 + a2*pos[i] + a3*pos[i]^2
00162 *      to determine the connection between the listed wave-
00163 *      length values and the gauss-fitted positions for each
00164 *      image column using the singular value decomposition 
00165 *      method. 
00166 *  10) Fits the each single parameter of the three fit parameters 
00167 *      acoefs from sinfo_polyfit through the image columns
00168 *  11) this routine determines a wavelength calibration map 
00169 *      frame associating a wavelength value to each pixel
00170 *      by using the fit coefficients determined before.
00171 *  12) this routine takes an image from a calibration
00172 *      emission lamp and delivers the fit coefficients of  
00173 *      a polynomial fit across the columns 
00174 *      of the coefficients of the polynomial line position
00175 *      fits as output. Furthermore it delivers an array of the fit parameters
00176 *      as output. This routine expects Nyquist sampled spectra 
00177 *     (either an interleaved image or an image convolved with an 
00178 *      appropriate function in spectral direction)
00179 *  13) convolves an emission line image with a sinfo_gaussian
00180 *      with user given integer half width by using the eclipse 
00181 *      routine sinfo_function1d_filter_lowpass().
00182 *  14) Given a source image and a corresponding wavelength
00183 *      calibration file this routine produces an image
00184 *      in which elements in a given row are associated
00185 *      with a single wavelength. It thus corrects for 
00186 *      the wavelength shifts between adjacent elements
00187 *      in the rows of the input image. The output image
00188 *      is larger in the wavelength domain than the input
00189 *      image with pixels in each column corresponding to 
00190 *      undefined (blank, ZERO) values. The distribution
00191 *      of these undefined values varies from column to
00192 *      column. The input image is resampled at discrete
00193 *      wavelength intervals using a polynomial interpolation
00194 *      routine. 
00195 *      The wavelength intervals (dispersion) and the 
00196 *      central wavelength are defined and stable for each
00197 *      used grating. Thus, each row has a defined wavelength
00198 *      for each grating. Only the number of rows can be 
00199 *      changed by the user. 
00200 *
00201 *   FILES
00202 *
00203 *   ENVIRONMENT
00204 *
00205 *   RETURN VALUES 
00206 *
00207 *   CAUTIONS 
00208 *
00209 *   EXAMPLES
00210 *
00211 *   SEE ALSO
00212 *
00213 *   BUGS   
00214 *
00215 *------------------------------------------------------------------------
00216 */
00217 
00218 #ifdef HAVE_CONFIG_H
00219 #  include <config.h>
00220 #endif
00221 #include "sinfo_vltPort.h"
00222 
00223 /* 
00224  * System Headers
00225  */
00226 
00227 /* 
00228  * Local Headers
00229  */
00230 
00231 #include "sinfo_function_1d.h"
00232 #include "sinfo_wave_calibration.h"
00233 #include "sinfo_solve_poly_root.h"
00234 #include "sinfo_recipes.h"
00235 #include "sinfo_globals.h"
00236 #include "sinfo_svd.h"
00237 #include "sinfo_msg.h"
00238 
00239 
00255 FitParams ** sinfo_new_fit_params( int n_params )
00256 {
00257     FitParams ** new_params =NULL;
00258     FitParams  * temp_params =NULL;
00259     float * temp_fit_mem =NULL;
00260     float * temp_derv_mem=NULL;
00261     int i ;
00262 
00263     
00264     if ( n_params <= 0 )
00265     {
00266         sinfo_msg_error (" wrong number of lines to fit\n") ;
00267         return NULL ;
00268     }
00269 
00270     if (NULL==(new_params=(FitParams **) cpl_calloc ( n_params , 
00271                                          sizeof (FitParams*) ) ) )
00272     {
00273         sinfo_msg_error (" could not allocate memory\n") ;
00274         return NULL ;
00275     }
00276     if ( NULL == (temp_params = cpl_calloc ( n_params , sizeof (FitParams) ) ) )
00277     {
00278         sinfo_msg_error (" could not allocate memory\n") ;
00279         return NULL ;
00280     }
00281     if ( NULL == (temp_fit_mem = (float *) cpl_calloc( n_params*MAXPAR, 
00282                                      sizeof (float) ) ) )
00283     {
00284         sinfo_msg_error (" could not allocate memory\n") ;
00285         return NULL ;
00286     }
00287 
00288 
00289     if ( NULL == (temp_derv_mem   = 
00290              (float *) cpl_calloc( n_params*MAXPAR, sizeof (float) ) ) )
00291     {
00292         sinfo_msg_error (" could not allocate memory\n") ;
00293         return NULL ;
00294     }
00295 
00296     for ( i = 0 ; i < n_params ; i ++ )
00297     {
00298         new_params[i] = temp_params+i;
00299         new_params[i] -> fit_par    = temp_fit_mem+i*MAXPAR;
00300         new_params[i] -> derv_par   = temp_derv_mem+i*MAXPAR;
00301         new_params[i] -> column     = 0 ;
00302         new_params[i] -> line       = 0 ;
00303         new_params[i] -> wavelength = 0. ;
00304         new_params[i] -> n_params   = n_params ;
00305     }
00306 
00307     return new_params ;
00308 }
00309 
00317 void sinfo_new_destroy_fit_params ( FitParams *** params )
00318 { 
00319     
00320     if ( *params == NULL )
00321     {
00322         return ;
00323     }
00324 
00325     cpl_free ( (*params)[0] -> fit_par ) ;
00326     (*params)[0] -> fit_par=NULL;
00327     cpl_free ( (*params)[0] -> derv_par ) ;
00328     (*params)[0] -> derv_par=NULL;
00329     cpl_free ( (*params)[0] ) ;
00330     (*params)[0]=NULL;
00331     cpl_free ( (*params) ) ;
00332     (*params)=NULL;
00333 }
00334 
00343 void sinfo_new_dump_fit_params_to_ascii ( FitParams ** params, const char * filename )
00344 {
00345     FILE * fp ;
00346     int    i ;
00347 
00348     if ( NULL == params )
00349     {
00350         sinfo_msg_error (" no fit parameters available!\n") ;
00351         return ;
00352     }
00353 
00354     if ( NULL == filename )
00355     {
00356         sinfo_msg_error (" no filename available!\n") ;
00357         return ;
00358     }
00359 
00360     if ( NULL == (fp = fopen ( filename, "w" ) ) )
00361     {
00362         sinfo_msg_error(" cannot open %s\n", filename) ;
00363         return ;
00364     }
00365 
00366     for ( i = 0 ; i < params[0] -> n_params ; i++ )
00367     {
00368         fprintf(fp, "%d %d %d %f %f %f %f %f %f %f %f %f\n", 
00369                      params[i]->n_params, 
00370                      params[i]->column, 
00371                      params[i]->line, 
00372                      params[i]->wavelength, 
00373                      params[i]->fit_par[0], 
00374                      params[i]->fit_par[1], 
00375                      params[i]->fit_par[2], 
00376                      params[i]->fit_par[3],
00377                      params[i]->derv_par[0], 
00378                      params[i]->derv_par[1], 
00379                      params[i]->derv_par[2], 
00380                      params[i]->derv_par[3] ) ; 
00381     }
00382     fclose(fp) ;
00383 }
00384 
00393 void 
00394 sinfo_new_dump_ascii_to_fit_params ( FitParams ** params, char * filename )
00395 {
00396     FILE * fp ;
00397     int i ;
00398 
00399     if ( NULL == params )
00400     {
00401         sinfo_msg_error (" no fit parameters available!\n") ;
00402         return ;
00403     }
00404 
00405     if ( NULL == filename )
00406     {
00407         sinfo_msg_error (" no filename available!\n") ;
00408         return ;
00409     }
00410 
00411     if ( NULL == (fp = fopen ( filename, "r" ) ) )
00412     {
00413         sinfo_msg_error(" cannot open %s\n", filename) ;
00414         return ;
00415     }
00416     
00417     for ( i = 0 ; i < params[0]->n_params ; i++ )
00418     {
00419         fscanf(fp, "%d %d %d %f %f %f %f %f %f %f %f %f\n", 
00420                     &params[i]->n_params, 
00421                     &params[i]->column, 
00422                     &params[i]->line, 
00423                     &params[i]->wavelength, 
00424                     &params[i]->fit_par[0], 
00425                     &params[i]->fit_par[1], 
00426                     &params[i]->fit_par[2], 
00427                     &params[i]->fit_par[3],
00428                     &params[i]->derv_par[0], 
00429                     &params[i]->derv_par[1], 
00430                     &params[i]->derv_par[2], 
00431                     &params[i]->derv_par[3] ) ; 
00432     }
00433     fclose(fp) ;
00434 }
00435 
00474 int sinfo_new_find_lines(cpl_image * lineImage, 
00475                float    * wave_position, 
00476                float    * wave_intensity,
00477                int        n_lines, 
00478                int     ** row_clean,
00479                float   ** wavelength_clean,
00480                float      beginWave, 
00481                float      dispersion1,
00482                float      dispersion2,
00483                float      mindiff, 
00484                int        halfWidth,
00485                int      * n_found_lines,
00486                float      sigma,
00487                int      * sum_lines )
00488 {
00489     int     ** row ;
00490     float   ** wavelength ;
00491     float buf1, buf2 ;
00492     float meanval ;
00493     float colmedian ;
00494     float * column, * tempcol ;
00495     float * lines ;
00496     float * conv_lines ;
00497     float * wave_buffer ;
00498     float * wave_mem;
00499     int   * dummy_row ;
00500     int i, j, k, m ;
00501     int position ;
00502     int gmax, gmin ;
00503     int col ;
00504     int * row_mem;
00505     float sum ;
00506     float angst ;
00507 
00508     int lx=0;
00509     int ly=0;
00510     float* pdata=NULL;
00511 
00512     if ( NULL == lineImage )
00513     {
00514         sinfo_msg_error (" no image given\n") ;
00515         return -1 ;
00516     }
00517 
00518     lx=cpl_image_get_size_x(lineImage);
00519     ly=cpl_image_get_size_y(lineImage);
00520     pdata=cpl_image_get_data_float(lineImage);
00521 
00522     if ( n_lines <= 0 || NULL == wave_position ) 
00523     {
00524         sinfo_msg_error(" no line list given\n") ;
00525         return -1 ;
00526     }
00527     if ( NULL == wave_intensity ) 
00528     {
00529         sinfo_msg_error(" no intensity list given\n") ;
00530         return -1 ;
00531     }
00532      
00533     if ( dispersion1 == 0. )
00534     {
00535         sinfo_msg_error(" wrong dispersion given\n") ;
00536         return -1 ;
00537     }
00538    
00539     if ( row_clean == NULL )
00540     {
00541         sinfo_msg_error(" row_clean array is not allocated\n") ;
00542         return -1 ;
00543     }
00544 
00545     if ( wavelength_clean == NULL )
00546     {
00547         sinfo_msg_error(" wavelength_clean array is not allocated\n") ;
00548         return -1 ;
00549     }
00550 
00551     if ( beginWave <= 0. )
00552     {
00553         sinfo_msg_error (" impossible beginWave given\n") ;
00554         return -1 ;
00555     }
00556     if ( mindiff < -100. )
00557     {
00558         sinfo_msg_error (" wrong mindiff value\n") ;
00559         return -1 ;
00560     }
00561 
00562     if ( halfWidth <= 0 )
00563     {
00564         sinfo_msg_error(" wrong half width of fit box given\n") ;
00565         return -1 ;
00566     }
00567 
00568     if ( n_found_lines == NULL )
00569     {
00570         sinfo_msg_error(" n_found_lines not allocated\n") ;
00571         return -1 ;
00572     }
00573 
00574     if ( sigma <= 0. || sigma >= ly / 2)
00575     {
00576         sinfo_msg_error(" wrong sigma given\n") ;
00577         return -1 ;
00578     }
00579     
00580     /* allocate memory */
00581     row        = (int**) cpl_calloc( lx, sizeof(int*)) ;
00582     wavelength = (float**) cpl_calloc( lx, sizeof(float*)) ;
00583     row_mem = cpl_calloc( n_lines*lx, sizeof(int) ) ;
00584     wave_mem = cpl_calloc( n_lines*lx, sizeof(float) ) ;
00585     for ( i = 0 ; i <lx ; i++ )
00586     {
00587         row[i] = row_mem + i*n_lines;
00588         wavelength[i] = wave_mem + i*n_lines;
00589     }
00590 
00591     /* find if the wavelength is given in microns, nanometers or Angstroem */
00592     if ( wave_position[0] > 10000. )
00593     {
00594     /* Angstroem */
00595         angst = 10000. ;
00596     }
00597     else if ( wave_position[0] > 1000. && wave_position[0] < 10000. )
00598     {
00599     /* nanometers */
00600     angst = 1000. ;
00601     }
00602     else
00603     {
00604     /* microns */
00605     angst = 1. ;
00606     }
00607 
00608     /*----------------------------------------------------------------------
00609      * compute the mean and median intensity value in the given 
00610        column and determine if there is enough intensity in the column to 
00611        do the correlation
00612      */
00613     tempcol = (float*) cpl_calloc(ly, sizeof(float)) ;
00614     *sum_lines = 0 ;
00615     buf1 = 0. ;
00616     buf2 = 0. ;
00617     /* allocate memory */
00618     column      = (float*) cpl_calloc(ly, sizeof (float)) ;
00619     lines       = (float*) cpl_calloc(ly, sizeof (float)) ;
00620     conv_lines  = (float*) cpl_calloc(ly, sizeof (float)) ;
00621     wave_buffer = (float*) cpl_calloc(ly, sizeof (float)) ;
00622     dummy_row   = (int*)   cpl_calloc(n_lines, sizeof(int)) ;
00623 
00624     for ( col = 0 ; col < lx ; col++ )
00625     {
00626         n_found_lines[col] = 0 ;
00627         sum = 0. ;
00628         for ( i = 0 ; i < ly ; i++ )
00629         {
00630             if (isnan(pdata[col + i*lx]) )
00631             {
00632                 tempcol[i] = 0. ;
00633                 continue ;
00634             }
00635 
00636         sum = sum + pdata[col + i*lx] ;
00637         tempcol[i] = pdata[col + i*lx];
00638         }
00639         meanval = sum / ly ;
00640         /* lets assume the sinfo_new_median is the background */
00641         colmedian =  sinfo_new_median ( tempcol, ly);
00642 
00643         if ( meanval - colmedian < mindiff )
00644         {
00645         sinfo_msg_warning(" sorry, not enough intensity "
00646                               "(mean: %f, diff: %f) in image column: "
00647                                "%d to correlate emission lines\n", 
00648                                 meanval, meanval - colmedian,col) ;
00649         continue ;
00650     }
00651 
00652         for ( i = 0 ; i < ly ; i++ )
00653           {
00654       conv_lines[i]=0;
00655       wave_buffer[i]=0;
00656     }
00657     for ( i = 0 ; i < n_lines ; i++ )
00658     {
00659       dummy_row[i] = 0;
00660     }
00661 
00662         /* go through the column with index col */
00663         for ( i = 0 ; i < ly ; i++ )
00664         {
00665             if ( isnan(pdata[col+i*lx]) )
00666             {
00667                 column[i] = 0. ;
00668             }
00669             else
00670             {
00671                 column[i] = pdata[col + i*lx] ;
00672             }
00673 
00674             /* determine the line position on the pixels */
00675             /*lines[i] = (dispersion * (float) i + beginWave) * angst ;*/ 
00676             lines[i] = (dispersion1 * (float) (i-ly/2) + 
00677                         dispersion2 * (float) (i-ly/2) * 
00678                                       (float) (i-ly/2) + 
00679                                               beginWave) * angst ; 
00680 
00681             /* ---------------------------------------------------------------
00682              * find the nearest line position for each wavelength in the list 
00683              * and set this position to the given line intensity as weight 
00684              */
00685             for ( j = 0 ; j < n_lines ; j ++ )
00686             {
00687                 buf1 = 0. ;
00688                 buf2 = 0. ;
00689                 if ( (wave_position[j] >= (lines[i] - 
00690                       fabs(dispersion1)/2.*angst)) && 
00691                      (wave_position[j] <= (lines[i] + 
00692                       fabs(dispersion1)/2.*angst)) ) 
00693                 {
00694                     buf1 = wave_intensity[j] ; /* set the given line intensity 
00695                                                   as weight */
00696                     buf2 = wave_position[j] ;
00697                     break ;
00698                 }
00699             }
00700             lines[i] = buf1 ;
00701             wave_buffer[i] = buf2 ; /* get the wavelength associated 
00702                                        with the corresponding 
00703                                            found emission line */
00704     
00705             /* convolve the artificial spectrum by a Gaussian 
00706                with given sigma value */
00707             if ( lines[i] != 0. )
00708             {
00709                 /* consider only +- 2 sigma */
00710                 gmin = sinfo_new_nint((float) i - 2. * sigma) ;
00711                 gmax = sinfo_new_nint((float) i + 2. * sigma) ;
00712 
00713                 /* be aware of image margins */
00714                 if ( gmin < 0 )
00715                 {
00716                     gmin = 0 ;
00717                 }
00718                 if ( gmax >= ly )
00719                 {
00720                     gmax = ly - 1 ;
00721                 } 
00722                 for ( j = gmin ; j <= gmax ; j++ )
00723                 {
00724                     conv_lines[j] += 
00725                         lines[i] * exp( (double)( -0.5*((j - i)*(j - i)))/
00726                                         (double) (sigma*sigma) ) ; 
00727                 }
00728             }
00729         }
00730 
00731         /* do the cross sinfo_new_correlitioation */
00732         position = INT32_MAX ;
00733         position = sinfo_new_correlation(column+5, conv_lines+5, ly-10 ) ; 
00734         if ( abs (position) > ly / 4 )
00735         {
00736             sinfo_msg_warning(" sorry, shift of artificial data relative to"
00737                               " image (%d) seems to be too high in column: %d",
00738                               position, col) ;
00739             continue ;
00740         }
00741 
00742         //AMO we initialize this to -999 and later check that it is not
00743         //-999 to prevent an invalid read out due to the fact that not
00744         //all elements of row are filled by the the loop below
00745         for ( j = 0 ; j < n_lines ; j ++ ) {
00746           row[col][j] = -999;
00747     }
00748 
00749         //The following loop does not fill all elements
00750         j = 0 ;
00751         for ( i = 0 ; i < ly ; i ++ )
00752         {
00753             if ( lines[i] != 0.0 )
00754             {
00755                 if ( (i - position) >= 0 && (i - position) < ly )
00756                 {
00757                     row[col][j] = i - position ;
00758                     /* get the wavelength corresponding to 
00759                        found line row index */
00760                     wavelength[col][j] = wave_buffer[i] / angst ;
00761                     j++ ;
00762                 }
00763             }
00764         }
00765 
00766 
00767         /* ------------------------------------------------------------------
00768          *  determine the row_clean array, that means, take only the row 
00769             values if the distance between adjacent lines is large enough 
00770             for the fit
00771          */
00772         //sinfo_msg("lx=%d",lx);
00773         for ( k = 1 ; k <= j && k<(lx-1); k ++ )
00774         {
00775             if (dummy_row[k-1] != -1)
00776             {
00777                 dummy_row[k-1] = row[col][k-1] ;
00778             }
00779             if ( (row[col][k] - row[col][k-1]) <= 2*halfWidth )
00780             {
00781                 dummy_row[k-1] = -1 ;
00782         if (k<n_lines) {
00783                   dummy_row[k]   = -1 ;
00784         }
00785             }
00786             /* the following gives invalid read size 4: check that k+1<lx */
00787             
00788             //sinfo_msg("col=%d k=%d row1=%d row2=%d",
00789             //           col,k,row[col][k+1],row[col][k]);
00790             if ( (row[col][j] != -999) && 
00791                  (row[col][k+1] - row[col][k]) <= 2*halfWidth)
00792             {
00793           if (k<n_lines) {
00794                   dummy_row[k]   = -1 ;
00795           }
00796           if (k+1<n_lines) {
00797                   dummy_row[k+1] = -1 ;
00798           }
00799             }
00800         }
00801 
00802         m = 0 ;
00803         for ( k = 0 ; k < j ; k ++ )
00804         {
00805             if ( dummy_row[k] != -1 && dummy_row[k] != 0 )
00806             {
00807                 row_clean[col][m] = dummy_row[k] ;
00808                 wavelength_clean[col][m] = wavelength[col][k] ;
00809                 m ++ ;
00810             }
00811         }
00812 
00813         n_found_lines[col] = m ;
00814 
00815         *sum_lines += n_found_lines[col] ;
00816     }
00817     cpl_free (column) ;
00818     cpl_free (lines) ;
00819     cpl_free (conv_lines) ;
00820     cpl_free (dummy_row) ;
00821     cpl_free (wave_buffer) ;
00822     cpl_free (row_mem) ;
00823     cpl_free (wave_mem) ;
00824     cpl_free (tempcol) ;
00825     cpl_free (row) ;
00826     cpl_free (wavelength) ;
00827 
00828     return 0 ;
00829 }
00830 
00840 int 
00841 sinfo_new_read_list( char * listname, 
00842                      float * lineCenter, 
00843                      float * lineIntensity )
00844 {
00845     FILE * fp ;
00846     int i, n_lines ;
00847     
00848     if ( NULL == lineCenter )
00849     {
00850         sinfo_msg_error(" lineCenter array is not allocated\n") ;
00851         return -1 ;
00852     }
00853 
00854     if ( NULL == lineIntensity )
00855     {
00856         sinfo_msg_error(" lineIntensity array is not allocated\n") ;
00857         return -1 ;
00858     }
00859 
00860     if ( NULL == (fp = fopen ( listname, "r" ) ) )
00861     {
00862         sinfo_msg_error(" cannot open %s\n", listname) ;
00863         return -1 ;
00864     }
00865 
00866     i = 0 ;
00867     while ( fscanf( fp, "%f %f", &lineCenter[i], &lineIntensity[i] ) != EOF )
00868     {
00869         i ++ ;
00870     }
00871     n_lines = i ;
00872     fclose(fp) ;
00873            
00874     return n_lines ;
00875 }
00876 
00877 
00909 int sinfo_new_line_fit ( cpl_image  *  mergedImage, 
00910               FitParams *  par,
00911               float        fwhm,
00912               int          lineInd,
00913               int          column, 
00914               int          halfWidth, 
00915               int          lineRow,
00916               float        min_amplitude,
00917           Vector    *  line,
00918           int       *  mpar,
00919           float     *  xdat,
00920           float     *  wdat )
00921 {
00922     int i, j ;
00923     int iters, xdim, ndat ;
00924     int numpar, its ;
00925     int position ;
00926     float maxval, tol, lab ;
00927     int lx=0;
00928     int ly=0;
00929     float* pdata=NULL;
00930 
00931     if ( mergedImage == NULL )
00932     {
00933         sinfo_msg_error (" no image given as input\n") ;
00934         return -8 ;
00935     }
00936     lx=cpl_image_get_size_x(mergedImage);
00937     ly=cpl_image_get_size_y(mergedImage);
00938     pdata=cpl_image_get_data_float(mergedImage);
00939 
00940 
00941     if ( par == NULL )
00942     {
00943         sinfo_msg_error(" fit parameters not given\n") ;
00944         return -9 ;
00945     }
00946     if ( column < 0 || column > lx )
00947     {
00948         sinfo_msg_error (" wrong column number\n") ;
00949         return -10 ;
00950     }
00951     if ( halfWidth < 0 || halfWidth > ly )
00952     {
00953         sinfo_msg_error (" wrong width given\n") ;
00954         return -11 ;
00955     }
00956     if ( lineRow < 0 || lineRow > ly )
00957     {
00958         sinfo_msg_error (" wrong number of row of the line given\n") ;
00959         return -12 ;
00960     }
00961     if ( min_amplitude < 1. )
00962     {
00963         sinfo_msg_error (" wrong minimum amplitude\n") ;
00964         return -13 ;
00965     }
00966     
00967     /* initialise the Vector */
00968     for ( i = 0 ; i < line -> n_elements ; i++) 
00969     {
00970         line->data[i] = 0;
00971     }
00972     
00973     par -> column = column  ;
00974     par -> line   = lineInd ;
00975 
00976     /* determine the values of the spectral sinfo_vector given as input */
00977     /* go through the chosen column */
00978 
00979     j = 0 ;
00980     for ( i = lineRow-halfWidth ; i <= lineRow+halfWidth ; i++ ) 
00981     {
00982         if ( i < 0 || i >= ly )
00983         {
00984             sinfo_msg_error (" wrong line position or width given\n") ;
00985             return -15 ;
00986         }
00987         else
00988         {
00989             line -> data[j] = pdata[column + i*lx] ;
00990             j ++ ;
00991         }
00992     } 
00993 
00994     /*-------------------------------------------------------------------- 
00995      * go through the spectral sinfo_vector 
00996      * determine the maximum pixel value in the spectral sinfo_vector 
00997      */
00998     maxval = -FLT_MAX ;
00999     position = -INT32_MAX ;
01000     for ( i = 0 ; i < line -> n_elements ; i++ )
01001     {
01002         xdat[i] = i ;
01003         wdat[i] = 1.0 ;
01004         if ( line -> data[i] >= maxval )
01005         {
01006             maxval = line -> data[i] ;
01007             position = i ;
01008         }
01009     }
01010 
01011     /* set initial values for the fitting routine */
01012     xdim     = XDIM ;
01013     ndat     = line -> n_elements ;
01014     numpar   = MAXPAR ;
01015     tol      = TOL ;
01016     lab      = LAB ;
01017     its      = ITS ;
01018     par -> fit_par[1] = fwhm ;
01019     par -> fit_par[2] = (float) position ;
01020     par -> fit_par[3] = (float) (line -> data[0] + 
01021                                  line -> data[line->n_elements - 1]) / 2.0 ;
01022     par -> fit_par[0]  = maxval - (par -> fit_par[3]) ;
01023 
01024     /* exclude low signal cases */
01025     if ( par->fit_par[0] < min_amplitude )
01026     {
01027         cpl_msg_debug ("sinfo_linefit:",
01028                        " sorry, amplitude of line too low to fit: %f",
01029                        par->fit_par[0] ) ;
01030         return -16 ;
01031     }
01032 
01033     for ( i = 0 ; i < MAXPAR ; i++ )
01034     {
01035         par -> derv_par[i] = 0.0 ;
01036         mpar[i] = 1 ;
01037     }
01038 
01039     /* finally, do the least square fit using a sinfo_gaussian */
01040     if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim, 
01041                                            line -> data, wdat, 
01042                                            &ndat, par -> fit_par,  
01043                                            par -> derv_par, mpar, 
01044                                            &numpar, &tol, &its, &lab )) )  
01045     {
01046         cpl_msg_debug ("sinfo_linefit:",
01047                        " sinfo_new_lsqfit_c: least squares fit failed,"
01048                        " error no.: %d\n", iters) ; 
01049         return -17 ;
01050     }
01051 
01052     /* correct the fitted position for the given row of the 
01053        line in image coordinates */
01054     par -> fit_par[2] =  (float) (lineRow - halfWidth) + par -> fit_par[2] ;
01055 
01056     /* all was o.k. */
01057     return iters ;
01058 }
01059 
01084 int sinfo_new_fit_lines ( cpl_image  *  line_image, 
01085                FitParams ** allParams,
01086                float        fwhm,
01087                int       *  n_lines, 
01088                int       ** row,
01089                float     ** wavelength, 
01090                int          width,
01091                float        min_amplitude ) 
01092 {
01093     int i, k, l ;
01094     int result ;
01095     Vector * line;
01096     int    * mpar;
01097     float  * xdat, * wdat;
01098     int lx=0;
01099     int ly=0;
01100     float* pdata=NULL;
01101 
01102     if ( line_image == NULL )
01103     {
01104         sinfo_msg_error (" no image given\n") ;
01105         return -18 ;
01106     }
01107     lx=cpl_image_get_size_x(line_image);
01108     ly=cpl_image_get_size_y(line_image);
01109     pdata=cpl_image_get_data_float(line_image);
01110 
01111     if ( n_lines == NULL )
01112     {
01113         sinfo_msg_error (" no counter of emission lines\n") ;
01114         return -19 ;
01115     } 
01116     if ( row == NULL || width <= 0 )
01117     {
01118         sinfo_msg_error (" row or width vectors are empty\n") ;
01119         return -20 ;
01120     }
01121     if ( wavelength == NULL )
01122     {
01123         sinfo_msg_error (" no wavelength array given\n") ;
01124         return -21 ;
01125     }
01126 
01127     k = 0 ;
01128 
01129     /* allocate memory for the spectral sinfo_vector */
01130     line = sinfo_new_vector (2*width + 1) ;
01131     /* allocate memory */
01132     xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
01133     wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
01134     mpar = (int *)   cpl_calloc( MAXPAR, sizeof (int) ) ;
01135     
01136     /* go through the columns */
01137     for ( i = 0 ; i < lx ; i++ )
01138     {
01139         if ( n_lines[i] == 0 )
01140         {
01141             continue ;
01142         }
01143         /* go through the emission lines in a column */
01144         for ( l = 0 ; l < n_lines[i] ; l++ )
01145         {
01146             if ( row[i][l] <= 0 )
01147             {
01148                 continue ;
01149             }
01150 
01151             /* --------------------------------------------------------------
01152              * fit the single lines using sinfo_linefit and store the 
01153                parameters in
01154              * an array of the FitParams data structure allParams[].
01155              */ 
01156             if ( (result = sinfo_new_line_fit ( line_image, 
01157                                                 allParams[k], fwhm, l, i, 
01158                                                 width, row[i][l], 
01159                                                 min_amplitude,line,mpar,
01160                                                 xdat,wdat ) ) < 0 )
01161             {
01162                 cpl_msg_debug ("sinfo_fitLines:",
01163                                " sinfo_linefit failed, error no.: %d,"
01164                                " column: %d, row: %d, line: %d\n", 
01165                                result, i, row[i][l], l) ;
01166                 continue ;
01167             }
01168             if ( (allParams[k] -> fit_par[0] <= 0.) || 
01169                  (allParams[k] -> fit_par[1] <= 0.)
01170                   || (allParams[k] -> fit_par[2] <= 0.) )
01171             {
01172                 sinfo_msg_warning (" negative fit parameters in column: %d,"
01173                                    " line: %d\n", i, l) ;
01174                 continue ;
01175             }
01176             allParams[k] -> wavelength = wavelength[i][l] ;
01177             k++ ;
01178         }
01179     }
01180 
01181     /* free memory */
01182     sinfo_new_destroy_vector(line);
01183     cpl_free(xdat);
01184     cpl_free(wdat);
01185     cpl_free(mpar);
01186     
01187     /* all is o.k. */
01188     return k ;
01189 }    
01190 
01218 float sinfo_new_polyfit( FitParams ** par,
01219                int          column,
01220                int          n_lines,
01221                int          n_rows,
01222                float        dispersion,
01223                float        max_residual,
01224                float *      acoefs,
01225                float *      dacoefs,
01226                int   *      n_reject,
01227                int          n_fitcoefs )
01228 {
01229     float ** ucoefs, ** vcoefs, ** covar ;
01230     float *mem;
01231     float * lambda, * posit ;
01232     float * weight, * resid ;
01233     float * newlam, * newpos, * newwet ;
01234     float * wcoefs=NULL ;
01235     float chisq, result ;
01236     float offset ;
01237     int num, found ;
01238     int i, j, k, n ;
01239 
01240     /* reset the fit coefficients and their errors */
01241     for ( i = 0 ; i < n_fitcoefs ; i++ )
01242     {
01243         acoefs[i]  = 0. ;
01244         dacoefs[i] = 0. ;
01245     }
01246     if ( NULL == par )
01247     {
01248         sinfo_msg_error(" no fit params given\n");
01249         return FLT_MAX ;
01250     }
01251 
01252     if ( 0 >= n_lines )
01253     {
01254       /*
01255         sinfo_msg_warning (" sorry, number of lines is wrong") ;
01256       */
01257         return FLT_MAX ;
01258     }
01259     if ( 0 >= n_rows )
01260     {
01261         sinfo_msg_error (" sorry, number of rows is wrong") ;
01262         return FLT_MAX ;
01263     }
01264     if ( dispersion == 0. )
01265     {
01266         sinfo_msg_error (" sorry, wrong dispersion given") ;
01267         return FLT_MAX ;
01268     }
01269 
01270     offset = (float)(n_rows - 1)/2. ;
01271 
01272     /* allocate memory */
01273     
01274     mem = (float*) cpl_calloc( n_lines*7, sizeof (float) ) ;
01275     lambda = mem;
01276     posit  = mem + n_lines;
01277     weight = mem + n_lines*2;
01278     resid  = mem + n_lines*3;
01279     newlam = mem + n_lines*4;
01280     newpos = mem + n_lines*5;
01281     newwet = mem + n_lines*6;
01282     
01283     /*lambda = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
01284     posit  = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
01285     weight = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
01286     resid  = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
01287     newlam = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
01288     newpos = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
01289     newwet = (float*) cpl_calloc( n_lines, sizeof (float) ) ;*/
01290 
01291     /* allocate coefficient matrices*/
01292     ucoefs = sinfo_matrix ( 1, n_lines, 1, n_fitcoefs ) ;
01293     vcoefs = sinfo_matrix ( 1, n_lines, 1, n_fitcoefs ) ;
01294     covar  = sinfo_matrix ( 1, n_fitcoefs, 1, n_fitcoefs ) ;
01295     wcoefs=cpl_calloc(n_fitcoefs,sizeof(float)) ;
01296 
01297     /* go through all fit parameters */
01298     n = 0 ;
01299     for ( i = 0 ; i < (par[0] -> n_params) ; i ++ )
01300     {
01301         found = -1 ;
01302         /* find the given column and go through the lines in that column */
01303         for ( j = 0 ; j < n_lines ; j ++ )
01304         {
01305             if ( (par[i] -> column == column) && (par[i] -> line == j) )
01306             {
01307                 found = i ;
01308             }
01309             else
01310             {
01311                 continue ;
01312             }
01313 
01314             /* store only fit params with reasonable values */
01315             if ( par[found] -> derv_par[2] != 0. && 
01316                  par[found] -> fit_par[2] > 0. &&
01317                  par[found] -> wavelength > 0. && 
01318                  par[found] -> fit_par[1] > 0. &&
01319                  par[found] -> fit_par[0] > 0. )
01320             {
01321                 /* ----------------------------------------------------------
01322                  * store the found position, error of the position as 
01323                    weight and the associated
01324                  * wavelength values of the fitted lines
01325                  */
01326                 posit[n]  = par[found] -> fit_par[2] ;
01327                 weight[n] = par[found] -> derv_par[2] ;
01328                 lambda[n] = par[found] -> wavelength ;
01329                 n ++ ;
01330             }
01331             else
01332             {
01333                 continue ;
01334             }
01335         }
01336 
01337     }
01338 
01339     num = n ;
01340     if ( num < n_fitcoefs )
01341     {
01342         sinfo_msg_warning("not enough lines found in column %d to "
01343                           "determine the three coefficients.\n", column) ;
01344         for ( i = 0 ; i < n_fitcoefs ; i++ )
01345         {
01346             acoefs[i]  = ZERO ;
01347             dacoefs[i] = ZERO ;
01348         }
01349         sinfo_free_matrix ( ucoefs, 1/*, n_lines*/,    1/*, n_fitcoefs*/ ) ;
01350         sinfo_free_matrix ( vcoefs, 1/*, n_lines*/,    1/*, n_fitcoefs*/ ) ;
01351         sinfo_free_matrix ( covar,  1/*, n_fitcoefs*/, 1/*, n_fitcoefs*/ ) ;
01352         /*cpl_free (lambda) ;
01353         cpl_free (posit) ;
01354         cpl_free (weight) ;
01355         cpl_free (resid) ;
01356         cpl_free (newlam) ;
01357         cpl_free (newpos) ;
01358         cpl_free (newwet) ;*/
01359     cpl_free (mem);
01360         return FLT_MAX ;
01361     }
01362 
01363     /*-------------------------------------------------------------------------
01364      * scale the pixel position values to smaller than 1 and transform 
01365        the weights to wavelength units 
01366      */
01367 
01368     for ( i = 0 ; i < num ; i ++ )
01369     {
01370         posit[i] = (posit[i] - offset)/offset ;
01371         weight[i] *= fabs(dispersion) ;
01372     }
01373 
01374     /* do the fit using the singular value decomposition method */
01375     sinfo_svd_fitting( posit - 1, lambda - 1, 
01376                       weight - 1, num, acoefs-1, n_fitcoefs,
01377             ucoefs, vcoefs, wcoefs-1, covar, &chisq, sinfo_fpol ) ;
01378 
01379     /* scale the linear and the quadratic coefficient */
01380     for ( i = 1 ; i < n_fitcoefs ; i++ )
01381     {
01382         acoefs[i] /= pow(offset, i) ;
01383     }
01384 
01385     /* now that we have determined the fit coefficients, find the residuals */
01386     *n_reject = 0 ;
01387 
01388     j = 0 ;
01389     for ( i = 0 ; i < num ; i++ )
01390     {
01391         result = 0. ;
01392         for ( k = 0 ; k < n_fitcoefs ; k++ )
01393         {
01394             result += acoefs[k] * pow(posit[i], k) ;
01395         }
01396 
01397         resid[i] = lambda[i] - result ;
01398 
01399         if ( fabs( resid[i] ) > max_residual)
01400         {
01401             (*n_reject) ++ ;
01402         }
01403         else
01404         {
01405             newlam[j] = lambda[i] ;
01406             newpos[j] = posit[i] ;
01407             newwet[j] = weight[i] ;
01408             j++ ;
01409         }
01410     }
01411 
01412     num = j ;
01413     if ( num >= n_fitcoefs )
01414     {
01415         sinfo_svd_fitting( newpos - 1, newlam - 1, 
01416                            newwet - 1, num, acoefs-1, n_fitcoefs, ucoefs,
01417                 vcoefs, wcoefs-1, covar, &chisq, sinfo_fpol ) ;
01418 
01419         /* scale the resulting coefficients */
01420         for ( i = 0 ; i < n_fitcoefs ; i++ )
01421         {
01422             acoefs[i] /= pow(offset, i) ;
01423             dacoefs[i] = sqrt( (double) covar[i+1][i+1] ) / pow(offset, i) ;
01424         }
01425     }
01426     else
01427     {
01428         sinfo_msg_warning (" too many lines rejected (number: %d) "
01429                            "due to high residuals, fit coefficients are set "
01430                            "zero, in column: %d\n", *n_reject, column) ;
01431         for ( i = 0 ; i < n_fitcoefs ; i++ )
01432         {
01433             acoefs[i]  = ZERO ;
01434             dacoefs[i] = ZERO ;
01435         }
01436     }
01437 
01438     sinfo_free_matrix ( ucoefs, 1/*, n_lines*/,    1/*, n_fitcoefs*/ ) ;
01439     sinfo_free_matrix ( vcoefs, 1/*, n_lines*/,    1/*, n_fitcoefs*/ ) ;
01440     sinfo_free_matrix ( covar,  1/*, n_fitcoefs*/, 1/*, n_fitcoefs*/ ) ;
01441     /*cpl_free (lambda) ;
01442     cpl_free (posit) ;
01443     cpl_free (weight) ;
01444     cpl_free (resid) ;
01445     cpl_free (newlam) ;
01446     cpl_free (newpos) ;
01447     cpl_free (newwet) ;*/
01448     cpl_free (mem);
01449     cpl_free(wcoefs) ;
01450 
01451     return chisq ;
01452 }
01453 
01470 float sinfo_new_coefs_cross_fit ( int      n_columns,
01471                       float *  acoefs,
01472                       float *  dacoefs,
01473                       float *  bcoefs,
01474                       int      n_fitcoefs,
01475                       float    sigma_factor )
01476 {
01477     float col_index;
01478     float* sub_col_index=NULL ;
01479     float* sub_acoefs=NULL ;
01480     float* sub_dacoefs=NULL ;
01481     float* wcoefs=NULL ;
01482     float ** ucoefs, **vcoefs, **covar ;
01483     float chisq ;
01484     float * acoefsclean ;
01485     double sum, sumq, mean ;
01486     double sigma ;
01487     double cliphi, cliplo ;
01488     float offset ;
01489     int i, n, num, ndata ;
01490     int nc ;
01491 
01492 
01493     if ( n_columns < 1 )
01494     {
01495         sinfo_msg_error(" wrong number of image columns given\n") ;
01496         return FLT_MAX ;
01497     }
01498     if ( acoefs == NULL || dacoefs == NULL )
01499     {
01500         sinfo_msg_error(" coeffs or errors of coefficients are not given\n") ;
01501         return FLT_MAX ;
01502     }
01503     if ( bcoefs == NULL )
01504     {
01505         sinfo_msg_error(" coeffs are not allocated\n") ;
01506         return FLT_MAX ;
01507     }
01508 
01509     if ( n_fitcoefs < 1 )
01510     {
01511         sinfo_msg_error(" wrong number of fit coefficients\n") ;
01512         return FLT_MAX ;
01513     }
01514     if ( sigma_factor <= 0. )
01515     {
01516         sinfo_msg_error(" impossible sigma_factor given!\n") ;
01517         return FLT_MAX ;
01518     }
01519 
01520     offset = (float)(n_columns - 1) / 2. ;
01521 
01522     /* ----------------------------------------------------------
01523      * determine the clean mean and sigma value of the coefficients,
01524      * that means reject 10 % of the extreme low and high values
01525      */
01526 
01527     wcoefs=cpl_calloc(n_fitcoefs,sizeof(float)) ;
01528 
01529     nc = 0 ;
01530     for ( i = 0 ; i < n_columns ; i++ )
01531     {
01532         if ( isnan(acoefs[i]) || acoefs[i] == 0. || dacoefs[i] == 0. )
01533         {
01534             continue ;
01535         }
01536         else
01537         {
01538             nc++ ;
01539         }
01540     }
01541     acoefsclean = (float*) cpl_calloc(nc , sizeof(float)) ;
01542     nc = 0 ;
01543     for ( i = 0 ; i < n_columns ; i++ )
01544     {
01545         if ( isnan(acoefs[i]) || acoefs[i] == 0. || dacoefs[i] == 0. )
01546         {
01547             continue ;
01548         }
01549         else
01550         {
01551             acoefsclean[nc] = acoefs[i] ;
01552             nc++ ;
01553         }
01554     }
01555     sinfo_pixel_qsort(acoefsclean, nc) ;
01556     sum   = 0. ;
01557     sumq  = 0. ;
01558     mean  = 0. ;
01559     sigma = 0. ;
01560     n     = 0 ;
01561     for ( i = (int)((float)nc*LOW_REJECT) ; 
01562           i < (int)((float)nc*HIGH_REJECT) ; i++ )
01563     {
01564         sum  += (double)acoefsclean[i] ;
01565         sumq += ((double)acoefsclean[i] * (double)acoefsclean[i]) ;
01566         n ++ ;
01567     }
01568     mean          = sum/(double)n ;
01569     sigma         = sqrt( sumq/(double)n - (mean * mean) ) ;
01570     cliphi        = mean + sigma * (double)sigma_factor ;
01571     cliplo        = mean - sigma * (double)sigma_factor ;
01572 
01573     sub_col_index=cpl_calloc(n_columns,sizeof(float)) ;
01574     sub_acoefs=cpl_calloc(n_columns,sizeof(float));
01575     sub_dacoefs=cpl_calloc(n_columns,sizeof(float)) ;
01576 
01577     /* fit only the reasonnable values */
01578     num = 0 ;
01579     for ( i = 0 ; i < n_columns ; i++ )
01580     {
01581         /* associate the column indices to the corresponding array */
01582         col_index = (float) i ;
01583 
01584         /* take only the reasonnable coefficients */
01585         if ( !isnan(acoefs[i]) && 
01586              (acoefs[i] <= cliphi) && (acoefs[i] >= cliplo) &&
01587              (dacoefs[i] != 0. ) && (acoefs[i] != 0.) )
01588         {
01589             sub_acoefs[num]    = acoefs[i] ;
01590             sub_dacoefs[num]   = dacoefs[i] ;
01591             sub_col_index[num] = col_index ;
01592             num ++ ;
01593         }
01594     }
01595     ndata = num ;
01596 
01597     if ( ndata < n_fitcoefs )
01598     {
01599         sinfo_msg_error("not enough data found to determine "
01600                         "the fit coefficients.\n") ;
01601 
01602         return FLT_MAX ;
01603     }
01604 
01605     /* allocate coefficient matrices */
01606     ucoefs = sinfo_matrix(1, ndata, 1, n_fitcoefs) ;
01607     vcoefs = sinfo_matrix(1, ndata, 1, n_fitcoefs) ;
01608     covar  = sinfo_matrix ( 1, n_fitcoefs, 1, n_fitcoefs ) ;
01609 
01610     /* scale the x-values for the fit */
01611     for ( i = 0 ; i < ndata ; i++ )
01612     {
01613         sub_col_index[i] = (sub_col_index[i] - offset) / offset ;
01614     }
01615 
01616     /* finally, do the singular value decomposition fit */
01617     sinfo_svd_fitting ( sub_col_index-1, sub_acoefs-1, 
01618                         sub_dacoefs-1, ndata, bcoefs-1,
01619                         n_fitcoefs, ucoefs, vcoefs, 
01620                         wcoefs-1, covar, &chisq, sinfo_fpol ) ;
01621 
01622     /* scale the found coefficients */
01623     for ( i = 0 ; i < n_fitcoefs ; i ++ )
01624     {
01625         bcoefs[i] /= pow(offset, i) ;
01626     }
01627 
01628     /* free memory */
01629     cpl_free (acoefsclean) ;
01630     sinfo_free_matrix( ucoefs, 1/*, ndata*/, 1/*, n_fitcoefs */) ;
01631     sinfo_free_matrix( vcoefs, 1/*, ndata*/, 1/*, n_fitcoefs */) ;
01632     sinfo_free_matrix ( covar, 1/*, n_fitcoefs*/, 1/*, n_fitcoefs*/ ) ;
01633 
01634     cpl_free(sub_col_index) ;
01635     cpl_free(sub_acoefs) ;
01636     cpl_free(sub_dacoefs) ;
01637     cpl_free(wcoefs) ;
01638 
01639     return chisq ;
01640 }
01641 
01642 
01662 cpl_image * sinfo_new_wave_map( cpl_image * lineImage,
01663                     float   ** bcoefs,
01664                     int        n_a_fitcoefs,
01665                     int        n_b_fitcoefs,
01666                     float    * wavelength,
01667                     float    * intensity,
01668                     int        n_lines,
01669                     int        magFactor)
01670 {
01671     cpl_image * retImage ;
01672     float cenpos, cenpix ;
01673     float centreval, centrepix, wavelag ;
01674     float  pixvalue ;
01675     float a_initial ;
01676     int i, j, k, l/*, m*/, line, col, row, found, sign ;
01677     int var, maxlag, cmin, cmax, offset ;
01678     double * result ;
01679     float col_off ;
01680     float angst ;
01681     double xcorr_max ;
01682     int delta ;
01683 
01684     double* z=NULL ;
01685     double* a=NULL ;
01686     double*  wave=NULL ;
01687     float* emline=NULL ;
01688     float* spec=NULL ;
01689     int ilx=0;
01690     int ily=0;
01691     int olx=0;
01692     int oly=0;
01693     float* pidata=NULL;
01694     float* podata=NULL;
01695 
01696 
01697     gsl_poly_complex_workspace * w ;
01698     
01699     if ( NULL == lineImage )
01700     {
01701         sinfo_msg_error("no image given\n") ;
01702         return NULL ;
01703     }
01704     ilx=cpl_image_get_size_x(lineImage);
01705     ily=cpl_image_get_size_y(lineImage);
01706     pidata=cpl_image_get_data_float(lineImage);
01707 
01708     if ( NULL == wavelength || n_lines <= 0 )
01709     {
01710         sinfo_msg_error("no wavelength list given\n") ;
01711         return NULL ;
01712     }
01713 
01714     if ( NULL == intensity )
01715     {
01716         sinfo_msg_error("no intensity list given\n") ;
01717         return NULL ;
01718     }
01719 
01720     if ( NULL == bcoefs )
01721     {
01722         sinfo_msg_error("no coefficients given\n") ;
01723         return NULL ;
01724     }
01725 
01726     if ( magFactor <= 1 )
01727     {
01728         sinfo_msg_error("wrong magnifying factor given\n") ;
01729         return NULL ;
01730     }
01731     
01732     /* allocate memory */
01733     if ( NULL == ( retImage = cpl_image_new( ilx, ily,CPL_TYPE_FLOAT ) ))
01734     {
01735         sinfo_msg_error("cannot allocate a new image\n");
01736         return NULL ;
01737     }
01738     olx=cpl_image_get_size_x(retImage);
01739     oly=cpl_image_get_size_y(retImage);
01740     podata=cpl_image_get_data_float(retImage);
01741 
01742 
01743     var    = (magFactor - 1)*(magFactor - 1) ;
01744     offset = ily * (magFactor/4 + 1) ;
01745 
01746     /* find out if Angstroem or microns are used */
01747     if ( wavelength[0] > 10000. )
01748     {
01749     /* Angstroem */
01750         angst = 10000. ;
01751     }
01752     else if ( wavelength[0] > 1000. && wavelength[0] < 10000. )
01753     {
01754     /* nanometers */
01755     angst = 1000. ;
01756     }
01757     else
01758     {
01759     /* microns */
01760     angst = 1. ;
01761     }
01762 
01763     z=cpl_calloc(2*(n_a_fitcoefs - 1),sizeof(double)) ;
01764     a=cpl_calloc(n_a_fitcoefs,sizeof(double));
01765     wave=cpl_calloc(n_lines,sizeof(double)) ;
01766     emline=cpl_calloc(2*magFactor*ily,sizeof(float));
01767     spec=cpl_calloc(2*magFactor*ily,sizeof(float)) ;
01768 
01769     /* go through the image columns */
01770     for ( col = 0 ; col < ilx ; col++ )
01771     {
01772         /* initialize the emline array for each column */
01773         for ( i = 0 ; i < 2*magFactor*ily ; i++ )
01774         {
01775             emline[i] = 0. ;
01776         }
01777         col_off = (float)col - (float)(ilx-1)/2. ;
01778 
01779         /* determine the coefficients by using the given bcoefs */
01780         for ( i = 0 ; i < n_a_fitcoefs ; i++ ) 
01781         {
01782             /* initialize coefficients and solution */
01783             a[i] = 0. ;
01784             if (i < n_a_fitcoefs-1)
01785             {
01786                 z[2*i] = 0. ;
01787                 z[2*i+1] = 0. ;
01788             }
01789             for ( j = 0 ; j < n_b_fitcoefs ; j++ )
01790             {
01791                 a[i] += bcoefs[i][j] * pow(col_off, j) ;
01792             }
01793         }
01794         a_initial = a[0] ;
01795         
01796         /* go through the lines and generate an artificial spectrum */
01797         for ( line = 0 ; line < n_lines ; line++ )
01798         {
01799             /* go from Angstroem to micron */
01800             wave[line] = wavelength[line]/angst ;
01801 
01802             /* ---------------------------------------------------------------
01803              * solve the polynomial for the exact offset of the line that means
01804              * find the root of the polynomial of order n_fitcoefs - 1
01805              */
01806             a[0] = a_initial - wave[line] ;
01807 
01808             if(NULL==(w=sinfo_gsl_poly_complex_workspace_alloc(n_a_fitcoefs)))
01809             {
01810                 sinfo_msg_error("could not allocate complex workspace!") ;
01811                 cpl_image_delete(retImage) ;
01812                 return NULL ;
01813             }
01814             if (-1 == sinfo_gsl_poly_complex_solve(a, n_a_fitcoefs, w, z))
01815             {
01816                 sinfo_msg_error("sinfo_gsl_poly_complex_solve did not work!") ;
01817                 cpl_image_delete(retImage) ;
01818                 return NULL ;
01819             }
01820             sinfo_gsl_poly_complex_workspace_free(w) ;
01821 
01822             
01823             j = 0 ;
01824             found = -1 ;
01825             for ( i = 0 ; i < n_a_fitcoefs - 1  ; i++ )
01826             {
01827                 /* test for appropriate solution */
01828                 if( z[2*i] > (-1.)*(float) ily/2. && 
01829                     z[2*i] < (float)ily/2. && z[2*i+1] == 0. )
01830                 {
01831                     found = 2*i ;
01832                     j ++ ;
01833                 }
01834                 else
01835                 {
01836                     continue ;
01837                 } 
01838             }
01839             if ( j == 0 )
01840             {
01841                 sinfo_msg_warning("no offset solution found "
01842                                   "for line %d in column %d\n", line, col) ;
01843                 continue ;
01844             } 
01845             else if ( j == 1 )
01846             {
01847                 cenpos = z[found] + (float) ily /2. ;
01848             }
01849             else
01850             {
01851                 sinfo_msg_warning("two or more offset solutions found "
01852                                   "for line %d in column %d\n", line, col) ;
01853                 continue ;
01854             }
01855              
01856             /*---------------------------------------------------------------
01857              * magnify image by the given factor add an additional offset 
01858              */
01859             cenpix = cenpos * (float) magFactor + (float) offset ;  
01860             
01861             /* determine max and min pixel limits over 
01862                which line should be convolved */
01863             cmin = (sinfo_new_nint(cenpix) - (var-1)) > 0 ? 
01864                     sinfo_new_nint(cenpix) - (var-1) : 0 ;
01865             cmax = (sinfo_new_nint(cenpix) + (var-1)) < 2*magFactor * ily ? 
01866                     sinfo_new_nint(cenpix) + (var-1) :  2*magFactor * ily ;
01867 
01868             /* convolve neon lines with Gaussian function */
01869             for ( j = cmin ; j < cmax ; j++ )
01870             {
01871                 emline[j] += intensity[line] * 
01872                 exp((double)(-0.5*(j-cenpix)*(j-cenpix))/(double)var) ;
01873             }
01874         }
01875                 
01876         /*--------------------------------------------------------------------- 
01877          * for each column, map the image data points onto an magFactor times 
01878            bigger element grid for FFT in the cross sinfo_new_correlation, 
01879            first initialize the two helping arrays for each new column.
01880          */
01881         for ( k = 0 ; k < 2*magFactor * ily ; k++ )
01882         {
01883             spec[k] =  0. ;
01884         }
01885    
01886         /* now take the image data points of the column and put them 
01887            into the spec array */
01888         for ( row = 0 ; row < ily ; row++ ) /* go through the column */
01889         {
01890             /* insert 8 values for each image row (magnification) and 
01891                add same offset as for emline array */
01892             for ( l = 0 ; l < magFactor ; l++ )   
01893         {
01894             /* set bad pixels or negative values to zero */
01895                 if (!isnan(pidata[col + row * ilx]) &&
01896                                 (pidata[col + row * ilx] > 0.))
01897                 {
01898                     spec[offset + l + (row * magFactor)] = 
01899                 pidata[col + row * ilx] ;     
01900                 }
01901                 else
01902                 {
01903                     spec[offset + l + (row * magFactor)] = 0. ;
01904                 }
01905             }
01906     }
01907  
01908         /* now call the cross sinfo_new_correlation routine */
01909         if (NULL == (result = sinfo_new_xcorrel(spec, 2*magFactor * ily, 
01910                                                 emline, 2*magFactor * ily, 
01911                                                 magFactor * ily, &delta, 
01912                                                 &maxlag, &xcorr_max)) ) 
01913         {
01914         sinfo_msg_warning ("cross sinfo_new_correlation did not work,"
01915                                " col: %d is set ZERO\n", col) ;
01916             for ( row = 0 ; row < ily ; row++ )
01917             {
01918                 podata[col + row * ilx] = ZERO ;
01919             }
01920             continue ;
01921         }
01922     
01923         if ( xcorr_max <= 0. )
01924         {
01925             sinfo_msg_warning ("cross sinfo_new_correlation sum is negative,"
01926                                " col: %d is set ZERO\n", col) ;
01927             for ( row = 0 ; row < ily ; row++ )
01928             {
01929                 podata[col + row * ilx] = ZERO ;
01930             }
01931             cpl_free(result) ;
01932             continue ;
01933         }
01934 
01935         wavelag = (float) -delta / (float) magFactor ;
01936         if ( fabs(wavelag) > (float)ily/20. )
01937         {
01938             sinfo_msg_warning("wave lag too big, col: %d is set ZERO\n", col) ;
01939             for ( row = 0 ; row < ily ; row++ )
01940             {
01941                 podata[col + row * ilx] = ZERO ;
01942             }
01943             cpl_free(result) ;
01944         continue ;
01945         }
01946 
01947         /*-------------------------------------------------------------------- 
01948          * determine new zero order coefficient centreval, of which the 
01949            formula is determined by setting equal a polynomial shifted by 
01950            wavelag with the same higher order coefficients and set the new 
01951            zero order coefficient to get both sides of the equation 
01952            approximately equal.
01953          */ 
01954         centreval = a_initial ;
01955         for ( i = 1 ; i < n_a_fitcoefs ; i++ )
01956         {
01957             if ( i%2 == 0 )
01958             {
01959                 sign = -1 ;
01960             }
01961             else
01962             {
01963                 sign = 1 ;
01964             }
01965             centreval += (float)sign * a[i]*pow(wavelag, i) ;
01966         }
01967 
01968         /* prepare to write out wavelength as pixel values */
01969         for ( row = 0 ; row < ily ; row++ )
01970         {
01971             centrepix = (float)row - ((float)ily - 1.)/2. ;
01972             pixvalue = 0. ;
01973             for ( i = 1 ; i < n_a_fitcoefs ; i++ )
01974             {
01975                 pixvalue += a[i]*pow(centrepix, i) ; 
01976             }
01977             podata[col + row * ilx] = centreval + pixvalue ; 
01978         }
01979         cpl_free(result) ;   
01980     }
01981 
01982 
01983 
01984     cpl_free(z) ;
01985     cpl_free(a) ;
01986     cpl_free(wave) ;
01987     cpl_free(emline) ;
01988     cpl_free(spec) ;
01989 
01990     return retImage ;
01991 }                    
01992 
02037 int sinfo_new_wavelength_calibration( cpl_image   * image,
02038                            FitParams ** par ,
02039                            float     ** bcoefs,
02040                            float      * wave,
02041                            int          n_lines,
02042                            int       ** row_clean,
02043                            float     ** wavelength_clean,
02044                            int        * n_found_lines,
02045                            float        dispersion,
02046                            int          halfWidth,
02047                            float        minAmplitude,
02048                            float        max_residual,
02049                            float        fwhm,
02050                            int          n_a_fitcoefs,
02051                            int          n_b_fitcoefs,
02052                            float        sigmaFactor,
02053                            float        pixel_tolerance )
02054 
02055 {
02056     int          i, j, k ;
02057     int          n_fit ;
02058     int          n_reject ;
02059     float     *  acoefs ;
02060     float     *  dacoefs ;
02061     float     ** abuf ;
02062     float     ** dabuf ;
02063     float        chisq_poly, chisq_cross ;
02064     int          zeroind ;
02065     /*float     *  mem ;*/
02066     int lx=0;
02067     int ly=0;
02068     float* pdata=NULL;
02069 
02070     if (  NULL == image )
02071     {
02072         sinfo_msg_error("no image given\n") ;
02073         return -1 ;
02074     }
02075     lx=cpl_image_get_size_x(image);
02076     ly=cpl_image_get_size_y(image);
02077     pdata=cpl_image_get_data_float(image);
02078 
02079     if ( par == NULL )
02080     {
02081         sinfo_msg_error("no fit parameter data structure given\n") ;
02082         return -1 ;
02083     }
02084     if ( wave == NULL )
02085     {
02086         sinfo_msg_error("no wavelength list given\n") ;
02087         return -1 ;
02088     }
02089     if ( n_lines <= 0 )
02090     {
02091         sinfo_msg_error("impossible number of lines in line list given\n") ;
02092         return -1 ;
02093     }
02094     if ( row_clean == NULL )
02095     {
02096         sinfo_msg_error("no row_clean array given\n") ;
02097         return -1 ;
02098     }
02099     if ( wavelength_clean == NULL )
02100     {
02101         sinfo_msg_error("no wavelength_clean array given\n") ;
02102         return -1 ;
02103     }
02104 
02105     if ( dispersion == 0. )
02106     {
02107         sinfo_msg_error("impossible dispersion given\n") ;
02108         return -1 ;
02109     }
02110 
02111     if ( halfWidth <= 0 || halfWidth > ly/2 )
02112     {
02113         sinfo_msg_error("impossible half width of the fitting box given\n") ;
02114         return -1 ;
02115     }
02116     if ( minAmplitude < 1. )
02117     {
02118         sinfo_msg_error("impossible minimal amplitude\n") ;
02119         return -1 ;
02120     }
02121 
02122     if ( max_residual <= 0. || max_residual > 1. )
02123     {
02124         sinfo_msg_error("impossible max_residual given\n") ;
02125         return -1 ;
02126     }
02127 
02128     if ( fwhm <= 0. || fwhm > 10. )
02129     {
02130         sinfo_msg_error("impossible fwhm given\n") ;
02131 
02132         return -1 ;
02133     }
02134 
02135     if ( n_a_fitcoefs <= 0 || n_a_fitcoefs > 9 )
02136     {
02137         sinfo_msg_error("unrealistic n_a_fitcoefs given\n") ;
02138         return -1 ;
02139     }
02140 
02141     if ( n_b_fitcoefs <= 0 || n_b_fitcoefs > 9 )
02142     {
02143         sinfo_msg_error(" unrealistic n_b_fitcoefs given\n") ;
02144         return -1 ;
02145     }
02146     if ( sigmaFactor <= 0. )
02147     {
02148         sinfo_msg_error(" impossible sigmaFactor given\n") ;
02149         return -1 ;
02150     }
02151 
02152     /* initialize the variables */
02153     n_reject = 0 ;
02154     n_fit = 0 ;
02155 
02156     /* fit each found line by using a Gaussian function and determine the 
02157        exact position */
02158     if ( 0 > (n_fit = sinfo_new_fit_lines( image , par, fwhm, 
02159                                            n_found_lines, row_clean, 
02160                                            wavelength_clean,
02161                                 halfWidth, minAmplitude )) )
02162     {
02163         sinfo_msg_error(" cannot fit the lines, "
02164                         "error code of sinfo_fitLines: %d\n", n_fit) ;
02165         return -1 ;
02166     }
02167 
02168     /* first check for faked lines like bad pixels */
02169     if ( -1 == sinfo_new_check_for_fake_lines (par, dispersion, 
02170                                                wavelength_clean, row_clean, 
02171                                                n_found_lines,
02172                                                lx, pixel_tolerance) )
02173     {
02174         sinfo_msg_error("cannot fit the lines, "
02175                         "error code of sinfo_fitLines: %d", n_fit) ;
02176         return -1 ;
02177     }
02178 
02179     /* allocate memory */
02180     if (NULL == (acoefs = (float*) cpl_calloc (n_a_fitcoefs, sizeof(float*))) ||
02181         NULL == (dacoefs = (float*)cpl_calloc (n_a_fitcoefs, sizeof(float*))) ||
02182         NULL == (abuf = (float**) cpl_calloc (n_a_fitcoefs, sizeof(float*))) ||
02183         NULL == (dabuf = (float**) cpl_calloc (n_a_fitcoefs, sizeof(float*))) )
02184     {
02185         sinfo_msg_error(" cannot allocate memory\n") ;
02186         return -1 ;
02187     }
02188 
02189     for ( i = 0 ; i < n_a_fitcoefs ; i++ )
02190     {
02191         if ( NULL == (abuf[i] = (float*) cpl_calloc(lx, sizeof(float))) ||
02192              NULL == (dabuf[i] = (float*) cpl_calloc(lx, sizeof(float))) )
02193         {
02194             sinfo_msg_error(" cannot allocate memory\n") ;
02195             cpl_free(abuf) ;
02196             cpl_free(dabuf) ;
02197             return -1 ;
02198         }
02199     }
02200 
02201     /* fit wavelengths to the corresponding found positions for each column */
02202     k = 0 ;
02203     
02204     for ( i = 0 ; i < lx ; i++ )
02205     {
02206         zeroind = 0 ;
02207         if ( FLT_MAX == (chisq_poly = sinfo_new_polyfit( par, i, 
02208                                                          n_found_lines[i], 
02209                                                          ly, dispersion,
02210                                                          max_residual, acoefs, 
02211                                                          dacoefs, &n_reject, 
02212                                                          n_a_fitcoefs)) )
02213         {
02214       /* 
02215            sinfo_msg_warning (" error in polyfitt in column: %d\n", i) ;
02216        */
02217             for ( j = 0 ; j < n_a_fitcoefs ; j++ )
02218             {
02219                 acoefs[j] = ZERO ;
02220                 dacoefs[j] = ZERO ;
02221             }
02222         }
02223 
02224         for ( j = 0 ; j < n_a_fitcoefs ; j++ )
02225         {
02226             if ( acoefs[0] <= 0. || acoefs[1] ==0. ||
02227                  dacoefs[j] == 0. || isnan(acoefs[j]) )
02228             {
02229                 zeroind = 1 ;
02230 
02231             }
02232         }
02233         for ( j = 0 ; j < n_a_fitcoefs ; j++ )
02234         {
02235             if ( zeroind == 0 )
02236             {
02237                 abuf[j][i]  = acoefs[j] ;
02238                 dabuf[j][i] = dacoefs[j] ;
02239             }
02240             else
02241             {
02242                 abuf[j][i]  = ZERO ;
02243                 dabuf[j][i] = ZERO ;
02244             }
02245         }
02246     }
02247 
02248     /* fit each acoefs across the columns to smooth the result */
02249     for ( i = 0 ; i < n_a_fitcoefs ; i++ )
02250     {
02251         if ( FLT_MAX == (chisq_cross = sinfo_new_coefs_cross_fit(lx, 
02252                                                                  abuf[i], 
02253                                                                  dabuf[i],
02254                                                                  bcoefs[i],
02255                                                                  n_b_fitcoefs,
02256                                                                  sigmaFactor)))
02257         {
02258             sinfo_msg_error (" cannot carry out the fitting of coefficients"
02259                              " across the columns, for the coefficient with"
02260                              " index: %d\n", i) ;
02261             for ( i = 0 ; i < n_a_fitcoefs ; i++ )
02262             {
02263                 cpl_free (abuf[i]) ;
02264                 cpl_free (dabuf[i]) ;
02265             }
02266             cpl_free ( acoefs ) ;
02267             cpl_free ( dacoefs ) ;
02268             cpl_free ( abuf ) ;
02269             cpl_free ( dabuf ) ;
02270             return -1 ;
02271         }
02272     }
02273 
02274     /* free all allocated memory */
02275     for ( i = 0 ; i < n_a_fitcoefs ; i++ )
02276     {
02277         cpl_free (abuf[i]) ;
02278         cpl_free (dabuf[i]) ;
02279     }
02280     cpl_free ( acoefs ) ;
02281     cpl_free ( dacoefs ) ;
02282     cpl_free ( abuf ) ;
02283     cpl_free ( dabuf ) ;
02284 
02285     return 0 ;   
02286 }
02287 
02288                            
02300 cpl_image * sinfo_new_convolve_image_by_gauss( cpl_image * lineImage,
02301                                  int        hw )
02302 {
02303     cpl_image * returnImage ;
02304     float* column_buffer=NULL ;
02305     float * filter ;
02306     int col, row ;
02307     int ilx=0;
02308     int ily=0;
02309     int olx=0;
02310     int oly=0;
02311     float* pidata=NULL;
02312     float* podata=NULL;
02313 
02314     if ( lineImage == NULL )
02315     {
02316         sinfo_msg_error(" no input image given!\n") ;
02317         return NULL ;
02318     }
02319     ilx=cpl_image_get_size_x(lineImage);
02320     ily=cpl_image_get_size_y(lineImage);
02321     pidata=cpl_image_get_data_float(lineImage);
02322 
02323     if ( hw < 1 )
02324     {
02325         sinfo_msg_error(" wrong half width given!\n") ;
02326         return NULL ;
02327     }
02328 
02329     /* allocate memory for returned image */
02330     if ( NULL == ( returnImage = cpl_image_new(ilx,ily,CPL_TYPE_FLOAT ) ))
02331     {
02332         sinfo_msg_error(" cannot allocate a new image\n");
02333         return NULL ;
02334     }
02335     olx=cpl_image_get_size_x(returnImage);
02336     oly=cpl_image_get_size_y(returnImage);
02337     podata=cpl_image_get_data_float(returnImage);
02338 
02339     column_buffer=cpl_calloc(ily,sizeof(float)) ;
02340 
02341     /* go through the image columns and save them in a buffer */
02342     for ( col = 0 ; col < ilx ; col++ )
02343     { 
02344         for ( row = 0 ; row < ily ; row++ )
02345         {
02346             column_buffer[row] = pidata[col + row*ilx] ;
02347         }
02348          
02349         /*--------------------------------------------------------------------- 
02350          * now low pass filter the columns by the sinfo_gaussian and fill 
02351            the return image.
02352          */  
02353         filter = sinfo_function1d_filter_lowpass( column_buffer,
02354                                             ily,
02355                                             LOW_PASS_GAUSSIAN,
02356                                             hw ) ;
02357         for ( row = 0 ; row < ily ; row++ )
02358         {
02359             podata[col + row*ilx] = filter[row] ;
02360         }
02361         sinfo_function1d_del(filter) ;
02362     }
02363                         
02364     cpl_free(column_buffer);
02365     return returnImage ;
02366 }
02367 
02407 cpl_image * sinfo_new_defined_resampling( cpl_image * image,
02408                               cpl_image * calimage,
02409                               int        n_params,
02410                               int*       n_rows,
02411                               double   * dispersion,
02412                               float    * minval,
02413                               float    * maxval,
02414                               double   * centralLambda,
02415                               int    * centralpix )
02416 {
02417     cpl_image * retImage ;
02418     cpl_image * tempCalImage ;
02419     cpl_image * tempImage ;
02420     float lambda ;
02421     float dif, lambda_renorm ;
02422     float * retimagecol = NULL;//[2560] ; /* retimagecol[n_rows] ; */
02423 
02424     float* imagecol=NULL ;
02425     float* calcol=NULL ;
02426     float* x_renorm=NULL ;
02427 
02428     float * imageptr ;
02429     float sum, new_sum ;
02430     float disp, mindisp ;
02431     int *calcolpos=NULL;//[2560];
02432     int i/*, j*/, col, row, testrow ;
02433     int half_width, firstpos ;
02434     int dispInd ;
02435     int n ;
02436     int flag;
02437     float temprow;
02438     float minLambda = 0. ;
02439     /*dpoint list[n_params] ;*/
02440     /*double * polycoeffs ;*/
02441     double poly ;
02442     /*float error;*/
02443     int zeroind ;
02444     int ilx=0;
02445     int ily=0;
02446     int clx=0;
02447     int cly=0;
02448     int olx=0;
02449     int oly=0;
02450 
02451     float* podata=NULL;
02452     float* pidata=NULL;
02453     float* pcdata=NULL;
02454     float* ptidata=NULL;
02455     float* ptcdata=NULL;
02456 
02457     if ( NULL == image )
02458     {
02459         sinfo_msg_error(" source image not given\n") ;
02460         return NULL ;
02461     }
02462     ilx=cpl_image_get_size_x(image);
02463     ily=cpl_image_get_size_y(image);
02464     pidata=cpl_image_get_data_float(image);
02465 
02466 
02467     if ( NULL == calimage )
02468     {
02469         sinfo_msg_error(" wavelength map image not given\n") ;
02470         return NULL ;
02471     }
02472     clx=cpl_image_get_size_x(calimage);
02473     cly=cpl_image_get_size_y(calimage);
02474     pcdata=cpl_image_get_data_float(calimage);
02475     if ( ilx != clx ||
02476          ily != cly )
02477     {
02478         sinfo_msg_error("source image and wavelength map image "
02479                         "are not compatible in size\n") ;
02480         return NULL ;
02481     }                              
02482   
02483     if ( n_params < 1 )
02484     {
02485         sinfo_msg_error (" wrong number of fit parameters given\n") ;
02486         return NULL ;
02487     }
02488 
02489     if ( n_params > 4 )
02490     {
02491         sinfo_msg_warning(" attention: very high number of fit "
02492                           "parameters given, not tested !!!\n") ;
02493     }
02494 
02495     imagecol=cpl_calloc(ily,sizeof(float)) ;
02496     calcol=cpl_calloc(cly,sizeof(float)) ;
02497     x_renorm=cpl_calloc(n_params,sizeof(float)) ;
02498 
02499 
02500     /*if ( n_rows <= cly)
02501     {
02502         sinfo_msg_error (" number of rows of resampled image will be "
02503                          " smaller than in wavelength calibration map,"
02504                          " information would get lost!") ;
02505         return NULL ;
02506     }*/
02507    
02508     dispInd = 0 ;
02509 
02510     /* first determine the dispersion direction */
02511     for ( col = 0 ; col < clx ; col++ )
02512     {
02513         if ( isnan(pcdata[col]) || pcdata[col] <= 0. )
02514         {
02515             continue ;
02516         }
02517         if ((pcdata[col] - pcdata[col+(clx)*(cly-1)]) > 0. )
02518         {
02519            dispInd--  ;
02520         }
02521         else if ((pcdata[col] - pcdata[col+(clx)*(cly-1)]) < 0. )
02522         {
02523            dispInd++ ;
02524         }
02525         else
02526         {
02527             continue ;
02528         }
02529     }
02530 
02531     if ( dispInd == 0 )
02532     {
02533         sinfo_msg_error(" zero dispersion?\n");
02534         return NULL ;
02535     }
02536    
02537     /* mirror the wavelength map and the raw image if 
02538        the dispersion is negative */
02539     if ( dispInd < 0 )
02540     {
02541 
02542         /* allocate a temp image */
02543         if ( NULL == ( tempCalImage = cpl_image_new(clx,cly,CPL_TYPE_FLOAT)))
02544         {
02545             sinfo_msg_error(" cannot allocate a new image\n");
02546             return NULL ;
02547         }
02548         ptcdata=cpl_image_get_data_float(tempCalImage);
02549         if ( NULL == ( tempImage = cpl_image_new( ilx, ily,CPL_TYPE_FLOAT)))
02550         {
02551             sinfo_msg_error(" cannot allocate a new image\n");
02552             cpl_image_delete(tempCalImage) ;
02553             return NULL ;
02554         }
02555         ptidata=cpl_image_get_data_float(tempImage);
02556 
02557         for ( col = 0 ; col < clx ; col++ )
02558         {
02559             n = cly - 1 ;
02560             for ( row = 0 ; row < cly ; row++ )
02561             {
02562                 ptcdata[col+row*clx] = pcdata[col+n*clx] ;
02563                 ptidata[col+row*clx] = pidata[col+n*clx] ;
02564                 n-- ;
02565             }
02566         }
02567 
02568         for ( i = 0 ; i < (int) ilx*ily ; i++ )
02569         {
02570             pidata[i] = ptidata[i] ;
02571             pcdata[i] = ptcdata[i] ;
02572         }
02573         cpl_image_delete(tempCalImage) ;
02574         cpl_image_delete(tempImage) ;
02575     }
02576 
02577     /* determine the max and min pixel value in the first and the last row */
02578     *maxval = -FLT_MAX ;
02579     *minval =  FLT_MAX ;
02580     mindisp = FLT_MAX ;
02581     for ( col = 0 ; col < clx ; col++ )
02582     {
02583         if ( isnan(pcdata[col]) || pcdata[col] <= 0. )
02584         {
02585            continue ;
02586         }
02587         disp = (pcdata[col+(clx)*((cly)-1)]
02588                - pcdata[col]) / (float)cly ;
02589         if ( mindisp > disp )
02590         {
02591             mindisp = disp ;
02592         }
02593         if ( *minval >= pcdata[col] )
02594         {
02595             *minval = pcdata[col] ;
02596         }
02597         if ( *maxval <= pcdata[col + (clx)*((cly)-1)] )
02598         {
02599             *maxval = pcdata[col + (clx)*((cly)-1)] ;
02600         }
02601     }
02602 
02603     /* find the used grating and set the dispersion to the defined value */
02604     if (*minval > 1.9 )
02605     {
02606         if ( cly > 1024 && cly < 3000)
02607         {
02608             *dispersion = DISPERSION_K_DITH ;
02609             *centralLambda = CENTRALLAMBDA_K ;
02610         }
02611         else if ( cly < 2000)
02612         {
02613             *dispersion = DISPERSION_K ;
02614             *centralLambda = CENTRALLAMBDA_K ;
02615         }
02616         else
02617         {
02618             *dispersion = DISPERSION_K_DITH/2 ;
02619             *centralLambda = CENTRALLAMBDA_K ;
02620         }
02621     }
02622     else if (*minval < 1.2 )
02623     {
02624         if ( cly > 1024 )
02625         {
02626             *dispersion = DISPERSION_J_DITH ;
02627             *centralLambda = CENTRALLAMBDA_J ;
02628         }
02629         else
02630         {
02631             *dispersion = DISPERSION_J ;
02632             *centralLambda = CENTRALLAMBDA_J ;
02633         }
02634     }
02635     else 
02636     {
02637         if ( *maxval > 2.3 )
02638         {
02639             if ( cly > 1024 )
02640             {
02641                 *dispersion = DISPERSION_HK_DITH ;
02642                 *centralLambda = CENTRALLAMBDA_HK ;
02643             }
02644             else
02645             {
02646                 *dispersion = DISPERSION_HK ;
02647                 *centralLambda = CENTRALLAMBDA_HK ;
02648             }
02649         }
02650         else 
02651         {
02652             if ( cly > 1024 )
02653             {
02654                 *dispersion = DISPERSION_H_DITH ;
02655                 *centralLambda = CENTRALLAMBDA_H ;
02656             }
02657             else
02658             {
02659                 *dispersion = DISPERSION_H ;
02660                 *centralLambda = CENTRALLAMBDA_H ;
02661             }
02662         }
02663     }
02664 
02665     /*if ( *minval + (float)n_rows * *dispersion < *maxval ) 
02666     {
02667         sinfo_msg_error(" given number of rows too small!\n");
02668         return NULL ;
02669     }*/
02670     if ( (*maxval - *minval) / *dispersion < (float)cly ) 
02671     {
02672         sinfo_msg_error(" must be something wrong with the wavelength map!\n");
02673         return NULL ;
02674     }
02675    
02676     /* determine the central pixel and the lambda in the first image row */
02677     *n_rows = floor(floor(0.5+(*maxval - *minval) / *dispersion)/2+0.5)*2;
02678     *centralpix = *n_rows / 2 ; 
02679     minLambda  = *centralLambda - *dispersion * (float)*centralpix ;
02680     /*if ( (minLambda + *dispersion * n_rows) < *maxval ) 
02681     {
02682         sinfo_msg_error(" not enough rows defined \n");
02683         return NULL ;
02684     }
02685     if ( minLambda  > *minval ) 
02686     {
02687         sinfo_msg_error(" not enough rows defined \n");
02688         return NULL ;
02689     }*/
02690 
02691     /* allocate memory */
02692     if ( NULL == ( retImage = cpl_image_new( ilx, *n_rows,CPL_TYPE_FLOAT ) ))
02693     {
02694         sinfo_msg_error(" cannot allocate a new image\n");
02695         return NULL ;
02696     }
02697     podata=cpl_image_get_data_float(retImage);
02698     olx=cpl_image_get_size_x(retImage);
02699     oly=cpl_image_get_size_y(retImage);
02700     /* now go through the columns */
02701     retimagecol = cpl_malloc(*n_rows * sizeof(retimagecol[0]));
02702     calcolpos = cpl_malloc(*n_rows * sizeof(calcolpos[0]));    
02703     for ( col = 0 ; col < olx ; col++ )
02704     {
02705         /*------------------------------------------------------------------ 
02706          * copy the columns of the source image and the wavemap image into
02707          * buffer arrays to speed things up
02708          */
02709         sum = 0. ;
02710         for ( row = 0 ; row < ily ; row++ )
02711         {
02712             imagecol[row] = pidata[col + row*ilx] ; 
02713             if (!isnan(imagecol[row]))
02714             {
02715                 sum += imagecol[row] ;
02716             }
02717             calcol[row]   = pcdata[col + row*clx] ; 
02718         }
02719 
02720         for ( row = 0 ; row < oly ; row++ )
02721         {
02722             retimagecol[row] = 0. ;
02723             calcolpos[row] = -1;
02724         }
02725 
02726     for ( row=0 ; row < cly ; row++)
02727     {
02728         temprow = (calcol[row]- minLambda)/ *dispersion;
02729         if (temprow >= 0 && temprow < oly)
02730             calcolpos[(int) temprow]  = row;
02731     }
02732         
02733     zeroind = 0 ;
02734        
02735 
02736         for ( row = 0 ; row < oly ; row++ )
02737         {
02738             lambda = minLambda + *dispersion * (float) row ;
02739       
02740             /*--------------------------------------------------------------- 
02741              * lambda must lie between the two available wavelength extremes
02742              * otherwise the image pixels are set to ZERO 
02743              */
02744             if ( row < cly )
02745             {
02746                 if ( isnan(calcol[row]) )
02747                 {
02748                     zeroind = 1 ;
02749                 } 
02750             }
02751 
02752             if ( (lambda < calcol[0]) || 
02753                  (lambda > calcol[(cly)-1]) || zeroind == 1 )
02754             {
02755                 retimagecol[row] = ZERO ;
02756                 continue ;
02757             }
02758             /*testrow = 0 ; 
02759             while ( lambda > calcol[testrow] )
02760             {
02761                 testrow++ ;
02762             }*/
02763         if (calcolpos[row]==-1) {
02764                 if(row>= (*n_rows-1)) calcolpos[row] = calcolpos[row-1];
02765                 if(row<  (*n_rows-1)) calcolpos[row] = calcolpos[row+1];
02766         }
02767         if(calcolpos[row]>0) {
02768           if (lambda-calcol[calcolpos[row]-1]==0.) {
02769         calcolpos[row]=calcolpos[row]-1;
02770           }
02771         }
02772         testrow = calcolpos[row];
02773 
02774             /*-----------------------------------------------------------------
02775              * at this point calcol[testrow-1] < lambda <= calcol[testrow] 
02776              * now determine the box position in which the polint fit is 
02777                carried through.
02778              * the half width of the box is half the number of fit parameters.
02779              * Now we determine the start position of the fitting box and treat
02780              * the special case of being near the sinfo_edge.
02781              */
02782 
02783             if ( n_params % 2 == 0 )
02784             {
02785                 half_width = (int)(n_params/2) - 1 ;
02786             }
02787             else
02788             {
02789                 half_width = (int)(n_params/2) ;
02790             }
02791 
02792 
02793             if ( isnan(imagecol[testrow]) )
02794             {
02795                 for ( i = row-half_width ; i < row-half_width+n_params ; i++ )
02796                 { 
02797                     if (i < 0) continue ;
02798                     if ( i >= oly ) continue  ;
02799                     retimagecol[i] = ZERO ;
02800                 }
02801                 imagecol[testrow] = 0. ;
02802             }
02803 
02804         }
02805 
02806         /* now loop over the rows and establish the lambda for each row */
02807         new_sum = 0. ;
02808         for ( row = 0 ; row < oly ; row++ )
02809         {
02810             if ( isnan(retimagecol[row]) )
02811             {
02812                 continue ;
02813             }
02814         lambda = minLambda + *dispersion * (float) row ;
02815       
02816             /*--------------------------------------------------------------- 
02817              * lambda must lie between the two available wavelength extremes
02818              * otherwise the image pixels are set to ZERO 
02819              */
02820             if ( (lambda < calcol[0]) || (lambda > calcol[(cly)-1]) ) 
02821             {
02822                 retimagecol[row] = ZERO ;
02823                 continue ;
02824             }
02825             /*testrow = 0 ; 
02826             while ( lambda > calcol[testrow] )
02827             {
02828                 testrow++ ;
02829             }*/
02830         if (calcolpos[row]==-1) {
02831                if(row >= (*n_rows-1)) calcolpos[row] = calcolpos[row-1];
02832                if(row <  (*n_rows-1)) calcolpos[row] = calcolpos[row+1];
02833         }
02834 
02835         testrow = calcolpos[row];
02836 
02837             /*--------------------------------------------------------------
02838              * at this point calcol[testrow-1] < lambda <= calcol[testrow] 
02839              * now determine the box position in which the polynomial 
02840                interpolation is carried through.
02841              * the half width of the box is half the number of fit parameters.
02842              * Now we determine the start position of the fitting box and treat
02843              * the special case of being near the sinfo_edge.
02844              */
02845 
02846             if ( n_params % 2 == 0 )
02847             {
02848                 half_width = (int)(n_params/2) - 1 ;
02849             }
02850             else
02851             {
02852                 half_width = (int)(n_params/2) ;
02853             }
02854 
02855             firstpos   = testrow - half_width ;
02856             if ( firstpos < 0 )
02857             {
02858                 firstpos = 0 ;
02859             }
02860             else if ( firstpos > ((cly)-n_params) )
02861             {
02862                firstpos = cly - n_params ;
02863             }
02864             if ( isnan(imagecol[firstpos]) )
02865             {
02866                 retimagecol[row] = ZERO ;
02867                 continue ;
02868             }
02869             
02870 
02871             /* we must rescale the x-values (smaller than 1) 
02872                for the fitting routine */
02873             dif = calcol[firstpos+n_params-1] - calcol[firstpos] ;
02874             for ( i = 0 ; i < n_params ; i++ )
02875             {
02876             x_renorm[i] = (calcol[firstpos + i] - calcol[firstpos]) / dif ;
02877         }
02878         
02879            
02880             lambda_renorm = ( lambda - calcol[firstpos] ) / dif ; 
02881         
02882         imageptr = &imagecol[firstpos] ;
02883         
02884         flag = 0;
02885         poly=sinfo_new_nev_ille(x_renorm, imageptr, 
02886                                     n_params-1, lambda_renorm, &flag);
02887         
02888             new_sum += poly ;
02889             retimagecol[row] = poly ; 
02890     }
02891     
02892         /* now renorm the total flux */
02893         for ( row = 0 ; row < oly ; row++ )
02894         {
02895             if ( new_sum == 0. ) new_sum = 1. ;
02896             if ( isnan(retimagecol[row]) )
02897             {
02898                 podata[col+row*olx] = ZERO ;
02899             }
02900             else
02901             {
02902                 /* rescaling is commented out because it delivers wrong results
02903                    in case of appearance of blanks or bad pixels */
02904                 podata[col+row*olx] = retimagecol[row] /* * sum/new_sum*/ ;
02905             }
02906         }
02907 
02908     }
02909     cpl_free(retimagecol);
02910     cpl_free(calcolpos);
02911     cpl_free(imagecol) ;
02912     cpl_free(calcol) ;
02913     cpl_free(x_renorm) ;
02914     
02915     return retImage ;
02916 }
02917 
02919 /*___oOo___*/

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