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