SINFONI Pipeline Reference Manual  2.5.2
sinfo_wave_calibration.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 13/07/00 created
27  */
28 
29 /************************************************************************
30  * NAME
31  * sinfo_wave_calibration.c -
32  * routines needed for wavelength calibration
33  *
34  * SYNOPSIS
35  *
36  * 1) FitParams ** sinfo_new_fit_params( int n_params )
37  *
38  * 2) void sinfo_new_destroy_fit_params ( FitParams ** params )
39  *
40  * 3) void sinfo_new_dump_fit_params_to_ascii(FitParams ** params,
41  const char * filename )
42  *
43  * 4) void sinfo_new_dump_ascii_to_fit_params ( FitParams ** params,
44  char * filename )
45  *
46  * 5) int sinfo_new_find_lines(cpl_image * lineImage,
47  * float * wave_position,
48  * float * wave_intensity,
49  * int n_lines,
50  * int ** row_clean,
51  * float ** wavelength_clean,
52  * float beginWave,
53  * float dispersion,
54  * float mindiff,
55  * int halfWidth,
56  * int * n_found_lines,
57  * float sigma,
58  * int * sum_lines )
59  *
60  * 6) int sinfo_new_read_list( char * listname,
61  float * lineCenter,
62  float * lineIntensity )
63  *
64  *
65  * 7) int sinfo_new_line_fit ( cpl_image * mergedImage,
66  * FitParams * par,
67  * float fwhm,
68  * int lineInd,
69  * int column,
70  * int halfWidth,
71  * int lineRow,
72  * float min_amplitude )
73  *
74  * 8) int sinfo_new_fit_lines ( cpl_image * line_image,
75  * FitParams ** allParams,
76  * float fwhm,
77  * int * n_lines,
78  * int ** row,
79  * float ** wavelength,
80  * int width,
81  * float min_amplitude )
82  *
83  * 9) float sinfo_new_polyfit( FitParams ** par,
84  * int column,
85  * int n_lines,
86  * int n_rows,
87  * float dispersion,
88  * float max_residual,
89  * float * acoefs,
90  * float * dacoefs,
91  * int * n_reject,
92  * int n_fitcoefs )
93  *
94  * 10) float sinfo_new_coefs_cross_fit ( int n_columns,
95  * float * acoefs,
96  * float * dacoefs,
97  * float * bcoefs,
98  * int n_fitcoefs,
99  * float sigma_factor )
100  *
101  *
102  * 11) cpl_image * sinfo_new_wave_map( cpl_image * lineImage,
103  * float ** bcoefs,
104  * int n_a_fitcoefs,
105  * int n_b_fitcoefs,
106  * float * wavelength,
107  * float * intensity,
108  * int n_lines,
109  * int magFactor,
110  * int * bad_column_mask,
111  * int n_bad_columns )
112  *
113  * 12) int sinfo_new_wavelength_calibration( cpl_image * image,
114  * FitParams ** par ,
115  * float ** bcoefs,
116  * float * wave,
117  * int n_lines,
118  * int ** row_clean,
119  * float ** wavelength_clean,
120  * int * n_found_lines,
121  * float dispersion,
122  * int halfWidth,
123  * float minAmplitude,
124  * float max_residual,
125  * float fwhm,
126  * int n_a_fitcoefs,
127  * int n_b_fitcoefs,
128  * float sigmaFactor )
129  *
130  * 13) cpl_image * sinfo_new_convolve_image_by_gauss( cpl_image * lineImage,
131  * int hw )
132  *
133  * 14) cpl_image * sinfo_new_defined_resampling( cpl_image * image,
134  * cpl_image * calimage,
135  * int n_params,
136  * int n_rows,
137  * double * dispersion,
138  * float * minval,
139  * float * maxval,
140  * double * centralLambda,
141  * int * centralpix )
142  *
143  * DESCRIPTION
144  *
145  * 1) allocates memory for a new sinfo_vector of
146  * FitParams data structures
147  * 2) frees memory of a sinfo_vector of FitParams data structures
148  * 3) dumps the fit parameters to an ASCII file
149  * 4) dumps ASCII information to an allocated FitParams data structure
150  * 5) determines the pixel shift between the line list
151  * and the real image by using the beginning wavelength
152  * on the detector and the dispersion estimate.
153  * 6) reads the line data of the calibration lamps
154  * 7) fits a sinfo_gaussian to a 1-dimensional slice of an image,
155  * this routine uses the routine sinfo_new_lsqfit_c as a non-linear
156  * least square fit method (Levenberg-Marquardt).
157  * 8) calculates and stores the fit parameters of the neon
158  * emission lines of a neon frame by using the sinfo_linefit
159  * routine.
160  * 9) fits a second order polynom
161  * lambda[i] = a1 + a2*pos[i] + a3*pos[i]^2
162  * to determine the connection between the listed wave-
163  * length values and the gauss-fitted positions for each
164  * image column using the singular value decomposition
165  * method.
166  * 10) Fits the each single parameter of the three fit parameters
167  * acoefs from sinfo_polyfit through the image columns
168  * 11) this routine determines a wavelength calibration map
169  * frame associating a wavelength value to each pixel
170  * by using the fit coefficients determined before.
171  * 12) this routine takes an image from a calibration
172  * emission lamp and delivers the fit coefficients of
173  * a polynomial fit across the columns
174  * of the coefficients of the polynomial line position
175  * fits as output. Furthermore it delivers an array of the fit parameters
176  * as output. This routine expects Nyquist sampled spectra
177  * (either an interleaved image or an image convolved with an
178  * appropriate function in spectral direction)
179  * 13) convolves an emission line image with a sinfo_gaussian
180  * with user given integer half width by using the eclipse
181  * routine sinfo_function1d_filter_lowpass().
182  * 14) Given a source image and a corresponding wavelength
183  * calibration file this routine produces an image
184  * in which elements in a given row are associated
185  * with a single wavelength. It thus corrects for
186  * the wavelength shifts between adjacent elements
187  * in the rows of the input image. The output image
188  * is larger in the wavelength domain than the input
189  * image with pixels in each column corresponding to
190  * undefined (blank, ZERO) values. The distribution
191  * of these undefined values varies from column to
192  * column. The input image is resampled at discrete
193  * wavelength intervals using a polynomial interpolation
194  * routine.
195  * The wavelength intervals (dispersion) and the
196  * central wavelength are defined and stable for each
197  * used grating. Thus, each row has a defined wavelength
198  * for each grating. Only the number of rows can be
199  * changed by the user.
200  *
201  * FILES
202  *
203  * ENVIRONMENT
204  *
205  * RETURN VALUES
206  *
207  * CAUTIONS
208  *
209  * EXAMPLES
210  *
211  * SEE ALSO
212  *
213  * BUGS
214  *
215  *------------------------------------------------------------------------
216  */
217 
218 #ifdef HAVE_CONFIG_H
219 # include <config.h>
220 #endif
221 #include "sinfo_vltPort.h"
222 
223 /*
224  * System Headers
225  */
226 
227 /*
228  * Local Headers
229  */
230 
231 #include "sinfo_function_1d.h"
232 #include "sinfo_wave_calibration.h"
233 #include "sinfo_solve_poly_root.h"
234 #include "sinfo_recipes.h"
235 #include "sinfo_globals.h"
236 #include "sinfo_svd.h"
237 #include "sinfo_msg.h"
238 
239 
255 FitParams ** sinfo_new_fit_params( int n_params )
256 {
257  FitParams ** new_params =NULL;
258  FitParams * temp_params =NULL;
259  float * temp_fit_mem =NULL;
260  float * temp_derv_mem=NULL;
261  int i ;
262 
263 
264  if ( n_params <= 0 )
265  {
266  sinfo_msg_error (" wrong number of lines to fit\n") ;
267  return NULL ;
268  }
269 
270  if (NULL==(new_params=(FitParams **) cpl_calloc ( n_params ,
271  sizeof (FitParams*) ) ) )
272  {
273  sinfo_msg_error (" could not allocate memory\n") ;
274  return NULL ;
275  }
276  if ( NULL == (temp_params = cpl_calloc ( n_params , sizeof (FitParams) ) ) )
277  {
278  sinfo_msg_error (" could not allocate memory\n") ;
279  return NULL ;
280  }
281  if ( NULL == (temp_fit_mem = (float *) cpl_calloc( n_params*MAXPAR,
282  sizeof (float) ) ) )
283  {
284  sinfo_msg_error (" could not allocate memory\n") ;
285  return NULL ;
286  }
287 
288 
289  if ( NULL == (temp_derv_mem =
290  (float *) cpl_calloc( n_params*MAXPAR, sizeof (float) ) ) )
291  {
292  sinfo_msg_error (" could not allocate memory\n") ;
293  return NULL ;
294  }
295 
296  for ( i = 0 ; i < n_params ; i ++ )
297  {
298  new_params[i] = temp_params+i;
299  new_params[i] -> fit_par = temp_fit_mem+i*MAXPAR;
300  new_params[i] -> derv_par = temp_derv_mem+i*MAXPAR;
301  new_params[i] -> column = 0 ;
302  new_params[i] -> line = 0 ;
303  new_params[i] -> wavelength = 0. ;
304  new_params[i] -> n_params = n_params ;
305  }
306 
307  return new_params ;
308 }
309 
317 void sinfo_new_destroy_fit_params ( FitParams *** params )
318 {
319 
320  if ( *params == NULL )
321  {
322  return ;
323  }
324 
325  cpl_free ( (*params)[0] -> fit_par ) ;
326  (*params)[0] -> fit_par=NULL;
327  cpl_free ( (*params)[0] -> derv_par ) ;
328  (*params)[0] -> derv_par=NULL;
329  cpl_free ( (*params)[0] ) ;
330  (*params)[0]=NULL;
331  cpl_free ( (*params) ) ;
332  (*params)=NULL;
333 }
334 
343 void sinfo_new_dump_fit_params_to_ascii ( FitParams ** params, const char * filename )
344 {
345  FILE * fp ;
346  int i ;
347 
348  if ( NULL == params )
349  {
350  sinfo_msg_error (" no fit parameters available!\n") ;
351  return ;
352  }
353 
354  if ( NULL == filename )
355  {
356  sinfo_msg_error (" no filename available!\n") ;
357  return ;
358  }
359 
360  if ( NULL == (fp = fopen ( filename, "w" ) ) )
361  {
362  sinfo_msg_error(" cannot open %s\n", filename) ;
363  return ;
364  }
365 
366  for ( i = 0 ; i < params[0] -> n_params ; i++ )
367  {
368  fprintf(fp, "%d %d %d %f %f %f %f %f %f %f %f %f\n",
369  params[i]->n_params,
370  params[i]->column,
371  params[i]->line,
372  params[i]->wavelength,
373  params[i]->fit_par[0],
374  params[i]->fit_par[1],
375  params[i]->fit_par[2],
376  params[i]->fit_par[3],
377  params[i]->derv_par[0],
378  params[i]->derv_par[1],
379  params[i]->derv_par[2],
380  params[i]->derv_par[3] ) ;
381  }
382  fclose(fp) ;
383 }
384 
393 void
394 sinfo_new_dump_ascii_to_fit_params ( FitParams ** params, char * filename )
395 {
396  FILE * fp ;
397  int i ;
398 
399  if ( NULL == params )
400  {
401  sinfo_msg_error (" no fit parameters available!\n") ;
402  return ;
403  }
404 
405  if ( NULL == filename )
406  {
407  sinfo_msg_error (" no filename available!\n") ;
408  return ;
409  }
410 
411  if ( NULL == (fp = fopen ( filename, "r" ) ) )
412  {
413  sinfo_msg_error(" cannot open %s\n", filename) ;
414  return ;
415  }
416 
417  for ( i = 0 ; i < params[0]->n_params ; i++ )
418  {
419  fscanf(fp, "%d %d %d %f %f %f %f %f %f %f %f %f\n",
420  &params[i]->n_params,
421  &params[i]->column,
422  &params[i]->line,
423  &params[i]->wavelength,
424  &params[i]->fit_par[0],
425  &params[i]->fit_par[1],
426  &params[i]->fit_par[2],
427  &params[i]->fit_par[3],
428  &params[i]->derv_par[0],
429  &params[i]->derv_par[1],
430  &params[i]->derv_par[2],
431  &params[i]->derv_par[3] ) ;
432  }
433  fclose(fp) ;
434 }
435 
474 int sinfo_new_find_lines(cpl_image * lineImage,
475  float * wave_position,
476  float * wave_intensity,
477  int n_lines,
478  int ** row_clean,
479  float ** wavelength_clean,
480  float beginWave,
481  float dispersion1,
482  float dispersion2,
483  float mindiff,
484  int halfWidth,
485  int * n_found_lines,
486  float sigma,
487  int * sum_lines )
488 {
489  int ** row ;
490  float ** wavelength ;
491  float buf1, buf2 ;
492  float meanval ;
493  float colmedian ;
494  float * column, * tempcol ;
495  float * lines ;
496  float * conv_lines ;
497  float * wave_buffer ;
498  float * wave_mem;
499  int * dummy_row ;
500  int i, j, k, m ;
501  int position ;
502  int gmax, gmin ;
503  int col ;
504  int * row_mem;
505  float sum ;
506  float angst ;
507 
508  int lx=0;
509  int ly=0;
510  float* pdata=NULL;
511 
512  if ( NULL == lineImage )
513  {
514  sinfo_msg_error (" no image given\n") ;
515  return -1 ;
516  }
517 
518  lx=cpl_image_get_size_x(lineImage);
519  ly=cpl_image_get_size_y(lineImage);
520  pdata=cpl_image_get_data_float(lineImage);
521 
522  if ( n_lines <= 0 || NULL == wave_position )
523  {
524  sinfo_msg_error(" no line list given\n") ;
525  return -1 ;
526  }
527  if ( NULL == wave_intensity )
528  {
529  sinfo_msg_error(" no intensity list given\n") ;
530  return -1 ;
531  }
532 
533  if ( dispersion1 == 0. )
534  {
535  sinfo_msg_error(" wrong dispersion given\n") ;
536  return -1 ;
537  }
538 
539  if ( row_clean == NULL )
540  {
541  sinfo_msg_error(" row_clean array is not allocated\n") ;
542  return -1 ;
543  }
544 
545  if ( wavelength_clean == NULL )
546  {
547  sinfo_msg_error(" wavelength_clean array is not allocated\n") ;
548  return -1 ;
549  }
550 
551  if ( beginWave <= 0. )
552  {
553  sinfo_msg_error (" impossible beginWave given\n") ;
554  return -1 ;
555  }
556  if ( mindiff < -100. )
557  {
558  sinfo_msg_error (" wrong mindiff value\n") ;
559  return -1 ;
560  }
561 
562  if ( halfWidth <= 0 )
563  {
564  sinfo_msg_error(" wrong half width of fit box given\n") ;
565  return -1 ;
566  }
567 
568  if ( n_found_lines == NULL )
569  {
570  sinfo_msg_error(" n_found_lines not allocated\n") ;
571  return -1 ;
572  }
573 
574  if ( sigma <= 0. || sigma >= ly / 2)
575  {
576  sinfo_msg_error(" wrong sigma given\n") ;
577  return -1 ;
578  }
579 
580  /* allocate memory */
581  row = (int**) cpl_calloc( lx, sizeof(int*)) ;
582  wavelength = (float**) cpl_calloc( lx, sizeof(float*)) ;
583  row_mem = cpl_calloc( n_lines*lx, sizeof(int) ) ;
584  wave_mem = cpl_calloc( n_lines*lx, sizeof(float) ) ;
585  for ( i = 0 ; i <lx ; i++ )
586  {
587  row[i] = row_mem + i*n_lines;
588  wavelength[i] = wave_mem + i*n_lines;
589  }
590 
591  /* find if the wavelength is given in microns, nanometers or Angstroem */
592  if ( wave_position[0] > 10000. )
593  {
594  /* Angstroem */
595  angst = 10000. ;
596  }
597  else if ( wave_position[0] > 1000. && wave_position[0] < 10000. )
598  {
599  /* nanometers */
600  angst = 1000. ;
601  }
602  else
603  {
604  /* microns */
605  angst = 1. ;
606  }
607 
608  /*----------------------------------------------------------------------
609  * compute the mean and median intensity value in the given
610  column and determine if there is enough intensity in the column to
611  do the correlation
612  */
613  tempcol = (float*) cpl_calloc(ly, sizeof(float)) ;
614  *sum_lines = 0 ;
615  buf1 = 0. ;
616  buf2 = 0. ;
617  /* allocate memory */
618  column = (float*) cpl_calloc(ly, sizeof (float)) ;
619  lines = (float*) cpl_calloc(ly, sizeof (float)) ;
620  conv_lines = (float*) cpl_calloc(ly, sizeof (float)) ;
621  wave_buffer = (float*) cpl_calloc(ly, sizeof (float)) ;
622  dummy_row = (int*) cpl_calloc(n_lines, sizeof(int)) ;
623 
624  for ( col = 0 ; col < lx ; col++ )
625  {
626  n_found_lines[col] = 0 ;
627  sum = 0. ;
628  for ( i = 0 ; i < ly ; i++ )
629  {
630  if (isnan(pdata[col + i*lx]) )
631  {
632  tempcol[i] = 0. ;
633  continue ;
634  }
635 
636  sum = sum + pdata[col + i*lx] ;
637  tempcol[i] = pdata[col + i*lx];
638  }
639  meanval = sum / ly ;
640  /* lets assume the sinfo_new_median is the background */
641  colmedian = sinfo_new_median ( tempcol, ly);
642 
643  if ( meanval - colmedian < mindiff )
644  {
645  sinfo_msg_warning(" sorry, not enough intensity "
646  "(mean: %f, diff: %f) in image column: "
647  "%d to correlate emission lines\n",
648  meanval, meanval - colmedian,col) ;
649  continue ;
650  }
651 
652  for ( i = 0 ; i < ly ; i++ )
653  {
654  conv_lines[i]=0;
655  wave_buffer[i]=0;
656  }
657  for ( i = 0 ; i < n_lines ; i++ )
658  {
659  dummy_row[i] = 0;
660  }
661 
662  /* go through the column with index col */
663  for ( i = 0 ; i < ly ; i++ )
664  {
665  if ( isnan(pdata[col+i*lx]) )
666  {
667  column[i] = 0. ;
668  }
669  else
670  {
671  column[i] = pdata[col + i*lx] ;
672  }
673 
674  /* determine the line position on the pixels */
675  /*lines[i] = (dispersion * (float) i + beginWave) * angst ;*/
676  lines[i] = (dispersion1 * (float) (i-ly/2) +
677  dispersion2 * (float) (i-ly/2) *
678  (float) (i-ly/2) +
679  beginWave) * angst ;
680 
681  /* ---------------------------------------------------------------
682  * find the nearest line position for each wavelength in the list
683  * and set this position to the given line intensity as weight
684  */
685  for ( j = 0 ; j < n_lines ; j ++ )
686  {
687  buf1 = 0. ;
688  buf2 = 0. ;
689  if ( (wave_position[j] >= (lines[i] -
690  fabs(dispersion1)/2.*angst)) &&
691  (wave_position[j] <= (lines[i] +
692  fabs(dispersion1)/2.*angst)) )
693  {
694  buf1 = wave_intensity[j] ; /* set the given line intensity
695  as weight */
696  buf2 = wave_position[j] ;
697  break ;
698  }
699  }
700  lines[i] = buf1 ;
701  wave_buffer[i] = buf2 ; /* get the wavelength associated
702  with the corresponding
703  found emission line */
704 
705  /* convolve the artificial spectrum by a Gaussian
706  with given sigma value */
707  if ( lines[i] != 0. )
708  {
709  /* consider only +- 2 sigma */
710  gmin = sinfo_new_nint((float) i - 2. * sigma) ;
711  gmax = sinfo_new_nint((float) i + 2. * sigma) ;
712 
713  /* be aware of image margins */
714  if ( gmin < 0 )
715  {
716  gmin = 0 ;
717  }
718  if ( gmax >= ly )
719  {
720  gmax = ly - 1 ;
721  }
722  for ( j = gmin ; j <= gmax ; j++ )
723  {
724  conv_lines[j] +=
725  lines[i] * exp( (double)( -0.5*((j - i)*(j - i)))/
726  (double) (sigma*sigma) ) ;
727  }
728  }
729  }
730 
731  /* do the cross sinfo_new_correlitioation */
732  position = INT32_MAX ;
733  position = sinfo_new_correlation(column+5, conv_lines+5, ly-10 ) ;
734  if ( abs (position) > ly / 4 )
735  {
736  sinfo_msg_warning(" sorry, shift of artificial data relative to"
737  " image (%d) seems to be too high in column: %d",
738  position, col) ;
739  continue ;
740  }
741 
742  //AMO we initialize this to -999 and later check that it is not
743  //-999 to prevent an invalid read out due to the fact that not
744  //all elements of row are filled by the the loop below
745  for ( j = 0 ; j < n_lines ; j ++ ) {
746  row[col][j] = -999;
747  }
748 
749  //The following loop does not fill all elements
750  j = 0 ;
751  for ( i = 0 ; i < ly ; i ++ )
752  {
753  if ( lines[i] != 0.0 )
754  {
755  if ( (i - position) >= 0 && (i - position) < ly )
756  {
757  row[col][j] = i - position ;
758  /* get the wavelength corresponding to
759  found line row index */
760  wavelength[col][j] = wave_buffer[i] / angst ;
761  j++ ;
762  }
763  }
764  }
765 
766 
767  /* ------------------------------------------------------------------
768  * determine the row_clean array, that means, take only the row
769  values if the distance between adjacent lines is large enough
770  for the fit
771  */
772  //sinfo_msg("lx=%d",lx);
773  for ( k = 1 ; k <= j && k<(lx-1); k ++ )
774  {
775  if (dummy_row[k-1] != -1)
776  {
777  dummy_row[k-1] = row[col][k-1] ;
778  }
779  if ( (row[col][k] - row[col][k-1]) <= 2*halfWidth )
780  {
781  dummy_row[k-1] = -1 ;
782  if (k<n_lines) {
783  dummy_row[k] = -1 ;
784  }
785  }
786  /* the following gives invalid read size 4: check that k+1<lx */
787 
788  //sinfo_msg("col=%d k=%d row1=%d row2=%d",
789  // col,k,row[col][k+1],row[col][k]);
790  if ( (row[col][j] != -999) &&
791  (row[col][k+1] - row[col][k]) <= 2*halfWidth)
792  {
793  if (k<n_lines) {
794  dummy_row[k] = -1 ;
795  }
796  if (k+1<n_lines) {
797  dummy_row[k+1] = -1 ;
798  }
799  }
800  }
801 
802  m = 0 ;
803  for ( k = 0 ; k < j ; k ++ )
804  {
805  if ( dummy_row[k] != -1 && dummy_row[k] != 0 )
806  {
807  row_clean[col][m] = dummy_row[k] ;
808  wavelength_clean[col][m] = wavelength[col][k] ;
809  m ++ ;
810  }
811  }
812 
813  n_found_lines[col] = m ;
814 
815  *sum_lines += n_found_lines[col] ;
816  }
817  cpl_free (column) ;
818  cpl_free (lines) ;
819  cpl_free (conv_lines) ;
820  cpl_free (dummy_row) ;
821  cpl_free (wave_buffer) ;
822  cpl_free (row_mem) ;
823  cpl_free (wave_mem) ;
824  cpl_free (tempcol) ;
825  cpl_free (row) ;
826  cpl_free (wavelength) ;
827 
828  return 0 ;
829 }
830 
840 int
841 sinfo_new_read_list( char * listname,
842  float * lineCenter,
843  float * lineIntensity )
844 {
845  FILE * fp ;
846  int i, n_lines ;
847 
848  if ( NULL == lineCenter )
849  {
850  sinfo_msg_error(" lineCenter array is not allocated\n") ;
851  return -1 ;
852  }
853 
854  if ( NULL == lineIntensity )
855  {
856  sinfo_msg_error(" lineIntensity array is not allocated\n") ;
857  return -1 ;
858  }
859 
860  if ( NULL == (fp = fopen ( listname, "r" ) ) )
861  {
862  sinfo_msg_error(" cannot open %s\n", listname) ;
863  return -1 ;
864  }
865 
866  i = 0 ;
867  while ( fscanf( fp, "%f %f", &lineCenter[i], &lineIntensity[i] ) != EOF )
868  {
869  i ++ ;
870  }
871  n_lines = i ;
872  fclose(fp) ;
873 
874  return n_lines ;
875 }
876 
877 
909 int sinfo_new_line_fit ( cpl_image * mergedImage,
910  FitParams * par,
911  float fwhm,
912  int lineInd,
913  int column,
914  int halfWidth,
915  int lineRow,
916  float min_amplitude,
917  Vector * line,
918  int * mpar,
919  float * xdat,
920  float * wdat )
921 {
922  int i, j ;
923  int iters, xdim, ndat ;
924  int numpar, its ;
925  int position ;
926  float maxval, tol, lab ;
927  int lx=0;
928  int ly=0;
929  float* pdata=NULL;
930 
931  if ( mergedImage == NULL )
932  {
933  sinfo_msg_error (" no image given as input\n") ;
934  return -8 ;
935  }
936  lx=cpl_image_get_size_x(mergedImage);
937  ly=cpl_image_get_size_y(mergedImage);
938  pdata=cpl_image_get_data_float(mergedImage);
939 
940 
941  if ( par == NULL )
942  {
943  sinfo_msg_error(" fit parameters not given\n") ;
944  return -9 ;
945  }
946  if ( column < 0 || column > lx )
947  {
948  sinfo_msg_error (" wrong column number\n") ;
949  return -10 ;
950  }
951  if ( halfWidth < 0 || halfWidth > ly )
952  {
953  sinfo_msg_error (" wrong width given\n") ;
954  return -11 ;
955  }
956  if ( lineRow < 0 || lineRow > ly )
957  {
958  sinfo_msg_error (" wrong number of row of the line given\n") ;
959  return -12 ;
960  }
961  if ( min_amplitude < 1. )
962  {
963  sinfo_msg_error (" wrong minimum amplitude\n") ;
964  return -13 ;
965  }
966 
967  /* initialise the Vector */
968  for ( i = 0 ; i < line -> n_elements ; i++)
969  {
970  line->data[i] = 0;
971  }
972 
973  par -> column = column ;
974  par -> line = lineInd ;
975 
976  /* determine the values of the spectral sinfo_vector given as input */
977  /* go through the chosen column */
978 
979  j = 0 ;
980  for ( i = lineRow-halfWidth ; i <= lineRow+halfWidth ; i++ )
981  {
982  if ( i < 0 || i >= ly )
983  {
984  sinfo_msg_error (" wrong line position or width given\n") ;
985  return -15 ;
986  }
987  else
988  {
989  line -> data[j] = pdata[column + i*lx] ;
990  j ++ ;
991  }
992  }
993 
994  /*--------------------------------------------------------------------
995  * go through the spectral sinfo_vector
996  * determine the maximum pixel value in the spectral sinfo_vector
997  */
998  maxval = -FLT_MAX ;
999  position = -INT32_MAX ;
1000  for ( i = 0 ; i < line -> n_elements ; i++ )
1001  {
1002  xdat[i] = i ;
1003  wdat[i] = 1.0 ;
1004  if ( line -> data[i] >= maxval )
1005  {
1006  maxval = line -> data[i] ;
1007  position = i ;
1008  }
1009  }
1010 
1011  /* set initial values for the fitting routine */
1012  xdim = XDIM ;
1013  ndat = line -> n_elements ;
1014  numpar = MAXPAR ;
1015  tol = TOL ;
1016  lab = LAB ;
1017  its = ITS ;
1018  par -> fit_par[1] = fwhm ;
1019  par -> fit_par[2] = (float) position ;
1020  par -> fit_par[3] = (float) (line -> data[0] +
1021  line -> data[line->n_elements - 1]) / 2.0 ;
1022  par -> fit_par[0] = maxval - (par -> fit_par[3]) ;
1023 
1024  /* exclude low signal cases */
1025  if ( par->fit_par[0] < min_amplitude )
1026  {
1027  cpl_msg_debug ("sinfo_linefit:",
1028  " sorry, amplitude of line too low to fit: %f",
1029  par->fit_par[0] ) ;
1030  return -16 ;
1031  }
1032 
1033  for ( i = 0 ; i < MAXPAR ; i++ )
1034  {
1035  par -> derv_par[i] = 0.0 ;
1036  mpar[i] = 1 ;
1037  }
1038 
1039  /* finally, do the least square fit using a sinfo_gaussian */
1040  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim,
1041  line -> data, wdat,
1042  &ndat, par -> fit_par,
1043  par -> derv_par, mpar,
1044  &numpar, &tol, &its, &lab )) )
1045  {
1046  cpl_msg_debug ("sinfo_linefit:",
1047  " sinfo_new_lsqfit_c: least squares fit failed,"
1048  " error no.: %d\n", iters) ;
1049  return -17 ;
1050  }
1051 
1052  /* correct the fitted position for the given row of the
1053  line in image coordinates */
1054  par -> fit_par[2] = (float) (lineRow - halfWidth) + par -> fit_par[2] ;
1055 
1056  /* all was o.k. */
1057  return iters ;
1058 }
1059 
1084 int sinfo_new_fit_lines ( cpl_image * line_image,
1085  FitParams ** allParams,
1086  float fwhm,
1087  int * n_lines,
1088  int ** row,
1089  float ** wavelength,
1090  int width,
1091  float min_amplitude )
1092 {
1093  int i, k, l ;
1094  int result ;
1095  Vector * line;
1096  int * mpar;
1097  float * xdat, * wdat;
1098  int lx=0;
1099  /* int ly=0; */
1100  /* float* pdata=NULL; */
1101 
1102  if ( line_image == NULL )
1103  {
1104  sinfo_msg_error (" no image given\n") ;
1105  return -18 ;
1106  }
1107  lx=cpl_image_get_size_x(line_image);
1108  /* ly=cpl_image_get_size_y(line_image); */
1109  /* pdata=cpl_image_get_data_float(line_image); */
1110 
1111  if ( n_lines == NULL )
1112  {
1113  sinfo_msg_error (" no counter of emission lines\n") ;
1114  return -19 ;
1115  }
1116  if ( row == NULL || width <= 0 )
1117  {
1118  sinfo_msg_error (" row or width vectors are empty\n") ;
1119  return -20 ;
1120  }
1121  if ( wavelength == NULL )
1122  {
1123  sinfo_msg_error (" no wavelength array given\n") ;
1124  return -21 ;
1125  }
1126 
1127  k = 0 ;
1128 
1129  /* allocate memory for the spectral sinfo_vector */
1130  line = sinfo_new_vector (2*width + 1) ;
1131  /* allocate memory */
1132  xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
1133  wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
1134  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
1135 
1136  /* go through the columns */
1137  for ( i = 0 ; i < lx ; i++ )
1138  {
1139  if ( n_lines[i] == 0 )
1140  {
1141  continue ;
1142  }
1143  /* go through the emission lines in a column */
1144  for ( l = 0 ; l < n_lines[i] ; l++ )
1145  {
1146  if ( row[i][l] <= 0 )
1147  {
1148  continue ;
1149  }
1150 
1151  /* --------------------------------------------------------------
1152  * fit the single lines using sinfo_linefit and store the
1153  parameters in
1154  * an array of the FitParams data structure allParams[].
1155  */
1156  if ( (result = sinfo_new_line_fit ( line_image,
1157  allParams[k], fwhm, l, i,
1158  width, row[i][l],
1159  min_amplitude,line,mpar,
1160  xdat,wdat ) ) < 0 )
1161  {
1162  cpl_msg_debug ("sinfo_fitLines:",
1163  " sinfo_linefit failed, error no.: %d,"
1164  " column: %d, row: %d, line: %d\n",
1165  result, i, row[i][l], l) ;
1166  continue ;
1167  }
1168  if ( (allParams[k] -> fit_par[0] <= 0.) ||
1169  (allParams[k] -> fit_par[1] <= 0.)
1170  || (allParams[k] -> fit_par[2] <= 0.) )
1171  {
1172  sinfo_msg_warning (" negative fit parameters in column: %d,"
1173  " line: %d\n", i, l) ;
1174  continue ;
1175  }
1176  allParams[k] -> wavelength = wavelength[i][l] ;
1177  k++ ;
1178  }
1179  }
1180 
1181  /* free memory */
1182  sinfo_new_destroy_vector(line);
1183  cpl_free(xdat);
1184  cpl_free(wdat);
1185  cpl_free(mpar);
1186 
1187  /* all is o.k. */
1188  return k ;
1189 }
1190 
1218 float sinfo_new_polyfit( FitParams ** par,
1219  int column,
1220  int n_lines,
1221  int n_rows,
1222  float dispersion,
1223  float max_residual,
1224  float * acoefs,
1225  float * dacoefs,
1226  int * n_reject,
1227  int n_fitcoefs )
1228 {
1229  float ** ucoefs, ** vcoefs, ** covar ;
1230  float *mem;
1231  float * lambda, * posit ;
1232  float * weight, * resid ;
1233  float * newlam, * newpos, * newwet ;
1234  float * wcoefs=NULL ;
1235  float chisq, result ;
1236  float offset ;
1237  int num, found ;
1238  int i, j, k, n ;
1239 
1240  /* reset the fit coefficients and their errors */
1241  for ( i = 0 ; i < n_fitcoefs ; i++ )
1242  {
1243  acoefs[i] = 0. ;
1244  dacoefs[i] = 0. ;
1245  }
1246  if ( NULL == par )
1247  {
1248  sinfo_msg_error(" no fit params given\n");
1249  return FLT_MAX ;
1250  }
1251 
1252  if ( 0 >= n_lines )
1253  {
1254  /*
1255  sinfo_msg_warning (" sorry, number of lines is wrong") ;
1256  */
1257  return FLT_MAX ;
1258  }
1259  if ( 0 >= n_rows )
1260  {
1261  sinfo_msg_error (" sorry, number of rows is wrong") ;
1262  return FLT_MAX ;
1263  }
1264  if ( dispersion == 0. )
1265  {
1266  sinfo_msg_error (" sorry, wrong dispersion given") ;
1267  return FLT_MAX ;
1268  }
1269 
1270  offset = (float)(n_rows - 1)/2. ;
1271 
1272  /* allocate memory */
1273 
1274  mem = (float*) cpl_calloc( n_lines*7, sizeof (float) ) ;
1275  lambda = mem;
1276  posit = mem + n_lines;
1277  weight = mem + n_lines*2;
1278  resid = mem + n_lines*3;
1279  newlam = mem + n_lines*4;
1280  newpos = mem + n_lines*5;
1281  newwet = mem + n_lines*6;
1282 
1283  /*lambda = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
1284  posit = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
1285  weight = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
1286  resid = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
1287  newlam = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
1288  newpos = (float*) cpl_calloc( n_lines, sizeof (float) ) ;
1289  newwet = (float*) cpl_calloc( n_lines, sizeof (float) ) ;*/
1290 
1291  /* allocate coefficient matrices*/
1292  ucoefs = sinfo_matrix ( 1, n_lines, 1, n_fitcoefs ) ;
1293  vcoefs = sinfo_matrix ( 1, n_lines, 1, n_fitcoefs ) ;
1294  covar = sinfo_matrix ( 1, n_fitcoefs, 1, n_fitcoefs ) ;
1295  wcoefs=cpl_calloc(n_fitcoefs,sizeof(float)) ;
1296 
1297  /* go through all fit parameters */
1298  n = 0 ;
1299  for ( i = 0 ; i < (par[0] -> n_params) ; i ++ )
1300  {
1301  found = -1 ;
1302  /* find the given column and go through the lines in that column */
1303  for ( j = 0 ; j < n_lines ; j ++ )
1304  {
1305  if ( (par[i] -> column == column) && (par[i] -> line == j) )
1306  {
1307  found = i ;
1308  }
1309  else
1310  {
1311  continue ;
1312  }
1313 
1314  /* store only fit params with reasonable values */
1315  if ( par[found] -> derv_par[2] != 0. &&
1316  par[found] -> fit_par[2] > 0. &&
1317  par[found] -> wavelength > 0. &&
1318  par[found] -> fit_par[1] > 0. &&
1319  par[found] -> fit_par[0] > 0. )
1320  {
1321  /* ----------------------------------------------------------
1322  * store the found position, error of the position as
1323  weight and the associated
1324  * wavelength values of the fitted lines
1325  */
1326  posit[n] = par[found] -> fit_par[2] ;
1327  weight[n] = par[found] -> derv_par[2] ;
1328  lambda[n] = par[found] -> wavelength ;
1329  n ++ ;
1330  }
1331  else
1332  {
1333  continue ;
1334  }
1335  }
1336 
1337  }
1338 
1339  num = n ;
1340  if ( num < n_fitcoefs )
1341  {
1342  sinfo_msg_warning("not enough lines found in column %d to "
1343  "determine the three coefficients.\n", column) ;
1344  for ( i = 0 ; i < n_fitcoefs ; i++ )
1345  {
1346  acoefs[i] = ZERO ;
1347  dacoefs[i] = ZERO ;
1348  }
1349  sinfo_free_matrix ( ucoefs, 1/*, n_lines*/, 1/*, n_fitcoefs*/ ) ;
1350  sinfo_free_matrix ( vcoefs, 1/*, n_lines*/, 1/*, n_fitcoefs*/ ) ;
1351  sinfo_free_matrix ( covar, 1/*, n_fitcoefs*/, 1/*, n_fitcoefs*/ ) ;
1352  /*cpl_free (lambda) ;
1353  cpl_free (posit) ;
1354  cpl_free (weight) ;
1355  cpl_free (resid) ;
1356  cpl_free (newlam) ;
1357  cpl_free (newpos) ;
1358  cpl_free (newwet) ;*/
1359  cpl_free (mem);
1360  cpl_free(wcoefs) ;
1361  return FLT_MAX ;
1362  }
1363 
1364  /*-------------------------------------------------------------------------
1365  * scale the pixel position values to smaller than 1 and transform
1366  the weights to wavelength units
1367  */
1368 
1369  for ( i = 0 ; i < num ; i ++ )
1370  {
1371  posit[i] = (posit[i] - offset)/offset ;
1372  weight[i] *= fabs(dispersion) ;
1373  }
1374 
1375  /* do the fit using the singular value decomposition method */
1376  sinfo_svd_fitting( posit - 1, lambda - 1,
1377  weight - 1, num, acoefs-1, n_fitcoefs,
1378  ucoefs, vcoefs, wcoefs-1, covar, &chisq, sinfo_fpol ) ;
1379 
1380  /* scale the linear and the quadratic coefficient */
1381  for ( i = 1 ; i < n_fitcoefs ; i++ )
1382  {
1383  acoefs[i] /= pow(offset, i) ;
1384  }
1385 
1386  /* now that we have determined the fit coefficients, find the residuals */
1387  *n_reject = 0 ;
1388 
1389  j = 0 ;
1390  for ( i = 0 ; i < num ; i++ )
1391  {
1392  result = 0. ;
1393  for ( k = 0 ; k < n_fitcoefs ; k++ )
1394  {
1395  result += acoefs[k] * pow(posit[i], k) ;
1396  }
1397 
1398  resid[i] = lambda[i] - result ;
1399 
1400  if ( fabs( resid[i] ) > max_residual)
1401  {
1402  (*n_reject) ++ ;
1403  }
1404  else
1405  {
1406  newlam[j] = lambda[i] ;
1407  newpos[j] = posit[i] ;
1408  newwet[j] = weight[i] ;
1409  j++ ;
1410  }
1411  }
1412 
1413  num = j ;
1414  if ( num >= n_fitcoefs )
1415  {
1416  sinfo_svd_fitting( newpos - 1, newlam - 1,
1417  newwet - 1, num, acoefs-1, n_fitcoefs, ucoefs,
1418  vcoefs, wcoefs-1, covar, &chisq, sinfo_fpol ) ;
1419 
1420  /* scale the resulting coefficients */
1421  for ( i = 0 ; i < n_fitcoefs ; i++ )
1422  {
1423  acoefs[i] /= pow(offset, i) ;
1424  dacoefs[i] = sqrt( (double) covar[i+1][i+1] ) / pow(offset, i) ;
1425  }
1426  }
1427  else
1428  {
1429  sinfo_msg_warning (" too many lines rejected (number: %d) "
1430  "due to high residuals, fit coefficients are set "
1431  "zero, in column: %d\n", *n_reject, column) ;
1432  for ( i = 0 ; i < n_fitcoefs ; i++ )
1433  {
1434  acoefs[i] = ZERO ;
1435  dacoefs[i] = ZERO ;
1436  }
1437  }
1438 
1439  sinfo_free_matrix ( ucoefs, 1/*, n_lines*/, 1/*, n_fitcoefs*/ ) ;
1440  sinfo_free_matrix ( vcoefs, 1/*, n_lines*/, 1/*, n_fitcoefs*/ ) ;
1441  sinfo_free_matrix ( covar, 1/*, n_fitcoefs*/, 1/*, n_fitcoefs*/ ) ;
1442  /*cpl_free (lambda) ;
1443  cpl_free (posit) ;
1444  cpl_free (weight) ;
1445  cpl_free (resid) ;
1446  cpl_free (newlam) ;
1447  cpl_free (newpos) ;
1448  cpl_free (newwet) ;*/
1449  cpl_free (mem);
1450  cpl_free(wcoefs) ;
1451 
1452  return chisq ;
1453 }
1454 
1471 float sinfo_new_coefs_cross_fit ( int n_columns,
1472  float * acoefs,
1473  float * dacoefs,
1474  float * bcoefs,
1475  int n_fitcoefs,
1476  float sigma_factor )
1477 {
1478  float col_index;
1479  float* sub_col_index=NULL ;
1480  float* sub_acoefs=NULL ;
1481  float* sub_dacoefs=NULL ;
1482  float* wcoefs=NULL ;
1483  float ** ucoefs, **vcoefs, **covar ;
1484  float chisq ;
1485  float * acoefsclean ;
1486  double sum, sumq, mean ;
1487  double sigma ;
1488  double cliphi, cliplo ;
1489  float offset ;
1490  int i, n, num, ndata ;
1491  int nc ;
1492 
1493 
1494  if ( n_columns < 1 )
1495  {
1496  sinfo_msg_error(" wrong number of image columns given\n") ;
1497  return FLT_MAX ;
1498  }
1499  if ( acoefs == NULL || dacoefs == NULL )
1500  {
1501  sinfo_msg_error(" coeffs or errors of coefficients are not given\n") ;
1502  return FLT_MAX ;
1503  }
1504  if ( bcoefs == NULL )
1505  {
1506  sinfo_msg_error(" coeffs are not allocated\n") ;
1507  return FLT_MAX ;
1508  }
1509 
1510  if ( n_fitcoefs < 1 )
1511  {
1512  sinfo_msg_error(" wrong number of fit coefficients\n") ;
1513  return FLT_MAX ;
1514  }
1515  if ( sigma_factor <= 0. )
1516  {
1517  sinfo_msg_error(" impossible sigma_factor given!\n") ;
1518  return FLT_MAX ;
1519  }
1520 
1521  offset = (float)(n_columns - 1) / 2. ;
1522 
1523  /* ----------------------------------------------------------
1524  * determine the clean mean and sigma value of the coefficients,
1525  * that means reject 10 % of the extreme low and high values
1526  */
1527 
1528  wcoefs=cpl_calloc(n_fitcoefs,sizeof(float)) ;
1529 
1530  nc = 0 ;
1531  for ( i = 0 ; i < n_columns ; i++ )
1532  {
1533  if ( isnan(acoefs[i]) || acoefs[i] == 0. || dacoefs[i] == 0. )
1534  {
1535  continue ;
1536  }
1537  else
1538  {
1539  nc++ ;
1540  }
1541  }
1542  acoefsclean = (float*) cpl_calloc(nc , sizeof(float)) ;
1543  nc = 0 ;
1544  for ( i = 0 ; i < n_columns ; i++ )
1545  {
1546  if ( isnan(acoefs[i]) || acoefs[i] == 0. || dacoefs[i] == 0. )
1547  {
1548  continue ;
1549  }
1550  else
1551  {
1552  acoefsclean[nc] = acoefs[i] ;
1553  nc++ ;
1554  }
1555  }
1556  sinfo_pixel_qsort(acoefsclean, nc) ;
1557  sum = 0. ;
1558  sumq = 0. ;
1559  mean = 0. ;
1560  sigma = 0. ;
1561  n = 0 ;
1562  for ( i = (int)((float)nc*LOW_REJECT) ;
1563  i < (int)((float)nc*HIGH_REJECT) ; i++ )
1564  {
1565  sum += (double)acoefsclean[i] ;
1566  sumq += ((double)acoefsclean[i] * (double)acoefsclean[i]) ;
1567  n ++ ;
1568  }
1569  mean = sum/(double)n ;
1570  sigma = sqrt( sumq/(double)n - (mean * mean) ) ;
1571  cliphi = mean + sigma * (double)sigma_factor ;
1572  cliplo = mean - sigma * (double)sigma_factor ;
1573 
1574  sub_col_index=cpl_calloc(n_columns,sizeof(float)) ;
1575  sub_acoefs=cpl_calloc(n_columns,sizeof(float));
1576  sub_dacoefs=cpl_calloc(n_columns,sizeof(float)) ;
1577 
1578  /* fit only the reasonnable values */
1579  num = 0 ;
1580  for ( i = 0 ; i < n_columns ; i++ )
1581  {
1582  /* associate the column indices to the corresponding array */
1583  col_index = (float) i ;
1584 
1585  /* take only the reasonnable coefficients */
1586  if ( !isnan(acoefs[i]) &&
1587  (acoefs[i] <= cliphi) && (acoefs[i] >= cliplo) &&
1588  (dacoefs[i] != 0. ) && (acoefs[i] != 0.) )
1589  {
1590  sub_acoefs[num] = acoefs[i] ;
1591  sub_dacoefs[num] = dacoefs[i] ;
1592  sub_col_index[num] = col_index ;
1593  num ++ ;
1594  }
1595  }
1596  ndata = num ;
1597 
1598  if ( ndata < n_fitcoefs )
1599  {
1600  sinfo_msg_error("not enough data found to determine "
1601  "the fit coefficients.\n") ;
1602 
1603  return FLT_MAX ;
1604  }
1605 
1606  /* allocate coefficient matrices */
1607  ucoefs = sinfo_matrix(1, ndata, 1, n_fitcoefs) ;
1608  vcoefs = sinfo_matrix(1, ndata, 1, n_fitcoefs) ;
1609  covar = sinfo_matrix ( 1, n_fitcoefs, 1, n_fitcoefs ) ;
1610 
1611  /* scale the x-values for the fit */
1612  for ( i = 0 ; i < ndata ; i++ )
1613  {
1614  sub_col_index[i] = (sub_col_index[i] - offset) / offset ;
1615  }
1616 
1617  /* finally, do the singular value decomposition fit */
1618  sinfo_svd_fitting ( sub_col_index-1, sub_acoefs-1,
1619  sub_dacoefs-1, ndata, bcoefs-1,
1620  n_fitcoefs, ucoefs, vcoefs,
1621  wcoefs-1, covar, &chisq, sinfo_fpol ) ;
1622 
1623  /* scale the found coefficients */
1624  for ( i = 0 ; i < n_fitcoefs ; i ++ )
1625  {
1626  bcoefs[i] /= pow(offset, i) ;
1627  }
1628 
1629  /* free memory */
1630  cpl_free (acoefsclean) ;
1631  sinfo_free_matrix( ucoefs, 1/*, ndata*/, 1/*, n_fitcoefs */) ;
1632  sinfo_free_matrix( vcoefs, 1/*, ndata*/, 1/*, n_fitcoefs */) ;
1633  sinfo_free_matrix ( covar, 1/*, n_fitcoefs*/, 1/*, n_fitcoefs*/ ) ;
1634 
1635  cpl_free(sub_col_index) ;
1636  cpl_free(sub_acoefs) ;
1637  cpl_free(sub_dacoefs) ;
1638  cpl_free(wcoefs) ;
1639 
1640  return chisq ;
1641 }
1642 
1643 
1663 cpl_image * sinfo_new_wave_map( cpl_image * lineImage,
1664  float ** bcoefs,
1665  int n_a_fitcoefs,
1666  int n_b_fitcoefs,
1667  float * wavelength,
1668  float * intensity,
1669  int n_lines,
1670  int magFactor)
1671 {
1672  cpl_image * retImage ;
1673  float cenpos, cenpix ;
1674  float centreval, centrepix, wavelag ;
1675  float pixvalue ;
1676  float a_initial ;
1677  int i, j, k, l/*, m*/, line, col, row, found, sign ;
1678  int var, maxlag, cmin, cmax, offset ;
1679  double * result ;
1680  float col_off ;
1681  float angst ;
1682  double xcorr_max ;
1683  int delta ;
1684 
1685  double* z=NULL ;
1686  double* a=NULL ;
1687  double* wave=NULL ;
1688  float* emline=NULL ;
1689  float* spec=NULL ;
1690  int ilx=0;
1691  int ily=0;
1692  /*
1693  int olx=0;
1694  int oly=0;
1695  */
1696  float* pidata=NULL;
1697  float* podata=NULL;
1698 
1699 
1700  gsl_poly_complex_workspace * w ;
1701 
1702  if ( NULL == lineImage )
1703  {
1704  sinfo_msg_error("no image given\n") ;
1705  return NULL ;
1706  }
1707  ilx=cpl_image_get_size_x(lineImage);
1708  ily=cpl_image_get_size_y(lineImage);
1709  pidata=cpl_image_get_data_float(lineImage);
1710 
1711  if ( NULL == wavelength || n_lines <= 0 )
1712  {
1713  sinfo_msg_error("no wavelength list given\n") ;
1714  return NULL ;
1715  }
1716 
1717  if ( NULL == intensity )
1718  {
1719  sinfo_msg_error("no intensity list given\n") ;
1720  return NULL ;
1721  }
1722 
1723  if ( NULL == bcoefs )
1724  {
1725  sinfo_msg_error("no coefficients given\n") ;
1726  return NULL ;
1727  }
1728 
1729  if ( magFactor <= 1 )
1730  {
1731  sinfo_msg_error("wrong magnifying factor given\n") ;
1732  return NULL ;
1733  }
1734 
1735  /* allocate memory */
1736  if ( NULL == ( retImage = cpl_image_new( ilx, ily,CPL_TYPE_FLOAT ) ))
1737  {
1738  sinfo_msg_error("cannot allocate a new image\n");
1739  return NULL ;
1740  }
1741  /*
1742  olx=cpl_image_get_size_x(retImage);
1743  oly=cpl_image_get_size_y(retImage);
1744  */
1745  podata=cpl_image_get_data_float(retImage);
1746 
1747 
1748  var = (magFactor - 1)*(magFactor - 1) ;
1749  offset = ily * (magFactor/4 + 1) ;
1750 
1751  /* find out if Angstroem or microns are used */
1752  if ( wavelength[0] > 10000. )
1753  {
1754  /* Angstroem */
1755  angst = 10000. ;
1756  }
1757  else if ( wavelength[0] > 1000. && wavelength[0] < 10000. )
1758  {
1759  /* nanometers */
1760  angst = 1000. ;
1761  }
1762  else
1763  {
1764  /* microns */
1765  angst = 1. ;
1766  }
1767 
1768  z=cpl_calloc(2*(n_a_fitcoefs - 1),sizeof(double)) ;
1769  a=cpl_calloc(n_a_fitcoefs,sizeof(double));
1770  wave=cpl_calloc(n_lines,sizeof(double)) ;
1771  emline=cpl_calloc(2*magFactor*ily,sizeof(float));
1772  spec=cpl_calloc(2*magFactor*ily,sizeof(float)) ;
1773 
1774  /* go through the image columns */
1775  for ( col = 0 ; col < ilx ; col++ )
1776  {
1777  /* initialize the emline array for each column */
1778  for ( i = 0 ; i < 2*magFactor*ily ; i++ )
1779  {
1780  emline[i] = 0. ;
1781  }
1782  col_off = (float)col - (float)(ilx-1)/2. ;
1783 
1784  /* determine the coefficients by using the given bcoefs */
1785  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
1786  {
1787  /* initialize coefficients and solution */
1788  a[i] = 0. ;
1789  if (i < n_a_fitcoefs-1)
1790  {
1791  z[2*i] = 0. ;
1792  z[2*i+1] = 0. ;
1793  }
1794  for ( j = 0 ; j < n_b_fitcoefs ; j++ )
1795  {
1796  a[i] += bcoefs[i][j] * pow(col_off, j) ;
1797  }
1798  }
1799  a_initial = a[0] ;
1800 
1801  /* go through the lines and generate an artificial spectrum */
1802  for ( line = 0 ; line < n_lines ; line++ )
1803  {
1804  /* go from Angstroem to micron */
1805  wave[line] = wavelength[line]/angst ;
1806 
1807  /* ---------------------------------------------------------------
1808  * solve the polynomial for the exact offset of the line that means
1809  * find the root of the polynomial of order n_fitcoefs - 1
1810  */
1811  a[0] = a_initial - wave[line] ;
1812 
1813  if(NULL==(w=sinfo_gsl_poly_complex_workspace_alloc(n_a_fitcoefs)))
1814  {
1815  sinfo_msg_error("could not allocate complex workspace!") ;
1816  cpl_image_delete(retImage) ;
1817  return NULL ;
1818  }
1819  if (-1 == sinfo_gsl_poly_complex_solve(a, n_a_fitcoefs, w, z))
1820  {
1821  sinfo_msg_error("sinfo_gsl_poly_complex_solve did not work!") ;
1822  cpl_image_delete(retImage) ;
1823  return NULL ;
1824  }
1825  sinfo_gsl_poly_complex_workspace_free(w) ;
1826 
1827 
1828  j = 0 ;
1829  found = -1 ;
1830  for ( i = 0 ; i < n_a_fitcoefs - 1 ; i++ )
1831  {
1832  /* test for appropriate solution */
1833  if( z[2*i] > (-1.)*(float) ily/2. &&
1834  z[2*i] < (float)ily/2. && z[2*i+1] == 0. )
1835  {
1836  found = 2*i ;
1837  j ++ ;
1838  }
1839  else
1840  {
1841  continue ;
1842  }
1843  }
1844  if ( j == 0 )
1845  {
1846  sinfo_msg_warning("no offset solution found "
1847  "for line %d in column %d\n", line, col) ;
1848  continue ;
1849  }
1850  else if ( j == 1 )
1851  {
1852  cenpos = z[found] + (float) ily /2. ;
1853  }
1854  else
1855  {
1856  sinfo_msg_warning("two or more offset solutions found "
1857  "for line %d in column %d\n", line, col) ;
1858  continue ;
1859  }
1860 
1861  /*---------------------------------------------------------------
1862  * magnify image by the given factor add an additional offset
1863  */
1864  cenpix = cenpos * (float) magFactor + (float) offset ;
1865 
1866  /* determine max and min pixel limits over
1867  which line should be convolved */
1868  cmin = (sinfo_new_nint(cenpix) - (var-1)) > 0 ?
1869  sinfo_new_nint(cenpix) - (var-1) : 0 ;
1870  cmax = (sinfo_new_nint(cenpix) + (var-1)) < 2*magFactor * ily ?
1871  sinfo_new_nint(cenpix) + (var-1) : 2*magFactor * ily ;
1872 
1873  /* convolve neon lines with Gaussian function */
1874  for ( j = cmin ; j < cmax ; j++ )
1875  {
1876  emline[j] += intensity[line] *
1877  exp((double)(-0.5*(j-cenpix)*(j-cenpix))/(double)var) ;
1878  }
1879  }
1880 
1881  /*---------------------------------------------------------------------
1882  * for each column, map the image data points onto an magFactor times
1883  bigger element grid for FFT in the cross sinfo_new_correlation,
1884  first initialize the two helping arrays for each new column.
1885  */
1886  for ( k = 0 ; k < 2*magFactor * ily ; k++ )
1887  {
1888  spec[k] = 0. ;
1889  }
1890 
1891  /* now take the image data points of the column and put them
1892  into the spec array */
1893  for ( row = 0 ; row < ily ; row++ ) /* go through the column */
1894  {
1895  /* insert 8 values for each image row (magnification) and
1896  add same offset as for emline array */
1897  for ( l = 0 ; l < magFactor ; l++ )
1898  {
1899  /* set bad pixels or negative values to zero */
1900  if (!isnan(pidata[col + row * ilx]) &&
1901  (pidata[col + row * ilx] > 0.))
1902  {
1903  spec[offset + l + (row * magFactor)] =
1904  pidata[col + row * ilx] ;
1905  }
1906  else
1907  {
1908  spec[offset + l + (row * magFactor)] = 0. ;
1909  }
1910  }
1911  }
1912 
1913  /* now call the cross sinfo_new_correlation routine */
1914  if (NULL == (result = sinfo_new_xcorrel(spec, 2*magFactor * ily,
1915  emline, 2*magFactor * ily,
1916  magFactor * ily, &delta,
1917  &maxlag, &xcorr_max)) )
1918  {
1919  sinfo_msg_warning ("cross sinfo_new_correlation did not work,"
1920  " col: %d is set ZERO\n", col) ;
1921  for ( row = 0 ; row < ily ; row++ )
1922  {
1923  podata[col + row * ilx] = ZERO ;
1924  }
1925  continue ;
1926  }
1927 
1928  if ( xcorr_max <= 0. )
1929  {
1930  sinfo_msg_warning ("cross sinfo_new_correlation sum is negative,"
1931  " col: %d is set ZERO\n", col) ;
1932  for ( row = 0 ; row < ily ; row++ )
1933  {
1934  podata[col + row * ilx] = ZERO ;
1935  }
1936  cpl_free(result) ;
1937  continue ;
1938  }
1939 
1940  wavelag = (float) -delta / (float) magFactor ;
1941  if ( fabs(wavelag) > (float)ily/20. )
1942  {
1943  sinfo_msg_warning("wave lag too big, col: %d is set ZERO\n", col) ;
1944  for ( row = 0 ; row < ily ; row++ )
1945  {
1946  podata[col + row * ilx] = ZERO ;
1947  }
1948  cpl_free(result) ;
1949  continue ;
1950  }
1951 
1952  /*--------------------------------------------------------------------
1953  * determine new zero order coefficient centreval, of which the
1954  formula is determined by setting equal a polynomial shifted by
1955  wavelag with the same higher order coefficients and set the new
1956  zero order coefficient to get both sides of the equation
1957  approximately equal.
1958  */
1959  centreval = a_initial ;
1960  for ( i = 1 ; i < n_a_fitcoefs ; i++ )
1961  {
1962  if ( i%2 == 0 )
1963  {
1964  sign = -1 ;
1965  }
1966  else
1967  {
1968  sign = 1 ;
1969  }
1970  centreval += (float)sign * a[i]*pow(wavelag, i) ;
1971  }
1972 
1973  /* prepare to write out wavelength as pixel values */
1974  for ( row = 0 ; row < ily ; row++ )
1975  {
1976  centrepix = (float)row - ((float)ily - 1.)/2. ;
1977  pixvalue = 0. ;
1978  for ( i = 1 ; i < n_a_fitcoefs ; i++ )
1979  {
1980  pixvalue += a[i]*pow(centrepix, i) ;
1981  }
1982  podata[col + row * ilx] = centreval + pixvalue ;
1983  }
1984  cpl_free(result) ;
1985  }
1986 
1987 
1988 
1989  cpl_free(z) ;
1990  cpl_free(a) ;
1991  cpl_free(wave) ;
1992  cpl_free(emline) ;
1993  cpl_free(spec) ;
1994 
1995  return retImage ;
1996 }
1997 
2042 int sinfo_new_wavelength_calibration( cpl_image * image,
2043  FitParams ** par ,
2044  float ** bcoefs,
2045  float * wave,
2046  int n_lines,
2047  int ** row_clean,
2048  float ** wavelength_clean,
2049  int * n_found_lines,
2050  float dispersion,
2051  int halfWidth,
2052  float minAmplitude,
2053  float max_residual,
2054  float fwhm,
2055  int n_a_fitcoefs,
2056  int n_b_fitcoefs,
2057  float sigmaFactor,
2058  float pixel_tolerance )
2059 
2060 {
2061  int i, j;
2062  /* int k ; */
2063  int n_fit ;
2064  int n_reject ;
2065  float * acoefs ;
2066  float * dacoefs ;
2067  float ** abuf ;
2068  float ** dabuf ;
2069  float chisq_poly, chisq_cross ;
2070  int zeroind ;
2071  /*float * mem ;*/
2072  int lx=0;
2073  int ly=0;
2074  /* float* pdata=NULL; */
2075 
2076  if ( NULL == image )
2077  {
2078  sinfo_msg_error("no image given\n") ;
2079  return -1 ;
2080  }
2081  lx=cpl_image_get_size_x(image);
2082  ly=cpl_image_get_size_y(image);
2083  /* pdata=cpl_image_get_data_float(image); */
2084 
2085  if ( par == NULL )
2086  {
2087  sinfo_msg_error("no fit parameter data structure given\n") ;
2088  return -1 ;
2089  }
2090  if ( wave == NULL )
2091  {
2092  sinfo_msg_error("no wavelength list given\n") ;
2093  return -1 ;
2094  }
2095  if ( n_lines <= 0 )
2096  {
2097  sinfo_msg_error("impossible number of lines in line list given\n") ;
2098  return -1 ;
2099  }
2100  if ( row_clean == NULL )
2101  {
2102  sinfo_msg_error("no row_clean array given\n") ;
2103  return -1 ;
2104  }
2105  if ( wavelength_clean == NULL )
2106  {
2107  sinfo_msg_error("no wavelength_clean array given\n") ;
2108  return -1 ;
2109  }
2110 
2111  if ( dispersion == 0. )
2112  {
2113  sinfo_msg_error("impossible dispersion given\n") ;
2114  return -1 ;
2115  }
2116 
2117  if ( halfWidth <= 0 || halfWidth > ly/2 )
2118  {
2119  sinfo_msg_error("impossible half width of the fitting box given\n") ;
2120  return -1 ;
2121  }
2122  if ( minAmplitude < 1. )
2123  {
2124  sinfo_msg_error("impossible minimal amplitude\n") ;
2125  return -1 ;
2126  }
2127 
2128  if ( max_residual <= 0. || max_residual > 1. )
2129  {
2130  sinfo_msg_error("impossible max_residual given\n") ;
2131  return -1 ;
2132  }
2133 
2134  if ( fwhm <= 0. || fwhm > 10. )
2135  {
2136  sinfo_msg_error("impossible fwhm given\n") ;
2137 
2138  return -1 ;
2139  }
2140 
2141  if ( n_a_fitcoefs <= 0 || n_a_fitcoefs > 9 )
2142  {
2143  sinfo_msg_error("unrealistic n_a_fitcoefs given\n") ;
2144  return -1 ;
2145  }
2146 
2147  if ( n_b_fitcoefs <= 0 || n_b_fitcoefs > 9 )
2148  {
2149  sinfo_msg_error(" unrealistic n_b_fitcoefs given\n") ;
2150  return -1 ;
2151  }
2152  if ( sigmaFactor <= 0. )
2153  {
2154  sinfo_msg_error(" impossible sigmaFactor given\n") ;
2155  return -1 ;
2156  }
2157 
2158  /* initialize the variables */
2159  n_reject = 0 ;
2160  n_fit = 0 ;
2161 
2162  /* fit each found line by using a Gaussian function and determine the
2163  exact position */
2164  if ( 0 > (n_fit = sinfo_new_fit_lines( image , par, fwhm,
2165  n_found_lines, row_clean,
2166  wavelength_clean,
2167  halfWidth, minAmplitude )) )
2168  {
2169  sinfo_msg_error(" cannot fit the lines, "
2170  "error code of sinfo_fitLines: %d\n", n_fit) ;
2171  return -1 ;
2172  }
2173 
2174  /* first check for faked lines like bad pixels */
2175  if ( -1 == sinfo_new_check_for_fake_lines (par, dispersion,
2176  wavelength_clean, row_clean,
2177  n_found_lines,
2178  lx, pixel_tolerance) )
2179  {
2180  sinfo_msg_error("cannot fit the lines, "
2181  "error code of sinfo_fitLines: %d", n_fit) ;
2182  return -1 ;
2183  }
2184 
2185  /* allocate memory */
2186  if (NULL == (acoefs = (float*) cpl_calloc (n_a_fitcoefs, sizeof(float*))) ||
2187  NULL == (dacoefs = (float*)cpl_calloc (n_a_fitcoefs, sizeof(float*))) ||
2188  NULL == (abuf = (float**) cpl_calloc (n_a_fitcoefs, sizeof(float*))) ||
2189  NULL == (dabuf = (float**) cpl_calloc (n_a_fitcoefs, sizeof(float*))) )
2190  {
2191  sinfo_msg_error(" cannot allocate memory\n") ;
2192  return -1 ;
2193  }
2194 
2195  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
2196  {
2197  if ( NULL == (abuf[i] = (float*) cpl_calloc(lx, sizeof(float))) ||
2198  NULL == (dabuf[i] = (float*) cpl_calloc(lx, sizeof(float))) )
2199  {
2200  sinfo_msg_error(" cannot allocate memory\n") ;
2201  cpl_free(abuf) ;
2202  cpl_free(dabuf) ;
2203  return -1 ;
2204  }
2205  }
2206 
2207  /* fit wavelengths to the corresponding found positions for each column */
2208  /* k = 0 ; */
2209 
2210  for ( i = 0 ; i < lx ; i++ )
2211  {
2212  zeroind = 0 ;
2213  if ( FLT_MAX == (chisq_poly = sinfo_new_polyfit( par, i,
2214  n_found_lines[i],
2215  ly, dispersion,
2216  max_residual, acoefs,
2217  dacoefs, &n_reject,
2218  n_a_fitcoefs)) )
2219  {
2220  /*
2221  sinfo_msg_warning (" error in polyfitt in column: %d\n", i) ;
2222  */
2223  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
2224  {
2225  acoefs[j] = ZERO ;
2226  dacoefs[j] = ZERO ;
2227  }
2228  }
2229 
2230  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
2231  {
2232  if ( acoefs[0] <= 0. || acoefs[1] ==0. ||
2233  dacoefs[j] == 0. || isnan(acoefs[j]) )
2234  {
2235  zeroind = 1 ;
2236 
2237  }
2238  }
2239  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
2240  {
2241  if ( zeroind == 0 )
2242  {
2243  abuf[j][i] = acoefs[j] ;
2244  dabuf[j][i] = dacoefs[j] ;
2245  }
2246  else
2247  {
2248  abuf[j][i] = ZERO ;
2249  dabuf[j][i] = ZERO ;
2250  }
2251  }
2252  }
2253 
2254  /* fit each acoefs across the columns to smooth the result */
2255  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
2256  {
2257  if ( FLT_MAX == (chisq_cross = sinfo_new_coefs_cross_fit(lx,
2258  abuf[i],
2259  dabuf[i],
2260  bcoefs[i],
2261  n_b_fitcoefs,
2262  sigmaFactor)))
2263  {
2264  sinfo_msg_error (" cannot carry out the fitting of coefficients"
2265  " across the columns, for the coefficient with"
2266  " index: %d\n", i) ;
2267  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
2268  {
2269  cpl_free (abuf[i]) ;
2270  cpl_free (dabuf[i]) ;
2271  }
2272  cpl_free ( acoefs ) ;
2273  cpl_free ( dacoefs ) ;
2274  cpl_free ( abuf ) ;
2275  cpl_free ( dabuf ) ;
2276  return -1 ;
2277  }
2278  }
2279 
2280  /* free all allocated memory */
2281  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
2282  {
2283  cpl_free (abuf[i]) ;
2284  cpl_free (dabuf[i]) ;
2285  }
2286  cpl_free ( acoefs ) ;
2287  cpl_free ( dacoefs ) ;
2288  cpl_free ( abuf ) ;
2289  cpl_free ( dabuf ) ;
2290 
2291  return 0 ;
2292 }
2293 
2294 
2306 cpl_image * sinfo_new_convolve_image_by_gauss( cpl_image * lineImage,
2307  int hw )
2308 {
2309  cpl_image * returnImage ;
2310  float* column_buffer=NULL ;
2311  float * filter ;
2312  int col, row ;
2313  int ilx=0;
2314  int ily=0;
2315  /*
2316  int olx=0;
2317  int oly=0;
2318  */
2319  float* pidata=NULL;
2320  float* podata=NULL;
2321 
2322  if ( lineImage == NULL )
2323  {
2324  sinfo_msg_error(" no input image given!\n") ;
2325  return NULL ;
2326  }
2327  ilx=cpl_image_get_size_x(lineImage);
2328  ily=cpl_image_get_size_y(lineImage);
2329  pidata=cpl_image_get_data_float(lineImage);
2330 
2331  if ( hw < 1 )
2332  {
2333  sinfo_msg_error(" wrong half width given!\n") ;
2334  return NULL ;
2335  }
2336 
2337  /* allocate memory for returned image */
2338  if ( NULL == ( returnImage = cpl_image_new(ilx,ily,CPL_TYPE_FLOAT ) ))
2339  {
2340  sinfo_msg_error(" cannot allocate a new image\n");
2341  return NULL ;
2342  }
2343  /*
2344  olx=cpl_image_get_size_x(returnImage);
2345  oly=cpl_image_get_size_y(returnImage);
2346  */
2347  podata=cpl_image_get_data_float(returnImage);
2348 
2349  column_buffer=cpl_calloc(ily,sizeof(float)) ;
2350 
2351  /* go through the image columns and save them in a buffer */
2352  for ( col = 0 ; col < ilx ; col++ )
2353  {
2354  for ( row = 0 ; row < ily ; row++ )
2355  {
2356  column_buffer[row] = pidata[col + row*ilx] ;
2357  }
2358 
2359  /*---------------------------------------------------------------------
2360  * now low pass filter the columns by the sinfo_gaussian and fill
2361  the return image.
2362  */
2363  filter = sinfo_function1d_filter_lowpass( column_buffer,
2364  ily,
2365  LOW_PASS_GAUSSIAN,
2366  hw ) ;
2367  for ( row = 0 ; row < ily ; row++ )
2368  {
2369  podata[col + row*ilx] = filter[row] ;
2370  }
2371  sinfo_function1d_del(filter) ;
2372  }
2373 
2374  cpl_free(column_buffer);
2375  return returnImage ;
2376 }
2377 
2417 cpl_image * sinfo_new_defined_resampling( cpl_image * image,
2418  cpl_image * calimage,
2419  int n_params,
2420  int* n_rows,
2421  double * dispersion,
2422  float * minval,
2423  float * maxval,
2424  double * centralLambda,
2425  int * centralpix )
2426 {
2427  cpl_image * retImage ;
2428  cpl_image * tempCalImage ;
2429  cpl_image * tempImage ;
2430  float lambda ;
2431  float dif, lambda_renorm ;
2432  float * retimagecol = NULL;//[2560] ; /* retimagecol[n_rows] ; */
2433 
2434  float* imagecol=NULL ;
2435  float* calcol=NULL ;
2436  float* x_renorm=NULL ;
2437 
2438  float * imageptr ;
2439  float sum, new_sum ;
2440  float disp, mindisp ;
2441  int *calcolpos=NULL;//[2560];
2442  int i/*, j*/, col, row, testrow ;
2443  int half_width, firstpos ;
2444  int dispInd ;
2445  int n ;
2446  int flag;
2447  float temprow;
2448  float minLambda = 0. ;
2449  /*dpoint list[n_params] ;*/
2450  /*double * polycoeffs ;*/
2451  double poly ;
2452  /*float error;*/
2453  int zeroind ;
2454  int ilx=0;
2455  int ily=0;
2456  int clx=0;
2457  int cly=0;
2458  int olx=0;
2459  int oly=0;
2460 
2461  float* podata=NULL;
2462  float* pidata=NULL;
2463  float* pcdata=NULL;
2464  float* ptidata=NULL;
2465  float* ptcdata=NULL;
2466 
2467  if ( NULL == image )
2468  {
2469  sinfo_msg_error(" source image not given\n") ;
2470  return NULL ;
2471  }
2472  ilx=cpl_image_get_size_x(image);
2473  ily=cpl_image_get_size_y(image);
2474  pidata=cpl_image_get_data_float(image);
2475 
2476 
2477  if ( NULL == calimage )
2478  {
2479  sinfo_msg_error(" wavelength map image not given\n") ;
2480  return NULL ;
2481  }
2482  clx=cpl_image_get_size_x(calimage);
2483  cly=cpl_image_get_size_y(calimage);
2484  pcdata=cpl_image_get_data_float(calimage);
2485  if ( ilx != clx ||
2486  ily != cly )
2487  {
2488  sinfo_msg_error("source image and wavelength map image "
2489  "are not compatible in size\n") ;
2490  return NULL ;
2491  }
2492 
2493  if ( n_params < 1 )
2494  {
2495  sinfo_msg_error (" wrong number of fit parameters given\n") ;
2496  return NULL ;
2497  }
2498 
2499  if ( n_params > 4 )
2500  {
2501  sinfo_msg_warning(" attention: very high number of fit "
2502  "parameters given, not tested !!!\n") ;
2503  }
2504 
2505  imagecol=cpl_calloc(ily,sizeof(float)) ;
2506  calcol=cpl_calloc(cly,sizeof(float)) ;
2507  x_renorm=cpl_calloc(n_params,sizeof(float)) ;
2508 
2509 
2510  /*if ( n_rows <= cly)
2511  {
2512  sinfo_msg_error (" number of rows of resampled image will be "
2513  " smaller than in wavelength calibration map,"
2514  " information would get lost!") ;
2515  return NULL ;
2516  }*/
2517 
2518  dispInd = 0 ;
2519 
2520  /* first determine the dispersion direction */
2521  for ( col = 0 ; col < clx ; col++ )
2522  {
2523  if ( isnan(pcdata[col]) || pcdata[col] <= 0. )
2524  {
2525  continue ;
2526  }
2527  if ((pcdata[col] - pcdata[col+(clx)*(cly-1)]) > 0. )
2528  {
2529  dispInd-- ;
2530  }
2531  else if ((pcdata[col] - pcdata[col+(clx)*(cly-1)]) < 0. )
2532  {
2533  dispInd++ ;
2534  }
2535  else
2536  {
2537  continue ;
2538  }
2539  }
2540 
2541  if ( dispInd == 0 )
2542  {
2543  sinfo_msg_error(" zero dispersion?\n");
2544  return NULL ;
2545  }
2546 
2547  /* mirror the wavelength map and the raw image if
2548  the dispersion is negative */
2549  if ( dispInd < 0 )
2550  {
2551 
2552  /* allocate a temp image */
2553  if ( NULL == ( tempCalImage = cpl_image_new(clx,cly,CPL_TYPE_FLOAT)))
2554  {
2555  sinfo_msg_error(" cannot allocate a new image\n");
2556  return NULL ;
2557  }
2558  ptcdata=cpl_image_get_data_float(tempCalImage);
2559  if ( NULL == ( tempImage = cpl_image_new( ilx, ily,CPL_TYPE_FLOAT)))
2560  {
2561  sinfo_msg_error(" cannot allocate a new image\n");
2562  cpl_image_delete(tempCalImage) ;
2563  return NULL ;
2564  }
2565  ptidata=cpl_image_get_data_float(tempImage);
2566 
2567  for ( col = 0 ; col < clx ; col++ )
2568  {
2569  n = cly - 1 ;
2570  for ( row = 0 ; row < cly ; row++ )
2571  {
2572  ptcdata[col+row*clx] = pcdata[col+n*clx] ;
2573  ptidata[col+row*clx] = pidata[col+n*clx] ;
2574  n-- ;
2575  }
2576  }
2577 
2578  for ( i = 0 ; i < (int) ilx*ily ; i++ )
2579  {
2580  pidata[i] = ptidata[i] ;
2581  pcdata[i] = ptcdata[i] ;
2582  }
2583  cpl_image_delete(tempCalImage) ;
2584  cpl_image_delete(tempImage) ;
2585  }
2586 
2587  /* determine the max and min pixel value in the first and the last row */
2588  *maxval = -FLT_MAX ;
2589  *minval = FLT_MAX ;
2590  mindisp = FLT_MAX ;
2591  for ( col = 0 ; col < clx ; col++ )
2592  {
2593  if ( isnan(pcdata[col]) || pcdata[col] <= 0. )
2594  {
2595  continue ;
2596  }
2597  disp = (pcdata[col+(clx)*((cly)-1)]
2598  - pcdata[col]) / (float)cly ;
2599  if ( mindisp > disp )
2600  {
2601  mindisp = disp ;
2602  }
2603  if ( *minval >= pcdata[col] )
2604  {
2605  *minval = pcdata[col] ;
2606  }
2607  if ( *maxval <= pcdata[col + (clx)*((cly)-1)] )
2608  {
2609  *maxval = pcdata[col + (clx)*((cly)-1)] ;
2610  }
2611  }
2612 
2613  /* find the used grating and set the dispersion to the defined value */
2614  if (*minval > 1.9 )
2615  {
2616  if ( cly > 1024 && cly < 3000)
2617  {
2618  *dispersion = DISPERSION_K_DITH ;
2619  *centralLambda = CENTRALLAMBDA_K ;
2620  }
2621  else if ( cly < 2000)
2622  {
2623  *dispersion = DISPERSION_K ;
2624  *centralLambda = CENTRALLAMBDA_K ;
2625  }
2626  else
2627  {
2628  *dispersion = DISPERSION_K_DITH/2 ;
2629  *centralLambda = CENTRALLAMBDA_K ;
2630  }
2631  }
2632  else if (*minval < 1.2 )
2633  {
2634  if ( cly > 1024 )
2635  {
2636  *dispersion = DISPERSION_J_DITH ;
2637  *centralLambda = CENTRALLAMBDA_J ;
2638  }
2639  else
2640  {
2641  *dispersion = DISPERSION_J ;
2642  *centralLambda = CENTRALLAMBDA_J ;
2643  }
2644  }
2645  else
2646  {
2647  if ( *maxval > 2.3 )
2648  {
2649  if ( cly > 1024 )
2650  {
2651  *dispersion = DISPERSION_HK_DITH ;
2652  *centralLambda = CENTRALLAMBDA_HK ;
2653  }
2654  else
2655  {
2656  *dispersion = DISPERSION_HK ;
2657  *centralLambda = CENTRALLAMBDA_HK ;
2658  }
2659  }
2660  else
2661  {
2662  if ( cly > 1024 )
2663  {
2664  *dispersion = DISPERSION_H_DITH ;
2665  *centralLambda = CENTRALLAMBDA_H ;
2666  }
2667  else
2668  {
2669  *dispersion = DISPERSION_H ;
2670  *centralLambda = CENTRALLAMBDA_H ;
2671  }
2672  }
2673  }
2674 
2675  /*if ( *minval + (float)n_rows * *dispersion < *maxval )
2676  {
2677  sinfo_msg_error(" given number of rows too small!\n");
2678  return NULL ;
2679  }*/
2680  if ( (*maxval - *minval) / *dispersion < (float)cly )
2681  {
2682  sinfo_msg_error(" must be something wrong with the wavelength map!\n");
2683  return NULL ;
2684  }
2685 
2686  /* determine the central pixel and the lambda in the first image row */
2687  *n_rows = floor(floor(0.5+(*maxval - *minval) / *dispersion)/2+0.5)*2;
2688  *centralpix = *n_rows / 2 ;
2689  minLambda = *centralLambda - *dispersion * (float)*centralpix ;
2690  /*if ( (minLambda + *dispersion * n_rows) < *maxval )
2691  {
2692  sinfo_msg_error(" not enough rows defined \n");
2693  return NULL ;
2694  }
2695  if ( minLambda > *minval )
2696  {
2697  sinfo_msg_error(" not enough rows defined \n");
2698  return NULL ;
2699  }*/
2700 
2701  /* allocate memory */
2702  if ( NULL == ( retImage = cpl_image_new( ilx, *n_rows,CPL_TYPE_FLOAT ) ))
2703  {
2704  sinfo_msg_error(" cannot allocate a new image\n");
2705  return NULL ;
2706  }
2707  podata=cpl_image_get_data_float(retImage);
2708  olx=cpl_image_get_size_x(retImage);
2709  oly=cpl_image_get_size_y(retImage);
2710  /* now go through the columns */
2711  retimagecol = cpl_malloc(*n_rows * sizeof(retimagecol[0]));
2712  calcolpos = cpl_malloc(*n_rows * sizeof(calcolpos[0]));
2713  for ( col = 0 ; col < olx ; col++ )
2714  {
2715  /*------------------------------------------------------------------
2716  * copy the columns of the source image and the wavemap image into
2717  * buffer arrays to speed things up
2718  */
2719  sum = 0. ;
2720  for ( row = 0 ; row < ily ; row++ )
2721  {
2722  imagecol[row] = pidata[col + row*ilx] ;
2723  if (!isnan(imagecol[row]))
2724  {
2725  sum += imagecol[row] ;
2726  }
2727  calcol[row] = pcdata[col + row*clx] ;
2728  }
2729 
2730  for ( row = 0 ; row < oly ; row++ )
2731  {
2732  retimagecol[row] = 0. ;
2733  calcolpos[row] = -1;
2734  }
2735 
2736  for ( row=0 ; row < cly ; row++)
2737  {
2738  temprow = (calcol[row]- minLambda)/ *dispersion;
2739  if (temprow >= 0 && temprow < oly)
2740  calcolpos[(int) temprow] = row;
2741  }
2742 
2743  zeroind = 0 ;
2744 
2745 
2746  for ( row = 0 ; row < oly ; row++ )
2747  {
2748  lambda = minLambda + *dispersion * (float) row ;
2749 
2750  /*---------------------------------------------------------------
2751  * lambda must lie between the two available wavelength extremes
2752  * otherwise the image pixels are set to ZERO
2753  */
2754  if ( row < cly )
2755  {
2756  if ( isnan(calcol[row]) )
2757  {
2758  zeroind = 1 ;
2759  }
2760  }
2761 
2762  if ( (lambda < calcol[0]) ||
2763  (lambda > calcol[(cly)-1]) || zeroind == 1 )
2764  {
2765  retimagecol[row] = ZERO ;
2766  continue ;
2767  }
2768  /*testrow = 0 ;
2769  while ( lambda > calcol[testrow] )
2770  {
2771  testrow++ ;
2772  }*/
2773  if (calcolpos[row]==-1) {
2774  if(row>= (*n_rows-1)) calcolpos[row] = calcolpos[row-1];
2775  if(row< (*n_rows-1)) calcolpos[row] = calcolpos[row+1];
2776  }
2777  if(calcolpos[row]>0) {
2778  if (lambda-calcol[calcolpos[row]-1]==0.) {
2779  calcolpos[row]=calcolpos[row]-1;
2780  }
2781  }
2782  testrow = calcolpos[row];
2783 
2784  /*-----------------------------------------------------------------
2785  * at this point calcol[testrow-1] < lambda <= calcol[testrow]
2786  * now determine the box position in which the polint fit is
2787  carried through.
2788  * the half width of the box is half the number of fit parameters.
2789  * Now we determine the start position of the fitting box and treat
2790  * the special case of being near the sinfo_edge.
2791  */
2792 
2793  if ( n_params % 2 == 0 )
2794  {
2795  half_width = (int)(n_params/2) - 1 ;
2796  }
2797  else
2798  {
2799  half_width = (int)(n_params/2) ;
2800  }
2801 
2802 
2803  if ( isnan(imagecol[testrow]) )
2804  {
2805  for ( i = row-half_width ; i < row-half_width+n_params ; i++ )
2806  {
2807  if (i < 0) continue ;
2808  if ( i >= oly ) continue ;
2809  retimagecol[i] = ZERO ;
2810  }
2811  imagecol[testrow] = 0. ;
2812  }
2813 
2814  }
2815 
2816  /* now loop over the rows and establish the lambda for each row */
2817  new_sum = 0. ;
2818  for ( row = 0 ; row < oly ; row++ )
2819  {
2820  if ( isnan(retimagecol[row]) )
2821  {
2822  continue ;
2823  }
2824  lambda = minLambda + *dispersion * (float) row ;
2825 
2826  /*---------------------------------------------------------------
2827  * lambda must lie between the two available wavelength extremes
2828  * otherwise the image pixels are set to ZERO
2829  */
2830  if ( (lambda < calcol[0]) || (lambda > calcol[(cly)-1]) )
2831  {
2832  retimagecol[row] = ZERO ;
2833  continue ;
2834  }
2835  /*testrow = 0 ;
2836  while ( lambda > calcol[testrow] )
2837  {
2838  testrow++ ;
2839  }*/
2840  if (calcolpos[row]==-1) {
2841  if(row >= (*n_rows-1)) calcolpos[row] = calcolpos[row-1];
2842  if(row < (*n_rows-1)) calcolpos[row] = calcolpos[row+1];
2843  }
2844 
2845  testrow = calcolpos[row];
2846 
2847  /*--------------------------------------------------------------
2848  * at this point calcol[testrow-1] < lambda <= calcol[testrow]
2849  * now determine the box position in which the polynomial
2850  interpolation is carried through.
2851  * the half width of the box is half the number of fit parameters.
2852  * Now we determine the start position of the fitting box and treat
2853  * the special case of being near the sinfo_edge.
2854  */
2855 
2856  if ( n_params % 2 == 0 )
2857  {
2858  half_width = (int)(n_params/2) - 1 ;
2859  }
2860  else
2861  {
2862  half_width = (int)(n_params/2) ;
2863  }
2864 
2865  firstpos = testrow - half_width ;
2866  if ( firstpos < 0 )
2867  {
2868  firstpos = 0 ;
2869  }
2870  else if ( firstpos > ((cly)-n_params) )
2871  {
2872  firstpos = cly - n_params ;
2873  }
2874  if ( isnan(imagecol[firstpos]) )
2875  {
2876  retimagecol[row] = ZERO ;
2877  continue ;
2878  }
2879 
2880 
2881  /* we must rescale the x-values (smaller than 1)
2882  for the fitting routine */
2883  dif = calcol[firstpos+n_params-1] - calcol[firstpos] ;
2884  for ( i = 0 ; i < n_params ; i++ )
2885  {
2886  x_renorm[i] = (calcol[firstpos + i] - calcol[firstpos]) / dif ;
2887  }
2888 
2889 
2890  lambda_renorm = ( lambda - calcol[firstpos] ) / dif ;
2891 
2892  imageptr = &imagecol[firstpos] ;
2893 
2894  flag = 0;
2895  poly=sinfo_new_nev_ille(x_renorm, imageptr,
2896  n_params-1, lambda_renorm, &flag);
2897 
2898  new_sum += poly ;
2899  retimagecol[row] = poly ;
2900  }
2901 
2902  /* now renorm the total flux */
2903  for ( row = 0 ; row < oly ; row++ )
2904  {
2905  if ( new_sum == 0. ) new_sum = 1. ;
2906  if ( isnan(retimagecol[row]) )
2907  {
2908  podata[col+row*olx] = ZERO ;
2909  }
2910  else
2911  {
2912  /* rescaling is commented out because it delivers wrong results
2913  in case of appearance of blanks or bad pixels */
2914  podata[col+row*olx] = retimagecol[row] /* * sum/new_sum*/ ;
2915  }
2916  }
2917 
2918  }
2919  cpl_free(retimagecol);
2920  cpl_free(calcolpos);
2921  cpl_free(imagecol) ;
2922  cpl_free(calcol) ;
2923  cpl_free(x_renorm) ;
2924 
2925  return retImage ;
2926 }
2927 
2929 /*___oOo___*/