sinfo_coltilt.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  19/12/00  created
00027 */
00028 
00029 /************************************************************************
00030 *   NAME
00031 *        sinfo_coltilt.c -
00032 *        procedures to correct for tilted spectra 
00033 *
00034 *   SYNOPSIS
00035 *   1) float sinfo_new_slope_of_spectrum(cpl_image * ns_image,
00036 *                             int        box_length,
00037 *                             float      fwhm,
00038 *                             float      minDiff )
00039 *   2) cpl_image * sinfo_new_shift_rows(cpl_image * image,
00040 *                            float      slope )
00041 *   3) void sinfo_new_parameter_to_ascii ( float * parameter, 
00042 *                              int n,
00043 *                              char * filename )
00044 *   4) float * sinfo_new_ascii_to_parameter ( char * filename,
00045 *                                 int * n )
00046 *   5) double * sinfo_new_curvature_of_spectrum( cpl_image * ns_image,
00047 *                              int        order,
00048 *                                    int        box_length,
00049 *                                    int        left_pos,
00050 *                                    int        right_pos,
00051 *                                    float      fwhm,
00052 *                                    float      minDiff )
00053 *
00054 *
00055 *   DESCRIPTION
00056 *   1)  determines the sub-pixel shifts of each row by using
00057 *       an image with at least one continuum spectrum of a pinhole
00058 *       this is done by searching the spectrum within the image
00059 *       then fitting the spectrum along the rows within a given box
00060 *       by a sinfo_gaussian, so that the exact position is determined for
00061 *       each row. Afterwards, a straight line is fitted through the
00062 *       fitted positions. The slope of this linear fit is returned.
00063 *   2)  shifts the rows of a raw image by using the output of 
00064 *       sinfo_slopeOfSpectrum and applying polynomial interpolation
00065 *   3)  stores parameters in an ASCII file 
00066 *   4)  writes parameters stored in an ASCII file in an float array
00067 *   5)  this routine determines the curvature of a spectrum by fitting
00068 *       a polynomial to a continuum spectrum. This is done by using
00069 *       an image with at least one continuum spectrum of a pinhole.
00070 *       this is done by searching the spectrum within the image
00071 *       then fitting the spectrum along the rows within a given box
00072 *       by a sinfo_gaussian, so that the exact position is determined for
00073 *       each row. Afterwards, a polynomial is fitted through the
00074 *       found positions. The polynomial coefficients are returned.
00075 *
00076 *
00077 *   FILES
00078 *
00079 *   ENVIRONMENT
00080 *
00081 *   RETURN VALUES
00082 *
00083 *   CAUTIONS
00084 *
00085 *   EXAMPLES
00086 *
00087 *   SEE ALSO
00088 *
00089 *   BUGS
00090 *
00091 *------------------------------------------------------------------------
00092 */
00093 #ifdef HAVE_CONFIG_H
00094 #  include <config.h>
00095 #endif
00096 
00097 #define POSIX_SOURCE 1
00098 #include "sinfo_vltPort.h"
00099 
00100 /*
00101  * System Headers
00102  */
00103 
00104 /*
00105  * Local Headers
00106  */
00107 
00108 #include "sinfo_coltilt.h"
00109 #include "sinfo_new_resampling.h"
00110 #include "sinfo_fit_curve.h"
00111 #include "sinfo_functions.h"
00119 /*----------------------------------------------------------------------------
00120  *                            Function codes
00121  *--------------------------------------------------------------------------*/
00122 
00143 float 
00144 sinfo_new_slope_of_spectrum( cpl_image * ns_image,
00145                        int        box_length,
00146                        float      fwhm,
00147                        float      minDiff )
00148 {
00149     int i, k, row, col ;
00150     int counter, iters ;
00151     int xdim, ndat, its, numpar ;
00152     float maxval ;
00153     float tol, lab ;
00154     float* col_value=NULL ;
00155     float* column_value=NULL ;
00156     pixelvalue* col_position=NULL ;
00157     int* column_position=NULL ;
00158     float* x_position=NULL ;
00159 
00160 
00161     int col_median ;
00162     float * xdat, * wdat ;
00163     int * mpar ;
00164     Vector * line ;
00165     FitParams ** dec_par ;
00166     FitParams *  par ;
00167 
00168     float* x=NULL; 
00169     float* y=NULL; 
00170     float* sig=NULL ;
00171 
00172     int position ;
00173     int ndata, mwt ;
00174     float a, b, siga, sigb, chi2, q ;
00175     int bad_ind ;
00176     int lx=0;
00177     int ly=0;
00178     float* pdata=NULL;
00179 
00180     if ( ns_image == NULL )
00181     {
00182         sinfo_msg_error(" sorry, no image given") ;
00183         return FLAG ;
00184     }
00185     lx=cpl_image_get_size_x(ns_image);
00186     ly=cpl_image_get_size_x(ns_image);
00187 
00188 
00189     if ( box_length <= 1 || box_length >= (int) sqrt(lx) )
00190     {
00191         sinfo_msg_error(" wrong box length given") ;
00192         return FLAG ;
00193     }
00194     if ( fwhm < 1. || fwhm > 10. )
00195     {
00196         sinfo_msg_error("wrong full width at half maximum given") ;
00197         return FLAG ;
00198     }
00199     if ( minDiff < 1. )
00200     {
00201         sinfo_msg_error("wrong amplitude threshold given") ;
00202         return FLAG ;
00203     }
00204 
00205 
00206 
00207     col_value=cpl_calloc(ly,sizeof(float)) ;
00208     column_value=cpl_calloc(ly,sizeof(float)) ;
00209     col_position=(pixelvalue*)cpl_calloc(ly,sizeof(pixelvalue)) ;
00210     column_position=cpl_calloc(ly,sizeof(int)) ;
00211     x_position=cpl_calloc(ly,sizeof(float)) ;
00212 
00213 
00214 
00215     x=cpl_calloc(lx,sizeof(float)); 
00216     y=cpl_calloc(lx,sizeof(float)); 
00217     sig=cpl_calloc(lx,sizeof(float)) ;
00218     pdata=cpl_image_get_data_float(ns_image);
00219     /* go through the image rows */
00220     for ( row = 0 ; row < ly ; row++ )
00221     {
00222         col_value[row] = -FLT_MAX ;
00223         col_position[row] = -1. ;
00224         /* find the maximum value in each row and store the found column */
00225         for ( col = 0 ; col < lx ; col++ )
00226         {
00227             if ( pdata[col+row*lx] > col_value[row] )
00228             {
00229                 col_value[row]    = pdata[col+row*lx] ;
00230                 col_position[row] = (pixelvalue)col ;
00231             }
00232         }
00233     }
00234 
00235     /* now determine the sinfo_new_median of the found columns to be sure 
00236        to have the brightest spectrum */
00237     col_median = (int)sinfo_new_median(col_position, ly) ;
00238     sinfo_msg ("sinfo_new_median column position of brightest spectrum %d\n", 
00239               col_median) ;
00240 
00241     /* now find the peaks around col_median over the whole spectral range */
00242     for ( row = 0 ; row < ly ; row++ )
00243     {
00244         x_position[row] = 0. ;
00245         column_value[row] = -FLT_MAX ;
00246         column_position[row] = -1 ;
00247         for ( col = col_median - box_length ; 
00248               col <= col_median + box_length ; col++ )
00249         {
00250             if ( pdata[col+row*lx] > column_value[row] )
00251             {
00252                 column_value[row] = pdata[col+row*lx] ; 
00253                 column_position[row] = col ;
00254             }
00255         }
00256 
00257         /* allocate memory for the array where the line is fitted in */
00258         if ( NULL == (line = sinfo_new_vector (2*box_length + 1)) )
00259         {
00260             sinfo_msg_error ("cannot allocate new Vector in row %d", row) ;
00261             return FLAG ;
00262         }
00263 
00264         /* allocate memory */
00265         xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00266         wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00267         mpar = (int *)   cpl_calloc( MAXPAR, sizeof (int) ) ;
00268         dec_par = sinfo_new_fit_params(1) ;
00269     par = dec_par[0];
00270 
00271         counter = 0 ;
00272         bad_ind = 0 ;
00273         /* store the values to fit in a Vector object */
00274         for ( col = column_position[row] - box_length ; 
00275               col <= column_position[row] + box_length ; col++ )
00276         {
00277             if ( col < 0 || col >= lx )
00278             {
00279                 sinfo_msg_error ("wrong spectrum position or box_length "
00280                                  "given in row: %d", row) ;
00281                 cpl_free (xdat) ;
00282                 cpl_free (wdat) ;
00283                 cpl_free (mpar) ;
00284                 sinfo_new_destroy_fit_params(&dec_par) ;
00285                 sinfo_new_destroy_vector( line ) ;
00286                 return FLAG ;
00287             }
00288             else if ( isnan(pdata[col+row*lx]) )
00289             {
00290                 bad_ind = 1 ;
00291             }
00292             else
00293             {
00294                 line -> data[counter] = pdata[col + row*lx] ;
00295                 counter++ ;
00296             }
00297         }
00298  
00299         /* go to the next row if a bad pixel is inside the box */
00300         if ( bad_ind == 1 )
00301         {
00302             sinfo_msg_warning ("sorry, bad pixel inside fitting "
00303                                "box in row: %d", row) ;
00304             cpl_free (xdat) ;
00305             cpl_free (wdat) ;
00306             cpl_free (mpar) ;
00307             sinfo_new_destroy_fit_params(&dec_par) ;
00308             sinfo_new_destroy_vector( line ) ;
00309             continue ;
00310         }
00311 
00312         /*--------------------------------------------------------------------
00313          * go through the line sinfo_vector
00314          * determine the maximum pixel value in the line sinfo_vector
00315          */
00316         maxval = -FLT_MAX ;
00317         position = -INT32_MAX ;
00318         for ( i = 0 ; i < counter ; i++ )
00319         {
00320             xdat[i] = i ;
00321             wdat[i] = 1.0 ;
00322             if ( line -> data[i] >= maxval )
00323             {
00324                 maxval = line -> data[i] ;
00325                 position = i ;
00326             }
00327         }
00328 
00329         /* set initial values for the fitting routine */
00330         xdim     = XDIM ;
00331         ndat     = line -> n_elements ;
00332         numpar   = MAXPAR ;
00333         tol      = TOL ;
00334         lab      = LAB ;
00335         its      = ITS ;
00336         (*par).fit_par[1] = fwhm ;
00337         (*par).fit_par[2] = (float) position ;
00338         (*par).fit_par[3] = (float) (line -> data[0] + 
00339                             line -> data[line->n_elements - 1]) / 2.0 ;
00340 
00341         (*par).fit_par[0]  = maxval - ((*par).fit_par[3]) ;
00342         /* exclude negative peaks and low signal cases */
00343         if ( (*par).fit_par[0] < minDiff )
00344         {
00345             sinfo_msg_warning ("sorry, negative peak or signal of line "
00346                                "too low to fit in row: %d", row) ;
00347             cpl_free (xdat) ;
00348             cpl_free (wdat) ;
00349             cpl_free (mpar) ;
00350             sinfo_new_destroy_fit_params(&dec_par) ;
00351             sinfo_new_destroy_vector( line ) ;
00352             continue ;
00353         }
00354 
00355         for ( k = 0 ; k < MAXPAR ; k++ )
00356         {
00357             (*par).derv_par[k] = 0.0 ;
00358             mpar[k] = 1 ;
00359         }
00360 
00361         /* finally, do the least square fit using a sinfo_gaussian */
00362         if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim, 
00363                                                line -> data, wdat, 
00364                                                &ndat, (*par).fit_par,
00365                                                (*par).derv_par, mpar, 
00366                                                &numpar, &tol, &its, &lab )) )
00367         {
00368             sinfo_msg_warning ("sinfo_new_lsqfit_c: least squares fit "
00369                                "failed in row: %d, error no.: %d",row,iters) ;
00370             cpl_free (xdat) ;
00371             cpl_free (wdat) ;
00372             cpl_free (mpar) ;
00373             sinfo_new_destroy_fit_params(&dec_par) ;
00374             sinfo_new_destroy_vector( line ) ;
00375             continue ;
00376         }
00377 
00378         /* check for negative fit results */
00379         if ( (*par).fit_par[0] <= 0. || (*par).fit_par[1] <= 0. ||
00380              (*par).fit_par[2] <= 0. )
00381         {
00382             sinfo_msg_warning ("negative parameters as fit result, "
00383                                "not used! in row: %d", row) ;
00384             cpl_free (xdat) ;
00385             cpl_free (wdat) ;
00386             cpl_free (mpar) ;
00387             sinfo_new_destroy_fit_params(&dec_par) ;
00388             sinfo_new_destroy_vector( line ) ;
00389             continue ;
00390         }
00391 
00392         /* correct the fitted position for the given row of the line in 
00393            image coordinates */
00394         x_position[row] =  (float) (column_position[row] - box_length) + 
00395                            (*par).fit_par[2] ;
00396 
00397         /* store the fit errors of the positions as weights for the later 
00398            linear fit */
00399         sig[row] = (*par).derv_par[2] ;
00400 
00401         /* free memory */
00402         sinfo_new_destroy_fit_params(&dec_par) ;
00403         sinfo_new_destroy_vector ( line ) ;
00404         cpl_free ( xdat ) ;
00405         cpl_free ( wdat ) ;
00406         cpl_free ( mpar ) ;
00407     }
00408 
00409     /* -----------------------------------------------------------------------
00410      * now that we have a sub-pixel resolved list of spectral maxima stored 
00411      * in x_position[row]
00412      * We can fit a flux weighted straight line to the positions to determine 
00413      * the spectral column shifts.
00414      */
00415     ndata = 0 ;
00416     for ( row = 0 ; row < lx ; row++ )
00417     {
00418         if ( x_position[row] == 0. || sig[row] == 0. )
00419         {
00420             continue ;
00421         }
00422         else 
00423         {
00424             y[ndata]   = x_position[row] ;
00425             x[ndata]   = (float)row ;
00426             sig[ndata] = sig[row] ;
00427             ndata++ ;
00428         }
00429     }
00430     if ( ndata < 10 )
00431     {
00432         sinfo_msg_error("not enough positions to do the linear fit") ;
00433         return FLAG ;
00434     }
00435 
00436     /* now do the fit and return the slope of the straight line */
00437     mwt = 0 ;
00438     sinfo_my_fit(x, y, ndata, sig, mwt, &a, &b, &siga, &sigb, &chi2, &q) ;
00439 
00440     cpl_free(col_value) ;
00441     cpl_free(column_value) ;
00442     cpl_free(col_position) ;
00443     cpl_free(column_position) ;
00444     cpl_free(x_position) ;
00445 
00446     cpl_free(x); 
00447     cpl_free(y); 
00448     cpl_free(sig) ;
00449 
00450     return b ;
00451 }
00452 
00465 cpl_image * 
00466 sinfo_new_shift_rows( cpl_image * image,
00467                       float      slope, 
00468                       int        n_order )
00469 {
00470     cpl_image * returnImage=NULL ;
00471     float xshift=0 ;
00472     int   intshift = 0 ;
00473     float sum=0;
00474     float new_sum=0;
00475 
00476     float* xnum=NULL ;
00477     float* row_data=NULL ;
00478     float* corrected_row_data=NULL ;
00479 
00480     float eval=0 /*, dy*/ ;
00481     float * imageptr=NULL ;
00482     int col=0;
00483     int row=0;
00484     int firstpos=0;
00485     int n_points=0;
00486     int i=0;
00487     int flag=0;
00488     int ilx=0;
00489     int ily=0;
00490     int olx=0;
00491     int oly=0;
00492     float* pidata=NULL;
00493     float* podata=NULL;
00494 
00495     if ( image == NULL )
00496     {
00497         sinfo_msg_error("sorry, no image given") ;
00498         return NULL ;
00499     }
00500 
00501     if ( slope == 0. )
00502     {
00503         sinfo_msg_error("there is no need to shift the image rows!") ;
00504         return NULL ;
00505     }
00506 
00507     if ( n_order <= 0 )
00508     {
00509         sinfo_msg_error("wrong order of interpolation polynom given!") ;
00510         return NULL ;
00511     }
00512 
00513     returnImage = cpl_image_duplicate( image ) ;
00514     ilx=cpl_image_get_size_x(image);
00515     ily=cpl_image_get_size_y(image);
00516     olx=cpl_image_get_size_x(returnImage);
00517     oly=cpl_image_get_size_y(returnImage);
00518     pidata=cpl_image_get_data_float(image);
00519     podata=cpl_image_get_data_float(returnImage);
00520 
00521 
00522     n_points = n_order + 1 ;
00523     if ( n_points % 2 == 0 )
00524     {
00525         firstpos = (int)(n_points/2) - 1 ;
00526     }
00527     else
00528     {
00529         firstpos = (int)(n_points/2) ;
00530     }
00531 
00532 
00533     xnum=cpl_calloc(n_order + 1,sizeof(float)) ;
00534     row_data=cpl_calloc(ilx,sizeof(float)) ;
00535     corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
00536 
00537     /* fill the xa[] array for the polint function */
00538     for ( i = 0 ; i < n_points ; i++ )
00539     {
00540         xnum[i] = i ;
00541     }
00542 
00543     /* go through the image rows */
00544     for ( row = 0 ; row < ily ; row++ )
00545     {
00546         /* determine the shift for each row, the middle row is not shifted */
00547         xshift = slope * (float)( (ily / 2) - row ) ;
00548 
00549         intshift = sinfo_new_nint(xshift) ;
00550         xshift = xshift - (float)intshift ;
00551 
00552         for ( col = 0 ; col < ilx ; col++ )
00553         {
00554             corrected_row_data[col] = 0. ;
00555         }
00556         sum = 0. ; /* initialize flux for later rescaling */
00557         /* go through the image columns */
00558         for ( col = 0 ; col < ilx ; col++ )
00559         {
00560         /* consider integer pixel shifts */
00561         if ( intshift < 0 )
00562             {
00563         if ( col - intshift < ilx )
00564         {
00565             row_data[col] = pidata[col-intshift+row*ilx] ;
00566                 }
00567         else
00568         {
00569             row_data[col] = 0. ;
00570                 }
00571         }
00572         else if ( intshift > 0 )
00573         {
00574         if ( col - intshift >= 0 )
00575         {
00576             row_data[col] = pidata[col-intshift+row*ilx] ;
00577                 }
00578         else
00579         {
00580             row_data[col] = 0. ;
00581         }
00582         }
00583         else
00584         {
00585                row_data[col] = pidata[col+row*ilx] ;
00586         }
00587 
00588             /* don't consider the sinfo_edge pixels for flux calculation */
00589             if ( col != 0 && col != ilx - 1 && !isnan(row_data[col]) )
00590             {
00591                 sum += row_data[col] ;
00592             }
00593             if (isnan(row_data[col])) 
00594             {
00595                 row_data[col] = 0. ;
00596                 for (i = col - firstpos ; i < col - firstpos + n_points ; i++ )
00597                 {
00598                     if ( i < 0 ) continue ;
00599                     if ( i >= ilx) continue ;
00600                     corrected_row_data[i] = ZERO ;
00601                 }
00602             }
00603         }
00604 
00605 
00606         /* --------------------------------------------------------------------
00607          * now we do the polynomial interpolation to achieve the fractional
00608          * shift that means call polint
00609          */
00610         new_sum = 0. ;
00611         for ( col = 0 ; col < ilx ; col++ )
00612         {
00613             /* ---------------------------------------------------------------
00614              * now determine the arrays of size n_points with which the
00615              * polynom is determined and determine the position eval
00616              * where the polynom is evaluated in polint of N.R..
00617              * Take care of the points near the row edges!
00618              */
00619             if ( isnan(corrected_row_data[col]) )
00620             {
00621                  continue ;
00622             }
00623             if ( col - firstpos < 0 )
00624             {
00625                 imageptr = &row_data[0] ;
00626                 eval     = (float)col - xshift ;
00627             }
00628             else if ( col - firstpos + n_points >= ilx )
00629             {
00630                 imageptr = &row_data[ilx - n_points] ;
00631                 eval     = (float)(col + n_points - ilx) - xshift ;
00632             }
00633             else
00634             {
00635                 imageptr = &row_data[col-firstpos] ;
00636                 eval     = (float)firstpos - xshift ;
00637             }
00638 
00639         flag=0;
00640         corrected_row_data[col]=sinfo_new_nev_ille(xnum,imageptr,
00641                                                        n_order,eval,&flag);
00642             /*polint( xnum - 1, imageptr, n_points, eval, 
00643                       &corrected_row_data[col], &dy ) ;*/
00644 
00645             /* don't take the sinfo_edge points to calculate 
00646                the scaling factor */
00647             if (col != 0 && col != ilx - 1 && !isnan(corrected_row_data[col]) )
00648             {
00649                 new_sum += corrected_row_data[col] ;
00650             }
00651         }
00652 
00653         if ( new_sum == 0. )
00654         {
00655             new_sum = 1. ;
00656         }
00657         for ( col = 0 ; col < ilx ; col++ )
00658         {
00659             if ( isnan(corrected_row_data[col]))
00660             {
00661                 podata[col+row*ilx] = ZERO ;
00662             }
00663             else
00664             {
00665               /* rescale the row data and fill the returned image */
00666               /* This gives sometimes inconsistent results if 
00667                  bad pixels are around */
00668               /* rescaling is commented out because it delivers wrong results
00669                  in case of appearance of blanks or bad pixels */
00670              /*   corrected_row_data[col] *= sum / new_sum ; */
00671                 podata[col+row*ilx] = corrected_row_data[col] ;
00672             }
00673         }
00674     }      
00675 
00676     cpl_free(xnum) ;
00677     cpl_free(row_data) ;
00678     cpl_free(corrected_row_data);
00679 
00680     return returnImage ;
00681 }
00682 
00683 
00694 void 
00695 sinfo_new_parameter_to_ascii ( float * parameter, 
00696                         int n,
00697                         char * filename )
00698 {
00699     FILE * fp ;
00700     int     i=0 ;
00701 
00702     if ( parameter == NULL || filename == NULL || n <= 0 )
00703     {
00704         sinfo_msg_error ("input is missing or wrong!") ;
00705         return ;
00706     }
00707     
00708     if ( NULL == (fp = fopen ( filename, "w" ) ) )
00709     {
00710         sinfo_msg_error("cannot open %s", filename) ;
00711         return ;
00712     }
00713 
00714     for ( i = 0 ; i < n ; i++ )
00715     {
00716         fprintf (fp, "%le\n", parameter[i] ) ;
00717     }
00718     fclose (fp ) ;
00719 }
00720 
00728 float * 
00729 sinfo_new_ascii_to_parameter ( char * filename,
00730                            int * n )
00731 {
00732     FILE * fp ;
00733     float * parameter=NULL ;
00734     int     i=0 ;
00735 
00736     if ( filename == NULL || n == NULL )
00737     {
00738         sinfo_msg_error ("Input is missing or wrong") ;
00739         return NULL ;
00740     }
00741     
00742     if ( NULL == (fp = fopen ( filename, "r" ) ) )
00743     {
00744         sinfo_msg_error("cannot open %s", filename) ;
00745         return NULL ;
00746     }
00747 
00748     /* allocate memory */
00749 
00750     if (NULL == ( parameter = (float*) cpl_calloc (ESTIMATE, sizeof(float)) ) )
00751     {
00752         sinfo_msg_error ("cannot allocate memory") ;
00753         fclose (fp ) ;
00754         return NULL ;
00755     }
00756 
00757     i = 0 ;
00758     while ( fscanf(fp, "%g\n", &parameter[i]) != EOF )
00759     {
00760         i++ ;
00761     }
00762     *n = i ;
00763 
00764     fclose (fp ) ;
00765 
00766     return parameter ;
00767 }
00768 
00769 
00792 double * 
00793 sinfo_new_curvature_of_spectrum( cpl_image * ns_image,
00794                     int        order,
00795                          int        box_length,
00796                  int        left_pos,
00797              int        right_pos,
00798                          float      fwhm,
00799                          float      minDiff )
00800 {
00801     int i=0;
00802     int k=0;
00803     int row=0;
00804     int col=0;
00805     int counter=0;
00806     int iters=0;
00807     int xdim=0;
00808     int ndat=0;
00809     int its=0;
00810     int numpar=0;
00811     float maxval=0 ;
00812     float tol=0;
00813     float lab=0;
00814 
00815     float* col_value=NULL ;
00816     float* column_value=NULL ;
00817     pixelvalue* col_position=NULL ;
00818     int* column_position=NULL ;
00819     float* x_position=NULL ;
00820 
00821     int col_median=0;
00822     float * xdat=NULL;
00823     float * wdat=NULL;
00824     int * mpar=NULL;
00825     Vector * line=NULL;
00826     FitParams ** dec_par=NULL ;
00827     FitParams * par=NULL ;
00828     int position=0 ;
00829     int ndata=0 ;
00830     int bad_ind=0 ;
00831     dpoint * list=NULL ;
00832     double * coeffs=NULL ;
00833     double offset=0 ;
00834     int lx=0;
00835     int ly=0;
00836     float* pdata=NULL;
00837 
00838     if ( ns_image == NULL )
00839     {
00840         sinfo_msg_error("sorry, no image given") ;
00841         return NULL ;
00842     }
00843     lx=cpl_image_get_size_x(ns_image);
00844     ly=cpl_image_get_size_y(ns_image);
00845 
00846     if ( box_length <= 1 || box_length >= right_pos - left_pos )
00847     {
00848         sinfo_msg_error("wrong box length given") ;
00849         return NULL ;
00850     }
00851     if ( fwhm < 1. || fwhm > 10. )
00852     {
00853         sinfo_msg_error("wrong full width at half maximum given") ;
00854         return NULL ;
00855     }
00856     if ( left_pos < 0 || right_pos <= left_pos || right_pos > lx )
00857     {
00858         sinfo_msg_error("wrong left and right positions") ;
00859         return NULL ;
00860     }
00861     if ( minDiff < 1. )
00862     {
00863         sinfo_msg_error("wrong amplitude threshold given!") ;
00864         return NULL ;
00865     }
00866 
00867 
00868 
00869     col_value=cpl_calloc(ly,sizeof(float)) ;
00870     column_value=cpl_calloc(ly,sizeof(float)) ;
00871     col_position=(pixelvalue*)cpl_calloc(ly,sizeof(pixelvalue)) ;
00872     column_position=cpl_calloc(ly,sizeof(int)) ;
00873     x_position=cpl_calloc(ly,sizeof(float)) ;
00874 
00875     /* go through the image rows */
00876     for ( row = 0 ; row < ly ; row++ )
00877     {
00878         col_value[row] = -FLT_MAX ;
00879         col_position[row] = -1. ;
00880         /* find the maximum value in each row and store the found column */
00881         for ( col = left_pos ; col < right_pos ; col++ )
00882         {
00883             if ( pdata[col+row*lx] > col_value[row] )
00884             {
00885                 col_value[row]    = pdata[col+row*lx] ;
00886                 col_position[row] = (pixelvalue)col ;
00887             }
00888         }
00889     }
00890 
00891     /* now determine the sinfo_new_median of the found columns to be sure 
00892        to have the brightest spectrum */
00893     col_median = (int)sinfo_new_median(col_position, right_pos - left_pos) ;
00894 
00895     /* now find the peaks around col_median over the whole spectral range */
00896     for ( row = 0 ; row < ly ; row++ )
00897     {
00898         x_position[row] = 0. ;
00899         column_value[row] = -FLT_MAX ;
00900         column_position[row] = -1 ;
00901         for ( col = col_median - box_length ; 
00902               col <= col_median + box_length ; col++ )
00903         {
00904             if ( pdata[col+row*lx] > column_value[row] )
00905             {
00906                 column_value[row] = pdata[col+row*lx] ; 
00907                 column_position[row] = col ;
00908             }
00909         }
00910 
00911         /* allocate memory for the array where the line is fitted in */
00912         if ( NULL == (line = sinfo_new_vector (2*box_length + 1)) )
00913         {
00914             sinfo_msg_error ("cannot allocate new Vector in row: %d", row) ;
00915             return NULL ;
00916         }
00917 
00918         /* allocate memory */
00919         xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00920         wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00921         mpar = (int *)   cpl_calloc( MAXPAR, sizeof (int) ) ;
00922         dec_par = sinfo_new_fit_params(1) ;
00923         par = dec_par[0];
00924     
00925         counter = 0 ;
00926         bad_ind = 0 ;
00927         /* store the values to fit in a Vector object */
00928         for ( col = column_position[row] - box_length ; 
00929               col <= column_position[row] + box_length ; col++ )
00930         {
00931             if ( col < 0 || col >= lx )
00932             {
00933                 sinfo_msg_error ("wrong spectrum position or box_length "
00934                                  "given in row: %d", row) ;
00935                 cpl_free (xdat) ;
00936                 cpl_free (wdat) ;
00937                 cpl_free (mpar) ;
00938                 sinfo_new_destroy_fit_params(&dec_par) ;
00939                 sinfo_new_destroy_vector( line ) ;
00940                 return NULL ;
00941             }
00942             else if ( isnan(pdata[col+row*lx]) )
00943             {
00944                 bad_ind = 1 ;
00945             }
00946             else
00947             {
00948                 line -> data[counter] = pdata[col + row*lx] ;
00949                 counter++ ;
00950             }
00951         }
00952  
00953         /* go to the next row if a bad pixel is inside the box */
00954         if ( bad_ind == 1 )
00955         {
00956             sinfo_msg_warning ("sorry, bad pixel inside fitting box "
00957                                "in row: %d", row) ;
00958             cpl_free (xdat) ;
00959             cpl_free (wdat) ;
00960             cpl_free (mpar) ;
00961             sinfo_new_destroy_fit_params(&dec_par) ;
00962             sinfo_new_destroy_vector( line ) ;
00963             continue ;
00964         }
00965 
00966         /*--------------------------------------------------------------------
00967          * go through the line sinfo_vector
00968          * determine the maximum pixel value in the line sinfo_vector
00969          */
00970         maxval = -FLT_MAX ;
00971         position = -INT32_MAX ;
00972         for ( i = 0 ; i < counter ; i++ )
00973         {
00974             xdat[i] = i ;
00975             wdat[i] = 1.0 ;
00976             if ( line -> data[i] >= maxval )
00977             {
00978                 maxval = line -> data[i] ;
00979                 position = i ;
00980             }
00981         }
00982 
00983         /* set initial values for the fitting routine */
00984         xdim     = XDIM ;
00985         ndat     = line -> n_elements ;
00986         numpar   = MAXPAR ;
00987         tol      = TOL ;
00988         lab      = LAB ;
00989         its      = ITS ;
00990         (*par).fit_par[1] = fwhm ;
00991         (*par).fit_par[2] = (float) position ;
00992         (*par).fit_par[3] = (float) (line -> data[0] + 
00993                                      line -> data[line->n_elements - 1]) / 2.0;
00994 
00995         (*par).fit_par[0]  = maxval - ((*par).fit_par[3]) ;
00996         /* exclude negative peaks and low signal cases */
00997         if ( (*par).fit_par[0] < minDiff )
00998         {
00999             sinfo_msg_warning ("sorry, negative peak or signal of line "
01000                                "too low to fit in row: %d", row) ;
01001             cpl_free (xdat) ;
01002             cpl_free (wdat) ;
01003             cpl_free (mpar) ;
01004             sinfo_new_destroy_fit_params(&dec_par) ;
01005             sinfo_new_destroy_vector( line ) ;
01006             continue ;
01007         }
01008 
01009         for ( k = 0 ; k < MAXPAR ; k++ )
01010         {
01011             (*par).derv_par[k] = 0.0 ;
01012             mpar[k] = 1 ;
01013         }
01014 
01015         /* finally, do the least square fit using a sinfo_gaussian */
01016         if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim, 
01017                                                line -> data, wdat, 
01018                                                &ndat, (*par).fit_par,
01019                                                (*par).derv_par, mpar, 
01020                                                &numpar, &tol, &its, &lab )) )
01021         {
01022             sinfo_msg_warning ("least squares fit failed in row: "
01023                                "%d, error no.: %d", row, iters) ;
01024             cpl_free (xdat) ;
01025             cpl_free (wdat) ;
01026             cpl_free (mpar) ;
01027             sinfo_new_destroy_fit_params(&dec_par) ;
01028             sinfo_new_destroy_vector( line ) ;
01029             continue ;
01030         }
01031 
01032         /* check for negative fit results */
01033         if ( (*par).fit_par[0] <= 0. || (*par).fit_par[1] <= 1. ||
01034              (*par).fit_par[2] <= 0. )
01035         {
01036             sinfo_msg_warning ("negative parameters as fit result, "
01037                                "not used! in row: %d", row) ;
01038             cpl_free (xdat) ;
01039             cpl_free (wdat) ;
01040             cpl_free (mpar) ;
01041             sinfo_new_destroy_fit_params(&dec_par) ;
01042             sinfo_new_destroy_vector( line ) ;
01043             continue ;
01044         }
01045 
01046         /* correct the fitted position for the given row of the line 
01047            in image coordinates */
01048         x_position[row] =  (float) (column_position[row] - box_length) + 
01049                                    (*par).fit_par[2] ;
01050         printf("%d %f %f\n",row, (*par).fit_par[1], x_position[row] ) ;
01051 
01052         /* free memory */
01053         sinfo_new_destroy_fit_params(&dec_par) ;
01054         sinfo_new_destroy_vector ( line ) ;
01055         cpl_free ( xdat ) ;
01056         cpl_free ( wdat ) ;
01057         cpl_free ( mpar ) ;
01058     }
01059     /* now allocate memory for the data to fit */
01060     if ( NULL == ( list = (dpoint*) cpl_calloc (ly, sizeof (dpoint)) ) ) 
01061     {
01062         sinfo_msg_error("could not allocate memory!") ;
01063         return NULL ;
01064     }
01065 
01066     /* ------------------------------------------------------------------------
01067      * now that we have a sub-pixel resolved list of spectral maxima stored 
01068      * in x_position[row] We can fit a flux weighted straight line to the 
01069      * positions to determine the spectral column shifts.
01070      */
01071     offset = (double) ly/2. ;
01072     ndata = 0 ;
01073     for ( row = 0 ; row < ly ; row++ )
01074     {
01075         if ( x_position[row] == 0. )
01076         {
01077             continue ;
01078         }
01079         else 
01080         {
01081             list[ndata].y   = (double)x_position[row] ;
01082             list[ndata].x   = (double)row - offset ;
01083             ndata++ ;
01084         }
01085     }
01086     
01087 
01088     if ( NULL == (coeffs = sinfo_fit_1d_poly(order, list, ndata, NULL)) )
01089     {
01090         sinfo_msg_error("eclipse function sinfo_fit_1d_poly() did not work!") ;
01091         return NULL ;
01092     }
01093     cpl_free ( list ) ;
01094 
01095 
01096 
01097     cpl_free(col_value) ;
01098     cpl_free(column_value) ;
01099     cpl_free(col_position) ;
01100     cpl_free(column_position) ;
01101     cpl_free(x_position) ;
01102      
01103     return coeffs ;
01104 }
01105 
01114 cpl_image * 
01115 sinfo_new_image_warp_fits( cpl_image * image,
01116                       char      * kernel_type, 
01117                       char      * poly_table )
01118 {
01119         cpl_image  * warped=NULL;
01120     /* Following are for polynomial transforms */
01121     cpl_polynomial    * poly_u=NULL;        /* polynomial definition */
01122     cpl_polynomial    * poly_v=NULL;        /* polynomial definition */
01123         cpl_table* poly_tbl=NULL;
01124     cpl_vector      *   profile=NULL ;
01125         cpl_size local_pow[2];
01126         int             i=0;
01127 
01128     /*fscanf(poly_in,"%s",poly_string);*/
01129     /* sinfo_msg("%s",poly_string); */
01130     
01131     poly_u = cpl_polynomial_new(2);
01132         if (poly_u == NULL) {
01133             sinfo_msg_error("cannot read 2D poly from arc table") ;
01134             return NULL ;
01135         }
01136  
01137         if (poly_u != NULL) {
01138       sinfo_msg_debug("Get the arc distortion from the file %s",
01139                           poly_table);
01140       if(sinfo_is_fits_file(poly_table) != 1) {
01141         sinfo_msg_error("Input file %s is not FITS",poly_table);
01142         return NULL;
01143       }
01144 
01145       if(NULL==(poly_tbl = cpl_table_load(poly_table,1,0))) {
01146         sinfo_msg_error("cannot load the arc table") ;
01147         cpl_polynomial_delete(poly_u) ;
01148         return NULL ;
01149       }
01150 
01151       for (i=0 ; i<cpl_table_get_nrow(poly_tbl) ; i++) {
01152             local_pow[0] = cpl_table_get_int(poly_tbl, "degx", i, NULL) ; 
01153             local_pow[1] = cpl_table_get_int(poly_tbl, "degy", i, NULL) ;
01154             cpl_polynomial_set_coeff(poly_u, local_pow,
01155            cpl_table_get_double(poly_tbl, "coeff", i, NULL)) ;
01156       }
01157 
01158       cpl_table_delete(poly_tbl) ;
01159     } else {
01160       sinfo_msg("Use the ID polynomial for the arc dist") ;
01161       local_pow[0] = 1 ;
01162       local_pow[1] = 0 ;
01163       cpl_polynomial_set_coeff(poly_u, local_pow, 1.0) ;
01164     }
01165 
01166         poly_v=cpl_polynomial_new(2);
01167         local_pow[0]=0;
01168         local_pow[1]=1;
01169 
01170         cpl_polynomial_set_coeff(poly_v,local_pow,1.0);
01171     profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES) ;
01172     cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_TANH,
01173                        CPL_KERNEL_DEF_WIDTH) ;
01174     warped=sinfo_new_warp_image_generic(image,kernel_type,poly_u,poly_v);
01175     /* YVES WAY 
01176       warped = cpl_image_new(cpl_image_get_size_x(image),
01177                                  cpl_image_get_size_y(image),
01178                                  CPL_TYPE_FLOAT);
01179        
01180     if (cpl_image_warp_polynomial(warped, image, poly_u, poly_v, 
01181                       profile,CPL_KERNEL_DEF_WIDTH,
01182                       profile,CPL_KERNEL_DEF_WIDTH)
01183         != CPL_ERROR_NONE) {
01184             sinfo_msg_error("cannot correct the distortion") ;
01185             cpl_image_delete(warped) ;
01186             cpl_polynomial_delete(poly_u) ;
01187             cpl_polynomial_delete(poly_v) ;
01188             cpl_vector_delete(profile) ;
01189             return NULL;
01190     }
01191     */
01192 
01193       cpl_vector_delete(profile) ;
01194       if (poly_u!=NULL) cpl_polynomial_delete(poly_u);
01195       if (poly_v!=NULL) cpl_polynomial_delete(poly_v);
01196     
01197       return warped;
01198 }
01199     

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