SINFONI Pipeline Reference Manual  2.6.0
sinfo_cube_construct.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 * who when what
23 * -------- -------- ----------------------------------------------
24 * schreib 30/08/00 created
25 */
26 
27 /************************************************************************
28 * NAME
29 * sinfo_cube_construct.c -
30 *------------------------------------------------------------------------
31 */
32 
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
36 #define POSIX_SOURCE 1
37 #include "sinfo_vltPort.h"
38 
39 /*
40  * System Headers
41  */
42 
43 /*
44  * Local Headers
45  */
46 #include "sinfo_function_1d.h"
47 #include "sinfo_cube_construct.h"
48 #include "sinfo_spectrum_ops.h"
49 #include "sinfo_wave_calibration.h"
50 #include "sinfo_utilities.h"
51 #include "sinfo_utils_wrappers.h"
52 #include "sinfo_local_types.h"
53 #include "sinfo_fft_base.h"
54 
55 static int
56 sinfo_sort_slitlets(const int kslit);
57 
58 
59 static int
60 sinfo_sort_slitlets_array(const int slit, int* row_index);
61 
69 /*----------------------------------------------------------------------------
70  * Function codes
71  *--------------------------------------------------------------------------*/
86 cpl_image *
87 sinfo_new_convolve_ns_image_by_gauss( cpl_image * lineImage,
88  int hw )
89 {
90  cpl_image * returnImage ;
91  float* row_buffer=NULL ;
92  float * filter ;
93  int col, row ;
94  int ilx=0;
95  int ily=0;
96 
97  float* pidata=NULL;
98  float* podata=NULL;
99 
100  if ( lineImage == NULL )
101  {
102  sinfo_msg_error("no input image given!\n") ;
103  return NULL ;
104  }
105  ilx=cpl_image_get_size_x(lineImage);
106  ily=cpl_image_get_size_y(lineImage);
107  pidata=cpl_image_get_data_float(lineImage);
108  if ( hw < 1 )
109  {
110  sinfo_msg_error(" wrong half width given!\n") ;
111  return NULL ;
112  }
113 
114  /* allocate memory for returned image */
115  if ( NULL == ( returnImage = cpl_image_new(ilx,ily,CPL_TYPE_FLOAT ) ))
116  {
117  sinfo_msg_error("cannot allocate a new image\n");
118  return NULL ;
119  }
120  podata=cpl_image_get_data_float(returnImage);
121 
122  /* go through the image rows and save them in a buffer */
123  row_buffer=cpl_calloc(ily,sizeof(float)) ;
124 
125  for ( row = 0 ; row < ily ; row++ )
126  {
127  for ( col = 0 ; col < ilx ; col++ )
128  {
129  if ( isnan(pidata[col+row*ilx]) )
130  {
131  row_buffer[col] = 0. ;
132  }
133  else
134  {
135  row_buffer[col] = pidata[col + row*ilx] ;
136  }
137  }
138 
139  /*--------------------------------------------------------------------
140  * now low pass filter the rows by the gaussian and fill the return
141  * image.
142  */
143  filter = sinfo_function1d_filter_lowpass( row_buffer,
144  ilx,
145  LOW_PASS_GAUSSIAN,
146  hw ) ;
147  for ( col = 0 ; col < ily ; col++ )
148  {
149  podata[col + row*ilx] = filter[col] ;
150  }
151  /* deallocate memory */
152  sinfo_function1d_del (filter) ;
153  }
154  cpl_free(row_buffer);
155  return returnImage ;
156 }
157 
178 float *
179 sinfo_north_south_test( cpl_image * ns_image,
180  int n_slitlets,
181  int halfWidth,
182  float fwhm,
183  float minDiff,
184  float estimated_dist,
185  float devtol,
186  int bottom,
187  int top )
188 {
189  int i, j, k, m, row, col, n, ni, na ;
190  int position, counter;
191  int xdim, ndat, its, numpar ;
192  pixelvalue row_buf[cpl_image_get_size_x(ns_image)] ;
193  float sum, mean, maxval ;
194  float tol, lab ;
195  float * distances ;
196  float distances_buf[cpl_image_get_size_y(ns_image)][n_slitlets-1] ;
197  float x_position[n_slitlets] ;
198  float * xdat, * wdat ;
199  int * mpar ;
200  int found[3*n_slitlets], found_clean[3*n_slitlets] ;
201  int found_cleanit[3*n_slitlets] ;
202  Vector * line ;
203  FitParams ** par ;
204  int foundit, begin, end ;
205  int ilx=0;
206  //int ily=0;
207 
208  float* pidata=NULL;
209 
210  if ( ns_image == NULL )
211  {
212  sinfo_msg_error("sorry, no image given\n") ;
213  return NULL ;
214  }
215  ilx=cpl_image_get_size_x(ns_image);
216  //ily=cpl_image_get_size_y(ns_image);
217  pidata=cpl_image_get_data_float(ns_image);
218 
219 
220  if ( n_slitlets < 1 )
221  {
222  sinfo_msg_error("wrong number of slitlets given\n") ;
223  return NULL ;
224  }
225  if ( halfWidth < 0 || halfWidth >= estimated_dist )
226  {
227  sinfo_msg_error("wrong half width given\n") ;
228  return NULL ;
229  }
230  if ( fwhm <= 0. )
231  {
232  sinfo_msg_error("wrong fwhm given\n") ;
233  return NULL ;
234  }
235  if ( minDiff < 1. )
236  {
237  sinfo_msg_error("wrong minDiff given\n") ;
238  return NULL ;
239  }
240 
241  /* allocate memory for output array */
242  if (NULL == (distances = (float *) cpl_calloc ( n_slitlets - 1 ,
243  sizeof (float) )))
244  {
245  sinfo_msg_error("could not allocate memory\n") ;
246  return NULL ;
247  }
248 
249  /* go through the image rows */
250  for ( row = bottom ; row < top ; row++ )
251  {
252  int zeroindicator = 0 ;
253 
254  /* initialize the distance buffer */
255  for ( i = 0 ; i < n_slitlets-1 ; i++ )
256  {
257  distances_buf[row][i] = ZERO ;
258  }
259 
260  /* fill the row buffer array with image data */
261  for ( col = 0 ; col < ilx ; col++ )
262  {
263  row_buf[col] = pidata[col + row*ilx] ;
264  }
265 
266  /* determine the mean of the row data */
267  sum = 0. ;
268  n = 0 ;
269  for ( i = 0 ; i < ilx ; i++ )
270  {
271  if ( isnan(row_buf[i]) )
272  {
273  continue ;
274  }
275  sum += row_buf[i] ;
276  n++ ;
277  }
278  mean = sum / (float)n ;
279 
280 
281  /* store the positions of image values greater than the mean */
282  n = 0 ;
283  for ( i = 0 ; i < ilx ; i++ )
284  {
285  if (isnan(row_buf[i]))
286  {
287  continue ;
288  }
289  if ( row_buf[i] > sqrt(mean*mean*9) )
290  {
291  found[n] = i ;
292  n++ ;
293  }
294  }
295 
296  if ( n < n_slitlets )
297  {
298  sinfo_msg_warning("t1 wrong number of intensity columns found "
299  "in row: %d, found number: %d, mean: %g",
300  row, n, mean) ;
301  continue ;
302  }
303  else
304  {
305  /* find the maximum value position around the found columns */
306  na = 0 ;
307  for ( i = 1 ; i < n ; i ++ )
308  {
309  if ( found[i] - found[i-1] < halfWidth )
310  {
311  begin = found[i] - halfWidth ;
312  if ( begin < 0 )
313  {
314  begin = 0 ;
315  }
316  end = found[i] + halfWidth ;
317  if ( end >= ilx )
318  {
319  end = ilx - 1 ;
320  }
321  /* find the maximum value inside the box
322  around the found positions*/
323  maxval = -FLT_MAX ;
324  foundit = 0 ;
325  for ( j = begin ; j <= end ; j++ )
326  {
327  /* do not consider boxes that contain bad pixels */
328  if (isnan(row_buf[j]))
329  {
330  continue ;
331  }
332  if (row_buf[j] >= maxval )
333  {
334  maxval = row_buf[j] ;
335  foundit = j ;
336  }
337  }
338  if (maxval == -FLT_MAX)
339  {
340  continue ;
341  }
342  for ( k = 0 ; k < na ; k++ )
343  {
344  if ( found_cleanit[k] >= begin &&
345  found_cleanit[k] < foundit )
346  {
347  na-- ;
348  }
349  }
350  for ( k = 0 ; k < n ; k++ )
351  {
352  if ( found[k] == foundit)
353  {
354  if (na>0){
355  if ( found_cleanit[na-1] != found[k] )
356  {
357  found_cleanit[na] = found[k] ;
358  na++ ;
359  }
360  }
361  else{
362  found_cleanit[na] = found[k] ;
363  na++ ;
364  }
365  }
366  }
367  }
368  else
369  {
370  if ( i == 1 )
371  {
372  found_cleanit[na] = found[0] ;
373  na++ ;
374  found_cleanit[na] = found[1] ;
375  na++ ;
376  }
377  else
378  {
379  if (na>0){
380  if ( found_cleanit[na-1] != found[i-1])
381  {
382  found_cleanit[na] = found[i-1] ;
383  na++ ;
384  }
385  if ( found_cleanit[na-1] != found[i])
386  {
387  found_cleanit[na] = found[i] ;
388  na++ ;
389  }
390  }
391  else
392  {
393  found_cleanit[na] = found[i] ;
394  na++ ;
395  }
396  }
397  }
398  }
399  /* determine only one pixel position for each slitlet intensity */
400  j = 1 ;
401  for ( i = 1 ; i < na ; i++ )
402  {
403  if ( (float)(found_cleanit[i] - found_cleanit[i-1]) <
404  (estimated_dist - devtol) ||
405  (float)(found_cleanit[i] - found_cleanit[i-1]) >
406  (estimated_dist + devtol) )
407  {
408  continue ;
409  }
410  else
411  {
412  found_clean[j-1] = found_cleanit[i-1] ;
413  found_clean[j] = found_cleanit[i] ;
414  j++ ;
415  }
416  }
417  }
418  if ( j > n_slitlets )
419  {
420  /* check the distance again */
421  ni = 1 ;
422  for ( i = 1 ; i < j ; i++ )
423  {
424  if ( (float)(found_clean[i] - found_clean[i-1]) <
425  (estimated_dist - devtol ) ||
426  (float)(found_clean[i] - found_clean[i-1]) >
427  (estimated_dist + devtol ) )
428  {
429  continue ;
430  }
431  else
432  {
433 
434  found_clean[ni-1] = found_clean[i-1] ;
435  found_clean[ni] = found_clean[i] ;
436  ni++ ;
437  }
438  }
439  if ( ni != n_slitlets )
440  {
441  sinfo_msg_warning("t2 wrong number of intensity columns"
442  " found in row: %d, found number: %d",
443  row, ni) ;
444  continue ;
445  }
446  else
447  {
448  j = ni ;
449  }
450  }
451  else if ( j < n_slitlets )
452  {
453  cpl_msg_debug ("north_south_test3:",
454  "t3 wrong number of intensity columns "
455  "found in row: %d , found number: %d, mean: %g\n",
456  row, j, mean) ;
457  continue ;
458  }
459  counter = 0 ;
460  /* go through the found intensity pixels in one row */
461  for ( i = 0 ; i < j ; i++ )
462  {
463  /* allocate memory for the array where the line is fitted in */
464  if ( NULL == (line = sinfo_new_vector (2*halfWidth + 1)) )
465  {
466  sinfo_msg_error ("cannot allocate new Vector \n") ;
467  cpl_free(distances) ;
468  return NULL ;
469  }
470 
471  /* allocate memory */
472  xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
473  wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
474  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
475  par = sinfo_new_fit_params(1) ;
476 
477  m = 0 ;
478  for ( k = found_clean[i]-halfWidth ;
479  k <= found_clean[i]+halfWidth ; k++ )
480  {
481  if ( k < 0 )
482  {
483  k = 0. ;
484  }
485  else if ( k >= ilx )
486  {
487  k = ilx - 1 ;
488  }
489  else if ( isnan(row_buf[k]) )
490  {
491  zeroindicator = 1 ;
492  break ;
493  }
494  else
495  {
496  line -> data[m] = row_buf[k] ;
497  m++ ;
498  }
499  }
500  if ( zeroindicator == 1 )
501  {
502  sinfo_new_destroy_vector(line) ;
503  cpl_free(xdat) ;
504  cpl_free(wdat) ;
505  cpl_free(mpar) ;
506  sinfo_new_destroy_fit_params(&par) ;
507  break ;
508  }
509 
510  /*----------------------------------------------------------------
511  * go through the spectral sinfo_vector
512  * determine the maximum pixel value in the spectral sinfo_vector
513  */
514  maxval = -FLT_MAX ;
515  position = -INT32_MAX ;
516  for ( k = 0 ; k < m ; k++ )
517  {
518  xdat[k] = k ;
519  wdat[k] = 1.0 ;
520  if ( line -> data[k] >= maxval )
521  {
522  maxval = line -> data[k] ;
523  position = k ;
524  }
525  }
526 
527  /* set initial values for the fitting routine */
528  xdim = XDIM ;
529  ndat = line -> n_elements ;
530  numpar = MAXPAR ;
531  tol = TOL ;
532  lab = LAB ;
533  its = ITS ;
534  (*par) -> fit_par[1] = fwhm ;
535  (*par) -> fit_par[2] = (float) position ;
536  (*par) -> fit_par[3] = (float) (line -> data[0] +
537  line -> data[line->n_elements - 1]) / 2.0 ;
538  (*par) -> fit_par[0] = maxval - ((*par) -> fit_par[3]) ;
539 
540 
541  /* exclude negative peaks and low signal cases */
542  if ( (*par) -> fit_par[0] < minDiff )
543  {
544  sinfo_msg_warning ("sorry, signal of line too low to fit "
545  "in row: %d in slitlet %d\n", row, i) ;
546  sinfo_new_destroy_vector(line) ;
547  cpl_free(xdat) ;
548  cpl_free(wdat) ;
549  cpl_free(mpar) ;
550  sinfo_new_destroy_fit_params(&par) ;
551  continue ;
552  }
553 
554  for ( k = 0 ; k < MAXPAR ; k++ )
555  {
556  (*par) -> derv_par[k] = 0.0 ;
557  mpar[k] = 1 ;
558  }
559  /* finally, do the least square fit using a Gaussian */
560  int iters;
561  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim,
562  line -> data, wdat, &ndat,
563  (*par) -> fit_par,
564  (*par) -> derv_par, mpar,
565  &numpar, &tol, &its, &lab)) )
566  {
567  /*
568  cpl_msg_debug ("north_south_test:",
569  "sinfo_lsqfit_c: least squares fit failed,"
570  " error no.: %d in row: %d in slitlet %d\n",
571  iters, row, i) ;
572  */
573  sinfo_new_destroy_vector(line) ;
574  cpl_free(xdat) ;
575  cpl_free(wdat) ;
576  cpl_free(mpar) ;
577  sinfo_new_destroy_fit_params(&par) ;
578  continue ;
579  }
580 
581  /* check for negative fit results */
582  if ( (*par) -> fit_par[0] <= 0. ||
583  (*par) -> fit_par[1] <= 0. ||
584  (*par) -> fit_par[2] < 0. )
585  {
586  sinfo_msg_warning ("negative parameters as fit result, "
587  "not used! in row %d in slitlet %d",
588  row, i) ;
589  sinfo_new_destroy_vector(line) ;
590  cpl_free(xdat) ;
591  cpl_free(wdat) ;
592  cpl_free(mpar) ;
593  sinfo_new_destroy_fit_params(&par) ;
594  continue ;
595  }
596 
597  /* correct the fitted position for the given row of the line
598  in image coordinates */
599  (*par) -> fit_par[2] = (float) (found_clean[i] - halfWidth) +
600  (*par) -> fit_par[2] ;
601  x_position[counter] = (*par) -> fit_par[2] ;
602  counter ++ ;
603 
604  /* free memory */
605  sinfo_new_destroy_fit_params(&par) ;
606  sinfo_new_destroy_vector ( line ) ;
607  cpl_free ( xdat ) ;
608  cpl_free ( wdat ) ;
609  cpl_free ( mpar ) ;
610  }
611  if (zeroindicator == 1)
612  {
613  sinfo_msg_debug ("bad pixel in fitting box in row: %d\n", row) ;
614  continue ;
615  }
616 
617  if ( counter != n_slitlets )
618  {
619  continue ;
620  sinfo_msg_warning("wrong number of slitlets found in row: %d",row);
621  }
622  /* store the distances between the sources in a buffer */
623  for ( i = 1 ; i < n_slitlets ; i++ )
624  {
625  distances_buf[row][i-1] = x_position[i] - x_position[i-1] ;
626  }
627  }
628 
629  /* ----------------------------------------------------------------
630  * go through the rows again and take the mean of the distances,
631  * throw away the runaways
632  */
633  for ( i = 0 ; i < n_slitlets-1 ; i++ )
634  {
635  n = 0 ;
636  sum = 0. ;
637  for ( row = bottom ; row < top ; row++ )
638  {
639  if ( fabs( distances_buf[row][i] - estimated_dist ) > devtol ||
640  isnan(distances_buf[row][i]) )
641  {
642  /*
643  sinfo_msg("dist=%g devtol=%g isan=%d",
644  distances_buf[row][i],
645  devtol,
646  isnan(distances_buf[row][i]));
647  */
648  continue ;
649  }
650  sum += distances_buf[row][i] ;
651  n++ ;
652  }
653  if ( n < 2 )
654  {
655  sinfo_msg_error("distances array could not be determined "
656  "completely!, deviations of distances from number "
657  "of slitlets too big\n" ) ;
658  cpl_free(distances) ;
659  return NULL ;
660  }
661  else
662  {
663  distances[i] = sum / (float)n ;
664  }
665  }
666  return distances ;
667 }
668 
697 cpl_imagelist *
698 sinfo_new_make_cube ( cpl_image * calibImage,
699  float * distances,
700  float * correct_diff_dist )
701 {
702  cpl_imagelist * returnCube ;
703  int imsize;
704  int z, col;
705  int ilx=0;
706  int ily=0;
707 
708  if ( NULL == calibImage )
709  {
710  sinfo_msg_error("no resampled image given!\n") ;
711  return NULL ;
712  }
713  ilx=cpl_image_get_size_x(calibImage);
714  ily=cpl_image_get_size_y(calibImage);
715  float* pidata=cpl_image_get_data_float(calibImage);
716 
717  if ( NULL == distances )
718  {
719  sinfo_msg_error("no distances array from ns_test given!/n") ;
720  return NULL ;
721  }
722 
723  if ( NULL == correct_diff_dist )
724  {
725  sinfo_msg_error("correct_diff_dist array is not allocated!/n") ;
726  return NULL ;
727  }
728 
729  if ( N_SLITLETS != 32 )
730  {
731  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
732  return NULL ;
733  }
734  imsize = ilx / N_SLITLETS ;
735 
736  /* allocate memory */
737  if ( NULL == (returnCube = cpl_imagelist_new()) )
738  {
739  sinfo_msg_error ("cannot allocate new cube \n" ) ;
740  return NULL ;
741  }
742 
743  /* now build the data cube out of the resampled image */
744  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
745  {
746 
747  cpl_image* o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
748  float* podata=cpl_image_get_data_float(o_img);
749  int kpix = 0 ;
750  int kslit = 0 ;
751  int slit_index = -1 ;
752  int recol = -1 ;
753  for ( col = 0 ; col < ilx ; col++ ) /* go through the image columns */
754  {
755  if ( col % imsize == 0 )
756  {
757  recol = 0 ;
758  kslit = col/imsize ;
759  /* sort the slitlets in the right spiffi specific way */
760  if((slit_index=sinfo_sort_slitlets(kslit)) == -1) {
761  sinfo_msg_error("wrong slitlet index: couldn't be a "
762  "spiffi image, there must be 32 slitlets!") ;
763  cpl_imagelist_delete(returnCube) ;
764  return NULL ;
765  }
766 
767  if ( kslit != 0 )
768  {
769  /*--------------------------------------------------------
770  * shift the first pixel by an integer if the absolute
771  * amount of distances[]
772  * is bigger than 0.5
773  */
774  kpix = sinfo_new_nint(distances[kslit-1]) ;
775 
776  /*-----------------------------------------------
777  * now sort the distances array according to the row order
778  * and add a 0 value for the first (reference) slitlet
779  * that means row 8
780  */
781  correct_diff_dist[slit_index] = distances[kslit-1] -
782  (float)kpix ;
783  }
784  /* refer all distances to the first slitlet */
785  else
786  {
787  correct_diff_dist[slit_index] = 0. ;
788  }
789  }
790 
791  /* fill each cube plane with one image row */
792  podata[recol+slit_index*imsize] = pidata[col+kpix+z*ilx];
793  recol++ ;
794 
795  if ( recol > imsize )
796  {
797  sinfo_msg_error("wrong column of reconstructed "
798  "image, shouldn't happen!\n") ;
799  cpl_imagelist_delete(returnCube) ;
800  return NULL ;
801  }
802  }
803  }
804  return returnCube ;
805 }
806 
807 
808 
819 static int
820 sinfo_sort_slitlets(const int kslit)
821 {
822  int slit_index=0;
823 
824  switch (kslit)
825  {
826  case 0:
827  slit_index = 8 ;
828  break ;
829  case 1:
830  slit_index = 7 ;
831  break ;
832  case 2:
833  slit_index = 9 ;
834  break ;
835  case 3:
836  slit_index = 6 ;
837  break ;
838  case 4:
839  slit_index = 10 ;
840  break ;
841  case 5:
842  slit_index = 5 ;
843  break ;
844  case 6:
845  slit_index = 11 ;
846  break ;
847  case 7:
848  slit_index = 4 ;
849  break ;
850  case 8:
851  slit_index = 12 ;
852  break ;
853  case 9:
854  slit_index = 3 ;
855  break ;
856  case 10:
857  slit_index = 13 ;
858  break ;
859  case 11:
860  slit_index = 2 ;
861  break ;
862  case 12:
863  slit_index = 14 ;
864  break ;
865  case 13:
866  slit_index = 1 ;
867  break ;
868  case 14:
869  slit_index = 15 ;
870  break ;
871  case 15:
872  slit_index = 0 ;
873  break ;
874  case 16:
875  slit_index = 31 ;
876  break ;
877  case 17:
878  slit_index = 16 ;
879  break ;
880  case 18:
881  slit_index = 30 ;
882  break ;
883  case 19:
884  slit_index = 17 ;
885  break ;
886  case 20:
887  slit_index = 29 ;
888  break ;
889  case 21:
890  slit_index = 18 ;
891  break ;
892  case 22:
893  slit_index = 28 ;
894  break ;
895  case 23:
896  slit_index = 19 ;
897  break ;
898  case 24:
899  slit_index = 27 ;
900  break ;
901  case 25:
902  slit_index = 20 ;
903  break ;
904  case 26:
905  slit_index = 26 ;
906  break ;
907  case 27:
908  slit_index = 21 ;
909  break ;
910  case 28:
911  slit_index = 25 ;
912  break ;
913  case 29:
914  slit_index = 22 ;
915  break ;
916  case 30:
917  slit_index = 24 ;
918  break ;
919  case 31:
920  slit_index = 23 ;
921  break ;
922  default:
923  sinfo_msg_error("wrong slitlet index: couldn't be a "
924  "spiffi image, there must be 32 slitlets!") ;
925  return -1 ;
926 
927 
928  }
929  return slit_index;
930 
931 }
932 
951 static int
952 sinfo_sort_slitlets_array(const int slit, int* row_index)
953 {
954 
955  switch (slit)
956  {
957  case 0:
958  row_index[0] = 8 ;
959  break ;
960  case 1:
961  row_index[1] = 7 ;
962  break ;
963  case 2:
964  row_index[2] = 9 ;
965  break ;
966  case 3:
967  row_index[3] = 6 ;
968  break ;
969  case 4:
970  row_index[4] = 10 ;
971  break ;
972  case 5:
973  row_index[5] = 5 ;
974  break ;
975  case 6:
976  row_index[6] = 11 ;
977  break ;
978  case 7:
979  row_index[7] = 4 ;
980  break ;
981  case 8:
982  row_index[8] = 12 ;
983  break ;
984  case 9:
985  row_index[9] = 3 ;
986  break ;
987  case 10:
988  row_index[10] = 13 ;
989  break ;
990  case 11:
991  row_index[11] = 2 ;
992  break ;
993  case 12:
994  row_index[12] = 14 ;
995  break ;
996  case 13:
997  row_index[13] = 1 ;
998  break ;
999  case 14:
1000  row_index[14] = 15 ;
1001  break ;
1002  case 15:
1003  row_index[15] = 0 ;
1004  break ;
1005  case 16:
1006  row_index[16] = 31 ;
1007  break ;
1008  case 17:
1009  row_index[17] = 16 ;
1010  break ;
1011  case 18:
1012  row_index[18] = 30 ;
1013  break ;
1014  case 19:
1015  row_index[19] = 17 ;
1016  break ;
1017  case 20:
1018  row_index[20] = 29 ;
1019  break ;
1020  case 21:
1021  row_index[21] = 18 ;
1022  break ;
1023  case 22:
1024  row_index[22] = 28 ;
1025  break ;
1026  case 23:
1027  row_index[23] = 19 ;
1028  break ;
1029  case 24:
1030  row_index[24] = 27 ;
1031  break ;
1032  case 25:
1033  row_index[25] = 20 ;
1034  break ;
1035  case 26:
1036  row_index[26] = 26 ;
1037  break ;
1038  case 27:
1039  row_index[27] = 21 ;
1040  break ;
1041  case 28:
1042  row_index[28] = 25 ;
1043  break ;
1044  case 29:
1045  row_index[29] = 22 ;
1046  break ;
1047  case 30:
1048  row_index[30] = 24 ;
1049  break ;
1050  case 31:
1051  row_index[31] = 23 ;
1052  break ;
1053  default:
1054  sinfo_msg_error("wrong slitlet index: couldn't be a spiffi "
1055  "image, there must be 32 slitlets!\n") ;
1056  return -1 ;
1057  }
1058 
1059  return 0;
1060 
1061 }
1062 
1063 
1064 
1086 cpl_imagelist *
1087 sinfo_new_make_cube_spi ( cpl_image * calibImage,
1088  float ** slit_edges,
1089  float * shift )
1090 {
1091  cpl_imagelist * returnCube ;
1092 
1093  float * center ;
1094  int * row_index ;
1095  int slit ;
1096  int col, z ;
1097  int imsize ;
1098  int * beginCol ;
1099  int col_counter ;
1100  int ilx=0;
1101  int ily=0;
1102 
1103 
1104  float* pidata=NULL;
1105 
1106 
1107  if ( NULL == calibImage )
1108  {
1109  sinfo_msg_error("no resampled image given!\n") ;
1110  return NULL ;
1111  }
1112  ilx=cpl_image_get_size_x(calibImage);
1113  ily=cpl_image_get_size_y(calibImage);
1114  pidata=cpl_image_get_data_float(calibImage);
1115 
1116  if ( NULL == slit_edges )
1117  {
1118  sinfo_msg_error("no slit_edges array given from sinfo_fitSlits()!/n") ;
1119  return NULL ;
1120  }
1121 
1122  if ( N_SLITLETS != 32 )
1123  {
1124  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1125  return NULL ;
1126  }
1127  imsize = ilx / N_SLITLETS ;
1128 
1129  /* allocate memory */
1130  if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1131  {
1132  sinfo_msg_error ("cannot allocate memory \n" ) ;
1133  return NULL ;
1134  }
1135  if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1136  {
1137  sinfo_msg_error ("cannot allocate memory \n" ) ;
1138  cpl_free(row_index) ;
1139  return NULL ;
1140  }
1141  if ( NULL == (center = (float*) cpl_calloc(N_SLITLETS, sizeof(float)) ) )
1142  {
1143  sinfo_msg_error ("cannot allocate memory \n" ) ;
1144  cpl_free (row_index) ;
1145  cpl_free (beginCol) ;
1146  return NULL ;
1147  }
1148  if ( NULL == (returnCube = cpl_imagelist_new()) )
1149  {
1150  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1151  cpl_free (row_index) ;
1152  cpl_free (beginCol) ;
1153  cpl_free (center) ;
1154  return NULL ;
1155  }
1156  /* determine the absolute center of the slitlets and the distances
1157  inside the image*/
1158  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1159  /* go through the slitlets of each row of the resampled image */
1160  {
1161  center[slit] = (slit_edges[slit][1] + slit_edges[slit][0]) / 2. ;
1162  /* -------------------------------------------------------------
1163  * sort the slitlets in the right spiffi specific way
1164  * the row_index describes the row index of the current slitlet
1165  * in the resulting cube images.
1166  */
1167  if(-1 == sinfo_sort_slitlets_array(slit,row_index)) {
1168  cpl_imagelist_delete(returnCube) ;
1169  cpl_free (row_index) ;
1170  cpl_free (beginCol) ;
1171  cpl_free (center) ;
1172  return NULL ;
1173  }
1174  /* determine the integer column on which the slitlet starts, center the
1175  slitlet on the image row */
1176  float start = center[slit] - (float) (imsize - 1)/2. ;
1177  beginCol[slit] = sinfo_new_nint (start) ;
1178  /* determine the error of using integer pixels */
1179  float diff = start - (float)beginCol[slit] ;
1180 
1181  /*--------------------------------------------------------------------
1182  * determine the output shift values by which the rows are finally
1183  shifted, consider the integer pixel errors
1184  * resort shift array to get the row index
1185  */
1186  shift[row_index[slit]] = diff ;
1187  }
1188 
1189  /* now build the data cube out of the resampled image */
1190  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1191  {
1192  cpl_image* o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1193  float* podata=cpl_image_get_data_float(o_img);
1194  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1195  {
1196  col_counter = beginCol[slit] ;
1197  /* each slitlet is centered on the final image row */
1198  for ( col = 0 ; col < imsize ; col++ )
1199  {
1200  if ( col_counter > ilx-1 )
1201  {
1202  col_counter-- ;
1203  }
1204  if ( col_counter + z*ilx < 0 )
1205  {
1206  podata[col+row_index[slit]*imsize] = pidata[0] ;
1207  }
1208  else
1209  {
1210  podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
1211  }
1212 
1213  col_counter++ ;
1214  }
1215  }
1216  cpl_imagelist_set(returnCube,o_img,z);
1217  }
1218  cpl_free (row_index) ;
1219  cpl_free (beginCol) ;
1220  cpl_free (center) ;
1221 
1222  return returnCube ;
1223 }
1256 cpl_imagelist *
1257 sinfo_new_make_cube_dist ( cpl_image * calibImage,
1258  float firstCol,
1259  float * distances,
1260  float * shift )
1261 {
1262  cpl_imagelist * returnCube ;
1263  float di ;
1264  float start ;
1265  int * row_index ;
1266  int slit ;
1267  int col, z ;
1268  int imsize ;
1269  int * beginCol ;
1270  int col_counter ;
1271  int ilx=0;
1272  int ily=0;
1273 
1274  float* podata=NULL;
1275  float* pidata=NULL;
1276 
1277  if ( NULL == calibImage )
1278  {
1279  sinfo_msg_error(" no resampled image given!\n") ;
1280  return NULL ;
1281  }
1282  ilx=cpl_image_get_size_x(calibImage);
1283  ily=cpl_image_get_size_y(calibImage);
1284  pidata=cpl_image_get_data_float(calibImage);
1285 
1286  if ( NULL == distances )
1287  {
1288  sinfo_msg_error("no distances array given from north_south_test()!") ;
1289  return NULL ;
1290  }
1291 
1292  if ( N_SLITLETS != 32 )
1293  {
1294  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1295  return NULL ;
1296  }
1297  imsize = ilx / N_SLITLETS ;
1298 
1299  /* allocate memory */
1300  if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1301  {
1302  sinfo_msg_error ("cannot allocate memory \n" ) ;
1303  return NULL ;
1304  }
1305  if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1306  {
1307  sinfo_msg_error ("cannot allocate memory \n" ) ;
1308  cpl_free(row_index) ;
1309  return NULL ;
1310  }
1311  if ( NULL == (returnCube = cpl_imagelist_new()) )
1312  {
1313  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1314  cpl_free(row_index) ;
1315  cpl_free(beginCol) ;
1316  return NULL ;
1317  }
1318 
1319  di = 0. ;
1320  /* determine the absolute beginning of the slitlets and the distances
1321  inside the image*/
1322  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1323  /* go through the slitlets of each row of the resampled image */
1324  {
1325 
1326  /* -------------------------------------------------------------
1327  * sort the slitlets in the right spiffi specific way
1328  * the row_index describes the row index of the current slitlet
1329  * in the resulting cube images.
1330  */
1331  if(-1 == sinfo_sort_slitlets_array(slit,row_index)) {
1332  cpl_imagelist_delete(returnCube) ;
1333  cpl_free(row_index) ;
1334  cpl_free(beginCol) ;
1335  return NULL ;
1336  }
1337 
1338  /* determine the integer column on which the slitlet starts */
1339  if ( slit == 0 )
1340  {
1341  start = firstCol ;
1342  }
1343  else
1344  {
1345  di += distances[slit-1] ;
1346  start = firstCol + di ;
1347  }
1348  beginCol[slit] = sinfo_new_nint(start) ;
1349 
1350  /* determine the error of using integer pixels, its always smaller
1351  than 1 */
1352  float diff = start - (float)beginCol[slit] ;
1353 
1354  /*----------------------------------------------------------------
1355  * determine the output shift values by which the rows are finally
1356  * shifted, consider the integer pixel errors and resort shift array
1357  * to get the row index
1358  */
1359  shift[row_index[slit]] = diff ;
1360  }
1361 
1362  /* now build the data cube out of the resampled image */
1363  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1364  {
1365  cpl_image* o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1366  podata=cpl_image_get_data_float(o_img);
1367  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1368  {
1369  col_counter = beginCol[slit] ;
1370  /* each slitlet is centered on the final image row */
1371  for ( col = 0 ; col < imsize ; col++ )
1372  {
1373  if ( col_counter > ilx-1 )
1374  {
1375  col_counter-- ;
1376  }
1377  if ( col_counter + z*ilx < 0 )
1378  {
1379  podata[col+row_index[slit]*imsize] = podata[0] ;
1380  }
1381  else
1382  {
1383  podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
1384  }
1385 
1386  col_counter++ ;
1387  }
1388  }
1389  cpl_imagelist_set(returnCube,o_img,z);
1390  }
1391  cpl_free (row_index) ;
1392  cpl_free (beginCol) ;
1393 
1394  return returnCube ;
1395 }
1427 cpl_imagelist *
1428 sinfo_new_make_3D_cube_dist ( cpl_image * calibImage,
1429  float firstCol,
1430  float * distances,
1431  float * shift )
1432 {
1433  cpl_imagelist * returnCube ;
1434  float di ;
1435  float start ;
1436  int * row_index ;
1437  int slit ;
1438  int col, z ;
1439  int imsize ;
1440  int * beginCol ;
1441  int col_counter ;
1442  int ilx=0;
1443  int ily=0;
1444 
1445  if ( NULL == calibImage )
1446  {
1447  sinfo_msg_error(" no resampled image given!\n") ;
1448  return NULL ;
1449  }
1450  ilx=cpl_image_get_size_x(calibImage);
1451  ily=cpl_image_get_size_y(calibImage);
1452  float* pidata=cpl_image_get_data_float(calibImage);
1453 
1454  if ( NULL == distances )
1455  {
1456  sinfo_msg_error("no distances array given from north_south_test()!") ;
1457  return NULL ;
1458  }
1459 
1460  if ( N_SLITLETS != 16 )
1461  {
1462  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1463  return NULL ;
1464  }
1465  imsize = ilx / N_SLITLETS ;
1466 
1467  /* allocate memory */
1468  if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1469  {
1470  sinfo_msg_error ("cannot allocate memory \n" ) ;
1471  return NULL ;
1472  }
1473  if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1474  {
1475  sinfo_msg_error ("cannot allocate memory \n" ) ;
1476  cpl_free(row_index) ;
1477  return NULL ;
1478  }
1479  if ( NULL == (returnCube = cpl_imagelist_new()) )
1480  {
1481  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1482  cpl_free(row_index) ;
1483  cpl_free(beginCol) ;
1484  return NULL ;
1485  }
1486 
1487  di = 0. ;
1488  /* determine the absolute beginning of the slitlets and the distances
1489  inside the image*/
1490  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1491  /* go through the slitlets of each row of the resampled image */
1492  {
1493 
1494  /* --------------------------------------------------------------
1495  * sort the slitlets in the right 3D specific way
1496  * the row_index describes the row index of the current slitlet
1497  * in the resulting cube images.
1498  */
1499  row_index[slit] = slit ;
1500 
1501  /* determine the integer column on which the slitlet starts */
1502  if ( slit == 0 )
1503  {
1504  start = firstCol ;
1505  }
1506  else
1507  {
1508  di += distances[slit-1] ;
1509  start = firstCol + di ;
1510  }
1511  beginCol[slit] = sinfo_new_nint(start) ;
1512 
1513  /* determine the error of using integer pixels,
1514  `its always smaller than 1 */
1515  float diff = start - (float)beginCol[slit] ;
1516 
1517  /*----------------------------------------------------------------
1518  * determine the output shift values by which the rows are finally
1519  shifted, consider the integer pixel errors and resort shift array
1520  to get the row index
1521  */
1522  shift[row_index[slit]] = diff ;
1523  }
1524 
1525  /* now build the data cube out of the resampled image */
1526  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1527  {
1528  cpl_image* o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1529  float* podata=cpl_image_get_data_float(o_img);
1530  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1531  {
1532  col_counter = beginCol[slit] ;
1533  /* each slitlet is centered on the final image row */
1534  for ( col = 0 ; col < imsize ; col++ )
1535  {
1536  if ( col_counter > ilx-1 )
1537  {
1538  col_counter-- ;
1539  }
1540  podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
1541  col_counter++ ;
1542  }
1543  }
1544  cpl_imagelist_set(returnCube,o_img,z);
1545  }
1546  cpl_free (row_index) ;
1547  cpl_free (beginCol) ;
1548 
1549  return returnCube ;
1550 }
1551 
1573 cpl_imagelist *
1574 sinfo_new_make_3D_cube ( cpl_image * calibImage,
1575  int * kpixshift,
1576  int kpixfirst )
1577 {
1578  cpl_imagelist * returnCube ;
1579  int imsize;
1580  int z, col;
1581  int ilx=0;
1582  int ily=0;
1583 
1584  if ( NULL == calibImage )
1585  {
1586  sinfo_msg_error("no resampled image given!\n") ;
1587  return NULL ;
1588  }
1589  ilx=cpl_image_get_size_x(calibImage);
1590  ily=cpl_image_get_size_y(calibImage);
1591  float* pidata=cpl_image_get_data_float(calibImage);
1592 
1593  if ( NULL == kpixshift )
1594  {
1595  sinfo_msg_error("no shift array given!/n") ;
1596  return NULL ;
1597  }
1598 
1599  if ( kpixfirst < 0 )
1600  {
1601  sinfo_msg_error("wrong first valid pixel given!/n") ;
1602  return NULL ;
1603  }
1604 
1605  if ( N_SLITLETS != 16 )
1606  {
1607  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1608  return NULL ;
1609  }
1610  imsize = ilx / N_SLITLETS ;
1611 
1612  if ( NULL == (returnCube = cpl_imagelist_new()) )
1613  {
1614  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1615  return NULL ;
1616  }
1617 
1618  /* now build the data cube out of the resampled image */
1619  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1620  {
1621  cpl_image* o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1622  float* podata=cpl_image_get_data_float(o_img);
1623  int kpix = 0 ;
1624  int kslit = 0 ;
1625  int recol = -1 ;
1626  for ( col = 0 ; col < ilx ; col++ ) /* go through the image columns */
1627  {
1628  if ( col % imsize == 0 )
1629  {
1630  recol = 0 ;
1631  kslit = col/imsize ;
1632  kpix = kpixfirst + kpixshift[kslit] ;
1633  }
1634 
1635  /* fill each cube plane with one image row */
1636  podata[recol+kslit*imsize] = pidata[col+kpix+z*ilx] ;
1637  recol++ ;
1638  if ( recol > imsize )
1639  {
1640  sinfo_msg_error("wrong column of reconstructed image, i"
1641  "shouldn't happen!\n") ;
1642  cpl_imagelist_delete(returnCube) ;
1643  return NULL ;
1644  }
1645  }
1646  cpl_imagelist_set(returnCube,o_img,z);
1647  }
1648  return returnCube ;
1649 }
1650 
1667 cpl_imagelist *
1668 sinfo_new_determine_mask_cube ( cpl_imagelist * sourceMaskCube,
1669  float lowLimit,
1670  float highLimit )
1671 {
1672  cpl_imagelist * retCube ;
1673  int z, n ;
1674  int ilx=0;
1675  int ily=0;
1676  int inp=0;
1677  int olx=0;
1678  int oly=0;
1679  int onp=0;
1680 
1681 
1682 
1683  if ( sourceMaskCube == NULL )
1684  {
1685  sinfo_msg_error("no cube given!\n") ;
1686  return NULL ;
1687  }
1688  ilx=cpl_image_get_size_x(cpl_imagelist_get(sourceMaskCube,0));
1689  ily=cpl_image_get_size_y(cpl_imagelist_get(sourceMaskCube,0));
1690  inp=cpl_imagelist_get_size(sourceMaskCube);
1691 
1692 
1693  if ( lowLimit > 0. )
1694  {
1695  sinfo_msg_error("lowLimit wrong!\n") ;
1696  return NULL ;
1697  }
1698  if ( highLimit >= 1. || highLimit < 0. )
1699  {
1700  sinfo_msg_error("highLimit wrong!\n") ;
1701  return NULL ;
1702  }
1703 
1704  retCube = cpl_imagelist_duplicate (sourceMaskCube) ;
1705  onp=inp;
1706  olx=ilx;
1707  oly=ily;
1708 
1709  for ( z = 0 ; z < onp ; z++ )
1710  {
1711  cpl_image* o_img=cpl_imagelist_get(retCube,0);
1712  float* podata=cpl_image_get_data_float(o_img);
1713  for ( n = 0 ; n < (int) olx*oly; n++ )
1714  {
1715  if ( podata[n] == 0. )
1716  {
1717  continue ;
1718  }
1719  if ( podata[n] == 1. )
1720  {
1721  continue ;
1722  }
1723  if ( podata[n] >= lowLimit &&
1724  podata[n] <= highLimit )
1725  {
1726  podata[n] = 0. ;
1727  }
1728  else
1729  {
1730  podata[n] = 1. ;
1731  }
1732  }
1733  }
1734  return retCube ;
1735 }
1778 cpl_imagelist *
1779 sinfo_new_interpol_cube ( cpl_imagelist * sourceCube,
1780  cpl_imagelist * maskCube,
1781  int n_neighbors, /* 7 */
1782  int max_radius ) /* 5 */
1783 {
1784  cpl_imagelist * returnCube ;
1785  float** spec=NULL ;
1786  float* spec1=NULL ;
1787  int n_im, n_bad, n_bad1, n_bad2 ;
1788  int n_planes, specn, nspec1 ;
1789  int i, m, n, z, ni, kk, p ;
1790  int dis, dismin, dismax ;
1791  int agreed ;
1792  int xcordi, ycordi, xcordm, ycordm ;
1793 
1794 
1795 
1796  int ilx=0;
1797  int ily=0;
1798  int inp=0;
1799 
1800  float* pidata=NULL;
1801  float* pmdata=NULL;
1802 
1803 
1804  if ( NULL == sourceCube )
1805  {
1806  sinfo_msg_error(" no source cube given!\n") ;
1807  return NULL ;
1808  }
1809 
1810 
1811  ilx=cpl_image_get_size_x(cpl_imagelist_get(sourceCube,0));
1812  ily=cpl_image_get_size_y(cpl_imagelist_get(sourceCube,0));
1813  inp=cpl_imagelist_get_size(sourceCube);
1814 
1815  if ( NULL == maskCube )
1816  {
1817  sinfo_msg_error("no bad pixel mask cube given!\n") ;
1818  return NULL ;
1819  }
1820 
1821  if ( n_neighbors <= 0 )
1822  {
1823  sinfo_msg_error("wrong number of neighbors in the spectral "
1824  "direction given!") ;
1825  return NULL ;
1826  }
1827 
1828  if ( max_radius <= 0 )
1829  {
1830  sinfo_msg_error("wrong maximal radius for interpolation inside "
1831  "an image plane given!") ;
1832  return NULL ;
1833  }
1834 
1835  returnCube = cpl_imagelist_duplicate(sourceCube) ;
1836 
1837  n_im = ilx * ily ;
1838  n_planes = inp ;
1839 
1840  spec1=cpl_calloc(300,sizeof(float)) ;
1841  spec=sinfo_new_2Dfloatarray(100,2*n_neighbors+1) ;
1842 
1843  /* loop over the image planes and look for bad pixels and correct them */
1844  for ( z = 0 ; z < n_planes ; z++ ) /* go through image planes */
1845  {
1846  cpl_image* m_img=cpl_imagelist_get(maskCube,z);
1847  pmdata=cpl_image_get_data_float(m_img);
1848  cpl_image* o_img=cpl_imagelist_get(returnCube,z);
1849  float* podata=cpl_image_get_data_float(o_img);
1850 
1851  /*-------------------------------------------------------------------
1852  * determine n, the length of one wing in one spectrum with which the
1853  * bad pixel will be interpolated. The length of one wing is
1854  n_neighbors but less at the edges of the cube.
1855  */
1856  if ( z < n_neighbors )
1857  {
1858  n = z ;
1859  }
1860  else if ( n_planes - z <= n_neighbors)
1861  {
1862  n = n_planes - z -1 ;
1863  }
1864  else
1865  {
1866  n = n_neighbors ;
1867  }
1868 
1869  for ( i = 0 ; i < n_im ; i ++ ) /* go through one image */
1870  {
1871  /* continue if the pixel is a good one */
1872  if ( pmdata[i] != 0. )
1873  {
1874  continue ;
1875  }
1876 
1877  /*-------------------------------------------------------------
1878  * exclude pixels with too many bad neighbors in the spectrum.
1879  * exit if: too few good pixels in the neighboring spectrum or
1880  * good pixels are only on one side of the spectrum.
1881  */
1882  n_bad = 0 ;
1883  n_bad1 = 0 ;
1884  n_bad2 = 0 ;
1885  /* go through the neighbor spectral pixels */
1886  for ( ni = z-n ; ni <= z+n ; ni++ )
1887  {
1888  if ( pmdata[i] == 0. )
1889  {
1890  n_bad++ ;
1891  /* count bad pixels on either spectral side of
1892  the bad pixel to be interpolated */
1893  if ( ni < z )
1894  {
1895  n_bad1++ ;
1896  }
1897  if ( ni > z )
1898  {
1899  n_bad2++ ;
1900  }
1901  }
1902  }
1903 
1904  /*---------------------------------------------------------------
1905  * now the criteria are checked which the neighborhood in the
1906  spectral dimension has to match if the pixel is interpolatable.
1907  * The total number of the good pixel in the spectrum must be more
1908  than 3 and there must be at least one good pixel on either side
1909  of the central pixel.
1910  */
1911  if ( (2*n+1 - n_bad) < 3 || (n - n_bad1) < 1 || (n - n_bad2) < 1 )
1912  {
1913  continue ;
1914  }
1915 
1916  /* read the master spectrum into the first row of the array spec */
1917  kk = 0 ;
1918  cpl_image* i_img;
1919  for ( ni = z-n ; ni <= z+n ; ni++ )
1920  {
1921  i_img=cpl_imagelist_get(sourceCube,ni);
1922  pidata=cpl_image_get_data_float(i_img);
1923  spec[1][kk] = pmdata[i] != 0. ? pidata[i] : ZERO ;
1924  kk++ ; /* length of spectrum */
1925  }
1926 
1927  /* look for appropriate neighbors in the x-y neighborhood */
1928  agreed = 1 ; /* loop guard */
1929  specn = 2 ; /* number of spectra in spec.
1930  First is master spectrum */
1931  dismin = 0 ; /* x+y minimal distance to bad pixel */
1932  dismax = 1 ; /* x+y maximal distance to bad pixel */
1933  do
1934  {
1935  for ( m = 0 ; m < n_im ; m++ )
1936  {
1937  if ( pmdata[m] == 0. )
1938  {
1939  continue ;
1940  }
1941 
1942  /* --------------------------------------------------------
1943  * determine the x and y coordinates of the bad pixel (i)
1944  * and the pixels used to interpolate (m)
1945  */
1946  xcordi = i % ilx ;
1947  xcordm = m % ilx ;
1948  ycordi = i / ilx ;
1949  ycordm = m / ilx ;
1950  /*-----------------------------------------------------
1951  * check the distance: take only close pixels
1952  * extension 'i' is coordinate of the bad pixel to be
1953  interpolated
1954  */
1955  dis = abs(xcordi-xcordm) + abs(ycordi-ycordm) ;
1956  if ( dis <= dismin || dis > dismax )
1957  {
1958  continue ;
1959  }
1960  /*--------------------------------------------------------
1961  * check on number of bad pixels in the spectrum of a
1962  * neighbor pixel; reject it if it contains less than 2
1963  * usable pixel pairs. a bit more explanation:
1964  * let this be a 15 pixel spectrum with the pixel to be
1965  * interpolated denoted by '0' and other bad pixels marked
1966  * with 'b'. Good pixels are marked with '1'. Below a
1967  * neighbor spectrum is drawn containing bad pixels as
1968  * well. The third line shows the position of the usable
1969  * pixel pairs, spectral
1970  * positions, where both spectra have valid pixels.
1971  *
1972  * 1 1 1 b b 1 1 0 b 1 b b 1 b b
1973  * b 1 1 1 b b 1 1 1 1 1 1 b b 1
1974  * ^ ^ ^ ^ 4 good pixel pairs
1975  */
1976 
1977  n_bad = 0 ;
1978  for ( ni = z-n ; ni <= z+n ; ni++ )
1979  {
1980  if ( pmdata[i] == 0. || pmdata[m] == 0. )
1981  {
1982  n_bad++ ;
1983  }
1984  }
1985  if ( n_bad > 2*n-1 )
1986  /* we need at least 2 usable pixel pairs */
1987  {
1988  continue ;
1989  }
1990 
1991  /* transfer the spectrum to the next position
1992  of array spec */
1993  kk = 0 ;
1994  for ( ni = z-n ; ni <= z+n ; ni++ )
1995  {
1996  i_img=cpl_imagelist_get(sourceCube,ni);
1997  pidata=cpl_image_get_data_float(i_img);
1998  spec[specn][kk] = pmdata[m] != 0. ? pidata[m] : ZERO ;
1999  kk++ ;
2000  }
2001  specn++ ;
2002  if ( specn > 10 ) /* if we have 9 neighbors then break */
2003  {
2004  agreed = 0 ;
2005  break ;
2006  }
2007  }
2008  /* if no break, increase search radius and continue */
2009  dismin++ ;
2010  dismax++ ;
2011  /* if search radius is too big, exit with fewer
2012  good neighbors */
2013  if ( dismax > max_radius )
2014  {
2015  agreed = 0 ;
2016  }
2017  } while(agreed) ;
2018 
2019  specn-- ;
2020  dismax -= 2 ;
2021  /* TODO: why compute dismax is later this is not used? */
2022  /* ---------------------------------------------------------------
2023  * Take the master spectrum with the bad pixel in the middle and
2024  divide it by each of the neighbor spectra and normalize the
2025  division with the value in the center position.
2026  */
2027  for ( kk = 0 ; kk < 2*n+1 ; kk++ )
2028  {
2029  if ( kk == n ) /* do not divide the master bad pixel */
2030  {
2031  continue ;
2032  }
2033 
2034  /* do not divide bad pixels in the master spectrum */
2035  if ( isnan(spec[1][kk]) )
2036  {
2037  for ( p = 2 ; p <= specn ; p++ )
2038  {
2039  spec[p][kk] = ZERO ;
2040  }
2041  }
2042  else /* all is well, now divide */
2043  {
2044  for ( p = 2 ; p <= specn ; p++ )
2045  {
2046  if ( !isnan(spec[p][kk]) && spec[p][kk] != 0. &&
2047  !isnan(spec[p][n]) )
2048  {
2049  spec[p][kk] = spec[1][kk] /
2050  spec[p][kk] * spec[p][n] ;
2051  }
2052  else
2053  {
2054  spec[p][kk] = ZERO ;
2055  }
2056  }
2057  }
2058  }
2059 
2060  /*-----------------------------------------------------------------
2061  * determine the sinfo_median of all values. With 9 good neighbors
2062  * and at least 2 good values per neighbor we have between 18 and
2063  * 9*14 values for the statistics. If there are not enough good
2064  * neighbors available, only continue if we have collected at
2065  * least 18 values.
2066  */
2067  nspec1 = 0 ;
2068  /* collect the good values in the array spec1 */
2069  for ( p = 2 ; p <= specn ; p++ )
2070  {
2071  for ( kk = 0 ; kk < 2*n+1 ; kk++ )
2072  {
2073  if ( !isnan(spec[p][kk]) && kk != n )
2074  {
2075  spec1[nspec1] = spec[p][kk] ;
2076  nspec1++ ;
2077  }
2078  }
2079  }
2080 
2081  /* now test if we have at least 18 values */
2082  if ( nspec1 < 18 )
2083  {
2084  continue ;
2085  }
2086 
2087  /* interpolate the bad pixel by the sinfo_median of spec1 */
2088  podata[i] = sinfo_new_median(spec1, nspec1) ;
2089  pmdata[i] = 1 ;
2090  }
2091  }
2092  sinfo_new_destroy_2Dfloatarray(&spec,2*n_neighbors+1) ;
2093  cpl_free(spec1);
2094  return returnCube ;
2095 }
2122 cpl_imagelist *
2123 sinfo_new_fine_tune_cube( cpl_imagelist * cube,
2124  float * correct_diff_dist,
2125  int n_order )
2126 {
2127  cpl_imagelist * returnCube ;
2128  float* row_data=NULL ;
2129  float* corrected_row_data=NULL ;
2130  float* xnum=NULL ;
2131  float sum, new_sum ;
2132  float eval/*, dy*/ ;
2133  float * imageptr ;
2134  int row, col ;
2135  int i, z ;
2136  int imsize, n_points ;
2137  int firstpos ;
2138  int flag;
2139  int ilx=0;
2140  int ily=0;
2141  int inp=0;
2142 
2143  if ( NULL == cube )
2144  {
2145  sinfo_msg_error("no input cube given!\n") ;
2146  return NULL ;
2147  }
2148  ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
2149  ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
2150  inp=cpl_imagelist_get_size(cube);
2151 
2152  if ( NULL == correct_diff_dist )
2153  {
2154  sinfo_msg_error("no distances array from ns_test given!n") ;
2155  return NULL ;
2156  }
2157 
2158  if ( n_order <= 0 )
2159  {
2160  sinfo_msg_error("wrong order of interpolation polynom given!") ;
2161  returnCube = cpl_imagelist_duplicate(cube);
2162  return returnCube ;
2163  }
2164 
2165  returnCube = cpl_imagelist_duplicate(cube);
2166 
2167  imsize = ily ;
2168  if ( imsize != N_SLITLETS )
2169  {
2170  sinfo_msg_error ("wrong image size\n" ) ;
2171  sinfo_free_imagelist(&returnCube);
2172  return NULL ;
2173  }
2174 
2175  n_points = n_order + 1 ;
2176  if ( n_points % 2 == 0 )
2177  {
2178  firstpos = (int)(n_points/2) - 1 ;
2179  }
2180  else
2181  {
2182  firstpos = (int)(n_points/2) ;
2183  }
2184  xnum=cpl_calloc(n_order+1,sizeof(float)) ;
2185 
2186  for ( i = 0 ; i < n_points ; i++ )
2187  {
2188  xnum[i] = i ;
2189  }
2190 
2191  row_data=cpl_calloc(ilx,sizeof(float)) ;
2192  corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
2193 
2194  for ( z = 0 ; z < inp ; z++ )
2195  {
2196  cpl_image* i_img=cpl_imagelist_get(cube,z);
2197  float* pidata=cpl_image_get_data_float(i_img);
2198  cpl_image* o_img=cpl_imagelist_get(returnCube,z);
2199  float* podata=cpl_image_get_data_float(o_img);
2200 
2201 
2202  for ( row = 0 ; row < imsize ; row++ )
2203  {
2204  for ( col = 0 ; col < ilx ; col++ )
2205  {
2206  corrected_row_data[col] = 0. ;
2207  }
2208  sum = 0. ;
2209  for ( col = 0 ; col < ilx ; col++ )
2210  {
2211  row_data[col] = pidata[col+row*ilx] ;
2212  if ( isnan(row_data[col]) )
2213  {
2214  row_data[col] = 0. ;
2215  for ( i = col - firstpos ;
2216  i < col -firstpos+n_points ; i++ )
2217  {
2218  if ( i < 0 ) continue ;
2219  if ( i >= ilx) continue ;
2220  corrected_row_data[i] = ZERO ;
2221  }
2222  }
2223  if ( col != 0 && col != ilx - 1 )
2224  {
2225  sum += row_data[col] ;
2226  }
2227  }
2228 
2229 
2230  new_sum = 0. ;
2231  for ( col = 0 ; col < ilx ; col++ )
2232  {
2233 
2234  if ( isnan(corrected_row_data[col]) )
2235  {
2236  continue ;
2237  }
2238  if ( col - firstpos < 0 )
2239  {
2240  imageptr = &row_data[0] ;
2241  eval = correct_diff_dist[row] + col ;
2242  }
2243  else if ( col - firstpos + n_points >= ilx )
2244  {
2245  imageptr = &row_data[ilx - n_points] ;
2246  eval = correct_diff_dist[row] + col + n_points - ilx ;
2247  }
2248  else
2249  {
2250  imageptr = &row_data[col-firstpos] ;
2251  eval = correct_diff_dist[row] + firstpos ;
2252  }
2253 
2254 
2255  flag = 0;
2256  corrected_row_data[col]=sinfo_new_nev_ille(xnum, imageptr,
2257  n_order, eval, &flag);
2258 
2259 
2260  if ( col != 0 && col != ilx - 1 )
2261  {
2262  new_sum += corrected_row_data[col] ;
2263  }
2264  }
2265  for ( col = 0 ; col < ilx ; col++ )
2266  {
2267 
2268  if ( col == 0 )
2269  {
2270  podata[col+row*ilx] = ZERO ;
2271  }
2272  else if ( col == ilx - 1 )
2273  {
2274  podata[col+row*ilx] = ZERO ;
2275  }
2276  else
2277  {
2278  if ( isnan(corrected_row_data[col]) )
2279  {
2280  podata[col+row*ilx] = ZERO ;
2281  }
2282  else
2283  {
2284  if ( new_sum == 0. ) new_sum = 1. ;
2285 
2286  podata[col+row*ilx] = corrected_row_data[col] ;
2287  }
2288  }
2289  }
2290  }
2291  }
2292 
2293  cpl_free(xnum) ;
2294  cpl_free(row_data) ;
2295  cpl_free(corrected_row_data) ;
2296 
2297  return returnCube ;
2298 }
2299 
2324 cpl_imagelist *
2325 sinfo_new_fine_tune_cube_by_FFT( cpl_imagelist * cube,
2326  float * correct_diff_dist )
2327 {
2328  cpl_imagelist * returnCube ;
2329 
2330  float* row_data=NULL ;
2331  dcomplex* data=NULL ;
2332  dcomplex* corrected_data=NULL ;
2333 
2334  unsigned nn[2];
2335  /*float corrected_row_data[cube->lx] ;*/
2336  float phi, pphi ;
2337  float coph, siph ;
2338  int row, col ;
2339  int i, z ;
2340  int imsize ;
2341  int blank_indicator ;
2342 
2343 
2344  int ilx=0;
2345  int ily=0;
2346  int inp=0;
2347 
2348 
2349 
2350 
2351 
2352 
2353  if ( NULL == cube )
2354  {
2355  sinfo_msg_error(" no input cube given!\n") ;
2356  return NULL ;
2357  }
2358  ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
2359  ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
2360  inp=cpl_imagelist_get_size(cube);
2361 
2362  nn[1] = ilx ;
2363  if ( NULL == correct_diff_dist )
2364  {
2365  sinfo_msg_error("no distances array from ns_test given!") ;
2366  return NULL ;
2367  }
2368 
2369  returnCube = cpl_imagelist_duplicate( cube ) ;
2370 
2371  imsize = ily ;
2372  if ( imsize != N_SLITLETS )
2373  {
2374  sinfo_msg_error ("wrong image size\n" ) ;
2375  sinfo_free_imagelist(&returnCube);
2376  return NULL ;
2377  }
2378 
2379  data=cpl_calloc(ilx,sizeof(dcomplex)) ;
2380  corrected_data=cpl_calloc(ilx,sizeof(dcomplex)) ;
2381 
2382  row_data=cpl_calloc(ilx,sizeof(float)) ;
2383  /* loop over the image planes */
2384  for ( z = 0 ; z < inp ; z++ )
2385  {
2386  cpl_image* i_img=cpl_imagelist_get(cube,z);
2387  float* pidata=cpl_image_get_data_float(i_img);
2388  cpl_image* o_img=cpl_imagelist_get(returnCube,z);
2389  float* podata=cpl_image_get_data_float(o_img);
2390  /* consider one row at a time */
2391  for ( row = 0 ; row < imsize ; row++ )
2392  {
2393  blank_indicator = 1 ;
2394  for ( col = 0 ; col < ilx ; col++ )
2395  {
2396  /* transfer the row data to a double sized array */
2397  row_data[col] = pidata[col+row*ilx] ;
2398  data[col].x = row_data[col] ;
2399  data[col].y = 0. ;
2400  /* if row contains a blank pixel proceed */
2401  if ( isnan(row_data[col]) )
2402  {
2403  blank_indicator = 0 ;
2404  }
2405  }
2406 
2407  /* if row contains a blank don't apply FFT but proceed */
2408  if ( blank_indicator == 0 )
2409  {
2410  for ( col = 0 ; col < ilx ; col++ )
2411  {
2412  podata[col+row*ilx] = ZERO ;
2413  }
2414  continue ;
2415  }
2416 
2417  /* FFT algorithm of eclipse */
2418  sinfo_fftn( data, nn, 1, 1 ) ;
2419 
2420  /* calculate the corrected phase shift for each frequency */
2421  phi = 2*PI_NUMB/(float)ilx * correct_diff_dist[row] ;
2422  for ( i = 0 ; i < ilx ; i++ )
2423  {
2424  /* positive frequencies */
2425  if ( i <= ilx/2 )
2426  {
2427  /* phase shift */
2428  pphi = phi * (float)(i) ;
2429  /* Euler factor */
2430  coph = cos ( pphi ) ;
2431  siph = sin ( pphi ) ;
2432  }
2433  else /* negative frequencies */
2434  {
2435  /* phase shift */
2436  pphi = phi * (float)(i - ilx/2) ;
2437  /* Euler factor */
2438  coph = cos ( pphi ) ;
2439  siph = sin ( pphi ) ;
2440  }
2441 
2442  /* ------------------------------------------------------------
2443  * now calculate the shift in the pixel space by multiplying
2444  * the fourier transform by the Euler factor of the phase shift
2445  * and inverse fourier transforming.
2446  * used Fourier pair: h(x-x0) <==> H(k)*exp(2*pi*i*k*x0)
2447  */
2448  /* calculate real part */
2449  corrected_data[i].x = data[i].x * coph - data[i].y * siph ;
2450  /* calculate imaginary part */
2451  corrected_data[i].y = data[i].x * siph + data[i].y * coph ;
2452  }
2453 
2454  /* transform back: inverse FFT */
2455  sinfo_fftn( corrected_data, nn, 1, -1 ) ;
2456 
2457  /* normalize */
2458  for ( i = 0 ; i < ilx ; i++ )
2459  {
2460  corrected_data[i].x /= ilx ;
2461  corrected_data[i].y /= ilx ;
2462  }
2463 
2464  /* now transfer row to output, leave the left-most
2465  and right-most pixel column */
2466  for ( col = 0 ; col < ilx ; col++ )
2467  {
2468  if ( col == 0 )
2469  {
2470  podata[col+row*ilx] = ZERO ;
2471  }
2472  else if ( col == ilx - 1 )
2473  {
2474  podata[col+row*ilx] = ZERO ;
2475  }
2476  else
2477  {
2478  podata[col+row*ilx] = corrected_data[col].x ;
2479  }
2480  }
2481  }
2482  }
2483 
2484  cpl_free(data) ;
2485  cpl_free(corrected_data) ;
2486 
2487 
2488  cpl_free(row_data);
2489  return returnCube ;
2490 }
2521 cpl_imagelist * sinfo_new_fine_tune_cube_by_spline ( cpl_imagelist * cube,
2522  float * correct_diff_dist )
2523 {
2524  cpl_imagelist * returnCube ;
2525 
2526  float* row_data=NULL ;
2527  float* corrected_row_data=NULL ;
2528  float* xnum=NULL ;
2529  float* eval=NULL ;
2530 
2531  float sum, new_sum ;
2532  int row, col ;
2533  int i, z ;
2534  int imsize ;
2535  int ilx=0;
2536  int ily=0;
2537  int inp=0;
2538 
2539  if ( NULL == cube )
2540  {
2541  sinfo_msg_error("no input cube given!\n") ;
2542  return NULL ;
2543  }
2544  ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
2545  ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
2546  inp=cpl_imagelist_get_size(cube);
2547 
2548  if ( NULL == correct_diff_dist )
2549  {
2550  sinfo_msg_error("no distances array from ns_test given!/n") ;
2551  return NULL ;
2552  }
2553 
2554  imsize = ily ;
2555  if ( imsize != N_SLITLETS )
2556  {
2557  sinfo_msg_error ("wrong image size\n" ) ;
2558  return NULL ;
2559  }
2560 
2561  returnCube = cpl_imagelist_duplicate( cube ) ;
2562 
2563  row_data=cpl_calloc(ilx,sizeof(float)) ;
2564  corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
2565  xnum=cpl_calloc(ilx,sizeof(float)) ;
2566  eval=cpl_calloc(ilx,sizeof(float)) ;
2567 
2568  /* fill the xa[] array for a polynomial interpolation */
2569  for ( i = 0 ; i < ilx ; i++ )
2570  {
2571  xnum[i] = i ;
2572  }
2573 
2574  /* loop over the image planes */
2575  for ( z = 0 ; z < inp ; z++ )
2576  {
2577  cpl_image* i_img=cpl_imagelist_get(cube,z);
2578  float* pidata=cpl_image_get_data_float(i_img);
2579  cpl_image* o_img=cpl_imagelist_get(returnCube,z);
2580  float* podata=cpl_image_get_data_float(o_img);
2581  /* consider 1 row at a time */
2582  for ( row = 0 ; row < imsize ; row++ )
2583  {
2584  for ( col = 0 ; col < ilx ; col++ )
2585  {
2586  corrected_row_data[col] = 0. ;
2587  }
2588  sum = 0. ; /* initialize flux for later rescaling */
2589  /* go through the columns and compute the flux for each
2590  row (leave the sinfo_edge points) */
2591  for ( col = 0 ; col < ilx ; col++ )
2592  {
2593  eval[col] = correct_diff_dist[row] + (float)col ;
2594  row_data[col] = pidata[col+row*ilx] ;
2595  if (col != 0 && col != ilx - 1 && !isnan(row_data[col]) )
2596  {
2597  sum += row_data[col] ;
2598  }
2599  if (isnan(row_data[col]) )
2600  {
2601  for ( i = col -1 ; i <= col+1 ; i++ )
2602  {
2603  if ( i < 0 ) continue ;
2604  if ( i >= ilx ) continue ;
2605  corrected_row_data[i] = ZERO ;
2606  }
2607  row_data[col] = 0. ;
2608  }
2609  }
2610 
2611 
2612  /* ---------------------------------------------------------------
2613  * now we do the cubic spline interpolation to achieve the
2614  fractional (see eclipse).
2615  */
2616  if ( -1 == sinfo_function1d_natural_spline(xnum,row_data, ilx,
2617  eval,corrected_row_data,
2618  ilx ) )
2619  {
2620  sinfo_msg_error("error in spline interpolation\n") ;
2621  cpl_imagelist_delete(returnCube) ;
2622  return NULL ;
2623  }
2624 
2625  new_sum = 0. ;
2626  for ( col = 0 ; col < ilx ; col++ )
2627  {
2628  if (isnan(corrected_row_data[col])) continue ;
2629  /* don't take the sinfo_edge points to calculate
2630  the scaling factor */
2631  if ( col != 0 && col != ilx - 1 )
2632  {
2633  new_sum += corrected_row_data[col] ;
2634  }
2635  }
2636  for ( col = 0 ; col < ilx ; col++ )
2637  {
2638  /* ----------------------------------------------------------
2639  * rescale the row data and fill the returned cube,
2640  * leave the left-most and right-most
2641  * pixel column
2642  */
2643  if ( col == 0 )
2644  {
2645  podata[col+row*ilx] = ZERO ;
2646  }
2647  else if ( col == ilx - 1 )
2648  {
2649  podata[col+row*ilx] = ZERO ;
2650  }
2651  else
2652  {
2653  if ( isnan(corrected_row_data[col]) )
2654  {
2655  podata[col+row*ilx] = ZERO ;
2656  }
2657  else
2658  {
2659  if (new_sum == 0.) new_sum = 1. ;
2660  /* rescaling is commented out because it delivers
2661  wrong results
2662  in case of appearance of blanks or bad pixels */
2663  /* corrected_row_data[col] *= sum / new_sum ; */
2664  podata[col+row*ilx] = corrected_row_data[col] ;
2665  }
2666  }
2667  }
2668  }
2669  }
2670 
2671  cpl_free(row_data) ;
2672  cpl_free(corrected_row_data) ;
2673  cpl_free(xnum) ;
2674  cpl_free(eval) ;
2675 
2676  return returnCube ;
2677 }
2678 
2701 float *
2702 sinfo_new_calibrate_ns_test( cpl_image * ns_image,
2703  int n_slitlets,
2704  int halfWidth,
2705  float fwhm,
2706  float minDiff,
2707  float estimated_dist,
2708  float devtol,
2709  int bottom,
2710  int top )
2711 {
2712  int i, j, k, m, row, col, n, ni, na ;
2713  int position, counter;
2714  int xdim, ndat, its, numpar ;
2715  float sum, mean, maxval ;
2716  float tol, lab ;
2717  float * distances ;
2718  float * ret_distances ;
2719 
2720  float * xdat, * wdat ;
2721  int * mpar ;
2722 
2723  pixelvalue* row_buf=NULL ;
2724  float** distances_buf=NULL ;
2725  float* x_position=NULL ;
2726  int* found=NULL;
2727  int* found_clean=NULL ;
2728  int* found_cleanit=NULL ;
2729 
2730  Vector * line ;
2731  FitParams ** par ;
2732  int foundit, begin, end ;
2733 
2734 
2735 
2736  int ilx=0;
2737  int ily=0;
2738  float* pidata=NULL;
2739 
2740  if ( ns_image == NULL )
2741  {
2742  sinfo_msg_error("sorry, no image given\n") ;
2743  return NULL ;
2744  }
2745  if ( n_slitlets < 1 )
2746  {
2747  sinfo_msg_error("wrong number of slitlets given\n") ;
2748  return NULL ;
2749  }
2750  if ( halfWidth < 0 || halfWidth >= estimated_dist )
2751  {
2752  sinfo_msg_error("wrong half width given\n") ;
2753  return NULL ;
2754  }
2755  if ( fwhm <= 0. )
2756  {
2757  sinfo_msg_error("wrong fwhm given\n") ;
2758  return NULL ;
2759  }
2760  if ( minDiff < 1. )
2761  {
2762  sinfo_msg_error("wrong minDiff given\n") ;
2763  return NULL ;
2764  }
2765 
2766  /* allocate memory for output array */
2767  if (NULL==(distances=(float *)cpl_calloc( n_slitlets , sizeof (float) )))
2768  {
2769  sinfo_msg_error("could not allocate memory\n") ;
2770  return NULL ;
2771  }
2772  /* allocate memory for output array */
2773  if (NULL == (ret_distances = (float *) cpl_calloc ( n_slitlets ,
2774  sizeof (float) )))
2775  {
2776  sinfo_msg_error("could not allocate memory\n") ;
2777  return NULL ;
2778  }
2779 
2780  ilx=cpl_image_get_size_x(ns_image);
2781  ily=cpl_image_get_size_y(ns_image);
2782  pidata=cpl_image_get_data_float(ns_image);
2783 
2784  row_buf=(pixelvalue*)cpl_calloc(ilx,sizeof(pixelvalue)) ;
2785  x_position=cpl_calloc(n_slitlets,sizeof(float)) ;
2786  found=cpl_calloc(3*n_slitlets,sizeof(int));
2787  found_clean=cpl_calloc(3*n_slitlets,sizeof(int)) ;
2788  found_cleanit=cpl_calloc(3*n_slitlets,sizeof(int)) ;
2789  distances_buf=sinfo_new_2Dfloatarray(ily,n_slitlets) ;
2790 
2791  /* go through the image rows */
2792  for ( row = 0 ; row < ily ; row++ )
2793  {
2794  int zeroindicator = 0 ;
2795 
2796  /* initialize the distance buffer */
2797  for ( i = 0 ; i < n_slitlets ; i++ )
2798  {
2799  distances_buf[row][i] = ZERO ;
2800  }
2801 
2802  /* fill the row buffer array with image data */
2803  for ( col = 0 ; col < ilx ; col++ )
2804  {
2805  row_buf[col] = pidata[col + row*ilx] ;
2806  }
2807 
2808  /* determine the mean of the row data */
2809  sum = 0. ;
2810  n = 0 ;
2811  for ( i = 0 ; i < ilx ; i++ )
2812  {
2813  if ( isnan(row_buf[i]) )
2814  {
2815  continue ;
2816  }
2817  sum += row_buf[i] ;
2818  n++ ;
2819  }
2820  mean = sum / (float)n ;
2821 
2822  /* store the positions of image values greater than the mean */
2823  n = 0 ;
2824  for ( i = 0 ; i < ilx ; i++ )
2825  {
2826  if (isnan(row_buf[i]))
2827  {
2828  continue ;
2829  }
2830  if ( row_buf[i] > mean + ESTIMATE )
2831  {
2832  found[n] = i ;
2833  n++ ;
2834  }
2835  }
2836 
2837  if ( n < n_slitlets )
2838  {
2839  sinfo_msg_warning("t4 wrong number of intensity columns "
2840  "found in row: %d, found number: %d", row, n) ;
2841  continue ;
2842  }
2843  else
2844  {
2845  /* find the maximum value position around the found columns */
2846  na = 0 ;
2847  for ( i = 1 ; i < n ; i ++ )
2848  {
2849  if ( found[i] - found[i-1] < halfWidth )
2850  {
2851  begin = found[i] - halfWidth ;
2852  if ( begin < 0 )
2853  {
2854  begin = 0 ;
2855  }
2856  end = found[i] + halfWidth ;
2857  if ( end >= ilx )
2858  {
2859  end = ilx - 1 ;
2860  }
2861  /* find the maximum value inside the box around
2862  the found positions*/
2863  maxval = -FLT_MAX ;
2864  foundit = 0 ;
2865  for ( j = begin ; j <= end ; j++ )
2866  {
2867  /* do not consider boxes that contain bad pixels */
2868  if (isnan(row_buf[j]))
2869  {
2870  continue ;
2871  }
2872  if (row_buf[j] >= maxval )
2873  {
2874  maxval = row_buf[j] ;
2875  foundit = j ;
2876  }
2877  }
2878  if (maxval == -FLT_MAX)
2879  {
2880  continue ;
2881  }
2882  for ( k = 0 ; k < na ; k++ )
2883  {
2884  if ( found_cleanit[k] >= begin &&
2885  found_cleanit[k] < foundit )
2886  {
2887  na-- ;
2888  }
2889  }
2890  for ( k = 0 ; k < n ; k++ )
2891  {
2892  if ( found[k] == foundit)
2893  {
2894  if ( found_cleanit[na-1] != found[k] )
2895  {
2896  found_cleanit[na] = found[k] ;
2897  na++ ;
2898  }
2899  }
2900  }
2901  }
2902  else
2903  {
2904  if ( i == 1 )
2905  {
2906  found_cleanit[na] = found[0] ;
2907  na++ ;
2908  found_cleanit[na] = found[1] ;
2909  na++ ;
2910  }
2911  else
2912  {
2913  if ( found_cleanit[na-1] != found[i-1])
2914  {
2915  found_cleanit[na] = found[i-1] ;
2916  na++ ;
2917  }
2918  if ( found_cleanit[na-1] != found[i])
2919  {
2920  found_cleanit[na] = found[i] ;
2921  na++ ;
2922  }
2923  }
2924  }
2925  }
2926 
2927  /* determine only one pixel position for each slitlet intensity */
2928  j = 1 ;
2929  for ( i = 1 ; i < na ; i++ )
2930  {
2931  if ( (float)(found_cleanit[i] - found_cleanit[i-1]) <
2932  (estimated_dist - devtol) ||
2933  (float)(found_cleanit[i] - found_cleanit[i-1]) >
2934  (estimated_dist + devtol) )
2935  {
2936  continue ;
2937  }
2938  else
2939  {
2940  found_clean[j-1] = found_cleanit[i-1] ;
2941  found_clean[j] = found_cleanit[i] ;
2942  j++ ;
2943  }
2944  }
2945  }
2946  if ( j > n_slitlets )
2947  {
2948  /* check the distance again */
2949  ni = 1 ;
2950  for ( i = 1 ; i < j ; i++ )
2951  {
2952  if ( (float)(found_clean[i] - found_clean[i-1]) <
2953  (estimated_dist - devtol ) ||
2954  (float)(found_clean[i] - found_clean[i-1]) >
2955  (estimated_dist + devtol ) )
2956  {
2957  continue ;
2958  }
2959  else
2960  {
2961  found_clean[ni-1] = found_clean[i-1] ;
2962  found_clean[ni] = found_clean[i] ;
2963  ni++ ;
2964  }
2965  }
2966  if ( ni != n_slitlets )
2967  {
2968  sinfo_msg_warning("t5 wrong number of intensity columns "
2969  "found in row: %d, found number: %d",
2970  row,ni) ;
2971  continue ;
2972  }
2973  else
2974  {
2975  j = ni ;
2976  }
2977  }
2978  else if ( j < n_slitlets )
2979  {
2980  sinfo_msg_warning("t6 wrong number of intensity columns found "
2981  "in row: %d , found number: %d\n", row, j) ;
2982  continue ;
2983  }
2984  counter = 0 ;
2985  /* go through the found intensity pixels in one row */
2986  for ( i = 0 ; i < j ; i++ )
2987  {
2988  /* allocate memory for the array where the line is fitted in */
2989  if ( NULL == (line = sinfo_new_vector (2*halfWidth + 1)) )
2990  {
2991  sinfo_msg_error ("cannot allocate new Vector \n") ;
2992  cpl_free(distances) ;
2993  return NULL ;
2994  }
2995 
2996  /* allocate memory */
2997  xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
2998  wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
2999  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
3000  par = sinfo_new_fit_params(1) ;
3001 
3002  m = 0 ;
3003  for ( k = found_clean[i]-halfWidth ;
3004  k <= found_clean[i]+halfWidth ; k++ )
3005  {
3006  if ( k < 0 )
3007  {
3008  k = 0. ;
3009  }
3010  else if ( k >= ilx )
3011  {
3012  k = ilx - 1 ;
3013  }
3014  else if ( isnan(row_buf[k]) )
3015  {
3016  zeroindicator = 1 ;
3017  break ;
3018  }
3019  else
3020  {
3021  line -> data[m] = row_buf[k] ;
3022  m++ ;
3023  }
3024  }
3025  if ( zeroindicator == 1 )
3026  {
3027  sinfo_new_destroy_vector(line) ;
3028  cpl_free(xdat) ;
3029  cpl_free(wdat) ;
3030  cpl_free(mpar) ;
3031  sinfo_new_destroy_fit_params(&par) ;
3032  break ;
3033  }
3034 
3035  /*-----------------------------------------------------------------
3036  * go through the spectral sinfo_vector
3037  * determine the maximum pixel value in the spectral sinfo_vector
3038  */
3039  maxval = -FLT_MAX ;
3040  position = -INT32_MAX ;
3041  for ( k = 0 ; k < m ; k++ )
3042  {
3043  xdat[k] = k ;
3044  wdat[k] = 1.0 ;
3045  if ( line -> data[k] >= maxval )
3046  {
3047  maxval = line -> data[k] ;
3048  position = k ;
3049  }
3050  }
3051 
3052  /* set initial values for the fitting routine */
3053  xdim = XDIM ;
3054  ndat = line -> n_elements ;
3055  numpar = MAXPAR ;
3056  tol = TOL ;
3057  lab = LAB ;
3058  its = ITS ;
3059  (*par) -> fit_par[1] = fwhm ;
3060  (*par) -> fit_par[2] = (float) position ;
3061  (*par) -> fit_par[3] = (float) (line -> data[0] +
3062  line -> data[line->n_elements - 1]) / 2.0 ;
3063  (*par) -> fit_par[0] = maxval - ((*par) -> fit_par[3]) ;
3064 
3065 
3066  /* exclude negative peaks and low signal cases */
3067  if ( (*par) -> fit_par[0] < minDiff )
3068  {
3069  sinfo_msg_warning ("sorry, signal of line too low to fit "
3070  "in row: %d in slitlet %d\n", row, i) ;
3071  sinfo_new_destroy_vector(line) ;
3072  cpl_free(xdat) ;
3073  cpl_free(wdat) ;
3074  cpl_free(mpar) ;
3075  sinfo_new_destroy_fit_params(&par) ;
3076  continue ;
3077  }
3078 
3079  for ( k = 0 ; k < MAXPAR ; k++ )
3080  {
3081  (*par) -> derv_par[k] = 0.0 ;
3082  mpar[k] = 1 ;
3083  }
3084  /* finally, do the least square fit using a sinfo_gaussian */
3085  int iters;
3086  if ( 0 > ( iters = sinfo_new_lsqfit_c(xdat, &xdim,
3087  line -> data, wdat,
3088  &ndat, (*par) -> fit_par,
3089  (*par) -> derv_par, mpar,
3090  &numpar, &tol,
3091  &its, &lab )) )
3092  {
3093  /*
3094  cpl_msg_debug ("sinfo_calibrate_ns_test:",
3095  "sinfo_lsqfit_c: least squares fit failed,"
3096  " error no.: %d in row: %d in slitlet %d\n",
3097  iters, row, i) ;
3098  */
3099  sinfo_new_destroy_vector(line) ;
3100  cpl_free(xdat) ;
3101  cpl_free(wdat) ;
3102  cpl_free(mpar) ;
3103  sinfo_new_destroy_fit_params(&par) ;
3104  continue ;
3105  }
3106 
3107  /* check for negative fit results */
3108  if ( (*par) -> fit_par[0] <= 0. || (*par) -> fit_par[1] <= 0. ||
3109  (*par) -> fit_par[2] < 0. )
3110  {
3111  sinfo_msg_warning ("negative parameters as fit result, not "
3112  "used! in row %d in slitlet %d", row, i) ;
3113  sinfo_new_destroy_vector(line) ;
3114  cpl_free(xdat) ;
3115  cpl_free(wdat) ;
3116  cpl_free(mpar) ;
3117  sinfo_new_destroy_fit_params(&par) ;
3118  continue ;
3119  }
3120 
3121  /* correct the fitted position for the given row of the line
3122  in image coordinates */
3123  (*par) -> fit_par[2] = (float) (found_clean[i] - halfWidth) +
3124  (*par) -> fit_par[2] ;
3125  x_position[counter] = (*par) -> fit_par[2] ;
3126  counter ++ ;
3127 
3128  /* free memory */
3129  sinfo_new_destroy_fit_params(&par) ;
3130  sinfo_new_destroy_vector ( line ) ;
3131  cpl_free ( xdat ) ;
3132  cpl_free ( wdat ) ;
3133  cpl_free ( mpar ) ;
3134  }
3135  if (zeroindicator == 1)
3136  {
3137  sinfo_msg_debug ("bad pixel in fitting box in row: %d\n", row) ;
3138  continue ;
3139  }
3140 
3141  if ( counter != n_slitlets )
3142  {
3143  sinfo_msg_warning("wrong number of slitlets found "
3144  "in row: %d", row) ;
3145  continue ;
3146  }
3147  /* store the distances between the sources and the slitlet centers */
3148  for ( i = 0 ; i < n_slitlets ; i++ )
3149  {
3150  distances_buf[row][i] = x_position[i] - (15.5 + 32.*(float)i) ;
3151  }
3152  }
3153 
3154  /* ----------------------------------------------------------------
3155  * go through the rows again and take the mean of the distances,
3156  * throw away the runaways
3157  */
3158  for ( i = 0 ; i < n_slitlets ; i++ )
3159  {
3160  n = 0 ;
3161  sum = 0. ;
3162  for ( row = bottom ; row < top ; row++ )
3163  {
3164  if ( fabs( distances_buf[row][i] ) > devtol ||
3165  isnan(distances_buf[row][i]) )
3166  {
3167  /*
3168  sinfo_msg("dist=%g devtol=%g isan=%d",
3169  distances_buf[row][i],
3170  devtol,
3171  isnan(distances_buf[row][i]));
3172  */
3173  continue ;
3174  }
3175  sum += distances_buf[row][i] ;
3176  n++ ;
3177  }
3178  if ( n < 2 )
3179  {
3180  sinfo_msg_error("distances array could not be determined"
3181  " completely!, deviations of distances from"
3182  " devtol too big" ) ;
3183  cpl_free(distances) ;
3184  return NULL ;
3185  }
3186  else
3187  {
3188  distances[i] = sum / (float)n ;
3189  }
3190  }
3191 
3192  /* now sort the result according to the row sequence in the
3193  reconstructed image*/
3194 
3195  for ( i = 0 ; i < n_slitlets ; i++ )
3196  {
3197  int row_index;
3198  if( (row_index=sinfo_sort_slitlets(i)) == -1) {
3199  sinfo_msg_error("wrong number of a slitlet\n") ;
3200  cpl_free (distances) ;
3201  return NULL ;
3202  }
3203  ret_distances[row_index] = distances[i] ;
3204  }
3205  cpl_free(distances) ;
3206 
3207  cpl_free(row_buf) ;
3208  cpl_free(x_position) ;
3209  cpl_free(found);
3210  cpl_free(found_clean) ;
3211  cpl_free(found_cleanit) ;
3212  sinfo_new_destroy_2Dfloatarray(&distances_buf,n_slitlets) ;
3213 
3214 
3215  return ret_distances ;
3216 }
3241 cpl_image *
3242 sinfo_new_make_true_resamp(cpl_image * calibImage,
3243  cpl_image * wavemap)
3244 {
3245  cpl_image * returnImage ;
3246  float edges[33] ;
3247  int imsize,i,j ;
3248  int z;
3249  int col;
3250  //int recol ;
3251  int wlx=0;
3252  //int wly=0;
3253  int clx=0 ;
3254  int cly=0;
3255 
3256  float* pcdata=NULL;
3257  float* pwdata=NULL;
3258  float* prdata=NULL;
3259 
3260 
3261  wlx=cpl_image_get_size_x(wavemap);
3262  //wly=cpl_image_get_size_y(wavemap);
3263  pwdata=cpl_image_get_data_float(wavemap);
3264 
3265  edges[0]=0;
3266  j=1;
3267  for(i=0;i<wlx-1;i++)
3268  {
3269  if((pwdata[i]-pwdata[i+1])>0.0025 || (pwdata[i]-pwdata[i+1])<-0.0025)
3270  {
3271  sinfo_msg_error("wavemap sinfo_edge %d", i+1);
3272  edges[j]=i+1;
3273  j++;
3274  }
3275  }
3276  edges[32]=2048;
3277 
3278  clx=cpl_image_get_size_x(calibImage);
3279  cly=cpl_image_get_size_y(calibImage);
3280  pcdata=cpl_image_get_data_float(calibImage);
3281 
3282  imsize = clx / N_SLITLETS ;
3283 
3284  /* allocate memory */
3285  returnImage = cpl_image_new(clx,cly,CPL_TYPE_FLOAT);
3286  prdata=cpl_image_get_data_float(returnImage);
3287  for ( z = 0 ; z < cly ; z++ ) /* go through the z-axis */
3288  {
3289  for ( col = 0 ; col < clx ; col++ ) /* go through the image columns */
3290  prdata[col+z*clx]=ZERO;
3291  }
3292 
3293 
3294  /* now build the data cube out of the resampled image */
3295  for ( z = 0 ; z < cly ; z++ ) /* go through the z-axis */
3296  {
3297  int kslit = 0 ;
3298 
3299  //recol = -1 ;
3300  for ( col = 0 ; col < clx ; col++ ) /* go through the image columns */
3301  {
3302  /*if ( col % imsize == 0 )
3303  {*/
3304  //recol = 0 ;
3305  /*kslit = col/imsize ;*/
3306  for(i=0;i<32;i++)
3307  {
3308  if(col>=sinfo_new_nint(edges[i]) &&
3309  col<sinfo_new_nint(edges[i+1]))
3310  kslit=i;
3311  }
3312  /* sort the slitlets in the right spiffi specific way */
3313  int slit_index = -1 ;
3314  if( (slit_index=sinfo_sort_slitlets(kslit)) == -1) {
3315  sinfo_msg_error("wrong slitlet index: couldn't be a "
3316  "spiffi image, there must be 32 "
3317  "slitlets!") ;
3318 
3319  }
3320 
3321  /*}*/
3322 
3323  /* fill each cube plane with one image row */
3324  if((col-sinfo_new_nint(edges[kslit]))>0 &&
3325  (col-sinfo_new_nint(edges[kslit]))<imsize-1 )
3326  prdata[(col-sinfo_new_nint(edges[kslit]))+
3327  slit_index*imsize+z*clx] =
3328  pcdata[col+z*clx] ;
3329  else
3330  prdata[(col-sinfo_new_nint(edges[kslit]))+
3331  slit_index*imsize+z*clx] = ZERO;
3332  /*recol++ ;*/
3333 
3334  }
3335  }
3336  return returnImage ;
3337 }
3338 
3339 /*The old slitlet order*/
3340 /*switch (kslit)
3341  {
3342  case 0:
3343  slit_index = 23 ;
3344  break ;
3345  case 1:
3346  slit_index = 24 ;
3347  break ;
3348  case 2:
3349  slit_index = 22 ;
3350  break ;
3351  case 3:
3352  slit_index = 25 ;
3353  break ;
3354  case 4:
3355  slit_index = 21 ;
3356  break ;
3357  case 5:
3358  slit_index = 26 ;
3359  break ;
3360  case 6:
3361  slit_index = 20 ;
3362  break ;
3363  case 7:
3364  slit_index = 27 ;
3365  break ;
3366  case 8:
3367  slit_index = 19 ;
3368  break ;
3369  case 9:
3370  slit_index = 28 ;
3371  break ;
3372  case 10:
3373  slit_index = 18 ;
3374  break ;
3375  case 11:
3376  slit_index = 29 ;
3377  break ;
3378  case 12:
3379  slit_index = 17 ;
3380  break ;
3381  case 13:
3382  slit_index = 30 ;
3383  break ;
3384  case 14:
3385  slit_index = 16 ;
3386  break ;
3387  case 15:
3388  slit_index = 31 ;
3389  break ;
3390  case 16:
3391  slit_index = 0 ;
3392  break ;
3393  case 17:
3394  slit_index = 15 ;
3395  break ;
3396  case 18:
3397  slit_index = 1 ;
3398  break ;
3399  case 19:
3400  slit_index = 14 ;
3401  break ;
3402  case 20:
3403  slit_index = 2 ;
3404  break ;
3405  case 21:
3406  slit_index = 13 ;
3407  break ;
3408  case 22:
3409  slit_index = 3 ;
3410  break ;
3411  case 23:
3412  slit_index = 12 ;
3413  break ;
3414  case 24:
3415  slit_index = 4 ;
3416  break ;
3417  case 25:
3418  slit_index = 11 ;
3419  break ;
3420  case 26:
3421  slit_index = 5 ;
3422  break ;
3423  case 27:
3424  slit_index = 10 ;
3425  break ;
3426  case 28:
3427  slit_index = 6 ;
3428  break ;
3429  case 29:
3430  slit_index = 9 ;
3431  break ;
3432  case 30:
3433  slit_index = 7 ;
3434  break ;
3435  case 31:
3436  slit_index = 8 ;
3437  break ;
3438  default:
3439  sinfo_msg_error("wrong slitlet index: couldn't "
3440  "be a spiffi image, \
3441  there must be 32 slitlets!\n") ;
3442  cpl_imagelist_delete(returnCube) ;
3443  return NULL ;
3444  break ;
3445  }*/
3446 
3447 
3448 /*--------------------------------------------------------------------------*/
#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