sinfo_cube_construct.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  30/08/00  created
00027 */
00028 
00029 /************************************************************************
00030 *   NAME
00031 *        sinfo_cube_construct.c -
00032 *        some procedures to construct a data cube
00033 *
00034 *   SYNOPSIS
00035 *
00036 *   1) cpl_image * sinfo_new_convolve_ns_image_by_gauss( cpl_image * lineImage,
00037 *                                         int        hw )
00038 *
00039 *   2) float * sinfo_north_south_test( cpl_image * ns_image,
00040 *                                int        n_slitlets,
00041 *                                int        halfWidth,
00042 *                                float      fwhm,
00043 *                                float      minDiff,
00044 *                                float      estimated_dist,
00045 *                                float      devtol )
00046 *
00047 *   3) cpl_imagelist * sinfo_new_make_cube ( cpl_image * calibImage,
00048 *                           float    * distances,
00049 *                           float    * correct_diff_dist )
00050 *
00051 *   4) cpl_imagelist * sinfo_new_make_cube_spi ( cpl_image *  calibImage,
00052 *                              float    ** slit_edges,
00053 *                              float    *  shift )
00054 *
00055 *   5) cpl_imagelist * sinfo_new_make_cube_dist ( cpl_image * calibImage,
00056 *                               float      firstCol,
00057 *                               float    * distances,
00058 *                               float    * shift )
00059 *
00060 *   6) cpl_imagelist * sinfo_new_make_3D_cube_dist ( cpl_image * calibImage,
00061 *                                 float      firstCol,
00062 *                                 float    * distances,
00063 *                                 float    * shift )
00064 *
00065 *   7) cpl_imagelist * sinfo_new_make_3D_cube ( cpl_image * calibImage,
00066 *                             int      * kpixshift,  
00067 *                             int        kpixfirst )
00068 *
00069 *   8) cpl_imagelist * 
00070        sinfo_new_determine_mask_cube(cpl_imagelist * sourceMaskCube,
00071 *                                    float     lowLimit,
00072 *                                    float     highLimit )
00073 *
00074 *   9) cpl_imagelist * sinfo_new_interpol_cube ( cpl_imagelist * sourceCube,
00075 *                               cpl_imagelist * maskCube,
00076 *                               int       n_neighbors, 
00077 *                               int       max_radius )
00078 *
00079 *   10) cpl_imagelist * sinfo_new_fine_tune_cube( cpl_imagelist * cube,
00080 *                              float   * correct_diff_dist )
00081 *
00082 *   11) cpl_imagelist * sinfo_new_fine_tune_cube_by_FFT( cpl_imagelist * cube,
00083 *                                   float   * correct_diff_dist )
00084 *
00085 *   12) cpl_imagelist * sinfo_new_fine_tune_cube_by_spline(cpl_imagelist * cube,
00086 *                                        float   * correct_diff_dist )
00087 *
00088 *   DESCRIPTION
00089 *
00090 *   1) convolves a north-south-test image with a sinfo_gaussian
00091 *      with user given integer half width by using the eclipse
00092 *      routine sinfo_function1d_filter_lowpass().
00093 *   2) determines the distances of the slitlets
00094 *   3) makes a data cube out of a resampled source image
00095 *      this SPIFFI specific routine takes into account the
00096 *      Spiffi slitlet order on the detector.
00097 *      Also shifts the resulting image rows by one pixel if
00098 *      necessary according to the distances array gained from
00099 *      the north-south test routine.
00100 *      Can do the same with the bad pixel map image to generate a
00101 *      bad pixel mask cube.
00102 *   4) makes a data cube out of a resampled source image
00103 *      this SPIFFI specific routine takes into account the
00104 *      Spiffi slitlet order on the detector.
00105 *      This routine takes fitted slitlet positions into account.
00106 *      Can do the same with the bad pixel map image to generate a
00107 *      bad pixel mask cube.
00108 *   5) makes a data cube out of a resampled source image
00109 *      this SPIFFI specific routine takes into account the
00110 *      Spiffi slitlet order on the detector.
00111 *      Also shifts the resulting image rows by one pixel if
00112 *      necessary according to the distances array gained from
00113 *      the north-south test routine.
00114 *      Can do the same with the bad pixel map image to generate a
00115 *      bad pixel mask cube.
00116 *   6) makes a data cube out of a resampled source image
00117 *      this 3D specific routine takes into account the
00118 *      3D slitlet order on the detector.
00119 *      Also shifts the resulting image rows by one pixel if
00120 *      necessary according to the distances array gained from
00121 *      the north-south test routine.
00122 *      Can do the same with the bad pixel map image to generate a
00123 *      bad pixel mask cube.
00124 *   7) makes a data cube out of a resampled source image
00125 *      this MPE 3D specific routine takes into account the
00126 *      3D slitlet order on the detector.
00127 *      Also shifts the resulting image row by an integer pixel shift if
00128 *      necessary according to the input kpixshift array 
00129 *      Can do the same with the bad pixel map image to generate a
00130 *      bad pixel mask cube.
00131 *   8) converts resampled bad pixels to real bad pixels in data cubes.
00132 *   9) Bad pixel interpolation 3D like (saturated pixels exist):
00133 *      interpolates the bad pixels of the source cube by
00134 *      using the nearest neighbors. 
00135 *      first it is checked if the bad pixel is interpolatable:
00136 *      it is only interpolatable if the number of good pixels 
00137 *      in its spectrum of length 2*n_neighbors+1 exceeds 3 and
00138 *      if there is at least one good pixel on either side of the
00139 *      central pixel.
00140 *      Afterwards good neighboring pixels are searched within the 
00141 *      image plane of the bad pixel by using an increasing pixel radius. 
00142 *      Good pixels mean, the corresponding spectral pixels of the 
00143 *      bad pixel and its spatial neighboring pixel must have
00144 *      at least 2 valid pixel pairs to be able to be used for
00145 *      the interpolation. The search is stopped if 9 valid neighboring
00146 *      pixels are found. 
00147 *      Now normalize the found spectral values, collect the valid pixels 
00148 *      (there must be at least 18) and take the sinfo_median of the valid 
00149 *      pixels with which the bad pixel is replaced.
00150 *   10) fine tunes each row in the right position according 
00151 *      to the distances of the slitlets to each other
00152 *      (output of the north-south test).
00153 *      This means that the rows must be realigned by a 
00154 *      fraction of a pixel to accomodate non-integer slit 
00155 *      length. The fractional realignment is done by using
00156 *      the polynomial interpolation algorithm of N.R. 
00157 *      Each row is rescaled so that the total flux is
00158 *      conserved.
00159 *  11) fine tunes each row in the right position according 
00160 *      to the distances of the slitlets to each other
00161 *      (output of the north-south test).
00162 *      This means that the rows must be realigned by a 
00163 *      fraction of a pixel to accomodate non-integer slit 
00164 *      length. The fractional realignment is done by using
00165 *      the FFT algorithm four1() of N.R. 
00166 *  12) fine tunes each row in the right position according 
00167 *      to the distances of the slitlets to each other
00168 *      (output of the north-south test).
00169 *      This means that the rows must be realigned by a 
00170 *      fraction of a pixel to accomodate non-integer slit 
00171 *      length. The fractional realignment is done by using
00172 *      the spline interpolation algorithm splint in connection
00173 *      with the algorithm spline of N.R. 
00174 *      This algorithms assume that each row is a tabulated
00175 *      function. The first derivatives of the interpolating
00176 *      function at the first and last point must be given.
00177 *      These are set higher than 1xe^30, so the routine
00178 *      sets the corresponding boundary condition for a natural
00179 *      spline, with zero second derivative on that boundary.
00180 *      Each row is rescaled so that the total flux is
00181 *      conserved.
00182 *
00183 *   FILES
00184 *
00185 *   ENVIRONMENT
00186 *
00187 *   RETURN VALUES
00188 *
00189 *   CAUTIONS
00190 *
00191 *   EXAMPLES
00192 *
00193 *   SEE ALSO
00194 *
00195 *   BUGS
00196 *
00197 *------------------------------------------------------------------------
00198 */
00199 
00200 #ifdef HAVE_CONFIG_H
00201 #  include <config.h>
00202 #endif
00203 #define POSIX_SOURCE 1
00204 #include "sinfo_vltPort.h"
00205 
00206 /*
00207  * System Headers
00208  */
00209 
00210 /*
00211  * Local Headers
00212  */
00213 #include "sinfo_function_1d.h"
00214 #include "sinfo_cube_construct.h"
00215 #include "sinfo_spectrum_ops.h"
00216 #include "sinfo_wave_calibration.h"
00217 #include "sinfo_utilities.h"
00218 #include "sinfo_local_types.h"
00219 #include "sinfo_fft_base.h"
00226 static int
00227 sinfo_sort_slitlets(const int kslit);
00228 
00229 
00230 static int
00231 sinfo_sort_slitlets_array(const int slit, int* row_index);
00232 
00235 /*----------------------------------------------------------------------------
00236  *                            Function codes
00237  *--------------------------------------------------------------------------*/
00248 cpl_image * 
00249 sinfo_new_convolve_ns_image_by_gauss( cpl_image * lineImage,
00250                                    int        hw )
00251 {
00252     cpl_image * returnImage ;
00253     float* row_buffer=NULL ;
00254     float * filter ;
00255     int col, row ;
00256     int ilx=0;
00257     int ily=0;
00258  
00259     float* pidata=NULL;
00260     float* podata=NULL;
00261 
00262     if ( lineImage == NULL )
00263     {
00264         sinfo_msg_error("no input image given!\n") ;
00265         return NULL ;
00266     }
00267     ilx=cpl_image_get_size_x(lineImage);
00268     ily=cpl_image_get_size_y(lineImage);
00269     pidata=cpl_image_get_data_float(lineImage);
00270     if ( hw < 1 )
00271     {
00272         sinfo_msg_error(" wrong half width given!\n") ;
00273         return NULL ;
00274     }
00275 
00276     /* allocate memory for returned image */
00277     if ( NULL == ( returnImage = cpl_image_new(ilx,ily,CPL_TYPE_FLOAT ) ))
00278     {
00279         sinfo_msg_error("cannot allocate a new image\n");
00280         return NULL ;
00281     }
00282     podata=cpl_image_get_data_float(returnImage);
00283 
00284     /* go through the image rows and save them in a buffer */
00285     row_buffer=cpl_calloc(ily,sizeof(float)) ;
00286 
00287     for ( row = 0 ; row < ily ; row++ )
00288     {
00289         for ( col = 0 ; col < ilx ; col++ )
00290         {
00291             if ( isnan(pidata[col+row*ilx]) )
00292             {
00293                 row_buffer[col] = 0. ;
00294             }
00295             else
00296             {
00297                 row_buffer[col] = pidata[col + row*ilx] ;
00298             }
00299         }
00300 
00301         /*--------------------------------------------------------------------
00302          * now low pass filter the rows by the gaussian and fill the return
00303          * image.
00304          */
00305         filter = sinfo_function1d_filter_lowpass( row_buffer,
00306                                             ilx,
00307                                             LOW_PASS_GAUSSIAN,
00308                                             hw ) ;
00309         for ( col = 0 ; col < ily ; col++ )
00310         {
00311             podata[col + row*ilx] = filter[col] ;
00312         }
00313         /* deallocate memory */
00314         sinfo_function1d_del (filter) ;
00315     }
00316     cpl_free(row_buffer);    
00317     return returnImage ;
00318 }
00319 
00336 float * 
00337 sinfo_north_south_test( cpl_image * ns_image,
00338                           int        n_slitlets,
00339                           int        halfWidth,
00340                           float      fwhm,
00341                           float      minDiff,
00342                           float      estimated_dist,
00343                           float      devtol,
00344               int         bottom,
00345               int         top )
00346 {
00347     int i, j, k, m, row, col, n, ni, na ;
00348     int position, counter, iters ;
00349     int xdim, ndat, its, numpar ;
00350     pixelvalue row_buf[cpl_image_get_size_x(ns_image)] ;
00351     float sum, mean, maxval ;
00352     float tol, lab ;
00353     float * distances ;
00354     float distances_buf[cpl_image_get_size_y(ns_image)][n_slitlets-1] ;
00355     float x_position[n_slitlets] ;
00356     float * xdat, * wdat ;
00357     int * mpar ;
00358     int found[3*n_slitlets], found_clean[3*n_slitlets] ;
00359     int found_cleanit[3*n_slitlets] ;
00360     Vector * line ;
00361     FitParams ** par ;
00362     int foundit, begin, end ;
00363     int zeroindicator ;
00364     int ilx=0;
00365     int ily=0;
00366  
00367     float* pidata=NULL;
00368  
00369     if ( ns_image == NULL )
00370     {
00371         sinfo_msg_error("sorry, no image given\n") ;
00372         return NULL ;
00373     }
00374     ilx=cpl_image_get_size_x(ns_image);
00375     ily=cpl_image_get_size_y(ns_image);
00376     pidata=cpl_image_get_data_float(ns_image);
00377 
00378 
00379     if ( n_slitlets < 1 )
00380     {
00381         sinfo_msg_error("wrong number of slitlets given\n") ;
00382         return NULL ;
00383     }
00384     if ( halfWidth < 0 || halfWidth >= estimated_dist )
00385     {
00386         sinfo_msg_error("wrong half width given\n") ;
00387         return NULL ;
00388     }
00389     if ( fwhm <= 0. )
00390     {
00391         sinfo_msg_error("wrong fwhm given\n") ;
00392         return NULL ;
00393     }
00394     if ( minDiff < 1. )
00395     {
00396         sinfo_msg_error("wrong minDiff given\n") ;
00397         return NULL ;
00398     }
00399 
00400     /* allocate memory for output array */
00401     if (NULL == (distances = (float *) cpl_calloc ( n_slitlets - 1 , 
00402                                                     sizeof (float) ))) 
00403     {
00404         sinfo_msg_error("could not allocate memory\n") ;
00405         return NULL ;
00406     }
00407 
00408     /* go through the image rows */
00409     for ( row = bottom ; row < top ; row++ )
00410     {
00411         zeroindicator = 0 ;
00412 
00413         /* initialize the distance buffer */
00414         for ( i = 0 ; i < n_slitlets-1 ; i++ )
00415         {
00416             distances_buf[row][i] = ZERO ;
00417         }
00418 
00419         /* fill the row buffer array with image data */
00420         for ( col = 0 ; col < ilx ; col++ )
00421         {
00422             row_buf[col] = pidata[col + row*ilx] ;
00423         }
00424 
00425         /* determine the mean of the row data */
00426         sum = 0. ;
00427         n = 0 ;
00428         for ( i = 0 ; i < ilx ; i++ )
00429         {
00430             if ( isnan(row_buf[i]) )
00431             {
00432                 continue ;
00433             }
00434             sum += row_buf[i] ;
00435             n++ ;
00436         }
00437         mean = sum / (float)n ;
00438 
00439 
00440         /* store the positions of image values greater than the mean */
00441         n = 0 ;
00442         for ( i = 0 ; i < ilx ; i++ )
00443         {
00444             if (isnan(row_buf[i]))
00445             {
00446                 continue ;
00447             }
00448             if ( row_buf[i] >  sqrt(mean*mean*9) )
00449             {
00450                 found[n] = i ;
00451                 n++ ;
00452             } 
00453         }
00454        
00455         if ( n < n_slitlets )
00456         {
00457             sinfo_msg_warning("t1 wrong number of intensity columns found "
00458                               "in row: %d, found number: %d, mean: %g",
00459                               row, n, mean) ;
00460             continue ;
00461         }
00462         else
00463         { 
00464             /* find the maximum value position around the found columns */
00465             na = 0 ;
00466             for ( i = 1 ; i < n ; i ++ )
00467             {
00468                 if ( found[i] - found[i-1] < halfWidth )
00469                 {
00470                     begin = found[i] - halfWidth ;
00471                     if ( begin < 0 )
00472                     {
00473                         begin = 0 ;
00474                     }
00475                     end = found[i] + halfWidth ;
00476                     if ( end >= ilx )
00477                     {
00478                         end = ilx - 1 ;
00479                     }
00480                     /* find the maximum value inside the box 
00481                        around the found positions*/
00482                     maxval = -FLT_MAX ;
00483                     foundit = 0 ;
00484                     for ( j = begin ; j <= end ; j++ )
00485                     {
00486                         /* do not consider boxes that contain bad pixels */
00487                         if (isnan(row_buf[j]))
00488                         {
00489                             continue ;
00490                         }
00491                         if (row_buf[j] >= maxval )
00492                         {
00493                             maxval = row_buf[j] ;
00494                             foundit = j ;
00495                         }
00496                     }
00497                     if (maxval == -FLT_MAX)
00498                     {
00499                         continue ;
00500                     }
00501                     for ( k = 0 ; k < na ; k++ )
00502                     {
00503                         if ( found_cleanit[k] >= begin && 
00504                              found_cleanit[k] < foundit )
00505                         {
00506                             na-- ;
00507                         }
00508                     }
00509                     for ( k = 0 ; k < n ; k++ )
00510                     {
00511                         if ( found[k] == foundit)
00512                         {
00513                  if (na>0){
00514                             if ( found_cleanit[na-1] != found[k] )
00515                             {
00516                                 found_cleanit[na] = found[k] ;
00517                                 na++ ;
00518                             }
00519              }
00520              else{
00521                 found_cleanit[na] = found[k] ;  
00522                             na++ ;
00523              } 
00524                       }
00525                     }
00526                 }
00527                 else
00528                 {
00529                     if ( i == 1 )
00530                     {
00531                         found_cleanit[na] = found[0] ;
00532                         na++ ;
00533                         found_cleanit[na] = found[1] ;
00534                         na++ ;
00535                     }
00536                     else
00537                     {   
00538                 if (na>0){
00539                             if ( found_cleanit[na-1] != found[i-1])
00540                             {
00541                                 found_cleanit[na] = found[i-1] ;
00542                                 na++ ;
00543                             }
00544                             if ( found_cleanit[na-1] != found[i])
00545                             {
00546                                 found_cleanit[na] = found[i] ;
00547                                 na++ ;
00548                             }
00549                         }
00550             else
00551                         {
00552                             found_cleanit[na] = found[i] ;
00553                             na++ ;
00554                         }
00555             }  
00556                 }
00557             }
00558             /* determine only one pixel position for each slitlet intensity */
00559             j = 1 ;
00560             for ( i = 1 ; i < na ; i++ )
00561             {
00562                 if ( (float)(found_cleanit[i] - found_cleanit[i-1]) < 
00563                             (estimated_dist - devtol) ||
00564                      (float)(found_cleanit[i] - found_cleanit[i-1]) > 
00565                             (estimated_dist + devtol) )
00566                 {
00567                     continue ;
00568                 }
00569                 else
00570                 {
00571                     found_clean[j-1] = found_cleanit[i-1] ;
00572                     found_clean[j]   = found_cleanit[i] ;
00573                     j++ ;
00574                 }
00575             }
00576         }
00577         if ( j > n_slitlets )
00578         {
00579             /* check the distance again */
00580             ni = 1 ;
00581             for ( i = 1 ; i < j ; i++ )
00582             {
00583                 if ( (float)(found_clean[i] - found_clean[i-1]) < 
00584                             (estimated_dist - devtol ) ||
00585                      (float)(found_clean[i] - found_clean[i-1]) > 
00586                             (estimated_dist + devtol ) )
00587                 { 
00588                     continue ;
00589                 }
00590                 else
00591                 {
00592 
00593                     found_clean[ni-1] = found_clean[i-1] ;
00594                     found_clean[ni]   = found_clean[i] ;
00595                     ni++ ;
00596                 }
00597             }
00598             if ( ni != n_slitlets )
00599             {
00600                 sinfo_msg_warning("t2 wrong number of intensity columns"
00601                                   " found in row: %d,  found number: %d",
00602                                   row, ni) ;
00603                 continue ;
00604             }
00605             else 
00606             {
00607                 j = ni ;
00608             }
00609         }
00610         else if ( j < n_slitlets )
00611         {
00612             cpl_msg_debug ("north_south_test3:",
00613                             "t3 wrong number of intensity columns "
00614                             "found in row: %d , found number: %d, mean: %g\n", 
00615                             row, j, mean) ;
00616             continue ;
00617         }
00618         counter = 0 ;
00619         /* go through the found intensity pixels in one row */
00620         for ( i = 0 ; i < j ; i++ )
00621         {
00622             /* allocate memory for the array where the line is fitted in */
00623             if ( NULL == (line = sinfo_new_vector (2*halfWidth + 1)) )
00624             {
00625                 sinfo_msg_error ("cannot allocate new Vector \n") ;
00626                 cpl_free(distances) ;
00627                 return NULL ;
00628             }
00629 
00630             /* allocate memory */
00631             xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00632             wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00633             mpar = (int *)   cpl_calloc( MAXPAR, sizeof (int) ) ;
00634             par = sinfo_new_fit_params(1) ;
00635 
00636             m = 0 ;
00637             for ( k = found_clean[i]-halfWidth ; 
00638                   k <= found_clean[i]+halfWidth ; k++ )
00639             {
00640                 if ( k < 0 )
00641                 {
00642                     k = 0. ;
00643                 }
00644                 else if ( k >= ilx )
00645                 {
00646                     k = ilx - 1 ;
00647                 }
00648                 else if ( isnan(row_buf[k]) )
00649                 {
00650                     zeroindicator = 1 ;
00651                     break ;
00652                 }
00653                 else
00654                 {
00655                     line -> data[m] = row_buf[k] ;
00656                     m++ ;
00657                 }
00658             }
00659             if ( zeroindicator == 1 )
00660             {
00661                 sinfo_new_destroy_vector(line) ;
00662                 cpl_free(xdat) ;
00663                 cpl_free(wdat) ;
00664                 cpl_free(mpar) ;
00665                 sinfo_new_destroy_fit_params(&par) ;
00666                 break ;
00667             }
00668 
00669             /*----------------------------------------------------------------
00670              * go through the spectral sinfo_vector
00671              * determine the maximum pixel value in the spectral sinfo_vector
00672              */
00673             maxval = -FLT_MAX ;
00674             position = -INT32_MAX ;
00675             for ( k = 0 ; k < m ; k++ )
00676             {
00677                 xdat[k] = k ;
00678                 wdat[k] = 1.0 ;
00679                 if ( line -> data[k] >= maxval )
00680                 {
00681                     maxval = line -> data[k] ;
00682                     position = k ;
00683                 }
00684             }
00685 
00686             /* set initial values for the fitting routine */
00687             xdim     = XDIM ;
00688             ndat     = line -> n_elements ;
00689             numpar   = MAXPAR ;
00690             tol      = TOL ;
00691             lab      = LAB ;
00692             its      = ITS ;
00693             (*par) -> fit_par[1] = fwhm ;
00694             (*par) -> fit_par[2] = (float) position ;
00695             (*par) -> fit_par[3] = (float) (line -> data[0] + 
00696                                    line -> data[line->n_elements - 1]) / 2.0 ;
00697             (*par) -> fit_par[0]  = maxval - ((*par) -> fit_par[3]) ;
00698 
00699 
00700             /* exclude negative peaks and low signal cases */
00701             if ( (*par) -> fit_par[0] < minDiff )
00702             {
00703                 sinfo_msg_warning ("sorry, signal of line too low to fit "
00704                                    "in row: %d in slitlet %d\n", row, i) ;
00705                 sinfo_new_destroy_vector(line) ;
00706                 cpl_free(xdat) ;
00707                 cpl_free(wdat) ;
00708                 cpl_free(mpar) ;
00709                 sinfo_new_destroy_fit_params(&par) ;
00710                 continue ;
00711             }
00712 
00713             for ( k = 0 ; k < MAXPAR ; k++ )
00714             {
00715                 (*par) -> derv_par[k] = 0.0 ;
00716                 mpar[k] = 1 ;
00717             }
00718             /* finally, do the least square fit using a Gaussian */
00719             if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim, 
00720                                                    line -> data, wdat, &ndat, 
00721                                                    (*par) -> fit_par,
00722                                                    (*par) -> derv_par, mpar, 
00723                                                    &numpar, &tol, &its, &lab)) )
00724             {
00725           /*
00726                 cpl_msg_debug ("north_south_test:",
00727                                "sinfo_lsqfit_c: least squares fit failed,"
00728                                " error no.: %d in row: %d in slitlet %d\n",
00729                                 iters, row, i) ;
00730           */
00731                 sinfo_new_destroy_vector(line) ;
00732                 cpl_free(xdat) ;
00733                 cpl_free(wdat) ;
00734                 cpl_free(mpar) ;
00735                 sinfo_new_destroy_fit_params(&par) ;
00736                 continue ;
00737             }
00738 
00739             /* check for negative fit results */
00740             if ( (*par) -> fit_par[0] <= 0. || 
00741                  (*par) -> fit_par[1] <= 0. ||
00742                  (*par) -> fit_par[2] < 0. )
00743             {
00744                 sinfo_msg_warning ("negative parameters as fit result, "
00745                                    "not used! in row %d in slitlet %d", 
00746                                    row, i) ;
00747                 sinfo_new_destroy_vector(line) ;
00748                 cpl_free(xdat) ;
00749                 cpl_free(wdat) ;
00750                 cpl_free(mpar) ;
00751                 sinfo_new_destroy_fit_params(&par) ;
00752                 continue ;
00753             }
00754 
00755             /* correct the fitted position for the given row of the line 
00756                in image coordinates */
00757             (*par) -> fit_par[2] =  (float) (found_clean[i] - halfWidth) + 
00758                                             (*par) -> fit_par[2] ;
00759             x_position[counter] = (*par) -> fit_par[2] ;
00760             counter ++ ;
00761 
00762             /* free memory */
00763             sinfo_new_destroy_fit_params(&par) ;
00764             sinfo_new_destroy_vector ( line ) ;
00765             cpl_free ( xdat ) ;
00766             cpl_free ( wdat ) ;
00767             cpl_free ( mpar ) ;
00768         }
00769         if (zeroindicator == 1)
00770         {
00771             sinfo_msg_debug ("bad pixel in fitting box in row: %d\n", row) ;
00772             continue ;
00773         }
00774 
00775         if ( counter != n_slitlets )
00776         {
00777             continue ;
00778             sinfo_msg_warning("wrong number of slitlets found in row: %d",row);
00779         }
00780         /* store the distances between the sources in a buffer */
00781         for ( i = 1 ; i < n_slitlets ; i++ )
00782         {
00783             distances_buf[row][i-1] = x_position[i] - x_position[i-1] ;
00784         }
00785     }
00786 
00787     /* ----------------------------------------------------------------
00788      * go through the rows again and take the mean of the distances, 
00789      * throw away the runaways 
00790      */
00791     for ( i = 0 ; i < n_slitlets-1 ; i++ )
00792     {
00793         n   = 0 ;
00794         sum = 0. ;
00795         for ( row = bottom ; row < top ; row++ )
00796         {
00797             if ( fabs( distances_buf[row][i] - estimated_dist ) > devtol || 
00798                  isnan(distances_buf[row][i]) )
00799             {
00800             /*
00801           sinfo_msg("dist=%g devtol=%g isan=%d", 
00802             distances_buf[row][i],
00803             devtol,
00804             isnan(distances_buf[row][i]));
00805             */
00806                 continue ;
00807             }
00808             sum += distances_buf[row][i] ;
00809             n++ ;
00810         }
00811         if ( n < 2 )
00812         {
00813             sinfo_msg_error("distances array could not be determined "
00814                             "completely!, deviations of distances from number "
00815                             "of slitlets too big\n" ) ;
00816             cpl_free(distances) ;
00817             return NULL ;
00818         }
00819         else
00820         {
00821             distances[i] = sum / (float)n ;
00822         }
00823     }
00824     return distances ; 
00825 }
00826 
00850 cpl_imagelist * 
00851 sinfo_new_make_cube ( cpl_image * calibImage,
00852                      float    * distances,
00853                      float    * correct_diff_dist )
00854 {
00855     cpl_imagelist * returnCube ;
00856     int imsize, kslit, kpix ;
00857     int slit_index ;
00858     int z, col, recol ;
00859     int ilx=0;
00860     int ily=0;
00861 
00862     float* podata=NULL;
00863     float* pidata=NULL;
00864     cpl_image* o_img;
00865 
00866     if ( NULL == calibImage )
00867     {
00868         sinfo_msg_error("no resampled image given!\n") ;
00869         return NULL ;
00870     }
00871     ilx=cpl_image_get_size_x(calibImage);
00872     ily=cpl_image_get_size_y(calibImage);
00873     pidata=cpl_image_get_data_float(calibImage);
00874 
00875     if ( NULL == distances )
00876     {
00877         sinfo_msg_error("no distances array from ns_test given!/n") ;
00878         return NULL ;
00879     }
00880 
00881     if ( NULL == correct_diff_dist )
00882     {
00883         sinfo_msg_error("correct_diff_dist array is not allocated!/n") ;
00884         return NULL ;
00885     }
00886        
00887     if ( N_SLITLETS != 32 )
00888     {
00889         sinfo_msg_error ("wrong number of slitlets given \n" ) ;
00890         return NULL ;
00891     }
00892     imsize = ilx / N_SLITLETS ;
00893 
00894     /* allocate memory */  
00895     if ( NULL == (returnCube = cpl_imagelist_new()) )
00896     {
00897         sinfo_msg_error ("cannot allocate new cube \n" ) ;
00898         return NULL ;
00899     }
00900 
00901     /* now build the data cube out of the resampled image */
00902     for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
00903     {
00904 
00905       o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
00906       podata=cpl_image_get_data_float(o_img);
00907         kpix       = 0 ;
00908         kslit      = 0 ;
00909         slit_index = -1 ;
00910         recol      = -1 ;
00911         for ( col = 0 ; col < ilx ; col++ ) /* go through the image columns */
00912         {
00913             if ( col % imsize == 0 )
00914             {
00915                 recol = 0 ;
00916                 kslit = col/imsize ;
00917                 /* sort the slitlets in the right spiffi specific way */
00918                 if((slit_index=sinfo_sort_slitlets(kslit)) == -1) {
00919                   sinfo_msg_error("wrong slitlet index: couldn't be a "
00920                                "spiffi image,  there must be 32 slitlets!") ;
00921                         cpl_imagelist_delete(returnCube) ;
00922                         return NULL ;
00923                 }
00924 
00925                 if ( kslit != 0 )
00926                 {
00927                     /*-------------------------------------------------------- 
00928                      * shift the first pixel by an integer if the absolute 
00929                      * amount of distances[]
00930                      * is bigger than 0.5 
00931                      */
00932                     kpix = sinfo_new_nint(distances[kslit-1]) ;
00933 
00934                     /*----------------------------------------------- 
00935                      * now sort the distances array according to the row order 
00936                      * and add a 0 value for the first (reference) slitlet 
00937                      * that means row 8 
00938                      */
00939                     correct_diff_dist[slit_index] = distances[kslit-1] - 
00940                                                     (float)kpix ;
00941                 }
00942                 /* refer all distances to the first slitlet */
00943                 else
00944                 {
00945                     correct_diff_dist[slit_index] = 0. ;
00946                 }
00947             }
00948 
00949             /* fill each cube plane with one image row */
00950             podata[recol+slit_index*imsize] = pidata[col+kpix+z*ilx];
00951             recol++ ;
00952 
00953             if ( recol > imsize )
00954             {
00955                 sinfo_msg_error("wrong column of reconstructed "
00956                                 "image, shouldn't happen!\n") ; 
00957                 cpl_imagelist_delete(returnCube) ;
00958                 return NULL ;
00959             }
00960         }
00961     }
00962     return returnCube ;
00963 }
00964 
00965 
00966 
00974 static int
00975 sinfo_sort_slitlets(const int kslit)
00976 {
00977   int slit_index=0;
00978 
00979   switch (kslit)
00980     {
00981     case 0:
00982       slit_index = 8 ;
00983       break ;
00984     case 1:
00985       slit_index = 7 ;
00986       break ;
00987     case 2:
00988       slit_index = 9 ;
00989       break ;
00990     case 3:
00991       slit_index = 6 ;
00992       break ;
00993     case 4:
00994       slit_index = 10 ;
00995       break ;
00996     case 5:
00997       slit_index = 5 ;
00998       break ;
00999     case 6:
01000       slit_index = 11 ;
01001       break ;
01002     case 7:
01003       slit_index = 4 ;
01004       break ;
01005     case 8:
01006       slit_index = 12 ;
01007       break ;
01008     case 9:
01009       slit_index = 3 ;
01010       break ;
01011     case 10:
01012       slit_index = 13 ;
01013       break ;
01014     case 11:
01015       slit_index = 2 ;
01016       break ;
01017     case 12:
01018       slit_index = 14 ;
01019       break ;
01020     case 13:
01021       slit_index = 1 ;
01022       break ;
01023     case 14:
01024       slit_index = 15 ;
01025       break ;
01026     case 15:
01027       slit_index = 0 ;
01028       break ;
01029     case 16:
01030       slit_index = 31 ;
01031       break ;
01032     case 17:
01033       slit_index = 16 ;
01034       break ;
01035     case 18:
01036       slit_index = 30 ;
01037       break ;
01038     case 19:
01039       slit_index = 17 ;
01040       break ;
01041     case 20:
01042       slit_index = 29 ;
01043       break ;
01044     case 21:
01045       slit_index = 18 ;
01046       break ;
01047     case 22:
01048       slit_index = 28 ;
01049       break ;
01050     case 23:
01051       slit_index = 19 ;
01052       break ;
01053     case 24:
01054       slit_index = 27 ;
01055       break ;
01056     case 25:
01057       slit_index = 20 ;
01058       break ;
01059     case 26:
01060       slit_index = 26 ;
01061       break ;
01062     case 27:
01063       slit_index = 21 ;
01064       break ;
01065     case 28:
01066       slit_index = 25 ;
01067       break ;
01068     case 29:
01069       slit_index = 22 ;
01070       break ;
01071     case 30:
01072       slit_index = 24 ;
01073       break ;
01074     case 31:
01075       slit_index = 23 ;
01076       break ;
01077     default:
01078       sinfo_msg_error("wrong slitlet index: couldn't be a "
01079                       "spiffi image,  there must be 32 slitlets!") ;
01080       return -1 ;
01081       break ;
01082                 
01083    }
01084    return slit_index;
01085 
01086 }
01087 
01098 static int
01099 sinfo_sort_slitlets_array(const int slit, int* row_index)
01100 {
01101 
01102   switch (slit)
01103     {
01104     case 0:
01105       row_index[0] = 8 ;
01106       break ;
01107     case 1:
01108       row_index[1] = 7 ;
01109       break ;
01110     case 2:
01111       row_index[2] = 9 ;
01112       break ;
01113     case 3:
01114       row_index[3] = 6 ;
01115       break ;
01116     case 4:
01117       row_index[4] = 10 ;
01118       break ;
01119     case 5:
01120       row_index[5] = 5 ;
01121       break ;
01122     case 6:
01123       row_index[6] = 11 ;
01124       break ;
01125     case 7:
01126       row_index[7] = 4 ;
01127       break ;
01128     case 8:
01129       row_index[8] = 12 ;
01130       break ;
01131     case 9:
01132       row_index[9] = 3 ;
01133       break ;
01134     case 10:
01135       row_index[10] = 13 ;
01136       break ;
01137     case 11:
01138       row_index[11] = 2 ;
01139       break ;
01140     case 12:
01141       row_index[12] = 14 ;
01142       break ;
01143     case 13:
01144       row_index[13] = 1 ;
01145       break ;
01146     case 14:
01147       row_index[14] = 15 ;
01148       break ;
01149     case 15:
01150       row_index[15] = 0 ;
01151       break ;
01152     case 16:
01153       row_index[16] = 31 ;
01154       break ;
01155     case 17:
01156       row_index[17] = 16 ;
01157       break ;
01158     case 18:
01159       row_index[18] = 30 ;
01160       break ;
01161     case 19:
01162       row_index[19] = 17 ;
01163       break ;
01164     case 20:
01165       row_index[20] = 29 ;
01166       break ;
01167     case 21:
01168       row_index[21] = 18 ;
01169       break ;
01170     case 22:
01171       row_index[22] = 28 ;
01172       break ;
01173     case 23:
01174       row_index[23] = 19 ;
01175       break ;
01176     case 24:
01177       row_index[24] = 27 ;
01178       break ;
01179     case 25:
01180       row_index[25] = 20 ;
01181       break ;
01182     case 26:
01183       row_index[26] = 26 ;
01184       break ;
01185     case 27:
01186       row_index[27] = 21 ;
01187       break ;
01188     case 28:
01189       row_index[28] = 25 ;
01190       break ;
01191     case 29:
01192       row_index[29] = 22 ;
01193       break ;
01194     case 30:
01195       row_index[30] = 24 ;
01196       break ;
01197     case 31:
01198       row_index[31] = 23 ;
01199       break ;
01200     default:
01201       sinfo_msg_error("wrong slitlet index: couldn't be a spiffi "
01202                       "image,  there must be 32 slitlets!\n") ;
01203       return -1 ;
01204     }
01205 
01206   return 0;
01207 
01208 }
01209 
01210 
01211 
01228 cpl_imagelist * 
01229 sinfo_new_make_cube_spi ( cpl_image *  calibImage,
01230                         float    ** slit_edges,
01231                         float    *  shift )
01232 {
01233     cpl_imagelist * returnCube ;
01234     float diff, start ;
01235     float * center ;
01236     int * row_index ;
01237     int slit ;
01238     int col, z ;
01239     int imsize ;
01240     int * beginCol ;
01241     int col_counter ;
01242     int ilx=0;
01243     int ily=0;
01244 
01245     float* podata=NULL;
01246     float* pidata=NULL;
01247     cpl_image* o_img;
01248 
01249 
01250     if ( NULL == calibImage )
01251     {
01252         sinfo_msg_error("no resampled image given!\n") ;
01253         return NULL ;
01254     }
01255     ilx=cpl_image_get_size_x(calibImage);
01256     ily=cpl_image_get_size_y(calibImage);
01257     pidata=cpl_image_get_data_float(calibImage);
01258 
01259     if ( NULL == slit_edges )
01260     {
01261         sinfo_msg_error("no slit_edges array given from sinfo_fitSlits()!/n") ;
01262         return NULL ;
01263     }
01264 
01265     if ( N_SLITLETS != 32 )
01266     {
01267         sinfo_msg_error ("wrong number of slitlets given \n" ) ;
01268         return NULL ;
01269     }
01270     imsize = ilx / N_SLITLETS ;
01271 
01272     /* allocate memory */  
01273     if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
01274     {
01275         sinfo_msg_error ("cannot allocate memory \n" ) ;
01276         return NULL ;
01277     }
01278     if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
01279     {
01280         sinfo_msg_error ("cannot allocate memory \n" ) ;
01281         cpl_free(row_index) ;
01282         return NULL ;
01283     }
01284     if ( NULL == (center = (float*) cpl_calloc(N_SLITLETS, sizeof(float)) ) )
01285     {
01286         sinfo_msg_error ("cannot allocate memory \n" ) ;
01287         cpl_free (row_index) ;
01288         cpl_free (beginCol) ;
01289         return NULL ;
01290     }
01291     if ( NULL == (returnCube = cpl_imagelist_new()) )
01292     {
01293         sinfo_msg_error ("cannot allocate new cube \n" ) ;
01294         cpl_free (row_index) ;
01295         cpl_free (beginCol) ;
01296         cpl_free (center) ;
01297         return NULL ;
01298     }
01299     /* determine the absolute center of the slitlets and the distances 
01300        inside the image*/
01301     for ( slit = 0 ; slit < N_SLITLETS ; slit++ ) 
01302     /* go through the slitlets of each row of the resampled image */
01303     {
01304         center[slit] = (slit_edges[slit][1] + slit_edges[slit][0]) / 2. ;
01305         /* -------------------------------------------------------------
01306          * sort the slitlets in the right spiffi specific way
01307          * the row_index describes the row index of the current slitlet 
01308          * in the resulting cube images.
01309          */
01310         if(-1 == sinfo_sort_slitlets_array(slit,row_index)) {
01311       cpl_imagelist_delete(returnCube) ;
01312       cpl_free (row_index) ;
01313           cpl_free (beginCol) ;
01314           cpl_free (center) ;
01315           return NULL ;
01316         }
01317         /* determine the integer column on which the slitlet starts, center the
01318            slitlet on the image row */
01319         start = center[slit] - (float) (imsize - 1)/2. ;
01320         beginCol[slit] = sinfo_new_nint (start) ;
01321         /* determine the error of using integer pixels */
01322         diff = start - (float)beginCol[slit] ;
01323 
01324         /*-------------------------------------------------------------------- 
01325          * determine the output shift values by which the rows are finally 
01326            shifted, consider the integer pixel errors  
01327          * resort shift array to get the row index 
01328          */
01329         shift[row_index[slit]] = diff ;
01330     }   
01331 
01332     /* now build the data cube out of the resampled image */
01333     for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
01334     {
01335       o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
01336       podata=cpl_image_get_data_float(o_img);
01337       for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
01338         {
01339       col_counter = beginCol[slit] ;
01340       /* each slitlet is centered on the final image row */
01341       for ( col = 0 ; col < imsize ; col++ )
01342             {
01343           if ( col_counter > ilx-1 )
01344                 {
01345           col_counter-- ;
01346                 }
01347           if ( col_counter + z*ilx < 0 )
01348                 {
01349           podata[col+row_index[slit]*imsize] = pidata[0] ;
01350                 }
01351               else
01352                 {   
01353                   podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
01354                 }
01355 
01356                 col_counter++ ;
01357             }
01358         }
01359       cpl_imagelist_set(returnCube,o_img,z);    
01360     }
01361     cpl_free (row_index) ;
01362     cpl_free (beginCol) ;
01363     cpl_free (center) ;
01364 
01365     return returnCube ;
01366 }
01393 cpl_imagelist * 
01394 sinfo_new_make_cube_dist ( cpl_image * calibImage,
01395                          float      firstCol,
01396                          float    * distances,
01397                          float    * shift )
01398 {
01399     cpl_imagelist * returnCube ;
01400     float di ;
01401     float diff, start ;
01402     int * row_index ;
01403     int slit ;
01404     int col, z ;
01405     int imsize ;
01406     int * beginCol ;
01407     int col_counter ;
01408     int ilx=0;
01409     int ily=0;
01410 
01411     float* podata=NULL;
01412     float* pidata=NULL;
01413     cpl_image* o_img;
01414 
01415     if ( NULL == calibImage )
01416     {
01417         sinfo_msg_error(" no resampled image given!\n") ;
01418         return NULL ;
01419     }
01420     ilx=cpl_image_get_size_x(calibImage);
01421     ily=cpl_image_get_size_y(calibImage);
01422     pidata=cpl_image_get_data_float(calibImage);
01423 
01424     if ( NULL == distances )
01425     {
01426         sinfo_msg_error("no distances array given from north_south_test()!") ;
01427         return NULL ;
01428     }
01429 
01430     if ( N_SLITLETS != 32 )
01431     {
01432         sinfo_msg_error ("wrong number of slitlets given \n" ) ;
01433         return NULL ;
01434     }
01435     imsize = ilx / N_SLITLETS ;
01436 
01437     /* allocate memory */  
01438     if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
01439     {
01440         sinfo_msg_error ("cannot allocate memory \n" ) ;
01441         return NULL ;
01442     }
01443     if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
01444     {
01445         sinfo_msg_error ("cannot allocate memory \n" ) ;
01446         cpl_free(row_index) ;
01447         return NULL ;
01448     }
01449     if ( NULL == (returnCube = cpl_imagelist_new()) )
01450     {
01451         sinfo_msg_error ("cannot allocate new cube \n" ) ;
01452         cpl_free(row_index) ;
01453         cpl_free(beginCol) ;
01454         return NULL ;
01455     }
01456 
01457     di = 0. ;
01458     /* determine the absolute beginning of the slitlets and the distances 
01459        inside the image*/
01460     for ( slit = 0 ; slit < N_SLITLETS ; slit++ ) 
01461     /* go through the slitlets of each row of the resampled image */
01462     {
01463 
01464         /* -------------------------------------------------------------
01465          * sort the slitlets in the right spiffi specific way
01466          * the row_index describes the row index of the current slitlet 
01467          * in the resulting cube images.
01468          */
01469         if(-1 == sinfo_sort_slitlets_array(slit,row_index)) {
01470       cpl_imagelist_delete(returnCube) ;
01471       cpl_free(row_index) ;
01472       cpl_free(beginCol) ;
01473       return NULL ;
01474         }
01475 
01476         /* determine the integer column on which the slitlet starts */
01477         if ( slit == 0 )
01478         {
01479             start = firstCol ;
01480         }
01481         else
01482         {
01483             di += distances[slit-1] ;
01484             start = firstCol + di ;
01485         }
01486         beginCol[slit] = sinfo_new_nint(start) ;
01487 
01488         /* determine the error of using integer pixels, its always smaller 
01489            than 1 */
01490         diff = start - (float)beginCol[slit] ;
01491 
01492         /*---------------------------------------------------------------- 
01493          * determine the output shift values by which the rows are finally 
01494          * shifted, consider the integer pixel errors and resort shift array 
01495          * to get the row index 
01496          */
01497         shift[row_index[slit]] = diff ;
01498     }   
01499 
01500     /* now build the data cube out of the resampled image */
01501     for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
01502     {
01503       o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
01504       podata=cpl_image_get_data_float(o_img);
01505       for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
01506         {
01507       col_counter = beginCol[slit] ;
01508       /* each slitlet is centered on the final image row */
01509       for ( col = 0 ; col < imsize ; col++ )
01510             {
01511           if ( col_counter > ilx-1 )
01512                 {
01513           col_counter-- ;
01514                 }
01515                 if ( col_counter + z*ilx < 0 )
01516                 {
01517           podata[col+row_index[slit]*imsize] = podata[0] ;
01518                 }
01519                 else
01520                 {   
01521                   podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
01522                 }
01523 
01524                 col_counter++ ;
01525             }
01526         }  
01527       cpl_imagelist_set(returnCube,o_img,z);  
01528     }
01529     cpl_free (row_index) ;
01530     cpl_free (beginCol) ;
01531 
01532     return returnCube ;
01533 }
01560 cpl_imagelist * 
01561 sinfo_new_make_3D_cube_dist ( cpl_image * calibImage,
01562                            float      firstCol,
01563                            float    * distances,
01564                            float    * shift )
01565 {
01566     cpl_imagelist * returnCube ;
01567     float di ;
01568     float diff, start ;
01569     int * row_index ;
01570     int slit ;
01571     int col, z ;
01572     int imsize ;
01573     int * beginCol ;
01574     int col_counter ;
01575     int ilx=0;
01576     int ily=0;
01577 
01578     float* podata=NULL;
01579     float* pidata=NULL;
01580     cpl_image* o_img;
01581 
01582     if ( NULL == calibImage )
01583     {
01584         sinfo_msg_error(" no resampled image given!\n") ;
01585         return NULL ;
01586     }
01587     ilx=cpl_image_get_size_x(calibImage);
01588     ily=cpl_image_get_size_y(calibImage);
01589     pidata=cpl_image_get_data_float(calibImage);
01590 
01591     if ( NULL == distances )
01592     {
01593         sinfo_msg_error("no distances array given from north_south_test()!") ;
01594         return NULL ;
01595     }
01596 
01597     if ( N_SLITLETS != 16 )
01598     {
01599         sinfo_msg_error ("wrong number of slitlets given \n" ) ;
01600         return NULL ;
01601     }
01602     imsize = ilx / N_SLITLETS ;
01603 
01604     /* allocate memory */  
01605     if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
01606     {
01607         sinfo_msg_error ("cannot allocate memory \n" ) ;
01608         return NULL ;
01609     }
01610     if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
01611     {
01612         sinfo_msg_error ("cannot allocate memory \n" ) ;
01613         cpl_free(row_index) ;
01614         return NULL ;
01615     }
01616     if ( NULL == (returnCube = cpl_imagelist_new()) )
01617     {
01618         sinfo_msg_error ("cannot allocate new cube \n" ) ;
01619         cpl_free(row_index) ;
01620         cpl_free(beginCol) ;
01621         return NULL ;
01622     }
01623 
01624     di = 0. ;
01625     /* determine the absolute beginning of the slitlets and the distances 
01626        inside the image*/
01627     for ( slit = 0 ; slit < N_SLITLETS ; slit++ ) 
01628     /* go through the slitlets of each row of the resampled image */
01629     {
01630 
01631         /* --------------------------------------------------------------
01632          * sort the slitlets in the right 3D specific way
01633          * the row_index describes the row index of the current slitlet 
01634          * in the resulting cube images.
01635          */
01636         row_index[slit] = slit ;
01637 
01638         /* determine the integer column on which the slitlet starts */
01639         if ( slit == 0 )
01640         {
01641             start = firstCol ;
01642         }
01643         else
01644         {
01645             di += distances[slit-1] ;
01646             start = firstCol + di ;
01647         }
01648         beginCol[slit] = sinfo_new_nint(start) ;
01649 
01650         /* determine the error of using integer pixels, 
01651            `its always smaller than 1 */
01652         diff = start - (float)beginCol[slit] ;
01653 
01654         /*---------------------------------------------------------------- 
01655          * determine the output shift values by which the rows are finally 
01656            shifted, consider the integer pixel errors and resort shift array 
01657            to get the row index 
01658          */
01659         shift[row_index[slit]] = diff ;
01660     }   
01661 
01662     /* now build the data cube out of the resampled image */
01663     for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
01664     {
01665       o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
01666       podata=cpl_image_get_data_float(o_img);
01667         for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
01668         {
01669             col_counter = beginCol[slit] ;
01670             /* each slitlet is centered on the final image row */
01671             for ( col = 0 ; col < imsize ; col++ )
01672             {
01673                 if ( col_counter > ilx-1 )
01674                 {
01675                     col_counter-- ;
01676                 }
01677                 podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
01678                 col_counter++ ;
01679             }
01680         } 
01681         cpl_imagelist_set(returnCube,o_img,z);   
01682     }
01683     cpl_free (row_index) ;
01684     cpl_free (beginCol) ;
01685 
01686     return returnCube ;
01687 }
01688 
01706 cpl_imagelist * 
01707 sinfo_new_make_3D_cube ( cpl_image * calibImage,
01708                        int      * kpixshift, 
01709                        int        kpixfirst )
01710 {
01711     cpl_imagelist * returnCube ;
01712     int imsize, kslit, kpix ;
01713     int z, col, recol ;
01714     int ilx=0;
01715     int ily=0;
01716 
01717     float* podata=NULL;
01718     float* pidata=NULL;
01719     cpl_image* o_img;
01720 
01721     if ( NULL == calibImage )
01722     {
01723         sinfo_msg_error("no resampled image given!\n") ;
01724         return NULL ;
01725     }
01726     ilx=cpl_image_get_size_x(calibImage);
01727     ily=cpl_image_get_size_y(calibImage);
01728     pidata=cpl_image_get_data_float(calibImage);
01729 
01730     if ( NULL == kpixshift )
01731     {
01732         sinfo_msg_error("no shift array given!/n") ;
01733         return NULL ;
01734     }
01735 
01736     if ( kpixfirst < 0 )
01737     {
01738         sinfo_msg_error("wrong first valid pixel given!/n") ;
01739         return NULL ;
01740     }
01741 
01742     if ( N_SLITLETS != 16 )
01743     {
01744         sinfo_msg_error ("wrong number of slitlets given \n" ) ;
01745         return NULL ;
01746     }
01747     imsize = ilx / N_SLITLETS ;
01748 
01749     if ( NULL == (returnCube = cpl_imagelist_new()) )
01750     {
01751         sinfo_msg_error ("cannot allocate new cube \n" ) ;
01752         return NULL ;
01753     }
01754 
01755     /* now build the data cube out of the resampled image */
01756     for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
01757     {
01758       o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
01759       podata=cpl_image_get_data_float(o_img);
01760         kpix       = 0 ;
01761         kslit      = 0 ;
01762         recol      = -1 ;
01763         for ( col = 0 ; col < ilx ; col++ ) /* go through the image columns */
01764         {
01765             if ( col % imsize == 0 ) 
01766             {
01767                 recol = 0 ;
01768                 kslit = col/imsize ;
01769                 kpix  = kpixfirst + kpixshift[kslit] ;
01770             }
01771 
01772             /* fill each cube plane with one image row */
01773             podata[recol+kslit*imsize] = pidata[col+kpix+z*ilx] ;
01774             recol++ ;
01775             if ( recol > imsize )
01776             {
01777                 sinfo_msg_error("wrong column of reconstructed image, i"
01778                                 "shouldn't happen!\n") ; 
01779                 cpl_imagelist_delete(returnCube) ;
01780                 return NULL ;
01781             }
01782         }
01783         cpl_imagelist_set(returnCube,o_img,z);
01784     }
01785     return returnCube ;
01786 }
01787 
01800 cpl_imagelist * 
01801 sinfo_new_determine_mask_cube ( cpl_imagelist * sourceMaskCube,
01802                               float     lowLimit,
01803                               float     highLimit )
01804 {
01805     cpl_imagelist * retCube ; 
01806     int z, n ;
01807     int ilx=0;
01808     int ily=0;
01809     int inp=0;
01810     int olx=0;
01811     int oly=0;
01812     int onp=0;
01813     float* podata=NULL;
01814     cpl_image* o_img;
01815 
01816     if ( sourceMaskCube == NULL )
01817     {
01818         sinfo_msg_error("no cube given!\n") ;
01819         return NULL ;
01820     }
01821     ilx=cpl_image_get_size_x(cpl_imagelist_get(sourceMaskCube,0));
01822     ily=cpl_image_get_size_y(cpl_imagelist_get(sourceMaskCube,0));
01823     inp=cpl_imagelist_get_size(sourceMaskCube);
01824 
01825 
01826     if ( lowLimit > 0. )
01827     {
01828         sinfo_msg_error("lowLimit wrong!\n") ;
01829         return NULL ;
01830     }
01831     if ( highLimit >= 1. || highLimit < 0. )
01832     {
01833         sinfo_msg_error("highLimit wrong!\n") ;
01834         return NULL ;
01835     }
01836 
01837     retCube = cpl_imagelist_duplicate (sourceMaskCube) ;
01838     onp=inp;
01839     olx=ilx;
01840     oly=ily;
01841 
01842     for ( z = 0 ; z < onp ; z++ )
01843     {
01844       o_img=cpl_imagelist_get(retCube,0);
01845       podata=cpl_image_get_data_float(o_img);
01846         for ( n = 0 ; n < (int) olx*oly; n++ )
01847         {
01848             if ( podata[n] == 0. )
01849             {
01850                continue ;
01851             }
01852             if ( podata[n] == 1. )
01853             {
01854                continue ;
01855             }
01856             if ( podata[n] >= lowLimit && 
01857                  podata[n] <= highLimit )
01858             {
01859                 podata[n] = 0. ;
01860             }
01861             else 
01862             {
01863                 podata[n] = 1. ;
01864             }
01865         }
01866     }
01867     return retCube ;
01868 }
01907 cpl_imagelist * 
01908 sinfo_new_interpol_cube ( cpl_imagelist * sourceCube,
01909                          cpl_imagelist * maskCube,
01910                          int       n_neighbors, /* 7 */
01911                          int       max_radius ) /* 5 */
01912 {
01913     cpl_imagelist  * returnCube ;
01914     float** spec=NULL ;
01915     float* spec1=NULL ;
01916     int n_im, n_bad, n_bad1, n_bad2 ;
01917     int n_planes, specn, nspec1 ;
01918     int i, m, n, z, ni, kk, p ;
01919     int dis, dismin, dismax ;
01920     int agreed ;
01921     int xcordi, ycordi, xcordm, ycordm ;
01922 
01923 
01924 
01925     int ilx=0;
01926     int ily=0;
01927     int inp=0;
01928    
01929     float* pidata=NULL;
01930     float* pmdata=NULL;
01931     float* podata=NULL;
01932     cpl_image* i_img=NULL;
01933     cpl_image* m_img=NULL;
01934     cpl_image* o_img=NULL;
01935 
01936     if ( NULL == sourceCube )
01937     {
01938         sinfo_msg_error(" no source cube given!\n") ;
01939         return NULL ;
01940     }
01941 
01942 
01943     ilx=cpl_image_get_size_x(cpl_imagelist_get(sourceCube,0));
01944     ily=cpl_image_get_size_y(cpl_imagelist_get(sourceCube,0));
01945     inp=cpl_imagelist_get_size(sourceCube);
01946 
01947     if ( NULL == maskCube )
01948     {
01949         sinfo_msg_error("no bad pixel mask cube given!\n") ;
01950         return NULL ;
01951     }
01952 
01953     if ( n_neighbors <= 0 )
01954     {
01955         sinfo_msg_error("wrong number of neighbors in the spectral "
01956                         "direction given!") ;
01957         return NULL ;
01958     }
01959    
01960     if ( max_radius <= 0 )
01961     {
01962         sinfo_msg_error("wrong maximal radius for interpolation inside "
01963                         "an image plane given!") ;
01964         return NULL ;
01965     }
01966 
01967     returnCube = cpl_imagelist_duplicate(sourceCube) ;
01968     
01969     n_im     = ilx * ily ;
01970     n_planes = inp ;
01971 
01972     spec1=cpl_calloc(300,sizeof(float)) ;
01973     spec=sinfo_new_2Dfloatarray(100,2*n_neighbors+1) ;
01974 
01975     /* loop over the image planes and look for bad pixels and correct them */
01976     for ( z = 0 ; z < n_planes ; z++ ) /* go through image planes */
01977     {
01978       m_img=cpl_imagelist_get(maskCube,z);
01979       pmdata=cpl_image_get_data_float(m_img);
01980       o_img=cpl_imagelist_get(returnCube,z);
01981       podata=cpl_image_get_data_float(o_img);
01982 
01983         /*-------------------------------------------------------------------
01984          * determine n, the length of one wing in one spectrum with which the 
01985          * bad pixel will be interpolated. The length of one wing is 
01986            n_neighbors but less at the edges of the cube. 
01987          */
01988         if ( z < n_neighbors )
01989         {
01990             n = z ;
01991         }
01992         else if ( n_planes - z <= n_neighbors)
01993         {
01994             n = n_planes - z -1 ;
01995         }
01996         else
01997         { 
01998             n = n_neighbors ;
01999         }
02000 
02001         for ( i = 0 ; i < n_im ; i ++ ) /* go through one image */
02002         {
02003             /* continue if the pixel is a good one */
02004             if ( pmdata[i] != 0. )
02005             {
02006                 continue ;
02007             }
02008         
02009             /*-------------------------------------------------------------
02010              * exclude pixels with too many bad neighbors in the spectrum.
02011              * exit if: too few good pixels in the neighboring spectrum or 
02012              * good pixels are only on one side of the spectrum.
02013              */
02014             n_bad  = 0 ;
02015             n_bad1 = 0 ;
02016             n_bad2 = 0 ;
02017             /* go through the neighbor spectral pixels */
02018             for ( ni = z-n ; ni <= z+n ; ni++ ) 
02019             {
02020                 if ( pmdata[i] == 0. )
02021                 {
02022                     n_bad++ ;
02023                     /* count bad pixels on either spectral side of 
02024                        the bad pixel to be interpolated */
02025                     if ( ni < z )
02026                     {
02027                         n_bad1++ ;
02028                     }
02029                     if ( ni > z )
02030                     {
02031                         n_bad2++ ;
02032                     }
02033                 }
02034             }
02035          
02036             /*--------------------------------------------------------------- 
02037              * now the criteria are checked which the neighborhood in the 
02038                spectral dimension has to match if the pixel is interpolatable.
02039              * The total number of the good pixel in the spectrum must be more 
02040                than 3 and there must be at least one good pixel on either side 
02041                of the central pixel.
02042              */
02043             if ( (2*n+1 - n_bad) < 3 || (n - n_bad1) < 1 || (n - n_bad2) < 1 )
02044             {
02045                 continue ;
02046             }
02047             
02048             /* read the master spectrum into the first row of the array spec */
02049             kk = 0 ;
02050             for ( ni = z-n ; ni <= z+n ; ni++ )
02051             {
02052           i_img=cpl_imagelist_get(sourceCube,ni);
02053               pidata=cpl_image_get_data_float(i_img);
02054                 spec[1][kk] = pmdata[i] != 0. ? pidata[i] : ZERO ;
02055                 kk++ ; /* length of spectrum */
02056             }
02057             
02058             /* look for appropriate neighbors in the x-y neighborhood */
02059             agreed = 1 ; /* loop guard */
02060             specn  = 2 ; /* number of spectra in spec. 
02061                             First is master spectrum */
02062             dismin = 0 ; /* x+y minimal distance to bad pixel */
02063             dismax = 1 ; /* x+y maximal distance to bad pixel */
02064             do
02065             {
02066                 for ( m = 0 ; m < n_im ; m++ )
02067                 {
02068                     if ( pmdata[m] == 0. )
02069                     {
02070                         continue ;
02071                     }
02072 
02073                     /* --------------------------------------------------------
02074                      * determine the x and y coordinates of the bad pixel (i)
02075                      * and the pixels used to interpolate (m) 
02076                      */
02077                     xcordi = i % ilx ;
02078                     xcordm = m % ilx ;
02079                     ycordi = i / ilx ;
02080                     ycordm = m / ilx ;
02081                     /*----------------------------------------------------- 
02082                      * check the distance: take only close pixels
02083                      * extension 'i' is coordinate of the bad pixel to be 
02084                        interpolated
02085                      */
02086                     dis = abs(xcordi-xcordm) + abs(ycordi-ycordm) ;
02087                     if ( dis <= dismin || dis > dismax )
02088                     {
02089                         continue ;
02090                     }
02091                     /*--------------------------------------------------------
02092                      * check on number of bad pixels in the spectrum of a 
02093                      * neighbor pixel; reject it if it contains less than 2 
02094                      * usable pixel pairs. a bit more explanation:
02095                      * let this be a 15 pixel spectrum with the pixel to be 
02096                      * interpolated denoted by '0' and other bad pixels marked 
02097                      * with 'b'. Good pixels are marked with '1'. Below a 
02098                      * neighbor spectrum is drawn containing bad pixels as 
02099                      * well. The third line shows the position of the usable 
02100                      * pixel pairs, spectral
02101                      * positions, where both spectra have valid pixels.
02102                      *
02103                      *   1 1 1 b b 1 1 0 b 1 b b 1 b b
02104                      *   b 1 1 1 b b 1 1 1 1 1 1 b b 1
02105                      *     ^ ^       ^     ^             4 good pixel pairs
02106                      */
02107       
02108                     n_bad = 0 ;
02109                     for ( ni = z-n ; ni <= z+n ; ni++ )
02110                     {
02111                         if ( pmdata[i] == 0. || pmdata[m] == 0. )
02112                         {
02113                             n_bad++ ;
02114                         }
02115                     }
02116                     if ( n_bad > 2*n-1 ) 
02117                     /* we need at least 2 usable pixel pairs */
02118                     {
02119                         continue ;
02120                     }
02121                     
02122                     /* transfer the spectrum to the next position 
02123                        of array spec */
02124                     kk = 0 ;
02125                     for ( ni = z-n ; ni <= z+n ; ni++ )
02126                     {
02127               i_img=cpl_imagelist_get(sourceCube,ni);
02128               pidata=cpl_image_get_data_float(i_img);
02129                         spec[specn][kk] = pmdata[m] != 0. ? pidata[m] : ZERO ;
02130                         kk++ ;
02131                     }
02132                     specn++ ;
02133                     if ( specn > 10 ) /* if we have 9 neighbors then break */
02134                     {
02135                         agreed = 0 ;
02136                         break ;
02137                     }
02138                 }
02139                 /* if no break, increase search radius and continue */
02140                 dismin++ ;        
02141                 dismax++ ;
02142                 /* if search radius is too big, exit with fewer 
02143                    good neighbors */
02144                 if ( dismax > max_radius )
02145                 {
02146                     agreed = 0 ;
02147                 }
02148             }   while(agreed) ;    
02149                        
02150             specn-- ;
02151             dismax -= 2 ;
02152 
02153             /* ---------------------------------------------------------------
02154              * Take the master spectrum with the bad pixel in the middle and 
02155                divide it by each of the neighbor spectra and normalize the 
02156                division with the value in  the center position.
02157              */
02158             for ( kk = 0 ; kk < 2*n+1 ; kk++ )
02159             {
02160                 if ( kk == n )    /* do not divide the master bad pixel */
02161                 {
02162                     continue ;
02163                 }
02164 
02165                 /* do not divide bad pixels in the master spectrum */
02166                 if ( isnan(spec[1][kk]) ) 
02167                 {
02168                     for ( p = 2 ; p <= specn ; p++ )
02169                     {
02170                         spec[p][kk] = ZERO ;
02171                     }
02172                 }    
02173                 else       /* all is well, now divide */
02174                 {
02175                     for ( p = 2 ; p <= specn ; p++ )
02176                     {
02177                         if ( !isnan(spec[p][kk]) && spec[p][kk] != 0. &&
02178                              !isnan(spec[p][n]) )
02179                         {
02180                             spec[p][kk] = spec[1][kk] / 
02181                                           spec[p][kk] * spec[p][n] ;
02182                         }
02183                         else
02184                         {
02185                             spec[p][kk] = ZERO ;
02186                         }
02187                     }
02188                 }
02189             }
02190  
02191             /*-----------------------------------------------------------------
02192              * determine the sinfo_median of all values. With 9 good neighbors 
02193              * and at least 2 good values per neighbor we have between 18 and 
02194              * 9*14 values for the statistics. If there are not enough good 
02195              * neighbors available, only continue if we have collected at 
02196              * least 18 values.
02197              */
02198             nspec1 = 0 ;  
02199             /* collect the good values in the array spec1 */ 
02200             for ( p = 2 ; p <= specn ; p++ )
02201             {
02202                 for ( kk = 0 ; kk < 2*n+1 ; kk++ )
02203                 {
02204                     if ( !isnan(spec[p][kk]) && kk != n )
02205                     {
02206                         spec1[nspec1] = spec[p][kk] ;
02207                         nspec1++ ;
02208                     }
02209                 }
02210             }
02211             
02212             /* now test if we have at least 18 values */
02213             if ( nspec1 < 18 )
02214             {
02215                 continue ;
02216             }
02217  
02218             /* interpolate the bad pixel by the sinfo_median of spec1 */
02219             podata[i] = sinfo_new_median(spec1, nspec1) ;
02220             pmdata[i] = 1 ;
02221         }
02222     }           
02223     sinfo_new_destroy_2Dfloatarray(&spec,2*n_neighbors+1) ;
02224     cpl_free(spec1);
02225     return returnCube ;
02226 }
02247 cpl_imagelist * 
02248 sinfo_new_fine_tune_cube( cpl_imagelist * cube,
02249                                      float   * correct_diff_dist,
02250                                      int       n_order )
02251 {
02252     cpl_imagelist * returnCube ;
02253     float* row_data=NULL ;
02254     float* corrected_row_data=NULL ;
02255     float* xnum=NULL ;
02256     float sum, new_sum ;
02257     float eval/*, dy*/ ;
02258     float * imageptr ;
02259     int row, col ;
02260     int i, z ;
02261     int imsize, n_points ;
02262     int firstpos ;
02263     int  flag;
02264     int ilx=0;
02265     int ily=0;
02266     int inp=0;
02267    
02268     float* pidata=NULL;
02269     float* podata=NULL;
02270     cpl_image* i_img=NULL;
02271     cpl_image* o_img=NULL;
02272 
02273 
02274     if ( NULL == cube )
02275     {
02276         sinfo_msg_error("no input cube given!\n") ;
02277         return NULL ;
02278     }
02279     ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
02280     ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
02281     inp=cpl_imagelist_get_size(cube);
02282 
02283     if ( NULL == correct_diff_dist )
02284     {
02285         sinfo_msg_error("no distances array from ns_test given!n") ;
02286         return NULL ;
02287     }
02288   
02289     if ( n_order <= 0 )
02290     {
02291         sinfo_msg_error("wrong order of interpolation polynom given!") ;
02292     returnCube = cpl_imagelist_duplicate(cube);
02293         return returnCube ;
02294     }
02295 
02296     returnCube = cpl_imagelist_duplicate(cube);
02297     
02298     imsize = ily ;
02299     if ( imsize != N_SLITLETS )
02300     {
02301         sinfo_msg_error ("wrong image size\n" ) ;
02302         return NULL ;
02303     }
02304 
02305     n_points = n_order + 1 ;
02306     if ( n_points % 2 == 0 )
02307     {
02308         firstpos = (int)(n_points/2) - 1 ;
02309     }
02310     else
02311     {
02312         firstpos = (int)(n_points/2) ;
02313     }
02314     xnum=cpl_calloc(n_order+1,sizeof(float)) ;
02315 
02316     for ( i = 0 ; i < n_points ; i++ )
02317     {
02318         xnum[i] = i ;
02319     }    
02320 
02321     row_data=cpl_calloc(ilx,sizeof(float)) ;
02322     corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
02323 
02324     for ( z = 0 ; z < inp ; z++ )
02325     {
02326       i_img=cpl_imagelist_get(cube,z);
02327       pidata=cpl_image_get_data_float(i_img);
02328       o_img=cpl_imagelist_get(returnCube,z);
02329       podata=cpl_image_get_data_float(o_img);
02330 
02331 
02332         for ( row = 0 ; row < imsize ; row++ )
02333         {
02334             for ( col = 0 ; col < ilx ; col++ )
02335             {
02336                 corrected_row_data[col] = 0. ;
02337             }
02338             sum = 0. ; 
02339             for ( col = 0 ; col < ilx ; col++ )
02340             {
02341                 row_data[col] = pidata[col+row*ilx] ;
02342                 if ( isnan(row_data[col]) )
02343                 {
02344                     row_data[col] = 0. ;
02345                     for ( i = col - firstpos ; 
02346                           i < col -firstpos+n_points ; i++ )
02347                     {
02348                         if ( i < 0 ) continue ;
02349                         if ( i >= ilx) continue ; 
02350                         corrected_row_data[i] = ZERO ;
02351                     }
02352                 }
02353                 if ( col != 0 && col != ilx - 1 )
02354                 {
02355                     sum += row_data[col] ;
02356                 }
02357             }
02358 
02359            
02360             new_sum = 0. ;
02361             for ( col = 0 ; col < ilx ; col++ )
02362             {
02363                 
02364                 if ( isnan(corrected_row_data[col]) )
02365                 {
02366                     continue ;
02367                 }
02368                 if ( col - firstpos < 0 )
02369                 {
02370                     imageptr = &row_data[0] ;
02371                     eval     = correct_diff_dist[row] + col ;
02372                 }
02373                 else if ( col - firstpos + n_points >= ilx )
02374                 {
02375                     imageptr = &row_data[ilx - n_points] ;
02376                     eval     = correct_diff_dist[row] + col + n_points - ilx ;
02377                 }
02378                 else
02379                 {
02380                     imageptr = &row_data[col-firstpos] ;
02381                     eval     = correct_diff_dist[row] + firstpos ;
02382                 }
02383 
02384         
02385         flag = 0;
02386         corrected_row_data[col]=sinfo_new_nev_ille(xnum, imageptr, 
02387                                                        n_order, eval, &flag);
02388 
02389                
02390                 if ( col != 0 && col != ilx - 1 )
02391                 {
02392                     new_sum += corrected_row_data[col] ;
02393                 }
02394             }
02395             for ( col = 0 ; col < ilx ; col++ )
02396             {
02397                 
02398                 if ( col == 0 )
02399                 {
02400                     podata[col+row*ilx] = ZERO ;
02401                 }
02402                 else if ( col == ilx - 1 )
02403                 {
02404                     podata[col+row*ilx] = ZERO ;
02405                 }
02406                 else
02407                 {
02408                     if ( isnan(corrected_row_data[col]) ) 
02409                     {
02410                         podata[col+row*ilx] = ZERO ;
02411                     }
02412                     else
02413                     {
02414                         if ( new_sum == 0. ) new_sum = 1. ;
02415                      
02416                         podata[col+row*ilx] = corrected_row_data[col] ;
02417                     }
02418                 }
02419             }
02420         }
02421     }       
02422 
02423     cpl_free(xnum) ;
02424     cpl_free(row_data) ;
02425     cpl_free(corrected_row_data) ;
02426 
02427     return returnCube ;
02428 }
02429 
02449 cpl_imagelist * 
02450 sinfo_new_fine_tune_cube_by_FFT( cpl_imagelist * cube,
02451                                            float   * correct_diff_dist )
02452 {
02453     cpl_imagelist * returnCube ;
02454 
02455     float* row_data=NULL ;
02456     dcomplex* data=NULL ;
02457     dcomplex* corrected_data=NULL ;
02458 
02459     unsigned nn[1];
02460     /*float corrected_row_data[cube->lx] ;*/
02461     float phi, pphi ;
02462     float coph, siph ;
02463     int row, col ;
02464     int i, z ;
02465     int imsize ;
02466     int blank_indicator ;
02467 
02468 
02469     int ilx=0;
02470     int ily=0;
02471     int inp=0;
02472    
02473     float* pidata=NULL;
02474     float* podata=NULL;
02475     cpl_image* i_img=NULL;
02476     cpl_image* o_img=NULL;
02477 
02478 
02479 
02480     if ( NULL == cube )
02481     {
02482         sinfo_msg_error(" no input cube given!\n") ;
02483         return NULL ;
02484     }
02485     ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
02486     ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
02487     inp=cpl_imagelist_get_size(cube);
02488 
02489     nn[1] = ilx ;
02490     if ( NULL == correct_diff_dist )
02491     {
02492         sinfo_msg_error("no distances array from ns_test given!") ;
02493         return NULL ;
02494     }
02495 
02496     returnCube = cpl_imagelist_duplicate( cube ) ;
02497 
02498     imsize = ily ;
02499     if ( imsize != N_SLITLETS )
02500     {
02501         sinfo_msg_error ("wrong image size\n" ) ;
02502         return NULL ;
02503     }
02504 
02505     data=cpl_calloc(ilx,sizeof(dcomplex)) ;
02506     corrected_data=cpl_calloc(ilx,sizeof(dcomplex)) ;
02507 
02508     row_data=cpl_calloc(ilx,sizeof(float)) ;
02509     /* loop over the image planes */
02510     for ( z = 0 ; z < inp ; z++ )
02511     {
02512       i_img=cpl_imagelist_get(cube,z);
02513       pidata=cpl_image_get_data_float(i_img);
02514       o_img=cpl_imagelist_get(returnCube,z);
02515       podata=cpl_image_get_data_float(o_img);
02516         /* consider one row at a time */
02517         for ( row = 0 ; row < imsize ; row++ )
02518         {
02519             blank_indicator = 1 ;
02520             for ( col = 0 ; col < ilx ; col++ )
02521             {
02522                 /* transfer the row data to a double sized array */
02523                 row_data[col] = pidata[col+row*ilx] ;
02524         data[col].x = row_data[col] ;
02525         data[col].y = 0. ;
02526                 /* if row contains a blank pixel proceed */
02527                 if ( isnan(row_data[col]) )
02528                 {
02529                     blank_indicator = 0 ; 
02530                 }
02531             }
02532 
02533             /* if row contains a blank don't apply FFT but proceed */
02534             if ( blank_indicator == 0 )
02535             {
02536                 for ( col = 0 ; col < ilx ; col++ )
02537                 {
02538                     podata[col+row*ilx] = ZERO ;
02539                 }
02540                 continue ;
02541             }
02542            
02543             /* FFT algorithm of eclipse */
02544             sinfo_fftn( data, nn, 1, 1 ) ;
02545  
02546             /* calculate the corrected phase shift for each frequency */
02547             phi = 2*PI_NUMB/(float)ilx * correct_diff_dist[row] ;
02548             for ( i = 0 ; i < ilx ; i++ )
02549             {
02550                 /* positive frequencies */
02551                 if ( i <= ilx/2 )
02552                 {
02553                     /* phase shift */
02554                     pphi = phi * (float)(i) ;
02555                     /* Euler factor */
02556                     coph = cos ( pphi ) ;
02557                     siph = sin ( pphi ) ;
02558                 }
02559                 else /* negative frequencies */
02560                 {
02561                     /* phase shift */
02562                     pphi = phi * (float)(i - ilx/2) ;
02563                     /* Euler factor */
02564                     coph = cos ( pphi ) ;
02565                     siph = sin ( pphi ) ;
02566                 }
02567 
02568                 /* ------------------------------------------------------------
02569                  * now calculate the shift in the pixel space by multiplying
02570                  * the fourier transform by the Euler factor of the phase shift
02571                  * and inverse fourier transforming.
02572                  * used Fourier pair: h(x-x0) <==> H(k)*exp(2*pi*i*k*x0) 
02573                  */
02574                 /* calculate real part */
02575                 corrected_data[i].x   = data[i].x * coph - data[i].y * siph ; 
02576                 /* calculate imaginary part */
02577                 corrected_data[i].y = data[i].x * siph + data[i].y * coph ;
02578             }
02579  
02580             /* transform back: inverse FFT */
02581             sinfo_fftn( corrected_data, nn, 1, -1 ) ;
02582 
02583             /* normalize */ 
02584             for ( i = 0 ; i < ilx ; i++ )
02585             {
02586                 corrected_data[i].x /= ilx ;
02587         corrected_data[i].y /= ilx ;
02588             } 
02589 
02590             /* now transfer row to output, leave the left-most 
02591                and right-most pixel column */
02592             for ( col = 0 ; col < ilx ; col++ )
02593             {
02594                 if ( col == 0 )
02595                 {
02596                     podata[col+row*ilx] = ZERO ;
02597                 }
02598                 else if ( col == ilx - 1 )
02599                 {
02600                     podata[col+row*ilx] = ZERO ;
02601                 }
02602                 else
02603                 {
02604                     podata[col+row*ilx] = corrected_data[col].x ; 
02605                 }
02606             }
02607         }
02608     }
02609 
02610     cpl_free(data) ;
02611     cpl_free(corrected_data) ;
02612 
02613 
02614     cpl_free(row_data);
02615     return returnCube ;
02616 }
02644 cpl_imagelist * sinfo_new_fine_tune_cube_by_spline ( cpl_imagelist * cube,
02645                                                float   * correct_diff_dist )
02646 {
02647     cpl_imagelist * returnCube ;
02648 
02649     float* row_data=NULL ;
02650     float* corrected_row_data=NULL ;
02651     float* xnum=NULL ;
02652     float* eval=NULL ;
02653 
02654     float sum, new_sum ;
02655     int row, col ;
02656     int i, z ;
02657     int imsize ;
02658     int ilx=0;
02659     int ily=0;
02660     int inp=0;
02661    
02662     float* pidata=NULL;
02663     float* podata=NULL;
02664     cpl_image* i_img=NULL;
02665     cpl_image* o_img=NULL;
02666 
02667  
02668     if ( NULL == cube )
02669     {
02670         sinfo_msg_error("no input cube given!\n") ;
02671         return NULL ;
02672     }
02673     ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
02674     ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
02675     inp=cpl_imagelist_get_size(cube);
02676 
02677     if ( NULL == correct_diff_dist )
02678     {
02679         sinfo_msg_error("no distances array from ns_test given!/n") ;
02680         return NULL ;
02681     }
02682   
02683     imsize = ily ;
02684     if ( imsize != N_SLITLETS )
02685     {
02686         sinfo_msg_error ("wrong image size\n" ) ;
02687         return NULL ;
02688     }
02689   
02690     returnCube = cpl_imagelist_duplicate( cube ) ;
02691 
02692     row_data=cpl_calloc(ilx,sizeof(float)) ;
02693     corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
02694     xnum=cpl_calloc(ilx,sizeof(float)) ;
02695     eval=cpl_calloc(ilx,sizeof(float)) ;
02696   
02697     /* fill the xa[] array for a polynomial interpolation */
02698     for ( i = 0 ; i < ilx ; i++ )
02699     {
02700         xnum[i] = i ;
02701     }    
02702 
02703     /* loop over the image planes */
02704     for ( z = 0 ; z < inp ; z++ )
02705     {
02706       i_img=cpl_imagelist_get(cube,z);
02707       pidata=cpl_image_get_data_float(i_img);
02708       o_img=cpl_imagelist_get(returnCube,z);
02709       podata=cpl_image_get_data_float(o_img);
02710         /* consider 1 row at a time */
02711         for ( row = 0 ; row < imsize ; row++ )
02712         {
02713             for ( col = 0 ; col < ilx ; col++ )
02714             {
02715                 corrected_row_data[col] = 0. ;
02716             }
02717         sum = 0. ; /* initialize flux for later rescaling */
02718             /* go through the columns and compute the flux for each 
02719                row (leave the sinfo_edge points) */
02720             for ( col = 0 ; col < ilx ; col++ )
02721             {   
02722             eval[col] = correct_diff_dist[row] + (float)col ;
02723                 row_data[col] = pidata[col+row*ilx] ;
02724                 if (col != 0 && col != ilx - 1 && !isnan(row_data[col]) )
02725                 {
02726                     sum += row_data[col] ;
02727                 }
02728                 if (isnan(row_data[col]) )
02729                 {
02730                     for ( i = col -1 ; i <= col+1 ; i++ ) 
02731                     {
02732                         if ( i < 0 ) continue ;
02733                         if ( i >= ilx ) continue ;
02734                         corrected_row_data[i] = ZERO ; 
02735                     }
02736                     row_data[col] = 0. ;
02737                 }
02738         }
02739 
02740 
02741             /* ---------------------------------------------------------------
02742              * now we do the cubic spline interpolation to achieve the 
02743                fractional (see eclipse).
02744              */
02745             if ( -1 == sinfo_function1d_natural_spline(xnum,row_data, ilx, 
02746                                                        eval,corrected_row_data,
02747                                                        ilx ) )
02748         {
02749             sinfo_msg_error("error in spline interpolation\n") ;
02750         cpl_imagelist_delete(returnCube) ;
02751         return NULL ;
02752         }    
02753 
02754             new_sum = 0. ;
02755             for ( col = 0 ; col < ilx ; col++ )
02756             {
02757                 if (isnan(corrected_row_data[col])) continue ;
02758                 /* don't take the sinfo_edge points to calculate 
02759                    the scaling factor */
02760                 if ( col != 0 && col != ilx - 1 )
02761                 {
02762                     new_sum += corrected_row_data[col] ;
02763                 }
02764             }
02765             for ( col = 0 ; col < ilx ; col++ )
02766             {
02767                 /* ----------------------------------------------------------
02768                  * rescale the row data and fill the returned cube, 
02769                  * leave the left-most and right-most
02770                  * pixel column 
02771                  */
02772                 if ( col == 0 )
02773                 {
02774                     podata[col+row*ilx] = ZERO ;
02775                 }
02776                 else if ( col == ilx - 1 )
02777                 {
02778                     podata[col+row*ilx] = ZERO ;
02779                 }
02780                 else
02781                 {
02782                     if ( isnan(corrected_row_data[col]) ) 
02783                     {
02784                         podata[col+row*ilx] = ZERO ;
02785                     }
02786                     else
02787                     {
02788                         if (new_sum == 0.) new_sum = 1. ;
02789                      /* rescaling is commented out because it delivers 
02790                         wrong results
02791                         in case of appearance of blanks or bad pixels */
02792                   /*       corrected_row_data[col] *= sum / new_sum ; */
02793                         podata[col+row*ilx] = corrected_row_data[col] ;
02794                     }
02795                 }
02796             }
02797         }
02798     }       
02799 
02800     cpl_free(row_data) ;
02801     cpl_free(corrected_row_data) ;
02802     cpl_free(xnum) ;
02803     cpl_free(eval) ;
02804 
02805     return returnCube ;
02806 }
02807 
02829 float * 
02830 sinfo_new_calibrate_ns_test( cpl_image * ns_image,
02831                            int        n_slitlets,
02832                            int        halfWidth,
02833                            float      fwhm,
02834                            float      minDiff,
02835                            float      estimated_dist,
02836                            float      devtol,
02837                int        bottom,
02838                int        top )
02839 {
02840     int i, j, k, m, row, col, n, ni, na ;
02841     int position, counter, iters ;
02842     int xdim, ndat, its, numpar ;
02843     float sum, mean, maxval ;
02844     float tol, lab ;
02845     float * distances ;
02846     float * ret_distances ;
02847 
02848     float * xdat, * wdat ;
02849     int * mpar ;
02850 
02851     pixelvalue* row_buf=NULL ;
02852     float** distances_buf=NULL ;
02853     float* x_position=NULL ;
02854     int* found=NULL;
02855     int* found_clean=NULL ;
02856     int* found_cleanit=NULL ;
02857 
02858     Vector * line ;
02859     FitParams ** par ;
02860     int foundit, begin, end ;
02861     int zeroindicator ;
02862     int row_index ;
02863 
02864     int ilx=0;
02865     int ily=0;
02866     float* pidata=NULL;
02867 
02868     if ( ns_image == NULL )
02869     {
02870         sinfo_msg_error("sorry, no image given\n") ;
02871         return NULL ;
02872     }
02873     if ( n_slitlets < 1 )
02874     {
02875         sinfo_msg_error("wrong number of slitlets given\n") ;
02876         return NULL ;
02877     }
02878     if ( halfWidth < 0 || halfWidth >= estimated_dist )
02879     {
02880         sinfo_msg_error("wrong half width given\n") ;
02881         return NULL ;
02882     }
02883     if ( fwhm <= 0. )
02884     {
02885         sinfo_msg_error("wrong fwhm given\n") ;
02886         return NULL ;
02887     }
02888     if ( minDiff < 1. )
02889     {
02890         sinfo_msg_error("wrong minDiff given\n") ;
02891         return NULL ;
02892     }
02893 
02894     /* allocate memory for output array */
02895     if (NULL==(distances=(float *)cpl_calloc( n_slitlets , sizeof (float) ))) 
02896     {
02897         sinfo_msg_error("could not allocate memory\n") ;
02898         return NULL ;
02899     }
02900     /* allocate memory for output array */
02901     if (NULL == (ret_distances = (float *) cpl_calloc ( n_slitlets , 
02902                                            sizeof (float) ))) 
02903     {
02904         sinfo_msg_error("could not allocate memory\n") ;
02905         return NULL ;
02906     }
02907 
02908     ilx=cpl_image_get_size_x(ns_image);
02909     ily=cpl_image_get_size_y(ns_image);
02910     pidata=cpl_image_get_data_float(ns_image);
02911 
02912     row_buf=(pixelvalue*)cpl_calloc(ilx,sizeof(pixelvalue)) ;
02913     x_position=cpl_calloc(n_slitlets,sizeof(float)) ;
02914     found=cpl_calloc(3*n_slitlets,sizeof(int));
02915     found_clean=cpl_calloc(3*n_slitlets,sizeof(int)) ;
02916     found_cleanit=cpl_calloc(3*n_slitlets,sizeof(int)) ;
02917     distances_buf=sinfo_new_2Dfloatarray(ily,n_slitlets) ;
02918 
02919     /* go through the image rows */
02920     for ( row = 0 ; row < ily ; row++ )
02921     {
02922         zeroindicator = 0 ;
02923 
02924         /* initialize the distance buffer */
02925         for ( i = 0 ; i < n_slitlets ; i++ )
02926         {
02927             distances_buf[row][i] = ZERO ;
02928         }
02929 
02930         /* fill the row buffer array with image data */
02931         for ( col = 0 ; col < ilx ; col++ )
02932         {
02933             row_buf[col] = pidata[col + row*ilx] ;
02934         }
02935 
02936         /* determine the mean of the row data */
02937         sum = 0. ;
02938         n = 0 ;
02939         for ( i = 0 ; i < ilx ; i++ )
02940         {
02941             if ( isnan(row_buf[i]) )
02942             {
02943                 continue ;
02944             }
02945             sum += row_buf[i] ;
02946             n++ ;
02947         }
02948         mean = sum / (float)n ;
02949 
02950         /* store the positions of image values greater than the mean */
02951         n = 0 ;
02952         for ( i = 0 ; i < ilx ; i++ )
02953         {
02954             if (isnan(row_buf[i]))
02955             {
02956                 continue ;
02957             }
02958             if ( row_buf[i] > mean + ESTIMATE )
02959             {
02960                 found[n] = i ;
02961                 n++ ;
02962             }
02963         }
02964        
02965         if ( n < n_slitlets )
02966         {
02967             sinfo_msg_warning("t4 wrong number of intensity columns "
02968                               "found in row: %d, found number: %d", row, n) ;
02969             continue ;
02970         }
02971         else
02972         { 
02973             /* find the maximum value position around the found columns */
02974             na = 0 ;
02975             for ( i = 1 ; i < n ; i ++ )
02976             {
02977                 if ( found[i] - found[i-1] < halfWidth )
02978                 {
02979                     begin = found[i] - halfWidth ;
02980                     if ( begin < 0 )
02981                     {
02982                         begin = 0 ;
02983                     }
02984                     end = found[i] + halfWidth ;
02985                     if ( end >= ilx )
02986                     {
02987                         end = ilx - 1 ;
02988                     }
02989                     /* find the maximum value inside the box around 
02990                        the found positions*/
02991                     maxval = -FLT_MAX ;
02992                     foundit = 0 ;
02993                     for ( j = begin ; j <= end ; j++ )
02994                     {
02995                         /* do not consider boxes that contain bad pixels */
02996                         if (isnan(row_buf[j]))
02997                         {
02998                             continue ;
02999                         }
03000                         if (row_buf[j] >= maxval )
03001                         {
03002                             maxval = row_buf[j] ;
03003                             foundit = j ;
03004                         }
03005                     }
03006                     if (maxval == -FLT_MAX)
03007                     {
03008                         continue ;
03009                     }
03010                     for ( k = 0 ; k < na ; k++ )
03011                     {
03012                         if ( found_cleanit[k] >= begin && 
03013                              found_cleanit[k] < foundit )
03014                         {
03015                             na-- ;
03016                         }
03017                     }
03018                     for ( k = 0 ; k < n ; k++ )
03019                     {
03020                         if ( found[k] == foundit)
03021                         {
03022                             if ( found_cleanit[na-1] != found[k] )
03023                             {
03024                                 found_cleanit[na] = found[k] ;
03025                                 na++ ;
03026                             }
03027                         }
03028                     }
03029                 }
03030                 else
03031                 {
03032                     if ( i == 1 )
03033                     {
03034                         found_cleanit[na] = found[0] ;
03035                         na++ ;
03036                         found_cleanit[na] = found[1] ;
03037                         na++ ;
03038                     }
03039                     else
03040                     {
03041                         if ( found_cleanit[na-1] != found[i-1])
03042                         {
03043                             found_cleanit[na] = found[i-1] ;
03044                             na++ ;
03045                         }
03046                         if ( found_cleanit[na-1] != found[i])
03047                         {
03048                             found_cleanit[na] = found[i] ;
03049                             na++ ;
03050                         }
03051                     }
03052                 }
03053             }
03054 
03055             /* determine only one pixel position for each slitlet intensity */
03056             j = 1 ;
03057             for ( i = 1 ; i < na ; i++ )
03058             {
03059                 if ( (float)(found_cleanit[i] - found_cleanit[i-1]) < 
03060                              (estimated_dist - devtol) ||
03061                      (float)(found_cleanit[i] - found_cleanit[i-1]) > 
03062                              (estimated_dist + devtol) )
03063                 {
03064                     continue ;
03065                 }
03066                 else
03067                 {
03068                     found_clean[j-1] = found_cleanit[i-1] ;
03069                     found_clean[j]   = found_cleanit[i] ;
03070                     j++ ;
03071                 }
03072             }
03073         }
03074         if ( j > n_slitlets )
03075         {
03076             /* check the distance again */
03077             ni = 1 ;
03078             for ( i = 1 ; i < j ; i++ )
03079             {
03080                 if ( (float)(found_clean[i] - found_clean[i-1]) < 
03081                             (estimated_dist - devtol ) ||
03082                      (float)(found_clean[i] - found_clean[i-1]) > 
03083                             (estimated_dist + devtol ) )
03084                 { 
03085                     continue ;
03086                 }
03087                 else
03088                 {
03089                     found_clean[ni-1] = found_clean[i-1] ;
03090                     found_clean[ni]   = found_clean[i] ;
03091                     ni++ ;
03092                 }
03093             }
03094             if ( ni != n_slitlets )
03095             {
03096                 sinfo_msg_warning("t5 wrong number of intensity columns "
03097                                   "found in row: %d, found number: %d",
03098                                   row,ni) ;
03099                 continue ;
03100             }
03101             else 
03102             {
03103                 j = ni ;
03104             }
03105         }
03106         else if ( j < n_slitlets )
03107         {
03108             sinfo_msg_warning("t6 wrong number of intensity columns found "
03109                               "in row: %d , found number: %d\n", row, j) ;
03110             continue ;
03111         }
03112         counter = 0 ;
03113         /* go through the found intensity pixels in one row */
03114         for ( i = 0 ; i < j ; i++ )
03115         {
03116             /* allocate memory for the array where the line is fitted in */
03117             if ( NULL == (line = sinfo_new_vector (2*halfWidth + 1)) )
03118             {
03119                 sinfo_msg_error ("cannot allocate new Vector \n") ;
03120                 cpl_free(distances) ;
03121                 return NULL ;
03122             }
03123 
03124             /* allocate memory */
03125             xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
03126             wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
03127             mpar = (int *)   cpl_calloc( MAXPAR, sizeof (int) ) ;
03128             par = sinfo_new_fit_params(1) ;
03129 
03130             m = 0 ;
03131             for ( k = found_clean[i]-halfWidth ; 
03132                   k <= found_clean[i]+halfWidth ; k++ )
03133             {
03134                 if ( k < 0 )
03135                 {
03136                     k = 0. ;
03137                 }
03138                 else if ( k >= ilx )
03139                 {
03140                     k = ilx - 1 ;
03141                 }
03142                 else if ( isnan(row_buf[k]) )
03143                 {
03144                     zeroindicator = 1 ;
03145                     break ;
03146                 }
03147                 else
03148                 {
03149                     line -> data[m] = row_buf[k] ;
03150                     m++ ;
03151                 }
03152             }
03153             if ( zeroindicator == 1 )
03154             {
03155                 sinfo_new_destroy_vector(line) ;
03156                 cpl_free(xdat) ;
03157                 cpl_free(wdat) ;
03158                 cpl_free(mpar) ;
03159                 sinfo_new_destroy_fit_params(&par) ;
03160                 break ;
03161             }
03162 
03163             /*-----------------------------------------------------------------
03164              * go through the spectral sinfo_vector
03165              * determine the maximum pixel value in the spectral sinfo_vector
03166              */
03167             maxval = -FLT_MAX ;
03168             position = -INT32_MAX ;
03169             for ( k = 0 ; k < m ; k++ )
03170             {
03171                 xdat[k] = k ;
03172                 wdat[k] = 1.0 ;
03173                 if ( line -> data[k] >= maxval )
03174                 {
03175                     maxval = line -> data[k] ;
03176                     position = k ;
03177                 }
03178             }
03179 
03180             /* set initial values for the fitting routine */
03181             xdim     = XDIM ;
03182             ndat     = line -> n_elements ;
03183             numpar   = MAXPAR ;
03184             tol      = TOL ;
03185             lab      = LAB ;
03186             its      = ITS ;
03187             (*par) -> fit_par[1] = fwhm ;
03188             (*par) -> fit_par[2] = (float) position ;
03189             (*par) -> fit_par[3] = (float) (line -> data[0] + 
03190                                     line -> data[line->n_elements - 1]) / 2.0 ;
03191             (*par) -> fit_par[0]  = maxval - ((*par) -> fit_par[3]) ;
03192 
03193 
03194             /* exclude negative peaks and low signal cases */
03195             if ( (*par) -> fit_par[0] < minDiff )
03196             {
03197                 sinfo_msg_warning ("sorry, signal of line too low to fit "
03198                                    "in row: %d in slitlet %d\n", row, i) ;
03199                 sinfo_new_destroy_vector(line) ;
03200                 cpl_free(xdat) ;
03201                 cpl_free(wdat) ;
03202                 cpl_free(mpar) ;
03203                 sinfo_new_destroy_fit_params(&par) ;
03204                 continue ;
03205             }
03206 
03207             for ( k = 0 ; k < MAXPAR ; k++ )
03208             {
03209                 (*par) -> derv_par[k] = 0.0 ;
03210                 mpar[k] = 1 ;
03211             }
03212             /* finally, do the least square fit using a sinfo_gaussian */
03213             if ( 0 > ( iters = sinfo_new_lsqfit_c(xdat, &xdim, 
03214                                                   line -> data, wdat, 
03215                                                   &ndat, (*par) -> fit_par,
03216                                                   (*par) -> derv_par, mpar, 
03217                                                   &numpar, &tol, 
03218                                                   &its, &lab )) )
03219             {
03220           /*
03221                cpl_msg_debug ("sinfo_calibrate_ns_test:",
03222                               "sinfo_lsqfit_c: least squares fit failed,"
03223                               " error no.: %d in row: %d in slitlet %d\n", 
03224                               iters, row, i) ;
03225           */
03226                 sinfo_new_destroy_vector(line) ;
03227                 cpl_free(xdat) ;
03228                 cpl_free(wdat) ;
03229                 cpl_free(mpar) ;
03230                 sinfo_new_destroy_fit_params(&par) ;
03231                 continue ;
03232             }
03233 
03234             /* check for negative fit results */
03235             if ( (*par) -> fit_par[0] <= 0. || (*par) -> fit_par[1] <= 0. ||
03236                  (*par) -> fit_par[2] < 0. )
03237             {
03238                 sinfo_msg_warning ("negative parameters as fit result, not "
03239                                    "used! in row %d in slitlet %d", row, i) ;
03240                 sinfo_new_destroy_vector(line) ;
03241                 cpl_free(xdat) ;
03242                 cpl_free(wdat) ;
03243                 cpl_free(mpar) ;
03244                 sinfo_new_destroy_fit_params(&par) ;
03245                 continue ;
03246             }
03247 
03248             /* correct the fitted position for the given row of the line 
03249                in image coordinates */
03250             (*par) -> fit_par[2] =  (float) (found_clean[i] - halfWidth) + 
03251                                     (*par) -> fit_par[2] ;
03252             x_position[counter] = (*par) -> fit_par[2] ;
03253             counter ++ ;
03254 
03255             /* free memory */
03256             sinfo_new_destroy_fit_params(&par) ;
03257             sinfo_new_destroy_vector ( line ) ;
03258             cpl_free ( xdat ) ;
03259             cpl_free ( wdat ) ;
03260             cpl_free ( mpar ) ;
03261         }
03262         if (zeroindicator == 1)
03263         {
03264             sinfo_msg_debug ("bad pixel in fitting box in row: %d\n", row) ;
03265             continue ;
03266         }
03267 
03268         if ( counter != n_slitlets )
03269         {
03270             sinfo_msg_warning("wrong number of slitlets found "
03271                               "in row: %d", row) ;
03272             continue ;
03273         }
03274         /* store the distances between the sources and the slitlet centers */
03275         for ( i = 0 ; i < n_slitlets ; i++ )
03276         {
03277             distances_buf[row][i] = x_position[i] - (15.5 + 32.*(float)i) ;
03278         }
03279     }
03280 
03281     /* ----------------------------------------------------------------
03282      * go through the rows again and take the mean of the distances, 
03283      * throw away the runaways 
03284      */
03285     for ( i = 0 ; i < n_slitlets ; i++ )
03286     {
03287         n   = 0 ;
03288         sum = 0. ;
03289         for ( row = bottom ; row < top ; row++ )
03290         {
03291             if ( fabs( distances_buf[row][i] ) > devtol || 
03292                  isnan(distances_buf[row][i]) )
03293             {
03294              /*
03295           sinfo_msg("dist=%g devtol=%g isan=%d", 
03296             distances_buf[row][i],
03297             devtol,
03298             isnan(distances_buf[row][i]));
03299               */              
03300                 continue ;
03301             }
03302             sum += distances_buf[row][i] ;
03303             n++ ;
03304         }
03305         if ( n < 2 )
03306         {
03307             sinfo_msg_error("distances array could not be determined"
03308                             " completely!, deviations of distances from"
03309                             " devtol too big" ) ;
03310             cpl_free(distances) ;
03311             return NULL ;
03312         }
03313         else
03314         {
03315             distances[i] = sum / (float)n ;
03316         }
03317     }
03318 
03319     /* now sort the result according to the row sequence in the 
03320        reconstructed image*/
03321     for ( i = 0 ; i < n_slitlets ; i++ )
03322     {
03323       if( (row_index=sinfo_sort_slitlets(i)) == -1) {
03324     sinfo_msg_error("wrong number of a slitlet\n") ;
03325     cpl_free (distances) ;
03326     return NULL ;
03327       }
03328       ret_distances[row_index] = distances[i] ;
03329     }
03330     cpl_free(distances) ;
03331 
03332     cpl_free(row_buf) ;
03333     cpl_free(x_position) ;
03334     cpl_free(found);
03335     cpl_free(found_clean) ;
03336     cpl_free(found_cleanit) ;
03337     sinfo_new_destroy_2Dfloatarray(&distances_buf,n_slitlets) ;
03338 
03339 
03340     return ret_distances ; 
03341 }
03366 cpl_image * 
03367 sinfo_new_make_true_resamp(cpl_image * calibImage, 
03368                            cpl_image * wavemap)
03369 {
03370     cpl_image * returnImage ;
03371     float edges[33] ;
03372     int imsize, kslit,i,j ;
03373     int slit_index ;
03374     int z, col, recol ;
03375     int wlx=0;
03376     int wly=0;
03377     int clx=0;
03378     int cly=0;
03379   
03380     float* pcdata=NULL;
03381     float* pwdata=NULL;
03382     float* prdata=NULL;
03383 
03384 
03385     wlx=cpl_image_get_size_x(wavemap);
03386     wly=cpl_image_get_size_y(wavemap);
03387     pwdata=cpl_image_get_data_float(wavemap);
03388 
03389     edges[0]=0;
03390     j=1;
03391     for(i=0;i<wlx-1;i++)
03392     {
03393         if((pwdata[i]-pwdata[i+1])>0.0025 || (pwdata[i]-pwdata[i+1])<-0.0025)
03394     {
03395         sinfo_msg_error("wavemap sinfo_edge %d", i+1);
03396         edges[j]=i+1;
03397         j++;
03398     }
03399     }
03400     edges[32]=2048;
03401 
03402     clx=cpl_image_get_size_x(calibImage);
03403     cly=cpl_image_get_size_y(calibImage);
03404     pcdata=cpl_image_get_data_float(calibImage);
03405  
03406     imsize = clx / N_SLITLETS ;
03407 
03408     /* allocate memory */  
03409     returnImage = cpl_image_new(clx,cly,CPL_TYPE_FLOAT);
03410     prdata=cpl_image_get_data_float(returnImage);
03411     for ( z = 0 ; z < cly ; z++ ) /* go through the z-axis */
03412     {
03413         for ( col = 0 ; col < clx ; col++ ) /* go through the image columns */
03414         prdata[col+z*clx]=ZERO;
03415     }
03416     
03417 
03418     /* now build the data cube out of the resampled image */
03419     for ( z = 0 ; z < cly ; z++ ) /* go through the z-axis */
03420     {
03421         kslit      = 0 ;
03422         slit_index = -1 ;
03423         recol      = -1 ;
03424         for ( col = 0 ; col < clx ; col++ ) /* go through the image columns */
03425         {
03426             /*if ( col % imsize == 0 )
03427             {*/
03428                 recol = 0 ;
03429                 /*kslit = col/imsize ;*/
03430         for(i=0;i<32;i++)
03431         {
03432           if(col>=sinfo_new_nint(edges[i]) && 
03433                      col<sinfo_new_nint(edges[i+1]))
03434             kslit=i;
03435         }
03436                 /* sort the slitlets in the right spiffi specific way */
03437     if( (slit_index=sinfo_sort_slitlets(kslit)) == -1) {
03438             sinfo_msg_error("wrong slitlet index: couldn't be a "
03439                              "spiffi image,  there must be 32 "
03440                 "slitlets!") ;
03441         
03442     }
03443 
03444             /*}*/
03445 
03446             /* fill each cube plane with one image row */
03447         if((col-sinfo_new_nint(edges[kslit]))>0 && 
03448                (col-sinfo_new_nint(edges[kslit]))<imsize-1 )
03449                 prdata[(col-sinfo_new_nint(edges[kslit]))+
03450                        slit_index*imsize+z*clx] = 
03451                       pcdata[col+z*clx] ;
03452             else
03453             prdata[(col-sinfo_new_nint(edges[kslit]))+
03454                         slit_index*imsize+z*clx] = ZERO;
03455             /*recol++ ;*/
03456 
03457         }
03458     }
03459     return returnImage ;
03460 }
03461 
03462 /*The old slitlet order*/
03463 /*switch (kslit)
03464                 {
03465                     case 0:
03466                         slit_index = 23 ;
03467                         break ;
03468                     case 1:
03469                         slit_index = 24 ;
03470                         break ;
03471                     case 2:
03472                         slit_index = 22 ;
03473                         break ;
03474                     case 3:
03475                         slit_index = 25 ;
03476                         break ;
03477                     case 4:
03478                         slit_index = 21 ;
03479                         break ;
03480                     case 5:
03481                         slit_index = 26 ;
03482                         break ;
03483                     case 6:
03484                         slit_index = 20 ;
03485                         break ;
03486                     case 7:
03487                         slit_index = 27 ;
03488                         break ;
03489                     case 8:
03490                         slit_index = 19 ;
03491                         break ;
03492                     case 9:
03493                         slit_index = 28 ;
03494                         break ;
03495                     case 10:
03496                         slit_index = 18 ;
03497                         break ;
03498                     case 11:
03499                         slit_index = 29 ;
03500                         break ;
03501                     case 12:
03502                         slit_index = 17 ;
03503                         break ;
03504                     case 13:
03505                         slit_index = 30 ;
03506                         break ;
03507                     case 14:
03508                         slit_index = 16 ;
03509                         break ;
03510                     case 15:
03511                         slit_index = 31 ;
03512                         break ;
03513                     case 16:
03514                         slit_index = 0 ;
03515                         break ;
03516                     case 17:
03517                         slit_index = 15 ;
03518                         break ;
03519                     case 18:
03520                         slit_index = 1 ;
03521                         break ;
03522                     case 19:
03523                         slit_index = 14 ;
03524                         break ;
03525                     case 20:
03526                         slit_index = 2 ;
03527                         break ;
03528                     case 21:
03529                         slit_index = 13 ;
03530                         break ;
03531                     case 22:
03532                         slit_index = 3 ;
03533                         break ;
03534                     case 23:
03535                         slit_index = 12 ;
03536                         break ;
03537                     case 24:
03538                         slit_index = 4 ;
03539                         break ;
03540                     case 25:
03541                         slit_index = 11 ;
03542                         break ;
03543                     case 26:
03544                         slit_index = 5 ;
03545                         break ;
03546                     case 27:
03547                         slit_index = 10 ;
03548                         break ;
03549                     case 28:
03550                         slit_index = 6 ;
03551                         break ;
03552                     case 29:
03553                         slit_index = 9 ;
03554                         break ;
03555                     case 30:
03556                         slit_index = 7 ;
03557                         break ;
03558                     case 31:
03559                         slit_index = 8 ;
03560                         break ;
03561                     default:
03562                         sinfo_msg_error("wrong slitlet index: couldn't "
03563                                         "be a spiffi image,  \
03564                                  there must be 32 slitlets!\n") ;
03565                         cpl_imagelist_delete(returnCube) ;
03566                         return NULL ;
03567                         break ;
03568                 }*/
03569 
03570 
03571 /*--------------------------------------------------------------------------*/

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