SINFONI Pipeline Reference Manual  2.5.2
sinfo_coltilt.c
1 /*
2  * This file is part of the ESO SINFONI Pipeline
3  * Copyright (C) 2004,2005 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18  */
19 /*******************************************************************************
20 * E.S.O. - VLT project
21 *
22 *
23 *
24 * who when what
25 * -------- -------- ----------------------------------------------
26 * schreib 19/12/00 created
27 */
28 
29 /************************************************************************
30 * NAME
31 * sinfo_coltilt.c -
32 * procedures to correct for tilted spectra
33 *
34 * SYNOPSIS
35 * 1) float sinfo_new_slope_of_spectrum(cpl_image * ns_image,
36 * int box_length,
37 * float fwhm,
38 * float minDiff )
39 * 2) cpl_image * sinfo_new_shift_rows(cpl_image * image,
40 * float slope )
41 * 3) void sinfo_new_parameter_to_ascii ( float * parameter,
42 * int n,
43 * char * filename )
44 * 4) float * sinfo_new_ascii_to_parameter ( char * filename,
45 * int * n )
46 * 5) double * sinfo_new_curvature_of_spectrum( cpl_image * ns_image,
47 * int order,
48 * int box_length,
49 * int left_pos,
50 * int right_pos,
51 * float fwhm,
52 * float minDiff )
53 *
54 *
55 * DESCRIPTION
56 * 1) determines the sub-pixel shifts of each row by using
57 * an image with at least one continuum spectrum of a pinhole
58 * this is done by searching the spectrum within the image
59 * then fitting the spectrum along the rows within a given box
60 * by a Gaussian, so that the exact position is determined for
61 * each row. Afterwards, a straight line is fitted through the
62 * fitted positions. The slope of this linear fit is returned.
63 * 2) shifts the rows of a raw image by using the output of
64 * sinfo_slopeOfSpectrum and applying polynomial interpolation
65 * 3) stores parameters in an ASCII file
66 * 4) writes parameters stored in an ASCII file in an float array
67 * 5) this routine determines the curvature of a spectrum by fitting
68 * a polynomial to a continuum spectrum. This is done by using
69 * an image with at least one continuum spectrum of a pinhole.
70 * this is done by searching the spectrum within the image
71 * then fitting the spectrum along the rows within a given box
72 * by a Gaussian, so that the exact position is determined for
73 * each row. Afterwards, a polynomial is fitted through the
74 * found positions. The polynomial coefficients are returned.
75 *
76 *
77 * FILES
78 *
79 * ENVIRONMENT
80 *
81 * RETURN VALUES
82 *
83 * CAUTIONS
84 *
85 * EXAMPLES
86 *
87 * SEE ALSO
88 *
89 * BUGS
90 *
91 *------------------------------------------------------------------------
92 */
93 #ifdef HAVE_CONFIG_H
94 # include <config.h>
95 #endif
96 
97 #define POSIX_SOURCE 1
98 #include "sinfo_vltPort.h"
99 
100 /*
101  * System Headers
102  */
103 
104 /*
105  * Local Headers
106  */
107 
108 #include "sinfo_coltilt.h"
109 #include "sinfo_new_resampling.h"
110 #include "sinfo_fit_curve.h"
111 #include "sinfo_functions.h"
119 /*----------------------------------------------------------------------------
120  * Function codes
121  *--------------------------------------------------------------------------*/
122 
143 float
144 sinfo_new_slope_of_spectrum( cpl_image * ns_image,
145  int box_length,
146  float fwhm,
147  float minDiff )
148 {
149  int i, k, row, col ;
150  int counter, iters ;
151  int xdim, ndat, its, numpar ;
152  float maxval ;
153  float tol, lab ;
154  float* col_value=NULL ;
155  float* column_value=NULL ;
156  pixelvalue* col_position=NULL ;
157  int* column_position=NULL ;
158  float* x_position=NULL ;
159 
160 
161  int col_median ;
162  float * xdat, * wdat ;
163  int * mpar ;
164  Vector * line ;
165  FitParams ** dec_par ;
166  FitParams * par ;
167 
168  float* x=NULL;
169  float* y=NULL;
170  float* sig=NULL ;
171 
172  int position ;
173  int ndata, mwt ;
174  float a, b, siga, sigb, chi2, q ;
175  int bad_ind ;
176  int lx=0;
177  int ly=0;
178  float* pdata=NULL;
179 
180  if ( ns_image == NULL )
181  {
182  sinfo_msg_error(" sorry, no image given") ;
183  return FLAG ;
184  }
185  lx=cpl_image_get_size_x(ns_image);
186  ly=cpl_image_get_size_x(ns_image);
187 
188 
189  if ( box_length <= 1 || box_length >= (int) sqrt(lx) )
190  {
191  sinfo_msg_error(" wrong box length given") ;
192  return FLAG ;
193  }
194  if ( fwhm < 1. || fwhm > 10. )
195  {
196  sinfo_msg_error("wrong full width at half maximum given") ;
197  return FLAG ;
198  }
199  if ( minDiff < 1. )
200  {
201  sinfo_msg_error("wrong amplitude threshold given") ;
202  return FLAG ;
203  }
204 
205 
206 
207  col_value=cpl_calloc(ly,sizeof(float)) ;
208  column_value=cpl_calloc(ly,sizeof(float)) ;
209  col_position=(pixelvalue*)cpl_calloc(ly,sizeof(pixelvalue)) ;
210  column_position=cpl_calloc(ly,sizeof(int)) ;
211  x_position=cpl_calloc(ly,sizeof(float)) ;
212 
213 
214 
215  x=cpl_calloc(lx,sizeof(float));
216  y=cpl_calloc(lx,sizeof(float));
217  sig=cpl_calloc(lx,sizeof(float)) ;
218  pdata=cpl_image_get_data_float(ns_image);
219  /* go through the image rows */
220  for ( row = 0 ; row < ly ; row++ )
221  {
222  col_value[row] = -FLT_MAX ;
223  col_position[row] = -1. ;
224  /* find the maximum value in each row and store the found column */
225  for ( col = 0 ; col < lx ; col++ )
226  {
227  if ( pdata[col+row*lx] > col_value[row] )
228  {
229  col_value[row] = pdata[col+row*lx] ;
230  col_position[row] = (pixelvalue)col ;
231  }
232  }
233  }
234 
235  /* now determine the sinfo_new_median of the found columns to be sure
236  to have the brightest spectrum */
237  col_median = (int)sinfo_new_median(col_position, ly) ;
238  sinfo_msg ("sinfo_new_median column position of brightest spectrum %d\n",
239  col_median) ;
240 
241  /* now find the peaks around col_median over the whole spectral range */
242  for ( row = 0 ; row < ly ; row++ )
243  {
244  x_position[row] = 0. ;
245  column_value[row] = -FLT_MAX ;
246  column_position[row] = -1 ;
247  for ( col = col_median - box_length ;
248  col <= col_median + box_length ; col++ )
249  {
250  if ( pdata[col+row*lx] > column_value[row] )
251  {
252  column_value[row] = pdata[col+row*lx] ;
253  column_position[row] = col ;
254  }
255  }
256 
257  /* allocate memory for the array where the line is fitted in */
258  if ( NULL == (line = sinfo_new_vector (2*box_length + 1)) )
259  {
260  sinfo_msg_error ("cannot allocate new Vector in row %d", row) ;
261  return FLAG ;
262  }
263 
264  /* allocate memory */
265  xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
266  wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
267  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
268  dec_par = sinfo_new_fit_params(1) ;
269  par = dec_par[0];
270 
271  counter = 0 ;
272  bad_ind = 0 ;
273  /* store the values to fit in a Vector object */
274  for ( col = column_position[row] - box_length ;
275  col <= column_position[row] + box_length ; col++ )
276  {
277  if ( col < 0 || col >= lx )
278  {
279  sinfo_msg_error ("wrong spectrum position or box_length "
280  "given in row: %d", row) ;
281  cpl_free (xdat) ;
282  cpl_free (wdat) ;
283  cpl_free (mpar) ;
284  sinfo_new_destroy_fit_params(&dec_par) ;
285  sinfo_new_destroy_vector( line ) ;
286  return FLAG ;
287  }
288  else if ( isnan(pdata[col+row*lx]) )
289  {
290  bad_ind = 1 ;
291  }
292  else
293  {
294  line -> data[counter] = pdata[col + row*lx] ;
295  counter++ ;
296  }
297  }
298 
299  /* go to the next row if a bad pixel is inside the box */
300  if ( bad_ind == 1 )
301  {
302  sinfo_msg_warning ("sorry, bad pixel inside fitting "
303  "box in row: %d", row) ;
304  cpl_free (xdat) ;
305  cpl_free (wdat) ;
306  cpl_free (mpar) ;
307  sinfo_new_destroy_fit_params(&dec_par) ;
308  sinfo_new_destroy_vector( line ) ;
309  continue ;
310  }
311 
312  /*--------------------------------------------------------------------
313  * go through the line sinfo_vector
314  * determine the maximum pixel value in the line sinfo_vector
315  */
316  maxval = -FLT_MAX ;
317  position = -INT32_MAX ;
318  for ( i = 0 ; i < counter ; i++ )
319  {
320  xdat[i] = i ;
321  wdat[i] = 1.0 ;
322  if ( line -> data[i] >= maxval )
323  {
324  maxval = line -> data[i] ;
325  position = i ;
326  }
327  }
328 
329  /* set initial values for the fitting routine */
330  xdim = XDIM ;
331  ndat = line -> n_elements ;
332  numpar = MAXPAR ;
333  tol = TOL ;
334  lab = LAB ;
335  its = ITS ;
336  (*par).fit_par[1] = fwhm ;
337  (*par).fit_par[2] = (float) position ;
338  (*par).fit_par[3] = (float) (line -> data[0] +
339  line -> data[line->n_elements - 1]) / 2.0 ;
340 
341  (*par).fit_par[0] = maxval - ((*par).fit_par[3]) ;
342  /* exclude negative peaks and low signal cases */
343  if ( (*par).fit_par[0] < minDiff )
344  {
345  sinfo_msg_warning ("sorry, negative peak or signal of line "
346  "too low to fit in row: %d", row) ;
347  cpl_free (xdat) ;
348  cpl_free (wdat) ;
349  cpl_free (mpar) ;
350  sinfo_new_destroy_fit_params(&dec_par) ;
351  sinfo_new_destroy_vector( line ) ;
352  continue ;
353  }
354 
355  for ( k = 0 ; k < MAXPAR ; k++ )
356  {
357  (*par).derv_par[k] = 0.0 ;
358  mpar[k] = 1 ;
359  }
360 
361  /* finally, do the least square fit using a sinfo_gaussian */
362  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim,
363  line -> data, wdat,
364  &ndat, (*par).fit_par,
365  (*par).derv_par, mpar,
366  &numpar, &tol, &its, &lab )) )
367  {
368  sinfo_msg_warning ("sinfo_new_lsqfit_c: least squares fit "
369  "failed in row: %d, error no.: %d",row,iters) ;
370  cpl_free (xdat) ;
371  cpl_free (wdat) ;
372  cpl_free (mpar) ;
373  sinfo_new_destroy_fit_params(&dec_par) ;
374  sinfo_new_destroy_vector( line ) ;
375  continue ;
376  }
377 
378  /* check for negative fit results */
379  if ( (*par).fit_par[0] <= 0. || (*par).fit_par[1] <= 0. ||
380  (*par).fit_par[2] <= 0. )
381  {
382  sinfo_msg_warning ("negative parameters as fit result, "
383  "not used! in row: %d", row) ;
384  cpl_free (xdat) ;
385  cpl_free (wdat) ;
386  cpl_free (mpar) ;
387  sinfo_new_destroy_fit_params(&dec_par) ;
388  sinfo_new_destroy_vector( line ) ;
389  continue ;
390  }
391 
392  /* correct the fitted position for the given row of the line in
393  image coordinates */
394  x_position[row] = (float) (column_position[row] - box_length) +
395  (*par).fit_par[2] ;
396 
397  /* store the fit errors of the positions as weights for the later
398  linear fit */
399  sig[row] = (*par).derv_par[2] ;
400 
401  /* free memory */
402  sinfo_new_destroy_fit_params(&dec_par) ;
403  sinfo_new_destroy_vector ( line ) ;
404  cpl_free ( xdat ) ;
405  cpl_free ( wdat ) ;
406  cpl_free ( mpar ) ;
407  }
408 
409  /* -----------------------------------------------------------------------
410  * now that we have a sub-pixel resolved list of spectral maxima stored
411  * in x_position[row]
412  * We can fit a flux weighted straight line to the positions to determine
413  * the spectral column shifts.
414  */
415  ndata = 0 ;
416  for ( row = 0 ; row < lx ; row++ )
417  {
418  if ( x_position[row] == 0. || sig[row] == 0. )
419  {
420  continue ;
421  }
422  else
423  {
424  y[ndata] = x_position[row] ;
425  x[ndata] = (float)row ;
426  sig[ndata] = sig[row] ;
427  ndata++ ;
428  }
429  }
430  if ( ndata < 10 )
431  {
432  sinfo_msg_error("not enough positions to do the linear fit") ;
433  return FLAG ;
434  }
435 
436  /* now do the fit and return the slope of the straight line */
437  mwt = 0 ;
438  sinfo_my_fit(x, y, ndata, sig, mwt, &a, &b, &siga, &sigb, &chi2, &q) ;
439 
440  cpl_free(col_value) ;
441  cpl_free(column_value) ;
442  cpl_free(col_position) ;
443  cpl_free(column_position) ;
444  cpl_free(x_position) ;
445 
446  cpl_free(x);
447  cpl_free(y);
448  cpl_free(sig) ;
449 
450  return b ;
451 }
452 
465 cpl_image *
466 sinfo_new_shift_rows( cpl_image * image,
467  float slope,
468  int n_order )
469 {
470  cpl_image * returnImage=NULL ;
471  float xshift=0 ;
472  int intshift = 0 ;
473  float sum=0;
474  float new_sum=0;
475 
476  float* xnum=NULL ;
477  float* row_data=NULL ;
478  float* corrected_row_data=NULL ;
479 
480  float eval=0 /*, dy*/ ;
481  float * imageptr=NULL ;
482  int col=0;
483  int row=0;
484  int firstpos=0;
485  int n_points=0;
486  int i=0;
487  int flag=0;
488  int ilx=0;
489  int ily=0;
490  /*
491  int olx=0;
492  int oly=0;
493  */
494  float* pidata=NULL;
495  float* podata=NULL;
496 
497  if ( image == NULL )
498  {
499  sinfo_msg_error("sorry, no image given") ;
500  return NULL ;
501  }
502 
503  if ( slope == 0. )
504  {
505  sinfo_msg_error("there is no need to shift the image rows!") ;
506  return NULL ;
507  }
508 
509  if ( n_order <= 0 )
510  {
511  sinfo_msg_error("wrong order of interpolation polynom given!") ;
512  return NULL ;
513  }
514 
515  returnImage = cpl_image_duplicate( image ) ;
516  ilx=cpl_image_get_size_x(image);
517  ily=cpl_image_get_size_y(image);
518  /*
519  olx=cpl_image_get_size_x(returnImage);
520  oly=cpl_image_get_size_y(returnImage);
521  */
522  pidata=cpl_image_get_data_float(image);
523  podata=cpl_image_get_data_float(returnImage);
524 
525 
526  n_points = n_order + 1 ;
527  if ( n_points % 2 == 0 )
528  {
529  firstpos = (int)(n_points/2) - 1 ;
530  }
531  else
532  {
533  firstpos = (int)(n_points/2) ;
534  }
535 
536 
537  xnum=cpl_calloc(n_order + 1,sizeof(float)) ;
538  row_data=cpl_calloc(ilx,sizeof(float)) ;
539  corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
540 
541  /* fill the xa[] array for the polint function */
542  for ( i = 0 ; i < n_points ; i++ )
543  {
544  xnum[i] = i ;
545  }
546 
547  /* go through the image rows */
548  for ( row = 0 ; row < ily ; row++ )
549  {
550  /* determine the shift for each row, the middle row is not shifted */
551  xshift = slope * (float)( (ily / 2) - row ) ;
552 
553  intshift = sinfo_new_nint(xshift) ;
554  xshift = xshift - (float)intshift ;
555 
556  for ( col = 0 ; col < ilx ; col++ )
557  {
558  corrected_row_data[col] = 0. ;
559  }
560  sum = 0. ; /* initialize flux for later rescaling */
561  /* go through the image columns */
562  for ( col = 0 ; col < ilx ; col++ )
563  {
564  /* consider integer pixel shifts */
565  if ( intshift < 0 )
566  {
567  if ( col - intshift < ilx )
568  {
569  row_data[col] = pidata[col-intshift+row*ilx] ;
570  }
571  else
572  {
573  row_data[col] = 0. ;
574  }
575  }
576  else if ( intshift > 0 )
577  {
578  if ( col - intshift >= 0 )
579  {
580  row_data[col] = pidata[col-intshift+row*ilx] ;
581  }
582  else
583  {
584  row_data[col] = 0. ;
585  }
586  }
587  else
588  {
589  row_data[col] = pidata[col+row*ilx] ;
590  }
591 
592  /* don't consider the sinfo_edge pixels for flux calculation */
593  if ( col != 0 && col != ilx - 1 && !isnan(row_data[col]) )
594  {
595  sum += row_data[col] ;
596  }
597  if (isnan(row_data[col]))
598  {
599  row_data[col] = 0. ;
600  for (i = col - firstpos ; i < col - firstpos + n_points ; i++ )
601  {
602  if ( i < 0 ) continue ;
603  if ( i >= ilx) continue ;
604  corrected_row_data[i] = ZERO ;
605  }
606  }
607  }
608 
609 
610  /* --------------------------------------------------------------------
611  * now we do the polynomial interpolation to achieve the fractional
612  * shift that means call polint
613  */
614  new_sum = 0. ;
615  for ( col = 0 ; col < ilx ; col++ )
616  {
617  /* ---------------------------------------------------------------
618  * now determine the arrays of size n_points with which the
619  * polynom is determined and determine the position eval
620  * where the polynom is evaluated in polint of N.R..
621  * Take care of the points near the row edges!
622  */
623  if ( isnan(corrected_row_data[col]) )
624  {
625  continue ;
626  }
627  if ( col - firstpos < 0 )
628  {
629  imageptr = &row_data[0] ;
630  eval = (float)col - xshift ;
631  }
632  else if ( col - firstpos + n_points >= ilx )
633  {
634  imageptr = &row_data[ilx - n_points] ;
635  eval = (float)(col + n_points - ilx) - xshift ;
636  }
637  else
638  {
639  imageptr = &row_data[col-firstpos] ;
640  eval = (float)firstpos - xshift ;
641  }
642 
643  flag=0;
644  corrected_row_data[col]=sinfo_new_nev_ille(xnum,imageptr,
645  n_order,eval,&flag);
646  /*polint( xnum - 1, imageptr, n_points, eval,
647  &corrected_row_data[col], &dy ) ;*/
648 
649  /* don't take the sinfo_edge points to calculate
650  the scaling factor */
651  if (col != 0 && col != ilx - 1 && !isnan(corrected_row_data[col]) )
652  {
653  new_sum += corrected_row_data[col] ;
654  }
655  }
656 
657  if ( new_sum == 0. )
658  {
659  new_sum = 1. ;
660  }
661  for ( col = 0 ; col < ilx ; col++ )
662  {
663  if ( isnan(corrected_row_data[col]))
664  {
665  podata[col+row*ilx] = ZERO ;
666  }
667  else
668  {
669  /* rescale the row data and fill the returned image */
670  /* This gives sometimes inconsistent results if
671  bad pixels are around */
672  /* rescaling is commented out because it delivers wrong results
673  in case of appearance of blanks or bad pixels */
674  /* corrected_row_data[col] *= sum / new_sum ; */
675  podata[col+row*ilx] = corrected_row_data[col] ;
676  }
677  }
678  }
679 
680  cpl_free(xnum) ;
681  cpl_free(row_data) ;
682  cpl_free(corrected_row_data);
683 
684  return returnImage ;
685 }
686 
687 
698 void
699 sinfo_new_parameter_to_ascii ( float * parameter,
700  int n,
701  char * filename )
702 {
703  FILE * fp ;
704  int i=0 ;
705 
706  if ( parameter == NULL || filename == NULL || n <= 0 )
707  {
708  sinfo_msg_error ("input is missing or wrong!") ;
709  return ;
710  }
711 
712  if ( NULL == (fp = fopen ( filename, "w" ) ) )
713  {
714  sinfo_msg_error("cannot open %s", filename) ;
715  return ;
716  }
717 
718  for ( i = 0 ; i < n ; i++ )
719  {
720  fprintf (fp, "%le\n", parameter[i] ) ;
721  }
722  fclose (fp ) ;
723 }
724 
732 float *
733 sinfo_new_ascii_to_parameter ( char * filename,
734  int * n )
735 {
736  FILE * fp ;
737  float * parameter=NULL ;
738  int i=0 ;
739 
740  if ( filename == NULL || n == NULL )
741  {
742  sinfo_msg_error ("Input is missing or wrong") ;
743  return NULL ;
744  }
745 
746  if ( NULL == (fp = fopen ( filename, "r" ) ) )
747  {
748  sinfo_msg_error("cannot open %s", filename) ;
749  return NULL ;
750  }
751 
752  /* allocate memory */
753 
754  if (NULL == ( parameter = (float*) cpl_calloc (ESTIMATE, sizeof(float)) ) )
755  {
756  sinfo_msg_error ("cannot allocate memory") ;
757  fclose (fp ) ;
758  return NULL ;
759  }
760 
761  i = 0 ;
762  while ( fscanf(fp, "%g\n", &parameter[i]) != EOF )
763  {
764  i++ ;
765  }
766  *n = i ;
767 
768  fclose (fp ) ;
769 
770  return parameter ;
771 }
772 
773 
796 double *
797 sinfo_new_curvature_of_spectrum( cpl_image * ns_image,
798  int order,
799  int box_length,
800  int left_pos,
801  int right_pos,
802  float fwhm,
803  float minDiff )
804 {
805  int i=0;
806  int k=0;
807  int row=0;
808  int col=0;
809  int counter=0;
810  int iters=0;
811  int xdim=0;
812  int ndat=0;
813  int its=0;
814  int numpar=0;
815  float maxval=0 ;
816  float tol=0;
817  float lab=0;
818 
819  float* col_value=NULL ;
820  float* column_value=NULL ;
821  pixelvalue* col_position=NULL ;
822  int* column_position=NULL ;
823  float* x_position=NULL ;
824 
825  int col_median=0;
826  float * xdat=NULL;
827  float * wdat=NULL;
828  int * mpar=NULL;
829  Vector * line=NULL;
830  FitParams ** dec_par=NULL ;
831  FitParams * par=NULL ;
832  int position=0 ;
833  int ndata=0 ;
834  int bad_ind=0 ;
835  dpoint * list=NULL ;
836  double * coeffs=NULL ;
837  double offset=0 ;
838  int lx=0;
839  int ly=0;
840  float* pdata=NULL;
841 
842  if ( ns_image == NULL )
843  {
844  sinfo_msg_error("sorry, no image given") ;
845  return NULL ;
846  }
847  lx=cpl_image_get_size_x(ns_image);
848  ly=cpl_image_get_size_y(ns_image);
849 
850  if ( box_length <= 1 || box_length >= right_pos - left_pos )
851  {
852  sinfo_msg_error("wrong box length given") ;
853  return NULL ;
854  }
855  if ( fwhm < 1. || fwhm > 10. )
856  {
857  sinfo_msg_error("wrong full width at half maximum given") ;
858  return NULL ;
859  }
860  if ( left_pos < 0 || right_pos <= left_pos || right_pos > lx )
861  {
862  sinfo_msg_error("wrong left and right positions") ;
863  return NULL ;
864  }
865  if ( minDiff < 1. )
866  {
867  sinfo_msg_error("wrong amplitude threshold given!") ;
868  return NULL ;
869  }
870 
871 
872 
873  col_value=cpl_calloc(ly,sizeof(float)) ;
874  column_value=cpl_calloc(ly,sizeof(float)) ;
875  col_position=(pixelvalue*)cpl_calloc(ly,sizeof(pixelvalue)) ;
876  column_position=cpl_calloc(ly,sizeof(int)) ;
877  x_position=cpl_calloc(ly,sizeof(float)) ;
878 
879  /* go through the image rows */
880  for ( row = 0 ; row < ly ; row++ )
881  {
882  col_value[row] = -FLT_MAX ;
883  col_position[row] = -1. ;
884  /* find the maximum value in each row and store the found column */
885  for ( col = left_pos ; col < right_pos ; col++ )
886  {
887  if ( pdata[col+row*lx] > col_value[row] )
888  {
889  col_value[row] = pdata[col+row*lx] ;
890  col_position[row] = (pixelvalue)col ;
891  }
892  }
893  }
894 
895  /* now determine the sinfo_new_median of the found columns to be sure
896  to have the brightest spectrum */
897  col_median = (int)sinfo_new_median(col_position, right_pos - left_pos) ;
898 
899  /* now find the peaks around col_median over the whole spectral range */
900  for ( row = 0 ; row < ly ; row++ )
901  {
902  x_position[row] = 0. ;
903  column_value[row] = -FLT_MAX ;
904  column_position[row] = -1 ;
905  for ( col = col_median - box_length ;
906  col <= col_median + box_length ; col++ )
907  {
908  if ( pdata[col+row*lx] > column_value[row] )
909  {
910  column_value[row] = pdata[col+row*lx] ;
911  column_position[row] = col ;
912  }
913  }
914 
915  /* allocate memory for the array where the line is fitted in */
916  if ( NULL == (line = sinfo_new_vector (2*box_length + 1)) )
917  {
918  sinfo_msg_error ("cannot allocate new Vector in row: %d", row) ;
919  return NULL ;
920  }
921 
922  /* allocate memory */
923  xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
924  wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
925  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
926  dec_par = sinfo_new_fit_params(1) ;
927  par = dec_par[0];
928 
929  counter = 0 ;
930  bad_ind = 0 ;
931  /* store the values to fit in a Vector object */
932  for ( col = column_position[row] - box_length ;
933  col <= column_position[row] + box_length ; col++ )
934  {
935  if ( col < 0 || col >= lx )
936  {
937  sinfo_msg_error ("wrong spectrum position or box_length "
938  "given in row: %d", row) ;
939  cpl_free (xdat) ;
940  cpl_free (wdat) ;
941  cpl_free (mpar) ;
942  sinfo_new_destroy_fit_params(&dec_par) ;
943  sinfo_new_destroy_vector( line ) ;
944  return NULL ;
945  }
946  else if ( isnan(pdata[col+row*lx]) )
947  {
948  bad_ind = 1 ;
949  }
950  else
951  {
952  line -> data[counter] = pdata[col + row*lx] ;
953  counter++ ;
954  }
955  }
956 
957  /* go to the next row if a bad pixel is inside the box */
958  if ( bad_ind == 1 )
959  {
960  sinfo_msg_warning ("sorry, bad pixel inside fitting box "
961  "in row: %d", row) ;
962  cpl_free (xdat) ;
963  cpl_free (wdat) ;
964  cpl_free (mpar) ;
965  sinfo_new_destroy_fit_params(&dec_par) ;
966  sinfo_new_destroy_vector( line ) ;
967  continue ;
968  }
969 
970  /*--------------------------------------------------------------------
971  * go through the line sinfo_vector
972  * determine the maximum pixel value in the line sinfo_vector
973  */
974  maxval = -FLT_MAX ;
975  position = -INT32_MAX ;
976  for ( i = 0 ; i < counter ; i++ )
977  {
978  xdat[i] = i ;
979  wdat[i] = 1.0 ;
980  if ( line -> data[i] >= maxval )
981  {
982  maxval = line -> data[i] ;
983  position = i ;
984  }
985  }
986 
987  /* set initial values for the fitting routine */
988  xdim = XDIM ;
989  ndat = line -> n_elements ;
990  numpar = MAXPAR ;
991  tol = TOL ;
992  lab = LAB ;
993  its = ITS ;
994  (*par).fit_par[1] = fwhm ;
995  (*par).fit_par[2] = (float) position ;
996  (*par).fit_par[3] = (float) (line -> data[0] +
997  line -> data[line->n_elements - 1]) / 2.0;
998 
999  (*par).fit_par[0] = maxval - ((*par).fit_par[3]) ;
1000  /* exclude negative peaks and low signal cases */
1001  if ( (*par).fit_par[0] < minDiff )
1002  {
1003  sinfo_msg_warning ("sorry, negative peak or signal of line "
1004  "too low to fit in row: %d", row) ;
1005  cpl_free (xdat) ;
1006  cpl_free (wdat) ;
1007  cpl_free (mpar) ;
1008  sinfo_new_destroy_fit_params(&dec_par) ;
1009  sinfo_new_destroy_vector( line ) ;
1010  continue ;
1011  }
1012 
1013  for ( k = 0 ; k < MAXPAR ; k++ )
1014  {
1015  (*par).derv_par[k] = 0.0 ;
1016  mpar[k] = 1 ;
1017  }
1018 
1019  /* finally, do the least square fit using a sinfo_gaussian */
1020  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim,
1021  line -> data, wdat,
1022  &ndat, (*par).fit_par,
1023  (*par).derv_par, mpar,
1024  &numpar, &tol, &its, &lab )) )
1025  {
1026  sinfo_msg_warning ("least squares fit failed in row: "
1027  "%d, error no.: %d", row, iters) ;
1028  cpl_free (xdat) ;
1029  cpl_free (wdat) ;
1030  cpl_free (mpar) ;
1031  sinfo_new_destroy_fit_params(&dec_par) ;
1032  sinfo_new_destroy_vector( line ) ;
1033  continue ;
1034  }
1035 
1036  /* check for negative fit results */
1037  if ( (*par).fit_par[0] <= 0. || (*par).fit_par[1] <= 1. ||
1038  (*par).fit_par[2] <= 0. )
1039  {
1040  sinfo_msg_warning ("negative parameters as fit result, "
1041  "not used! in row: %d", row) ;
1042  cpl_free (xdat) ;
1043  cpl_free (wdat) ;
1044  cpl_free (mpar) ;
1045  sinfo_new_destroy_fit_params(&dec_par) ;
1046  sinfo_new_destroy_vector( line ) ;
1047  continue ;
1048  }
1049 
1050  /* correct the fitted position for the given row of the line
1051  in image coordinates */
1052  x_position[row] = (float) (column_position[row] - box_length) +
1053  (*par).fit_par[2] ;
1054  printf("%d %f %f\n",row, (*par).fit_par[1], x_position[row] ) ;
1055 
1056  /* free memory */
1057  sinfo_new_destroy_fit_params(&dec_par) ;
1058  sinfo_new_destroy_vector ( line ) ;
1059  cpl_free ( xdat ) ;
1060  cpl_free ( wdat ) ;
1061  cpl_free ( mpar ) ;
1062  }
1063  /* now allocate memory for the data to fit */
1064  if ( NULL == ( list = (dpoint*) cpl_calloc (ly, sizeof (dpoint)) ) )
1065  {
1066  sinfo_msg_error("could not allocate memory!") ;
1067  return NULL ;
1068  }
1069 
1070  /* ------------------------------------------------------------------------
1071  * now that we have a sub-pixel resolved list of spectral maxima stored
1072  * in x_position[row] We can fit a flux weighted straight line to the
1073  * positions to determine the spectral column shifts.
1074  */
1075  offset = (double) ly/2. ;
1076  ndata = 0 ;
1077  for ( row = 0 ; row < ly ; row++ )
1078  {
1079  if ( x_position[row] == 0. )
1080  {
1081  continue ;
1082  }
1083  else
1084  {
1085  list[ndata].y = (double)x_position[row] ;
1086  list[ndata].x = (double)row - offset ;
1087  ndata++ ;
1088  }
1089  }
1090 
1091 
1092  if ( NULL == (coeffs = sinfo_fit_1d_poly(order, list, ndata, NULL)) )
1093  {
1094  sinfo_msg_error("eclipse function sinfo_fit_1d_poly() did not work!") ;
1095  return NULL ;
1096  }
1097  cpl_free ( list ) ;
1098 
1099 
1100 
1101  cpl_free(col_value) ;
1102  cpl_free(column_value) ;
1103  cpl_free(col_position) ;
1104  cpl_free(column_position) ;
1105  cpl_free(x_position) ;
1106 
1107  return coeffs ;
1108 }
1109 
1118 cpl_image *
1119 sinfo_new_image_warp_fits( cpl_image * image,
1120  char * kernel_type,
1121  char * poly_table )
1122 {
1123  cpl_image * warped=NULL;
1124  /* Following are for polynomial transforms */
1125  cpl_polynomial * poly_u=NULL; /* polynomial definition */
1126  cpl_polynomial * poly_v=NULL; /* polynomial definition */
1127  cpl_table* poly_tbl=NULL;
1128  cpl_vector * profile=NULL ;
1129  cpl_size local_pow[2];
1130  int i=0;
1131 
1132  /*fscanf(poly_in,"%s",poly_string);*/
1133  /* sinfo_msg("%s",poly_string); */
1134 
1135  poly_u = cpl_polynomial_new(2);
1136  if (poly_u == NULL) {
1137  sinfo_msg_error("cannot read 2D poly from arc table") ;
1138  return NULL ;
1139  }
1140 
1141  if (poly_u != NULL) {
1142  sinfo_msg_debug("Get the arc distortion from the file %s",
1143  poly_table);
1144  if(sinfo_is_fits_file(poly_table) != 1) {
1145  sinfo_msg_error("Input file %s is not FITS",poly_table);
1146  return NULL;
1147  }
1148 
1149  if(NULL==(poly_tbl = cpl_table_load(poly_table,1,0))) {
1150  sinfo_msg_error("cannot load the arc table") ;
1151  cpl_polynomial_delete(poly_u) ;
1152  return NULL ;
1153  }
1154 
1155  for (i=0 ; i<cpl_table_get_nrow(poly_tbl) ; i++) {
1156  local_pow[0] = cpl_table_get_int(poly_tbl, "degx", i, NULL) ;
1157  local_pow[1] = cpl_table_get_int(poly_tbl, "degy", i, NULL) ;
1158  cpl_polynomial_set_coeff(poly_u, local_pow,
1159  cpl_table_get_double(poly_tbl, "coeff", i, NULL)) ;
1160  }
1161 
1162  cpl_table_delete(poly_tbl) ;
1163  } else {
1164  sinfo_msg("Use the ID polynomial for the arc dist") ;
1165  local_pow[0] = 1 ;
1166  local_pow[1] = 0 ;
1167  cpl_polynomial_set_coeff(poly_u, local_pow, 1.0) ;
1168  }
1169 
1170  poly_v=cpl_polynomial_new(2);
1171  local_pow[0]=0;
1172  local_pow[1]=1;
1173 
1174  cpl_polynomial_set_coeff(poly_v,local_pow,1.0);
1175  profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES) ;
1176  cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_TANH,
1177  CPL_KERNEL_DEF_WIDTH) ;
1178  warped=sinfo_new_warp_image_generic(image,kernel_type,poly_u,poly_v);
1179  /* YVES WAY
1180  warped = cpl_image_new(cpl_image_get_size_x(image),
1181  cpl_image_get_size_y(image),
1182  CPL_TYPE_FLOAT);
1183 
1184  if (cpl_image_warp_polynomial(warped, image, poly_u, poly_v,
1185  profile,CPL_KERNEL_DEF_WIDTH,
1186  profile,CPL_KERNEL_DEF_WIDTH)
1187  != CPL_ERROR_NONE) {
1188  sinfo_msg_error("cannot correct the distortion") ;
1189  cpl_image_delete(warped) ;
1190  cpl_polynomial_delete(poly_u) ;
1191  cpl_polynomial_delete(poly_v) ;
1192  cpl_vector_delete(profile) ;
1193  return NULL;
1194  }
1195  */
1196 
1197  cpl_vector_delete(profile) ;
1198  if (poly_u!=NULL) cpl_polynomial_delete(poly_u);
1199  if (poly_v!=NULL) cpl_polynomial_delete(poly_v);
1200 
1201  return warped;
1202 }
1203