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         return NULL ;
00754     }
00755 
00756     i = 0 ;
00757     while ( fscanf(fp, "%g\n", &parameter[i]) != EOF )
00758     {
00759         i++ ;
00760     }
00761     *n = i ;
00762 
00763     fclose (fp ) ;
00764 
00765     return parameter ;
00766 }
00767 
00768 
00791 double * 
00792 sinfo_new_curvature_of_spectrum( cpl_image * ns_image,
00793                     int        order,
00794                          int        box_length,
00795                  int        left_pos,
00796              int        right_pos,
00797                          float      fwhm,
00798                          float      minDiff )
00799 {
00800     int i=0;
00801     int k=0;
00802     int row=0;
00803     int col=0;
00804     int counter=0;
00805     int iters=0;
00806     int xdim=0;
00807     int ndat=0;
00808     int its=0;
00809     int numpar=0;
00810     float maxval=0 ;
00811     float tol=0;
00812     float lab=0;
00813 
00814     float* col_value=NULL ;
00815     float* column_value=NULL ;
00816     pixelvalue* col_position=NULL ;
00817     int* column_position=NULL ;
00818     float* x_position=NULL ;
00819 
00820     int col_median=0;
00821     float * xdat=NULL;
00822     float * wdat=NULL;
00823     int * mpar=NULL;
00824     Vector * line=NULL;
00825     FitParams ** dec_par=NULL ;
00826     FitParams * par=NULL ;
00827     int position=0 ;
00828     int ndata=0 ;
00829     int bad_ind=0 ;
00830     dpoint * list=NULL ;
00831     double * coeffs=NULL ;
00832     double offset=0 ;
00833     int lx=0;
00834     int ly=0;
00835     float* pdata=NULL;
00836 
00837     if ( ns_image == NULL )
00838     {
00839         sinfo_msg_error("sorry, no image given") ;
00840         return NULL ;
00841     }
00842     lx=cpl_image_get_size_x(ns_image);
00843     ly=cpl_image_get_size_y(ns_image);
00844 
00845     if ( box_length <= 1 || box_length >= right_pos - left_pos )
00846     {
00847         sinfo_msg_error("wrong box length given") ;
00848         return NULL ;
00849     }
00850     if ( fwhm < 1. || fwhm > 10. )
00851     {
00852         sinfo_msg_error("wrong full width at half maximum given") ;
00853         return NULL ;
00854     }
00855     if ( left_pos < 0 || right_pos <= left_pos || right_pos > lx )
00856     {
00857         sinfo_msg_error("wrong left and right positions") ;
00858         return NULL ;
00859     }
00860     if ( minDiff < 1. )
00861     {
00862         sinfo_msg_error("wrong amplitude threshold given!") ;
00863         return NULL ;
00864     }
00865 
00866 
00867 
00868     col_value=cpl_calloc(ly,sizeof(float)) ;
00869     column_value=cpl_calloc(ly,sizeof(float)) ;
00870     col_position=(pixelvalue*)cpl_calloc(ly,sizeof(pixelvalue)) ;
00871     column_position=cpl_calloc(ly,sizeof(int)) ;
00872     x_position=cpl_calloc(ly,sizeof(float)) ;
00873 
00874     /* go through the image rows */
00875     for ( row = 0 ; row < ly ; row++ )
00876     {
00877         col_value[row] = -FLT_MAX ;
00878         col_position[row] = -1. ;
00879         /* find the maximum value in each row and store the found column */
00880         for ( col = left_pos ; col < right_pos ; col++ )
00881         {
00882             if ( pdata[col+row*lx] > col_value[row] )
00883             {
00884                 col_value[row]    = pdata[col+row*lx] ;
00885                 col_position[row] = (pixelvalue)col ;
00886             }
00887         }
00888     }
00889 
00890     /* now determine the sinfo_new_median of the found columns to be sure 
00891        to have the brightest spectrum */
00892     col_median = (int)sinfo_new_median(col_position, right_pos - left_pos) ;
00893 
00894     /* now find the peaks around col_median over the whole spectral range */
00895     for ( row = 0 ; row < ly ; row++ )
00896     {
00897         x_position[row] = 0. ;
00898         column_value[row] = -FLT_MAX ;
00899         column_position[row] = -1 ;
00900         for ( col = col_median - box_length ; 
00901               col <= col_median + box_length ; col++ )
00902         {
00903             if ( pdata[col+row*lx] > column_value[row] )
00904             {
00905                 column_value[row] = pdata[col+row*lx] ; 
00906                 column_position[row] = col ;
00907             }
00908         }
00909 
00910         /* allocate memory for the array where the line is fitted in */
00911         if ( NULL == (line = sinfo_new_vector (2*box_length + 1)) )
00912         {
00913             sinfo_msg_error ("cannot allocate new Vector in row: %d", row) ;
00914             return NULL ;
00915         }
00916 
00917         /* allocate memory */
00918         xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00919         wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
00920         mpar = (int *)   cpl_calloc( MAXPAR, sizeof (int) ) ;
00921         dec_par = sinfo_new_fit_params(1) ;
00922         par = dec_par[0];
00923     
00924         counter = 0 ;
00925         bad_ind = 0 ;
00926         /* store the values to fit in a Vector object */
00927         for ( col = column_position[row] - box_length ; 
00928               col <= column_position[row] + box_length ; col++ )
00929         {
00930             if ( col < 0 || col >= lx )
00931             {
00932                 sinfo_msg_error ("wrong spectrum position or box_length "
00933                                  "given in row: %d", row) ;
00934                 cpl_free (xdat) ;
00935                 cpl_free (wdat) ;
00936                 cpl_free (mpar) ;
00937                 sinfo_new_destroy_fit_params(&dec_par) ;
00938                 sinfo_new_destroy_vector( line ) ;
00939                 return NULL ;
00940             }
00941             else if ( isnan(pdata[col+row*lx]) )
00942             {
00943                 bad_ind = 1 ;
00944             }
00945             else
00946             {
00947                 line -> data[counter] = pdata[col + row*lx] ;
00948                 counter++ ;
00949             }
00950         }
00951  
00952         /* go to the next row if a bad pixel is inside the box */
00953         if ( bad_ind == 1 )
00954         {
00955             sinfo_msg_warning ("sorry, bad pixel inside fitting box "
00956                                "in row: %d", row) ;
00957             cpl_free (xdat) ;
00958             cpl_free (wdat) ;
00959             cpl_free (mpar) ;
00960             sinfo_new_destroy_fit_params(&dec_par) ;
00961             sinfo_new_destroy_vector( line ) ;
00962             continue ;
00963         }
00964 
00965         /*--------------------------------------------------------------------
00966          * go through the line sinfo_vector
00967          * determine the maximum pixel value in the line sinfo_vector
00968          */
00969         maxval = -FLT_MAX ;
00970         position = -INT32_MAX ;
00971         for ( i = 0 ; i < counter ; i++ )
00972         {
00973             xdat[i] = i ;
00974             wdat[i] = 1.0 ;
00975             if ( line -> data[i] >= maxval )
00976             {
00977                 maxval = line -> data[i] ;
00978                 position = i ;
00979             }
00980         }
00981 
00982         /* set initial values for the fitting routine */
00983         xdim     = XDIM ;
00984         ndat     = line -> n_elements ;
00985         numpar   = MAXPAR ;
00986         tol      = TOL ;
00987         lab      = LAB ;
00988         its      = ITS ;
00989         (*par).fit_par[1] = fwhm ;
00990         (*par).fit_par[2] = (float) position ;
00991         (*par).fit_par[3] = (float) (line -> data[0] + 
00992                                      line -> data[line->n_elements - 1]) / 2.0;
00993 
00994         (*par).fit_par[0]  = maxval - ((*par).fit_par[3]) ;
00995         /* exclude negative peaks and low signal cases */
00996         if ( (*par).fit_par[0] < minDiff )
00997         {
00998             sinfo_msg_warning ("sorry, negative peak or signal of line "
00999                                "too low to fit in row: %d", row) ;
01000             cpl_free (xdat) ;
01001             cpl_free (wdat) ;
01002             cpl_free (mpar) ;
01003             sinfo_new_destroy_fit_params(&dec_par) ;
01004             sinfo_new_destroy_vector( line ) ;
01005             continue ;
01006         }
01007 
01008         for ( k = 0 ; k < MAXPAR ; k++ )
01009         {
01010             (*par).derv_par[k] = 0.0 ;
01011             mpar[k] = 1 ;
01012         }
01013 
01014         /* finally, do the least square fit using a sinfo_gaussian */
01015         if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim, 
01016                                                line -> data, wdat, 
01017                                                &ndat, (*par).fit_par,
01018                                                (*par).derv_par, mpar, 
01019                                                &numpar, &tol, &its, &lab )) )
01020         {
01021             sinfo_msg_warning ("least squares fit failed in row: "
01022                                "%d, error no.: %d", row, iters) ;
01023             cpl_free (xdat) ;
01024             cpl_free (wdat) ;
01025             cpl_free (mpar) ;
01026             sinfo_new_destroy_fit_params(&dec_par) ;
01027             sinfo_new_destroy_vector( line ) ;
01028             continue ;
01029         }
01030 
01031         /* check for negative fit results */
01032         if ( (*par).fit_par[0] <= 0. || (*par).fit_par[1] <= 1. ||
01033              (*par).fit_par[2] <= 0. )
01034         {
01035             sinfo_msg_warning ("negative parameters as fit result, "
01036                                "not used! in row: %d", row) ;
01037             cpl_free (xdat) ;
01038             cpl_free (wdat) ;
01039             cpl_free (mpar) ;
01040             sinfo_new_destroy_fit_params(&dec_par) ;
01041             sinfo_new_destroy_vector( line ) ;
01042             continue ;
01043         }
01044 
01045         /* correct the fitted position for the given row of the line 
01046            in image coordinates */
01047         x_position[row] =  (float) (column_position[row] - box_length) + 
01048                                    (*par).fit_par[2] ;
01049         printf("%d %f %f\n",row, (*par).fit_par[1], x_position[row] ) ;
01050 
01051         /* free memory */
01052         sinfo_new_destroy_fit_params(&dec_par) ;
01053         sinfo_new_destroy_vector ( line ) ;
01054         cpl_free ( xdat ) ;
01055         cpl_free ( wdat ) ;
01056         cpl_free ( mpar ) ;
01057     }
01058     /* now allocate memory for the data to fit */
01059     if ( NULL == ( list = (dpoint*) cpl_calloc (ly, sizeof (dpoint)) ) ) 
01060     {
01061         sinfo_msg_error("could not allocate memory!") ;
01062         return NULL ;
01063     }
01064 
01065     /* ------------------------------------------------------------------------
01066      * now that we have a sub-pixel resolved list of spectral maxima stored 
01067      * in x_position[row] We can fit a flux weighted straight line to the 
01068      * positions to determine the spectral column shifts.
01069      */
01070     offset = (double) ly/2. ;
01071     ndata = 0 ;
01072     for ( row = 0 ; row < ly ; row++ )
01073     {
01074         if ( x_position[row] == 0. )
01075         {
01076             continue ;
01077         }
01078         else 
01079         {
01080             list[ndata].y   = (double)x_position[row] ;
01081             list[ndata].x   = (double)row - offset ;
01082             ndata++ ;
01083         }
01084     }
01085     
01086 
01087     if ( NULL == (coeffs = sinfo_fit_1d_poly(order, list, ndata, NULL)) )
01088     {
01089         sinfo_msg_error("eclipse function sinfo_fit_1d_poly() did not work!") ;
01090         return NULL ;
01091     }
01092     cpl_free ( list ) ;
01093 
01094 
01095 
01096     cpl_free(col_value) ;
01097     cpl_free(column_value) ;
01098     cpl_free(col_position) ;
01099     cpl_free(column_position) ;
01100     cpl_free(x_position) ;
01101      
01102     return coeffs ;
01103 }
01104 
01113 cpl_image * 
01114 sinfo_new_image_warp_fits( cpl_image * image,
01115                       char      * kernel_type, 
01116                       char      * poly_table )
01117 {
01118         cpl_image  * warped=NULL;
01119     /* Following are for polynomial transforms */
01120     cpl_polynomial    * poly_u=NULL;        /* polynomial definition */
01121     cpl_polynomial    * poly_v=NULL;        /* polynomial definition */
01122         cpl_table* poly_tbl=NULL;
01123     cpl_vector      *   profile=NULL ;
01124         int local_pow[2];
01125         int             i=0;
01126 
01127     /*fscanf(poly_in,"%s",poly_string);*/
01128     /* sinfo_msg("%s",poly_string); */
01129     
01130     poly_u = cpl_polynomial_new(2);
01131         if (poly_u == NULL) {
01132             sinfo_msg_error("cannot read 2D poly from arc table") ;
01133             return NULL ;
01134         }
01135  
01136         if (poly_u != NULL) {
01137       sinfo_msg_debug("Get the arc distortion from the file %s",
01138                           poly_table);
01139       if(sinfo_is_fits_file(poly_table) != 1) {
01140         sinfo_msg_error("Input file %s is not FITS",poly_table);
01141         return NULL;
01142       }
01143 
01144       if(NULL==(poly_tbl = cpl_table_load(poly_table,1,0))) {
01145         sinfo_msg_error("cannot load the arc table") ;
01146         cpl_polynomial_delete(poly_u) ;
01147         return NULL ;
01148       }
01149 
01150       for (i=0 ; i<cpl_table_get_nrow(poly_tbl) ; i++) {
01151             local_pow[0] = cpl_table_get_int(poly_tbl, "degx", i, NULL) ; 
01152             local_pow[1] = cpl_table_get_int(poly_tbl, "degy", i, NULL) ;
01153             cpl_polynomial_set_coeff(poly_u, local_pow,
01154            cpl_table_get_double(poly_tbl, "coeff", i, NULL)) ;
01155       }
01156 
01157       cpl_table_delete(poly_tbl) ;
01158     } else {
01159       sinfo_msg("Use the ID polynomial for the arc dist") ;
01160       local_pow[0] = 1 ;
01161       local_pow[1] = 0 ;
01162       cpl_polynomial_set_coeff(poly_u, local_pow, 1.0) ;
01163     }
01164 
01165         poly_v=cpl_polynomial_new(2);
01166         local_pow[0]=0;
01167         local_pow[1]=1;
01168 
01169         cpl_polynomial_set_coeff(poly_v,local_pow,1.0);
01170     profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES) ;
01171     cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_TANH,
01172                        CPL_KERNEL_DEF_WIDTH) ;
01173     warped=sinfo_new_warp_image_generic(image,kernel_type,poly_u,poly_v);
01174     /* YVES WAY 
01175       warped = cpl_image_new(cpl_image_get_size_x(image),
01176                                  cpl_image_get_size_y(image),
01177                                  CPL_TYPE_FLOAT);
01178        
01179     if (cpl_image_warp_polynomial(warped, image, poly_u, poly_v, 
01180                       profile,CPL_KERNEL_DEF_WIDTH,
01181                       profile,CPL_KERNEL_DEF_WIDTH)
01182         != CPL_ERROR_NONE) {
01183             sinfo_msg_error("cannot correct the distortion") ;
01184             cpl_image_delete(warped) ;
01185             cpl_polynomial_delete(poly_u) ;
01186             cpl_polynomial_delete(poly_v) ;
01187             cpl_vector_delete(profile) ;
01188             return NULL;
01189     }
01190     */
01191 
01192       cpl_vector_delete(profile) ;
01193       if (poly_u!=NULL) cpl_polynomial_delete(poly_u);
01194       if (poly_v!=NULL) cpl_polynomial_delete(poly_v);
01195     
01196       return warped;
01197 }
01198     

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