SINFONI Pipeline Reference Manual  2.5.2
sinfo_wavecal.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 22/01/02 created
27  */
28 
29 /************************************************************************
30  * NAME
31  * sinfo_wavecal.c -
32  * routines needed for wavelength calibration with smoothing only
33  * within the slitlets
34  *
35  * SYNOPSIS
36  * 1) Bcoeffs * sinfo_new_b_coeffs( int n_slitlets,
37  * int n_acoeffs,
38  * int n_bcoeffs )
39  * 2) void sinfo_new_destroy_b_coeffs ( Bcoeffs * bco )
40  * 3) int sinfo_new_coeffs_cross_slit_fit ( int n_columns,
41  * float ** acoefs,
42  * float ** dacoefs,
43  * Bcoeffs* bco,
44  * float sigma_factor,
45  * float dispersion,
46  * float pixel_dist,
47  * float * chisq )
48  * 4) cpl_image * sinfo_new_wave_map_slit ( float ** acoefs,
49  * int n_acoefs,
50  * int n_rows,
51  * int n_columns )
52  * 5) cpl_image * sinfo_new_wave_cal( cpl_image * image,
53  * FitParams ** par ,
54  * float ** abuf,
55  * int n_slitlets,
56  * int ** row_clean,
57  * float ** wavelength_clean,
58  * int * n_found_lines,
59  * float dispersion,
60  * int halfWidth,
61  * float minAmplitude,
62  * float max_residual,
63  * float fwhm,
64  * int n_a_fitcoefs,
65  * int n_b_fitcoefs,
66  * float sigmaFactor,
67  * float pixel_dist )
68  * 6) int sinfo_new_check_for_fake_lines ( FitParams ** par,
69  * float dispersion,
70  * float ** wavelength_clean,
71  * int ** row_clean,
72  * int * n_found_lines,
73  * int n_columns,
74  * float pixel_tolerance )
75  * 7) cpl_image * sinfo_new_create_shifted_slit_wavemap ( cpl_image * lineIm,
76  * float ** coeffs,
77  * int n_fitcoeffs,
78  * float * wavelength,
79  * float * intensity,
80  * int n_lines,
81  * int magFactor )
82  *
83  * DESCRIPTION
84  * 1) allocates memory for a new array of
85  * Bcoeffs data structures
86  * 2) frees memory of an array of Bcoeffs data structures
87  * 3) Fits each single polynomial coefficient acoefs resulting from
88  sinfo_polyfit
89  * across the columns of each slitlet and use the result of this fit to
90  * smooth the acoefs.
91  * 4) builds a new wavelength calibration map as fits image
92  * by using the fit coeficients.
93  * 5) this routine takes an image from a calibration
94  * emission lamp and delivers the smoothed fit coefficients of
95  * a polynomial fit along the columns of the line positions as output.
96  * This routine expects Nyquist sampled spectra
97  * (either an interleaved image or an image convolved with an
98  * appropriate function in spectral direction)
99  * 6) this routine searches for successfully fitted fake lines like
100  * bad pixels by comparing the found line positons with
101  * estimated template positions. This routine should be
102  * inserted in the wavelength calibration routine just after
103  * the sinfo_fitLines() routine.
104  * 7) This routine cross-correlates a shifted emission line frames
105  * and determines the shift to the old one which is given by
106  * its polynomial coefficients.
107  * Then the a0 coefficients is recalculated and afterwards
108  * a new wavelength calibration map is generated using the
109  * already calculated smoothed polynomial coefficients.
110  *
111  * FILES
112  *
113  * ENVIRONMENT
114  *
115  * RETURN VALUES
116  *
117  * CAUTIONS
118  *
119  * EXAMPLES
120  *
121  * SEE ALSO
122  *
123  * BUGS
124  *
125  *------------------------------------------------------------------------
126  */
127 
128 #ifdef HAVE_CONFIG_H
129 # include <config.h>
130 #endif
131 #include "sinfo_vltPort.h"
132 #include <math.h>
133 
134 /*
135  * System Headers
136  */
137 /*
138  * Local Headers
139  */
140 
141 #include "sinfo_function_1d.h"
142 #include "sinfo_recipes.h"
143 #include "sinfo_wavecal.h"
144 #include "sinfo_wave_calibration.h"
145 #include "sinfo_solve_poly_root.h"
146 #include "sinfo_utils_wrappers.h"
147 #include "sinfo_error.h"
148 
149 #include "sinfo_svd.h"
150 /*
151  * Private functions prototype
152  */
153 static Bcoeffs *
154 sinfo_new_b_coeffs( int n_slitlets,
155  int n_acoeffs,
156  int n_bcoeffs ) ;
157 
158 static void
159 sinfo_new_destroy_b_coeffs ( Bcoeffs * bco ) ;
160 
161 static int
162 sinfo_new_coeffs_cross_slit_fit ( int n_columns,
163  float ** acoefs,
164  float ** dacoefs,
165  Bcoeffs* bco,
166  float sigma_factor,
167  float dispersion,
168  float pixel_dist,
169  float * chisq ) ;
170 
171 
172 static int
173 sinfo_new_spred_coeffs_cross_slit_fit ( int n_columns,
174  float ** acoefs,
175  float ** dacoefs,
176  Bcoeffs* bco,
177  float sigma_factor,
178  float dispersion,
179  float pixel_dist,
180  float * chisq,
181  float ** sinfo_slit_pos) ;
182 /*
183  * function definitions
184  */
200 static Bcoeffs *
201 sinfo_new_b_coeffs( int n_slitlets,
202  int n_acoeffs,
203  int n_bcoeffs )
204 {
205  int i, n ;
206  Bcoeffs * returnbco ;
207 
208  if(NULL == (returnbco=(Bcoeffs*) cpl_calloc(n_slitlets, sizeof(Bcoeffs))) )
209  {
210  sinfo_msg_error ("could not allocate memory") ;
211  return NULL ;
212  }
213  returnbco -> n_slitlets = n_slitlets ;
214  returnbco -> n_acoeffs = n_acoeffs ;
215  returnbco -> n_bcoeffs = n_bcoeffs ;
216  for ( i = 0 ; i < n_slitlets ; i++ )
217  {
218  returnbco[i].slitlet = i ;
219  if ( NULL == (returnbco[i].b = (float**)cpl_calloc(n_acoeffs,
220  sizeof(float*)) ) )
221  {
222  sinfo_msg_error ("could not allocate memory") ;
223  return NULL ;
224  }
225  for ( n = 0 ; n < n_acoeffs ; n++ )
226  {
227  if ( NULL == (returnbco[i].b[n] = (float*)cpl_calloc(n_bcoeffs,
228  sizeof(float))) )
229  {
230  sinfo_msg_error ("could not allocate memory") ;
231  return NULL ;
232  }
233  }
234  }
235  return returnbco ;
236 }
237 
245 static void
246 sinfo_new_destroy_b_coeffs ( Bcoeffs * bco )
247 {
248  int i, n ;
249 
250  for ( i = 0 ; i < bco->n_slitlets ; i++ )
251  {
252  for ( n = 0 ; n < bco->n_acoeffs ; n++ )
253  {
254  cpl_free (bco[i].b[n]) ;
255  }
256  cpl_free(bco[i].b) ;
257  }
258 
259  cpl_free (bco) ;
260 }
261 
287 static int
288 sinfo_new_coeffs_cross_slit_fit ( int n_columns,
289  float ** acoefs,
290  float ** dacoefs,
291  Bcoeffs* bco,
292  float sigma_factor,
293  float dispersion,
294  float pixel_dist,
295  float * chisq )
296 {
297  float col_index;
298  float ** ucoefs, **vcoefs, **covar ;
299  float * acoefsclean ;
300  double sum, sumq, mean ;
301  double sigma ;
302  double cliphi, cliplo ;
303  float offset ;
304  float threshold ;
305  float* sub_col_index=NULL ;
306  float* sub_acoefs=NULL;
307  float* sub_dacoefs=NULL ;
308  float* wcoefs=NULL ;
309  int* edge=NULL ;
310 
311  int ed1, ed2 ;
312  int i, n, num, ndata ;
313  int nc, ns ;
314  int loc_index ;
315  int last_i=PIXEL;
316 
317  if ( n_columns < 1 )
318  {
319  sinfo_msg_error("wrong number of image columns given") ;
320  return -1 ;
321  }
322  if ( acoefs == NULL || dacoefs == NULL )
323  {
324  sinfo_msg_error("acoeffs or errors of coefficients are not given") ;
325  return -1 ;
326  }
327  if ( bco == NULL )
328  {
329  sinfo_msg_error("bcoeffs are not allocated") ;
330  return -1 ;
331  }
332  if ( sigma_factor <= 0. )
333  {
334  sinfo_msg_error("impossible sigma_factor given!") ;
335  return -1 ;
336  }
337  if ( dispersion == 0. )
338  {
339  sinfo_msg_error("impossible dispersion given!") ;
340  return -1 ;
341  }
342 
343  /*-------------------------------------------------------------------------
344  * search for the slitlet edges by comparing the a0 coefficients along
345  the columns if a bigger deviation occurrs it is assumed that there
346  is an edge.
347  */
348 
349  edge=cpl_calloc(bco->n_slitlets,sizeof(int)) ;
350  wcoefs=cpl_calloc(bco->n_bcoeffs,sizeof(float)) ;
351 
352  n = 0 ;
353  threshold = pixel_dist * fabs(dispersion) ;
354  for ( i = PIXEL ; i < n_columns - PIXEL ; )
355  {
356  if ( !isnan(acoefs[0][i+1]) &&
357  acoefs[0][i+1] != 0. &&
358  acoefs[0][i] != 0. &&
359  dacoefs[0][i+1] != 0.)
360  {
361  if ( isnan(acoefs[0][i]) || acoefs[0][i] == 0. )
362  {
363  if (fabs(acoefs[0][i+1] - acoefs[0][i-1]) >= threshold )
364  {
365  if( (i-last_i) < 60 && (i > 80) ) {
366  sinfo_msg_warning("skip1 i=%d diff=%d\n",i,i-last_i);
367  goto skip;
368  } else {
369  /*
370  sinfo_msg("diff1=%f i=%d threshold-%f size=%d\n",
371  fabs(acoefs[0][i+1] - acoefs[0][i-1]),i,
372  threshold,i-last_i);
373  */
374  edge[n] = i+1 ;
375  //sinfo_msg("1found edge: %d",edge[n]);
376  n++ ;
377  last_i = i;
378  i += PIXEL ;
379  }
380  }
381  }
382  else
383  {
384  if ((fabs(acoefs[0][i+1] - acoefs[0][i]) >= threshold) ||
385  (i-last_i) > 63 )
386  {
387  if( (i-last_i) < 60 && ((i> 80) || (i<PIXEL+2))) {
388  sinfo_msg_warning("skip2 i=%d diff=%d\n",i,i-last_i);
389  goto skip;
390  } else {
391 
392  /*
393  sinfo_msg_warning("diff2=%f i=%d threshold-%f size=%d",
394  fabs(acoefs[0][i+1] - acoefs[0][i]),
395  i,threshold,i-last_i);
396  */
397 
398 
399 
400  edge[n] = i+1 ;
401  //sinfo_msg("2found edge: %d",edge[n]);
402  n++ ;
403  last_i = i;
404  i += PIXEL ;
405  }
406  }
407  }
408  /* sometimes a slitlet may be lost due to divergences in acoeffs[0]
409  we try to recover it */
410  if( ( (i-last_i) > 63 ) &&
411  ( isnan(fabs(acoefs[0][i+1] - acoefs[0][i])) ||
412  isnan(fabs(acoefs[0][i+1] - acoefs[0][i-1])) ) )
413  {
414  edge[n] = i+1 ;
415  //sinfo_msg("3found edge: %d",edge[n]);
416  n++ ;
417  last_i = i;
418  sinfo_msg_warning("recovered slitlet edge i=%d",i);
419  i += PIXEL ;
420 
421  }
422  }
423  skip:
424  i++ ;
425  }
426  /*
427  printf("X min %d max %d last %d\n", PIXEL, n_columns - PIXEL, i);
428  printf("n=%d check=%d\n",n,bco->n_slitlets - 1);
429  */
430  if ( n != bco->n_slitlets - 1 )
431  {
432  sinfo_msg_error("could not find the right number "
433  "of slitlets, found: %d",n+1) ;
434  return -1 ;
435  }
436 
437  sub_col_index=cpl_calloc(n_columns,sizeof(float)) ;
438  sub_acoefs=cpl_calloc(n_columns,sizeof(float));
439  sub_dacoefs=cpl_calloc(n_columns,sizeof(float)) ;
440 
441  /* go through the coefficents indices */
442  for ( loc_index = 0 ; loc_index < bco->n_acoeffs ; loc_index++ )
443  {
444  /* go through the single slitlets */
445  for ( ns = 0 ; ns < bco->n_slitlets ; ns++ )
446  {
447  /* determine the slitlet edges */
448  if ( ns == 0 )
449  {
450  ed1 = 0 ;
451  ed2 = edge[0] ;
452  }
453  else if ( ns == bco->n_slitlets - 1 )
454  {
455  ed1 = edge[bco->n_slitlets - 2] ;
456  ed2 = n_columns ;
457  }
458  else
459  {
460  ed1 = edge[ns-1] ;
461  ed2 = edge[ns] ;
462  }
463 
464  nc = 0 ;
465  for ( i = ed1 ; i < ed2 ; i++ )
466  {
467  if ( isnan(acoefs[loc_index][i]) ||
468  acoefs[loc_index][i] == 0. ||
469  dacoefs[loc_index][i] == 0. )
470  {
471  continue ;
472  }
473  else
474  {
475  nc++ ;
476  }
477  }
478  if (NULL==(acoefsclean = (float*) cpl_calloc(nc , sizeof(float))) )
479  {
480  sinfo_msg_error("could not allocate memory for acoefsclean!") ;
481  return -1 ;
482  }
483  nc = 0 ;
484  for ( i = ed1 ; i < ed2 ; i++ )
485  {
486  if ( isnan(acoefs[loc_index][i]) ||
487  acoefs[loc_index][i] == 0. ||
488  dacoefs[loc_index][i] == 0. )
489  {
490  continue ;
491  }
492  else
493  {
494  acoefsclean[nc] = acoefs[loc_index][i] ;
495  nc++ ;
496  }
497  }
498 
499  /* ----------------------------------------------------------
500  * determine the clean mean and sigma value of the coefficients,
501  * that means reject 10 % of the extreme low and high values
502  */
503  sinfo_pixel_qsort(acoefsclean, nc) ;
504 
505  sum = 0. ;
506  sumq = 0. ;
507  mean = 0. ;
508  sigma = 0. ;
509  n = 0 ;
510  for ( i = (int)((float)nc*LOW_REJECT) ;
511  i < (int)((float)nc*HIGH_REJECT) ; i++ )
512  {
513  sum += (double)acoefsclean[i] ;
514  sumq += ((double)acoefsclean[i] * (double)acoefsclean[i]) ;
515  n ++ ;
516  }
517  mean = sum/(double)n ;
518  sigma = sqrt( sumq/(double)n - (mean * mean) ) ;
519  cliphi = mean + sigma * (double)sigma_factor ;
520  cliplo = mean - sigma * (double)sigma_factor ;
521  /* fit only the reasonnable values */
522  num = 0 ;
523  col_index = 0 ;
524  /*
525  printf("ed1=%d ed2=%d\n",ed1,ed2);
526  */
527  for ( i = ed1 ; i < ed2 ; i++ )
528  {
529  /* take only the reasonnable coefficients */
530  /*
531  printf("acoeffs=%f dacoefs=%f cliphi=%f cliplo=%f\n",
532  acoefs[loc_index][i],dacoefs[loc_index][i],cliphi,cliplo);
533  */
534  if ( !isnan(acoefs[loc_index][i]) &&
535  (acoefs[loc_index][i] <= cliphi) &&
536  (acoefs[loc_index][i] >= cliplo) &&
537  (dacoefs[loc_index][i] != 0. ) &&
538  (acoefs[loc_index][i] != 0.) )
539  {
540  sub_acoefs[num] = acoefs[loc_index][i] ;
541  sub_dacoefs[num] = dacoefs[loc_index][i] ;
542  sub_col_index[num] = col_index ;
543  num ++ ;
544  }
545  col_index++ ;
546  }
547  ndata = num ;
548  offset = (float)(col_index-1) / 2. ;
549  /* printf("ndata=%d bco->n_bcoeffs=%d\n",ndata,bco->n_bcoeffs); */
550 
551  if ( ndata < bco->n_bcoeffs )
552  {
553  sinfo_msg_error("not enough data found in slitlet %d to "
554  "determine the fit coefficients.", ns) ;
555  cpl_free(acoefsclean) ;
556  return -1 ;
557  }
558 
559  /* allocate coefficient matrices */
560  ucoefs = sinfo_matrix(1, ndata, 1, bco->n_bcoeffs) ;
561  vcoefs = sinfo_matrix(1, ndata, 1, bco->n_bcoeffs) ;
562  covar = sinfo_matrix(1, bco->n_bcoeffs, 1, bco->n_bcoeffs) ;
563 
564  /* scale the x-values for the fit */
565  for ( i = 0 ; i < ndata ; i++ )
566  {
567  sub_col_index[i] = (sub_col_index[i] - offset) / offset ;
568  }
569 
570  /* finally, do the singular value decomposition fit */
571  sinfo_svd_fitting ( sub_col_index-1, sub_acoefs-1,
572  sub_dacoefs-1, ndata, bco[ns].b[loc_index]-1,
573  bco->n_bcoeffs, ucoefs, vcoefs,
574  wcoefs-1, covar, &chisq[ns], sinfo_fpol ) ;
575 
576  /* scale the found coefficients */
577  for ( i = 0 ; i < bco->n_bcoeffs ; i ++ )
578  {
579  bco[ns].b[loc_index][i] /= pow( offset, i ) ;
580  }
581 
582  /* free memory */
583  cpl_free (acoefsclean) ;
584  sinfo_free_matrix( ucoefs, 1/*, ndata*/, 1/*, bco->n_bcoeffs */) ;
585  sinfo_free_matrix( vcoefs, 1/*, ndata*/, 1/*, bco->n_bcoeffs */) ;
586  sinfo_free_matrix( covar, 1/*, bco->n_bcoeffs*/,
587  1/*, bco->n_bcoeffs */) ;
588 
589  /* now calculate the smoothed acoefs for each column */
590  col_index = 0 ;
591  for ( i = ed1 ; i < ed2 ; i++ )
592  {
593  acoefs[loc_index][i] = 0. ;
594  for ( n = 0 ; n < bco->n_bcoeffs ; n++ )
595  {
596  acoefs[loc_index][i] += bco[ns].b[loc_index][n] *
597  pow(col_index - offset, n) ;
598  }
599  col_index++ ;
600  }
601 
602  }
603  }
604 
605  cpl_free(sub_col_index) ;
606  cpl_free(sub_acoefs) ;
607  cpl_free(sub_dacoefs) ;
608 
609 
610  cpl_free(edge) ;
611  cpl_free(wcoefs) ;
612 
613  return 0 ;
614 }
615 
616 
629 cpl_image * sinfo_new_wave_map_slit ( float ** acoefs,
630  int n_acoefs,
631  int n_rows,
632  int n_columns )
633 {
634  cpl_image * newIm=NULL ;
635  float lambda=0 ;
636  float offset=0 ;
637  int col=0;
638  int row=0 ;
639  int i=0 ;
640  float row_index=0 ;
641  float* podata=NULL;
642  if ( NULL == acoefs )
643  {
644  sinfo_msg_error (" no coefficient sinfo_matrix given!") ;
645  return NULL ;
646  }
647 
648  /* allocate new image */
649  if ( NULL == (newIm = cpl_image_new(n_columns , n_rows,CPL_TYPE_FLOAT)) )
650  {
651  sinfo_msg_error ("could not allocate new image!") ;
652  return NULL ;
653  }
654  podata=cpl_image_get_data_float(newIm);
655 
656  /* make the parabola symmetric to the image */
657  offset = (float)(n_rows - 1) / 2. ;
658 
659  /* go through the rows */
660  for ( col = 0 ; col < n_columns ; col++ )
661  {
662  /* go through the columns */
663  for ( row = 0 ; row < n_rows ; row++ )
664  {
665  lambda = 0. ;
666  row_index = (float)row - offset ;
667  for ( i = 0 ; i < n_acoefs ; i++ )
668  {
669  lambda += acoefs[i][col] * pow(row_index, i) ;
670  }
671  podata[col+row*n_columns] = lambda ;
672  }
673  }
674  return newIm ;
675 }
676 
677 
724 cpl_image * sinfo_new_wave_cal( cpl_image * image,
725  FitParams ** par ,
726  float ** abuf,
727  int n_slitlets,
728  int ** row_clean,
729  float ** wavelength_clean,
730  int * n_found_lines,
731  float dispersion,
732  int halfWidth,
733  float minAmplitude,
734  float max_residual,
735  float fwhm,
736  int n_a_fitcoefs,
737  int n_b_fitcoefs,
738  float sigmaFactor,
739  float pixel_dist,
740  float pixel_tolerance )
741 
742 {
743  int i=0, j=0;
744  /* int k=0 ; */
745  int n_fit=0 ;
746  int n_reject=0 ;
747  float * acoefs=NULL ;
748  float * dacoefs=NULL ;
749  float ** dabuf=NULL ;
750  float chisq_poly=0 ;
751  float * chisq_cross=NULL ;
752  int zeroind=0 ;
753  int crossInd=0 ;
754  Bcoeffs * bco=NULL ;
755  cpl_image * wavemap=NULL ;
756  int ilx=0;
757  int ily=0;
758  /* float* pidata=NULL; */
759 
760 
761  if ( NULL == image )
762  {
763  sinfo_msg_error("no image given") ;
764  return NULL ;
765  }
766  check_nomsg(ilx=cpl_image_get_size_x(image));
767  check_nomsg(ily=cpl_image_get_size_y(image));
768  /* check_nomsg(pidata=cpl_image_get_data_float(image)); */
769 
770  if ( par == NULL )
771  {
772  sinfo_msg_error("no fit parameter data structure given") ;
773  return NULL ;
774  }
775  if ( abuf == NULL )
776  {
777  sinfo_msg_error("no buffer for fit coefficients given") ;
778  return NULL ;
779  }
780  if ( n_slitlets <= 0 )
781  {
782  sinfo_msg_error("impossible number of slitlets given") ;
783  return NULL ;
784  }
785  if ( row_clean == NULL )
786  {
787  sinfo_msg_error("no row_clean array given") ;
788  return NULL ;
789  }
790  if ( wavelength_clean == NULL )
791  {
792  sinfo_msg_error("no wavelength_clean array given") ;
793  return NULL ;
794  }
795 
796  if ( dispersion == 0. )
797  {
798  sinfo_msg_error("impossible dispersion given") ;
799  return NULL ;
800  }
801 
802  if ( halfWidth <= 0 || halfWidth > ily/2 )
803  {
804  sinfo_msg_error("impossible half width of the fitting box given") ;
805  return NULL ;
806  }
807  if ( minAmplitude < 1. )
808  {
809  sinfo_msg_error("impossible minimal amplitude") ;
810  return NULL ;
811  }
812 
813  if ( max_residual <= 0. || max_residual > 1. )
814  {
815  sinfo_msg_error("impossible max_residual given") ;
816  return NULL ;
817  }
818  if ( fwhm <= 0. || fwhm > 10. )
819  {
820  sinfo_msg_error("impossible fwhm given") ;
821  return NULL ;
822  }
823 
824  if ( n_a_fitcoefs <= 0 || n_a_fitcoefs > 9 )
825  {
826  sinfo_msg_error("unrealistic n_a_fitcoefs given") ;
827  return NULL ;
828  }
829 
830  if ( n_b_fitcoefs <= 0 || n_b_fitcoefs > 9 )
831  {
832  sinfo_msg_error("unrealistic n_b_fitcoefs given") ;
833  return NULL ;
834  }
835  if ( sigmaFactor <= 0. )
836  {
837  sinfo_msg_error("impossible sigmaFactor given") ;
838  return NULL ;
839  }
840 
841  /* initialize the variables */
842  n_reject = 0 ;
843  n_fit = 0 ;
844 
845 
846  /* fit each found line by using a Gaussian function and determine
847  the exact position */
848  if ( 0 > (n_fit = sinfo_new_fit_lines( image , par, fwhm, n_found_lines,
849  row_clean, wavelength_clean,
850  halfWidth, minAmplitude )) )
851  {
852  sinfo_msg_error("cannot fit the lines, error code of "
853  "sinfo_fitLines: %d", n_fit) ;
854  return NULL ;
855  }
856 
857  /* first check for faked lines like bad pixels */
858  if ( -1 == sinfo_new_check_for_fake_lines (par, dispersion,
859  wavelength_clean,
860  row_clean, n_found_lines,
861  ilx, pixel_tolerance) )
862  {
863  sinfo_msg_error("cannot fit the lines, error code of "
864  "sinfo_fitLines: %d", n_fit) ;
865  return NULL ;
866  }
867 
868  /* allocate memory */
869  if (NULL == (acoefs = (float*) cpl_calloc(n_a_fitcoefs, sizeof(float))) ||
870  NULL == (dacoefs = (float*) cpl_calloc(n_a_fitcoefs, sizeof(float))) ||
871  NULL == (dabuf = (float**) cpl_calloc(n_a_fitcoefs, sizeof(float*))) ||
872  NULL == (chisq_cross = (float*) cpl_calloc(n_slitlets, sizeof(float))))
873  {
874  sinfo_msg_error("cannot allocate memory\n") ;
875  return NULL ;
876  }
877  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
878  {
879  if ( NULL == (dabuf[i] = (float*) cpl_calloc(ilx, sizeof(float))) )
880  {
881  sinfo_msg_error("cannot allocate memory") ;
882  sinfo_free_float (&acoefs ) ;
883  sinfo_free_float ( &dacoefs ) ;
884  sinfo_free_float ( &chisq_cross ) ;
885  sinfo_free_float_array(&dabuf,n_a_fitcoefs) ;
886  return NULL ;
887  }
888  }
889 
890 
891  /* fit wavelengths to the corresponding found positions for each column */
892  /* k = 0 ; */
893  for ( i = 0 ; i < ilx ; i++ )
894  {
895  zeroind = 0 ;
896  if ( FLT_MAX == (chisq_poly = sinfo_new_polyfit( par, i,
897  n_found_lines[i],
898  ily, dispersion,
899  max_residual, acoefs,
900  dacoefs, &n_reject,
901  n_a_fitcoefs)) )
902  {
903  /*
904  sinfo_msg_warning ("error in sinfo_polyfit in column: %d\n", i) ;
905  */
906  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
907  {
908  acoefs[j] = ZERO ;
909  dacoefs[j] = ZERO ;
910  }
911  }
912 
913  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
914  {
915 
916  if ( acoefs[0] <= 0. || acoefs[1] ==0. ||
917  dacoefs[j] == 0. || isnan(acoefs[j]) )
918  {
919  zeroind = 1 ;
920  }
921  }
922  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
923  {
924  if ( zeroind == 0 )
925  {
926  abuf[j][i] = acoefs[j] ;
927  dabuf[j][i] = dacoefs[j] ;
928  }
929  else
930  {
931  abuf[j][i] = ZERO ;
932  dabuf[j][i] = ZERO ;
933  }
934  }
935  }
936 
937  /* allocate memory for the fitting coefficients */
938  if ( NULL == ( bco = sinfo_new_b_coeffs( n_slitlets,
939  n_a_fitcoefs, n_b_fitcoefs)) )
940  {
941  sinfo_msg_error ("cannot allocate memory for the bcoeffs") ;
942  sinfo_free_float_array(&dabuf,n_a_fitcoefs) ;
943  sinfo_free_float (&acoefs ) ;
944  sinfo_free_float (&dacoefs ) ;
945  sinfo_free_float (&chisq_cross ) ;
946  return NULL ;
947  }
948 
949  /* fit each acoefs across the slitlets to smooth the result */
950  if ( -1 == ( crossInd = sinfo_new_coeffs_cross_slit_fit( ilx,
951  abuf,
952  dabuf,
953  bco,
954  sigmaFactor,
955  dispersion,
956  pixel_dist,
957  chisq_cross )) )
958  {
959  sinfo_msg_error ("cannot carry out the fitting of "
960  "coefficients across the columns") ;
961  sinfo_free_float_array(&dabuf,n_a_fitcoefs) ;
962  sinfo_free_float (&acoefs ) ;
963  sinfo_free_float (&dacoefs ) ;
964  sinfo_free_float (&chisq_cross ) ;
965  return NULL ;
966  }
967 
968 
969  if ( NULL == (wavemap = sinfo_new_wave_map_slit (abuf, n_a_fitcoefs,
970  ily, ilx)) )
971  {
972  sinfo_msg_error ("cannot carry out wavemap creation") ;
973  sinfo_free_float_array(&dabuf,n_a_fitcoefs) ;
974  sinfo_free_float (&acoefs ) ;
975  sinfo_free_float (&dacoefs ) ;
976  sinfo_free_float (&chisq_cross ) ;
977  sinfo_new_destroy_b_coeffs(bco) ;
978  return NULL ;
979  }
980 
981  /* free all allocated memory */
982  sinfo_free_float_array(&dabuf,n_a_fitcoefs) ;
983  sinfo_free_float (&acoefs ) ;
984  sinfo_free_float (&dacoefs ) ;
985  sinfo_free_float (&chisq_cross ) ;
986  sinfo_new_destroy_b_coeffs(bco) ;
987 
988  return wavemap ;
989  cleanup:
990  sinfo_free_float (&acoefs ) ;
991  sinfo_free_float ( &dacoefs ) ;
992  sinfo_free_float ( &chisq_cross ) ;
993  sinfo_free_float_array(&dabuf,n_a_fitcoefs) ;
994  sinfo_new_destroy_b_coeffs(bco) ;
995  return NULL;
996 }
997 
998 
999 
1022 int sinfo_new_check_for_fake_lines ( FitParams ** par,
1023  float dispersion,
1024  float ** wavelength_clean,
1025  int ** row_clean,
1026  int * n_found_lines,
1027  int n_columns,
1028  float pixel_tolerance )
1029 {
1030  int i, k ;
1031  int col ;
1032  int found ;
1033  float row ;
1034  float * beginWave ;
1035  float firstWave ;
1036 
1037  if ( par == NULL )
1038  {
1039  sinfo_msg_error("no fit parameter data structure given") ;
1040  return -1 ;
1041  }
1042  if ( dispersion == 0. )
1043  {
1044  sinfo_msg_error("dispersion zero given!") ;
1045  return -1 ;
1046  }
1047  if ( wavelength_clean == NULL )
1048  {
1049  sinfo_msg_error("no wavelength array given!") ;
1050  return -1 ;
1051  }
1052  if ( row_clean == NULL )
1053  {
1054  sinfo_msg_error("no row array given!") ;
1055  return -1 ;
1056  }
1057  if ( n_found_lines == NULL )
1058  {
1059  sinfo_msg_error("no number of lines given!") ;
1060  return -1 ;
1061  }
1062  if ( n_columns < 200 )
1063  {
1064  sinfo_msg_error("wrong number of columns given!") ;
1065  return -1 ;
1066  }
1067 
1068  /* first determine the estimated beginning wavelength of the first row */
1069  for ( col = 0 ; col < n_columns ; col++ )
1070  {
1071  if ( n_found_lines[col] == 0 )
1072  {
1073  continue ;
1074  }
1075  if ( NULL == (beginWave = (float*) cpl_calloc( n_found_lines[col],
1076  sizeof(float) ) ) )
1077  {
1078  sinfo_msg_error("could not allocate memory!") ;
1079  return -1 ;
1080  }
1081  for ( k = 0 ; k < n_found_lines[col] ; k++ )
1082  {
1083  beginWave[k] = wavelength_clean[col][k] -
1084  (float)row_clean[col][k] * dispersion ;
1085  }
1086  /* determine the clean mean of the estimated
1087  beginning wavelengths of one column */
1088  if ( FLT_MAX == (firstWave = sinfo_new_clean_mean (beginWave,
1089  n_found_lines[col],
1090  10., 10.) ) )
1091  {
1092  sinfo_msg_error("clean mean did not work!") ;
1093  return -1 ;
1094  }
1095 
1096  cpl_free (beginWave) ;
1097  /* go through the lines in that column and select the
1098  correct FitParam structure */
1099  for ( k = 0 ; k < n_found_lines[col] ; k++ )
1100  {
1101  /* compute the estimated line position */
1102  row = ( wavelength_clean[col][k] - firstWave ) / dispersion ;
1103 
1104  /* go through all fit parameters and find the corresponding one */
1105  found = -1 ;
1106  for ( i = 0 ; i < (par[0] -> n_params) ; i ++ )
1107  {
1108  /* find the given column and go through the
1109  lines in that column */
1110  if ( (par[i] -> column == col) && (par[i] -> line == k) &&
1111  (par[i] -> wavelength == wavelength_clean[col][k]) )
1112  {
1113  found = i ;
1114  break ;
1115  }
1116  }
1117  if ( found != -1 )
1118  {
1119  /* set fit params to zero where the fitted row
1120  position and the estimated
1121  row positions are outside the tolerance */
1122  if ( fabs(row - par[found]->fit_par[2]) > pixel_tolerance )
1123  {
1124  sinfo_msg_warning("found bad line in col: "
1125  "%d line: %d in row: %f difference: %f",
1126  col, k, par[found]->fit_par[2],
1127  row - par[found]->fit_par[2]) ;
1128  par[found]->fit_par[2] = 0. ;
1129  }
1130  }
1131  else
1132  {
1133  sinfo_msg_warning("fit parameter of col %d and line "
1134  "no %d not found!\n", col, k ) ;
1135  }
1136  }
1137  }
1138 
1139  return 0 ;
1140 }
1141 
1160 cpl_image *
1161 sinfo_new_create_shifted_slit_wavemap ( cpl_image * lineIm,
1162  float ** coeffs,
1163  int n_fitcoeffs,
1164  float * wavelength,
1165  float * intensity,
1166  int n_lines,
1167  int magFactor )
1168 {
1169  cpl_image * wavemap ;
1170  float* emline=NULL ;
1171  float* spec=NULL ;
1172  float* wave=NULL ;
1173  double* a=NULL ;
1174  float* par=NULL ;
1175  float* derv_par=NULL ;
1176  double* z=NULL ;
1177 
1178  double * result ;
1179  float * filter_spec ;
1180  float centreval ;
1181  float centrepix ;
1182  float cenpos, cenpix ;
1183  float pixvalue ;
1184  float wavelag ;
1185  float angst ;
1186  float a_initial ;
1187  int numpar, its ;
1188  int * mpar ;
1189  float tol, lab ;
1190  float * xdat, * wdat ;
1191  Vector * peak;
1192  int iters, xdim, ndat ;
1193  int row , col ;
1194  int i, j, k/*, l, m*/ ;
1195  int sign, found, line, width ;
1196  int var, maxlag, cmin, cmax ;
1197  gsl_poly_complex_workspace * w ;
1198  double xcorr_max ;
1199  int delta ;
1200  int ilx=0;
1201  int ily=0;
1202  int olx=0;
1203  int oly=0;
1204  float* pidata=NULL;
1205  float* podata=NULL;
1206 
1207 
1208  if ( lineIm == NULL )
1209  {
1210  sinfo_msg_error ("no input image given!") ;
1211  return NULL ;
1212  }
1213  ilx=cpl_image_get_size_x(lineIm);
1214  ily=cpl_image_get_size_y(lineIm);
1215  pidata=cpl_image_get_data_float(lineIm);
1216 
1217  if ( coeffs == NULL )
1218  {
1219  sinfo_msg_error ("no coefficient sinfo_matrix given!") ;
1220  return NULL ;
1221  }
1222  if ( n_fitcoeffs < 2 )
1223  {
1224  sinfo_msg_error ("wrong number of polynomial coefficients given!") ;
1225  return NULL ;
1226  }
1227  if ( wavelength == NULL || intensity == NULL )
1228  {
1229  sinfo_msg_error ("no input image given!") ;
1230  return NULL ;
1231  }
1232  if ( n_lines < 1 )
1233  {
1234  sinfo_msg_error ("no input image given!") ;
1235  return NULL ;
1236  }
1237 
1238  /* find out if Angstroem or microns are used */
1239  if ( wavelength[0] > 10000. )
1240  {
1241  /* Angstroem */
1242  angst = 10000. ;
1243  }
1244  else if ( wavelength[0] > 1000. && wavelength[0] < 10000. )
1245  {
1246  /* nanometers */
1247  angst = 1000. ;
1248  }
1249  else
1250  {
1251  /* microns */
1252  angst = 1. ;
1253  }
1254 
1255  /* allocate memory */
1256  if ( NULL == (wavemap = cpl_image_new ( ilx, ily, CPL_TYPE_FLOAT)) )
1257  {
1258  sinfo_msg_error ("could not allocate memory!") ;
1259  return NULL ;
1260  }
1261  olx=cpl_image_get_size_x(wavemap);
1262  oly=cpl_image_get_size_y(wavemap);
1263  podata=cpl_image_get_data_float(wavemap);
1264 
1265  var = (magFactor-1)*(magFactor-1) ;
1266 
1267 
1268 
1269  emline=cpl_calloc(ily,sizeof(float)) ;
1270  spec=cpl_calloc(ily,sizeof(float)) ;
1271  wave=cpl_calloc(n_lines,sizeof(float)) ;
1272  par=cpl_calloc(MAXPAR,sizeof(float)) ;
1273  derv_par=cpl_calloc(MAXPAR,sizeof(float)) ;
1274 
1275  a=cpl_calloc(n_fitcoeffs,sizeof(double)) ;
1276  z=cpl_calloc(2*(n_fitcoeffs - 1),sizeof(double)) ;
1277 
1278 
1279  /* first store each spectrum in a buffer */
1280  for ( col = 0 ; col < ilx ; col++ )
1281  {
1282  /* initialize the emline array for each column */
1283  for ( i = 0 ; i < ily ; i++ )
1284  {
1285  emline[i] = 0. ;
1286  }
1287  /* determine the coefficients by using the given bcoefs */
1288  for ( i = 0 ; i < n_fitcoeffs ; i++ )
1289  {
1290  /* initialize coefficients and solution */
1291  if (i < n_fitcoeffs-1)
1292  {
1293  z[2*i] = 0. ;
1294  z[2*i+1] = 0. ;
1295  }
1296  a[i] = coeffs[i][col] ;
1297  }
1298 
1299  a_initial = coeffs[0][col] ;
1300  /* go through the lines and generate an artificial spectrum */
1301  for ( line = 0 ; line < n_lines ; line++ )
1302  {
1303  /* go from Angstroem to micron */
1304  wave[line] = wavelength[line]/angst ;
1305 
1306  /* -----------------------------------------------------------
1307  * solve the polynomial for the exact offset of the line that means
1308  * find the root of the polynomial of order n_fitcoefs - 1
1309  */
1310  a[0] = a_initial - wave[line] ;
1311 
1312  if(NULL==(w=sinfo_gsl_poly_complex_workspace_alloc(n_fitcoeffs)))
1313  {
1314  sinfo_msg_error("could not allocate complex workspace!") ;
1315  cpl_image_delete(wavemap) ;
1316  return NULL ;
1317  }
1318  if (-1 == sinfo_gsl_poly_complex_solve(a, n_fitcoeffs, w, z))
1319  {
1320  sinfo_msg_error("sinfo_gsl_poly_complex_solve did not work!") ;
1321  cpl_image_delete(wavemap) ;
1322  return NULL ;
1323  }
1324  sinfo_gsl_poly_complex_workspace_free(w) ;
1325 
1326  j = 0 ;
1327  found = -1 ;
1328  for ( i = 0 ; i < n_fitcoeffs - 1 ; i++ )
1329  {
1330  /* test for appropriate solution */
1331  if( (z[2*i] > (-1.)*(float) ily/2. &&
1332  z[2*i] < (float)ily/2.) && z[2*i+1] == 0. )
1333  {
1334  found = 2*i ;
1335  j ++ ;
1336  }
1337  else
1338  {
1339  continue ;
1340  }
1341  }
1342  if ( j == 0 )
1343  {
1344  sinfo_msg_warning("no offset solution found for line %d in "
1345  "column %d", line, col) ;
1346  continue ;
1347  }
1348  else if ( j == 1 )
1349  {
1350  cenpos = z[found] + (float) ily /2. ;
1351  }
1352  else
1353  {
1354  sinfo_msg_warning("two or more offset solutions found for "
1355  "line %d in column %d", line, col) ;
1356  continue ;
1357  }
1358 
1359  /*-----------------------------------------------------------------
1360  * magnify image by the given factor add an additional offset
1361  */
1362  cenpix = cenpos ;
1363 
1364  /* determine max and min pixel limits over
1365  which line should be convolved */
1366  cmin = (sinfo_new_nint(cenpix) - (var-1)) > 0 ?
1367  sinfo_new_nint(cenpix) - (var-1) : 0 ;
1368  cmax = (sinfo_new_nint(cenpix) + (var-1)) < ily ?
1369  sinfo_new_nint(cenpix) + (var-1) : ily ;
1370 
1371  /* convolve neon lines with Gaussian function */
1372  for ( j = cmin ; j < cmax ; j++ )
1373  {
1374  emline[j] += intensity[line] *
1375  exp((double)(-0.5*(j-cenpix)*(j-cenpix))/(double)var) ;
1376  }
1377  }
1378 
1379  /*-------------------------------------------------------------------
1380  * for each column, map the image data points onto an magFactor times
1381  bigger element grid for FFT in the cross sinfo_correlation, first
1382  initialize the two helping arrays for each new column.
1383  */
1384  for ( k = 0 ; k < ily ; k++ )
1385  {
1386  spec[k] = 0. ;
1387  }
1388 
1389  /* now take the image data points of the column and put
1390  them into the spec array */
1391  for ( row = 0 ; row < ily ; row++ ) /* go through the column */
1392  {
1393  /* set bad pixels or negative values to zero */
1394  if (!isnan(pidata[col + row*ilx]) &&
1395  (pidata[col + row*ilx] > 0.))
1396  {
1397  spec[row] = pidata[col + row*ilx] ;
1398  }
1399  else
1400  {
1401  spec[row] = 0. ;
1402  }
1403  }
1404  /* convolve the spectrum by Gaussian */
1405  filter_spec = sinfo_function1d_filter_lowpass(spec, ily,
1406  LOW_PASS_GAUSSIAN,
1407  magFactor) ;
1408 
1409  /* now call the cross sinfo_correlation routine */
1410  result = sinfo_new_xcorrel( filter_spec, ily, emline, ily,
1411  ily/2, &delta, &maxlag, &xcorr_max) ;
1412 
1413  if ( xcorr_max <= 0. )
1414  {
1415  sinfo_msg_warning("no positive cross correlation sum , "
1416  "col %d set to ZERO \n", col) ;
1417  for ( row = 0 ; row < ily ; row++ )
1418  {
1419  podata[col + row*ilx] = ZERO ;
1420  }
1421  sinfo_function1d_del(filter_spec) ;
1422  cpl_free(result) ;
1423  continue ;
1424  }
1425 
1426  /* in this section, we fit the correlation function with a gauss,
1427  and find its peak, thus getting subpixel-accuracy */
1428 
1429  i = maxlag; j = i+1;
1430  while (result[j] < result[i])
1431  {
1432  i++; j++;
1433  }
1434  i = maxlag; k = i-1;
1435  while (result[k] < result[i])
1436  {
1437  i--; k--;
1438  }
1439  width = j-k+1;
1440  /* allocate memory for the spectral sinfo_vector */
1441  if ( NULL == (peak = sinfo_new_vector (width)) )
1442  {
1443  sinfo_msg_error ("cannot allocate new Vector \n") ;
1444  sinfo_function1d_del(filter_spec) ;
1445  cpl_free(result) ;
1446  return NULL ;
1447  }
1448 
1449 
1450  /* allocate memory */
1451  xdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
1452  wdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
1453  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
1454 
1455  /* determine the values of the spectral sinfo_vector given as input */
1456  /* go through the chosen column */
1457 
1458  for ( i = 0 ; i < width ; i++ )
1459  {
1460  peak -> data[i] = result[k+i]/xcorr_max * 100. ;
1461  xdat[i] = i;
1462  wdat[i] = 1.0;
1463  }
1464 
1465  /* set initial values for the fitting routine */
1466  xdim = XDIM;
1467  ndat = peak -> n_elements ;
1468  numpar = MAXPAR ;
1469  tol = TOL ;
1470  lab = LAB ;
1471  its = ITS ;
1472  par[1] = width/2.0 ;
1473  par[2] = (float) (maxlag - k) ;
1474  par[3] = (peak -> data[0] + peak -> data[peak->n_elements - 1]) / 2.0 ;
1475  par[0] = result[maxlag]/xcorr_max * 100. - (par[3]) ;
1476 
1477  for ( i = 0 ; i < MAXPAR ; i++ )
1478  {
1479  derv_par[i] = 0.0 ;
1480  mpar[i] = 1 ;
1481  }
1482 
1483  /* finally, do the least square fit using a sinfo_gaussian */
1484  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim,
1485  peak -> data, wdat,
1486  &ndat, par, derv_par, mpar,
1487  &numpar, &tol, &its, &lab )) )
1488  {
1489  sinfo_msg_warning ("sinfo_new_lsqfit_c: least squares fit failed "
1490  "in col: %d, error no.: %d", col, iters) ;
1491  sinfo_new_destroy_vector ( peak ) ;
1492  cpl_free ( xdat ) ;
1493  cpl_free ( wdat ) ;
1494  cpl_free ( mpar ) ;
1495  sinfo_function1d_del(filter_spec) ;
1496  cpl_free(result) ;
1497  continue ;
1498  }
1499 
1500  sinfo_new_destroy_vector ( peak ) ;
1501  cpl_free (xdat) ;
1502  cpl_free (wdat) ;
1503  cpl_free (mpar) ;
1504  sinfo_function1d_del(filter_spec) ;
1505  cpl_free(result) ;
1506 
1507  wavelag =((float)ily/2 - (float)k - par[2]) ;
1508 
1509  if ( fabs(wavelag) > (float)ily/20. )
1510  {
1511  sinfo_msg_warning("wavelag very big , col %d set to ZERO", col) ;
1512  for ( row = 0 ; row < ily ; row++ )
1513  {
1514  podata[col + row*ilx] = ZERO ;
1515  }
1516  continue ;
1517  }
1518 
1519  /*--------------------------------------------------------------------
1520  * determine new zero order coefficient centreval, of which the
1521  * formula is determined by setting equal a polynomial shifted by
1522  * wavelag with the same higher order coefficients and set the new
1523  * zero order coefficient to
1524  * get both sides of the equation approximately equal.
1525  */
1526  centreval = a_initial ;
1527  for ( i = 1 ; i < n_fitcoeffs ; i++ )
1528  {
1529  if ( i%2 == 0 )
1530  {
1531  sign = -1 ;
1532  }
1533  else
1534  {
1535  sign = 1 ;
1536  }
1537  centreval += (float)sign * coeffs[i][col]*pow(wavelag, i) ;
1538  }
1539 
1540  /* prepare to write out wavelength as pixel values */
1541  for ( row = 0 ; row < oly ; row++ )
1542  {
1543  centrepix = (float)row - ((float)oly - 1.)/2. ;
1544  pixvalue = 0. ;
1545  for ( i = 1 ; i < n_fitcoeffs ; i++ )
1546  {
1547  pixvalue += coeffs[i][col]*pow(centrepix, i) ;
1548  }
1549  podata[col+row*olx] = centreval + pixvalue ;
1550  }
1551  }
1552 
1553 
1554  cpl_free(emline) ;
1555  cpl_free(spec) ;
1556  cpl_free(wave) ;
1557  cpl_free(par) ;
1558  cpl_free(derv_par) ;
1559 
1560  cpl_free(a) ;
1561  cpl_free(z) ;
1562 
1563 
1564 
1565  return wavemap ;
1566 }
1567 
1592 cpl_image * sinfo_new_create_shifted_slit_wavemap2 ( cpl_image * lineIm,
1593  float ** coeffs,
1594  int n_fitcoeffs,
1595  float * wavelength,
1596  float * intensity,
1597  int n_lines,
1598  int magFactor,
1599  float dispersion,
1600  float pixel_dist )
1601 {
1602  cpl_image * wavemap ;
1603  double * result ;
1604  float * filter_spec ;
1605  float centreval ;
1606  float centrepix ;
1607  float cenpos, cenpix ;
1608  float pixvalue ;
1609  float wavelag ;
1610  /*float maxres ;*/
1611  float angst ;
1612  /*float temp ;*/
1613  float a_initial ;
1614  int numpar, its ;
1615  int * mpar ;
1616  float tol, lab ;
1617  float * xdat, * wdat ;
1618  Vector * peak;
1619  int iters, xdim, ndat ;
1620  int row , col ;
1621  int i, j, k/*, l, m*/, n ;
1622  int sign, found, line, width ;
1623  int var, maxlag, cmin, cmax ;
1624  float offset2 ;
1625  float threshold ;
1626  int ed1, ed2 ;
1627 
1628  int edge[N_SLITLETS] ;
1629  float par[MAXPAR] ;
1630  float derv_par[MAXPAR] ;
1631 
1632  float* emline=NULL ;
1633  float* spec=NULL ;
1634  float* wave=NULL ;
1635  float* a0=NULL ;
1636  float* a0_clean=NULL ;
1637 
1638 
1639  float* sub_col_index=NULL ;
1640  float* sub_acoefs=NULL;
1641  float* sub_dacoefs=NULL ;
1642  double* z=NULL ;
1643  double* a=NULL ;
1644 
1645  float** bcoef=NULL ;
1646  float* wcoefs=NULL ;
1647 
1648 
1649  int ns, nc ;
1650  float * acoefsclean ;
1651  float col_index;
1652 
1653  float ** ucoefs, **vcoefs, **covar ;
1654  double sum, sumq, mean ;
1655  double sigma ;
1656  double cliphi, cliplo ;
1657  float chisq ;
1658  int num, ndata ;
1659  gsl_poly_complex_workspace * w ;
1660  double xcorr_max ;
1661  int delta ;
1662  int ilx=0;
1663  int ily=0;
1664  int olx=0;
1665  int oly=0;
1666  float* pidata=NULL;
1667  float* podata=NULL;
1668 
1669 
1670  if ( lineIm == NULL )
1671  {
1672  sinfo_msg_error (" no input image given!\n") ;
1673  return NULL ;
1674  }
1675 
1676  ilx=cpl_image_get_size_x(lineIm);
1677  ily=cpl_image_get_size_y(lineIm);
1678  pidata=cpl_image_get_data_float(lineIm);
1679 
1680  if ( coeffs == NULL )
1681  {
1682  sinfo_msg_error (" no coefficient sinfo_matrix given!\n") ;
1683  return NULL ;
1684  }
1685  if ( n_fitcoeffs < 2 )
1686  {
1687  sinfo_msg_error (" wrong number of polynomial coefficients given!\n") ;
1688  return NULL ;
1689  }
1690  if ( wavelength == NULL || intensity == NULL )
1691  {
1692  sinfo_msg_error (" no input image given!\n") ;
1693  return NULL ;
1694  }
1695  if ( n_lines < 1 || magFactor < 1 )
1696  {
1697  sinfo_msg_error (" no input image given!\n") ;
1698  return NULL ;
1699  }
1700  var = (magFactor - 1)*(magFactor - 1) ;
1701  /* find out if Angstroem or microns are used */
1702  if ( wavelength[0] > 10000. )
1703  {
1704  /* Angstroem */
1705  angst = 10000. ;
1706  }
1707  else if ( wavelength[0] > 1000. && wavelength[0] < 10000. )
1708  {
1709  /* nanometers */
1710  angst = 1000. ;
1711  }
1712  else
1713  {
1714  /* microns */
1715  angst = 1. ;
1716  }
1717 
1718  bcoef=sinfo_new_2Dfloatarray(N_SLITLETS,n_fitcoeffs) ;
1719  wcoefs=cpl_calloc(n_fitcoeffs,sizeof(float)) ;
1720 
1721  emline=cpl_calloc(ily,sizeof(float)) ;
1722  spec=cpl_calloc(ily,sizeof(float)) ;
1723  wave=cpl_calloc(n_lines,sizeof(float)) ;
1724  a0=cpl_calloc(ilx,sizeof(float)) ;
1725  a0_clean=cpl_calloc(ilx,sizeof(float)) ;
1726 
1727 
1728 
1729  sub_col_index=cpl_calloc(ilx,sizeof(float)) ;
1730  sub_acoefs=cpl_calloc(ilx,sizeof(float));
1731  sub_dacoefs=cpl_calloc(ilx,sizeof(float)) ;
1732 
1733  a=cpl_calloc(n_fitcoeffs,sizeof(double)) ;
1734  z=cpl_calloc(2*(n_fitcoeffs - 1),sizeof(double)) ;
1735 
1736  /* find the slitlet edges from the a0 coefficient */
1737  n = 0 ;
1738  threshold = pixel_dist * fabs(dispersion) ;
1739  for ( i = PIXEL ; i < ilx - PIXEL ; )
1740  {
1741  if (fabs(coeffs[0][i+1] - coeffs[0][i]) >= threshold )
1742  {
1743  edge[n] = i+1 ;
1744  n++ ;
1745  i += PIXEL ;
1746  }
1747  i++ ;
1748  }
1749 
1750 
1751  /* allocate memory */
1752  if ( NULL == (wavemap = cpl_image_new ( ilx, ily, CPL_TYPE_FLOAT)) )
1753  {
1754  sinfo_msg_error (" could not allocate memory!\n") ;
1755  return NULL ;
1756  }
1757  olx=cpl_image_get_size_x(wavemap);
1758  oly=cpl_image_get_size_y(wavemap);
1759  podata=cpl_image_get_data_float(wavemap);
1760 
1761  /* first store each spectrum in a buffer */
1762  for ( col = 0 ; col < ilx ; col++ )
1763  {
1764  /* initialize the emline array for each column */
1765  for ( i = 0 ; i < ily ; i++ )
1766  {
1767  emline[i] = 0. ;
1768  }
1769  /* determine the coefficients by using the given bcoefs */
1770  for ( i = 0 ; i < n_fitcoeffs ; i++ )
1771  {
1772  /* initialize coefficients and solution */
1773  if (i < n_fitcoeffs-1)
1774  {
1775  z[2*i] = 0. ;
1776  z[2*i+1] = 0. ;
1777  }
1778  a[i] = coeffs[i][col] ;
1779  }
1780 
1781  a_initial = coeffs[0][col] ;
1782  /* go through the lines and generate an artificial spectrum */
1783  for ( line = 0 ; line < n_lines ; line++ )
1784  {
1785  /* go from Angstroem to micron */
1786  wave[line] = wavelength[line]/angst ;
1787 
1788  /* ------------------------------------------------------------
1789  * solve the polynomial for the exact offset of the line that means
1790  * find the root of the polynomial of order n_fitcoefs - 1
1791  */
1792  a[0] = a_initial - wave[line] ;
1793 
1794  if (NULL==(w=sinfo_gsl_poly_complex_workspace_alloc(n_fitcoeffs)))
1795  {
1796  sinfo_msg_error(" could not allocate complex workspace!") ;
1797  cpl_image_delete(wavemap) ;
1798  return NULL ;
1799  }
1800  if (-1 == sinfo_gsl_poly_complex_solve(a, n_fitcoeffs, w, z))
1801  {
1802  sinfo_msg_error(" sinfo_gsl_poly_complex_solve did not work!") ;
1803  cpl_image_delete(wavemap) ;
1804  return NULL ;
1805  }
1806  sinfo_gsl_poly_complex_workspace_free(w) ;
1807 
1808  j = 0 ;
1809  found = -1 ;
1810  for ( i = 0 ; i < n_fitcoeffs - 1 ; i++ )
1811  {
1812  /* test for appropriate solution */
1813  if( (z[2*i] > (-1.)*(float) ily/2. &&
1814  z[2*i] < (float)ily/2.) && z[2*i+1] == 0. )
1815  {
1816  found = 2*i ;
1817  j ++ ;
1818  }
1819  else
1820  {
1821  continue ;
1822  }
1823  }
1824  if ( j == 0 )
1825  {
1826  sinfo_msg_warning(" no offset solution found for "
1827  "line %d in column %d\n", line, col) ;
1828  continue ;
1829  }
1830  else if ( j == 1 )
1831  {
1832  cenpos = z[found] + (float) ily/2. ;
1833  }
1834  else
1835  {
1836  sinfo_msg_warning(" two or more offset solutions found "
1837  "for line %d in column %d", line, col) ;
1838  continue ;
1839  }
1840 
1841  /*----------------------------------------------------------------
1842  * magnify image by the given factor add an additional offset
1843  */
1844  cenpix = cenpos ;
1845 
1846  /* determine max and min pixel limits over which line should
1847  be convolved */
1848  cmin = (sinfo_new_nint(cenpix) - (var-1)) > 0 ?
1849  sinfo_new_nint(cenpix) - (var-1) : 0 ;
1850  cmax = (sinfo_new_nint(cenpix) + (var-1)) < ily ?
1851  sinfo_new_nint(cenpix) + (var-1) : ily ;
1852 
1853  /* convolve neon lines with Gaussian function */
1854  for ( j = cmin ; j < cmax ; j++ )
1855  {
1856  emline[j] += intensity[line] *
1857  exp((double)(-0.5*(j-cenpix)*(j-cenpix))/(double)var) ;
1858  }
1859  }
1860 
1861  /*--------------------------------------------------------------------
1862  * for each column, map the image data points onto an magFactor times
1863  bigger element grid for FFT in the cross sinfo_correlation, first
1864  initialize the two helping arrays for each new column.
1865  */
1866  for ( k = 0 ; k < ily ; k++ )
1867  {
1868  spec[k] = 0. ;
1869  }
1870 
1871  /* now take the image data points of the column and put them into
1872  the spec array */
1873  for ( row = 0 ; row < ily ; row++ ) /* go through the column */
1874  {
1875  /* set bad pixels or negative values to zero */
1876  if (!isnan(pidata[col + row*ilx]) &&
1877  (pidata[col + row*ilx] > 0.))
1878  {
1879  spec[row] = pidata[col + row*ilx] ;
1880  }
1881  else
1882  {
1883  spec[row] = 0. ;
1884  }
1885  }
1886  /* convolve the spectrum by Gaussian */
1887  filter_spec = sinfo_function1d_filter_lowpass(spec,ily,
1888  LOW_PASS_GAUSSIAN,
1889  magFactor) ;
1890 
1891  /* now call the cross sinfo_correlation routine */
1892  result = sinfo_new_xcorrel( filter_spec, ily, emline, ily,
1893  ily/2, &delta, &maxlag, &xcorr_max) ;
1894 
1895  if ( xcorr_max <= 0. )
1896  {
1897  sinfo_msg_warning("no positive cross sinfo_correlation "
1898  "sum , col %d set to ZERO \n", col) ;
1899  for ( row = 0 ; row < ily ; row++ )
1900  {
1901  podata[col + row*ilx] = ZERO ;
1902  }
1903  sinfo_function1d_del(filter_spec) ;
1904  cpl_free(result) ;
1905  continue ;
1906  }
1907 
1908  /* in this section, we fit the sinfo_correlation function with a gauss,
1909  and find its peak, thus getting subpixel-accuracy */
1910 
1911  i = maxlag; j = i+1;
1912  while (result[j] < result[i])
1913  {
1914  i++; j++;
1915  }
1916  i = maxlag; k = i-1;
1917  while (result[k] < result[i])
1918  {
1919  i--; k--;
1920  }
1921  width = j-k+1;
1922  /* allocate memory for the spectral sinfo_vector */
1923  if ( NULL == (peak = sinfo_new_vector (width)) )
1924  {
1925  sinfo_msg_error (" cannot allocate new Vector \n") ;
1926  sinfo_function1d_del(filter_spec) ;
1927  cpl_free(result) ;
1928  return NULL ;
1929  }
1930 
1931 
1932  /* allocate memory */
1933  xdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
1934  wdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
1935  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
1936 
1937  /* determine the values of the spectral sinfo_vector given as input */
1938  /* go through the chosen column */
1939 
1940  for ( i = 0 ; i < width ; i++ )
1941  {
1942  peak -> data[i] = result[k+i]/xcorr_max * 100. ;
1943  xdat[i] = i;
1944  wdat[i] = 1.0;
1945  }
1946 
1947  /* set initial values for the fitting routine */
1948  xdim = XDIM;
1949  ndat = peak -> n_elements ;
1950  numpar = MAXPAR ;
1951  tol = TOL ;
1952  lab = LAB ;
1953  its = ITS ;
1954  par[1] = width/2.0 ;
1955  par[2] = (float) (maxlag - k) ;
1956  par[3] = (peak -> data[0] + peak -> data[peak->n_elements - 1]) / 2.0 ;
1957  par[0] = result[maxlag]/xcorr_max * 100. - (par[3]) ;
1958 
1959  for ( i = 0 ; i < MAXPAR ; i++ )
1960  {
1961  derv_par[i] = 0.0 ;
1962  mpar[i] = 1 ;
1963  }
1964 
1965  /* finally, do the least square fit using a sinfo_gaussian */
1966  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim, peak -> data,
1967  wdat, &ndat, par,
1968  derv_par, mpar,
1969  &numpar, &tol, &its, &lab )) )
1970  {
1971  sinfo_msg_warning (" sinfo_new_lsqfit_c: least squares fit "
1972  "failed in col: %d, error no.: %d", col, iters);
1973  sinfo_new_destroy_vector ( peak ) ;
1974  cpl_free ( xdat ) ;
1975  cpl_free ( wdat ) ;
1976  cpl_free ( mpar ) ;
1977  sinfo_function1d_del(filter_spec) ;
1978  cpl_free(result) ;
1979  continue ;
1980  }
1981 
1982  sinfo_new_destroy_vector ( peak ) ;
1983  cpl_free (xdat) ;
1984  cpl_free (wdat) ;
1985  cpl_free (mpar) ;
1986  sinfo_function1d_del(filter_spec) ;
1987  cpl_free(result) ;
1988 
1989  wavelag =((float)ily/2 - (float)k - par[2]) ;
1990 
1991  if ( fabs(wavelag) > (float)ily/20. )
1992  {
1993  sinfo_msg_warning("wavelag very big , col %d set to ZERO ", col) ;
1994  for ( row = 0 ; row < ily ; row++ )
1995  {
1996  podata[col + row*ilx] = ZERO ;
1997  }
1998  continue ;
1999  }
2000 
2001  /*--------------------------------------------------------------------
2002  * determine new zero order coefficient centreval, of which the
2003  * formula is determined by setting equal a polynomial shifted by
2004  * wavelag with the same higher order coefficients and set the new
2005  * zero order coefficient to get both sides of the equation
2006  * approximately equal.
2007  */
2008  centreval = a_initial ;
2009  for ( i = 1 ; i < n_fitcoeffs ; i++ )
2010  {
2011  if ( i%2 == 0 )
2012  {
2013  sign = -1 ;
2014  }
2015  else
2016  {
2017  sign = 1 ;
2018  }
2019  centreval += (float)sign * coeffs[i][col]*pow(wavelag, i) ;
2020  }
2021  a0[col] = centreval ;
2022  }
2023 
2024  /* go through the single slitlets */
2025  for ( ns = 0 ; ns < N_SLITLETS ; ns++ )
2026  {
2027  /* determine the slitlet edges */
2028  if ( ns == 0 )
2029  {
2030  ed1 = 0 ;
2031  ed2 = edge[0] ;
2032  }
2033  else if ( ns == N_SLITLETS - 1 )
2034  {
2035  ed1 = edge[N_SLITLETS - 2] ;
2036  ed2 = ilx ;
2037  }
2038  else
2039  {
2040  ed1 = edge[ns-1] ;
2041  ed2 = edge[ns] ;
2042  }
2043 
2044  nc = 0 ;
2045  for ( i = ed1 ; i < ed2 ; i++ )
2046  {
2047  if ( isnan(a0[i]) || a0[i] == 0. )
2048  {
2049  continue ;
2050  }
2051  else
2052  {
2053  nc++ ;
2054  }
2055  }
2056  if ( NULL == (acoefsclean = (float*) cpl_calloc(nc , sizeof(float))) )
2057  {
2058  sinfo_msg_error("could not allocate memory for acoefsclean!\n") ;
2059  return NULL ;
2060  }
2061  nc = 0 ;
2062  for ( i = ed1 ; i < ed2 ; i++ )
2063  {
2064  if ( isnan(a0[i]) || a0[i] == 0. )
2065  {
2066  continue ;
2067  }
2068  else
2069  {
2070  acoefsclean[nc] = a0[i] ;
2071  nc++ ;
2072  }
2073  }
2074 
2075  /* ----------------------------------------------------------
2076  * determine the clean mean and sigma value of the coefficients,
2077  * that means reject 10 % of the extreme low and high values
2078  */
2079  sinfo_pixel_qsort(acoefsclean, nc) ;
2080  sum = 0. ;
2081  sumq = 0. ;
2082  mean = 0. ;
2083  sigma = 0. ;
2084  n = 0 ;
2085  for ( i = (int)((float)nc*LOW_REJECT) ;
2086  i < (int)((float)nc*HIGH_REJECT) ; i++ )
2087  {
2088  sum += (double)acoefsclean[i] ;
2089  sumq += ((double)acoefsclean[i] * (double)acoefsclean[i]) ;
2090  n ++ ;
2091  }
2092  mean = sum/(double)n ;
2093  sigma = sqrt( sumq/(double)n - (mean * mean) ) ;
2094  cliphi = mean + sigma * (double)3. ;
2095  cliplo = mean - sigma * (double)3. ;
2096  /* fit only the reasonnable values */
2097  num = 0 ;
2098  col_index = 0 ;
2099  for ( i = ed1 ; i < ed2 ; i++ )
2100  {
2101  /* take only the reasonnable coefficients */
2102  if ( !isnan(a0[i]) && (a0[i] <= cliphi) && (a0[i] >= cliplo) &&
2103  (a0[i] != 0.) )
2104  {
2105  sub_acoefs[num] = a0[i] ;
2106  sub_dacoefs[num] = 0.0000005 ;
2107  sub_col_index[num] = col_index ;
2108  num ++ ;
2109  }
2110  col_index++ ;
2111  }
2112  ndata = num ;
2113  offset2 = (float)(col_index-1) / 2. ;
2114 
2115  if ( ndata < n_fitcoeffs )
2116  {
2117  sinfo_msg_error(" not enough data found in slitlet %d\
2118  to determine the fit coefficients.\n", ns) ;
2119  cpl_free(acoefsclean) ;
2120  return NULL ;
2121  }
2122 
2123  /* allocate coefficient matrices, see numerical recipe function
2124  sinfo_matrix */
2125  ucoefs = sinfo_matrix(1, ndata, 1, n_fitcoeffs) ;
2126  vcoefs = sinfo_matrix(1, ndata, 1, n_fitcoeffs) ;
2127  covar = sinfo_matrix(1, n_fitcoeffs, 1, n_fitcoeffs) ;
2128 
2129  /* scale the x-values for the fit */
2130  for ( i = 0 ; i < ndata ; i++ )
2131  {
2132  sub_col_index[i] = (sub_col_index[i] - offset2) / offset2 ;
2133  }
2134 
2135  /* finally, do the singular value decomposition fit */
2136  sinfo_svd_fitting ( sub_col_index-1, sub_acoefs-1,
2137  sub_dacoefs-1, ndata, bcoef[ns]-1,
2138  n_fitcoeffs, ucoefs, vcoefs, wcoefs-1,
2139  covar, &chisq, sinfo_fpol ) ;
2140 
2141  /* scale the found coefficients */
2142  for ( i = 0 ; i < n_fitcoeffs ; i ++ )
2143  {
2144  bcoef[ns][i] /= pow( offset2, i ) ;
2145  }
2146 
2147  /* free memory */
2148  cpl_free (acoefsclean) ;
2149  sinfo_free_matrix( ucoefs, 1/*, ndata*/, 1/*, n_fitcoeffs */) ;
2150  sinfo_free_matrix( vcoefs, 1/*, ndata*/, 1/*, n_fitcoeffs */) ;
2151  sinfo_free_matrix( covar, 1/*, n_fitcoeffs*/, 1/*, n_fitcoeffs*/) ;
2152 
2153  /* now calculate the smoothed acoefs for each column */
2154  col_index = 0 ;
2155  for ( i = ed1 ; i < ed2 ; i++ )
2156  {
2157  a0_clean[i] = 0. ;
2158  for ( n = 0 ; n < n_fitcoeffs ; n++ )
2159  {
2160  a0_clean[i] += bcoef[ns][n] *
2161  pow((float)col_index - offset2, n) ;
2162  }
2163  col_index++ ;
2164  }
2165 
2166  }
2167 
2168  for ( col = 0 ; col < ilx ; col++ )
2169  {
2170  /* prepare to write out wavelength as pixel values */
2171  for ( row = 0 ; row < oly ; row++ )
2172  {
2173  centrepix = (float)row - ((float)oly - 1.)/2. ;
2174  pixvalue = 0. ;
2175  for ( i = 1 ; i < n_fitcoeffs ; i++ )
2176  {
2177  pixvalue += coeffs[i][col]*pow(centrepix, i) ;
2178  }
2179  podata[col+row*olx] = a0_clean[col] + pixvalue ;
2180  }
2181  }
2182 
2183 
2184  cpl_free(emline) ;
2185  cpl_free(spec) ;
2186  cpl_free(wave) ;
2187  cpl_free(a0) ;
2188  cpl_free(a0_clean) ;
2189 
2190 
2191  cpl_free(sub_col_index) ;
2192  cpl_free(sub_acoefs);
2193  cpl_free(sub_dacoefs) ;
2194 
2195  cpl_free(a) ;
2196  cpl_free(z) ;
2197 
2198  sinfo_new_destroy_2Dfloatarray(&bcoef,n_fitcoeffs) ;
2199  cpl_free(wcoefs) ;
2200 
2201  return wavemap ;
2202 }
2203 
2227 cpl_image * sinfo_new_create_shifted_slit_wavemap3 ( cpl_image * lineIm,
2228  float ** coeffs,
2229  int n_fitcoeffs,
2230  float * wavelength,
2231  float * intensity,
2232  int n_lines,
2233  int magFactor )
2234 {
2235 
2236  cpl_image * wavemap ;
2237  double * result ;
2238  float * filter_spec ;
2239  float centreval ;
2240  float centrepix ;
2241  float cenpos, cenpix ;
2242  float pixvalue ;
2243  float wavelag_mean ;
2244  /*float maxres ;*/
2245  float angst ;
2246  /*float temp ;*/
2247  float a_initial ;
2248  /*float solution[n_fitcoeffs-1], im_solution[n_fitcoeffs-1] ;*/
2249 
2250  float par[MAXPAR] ;
2251  float derv_par[MAXPAR] ;
2252  int numpar, its ;
2253  int * mpar ;
2254  float tol, lab ;
2255  float * xdat, * wdat ;
2256  Vector * peak;
2257  int iters, xdim, ndat ;
2258  int row , col ;
2259  int i, j, k/*, l, m, n*/ ;
2260  int sign, found, line, width ;
2261  int var, maxlag, cmin, cmax ;
2262 
2263  float* emline=NULL ;
2264  float* spec=NULL ;
2265  float* wavelag=NULL ;
2266  float* wave=NULL ;
2267  double* a=NULL ;
2268  double* z=NULL ;
2269 
2270  gsl_poly_complex_workspace * w ;
2271  double xcorr_max ;
2272  int delta ;
2273 
2274  int ilx=0;
2275  int ily=0;
2276  float* pidata=NULL;
2277  int olx=0;
2278  int oly=0;
2279  float* podata=NULL;
2280 
2281 
2282 
2283  if ( lineIm == NULL )
2284  {
2285  sinfo_msg_error (" no input image given!\n") ;
2286  return NULL ;
2287  }
2288  ilx=cpl_image_get_size_x(lineIm);
2289  ily=cpl_image_get_size_y(lineIm);
2290  pidata=cpl_image_get_data_float(lineIm);
2291 
2292  if ( coeffs == NULL )
2293  {
2294  sinfo_msg_error (" no coefficient sinfo_matrix given!\n") ;
2295  return NULL ;
2296  }
2297  if ( n_fitcoeffs < 2 )
2298  {
2299  sinfo_msg_error (" wrong number of polynomial coefficients given!\n") ;
2300  return NULL ;
2301  }
2302 
2303  if ( wavelength == NULL || intensity == NULL )
2304  {
2305  sinfo_msg_error (" no wavelength list given!\n") ;
2306  return NULL ;
2307  }
2308  if ( n_lines < 1 || magFactor < 1 )
2309  {
2310  sinfo_msg_error (" wrong n_lines or magFactor given!\n") ;
2311  return NULL ;
2312  }
2313 
2314  var = (magFactor - 1)*(magFactor - 1) ;
2315  /* find out if Angstroem or microns are used */
2316  if ( wavelength[0] > 10000. )
2317  {
2318  /* Angstroem */
2319  angst = 10000. ;
2320  }
2321  else if ( wavelength[0] > 1000. && wavelength[0] < 10000. )
2322  {
2323  /* nanometers */
2324  angst = 1000. ;
2325  }
2326  else
2327  {
2328  /* microns */
2329  angst = 1. ;
2330  }
2331 
2332 
2333 
2334  /* allocate memory */
2335  if ( NULL == (wavemap = cpl_image_new ( ilx, ily,CPL_TYPE_FLOAT)) )
2336  {
2337  sinfo_msg_error (" could not allocate memory!\n") ;
2338  return NULL ;
2339  }
2340  podata=cpl_image_get_data_float(lineIm);
2341  olx=ilx;
2342  oly=ily;
2343 
2344  emline=cpl_calloc(ily,sizeof(float)) ;
2345  spec=cpl_calloc(ily,sizeof(float)) ;
2346  wavelag=cpl_calloc(ilx,sizeof(float)) ;
2347  wave=cpl_calloc(n_lines,sizeof(float)) ;
2348  a=cpl_calloc(n_fitcoeffs,sizeof(double)) ;
2349  z=cpl_calloc(2*(n_fitcoeffs - 1),sizeof(double)) ;
2350 
2351 
2352  /* first store each spectrum in a buffer */
2353  for ( col = 0 ; col < ilx ; col++ )
2354  {
2355  /* initialize the emline array for each column */
2356  for ( i = 0 ; i < ily ; i++ )
2357  {
2358  emline[i] = 0. ;
2359  }
2360  /* determine the coefficients by using the given bcoefs */
2361  for ( i = 0 ; i < n_fitcoeffs ; i++ )
2362  {
2363  /* initialize coefficients and solution */
2364  if (i < n_fitcoeffs-1)
2365  {
2366  z[2*i] = 0. ;
2367  z[2*i+1] = 0. ;
2368  }
2369  a[i] = coeffs[i][col] ;
2370  }
2371 
2372  a_initial = coeffs[0][col] ;
2373  /* go through the lines and generate an artificial spectrum */
2374  for ( line = 0 ; line < n_lines ; line++ )
2375  {
2376  /* go from Angstroem to micron */
2377  wave[line] = wavelength[line]/angst ;
2378 
2379  /* ----------------------------------------------------------------
2380  * solve the polynomial for the exact offset of the line that means
2381  * find the root of the polynomial of order n_fitcoefs - 1
2382  */
2383  a[0] = a_initial - wave[line] ;
2384 
2385  if (NULL==(w=sinfo_gsl_poly_complex_workspace_alloc(n_fitcoeffs)))
2386  {
2387  sinfo_msg_error(" could not allocate complex workspace!") ;
2388  cpl_image_delete(wavemap) ;
2389  return NULL ;
2390  }
2391  if (-1 == sinfo_gsl_poly_complex_solve(a, n_fitcoeffs, w, z))
2392  {
2393  sinfo_msg_error("sinfo_gsl_poly_complex_solve did not work!") ;
2394  cpl_image_delete(wavemap) ;
2395  return NULL ;
2396  }
2397  sinfo_gsl_poly_complex_workspace_free(w) ;
2398 
2399  j = 0 ;
2400  found = -1 ;
2401  for ( i = 0 ; i < n_fitcoeffs - 1 ; i++ )
2402  {
2403  /* test for appropriate solution */
2404  if( (z[2*i] > (-1.)*(float) ily/2. &&
2405  z[2*i] < (float)ily/2.) && z[2*i+1] == 0. )
2406  {
2407  found = 2*i ;
2408  j ++ ;
2409  }
2410  else
2411  {
2412  continue ;
2413  }
2414  }
2415  if ( j == 0 )
2416  {
2417  sinfo_msg_warning("no offset solution found for line %d "
2418  "in column %d\n", line, col) ;
2419  continue ;
2420  }
2421  else if ( j == 1 )
2422  {
2423  cenpos = z[found] + (float) ily /2. ;
2424  }
2425  else
2426  {
2427  sinfo_msg_warning("two or more offset solutions found for "
2428  "line %d in column %d\n", line, col) ;
2429  continue ;
2430  }
2431 
2432  /*-----------------------------------------------------------------
2433  * magnify image by the given factor add an additional offset
2434  */
2435  cenpix = cenpos ;
2436 
2437  /* determine max and min pixel limits over which
2438  line should be convolved */
2439  cmin = (sinfo_new_nint(cenpix) - (var-1)) > 0 ?
2440  sinfo_new_nint(cenpix) - (var-1) : 0 ;
2441  cmax = (sinfo_new_nint(cenpix) + (var-1)) < ily ?
2442  sinfo_new_nint(cenpix) + (var-1) : ily ;
2443 
2444  /* convolve neon lines with Gaussian function */
2445  for ( j = cmin ; j < cmax ; j++ )
2446  {
2447  emline[j] += intensity[line] *
2448  exp((double)(-0.5*(j-cenpix)*(j-cenpix))/(double)var) ;
2449  }
2450  }
2451 
2452  /*--------------------------------------------------------------------
2453  * for each column, map the image data points onto an magFactor times
2454  bigger element grid for FFT in the cross sinfo_correlation, first
2455  initialize the two helping arrays for each new column.
2456  */
2457  for ( k = 0 ; k < ily ; k++ )
2458  {
2459  spec[k] = 0. ;
2460  }
2461 
2462  /* now take the image data points of the column and put them into
2463  the spec array */
2464  for ( row = 0 ; row < ily ; row++ ) /* go through the column */
2465  {
2466  /* set bad pixels or negative values to zero */
2467  if (!isnan(pidata[col + row*ilx]) &&
2468  (pidata[col + row*ilx] > 0.))
2469  {
2470  spec[row] = pidata[col + row*ilx] ;
2471  }
2472  else
2473  {
2474  spec[row] = 0. ;
2475  }
2476  }
2477  /* convolve the spectrum by Gaussian */
2478  filter_spec = sinfo_function1d_filter_lowpass(spec, ily,
2479  LOW_PASS_GAUSSIAN,
2480  magFactor) ;
2481 
2482  /* now call the cross sinfo_correlation routine */
2483  result = sinfo_new_xcorrel( filter_spec, ily, emline, ily,
2484  ily/2, &delta, &maxlag, &xcorr_max) ;
2485 
2486  if ( xcorr_max <= 0. )
2487  {
2488  sinfo_msg_warning("no positive cross correlation sum , "
2489  "col %d set to ZERO \n", col) ;
2490  for ( row = 0 ; row < ily ; row++ )
2491  {
2492  podata[col + row*ilx] = ZERO ;
2493  }
2494  sinfo_function1d_del(filter_spec) ;
2495  cpl_free(result) ;
2496  continue ;
2497  }
2498 
2499  /* in this section, we fit the sinfo_correlation function with a
2500  gauss, and find its peak, thus getting subpixel-accuracy */
2501 
2502  i = maxlag; j = i+1;
2503  while (result[j] < result[i])
2504  {
2505  i++; j++;
2506  }
2507  i = maxlag; k = i-1;
2508  while (result[k] < result[i])
2509  {
2510  i--; k--;
2511  }
2512  width = j-k+1;
2513  /* allocate memory for the spectral sinfo_vector */
2514  if ( NULL == (peak = sinfo_new_vector (width)) )
2515  {
2516  sinfo_msg_error (" cannot allocate new Vector \n") ;
2517  sinfo_function1d_del(filter_spec) ;
2518  cpl_free(result) ;
2519  return NULL ;
2520  }
2521 
2522 
2523  /* allocate memory */
2524  xdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
2525  wdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
2526  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
2527 
2528  /* determine the values of the spectral sinfo_vector given as input */
2529  /* go through the chosen column */
2530 
2531  for ( i = 0 ; i < width ; i++ )
2532  {
2533  peak -> data[i] = result[k+i]/xcorr_max * 100. ;
2534  xdat[i] = i;
2535  wdat[i] = 1.0;
2536  }
2537 
2538  /* set initial values for the fitting routine */
2539  xdim = XDIM;
2540  ndat = peak -> n_elements ;
2541  numpar = MAXPAR ;
2542  tol = TOL ;
2543  lab = LAB ;
2544  its = ITS ;
2545  par[1] = width/2.0 ;
2546  par[2] = (float) (maxlag - k) ;
2547  par[3] = (peak -> data[0] + peak -> data[peak->n_elements - 1]) / 2.0 ;
2548  par[0] = result[maxlag]/xcorr_max * 100. - (par[3]) ;
2549 
2550  for ( i = 0 ; i < MAXPAR ; i++ )
2551  {
2552  derv_par[i] = 0.0 ;
2553  mpar[i] = 1 ;
2554  }
2555 
2556  /* finally, do the least square fit using a sinfo_gaussian */
2557  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim,
2558  peak -> data, wdat,
2559  &ndat, par, derv_par, mpar,
2560  &numpar, &tol, &its, &lab )) )
2561  {
2562  sinfo_msg_warning (" sinfo_new_lsqfit_c: least squares fit"
2563  " failed in col: %d, error no.: %d\n",
2564  col, iters) ;
2565  sinfo_new_destroy_vector ( peak ) ;
2566  cpl_free ( xdat ) ;
2567  cpl_free ( wdat ) ;
2568  cpl_free ( mpar ) ;
2569  sinfo_function1d_del(filter_spec) ;
2570  cpl_free(result) ;
2571  continue ;
2572  }
2573 
2574  sinfo_new_destroy_vector ( peak ) ;
2575  cpl_free (xdat) ;
2576  cpl_free (wdat) ;
2577  cpl_free (mpar) ;
2578  sinfo_function1d_del(filter_spec) ;
2579  cpl_free(result) ;
2580 
2581  wavelag[col] =((float)ily/2 - (float)k - par[2]) ;
2582 
2583  }
2584 
2585  if (FLT_MAX==(wavelag_mean=sinfo_new_clean_mean(wavelag, ilx, 10., 10.)) )
2586  {
2587  sinfo_msg_error(" could not determine a mean offset\n") ;
2588  return NULL ;
2589  }
2590 
2591  if ( fabs(wavelag_mean) > (float)ily/20. )
2592  {
2593  sinfo_msg_error(" wavelag too big \n") ;
2594  return NULL ;
2595  }
2596 
2597 
2598 
2599  for ( col = 0 ; col < ilx ; col++ )
2600  {
2601  /*--------------------------------------------------------------------
2602  * determine new zero order coefficient centreval, of which the
2603  * formula is determined by setting equal a polynomial shifted by
2604  * wavelag with the same higher order coefficients and set the new
2605  * zero order coefficient to get both sides of the equation
2606  * approximately equal.
2607  */
2608  a_initial = coeffs[0][col] ;
2609  centreval = a_initial ;
2610  for ( i = 1 ; i < n_fitcoeffs ; i++ )
2611  {
2612  if ( i%2 == 0 )
2613  {
2614  sign = -1 ;
2615  }
2616  else
2617  {
2618  sign = 1 ;
2619  }
2620  centreval += (float)sign * coeffs[i][col]*pow(wavelag_mean, i) ;
2621  }
2622 
2623 
2624  /* prepare to write out wavelength as pixel values */
2625  for ( row = 0 ; row < oly ; row++ )
2626  {
2627  centrepix = (float)row - ((float)oly - 1.)/2. ;
2628  pixvalue = 0. ;
2629  for ( i = 1 ; i < n_fitcoeffs ; i++ )
2630  {
2631  pixvalue += coeffs[i][col]*pow(centrepix, i) ;
2632  }
2633  podata[col+row*olx] = centreval + pixvalue ;
2634  }
2635  }
2636 
2637 
2638 
2639  cpl_free(emline) ;
2640  cpl_free(spec) ;
2641  cpl_free(wavelag) ;
2642  cpl_free(wave) ;
2643  cpl_free(a) ;
2644  cpl_free(z) ;
2645 
2646 
2647  return wavemap ;
2648 }
2649 
2672 float sinfo_new_check_line_positions ( cpl_image * lineIm,
2673  float ** coeffs,
2674  int n_fitcoeffs,
2675  float gdisp1,
2676  FitParams ** par )
2677 {
2678  float wave_shift=0 ;
2679  float amp[100] ;
2680  float sort_amp[100] ;
2681  float offset=0 ;
2682  float shift=0 ;
2683  float position=0;
2684  float lambda=0;
2685  float wave=0 ;
2686  int i=0;
2687  int j=0;
2688  int k=0;
2689  int l=0;
2690  int m=0;
2691  int n=0;
2692  int col=0;
2693  int firstj=0;
2694  float* shift_col=NULL ;
2695  int* foundit=NULL ;
2696  int n_lines=0;
2697  int lin, found=0 ;
2698  int lx=0;
2699  int ly=0;
2700  /* float* pdata=NULL; */
2701 
2702  if ( lineIm == NULL )
2703  {
2704  sinfo_msg_error (" no input image given!\n") ;
2705  return FLAG ;
2706  }
2707  lx=cpl_image_get_size_x(lineIm);
2708  ly=cpl_image_get_size_y(lineIm);
2709  /* pdata=cpl_image_get_data_float(lineIm); */
2710 
2711  if ( coeffs == NULL )
2712  {
2713  sinfo_msg_error (" no coefficient sinfo_matrix given!\n") ;
2714  return FLAG ;
2715  }
2716  if ( par == NULL )
2717  {
2718  sinfo_msg_error (" no fit parameters given!\n") ;
2719  return FLAG ;
2720  }
2721  if ( n_fitcoeffs < 2 )
2722  {
2723  sinfo_msg_error (" wrong number of polynomial coefficients given!\n") ;
2724  return FLAG ;
2725  }
2726 
2727  offset = (float) (ly -1.) / 2. ;
2728  n_lines = par[0]->n_params/lx ;
2729 
2730  shift_col=cpl_calloc(lx,sizeof(float)) ;
2731  foundit=cpl_calloc(par[0]->n_params,sizeof(int)) ;
2732 
2733  /*search for the brightest 5 lines in each column and compute the
2734  wavelength difference*/
2735  for ( col = 0 ; col < lx ; col++ )
2736  {
2737  n = 0 ;
2738  for ( i = 0 ; i < par[0]->n_params ; i++ )
2739  {
2740  if (par[i]->column == col && par[i]->fit_par[2] != 0. &&
2741  par[i]->fit_par[1] > 1. && par[i]->fit_par[1] < 7. )
2742  {
2743  foundit[n] = i ;
2744  amp[n] = par[i]->fit_par[0] ;
2745  sort_amp[n] = amp[n] ;
2746  n++ ;
2747  }
2748  }
2749  sinfo_pixel_qsort(sort_amp, n) ;
2750 
2751  if ( n > 5 )
2752  {
2753  firstj = n - 5 ;
2754  }
2755  else
2756  {
2757  firstj = 0 ;
2758  }
2759  l = 0 ;
2760  shift = 0 ;
2761  for ( j = firstj ; j < n ; j++ )
2762  {
2763  for ( m = 0 ; m < n ; m++ )
2764  {
2765  if ( sort_amp[j] == amp[m] )
2766  {
2767  position = par[foundit[m]]->fit_par[2] ;
2768  lambda = par[foundit[m]]->wavelength ;
2769  wave = 0 ;
2770  for ( k = 0 ; k < n_fitcoeffs ; k++ )
2771  {
2772  wave += coeffs[k][col]*pow(position-offset, k) ;
2773  }
2774  shift += lambda - wave ;
2775  l++ ;
2776  }
2777  }
2778  }
2779  if ( l == 0 ) continue ;
2780  shift_col[col] = shift/(float)l ;
2781  }
2782  wave_shift = sinfo_new_clean_mean(shift_col, lx, 10., 10.) ;
2783  sinfo_msg("Overall positioning error: %3.2g [um] %3.2g [pix]",
2784  wave_shift,wave_shift/fabs(gdisp1)) ;
2785 
2786 
2787  /* determine positioning error for each found line */
2788  for ( lin = 0 ; lin < n_lines ; lin++ )
2789  {
2790  for ( col = 0 ; col < lx ; col++ )
2791  {
2792  shift_col[col] = 0. ;
2793  found = -1 ;
2794  for ( i = 0 ; i < par[0]->n_params ; i++ )
2795  {
2796  if (par[i]->column == col && par[i]->fit_par[2] != 0. &&
2797  par[i]->fit_par[1] > 1. && par[i]->fit_par[1] < 7. &&
2798  par[i]->line == lin )
2799  {
2800  found = i ;
2801  }
2802  }
2803  if (found == -1) break ;
2804 
2805  position = par[found]->fit_par[2] ;
2806  lambda = par[found]->wavelength ;
2807  wave = 0 ;
2808  for ( k = 0 ; k < n_fitcoeffs ; k++ )
2809  {
2810  wave += coeffs[k][col]*pow(position-offset, k) ;
2811  }
2812  shift_col[col] = lambda - wave ;
2813  }
2814  if (found != -1 )
2815  {
2816  sinfo_msg("shift: %3.2g [um] %3.2g (pix) at: %4.3f [um]",
2817  sinfo_new_clean_mean(shift_col,lx, 10., 10.),
2818  sinfo_new_clean_mean(shift_col,lx, 10., 10.)/fabs(gdisp1),
2819  lambda) ;
2820  }
2821  }
2822  cpl_free(shift_col) ;
2823  cpl_free(foundit) ;
2824 
2825  return wave_shift ;
2826 }
2827 
2828 
2857 float sinfo_new_check_correlated_line_positions ( cpl_image * lineIm,
2858  float ** coeffs,
2859  int n_fitcoeffs,
2860  float * wavelength,
2861  float * intensity,
2862  int n_lines,
2863  float fwhm,
2864  float width,
2865  float min_amplitude,
2866  float dispersion,
2867  FitParams ** par )
2868 {
2869  float wave_shift=0 ;
2870  float offset=0;
2871  float shift=0;
2872  float position=0;
2873  float lambda=0;
2874  float wave=0;
2875  int i=0;
2876  int j=0;
2877  int k=0; /*, l, m*/
2878  int n=0;
2879  int c=0;
2880  int z=0;
2881  int col=0;/*, firstj*/
2882  int found=0;/*lin,*/
2883  int line=0;
2884  int result=0;
2885  float cenpos=0;
2886  float angst=0;
2887  float a_initial=0;
2888 
2889  int* foundit=NULL ;
2890  float* shift_col=NULL ;
2891  float* wave_cor=NULL ;
2892  double* a=NULL ;
2893  double* zroot=NULL ;
2894 
2895  gsl_poly_complex_workspace * w=NULL ;
2896  Vector * vline=NULL;
2897  int * mpar=NULL;
2898  float * xdat=NULL;
2899  float * wdat=NULL;
2900  int lx=0;
2901  int ly=0;
2902  /* float* pdata=NULL; */
2903 
2904  if ( lineIm == NULL )
2905  {
2906  sinfo_msg_error (" no input image given!\n") ;
2907  return FLAG ;
2908  }
2909  lx=cpl_image_get_size_x(lineIm);
2910  ly=cpl_image_get_size_y(lineIm);
2911  /* pdata=cpl_image_get_data_float(lineIm); */
2912 
2913 
2914  if ( coeffs == NULL )
2915  {
2916  sinfo_msg_error (" no coefficient sinfo_matrix given!\n") ;
2917  return FLAG ;
2918  }
2919  if ( par == NULL )
2920  {
2921  sinfo_msg_error (" no fit parameters given!\n") ;
2922  return FLAG ;
2923  }
2924  if ( n_fitcoeffs < 2 )
2925  {
2926  sinfo_msg_error (" wrong number of polynomial coefficients given!\n") ;
2927  return FLAG ;
2928  }
2929  if ( wavelength == NULL || intensity == NULL )
2930  {
2931  sinfo_msg_error (" no line list given!\n") ;
2932  return FLAG ;
2933  }
2934  if ( fwhm <= 0 )
2935  {
2936  sinfo_msg_error (" wrong guess fwhm given!\n") ;
2937  return FLAG ;
2938  }
2939  if ( width <= 0 )
2940  {
2941  sinfo_msg_error (" wrong half width given!\n") ;
2942  return FLAG ;
2943  }
2944  if ( min_amplitude <= 0 )
2945  {
2946  sinfo_msg_error (" wrong guess amplitude given!\n") ;
2947  return FLAG ;
2948  }
2949 
2950  /* allocate memory for the spectral sinfo_vector */
2951  if ( NULL == (vline = sinfo_new_vector (2*width + 1)) )
2952  {
2953  sinfo_msg_error (" cannot allocate new Vector \n") ;
2954  return -14 ;
2955  }
2956  /* allocate memory */
2957  xdat = (float *) cpl_calloc( vline -> n_elements, sizeof (float) ) ;
2958  wdat = (float *) cpl_calloc( vline -> n_elements, sizeof (float) ) ;
2959  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
2960 
2961 
2962  foundit=cpl_calloc(par[0]->n_params,sizeof(int)) ;
2963  shift_col=cpl_calloc(lx,sizeof(float)) ;
2964  wave_cor=cpl_calloc(n_lines,sizeof(float)) ;
2965  a=cpl_calloc(n_fitcoeffs,sizeof(float)) ;
2966  zroot=cpl_calloc(2*(n_fitcoeffs - 1),sizeof(float)) ;
2967 
2968 
2969 
2970  /* determine the approximate line positions using the line list and the
2971  coefficients */
2972  /* find out if Angstroem or microns are used */
2973  if ( wavelength[0] > 10000. )
2974  {
2975  /* Angstroem */
2976  angst = 10000. ;
2977  }
2978  else if ( wavelength[0] > 1000. && wavelength[0] < 10000. )
2979  {
2980  /* nanometers */
2981  angst = 1000. ;
2982  }
2983  else
2984  {
2985  /* microns */
2986  angst = 1. ;
2987  }
2988  offset = ((float) ly -1.) / 2. ;
2989 
2990  k = 0 ;
2991  for ( col = 10 ; col < 25 ; col++ )
2992  {
2993  /* determine the coefficients by using the given bcoefs */
2994  for ( i = 0 ; i < n_fitcoeffs ; i++ )
2995  {
2996  /* initialize coefficients and solution */
2997  if (i < n_fitcoeffs-1)
2998  {
2999  zroot[2*i] = 0. ;
3000  zroot[2*i+1] = 0. ;
3001  }
3002  a[i] = coeffs[i][col] ;
3003  }
3004  a_initial = a[0] ;
3005 
3006  /* go through the lines */
3007  for ( line = 0 ; line < n_lines ; line++ )
3008  {
3009  /* go from Angstroem to micron */
3010  wave_cor[line] = wavelength[line]/angst ;
3011  if (line > 0 && line < n_lines-1)
3012  {
3013  if (fabs((wave_cor[line] - wave_cor[line-1]) /
3014  dispersion ) < 2*width ||
3015  fabs((wave_cor[line] - wave_cor[line+1]) /
3016  dispersion ) < 2*width )
3017  {
3018  continue ;
3019  }
3020  }
3021 
3022  a[0] = a_initial - wave_cor[line] ;
3023 
3024  if (NULL==(w=sinfo_gsl_poly_complex_workspace_alloc(n_fitcoeffs)))
3025  {
3026  sinfo_msg_error(" could not allocate complex workspace!") ;
3027  return FLAG ;
3028  }
3029  if (-1 == sinfo_gsl_poly_complex_solve(a, n_fitcoeffs, w, zroot))
3030  {
3031  sinfo_msg_error(" sinfo_gsl_poly_complex_solve did not work!") ;
3032  return FLAG ;
3033  }
3034  sinfo_gsl_poly_complex_workspace_free(w) ;
3035 
3036  j = 0 ;
3037  found = -1 ;
3038  for ( i = 0 ; i < n_fitcoeffs - 1 ; i++ )
3039  {
3040  /* test for appropriate solution */
3041  if( (zroot[2*i] > (-1.)*(float) ly/2. &&
3042  zroot[2*i] < (float)ly/2.) && zroot[2*i+1] == 0. )
3043  {
3044  found = 2*i ;
3045  j ++ ;
3046  }
3047  else
3048  {
3049  continue ;
3050  }
3051  }
3052 
3053  if ( j == 0 )
3054  {
3055  sinfo_msg_warning(" no offset solution found for line %d "
3056  "in column %d\n", line, col) ;
3057  continue ;
3058  }
3059  else if ( j == 1 )
3060  {
3061  cenpos = zroot[found] + (float)ly / 2. ; ;
3062  }
3063  else
3064  {
3065  sinfo_msg_warning(" two or more offset solutions found for \
3066  line %d in column %d\n", line, col) ;
3067  continue ;
3068  }
3069 
3070  if ( cenpos <= 0 )
3071  {
3072  continue ;
3073  }
3074 
3075  /* --------------------------------------------------------------
3076  * fit the single lines using sinfo_linefit and store the
3077  * parameters in
3078  * an array of the FitParams data structure allParams[].
3079  */
3080  if ( (result = sinfo_new_line_fit ( lineIm, par[k],
3081  fwhm, line, col,
3082  width, cenpos, min_amplitude, vline,
3083  mpar, xdat, wdat ) ) < 0 )
3084  {
3085  sinfo_msg_debug ("sinfo_linefit failed, error no.: %d, "
3086  "column: %d, row: %f, line: %d\n",
3087  result, col, cenpos, line) ;
3088  continue ;
3089  }
3090  if ( (par[k] -> fit_par[0] <= 0.) || (par[k] -> fit_par[1] <= 0.)
3091  || (par[k] -> fit_par[2] <= 0.) )
3092  {
3093  sinfo_msg_warning ("negative fit parameters in column: %d, "
3094  "line: %d\n", col, line) ;
3095  continue ;
3096  }
3097  par[k] -> wavelength = wavelength[line] ;
3098  k++ ;
3099  }
3100 
3101  }
3102 
3103  /* free memory */
3104  sinfo_new_destroy_vector(vline);
3105  cpl_free(xdat);
3106  cpl_free(wdat);
3107  cpl_free(mpar);
3108 
3109 
3110  c = 0 ;
3111  for ( col = 10 ; col < 25 ; col++ )
3112  {
3113  n = 0 ;
3114  for ( i = 0 ; i < k ; i++ )
3115  {
3116  if (par[i]->column == col && par[i]->fit_par[2] != 0. &&
3117  par[i]->fit_par[1] > 1. && par[i]->fit_par[1] < 7. )
3118  {
3119  foundit[n] = i ;
3120  n++ ;
3121  }
3122  }
3123  if ( n == 0 ) continue ;
3124 
3125  shift = 0 ;
3126  z = 0 ;
3127  for ( j = 0 ; j < n ; j++ )
3128  {
3129  position = par[foundit[j]]->fit_par[2] ;
3130  lambda = par[foundit[j]]->wavelength ;
3131  line = par[foundit[j]]->line ;
3132  if (line > 0 && line < n_lines-1)
3133  {
3134  if (fabs((wave_cor[line] - wave_cor[line-1]) /
3135  dispersion ) < 2*width ||
3136  fabs((wave_cor[line] - wave_cor[line+1]) /
3137  dispersion ) < 2*width )
3138  {
3139  continue ;
3140  }
3141  }
3142  wave = 0 ;
3143  for ( i = 0 ; i < n_fitcoeffs ; i++ )
3144  {
3145  wave += coeffs[i][col]*pow(position-offset, i) ;
3146  }
3147  shift += lambda - wave ;
3148  z++ ;
3149  }
3150  shift_col[c] = shift/(float)z ;
3151  c++ ;
3152  }
3153  if ( c > 0 )
3154  {
3155  wave_shift = sinfo_new_clean_mean(shift_col, c, 10., 10.) ;
3156  sinfo_msg("overall positioning error in microns: %g", wave_shift) ;
3157  }
3158 
3159  /* determine positioning error for each found line */
3160  for ( line = 0 ; line < n_lines ; line++ )
3161  {
3162  if (line > 0 && line < n_lines-1)
3163  {
3164  if (fabs((wave_cor[line] - wave_cor[line-1]) / dispersion ) <
3165  2*width ||
3166  fabs((wave_cor[line] - wave_cor[line+1]) / dispersion ) <
3167  2*width )
3168  {
3169  continue ;
3170  }
3171  }
3172 
3173  c = 0 ;
3174  for ( col = 10 ; col < 25 ; col++ )
3175  {
3176  shift_col[c] = 0. ;
3177  found = -1 ;
3178  for ( i = 0 ; i < k ; i++ )
3179  {
3180  if (par[i]->column == col && par[i]->fit_par[2] != 0. &&
3181  par[i]->fit_par[1] > 1. && par[i]->fit_par[1] < 7. &&
3182  par[i]->line == line )
3183  {
3184  found = i ;
3185  }
3186  }
3187  if (found == -1) break ;
3188 
3189  position = par[found]->fit_par[2] ;
3190  lambda = par[found]->wavelength ;
3191  wave = 0 ;
3192  for ( i = 0 ; i < n_fitcoeffs ; i++ )
3193  {
3194  wave += coeffs[i][col]*pow(position-offset, i) ;
3195  }
3196  shift_col[c] = lambda - wave ;
3197  c++ ;
3198  }
3199  if (found != -1 && c > 0 )
3200  {
3201  sinfo_msg("shift in microns: %g at wavelength: %f\n",
3202  sinfo_new_clean_mean(shift_col, c, 20., 20.), lambda) ;
3203  }
3204  }
3205 
3206 
3207 
3208  cpl_free(foundit) ;
3209  cpl_free(shift_col) ;
3210  cpl_free(wave_cor) ;
3211  cpl_free(a) ;
3212  cpl_free(zroot) ;
3213 
3214  return wave_shift ;
3215 }
3216 
3217 
3218 
3243 static int
3244 sinfo_new_spred_coeffs_cross_slit_fit ( int n_columns,
3245  float ** acoefs,
3246  float ** dacoefs,
3247  Bcoeffs* bco,
3248  float sigma_factor,
3249  float dispersion,
3250  float pixel_dist,
3251  float * chisq,
3252  float ** sinfo_slit_pos )
3253 {
3254  float col_index;
3255 
3256 
3257  float ** ucoefs, **vcoefs, **covar ;
3258  float * acoefsclean ;
3259  double sum, sumq, mean ;
3260  double sigma ;
3261  double cliphi, cliplo ;
3262  float offset ;
3263  float threshold ;
3264 
3265  int* edge=NULL ;
3266  float* sub_col_index=NULL ;
3267  float* sub_acoefs=NULL;
3268  float* sub_dacoefs=NULL ;
3269  float* wcoefs=NULL ;
3270 
3271 
3272  int ed1, ed2 ;
3273  int i, n, num, ndata ;
3274  int nc, ns ;
3275  int loc_index ;
3276  int sl_index;
3277  int last_i=PIXEL;
3278 
3279  if ( n_columns < 1 )
3280  {
3281  sinfo_msg_error(" wrong number of image columns given\n") ;
3282  return -1 ;
3283  }
3284  if ( acoefs == NULL || dacoefs == NULL )
3285  {
3286  sinfo_msg_error(" acoeffs or errors of coefficients are not given") ;
3287  return -1 ;
3288  }
3289  if ( bco == NULL )
3290  {
3291  sinfo_msg_error(" bcoeffs are not allocated\n") ;
3292  return -1 ;
3293  }
3294  if ( sigma_factor <= 0. )
3295  {
3296  sinfo_msg_error(" impossible sigma_factor given!\n") ;
3297  return -1 ;
3298  }
3299  if ( dispersion == 0. )
3300  {
3301  sinfo_msg_error(" impossible dispersion given!\n") ;
3302  return -1 ;
3303  }
3304 
3305 
3306  edge=cpl_calloc(bco->n_slitlets,sizeof(int)) ;
3307  sub_col_index=cpl_calloc(n_columns,sizeof(float)) ;
3308  sub_acoefs=cpl_calloc(n_columns,sizeof(float));
3309  sub_dacoefs=cpl_calloc(n_columns,sizeof(float)) ;
3310 
3311  wcoefs=cpl_calloc(bco->n_bcoeffs,sizeof(float)) ;
3312 
3313  /*------------------------------------------------------------------------
3314  * search for the slitlet edges by comparing the a0 coefficients along i
3315  * the columns
3316  * if a bigger deviation occurrs it is assumed that there is an edge.
3317  */
3318  n = 0 ;
3319  threshold = pixel_dist * fabs(dispersion) ;
3320  sinfo_slit_pos[0][0]=0 ;
3321  sl_index = 0;
3322  /* it was for ( i = PIXEL ; i < n_columns - PIXEL ; ) */
3323  for ( i = 0 ; i < n_columns - PIXEL ; )
3324  {
3325  if ( !isnan(acoefs[0][i+1]) &&
3326  acoefs[0][i+1] != 0. &&
3327  acoefs[0][i] != 0.
3328  && dacoefs[0][i+1] != 0.)
3329  {
3330  if ( isnan(acoefs[0][i]) || acoefs[0][i] == 0. )
3331  {
3332  if (fabs(acoefs[0][i+1] - acoefs[0][i-1]) >= threshold )
3333  {
3334  /* printf("case a pos1 %d pos2 %d \n",i,i+1); */
3335  edge[n] = i+1 ;
3336  sinfo_slit_pos[sl_index][1] = i ;
3337  sinfo_slit_pos[sl_index+1][0] = i + 1 ;
3338  sl_index++;
3339  n++ ;
3340  last_i = i;
3341  i += PIXEL ;
3342  }
3343  }
3344  else
3345  {
3346  if (fabs(acoefs[0][i+1] - acoefs[0][i]) >= threshold )
3347  {
3348  /* printf("case b pos1 %d pos2 %d \n",i,i+1); */
3349  edge[n] = i+1 ;
3350  sinfo_slit_pos[sl_index][1] = i ;
3351  sinfo_slit_pos[sl_index+1][0] = i + 1 ;
3352  sl_index++;
3353  n++ ;
3354  last_i = i;
3355  i += PIXEL ;
3356  }
3357  }
3358 
3359 
3360  /* sometimes a slitlet may be lost due to divergences in
3361  acoeffs[0] we try to recover it */
3362  if( ( (i-last_i) > 63 ) &&
3363  ( isnan(fabs(acoefs[0][i+1] - acoefs[0][i])) ||
3364  isnan(fabs(acoefs[0][i+1] - acoefs[0][i-1])) ) )
3365  {
3366  edge[n] = i+1 ;
3367  sinfo_slit_pos[sl_index][1] = i ;
3368  sinfo_slit_pos[sl_index+1][0] = i + 1 ;
3369  sl_index++;
3370  n++ ;
3371 
3372  last_i = i;
3373  sinfo_msg_warning("2 recovered slitlet edge i=%d",i);
3374  i += PIXEL ;
3375 
3376  }
3377  }
3378  i++ ;
3379  }
3380  sinfo_slit_pos[sl_index][1] = 2047;
3381  /* printf("2 Found n slitlest: %d check %d\n", n,bco->n_slitlets - 1); */
3382  if ( n != bco->n_slitlets - 1 )
3383  {
3384  sinfo_msg_error("could not find the right number of "
3385  "slitlets, found: %d\n",n+1) ;
3386  return -1 ;
3387  }
3388 
3389  /* go through the coefficents indices */
3390  for ( loc_index = 0 ; loc_index < bco->n_acoeffs ; loc_index++ )
3391  {
3392  /* go through the single slitlets */
3393  for ( ns = 0 ; ns < bco->n_slitlets ; ns++ )
3394  {
3395  /* determine the slitlet edges */
3396  if ( ns == 0 )
3397  {
3398  ed1 = 0 ;
3399  ed2 = edge[0] ;
3400  }
3401  else if ( ns == bco->n_slitlets - 1 )
3402  {
3403  ed1 = edge[bco->n_slitlets - 2] ;
3404  ed2 = n_columns ;
3405  }
3406  else
3407  {
3408  ed1 = edge[ns-1] ;
3409  ed2 = edge[ns] ;
3410  }
3411 
3412  nc = 0 ;
3413  for ( i = ed1 ; i < ed2 ; i++ )
3414  {
3415  if ( isnan(acoefs[loc_index][i]) ||
3416  acoefs[loc_index][i] == 0. ||
3417  dacoefs[loc_index][i] == 0. )
3418  {
3419  continue ;
3420  }
3421  else
3422  {
3423  nc++ ;
3424  }
3425  }
3426  if (NULL==(acoefsclean=(float*) cpl_calloc(nc , sizeof(float))) )
3427  {
3428  sinfo_msg_error("could not allocate memory for acoefsclean!");
3429  return -1 ;
3430  }
3431  nc = 0 ;
3432  for ( i = ed1 ; i < ed2 ; i++ )
3433  {
3434  if ( isnan(acoefs[loc_index][i]) ||
3435  acoefs[loc_index][i] == 0. ||
3436  dacoefs[loc_index][i] == 0. )
3437  {
3438  continue ;
3439  }
3440  else
3441  {
3442  acoefsclean[nc] = acoefs[loc_index][i] ;
3443  nc++ ;
3444  }
3445  }
3446 
3447  /* ----------------------------------------------------------
3448  * determine the clean mean and sigma value of the coefficients,
3449  * that means reject 10 % of the extreme low and high values
3450  */
3451  sinfo_pixel_qsort(acoefsclean, nc) ;
3452 
3453  sum = 0. ;
3454  sumq = 0. ;
3455  mean = 0. ;
3456  sigma = 0. ;
3457  n = 0 ;
3458  for ( i = (int)((float)nc*LOW_REJECT) ;
3459  i < (int)((float)nc*HIGH_REJECT) ; i++ )
3460  {
3461  sum += (double)acoefsclean[i] ;
3462  sumq += ((double)acoefsclean[i] * (double)acoefsclean[i]) ;
3463  n ++ ;
3464  }
3465  mean = sum/(double)n ;
3466  sigma = sqrt( sumq/(double)n - (mean * mean) ) ;
3467  cliphi = mean + sigma * (double)sigma_factor ;
3468  cliplo = mean - sigma * (double)sigma_factor ;
3469  /* fit only the reasonnable values */
3470  num = 0 ;
3471  col_index = 0 ;
3472  for ( i = ed1 ; i < ed2 ; i++ )
3473  {
3474  /* take only the reasonnable coefficients */
3475  if ( !isnan(acoefs[loc_index][i]) &&
3476  (acoefs[loc_index][i] <= cliphi) &&
3477  (acoefs[loc_index][i] >= cliplo) &&
3478  (dacoefs[loc_index][i] != 0. ) &&
3479  (acoefs[loc_index][i] != 0.) )
3480  {
3481  sub_acoefs[num] = acoefs[loc_index][i] ;
3482  sub_dacoefs[num] = dacoefs[loc_index][i] ;
3483  sub_col_index[num] = col_index ;
3484  num ++ ;
3485  }
3486  col_index++ ;
3487  }
3488  ndata = num ;
3489  offset = (float)(col_index-1) / 2. ;
3490 
3491  if ( ndata < bco->n_bcoeffs )
3492  {
3493  sinfo_msg_error(" not enough data found in slitlet %da"
3494  " to determine the fit coefficients.\n", ns) ;
3495  cpl_free(acoefsclean) ;
3496  return -1 ;
3497  }
3498 
3499  /* allocate coefficient matrices */
3500  ucoefs = sinfo_matrix(1, ndata, 1, bco->n_bcoeffs) ;
3501  vcoefs = sinfo_matrix(1, ndata, 1, bco->n_bcoeffs) ;
3502  covar = sinfo_matrix(1, bco->n_bcoeffs, 1, bco->n_bcoeffs) ;
3503 
3504  /* scale the x-values for the fit */
3505  for ( i = 0 ; i < ndata ; i++ )
3506  {
3507  sub_col_index[i] = (sub_col_index[i] - offset) / offset ;
3508  }
3509 
3510  /* finally, do the singular value decomposition fit */
3511  sinfo_svd_fitting ( sub_col_index-1, sub_acoefs-1,
3512  sub_dacoefs-1, ndata, bco[ns].b[loc_index]-1,
3513  bco->n_bcoeffs, ucoefs, vcoefs, wcoefs-1,
3514  covar, &chisq[ns], sinfo_fpol ) ;
3515 
3516  /* scale the found coefficients */
3517  for ( i = 0 ; i < bco->n_bcoeffs ; i ++ )
3518  {
3519  bco[ns].b[loc_index][i] /= pow( offset, i ) ;
3520  }
3521 
3522  /* free memory */
3523  cpl_free (acoefsclean) ;
3524  sinfo_free_matrix( ucoefs, 1/*, ndata*/, 1/*, bco->n_bcoeffs */) ;
3525  sinfo_free_matrix( vcoefs, 1/*, ndata*/, 1/*, bco->n_bcoeffs */) ;
3526  sinfo_free_matrix( covar, 1/*, bco->n_bcoeffs*/,
3527  1/*, bco->n_bcoeffs */) ;
3528 
3529  /* now calculate the smoothed acoefs for each column */
3530  col_index = 0 ;
3531  for ( i = ed1 ; i < ed2 ; i++ )
3532  {
3533  acoefs[loc_index][i] = 0. ;
3534  for ( n = 0 ; n < bco->n_bcoeffs ; n++ )
3535  {
3536  acoefs[loc_index][i] += bco[ns].b[loc_index][n] *
3537  pow(col_index - offset, n) ;
3538  }
3539  col_index++ ;
3540  }
3541 
3542  }
3543  }
3544 
3545 
3546  cpl_free(edge) ;
3547  cpl_free(sub_col_index) ;
3548  cpl_free(sub_acoefs);
3549  cpl_free(sub_dacoefs) ;
3550  cpl_free(wcoefs) ;
3551 
3552  return 0 ;
3553 }
3554 
3555 
3604 cpl_image * sinfo_new_spred_wave_cal( cpl_image * image,
3605  FitParams ** par ,
3606  float ** abuf,
3607  int n_slitlets,
3608  int ** row_clean,
3609  float ** wavelength_clean,
3610  int * n_found_lines,
3611  float dispersion,
3612  int halfWidth,
3613  float minAmplitude,
3614  float max_residual,
3615  float fwhm,
3616  int n_a_fitcoefs,
3617  int n_b_fitcoefs,
3618  float sigmaFactor,
3619  float pixel_dist,
3620  float pixel_tolerance,
3621  float ** sinfo_slit_pos)
3622 
3623 
3624 {
3625  int i, j;
3626  /* int k ; */
3627  int n_fit ;
3628  int n_reject ;
3629  float * acoefs ;
3630  float * dacoefs ;
3631  float ** dabuf ;
3632  float chisq_poly ;
3633  float * chisq_cross ;
3634  int zeroind ;
3635  int crossInd ;
3636  Bcoeffs * bco ;
3637  cpl_image * wavemap ;
3638  int ilx=0;
3639  int ily=0;
3640  /* float* pidata=NULL; */
3641 
3642 
3643  if ( NULL == image )
3644  {
3645  sinfo_msg_error(" no image given\n") ;
3646  return NULL ;
3647  }
3648  ilx=cpl_image_get_size_x(image);
3649  ily=cpl_image_get_size_y(image);
3650  /* pidata=cpl_image_get_data_float(image); */
3651 
3652  if ( par == NULL )
3653  {
3654  sinfo_msg_error(" no fit parameter data structure given\n") ;
3655  return NULL ;
3656  }
3657  if ( abuf == NULL )
3658  {
3659  sinfo_msg_error(" no buffer for fit coefficients given\n") ;
3660  return NULL ;
3661  }
3662  if ( n_slitlets <= 0 )
3663  {
3664  sinfo_msg_error(" impossible number of slitlets given\n") ;
3665  return NULL ;
3666  }
3667  if ( row_clean == NULL )
3668  {
3669  sinfo_msg_error(" no row_clean array given\n") ;
3670  return NULL ;
3671  }
3672  if ( wavelength_clean == NULL )
3673  {
3674  sinfo_msg_error(" no wavelength_clean array given\n") ;
3675  return NULL ;
3676  }
3677 
3678  if ( dispersion == 0. )
3679  {
3680  sinfo_msg_error(" impossible dispersion given\n") ;
3681  return NULL ;
3682  }
3683 
3684  if ( halfWidth <= 0 || halfWidth > ily/2 )
3685  {
3686  sinfo_msg_error(" impossible half width of the fitting box given\n") ;
3687  return NULL ;
3688  }
3689  if ( minAmplitude < 1. )
3690  {
3691  sinfo_msg_error(" impossible minimal amplitude\n") ;
3692  return NULL ;
3693  }
3694 
3695  if ( max_residual <= 0. || max_residual > 1. )
3696  {
3697  sinfo_msg_error(" impossible max_residual given\n") ;
3698  return NULL ;
3699  }
3700  if ( fwhm <= 0. || fwhm > 10. )
3701  {
3702  sinfo_msg_error(" impossible fwhm given\n") ;
3703  return NULL ;
3704  }
3705 
3706  if ( n_a_fitcoefs <= 0 || n_a_fitcoefs > 9 )
3707  {
3708  sinfo_msg_error(" unrealistic n_a_fitcoefs given\n") ;
3709  return NULL ;
3710  }
3711 
3712  if ( n_b_fitcoefs <= 0 || n_b_fitcoefs > 9 )
3713  {
3714  sinfo_msg_error(" unrealistic n_b_fitcoefs given\n") ;
3715  return NULL ;
3716  }
3717  if ( sigmaFactor <= 0. )
3718  {
3719  sinfo_msg_error(" impossible sigmaFactor given\n") ;
3720  return NULL ;
3721  }
3722 
3723  /* initialize the variables */
3724  n_reject = 0 ;
3725  n_fit = 0 ;
3726 
3727  /* fit each found line by using a sinfo_gaussian function and
3728  determine the exact position */
3729  if ( 0 > (n_fit = sinfo_new_fit_lines( image , par, fwhm, n_found_lines,
3730  row_clean, wavelength_clean,
3731  halfWidth, minAmplitude )) )
3732  {
3733  sinfo_msg_error(" cannot fit the lines, error code of "
3734  "sinfo_fitLines: %d", n_fit) ;
3735  return NULL ;
3736  }
3737 
3738  /* first check for faked lines like bad pixels */
3739  if ( -1 == sinfo_new_check_for_fake_lines (par,
3740  dispersion,
3741  wavelength_clean,
3742  row_clean,
3743  n_found_lines,
3744  ilx,
3745  pixel_tolerance) )
3746  {
3747  sinfo_msg_error(" cannot fit the lines, error code of "
3748  " sinfo_fitLines: %d\n", n_fit) ;
3749  return NULL ;
3750  }
3751 
3752 
3753  /* allocate memory */
3754  if (NULL==(acoefs = (float*) cpl_calloc (n_a_fitcoefs, sizeof(float))) ||
3755  NULL==(dacoefs = (float*) cpl_calloc (n_a_fitcoefs, sizeof(float))) ||
3756  NULL==(dabuf = (float**) cpl_calloc (n_a_fitcoefs, sizeof(float*))) ||
3757  NULL==(chisq_cross = (float*) cpl_calloc(n_slitlets, sizeof(float))) )
3758  {
3759  sinfo_msg_error(" cannot allocate memory\n") ;
3760  return NULL ;
3761  }
3762  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
3763  {
3764  if ( NULL == (dabuf[i] = (float*) cpl_calloc(ilx, sizeof(float))) )
3765  {
3766  sinfo_msg_error(" cannot allocate memory\n") ;
3767  cpl_free ( acoefs ) ;
3768  cpl_free ( dacoefs ) ;
3769  cpl_free ( chisq_cross ) ;
3770  cpl_free(dabuf) ;
3771  return NULL ;
3772  }
3773  }
3774 
3775  /* fit wavelengths to the corresponding found positions for each column */
3776  /* k = 0 ; */
3777  for ( i = 0 ; i < ilx ; i++ )
3778  {
3779  zeroind = 0 ;
3780  if ( FLT_MAX == (chisq_poly = sinfo_new_polyfit( par, i,
3781  n_found_lines[i],
3782  ily, dispersion,
3783  max_residual, acoefs,
3784  dacoefs, &n_reject,
3785  n_a_fitcoefs)) )
3786  {
3787  sinfo_msg_warning (" error in sinfo_polyfit in column: %d\n", i) ;
3788  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
3789  {
3790  acoefs[j] = ZERO ;
3791  dacoefs[j] = ZERO ;
3792  }
3793  }
3794 
3795  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
3796  {
3797 
3798  if ( acoefs[0] <= 0. || acoefs[1] ==0. ||
3799  dacoefs[j] == 0. || isnan(acoefs[j]) )
3800  {
3801  zeroind = 1 ;
3802  }
3803  }
3804  for ( j = 0 ; j < n_a_fitcoefs ; j++ )
3805  {
3806  if ( zeroind == 0 )
3807  {
3808  abuf[j][i] = acoefs[j] ;
3809  dabuf[j][i] = dacoefs[j] ;
3810  }
3811  else
3812  {
3813  abuf[j][i] = ZERO ;
3814  dabuf[j][i] = ZERO ;
3815  }
3816  }
3817  }
3818 
3819  /* allocate memory for the fitting coefficients */
3820  if ( NULL == ( bco = sinfo_new_b_coeffs( n_slitlets,
3821  n_a_fitcoefs, n_b_fitcoefs)) )
3822  {
3823  sinfo_msg_error (" cannot allocate memory for the bcoeffs\n") ;
3824  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
3825  {
3826  cpl_free (dabuf[i]) ;
3827  }
3828  cpl_free (dabuf) ;
3829  cpl_free ( acoefs ) ;
3830  cpl_free ( dacoefs ) ;
3831  cpl_free ( chisq_cross ) ;
3832  return NULL ;
3833  }
3834 
3835  /* fit each acoefs across the slitlets to smooth the result */
3836  if ( -1 == ( crossInd = sinfo_new_spred_coeffs_cross_slit_fit( ilx, abuf,
3837  dabuf,
3838  bco, sigmaFactor,
3839  dispersion,
3840  pixel_dist,
3841  chisq_cross,
3842  sinfo_slit_pos )) )
3843  {
3844  sinfo_msg_error (" cannot carry out the fitting of "
3845  "coefficients across the columns\n") ;
3846  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
3847  {
3848  cpl_free (dabuf[i]) ;
3849  }
3850 
3851  cpl_free (dabuf) ;
3852  cpl_free ( acoefs ) ;
3853  cpl_free ( dacoefs ) ;
3854  sinfo_new_destroy_b_coeffs(bco) ;
3855  cpl_free ( chisq_cross ) ;
3856  return NULL ;
3857  }
3858 
3859  if ( NULL == (wavemap = sinfo_new_wave_map_slit (abuf, n_a_fitcoefs,
3860  ily, ilx)))
3861  {
3862  sinfo_msg_error (" cannot carry out wavemap creation\n") ;
3863  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
3864  {
3865  cpl_free (dabuf[i]) ;
3866  }
3867 
3868  cpl_free (dabuf) ;
3869  cpl_free ( acoefs ) ;
3870  cpl_free ( dacoefs ) ;
3871  sinfo_new_destroy_b_coeffs(bco) ;
3872  cpl_free ( chisq_cross ) ;
3873  return NULL ;
3874  }
3875 
3876  /* free all allocated memory */
3877  for ( i = 0 ; i < n_a_fitcoefs ; i++ )
3878  {
3879  cpl_free (dabuf[i]) ;
3880  }
3881  cpl_free (dabuf) ;
3882  cpl_free ( acoefs ) ;
3883  cpl_free ( dacoefs ) ;
3884  sinfo_new_destroy_b_coeffs(bco) ;
3885  cpl_free ( chisq_cross ) ;
3886 
3887  return wavemap ;
3888 }
3889 
3891 /*___oOo___*/