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