SINFONI Pipeline Reference Manual  2.5.2
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 *
23 *
24 * who when what
25 * -------- -------- ----------------------------------------------
26 * schreib 30/08/00 created
27 */
28 
29 /************************************************************************
30 * NAME
31 * sinfo_cube_construct.c -
32 * some procedures to construct a data cube
33 *
34 * SYNOPSIS
35 *
36 * 1) cpl_image * sinfo_new_convolve_ns_image_by_gauss( cpl_image * lineImage,
37 * int hw )
38 *
39 * 2) float * sinfo_north_south_test( cpl_image * ns_image,
40 * int n_slitlets,
41 * int halfWidth,
42 * float fwhm,
43 * float minDiff,
44 * float estimated_dist,
45 * float devtol )
46 *
47 * 3) cpl_imagelist * sinfo_new_make_cube ( cpl_image * calibImage,
48 * float * distances,
49 * float * correct_diff_dist )
50 *
51 * 4) cpl_imagelist * sinfo_new_make_cube_spi ( cpl_image * calibImage,
52 * float ** slit_edges,
53 * float * shift )
54 *
55 * 5) cpl_imagelist * sinfo_new_make_cube_dist ( cpl_image * calibImage,
56 * float firstCol,
57 * float * distances,
58 * float * shift )
59 *
60 * 6) cpl_imagelist * sinfo_new_make_3D_cube_dist ( cpl_image * calibImage,
61 * float firstCol,
62 * float * distances,
63 * float * shift )
64 *
65 * 7) cpl_imagelist * sinfo_new_make_3D_cube ( cpl_image * calibImage,
66 * int * kpixshift,
67 * int kpixfirst )
68 *
69 * 8) cpl_imagelist *
70  sinfo_new_determine_mask_cube(cpl_imagelist * sourceMaskCube,
71 * float lowLimit,
72 * float highLimit )
73 *
74 * 9) cpl_imagelist * sinfo_new_interpol_cube ( cpl_imagelist * sourceCube,
75 * cpl_imagelist * maskCube,
76 * int n_neighbors,
77 * int max_radius )
78 *
79 * 10) cpl_imagelist * sinfo_new_fine_tune_cube( cpl_imagelist * cube,
80 * float * correct_diff_dist )
81 *
82 * 11) cpl_imagelist * sinfo_new_fine_tune_cube_by_FFT( cpl_imagelist * cube,
83 * float * correct_diff_dist )
84 *
85 * 12) cpl_imagelist * sinfo_new_fine_tune_cube_by_spline(cpl_imagelist * cube,
86 * float * correct_diff_dist )
87 *
88 * DESCRIPTION
89 *
90 * 1) convolves a north-south-test image with a sinfo_gaussian
91 * with user given integer half width by using the eclipse
92 * routine sinfo_function1d_filter_lowpass().
93 * 2) determines the distances of the slitlets
94 * 3) makes a data cube out of a resampled source image
95 * this SPIFFI specific routine takes into account the
96 * Spiffi slitlet order on the detector.
97 * Also shifts the resulting image rows by one pixel if
98 * necessary according to the distances array gained from
99 * the north-south test routine.
100 * Can do the same with the bad pixel map image to generate a
101 * bad pixel mask cube.
102 * 4) makes a data cube out of a resampled source image
103 * this SPIFFI specific routine takes into account the
104 * Spiffi slitlet order on the detector.
105 * This routine takes fitted slitlet positions into account.
106 * Can do the same with the bad pixel map image to generate a
107 * bad pixel mask cube.
108 * 5) makes a data cube out of a resampled source image
109 * this SPIFFI specific routine takes into account the
110 * Spiffi slitlet order on the detector.
111 * Also shifts the resulting image rows by one pixel if
112 * necessary according to the distances array gained from
113 * the north-south test routine.
114 * Can do the same with the bad pixel map image to generate a
115 * bad pixel mask cube.
116 * 6) makes a data cube out of a resampled source image
117 * this 3D specific routine takes into account the
118 * 3D slitlet order on the detector.
119 * Also shifts the resulting image rows by one pixel if
120 * necessary according to the distances array gained from
121 * the north-south test routine.
122 * Can do the same with the bad pixel map image to generate a
123 * bad pixel mask cube.
124 * 7) makes a data cube out of a resampled source image
125 * this MPE 3D specific routine takes into account the
126 * 3D slitlet order on the detector.
127 * Also shifts the resulting image row by an integer pixel shift if
128 * necessary according to the input kpixshift array
129 * Can do the same with the bad pixel map image to generate a
130 * bad pixel mask cube.
131 * 8) converts resampled bad pixels to real bad pixels in data cubes.
132 * 9) Bad pixel interpolation 3D like (saturated pixels exist):
133 * interpolates the bad pixels of the source cube by
134 * using the nearest neighbors.
135 * first it is checked if the bad pixel is interpolatable:
136 * it is only interpolatable if the number of good pixels
137 * in its spectrum of length 2*n_neighbors+1 exceeds 3 and
138 * if there is at least one good pixel on either side of the
139 * central pixel.
140 * Afterwards good neighboring pixels are searched within the
141 * image plane of the bad pixel by using an increasing pixel radius.
142 * Good pixels mean, the corresponding spectral pixels of the
143 * bad pixel and its spatial neighboring pixel must have
144 * at least 2 valid pixel pairs to be able to be used for
145 * the interpolation. The search is stopped if 9 valid neighboring
146 * pixels are found.
147 * Now normalize the found spectral values, collect the valid pixels
148 * (there must be at least 18) and take the sinfo_median of the valid
149 * pixels with which the bad pixel is replaced.
150 * 10) fine tunes each row in the right position according
151 * to the distances of the slitlets to each other
152 * (output of the north-south test).
153 * This means that the rows must be realigned by a
154 * fraction of a pixel to accomodate non-integer slit
155 * length. The fractional realignment is done by using
156 * the polynomial interpolation algorithm of N.R.
157 * Each row is rescaled so that the total flux is
158 * conserved.
159 * 11) fine tunes each row in the right position according
160 * to the distances of the slitlets to each other
161 * (output of the north-south test).
162 * This means that the rows must be realigned by a
163 * fraction of a pixel to accomodate non-integer slit
164 * length. The fractional realignment is done by using
165 * the FFT algorithm four1() of N.R.
166 * 12) fine tunes each row in the right position according
167 * to the distances of the slitlets to each other
168 * (output of the north-south test).
169 * This means that the rows must be realigned by a
170 * fraction of a pixel to accomodate non-integer slit
171 * length. The fractional realignment is done by using
172 * the spline interpolation algorithm splint in connection
173 * with the algorithm spline of N.R.
174 * This algorithms assume that each row is a tabulated
175 * function. The first derivatives of the interpolating
176 * function at the first and last point must be given.
177 * These are set higher than 1xe^30, so the routine
178 * sets the corresponding boundary condition for a natural
179 * spline, with zero second derivative on that boundary.
180 * Each row is rescaled so that the total flux is
181 * conserved.
182 *
183 * FILES
184 *
185 * ENVIRONMENT
186 *
187 * RETURN VALUES
188 *
189 * CAUTIONS
190 *
191 * EXAMPLES
192 *
193 * SEE ALSO
194 *
195 * BUGS
196 *
197 *------------------------------------------------------------------------
198 */
199 
200 #ifdef HAVE_CONFIG_H
201 # include <config.h>
202 #endif
203 #define POSIX_SOURCE 1
204 #include "sinfo_vltPort.h"
205 
206 /*
207  * System Headers
208  */
209 
210 /*
211  * Local Headers
212  */
213 #include "sinfo_function_1d.h"
214 #include "sinfo_cube_construct.h"
215 #include "sinfo_spectrum_ops.h"
216 #include "sinfo_wave_calibration.h"
217 #include "sinfo_utilities.h"
218 #include "sinfo_local_types.h"
219 #include "sinfo_fft_base.h"
220 
221 static int
222 sinfo_sort_slitlets(const int kslit);
223 
224 
225 static int
226 sinfo_sort_slitlets_array(const int slit, int* row_index);
227 
235 /*----------------------------------------------------------------------------
236  * Function codes
237  *--------------------------------------------------------------------------*/
248 cpl_image *
249 sinfo_new_convolve_ns_image_by_gauss( cpl_image * lineImage,
250  int hw )
251 {
252  cpl_image * returnImage ;
253  float* row_buffer=NULL ;
254  float * filter ;
255  int col, row ;
256  int ilx=0;
257  int ily=0;
258 
259  float* pidata=NULL;
260  float* podata=NULL;
261 
262  if ( lineImage == NULL )
263  {
264  sinfo_msg_error("no input image given!\n") ;
265  return NULL ;
266  }
267  ilx=cpl_image_get_size_x(lineImage);
268  ily=cpl_image_get_size_y(lineImage);
269  pidata=cpl_image_get_data_float(lineImage);
270  if ( hw < 1 )
271  {
272  sinfo_msg_error(" wrong half width given!\n") ;
273  return NULL ;
274  }
275 
276  /* allocate memory for returned image */
277  if ( NULL == ( returnImage = cpl_image_new(ilx,ily,CPL_TYPE_FLOAT ) ))
278  {
279  sinfo_msg_error("cannot allocate a new image\n");
280  return NULL ;
281  }
282  podata=cpl_image_get_data_float(returnImage);
283 
284  /* go through the image rows and save them in a buffer */
285  row_buffer=cpl_calloc(ily,sizeof(float)) ;
286 
287  for ( row = 0 ; row < ily ; row++ )
288  {
289  for ( col = 0 ; col < ilx ; col++ )
290  {
291  if ( isnan(pidata[col+row*ilx]) )
292  {
293  row_buffer[col] = 0. ;
294  }
295  else
296  {
297  row_buffer[col] = pidata[col + row*ilx] ;
298  }
299  }
300 
301  /*--------------------------------------------------------------------
302  * now low pass filter the rows by the gaussian and fill the return
303  * image.
304  */
305  filter = sinfo_function1d_filter_lowpass( row_buffer,
306  ilx,
307  LOW_PASS_GAUSSIAN,
308  hw ) ;
309  for ( col = 0 ; col < ily ; col++ )
310  {
311  podata[col + row*ilx] = filter[col] ;
312  }
313  /* deallocate memory */
314  sinfo_function1d_del (filter) ;
315  }
316  cpl_free(row_buffer);
317  return returnImage ;
318 }
319 
336 float *
337 sinfo_north_south_test( cpl_image * ns_image,
338  int n_slitlets,
339  int halfWidth,
340  float fwhm,
341  float minDiff,
342  float estimated_dist,
343  float devtol,
344  int bottom,
345  int top )
346 {
347  int i, j, k, m, row, col, n, ni, na ;
348  int position, counter, iters ;
349  int xdim, ndat, its, numpar ;
350  pixelvalue row_buf[cpl_image_get_size_x(ns_image)] ;
351  float sum, mean, maxval ;
352  float tol, lab ;
353  float * distances ;
354  float distances_buf[cpl_image_get_size_y(ns_image)][n_slitlets-1] ;
355  float x_position[n_slitlets] ;
356  float * xdat, * wdat ;
357  int * mpar ;
358  int found[3*n_slitlets], found_clean[3*n_slitlets] ;
359  int found_cleanit[3*n_slitlets] ;
360  Vector * line ;
361  FitParams ** par ;
362  int foundit, begin, end ;
363  int zeroindicator ;
364  int ilx=0;
365  //int ily=0;
366 
367  float* pidata=NULL;
368 
369  if ( ns_image == NULL )
370  {
371  sinfo_msg_error("sorry, no image given\n") ;
372  return NULL ;
373  }
374  ilx=cpl_image_get_size_x(ns_image);
375  //ily=cpl_image_get_size_y(ns_image);
376  pidata=cpl_image_get_data_float(ns_image);
377 
378 
379  if ( n_slitlets < 1 )
380  {
381  sinfo_msg_error("wrong number of slitlets given\n") ;
382  return NULL ;
383  }
384  if ( halfWidth < 0 || halfWidth >= estimated_dist )
385  {
386  sinfo_msg_error("wrong half width given\n") ;
387  return NULL ;
388  }
389  if ( fwhm <= 0. )
390  {
391  sinfo_msg_error("wrong fwhm given\n") ;
392  return NULL ;
393  }
394  if ( minDiff < 1. )
395  {
396  sinfo_msg_error("wrong minDiff given\n") ;
397  return NULL ;
398  }
399 
400  /* allocate memory for output array */
401  if (NULL == (distances = (float *) cpl_calloc ( n_slitlets - 1 ,
402  sizeof (float) )))
403  {
404  sinfo_msg_error("could not allocate memory\n") ;
405  return NULL ;
406  }
407 
408  /* go through the image rows */
409  for ( row = bottom ; row < top ; row++ )
410  {
411  zeroindicator = 0 ;
412 
413  /* initialize the distance buffer */
414  for ( i = 0 ; i < n_slitlets-1 ; i++ )
415  {
416  distances_buf[row][i] = ZERO ;
417  }
418 
419  /* fill the row buffer array with image data */
420  for ( col = 0 ; col < ilx ; col++ )
421  {
422  row_buf[col] = pidata[col + row*ilx] ;
423  }
424 
425  /* determine the mean of the row data */
426  sum = 0. ;
427  n = 0 ;
428  for ( i = 0 ; i < ilx ; i++ )
429  {
430  if ( isnan(row_buf[i]) )
431  {
432  continue ;
433  }
434  sum += row_buf[i] ;
435  n++ ;
436  }
437  mean = sum / (float)n ;
438 
439 
440  /* store the positions of image values greater than the mean */
441  n = 0 ;
442  for ( i = 0 ; i < ilx ; i++ )
443  {
444  if (isnan(row_buf[i]))
445  {
446  continue ;
447  }
448  if ( row_buf[i] > sqrt(mean*mean*9) )
449  {
450  found[n] = i ;
451  n++ ;
452  }
453  }
454 
455  if ( n < n_slitlets )
456  {
457  sinfo_msg_warning("t1 wrong number of intensity columns found "
458  "in row: %d, found number: %d, mean: %g",
459  row, n, mean) ;
460  continue ;
461  }
462  else
463  {
464  /* find the maximum value position around the found columns */
465  na = 0 ;
466  for ( i = 1 ; i < n ; i ++ )
467  {
468  if ( found[i] - found[i-1] < halfWidth )
469  {
470  begin = found[i] - halfWidth ;
471  if ( begin < 0 )
472  {
473  begin = 0 ;
474  }
475  end = found[i] + halfWidth ;
476  if ( end >= ilx )
477  {
478  end = ilx - 1 ;
479  }
480  /* find the maximum value inside the box
481  around the found positions*/
482  maxval = -FLT_MAX ;
483  foundit = 0 ;
484  for ( j = begin ; j <= end ; j++ )
485  {
486  /* do not consider boxes that contain bad pixels */
487  if (isnan(row_buf[j]))
488  {
489  continue ;
490  }
491  if (row_buf[j] >= maxval )
492  {
493  maxval = row_buf[j] ;
494  foundit = j ;
495  }
496  }
497  if (maxval == -FLT_MAX)
498  {
499  continue ;
500  }
501  for ( k = 0 ; k < na ; k++ )
502  {
503  if ( found_cleanit[k] >= begin &&
504  found_cleanit[k] < foundit )
505  {
506  na-- ;
507  }
508  }
509  for ( k = 0 ; k < n ; k++ )
510  {
511  if ( found[k] == foundit)
512  {
513  if (na>0){
514  if ( found_cleanit[na-1] != found[k] )
515  {
516  found_cleanit[na] = found[k] ;
517  na++ ;
518  }
519  }
520  else{
521  found_cleanit[na] = found[k] ;
522  na++ ;
523  }
524  }
525  }
526  }
527  else
528  {
529  if ( i == 1 )
530  {
531  found_cleanit[na] = found[0] ;
532  na++ ;
533  found_cleanit[na] = found[1] ;
534  na++ ;
535  }
536  else
537  {
538  if (na>0){
539  if ( found_cleanit[na-1] != found[i-1])
540  {
541  found_cleanit[na] = found[i-1] ;
542  na++ ;
543  }
544  if ( found_cleanit[na-1] != found[i])
545  {
546  found_cleanit[na] = found[i] ;
547  na++ ;
548  }
549  }
550  else
551  {
552  found_cleanit[na] = found[i] ;
553  na++ ;
554  }
555  }
556  }
557  }
558  /* determine only one pixel position for each slitlet intensity */
559  j = 1 ;
560  for ( i = 1 ; i < na ; i++ )
561  {
562  if ( (float)(found_cleanit[i] - found_cleanit[i-1]) <
563  (estimated_dist - devtol) ||
564  (float)(found_cleanit[i] - found_cleanit[i-1]) >
565  (estimated_dist + devtol) )
566  {
567  continue ;
568  }
569  else
570  {
571  found_clean[j-1] = found_cleanit[i-1] ;
572  found_clean[j] = found_cleanit[i] ;
573  j++ ;
574  }
575  }
576  }
577  if ( j > n_slitlets )
578  {
579  /* check the distance again */
580  ni = 1 ;
581  for ( i = 1 ; i < j ; i++ )
582  {
583  if ( (float)(found_clean[i] - found_clean[i-1]) <
584  (estimated_dist - devtol ) ||
585  (float)(found_clean[i] - found_clean[i-1]) >
586  (estimated_dist + devtol ) )
587  {
588  continue ;
589  }
590  else
591  {
592 
593  found_clean[ni-1] = found_clean[i-1] ;
594  found_clean[ni] = found_clean[i] ;
595  ni++ ;
596  }
597  }
598  if ( ni != n_slitlets )
599  {
600  sinfo_msg_warning("t2 wrong number of intensity columns"
601  " found in row: %d, found number: %d",
602  row, ni) ;
603  continue ;
604  }
605  else
606  {
607  j = ni ;
608  }
609  }
610  else if ( j < n_slitlets )
611  {
612  cpl_msg_debug ("north_south_test3:",
613  "t3 wrong number of intensity columns "
614  "found in row: %d , found number: %d, mean: %g\n",
615  row, j, mean) ;
616  continue ;
617  }
618  counter = 0 ;
619  /* go through the found intensity pixels in one row */
620  for ( i = 0 ; i < j ; i++ )
621  {
622  /* allocate memory for the array where the line is fitted in */
623  if ( NULL == (line = sinfo_new_vector (2*halfWidth + 1)) )
624  {
625  sinfo_msg_error ("cannot allocate new Vector \n") ;
626  cpl_free(distances) ;
627  return NULL ;
628  }
629 
630  /* allocate memory */
631  xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
632  wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
633  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
634  par = sinfo_new_fit_params(1) ;
635 
636  m = 0 ;
637  for ( k = found_clean[i]-halfWidth ;
638  k <= found_clean[i]+halfWidth ; k++ )
639  {
640  if ( k < 0 )
641  {
642  k = 0. ;
643  }
644  else if ( k >= ilx )
645  {
646  k = ilx - 1 ;
647  }
648  else if ( isnan(row_buf[k]) )
649  {
650  zeroindicator = 1 ;
651  break ;
652  }
653  else
654  {
655  line -> data[m] = row_buf[k] ;
656  m++ ;
657  }
658  }
659  if ( zeroindicator == 1 )
660  {
661  sinfo_new_destroy_vector(line) ;
662  cpl_free(xdat) ;
663  cpl_free(wdat) ;
664  cpl_free(mpar) ;
665  sinfo_new_destroy_fit_params(&par) ;
666  break ;
667  }
668 
669  /*----------------------------------------------------------------
670  * go through the spectral sinfo_vector
671  * determine the maximum pixel value in the spectral sinfo_vector
672  */
673  maxval = -FLT_MAX ;
674  position = -INT32_MAX ;
675  for ( k = 0 ; k < m ; k++ )
676  {
677  xdat[k] = k ;
678  wdat[k] = 1.0 ;
679  if ( line -> data[k] >= maxval )
680  {
681  maxval = line -> data[k] ;
682  position = k ;
683  }
684  }
685 
686  /* set initial values for the fitting routine */
687  xdim = XDIM ;
688  ndat = line -> n_elements ;
689  numpar = MAXPAR ;
690  tol = TOL ;
691  lab = LAB ;
692  its = ITS ;
693  (*par) -> fit_par[1] = fwhm ;
694  (*par) -> fit_par[2] = (float) position ;
695  (*par) -> fit_par[3] = (float) (line -> data[0] +
696  line -> data[line->n_elements - 1]) / 2.0 ;
697  (*par) -> fit_par[0] = maxval - ((*par) -> fit_par[3]) ;
698 
699 
700  /* exclude negative peaks and low signal cases */
701  if ( (*par) -> fit_par[0] < minDiff )
702  {
703  sinfo_msg_warning ("sorry, signal of line too low to fit "
704  "in row: %d in slitlet %d\n", row, i) ;
705  sinfo_new_destroy_vector(line) ;
706  cpl_free(xdat) ;
707  cpl_free(wdat) ;
708  cpl_free(mpar) ;
709  sinfo_new_destroy_fit_params(&par) ;
710  continue ;
711  }
712 
713  for ( k = 0 ; k < MAXPAR ; k++ )
714  {
715  (*par) -> derv_par[k] = 0.0 ;
716  mpar[k] = 1 ;
717  }
718  /* finally, do the least square fit using a Gaussian */
719  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim,
720  line -> data, wdat, &ndat,
721  (*par) -> fit_par,
722  (*par) -> derv_par, mpar,
723  &numpar, &tol, &its, &lab)) )
724  {
725  /*
726  cpl_msg_debug ("north_south_test:",
727  "sinfo_lsqfit_c: least squares fit failed,"
728  " error no.: %d in row: %d in slitlet %d\n",
729  iters, row, i) ;
730  */
731  sinfo_new_destroy_vector(line) ;
732  cpl_free(xdat) ;
733  cpl_free(wdat) ;
734  cpl_free(mpar) ;
735  sinfo_new_destroy_fit_params(&par) ;
736  continue ;
737  }
738 
739  /* check for negative fit results */
740  if ( (*par) -> fit_par[0] <= 0. ||
741  (*par) -> fit_par[1] <= 0. ||
742  (*par) -> fit_par[2] < 0. )
743  {
744  sinfo_msg_warning ("negative parameters as fit result, "
745  "not used! in row %d in slitlet %d",
746  row, i) ;
747  sinfo_new_destroy_vector(line) ;
748  cpl_free(xdat) ;
749  cpl_free(wdat) ;
750  cpl_free(mpar) ;
751  sinfo_new_destroy_fit_params(&par) ;
752  continue ;
753  }
754 
755  /* correct the fitted position for the given row of the line
756  in image coordinates */
757  (*par) -> fit_par[2] = (float) (found_clean[i] - halfWidth) +
758  (*par) -> fit_par[2] ;
759  x_position[counter] = (*par) -> fit_par[2] ;
760  counter ++ ;
761 
762  /* free memory */
763  sinfo_new_destroy_fit_params(&par) ;
764  sinfo_new_destroy_vector ( line ) ;
765  cpl_free ( xdat ) ;
766  cpl_free ( wdat ) ;
767  cpl_free ( mpar ) ;
768  }
769  if (zeroindicator == 1)
770  {
771  sinfo_msg_debug ("bad pixel in fitting box in row: %d\n", row) ;
772  continue ;
773  }
774 
775  if ( counter != n_slitlets )
776  {
777  continue ;
778  sinfo_msg_warning("wrong number of slitlets found in row: %d",row);
779  }
780  /* store the distances between the sources in a buffer */
781  for ( i = 1 ; i < n_slitlets ; i++ )
782  {
783  distances_buf[row][i-1] = x_position[i] - x_position[i-1] ;
784  }
785  }
786 
787  /* ----------------------------------------------------------------
788  * go through the rows again and take the mean of the distances,
789  * throw away the runaways
790  */
791  for ( i = 0 ; i < n_slitlets-1 ; i++ )
792  {
793  n = 0 ;
794  sum = 0. ;
795  for ( row = bottom ; row < top ; row++ )
796  {
797  if ( fabs( distances_buf[row][i] - estimated_dist ) > devtol ||
798  isnan(distances_buf[row][i]) )
799  {
800  /*
801  sinfo_msg("dist=%g devtol=%g isan=%d",
802  distances_buf[row][i],
803  devtol,
804  isnan(distances_buf[row][i]));
805  */
806  continue ;
807  }
808  sum += distances_buf[row][i] ;
809  n++ ;
810  }
811  if ( n < 2 )
812  {
813  sinfo_msg_error("distances array could not be determined "
814  "completely!, deviations of distances from number "
815  "of slitlets too big\n" ) ;
816  cpl_free(distances) ;
817  return NULL ;
818  }
819  else
820  {
821  distances[i] = sum / (float)n ;
822  }
823  }
824  return distances ;
825 }
826 
850 cpl_imagelist *
851 sinfo_new_make_cube ( cpl_image * calibImage,
852  float * distances,
853  float * correct_diff_dist )
854 {
855  cpl_imagelist * returnCube ;
856  int imsize, kslit, kpix ;
857  int slit_index ;
858  int z, col, recol ;
859  int ilx=0;
860  int ily=0;
861 
862  float* podata=NULL;
863  float* pidata=NULL;
864  cpl_image* o_img;
865 
866  if ( NULL == calibImage )
867  {
868  sinfo_msg_error("no resampled image given!\n") ;
869  return NULL ;
870  }
871  ilx=cpl_image_get_size_x(calibImage);
872  ily=cpl_image_get_size_y(calibImage);
873  pidata=cpl_image_get_data_float(calibImage);
874 
875  if ( NULL == distances )
876  {
877  sinfo_msg_error("no distances array from ns_test given!/n") ;
878  return NULL ;
879  }
880 
881  if ( NULL == correct_diff_dist )
882  {
883  sinfo_msg_error("correct_diff_dist array is not allocated!/n") ;
884  return NULL ;
885  }
886 
887  if ( N_SLITLETS != 32 )
888  {
889  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
890  return NULL ;
891  }
892  imsize = ilx / N_SLITLETS ;
893 
894  /* allocate memory */
895  if ( NULL == (returnCube = cpl_imagelist_new()) )
896  {
897  sinfo_msg_error ("cannot allocate new cube \n" ) ;
898  return NULL ;
899  }
900 
901  /* now build the data cube out of the resampled image */
902  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
903  {
904 
905  o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
906  podata=cpl_image_get_data_float(o_img);
907  kpix = 0 ;
908  kslit = 0 ;
909  slit_index = -1 ;
910  recol = -1 ;
911  for ( col = 0 ; col < ilx ; col++ ) /* go through the image columns */
912  {
913  if ( col % imsize == 0 )
914  {
915  recol = 0 ;
916  kslit = col/imsize ;
917  /* sort the slitlets in the right spiffi specific way */
918  if((slit_index=sinfo_sort_slitlets(kslit)) == -1) {
919  sinfo_msg_error("wrong slitlet index: couldn't be a "
920  "spiffi image, there must be 32 slitlets!") ;
921  cpl_imagelist_delete(returnCube) ;
922  return NULL ;
923  }
924 
925  if ( kslit != 0 )
926  {
927  /*--------------------------------------------------------
928  * shift the first pixel by an integer if the absolute
929  * amount of distances[]
930  * is bigger than 0.5
931  */
932  kpix = sinfo_new_nint(distances[kslit-1]) ;
933 
934  /*-----------------------------------------------
935  * now sort the distances array according to the row order
936  * and add a 0 value for the first (reference) slitlet
937  * that means row 8
938  */
939  correct_diff_dist[slit_index] = distances[kslit-1] -
940  (float)kpix ;
941  }
942  /* refer all distances to the first slitlet */
943  else
944  {
945  correct_diff_dist[slit_index] = 0. ;
946  }
947  }
948 
949  /* fill each cube plane with one image row */
950  podata[recol+slit_index*imsize] = pidata[col+kpix+z*ilx];
951  recol++ ;
952 
953  if ( recol > imsize )
954  {
955  sinfo_msg_error("wrong column of reconstructed "
956  "image, shouldn't happen!\n") ;
957  cpl_imagelist_delete(returnCube) ;
958  return NULL ;
959  }
960  }
961  }
962  return returnCube ;
963 }
964 
965 
966 
974 static int
975 sinfo_sort_slitlets(const int kslit)
976 {
977  int slit_index=0;
978 
979  switch (kslit)
980  {
981  case 0:
982  slit_index = 8 ;
983  break ;
984  case 1:
985  slit_index = 7 ;
986  break ;
987  case 2:
988  slit_index = 9 ;
989  break ;
990  case 3:
991  slit_index = 6 ;
992  break ;
993  case 4:
994  slit_index = 10 ;
995  break ;
996  case 5:
997  slit_index = 5 ;
998  break ;
999  case 6:
1000  slit_index = 11 ;
1001  break ;
1002  case 7:
1003  slit_index = 4 ;
1004  break ;
1005  case 8:
1006  slit_index = 12 ;
1007  break ;
1008  case 9:
1009  slit_index = 3 ;
1010  break ;
1011  case 10:
1012  slit_index = 13 ;
1013  break ;
1014  case 11:
1015  slit_index = 2 ;
1016  break ;
1017  case 12:
1018  slit_index = 14 ;
1019  break ;
1020  case 13:
1021  slit_index = 1 ;
1022  break ;
1023  case 14:
1024  slit_index = 15 ;
1025  break ;
1026  case 15:
1027  slit_index = 0 ;
1028  break ;
1029  case 16:
1030  slit_index = 31 ;
1031  break ;
1032  case 17:
1033  slit_index = 16 ;
1034  break ;
1035  case 18:
1036  slit_index = 30 ;
1037  break ;
1038  case 19:
1039  slit_index = 17 ;
1040  break ;
1041  case 20:
1042  slit_index = 29 ;
1043  break ;
1044  case 21:
1045  slit_index = 18 ;
1046  break ;
1047  case 22:
1048  slit_index = 28 ;
1049  break ;
1050  case 23:
1051  slit_index = 19 ;
1052  break ;
1053  case 24:
1054  slit_index = 27 ;
1055  break ;
1056  case 25:
1057  slit_index = 20 ;
1058  break ;
1059  case 26:
1060  slit_index = 26 ;
1061  break ;
1062  case 27:
1063  slit_index = 21 ;
1064  break ;
1065  case 28:
1066  slit_index = 25 ;
1067  break ;
1068  case 29:
1069  slit_index = 22 ;
1070  break ;
1071  case 30:
1072  slit_index = 24 ;
1073  break ;
1074  case 31:
1075  slit_index = 23 ;
1076  break ;
1077  default:
1078  sinfo_msg_error("wrong slitlet index: couldn't be a "
1079  "spiffi image, there must be 32 slitlets!") ;
1080  return -1 ;
1081 
1082 
1083  }
1084  return slit_index;
1085 
1086 }
1087 
1098 static int
1099 sinfo_sort_slitlets_array(const int slit, int* row_index)
1100 {
1101 
1102  switch (slit)
1103  {
1104  case 0:
1105  row_index[0] = 8 ;
1106  break ;
1107  case 1:
1108  row_index[1] = 7 ;
1109  break ;
1110  case 2:
1111  row_index[2] = 9 ;
1112  break ;
1113  case 3:
1114  row_index[3] = 6 ;
1115  break ;
1116  case 4:
1117  row_index[4] = 10 ;
1118  break ;
1119  case 5:
1120  row_index[5] = 5 ;
1121  break ;
1122  case 6:
1123  row_index[6] = 11 ;
1124  break ;
1125  case 7:
1126  row_index[7] = 4 ;
1127  break ;
1128  case 8:
1129  row_index[8] = 12 ;
1130  break ;
1131  case 9:
1132  row_index[9] = 3 ;
1133  break ;
1134  case 10:
1135  row_index[10] = 13 ;
1136  break ;
1137  case 11:
1138  row_index[11] = 2 ;
1139  break ;
1140  case 12:
1141  row_index[12] = 14 ;
1142  break ;
1143  case 13:
1144  row_index[13] = 1 ;
1145  break ;
1146  case 14:
1147  row_index[14] = 15 ;
1148  break ;
1149  case 15:
1150  row_index[15] = 0 ;
1151  break ;
1152  case 16:
1153  row_index[16] = 31 ;
1154  break ;
1155  case 17:
1156  row_index[17] = 16 ;
1157  break ;
1158  case 18:
1159  row_index[18] = 30 ;
1160  break ;
1161  case 19:
1162  row_index[19] = 17 ;
1163  break ;
1164  case 20:
1165  row_index[20] = 29 ;
1166  break ;
1167  case 21:
1168  row_index[21] = 18 ;
1169  break ;
1170  case 22:
1171  row_index[22] = 28 ;
1172  break ;
1173  case 23:
1174  row_index[23] = 19 ;
1175  break ;
1176  case 24:
1177  row_index[24] = 27 ;
1178  break ;
1179  case 25:
1180  row_index[25] = 20 ;
1181  break ;
1182  case 26:
1183  row_index[26] = 26 ;
1184  break ;
1185  case 27:
1186  row_index[27] = 21 ;
1187  break ;
1188  case 28:
1189  row_index[28] = 25 ;
1190  break ;
1191  case 29:
1192  row_index[29] = 22 ;
1193  break ;
1194  case 30:
1195  row_index[30] = 24 ;
1196  break ;
1197  case 31:
1198  row_index[31] = 23 ;
1199  break ;
1200  default:
1201  sinfo_msg_error("wrong slitlet index: couldn't be a spiffi "
1202  "image, there must be 32 slitlets!\n") ;
1203  return -1 ;
1204  }
1205 
1206  return 0;
1207 
1208 }
1209 
1210 
1211 
1228 cpl_imagelist *
1229 sinfo_new_make_cube_spi ( cpl_image * calibImage,
1230  float ** slit_edges,
1231  float * shift )
1232 {
1233  cpl_imagelist * returnCube ;
1234  float diff, start ;
1235  float * center ;
1236  int * row_index ;
1237  int slit ;
1238  int col, z ;
1239  int imsize ;
1240  int * beginCol ;
1241  int col_counter ;
1242  int ilx=0;
1243  int ily=0;
1244 
1245  float* podata=NULL;
1246  float* pidata=NULL;
1247  cpl_image* o_img;
1248 
1249 
1250  if ( NULL == calibImage )
1251  {
1252  sinfo_msg_error("no resampled image given!\n") ;
1253  return NULL ;
1254  }
1255  ilx=cpl_image_get_size_x(calibImage);
1256  ily=cpl_image_get_size_y(calibImage);
1257  pidata=cpl_image_get_data_float(calibImage);
1258 
1259  if ( NULL == slit_edges )
1260  {
1261  sinfo_msg_error("no slit_edges array given from sinfo_fitSlits()!/n") ;
1262  return NULL ;
1263  }
1264 
1265  if ( N_SLITLETS != 32 )
1266  {
1267  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1268  return NULL ;
1269  }
1270  imsize = ilx / N_SLITLETS ;
1271 
1272  /* allocate memory */
1273  if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1274  {
1275  sinfo_msg_error ("cannot allocate memory \n" ) ;
1276  return NULL ;
1277  }
1278  if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1279  {
1280  sinfo_msg_error ("cannot allocate memory \n" ) ;
1281  cpl_free(row_index) ;
1282  return NULL ;
1283  }
1284  if ( NULL == (center = (float*) cpl_calloc(N_SLITLETS, sizeof(float)) ) )
1285  {
1286  sinfo_msg_error ("cannot allocate memory \n" ) ;
1287  cpl_free (row_index) ;
1288  cpl_free (beginCol) ;
1289  return NULL ;
1290  }
1291  if ( NULL == (returnCube = cpl_imagelist_new()) )
1292  {
1293  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1294  cpl_free (row_index) ;
1295  cpl_free (beginCol) ;
1296  cpl_free (center) ;
1297  return NULL ;
1298  }
1299  /* determine the absolute center of the slitlets and the distances
1300  inside the image*/
1301  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1302  /* go through the slitlets of each row of the resampled image */
1303  {
1304  center[slit] = (slit_edges[slit][1] + slit_edges[slit][0]) / 2. ;
1305  /* -------------------------------------------------------------
1306  * sort the slitlets in the right spiffi specific way
1307  * the row_index describes the row index of the current slitlet
1308  * in the resulting cube images.
1309  */
1310  if(-1 == sinfo_sort_slitlets_array(slit,row_index)) {
1311  cpl_imagelist_delete(returnCube) ;
1312  cpl_free (row_index) ;
1313  cpl_free (beginCol) ;
1314  cpl_free (center) ;
1315  return NULL ;
1316  }
1317  /* determine the integer column on which the slitlet starts, center the
1318  slitlet on the image row */
1319  start = center[slit] - (float) (imsize - 1)/2. ;
1320  beginCol[slit] = sinfo_new_nint (start) ;
1321  /* determine the error of using integer pixels */
1322  diff = start - (float)beginCol[slit] ;
1323 
1324  /*--------------------------------------------------------------------
1325  * determine the output shift values by which the rows are finally
1326  shifted, consider the integer pixel errors
1327  * resort shift array to get the row index
1328  */
1329  shift[row_index[slit]] = diff ;
1330  }
1331 
1332  /* now build the data cube out of the resampled image */
1333  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1334  {
1335  o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1336  podata=cpl_image_get_data_float(o_img);
1337  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1338  {
1339  col_counter = beginCol[slit] ;
1340  /* each slitlet is centered on the final image row */
1341  for ( col = 0 ; col < imsize ; col++ )
1342  {
1343  if ( col_counter > ilx-1 )
1344  {
1345  col_counter-- ;
1346  }
1347  if ( col_counter + z*ilx < 0 )
1348  {
1349  podata[col+row_index[slit]*imsize] = pidata[0] ;
1350  }
1351  else
1352  {
1353  podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
1354  }
1355 
1356  col_counter++ ;
1357  }
1358  }
1359  cpl_imagelist_set(returnCube,o_img,z);
1360  }
1361  cpl_free (row_index) ;
1362  cpl_free (beginCol) ;
1363  cpl_free (center) ;
1364 
1365  return returnCube ;
1366 }
1393 cpl_imagelist *
1394 sinfo_new_make_cube_dist ( cpl_image * calibImage,
1395  float firstCol,
1396  float * distances,
1397  float * shift )
1398 {
1399  cpl_imagelist * returnCube ;
1400  float di ;
1401  float diff, start ;
1402  int * row_index ;
1403  int slit ;
1404  int col, z ;
1405  int imsize ;
1406  int * beginCol ;
1407  int col_counter ;
1408  int ilx=0;
1409  int ily=0;
1410 
1411  float* podata=NULL;
1412  float* pidata=NULL;
1413  cpl_image* o_img;
1414 
1415  if ( NULL == calibImage )
1416  {
1417  sinfo_msg_error(" no resampled image given!\n") ;
1418  return NULL ;
1419  }
1420  ilx=cpl_image_get_size_x(calibImage);
1421  ily=cpl_image_get_size_y(calibImage);
1422  pidata=cpl_image_get_data_float(calibImage);
1423 
1424  if ( NULL == distances )
1425  {
1426  sinfo_msg_error("no distances array given from north_south_test()!") ;
1427  return NULL ;
1428  }
1429 
1430  if ( N_SLITLETS != 32 )
1431  {
1432  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1433  return NULL ;
1434  }
1435  imsize = ilx / N_SLITLETS ;
1436 
1437  /* allocate memory */
1438  if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1439  {
1440  sinfo_msg_error ("cannot allocate memory \n" ) ;
1441  return NULL ;
1442  }
1443  if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1444  {
1445  sinfo_msg_error ("cannot allocate memory \n" ) ;
1446  cpl_free(row_index) ;
1447  return NULL ;
1448  }
1449  if ( NULL == (returnCube = cpl_imagelist_new()) )
1450  {
1451  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1452  cpl_free(row_index) ;
1453  cpl_free(beginCol) ;
1454  return NULL ;
1455  }
1456 
1457  di = 0. ;
1458  /* determine the absolute beginning of the slitlets and the distances
1459  inside the image*/
1460  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1461  /* go through the slitlets of each row of the resampled image */
1462  {
1463 
1464  /* -------------------------------------------------------------
1465  * sort the slitlets in the right spiffi specific way
1466  * the row_index describes the row index of the current slitlet
1467  * in the resulting cube images.
1468  */
1469  if(-1 == sinfo_sort_slitlets_array(slit,row_index)) {
1470  cpl_imagelist_delete(returnCube) ;
1471  cpl_free(row_index) ;
1472  cpl_free(beginCol) ;
1473  return NULL ;
1474  }
1475 
1476  /* determine the integer column on which the slitlet starts */
1477  if ( slit == 0 )
1478  {
1479  start = firstCol ;
1480  }
1481  else
1482  {
1483  di += distances[slit-1] ;
1484  start = firstCol + di ;
1485  }
1486  beginCol[slit] = sinfo_new_nint(start) ;
1487 
1488  /* determine the error of using integer pixels, its always smaller
1489  than 1 */
1490  diff = start - (float)beginCol[slit] ;
1491 
1492  /*----------------------------------------------------------------
1493  * determine the output shift values by which the rows are finally
1494  * shifted, consider the integer pixel errors and resort shift array
1495  * to get the row index
1496  */
1497  shift[row_index[slit]] = diff ;
1498  }
1499 
1500  /* now build the data cube out of the resampled image */
1501  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1502  {
1503  o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1504  podata=cpl_image_get_data_float(o_img);
1505  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1506  {
1507  col_counter = beginCol[slit] ;
1508  /* each slitlet is centered on the final image row */
1509  for ( col = 0 ; col < imsize ; col++ )
1510  {
1511  if ( col_counter > ilx-1 )
1512  {
1513  col_counter-- ;
1514  }
1515  if ( col_counter + z*ilx < 0 )
1516  {
1517  podata[col+row_index[slit]*imsize] = podata[0] ;
1518  }
1519  else
1520  {
1521  podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
1522  }
1523 
1524  col_counter++ ;
1525  }
1526  }
1527  cpl_imagelist_set(returnCube,o_img,z);
1528  }
1529  cpl_free (row_index) ;
1530  cpl_free (beginCol) ;
1531 
1532  return returnCube ;
1533 }
1560 cpl_imagelist *
1561 sinfo_new_make_3D_cube_dist ( cpl_image * calibImage,
1562  float firstCol,
1563  float * distances,
1564  float * shift )
1565 {
1566  cpl_imagelist * returnCube ;
1567  float di ;
1568  float diff, start ;
1569  int * row_index ;
1570  int slit ;
1571  int col, z ;
1572  int imsize ;
1573  int * beginCol ;
1574  int col_counter ;
1575  int ilx=0;
1576  int ily=0;
1577 
1578  float* podata=NULL;
1579  float* pidata=NULL;
1580  cpl_image* o_img;
1581 
1582  if ( NULL == calibImage )
1583  {
1584  sinfo_msg_error(" no resampled image given!\n") ;
1585  return NULL ;
1586  }
1587  ilx=cpl_image_get_size_x(calibImage);
1588  ily=cpl_image_get_size_y(calibImage);
1589  pidata=cpl_image_get_data_float(calibImage);
1590 
1591  if ( NULL == distances )
1592  {
1593  sinfo_msg_error("no distances array given from north_south_test()!") ;
1594  return NULL ;
1595  }
1596 
1597  if ( N_SLITLETS != 16 )
1598  {
1599  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1600  return NULL ;
1601  }
1602  imsize = ilx / N_SLITLETS ;
1603 
1604  /* allocate memory */
1605  if ( NULL == (row_index = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1606  {
1607  sinfo_msg_error ("cannot allocate memory \n" ) ;
1608  return NULL ;
1609  }
1610  if ( NULL == (beginCol = (int*) cpl_calloc(N_SLITLETS, sizeof(int)) ) )
1611  {
1612  sinfo_msg_error ("cannot allocate memory \n" ) ;
1613  cpl_free(row_index) ;
1614  return NULL ;
1615  }
1616  if ( NULL == (returnCube = cpl_imagelist_new()) )
1617  {
1618  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1619  cpl_free(row_index) ;
1620  cpl_free(beginCol) ;
1621  return NULL ;
1622  }
1623 
1624  di = 0. ;
1625  /* determine the absolute beginning of the slitlets and the distances
1626  inside the image*/
1627  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1628  /* go through the slitlets of each row of the resampled image */
1629  {
1630 
1631  /* --------------------------------------------------------------
1632  * sort the slitlets in the right 3D specific way
1633  * the row_index describes the row index of the current slitlet
1634  * in the resulting cube images.
1635  */
1636  row_index[slit] = slit ;
1637 
1638  /* determine the integer column on which the slitlet starts */
1639  if ( slit == 0 )
1640  {
1641  start = firstCol ;
1642  }
1643  else
1644  {
1645  di += distances[slit-1] ;
1646  start = firstCol + di ;
1647  }
1648  beginCol[slit] = sinfo_new_nint(start) ;
1649 
1650  /* determine the error of using integer pixels,
1651  `its always smaller than 1 */
1652  diff = start - (float)beginCol[slit] ;
1653 
1654  /*----------------------------------------------------------------
1655  * determine the output shift values by which the rows are finally
1656  shifted, consider the integer pixel errors and resort shift array
1657  to get the row index
1658  */
1659  shift[row_index[slit]] = diff ;
1660  }
1661 
1662  /* now build the data cube out of the resampled image */
1663  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1664  {
1665  o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1666  podata=cpl_image_get_data_float(o_img);
1667  for ( slit = 0 ; slit < N_SLITLETS ; slit++ )
1668  {
1669  col_counter = beginCol[slit] ;
1670  /* each slitlet is centered on the final image row */
1671  for ( col = 0 ; col < imsize ; col++ )
1672  {
1673  if ( col_counter > ilx-1 )
1674  {
1675  col_counter-- ;
1676  }
1677  podata[col+row_index[slit]*imsize]=pidata[col_counter+z*ilx];
1678  col_counter++ ;
1679  }
1680  }
1681  cpl_imagelist_set(returnCube,o_img,z);
1682  }
1683  cpl_free (row_index) ;
1684  cpl_free (beginCol) ;
1685 
1686  return returnCube ;
1687 }
1688 
1706 cpl_imagelist *
1707 sinfo_new_make_3D_cube ( cpl_image * calibImage,
1708  int * kpixshift,
1709  int kpixfirst )
1710 {
1711  cpl_imagelist * returnCube ;
1712  int imsize, kslit, kpix ;
1713  int z, col, recol ;
1714  int ilx=0;
1715  int ily=0;
1716 
1717  float* podata=NULL;
1718  float* pidata=NULL;
1719  cpl_image* o_img;
1720 
1721  if ( NULL == calibImage )
1722  {
1723  sinfo_msg_error("no resampled image given!\n") ;
1724  return NULL ;
1725  }
1726  ilx=cpl_image_get_size_x(calibImage);
1727  ily=cpl_image_get_size_y(calibImage);
1728  pidata=cpl_image_get_data_float(calibImage);
1729 
1730  if ( NULL == kpixshift )
1731  {
1732  sinfo_msg_error("no shift array given!/n") ;
1733  return NULL ;
1734  }
1735 
1736  if ( kpixfirst < 0 )
1737  {
1738  sinfo_msg_error("wrong first valid pixel given!/n") ;
1739  return NULL ;
1740  }
1741 
1742  if ( N_SLITLETS != 16 )
1743  {
1744  sinfo_msg_error ("wrong number of slitlets given \n" ) ;
1745  return NULL ;
1746  }
1747  imsize = ilx / N_SLITLETS ;
1748 
1749  if ( NULL == (returnCube = cpl_imagelist_new()) )
1750  {
1751  sinfo_msg_error ("cannot allocate new cube \n" ) ;
1752  return NULL ;
1753  }
1754 
1755  /* now build the data cube out of the resampled image */
1756  for ( z = 0 ; z < ily ; z++ ) /* go through the z-axis */
1757  {
1758  o_img=cpl_image_new(imsize,N_SLITLETS,CPL_TYPE_FLOAT);
1759  podata=cpl_image_get_data_float(o_img);
1760  kpix = 0 ;
1761  kslit = 0 ;
1762  recol = -1 ;
1763  for ( col = 0 ; col < ilx ; col++ ) /* go through the image columns */
1764  {
1765  if ( col % imsize == 0 )
1766  {
1767  recol = 0 ;
1768  kslit = col/imsize ;
1769  kpix = kpixfirst + kpixshift[kslit] ;
1770  }
1771 
1772  /* fill each cube plane with one image row */
1773  podata[recol+kslit*imsize] = pidata[col+kpix+z*ilx] ;
1774  recol++ ;
1775  if ( recol > imsize )
1776  {
1777  sinfo_msg_error("wrong column of reconstructed image, i"
1778  "shouldn't happen!\n") ;
1779  cpl_imagelist_delete(returnCube) ;
1780  return NULL ;
1781  }
1782  }
1783  cpl_imagelist_set(returnCube,o_img,z);
1784  }
1785  return returnCube ;
1786 }
1787 
1800 cpl_imagelist *
1801 sinfo_new_determine_mask_cube ( cpl_imagelist * sourceMaskCube,
1802  float lowLimit,
1803  float highLimit )
1804 {
1805  cpl_imagelist * retCube ;
1806  int z, n ;
1807  int ilx=0;
1808  int ily=0;
1809  int inp=0;
1810  int olx=0;
1811  int oly=0;
1812  int onp=0;
1813  float* podata=NULL;
1814  cpl_image* o_img;
1815 
1816  if ( sourceMaskCube == NULL )
1817  {
1818  sinfo_msg_error("no cube given!\n") ;
1819  return NULL ;
1820  }
1821  ilx=cpl_image_get_size_x(cpl_imagelist_get(sourceMaskCube,0));
1822  ily=cpl_image_get_size_y(cpl_imagelist_get(sourceMaskCube,0));
1823  inp=cpl_imagelist_get_size(sourceMaskCube);
1824 
1825 
1826  if ( lowLimit > 0. )
1827  {
1828  sinfo_msg_error("lowLimit wrong!\n") ;
1829  return NULL ;
1830  }
1831  if ( highLimit >= 1. || highLimit < 0. )
1832  {
1833  sinfo_msg_error("highLimit wrong!\n") ;
1834  return NULL ;
1835  }
1836 
1837  retCube = cpl_imagelist_duplicate (sourceMaskCube) ;
1838  onp=inp;
1839  olx=ilx;
1840  oly=ily;
1841 
1842  for ( z = 0 ; z < onp ; z++ )
1843  {
1844  o_img=cpl_imagelist_get(retCube,0);
1845  podata=cpl_image_get_data_float(o_img);
1846  for ( n = 0 ; n < (int) olx*oly; n++ )
1847  {
1848  if ( podata[n] == 0. )
1849  {
1850  continue ;
1851  }
1852  if ( podata[n] == 1. )
1853  {
1854  continue ;
1855  }
1856  if ( podata[n] >= lowLimit &&
1857  podata[n] <= highLimit )
1858  {
1859  podata[n] = 0. ;
1860  }
1861  else
1862  {
1863  podata[n] = 1. ;
1864  }
1865  }
1866  }
1867  return retCube ;
1868 }
1907 cpl_imagelist *
1908 sinfo_new_interpol_cube ( cpl_imagelist * sourceCube,
1909  cpl_imagelist * maskCube,
1910  int n_neighbors, /* 7 */
1911  int max_radius ) /* 5 */
1912 {
1913  cpl_imagelist * returnCube ;
1914  float** spec=NULL ;
1915  float* spec1=NULL ;
1916  int n_im, n_bad, n_bad1, n_bad2 ;
1917  int n_planes, specn, nspec1 ;
1918  int i, m, n, z, ni, kk, p ;
1919  int dis, dismin, dismax ;
1920  int agreed ;
1921  int xcordi, ycordi, xcordm, ycordm ;
1922 
1923 
1924 
1925  int ilx=0;
1926  int ily=0;
1927  int inp=0;
1928 
1929  float* pidata=NULL;
1930  float* pmdata=NULL;
1931  float* podata=NULL;
1932  cpl_image* i_img=NULL;
1933  cpl_image* m_img=NULL;
1934  cpl_image* o_img=NULL;
1935 
1936  if ( NULL == sourceCube )
1937  {
1938  sinfo_msg_error(" no source cube given!\n") ;
1939  return NULL ;
1940  }
1941 
1942 
1943  ilx=cpl_image_get_size_x(cpl_imagelist_get(sourceCube,0));
1944  ily=cpl_image_get_size_y(cpl_imagelist_get(sourceCube,0));
1945  inp=cpl_imagelist_get_size(sourceCube);
1946 
1947  if ( NULL == maskCube )
1948  {
1949  sinfo_msg_error("no bad pixel mask cube given!\n") ;
1950  return NULL ;
1951  }
1952 
1953  if ( n_neighbors <= 0 )
1954  {
1955  sinfo_msg_error("wrong number of neighbors in the spectral "
1956  "direction given!") ;
1957  return NULL ;
1958  }
1959 
1960  if ( max_radius <= 0 )
1961  {
1962  sinfo_msg_error("wrong maximal radius for interpolation inside "
1963  "an image plane given!") ;
1964  return NULL ;
1965  }
1966 
1967  returnCube = cpl_imagelist_duplicate(sourceCube) ;
1968 
1969  n_im = ilx * ily ;
1970  n_planes = inp ;
1971 
1972  spec1=cpl_calloc(300,sizeof(float)) ;
1973  spec=sinfo_new_2Dfloatarray(100,2*n_neighbors+1) ;
1974 
1975  /* loop over the image planes and look for bad pixels and correct them */
1976  for ( z = 0 ; z < n_planes ; z++ ) /* go through image planes */
1977  {
1978  m_img=cpl_imagelist_get(maskCube,z);
1979  pmdata=cpl_image_get_data_float(m_img);
1980  o_img=cpl_imagelist_get(returnCube,z);
1981  podata=cpl_image_get_data_float(o_img);
1982 
1983  /*-------------------------------------------------------------------
1984  * determine n, the length of one wing in one spectrum with which the
1985  * bad pixel will be interpolated. The length of one wing is
1986  n_neighbors but less at the edges of the cube.
1987  */
1988  if ( z < n_neighbors )
1989  {
1990  n = z ;
1991  }
1992  else if ( n_planes - z <= n_neighbors)
1993  {
1994  n = n_planes - z -1 ;
1995  }
1996  else
1997  {
1998  n = n_neighbors ;
1999  }
2000 
2001  for ( i = 0 ; i < n_im ; i ++ ) /* go through one image */
2002  {
2003  /* continue if the pixel is a good one */
2004  if ( pmdata[i] != 0. )
2005  {
2006  continue ;
2007  }
2008 
2009  /*-------------------------------------------------------------
2010  * exclude pixels with too many bad neighbors in the spectrum.
2011  * exit if: too few good pixels in the neighboring spectrum or
2012  * good pixels are only on one side of the spectrum.
2013  */
2014  n_bad = 0 ;
2015  n_bad1 = 0 ;
2016  n_bad2 = 0 ;
2017  /* go through the neighbor spectral pixels */
2018  for ( ni = z-n ; ni <= z+n ; ni++ )
2019  {
2020  if ( pmdata[i] == 0. )
2021  {
2022  n_bad++ ;
2023  /* count bad pixels on either spectral side of
2024  the bad pixel to be interpolated */
2025  if ( ni < z )
2026  {
2027  n_bad1++ ;
2028  }
2029  if ( ni > z )
2030  {
2031  n_bad2++ ;
2032  }
2033  }
2034  }
2035 
2036  /*---------------------------------------------------------------
2037  * now the criteria are checked which the neighborhood in the
2038  spectral dimension has to match if the pixel is interpolatable.
2039  * The total number of the good pixel in the spectrum must be more
2040  than 3 and there must be at least one good pixel on either side
2041  of the central pixel.
2042  */
2043  if ( (2*n+1 - n_bad) < 3 || (n - n_bad1) < 1 || (n - n_bad2) < 1 )
2044  {
2045  continue ;
2046  }
2047 
2048  /* read the master spectrum into the first row of the array spec */
2049  kk = 0 ;
2050  for ( ni = z-n ; ni <= z+n ; ni++ )
2051  {
2052  i_img=cpl_imagelist_get(sourceCube,ni);
2053  pidata=cpl_image_get_data_float(i_img);
2054  spec[1][kk] = pmdata[i] != 0. ? pidata[i] : ZERO ;
2055  kk++ ; /* length of spectrum */
2056  }
2057 
2058  /* look for appropriate neighbors in the x-y neighborhood */
2059  agreed = 1 ; /* loop guard */
2060  specn = 2 ; /* number of spectra in spec.
2061  First is master spectrum */
2062  dismin = 0 ; /* x+y minimal distance to bad pixel */
2063  dismax = 1 ; /* x+y maximal distance to bad pixel */
2064  do
2065  {
2066  for ( m = 0 ; m < n_im ; m++ )
2067  {
2068  if ( pmdata[m] == 0. )
2069  {
2070  continue ;
2071  }
2072 
2073  /* --------------------------------------------------------
2074  * determine the x and y coordinates of the bad pixel (i)
2075  * and the pixels used to interpolate (m)
2076  */
2077  xcordi = i % ilx ;
2078  xcordm = m % ilx ;
2079  ycordi = i / ilx ;
2080  ycordm = m / ilx ;
2081  /*-----------------------------------------------------
2082  * check the distance: take only close pixels
2083  * extension 'i' is coordinate of the bad pixel to be
2084  interpolated
2085  */
2086  dis = abs(xcordi-xcordm) + abs(ycordi-ycordm) ;
2087  if ( dis <= dismin || dis > dismax )
2088  {
2089  continue ;
2090  }
2091  /*--------------------------------------------------------
2092  * check on number of bad pixels in the spectrum of a
2093  * neighbor pixel; reject it if it contains less than 2
2094  * usable pixel pairs. a bit more explanation:
2095  * let this be a 15 pixel spectrum with the pixel to be
2096  * interpolated denoted by '0' and other bad pixels marked
2097  * with 'b'. Good pixels are marked with '1'. Below a
2098  * neighbor spectrum is drawn containing bad pixels as
2099  * well. The third line shows the position of the usable
2100  * pixel pairs, spectral
2101  * positions, where both spectra have valid pixels.
2102  *
2103  * 1 1 1 b b 1 1 0 b 1 b b 1 b b
2104  * b 1 1 1 b b 1 1 1 1 1 1 b b 1
2105  * ^ ^ ^ ^ 4 good pixel pairs
2106  */
2107 
2108  n_bad = 0 ;
2109  for ( ni = z-n ; ni <= z+n ; ni++ )
2110  {
2111  if ( pmdata[i] == 0. || pmdata[m] == 0. )
2112  {
2113  n_bad++ ;
2114  }
2115  }
2116  if ( n_bad > 2*n-1 )
2117  /* we need at least 2 usable pixel pairs */
2118  {
2119  continue ;
2120  }
2121 
2122  /* transfer the spectrum to the next position
2123  of array spec */
2124  kk = 0 ;
2125  for ( ni = z-n ; ni <= z+n ; ni++ )
2126  {
2127  i_img=cpl_imagelist_get(sourceCube,ni);
2128  pidata=cpl_image_get_data_float(i_img);
2129  spec[specn][kk] = pmdata[m] != 0. ? pidata[m] : ZERO ;
2130  kk++ ;
2131  }
2132  specn++ ;
2133  if ( specn > 10 ) /* if we have 9 neighbors then break */
2134  {
2135  agreed = 0 ;
2136  break ;
2137  }
2138  }
2139  /* if no break, increase search radius and continue */
2140  dismin++ ;
2141  dismax++ ;
2142  /* if search radius is too big, exit with fewer
2143  good neighbors */
2144  if ( dismax > max_radius )
2145  {
2146  agreed = 0 ;
2147  }
2148  } while(agreed) ;
2149 
2150  specn-- ;
2151  dismax -= 2 ;
2152  /* TODO: why compute dismax is later this is not used? */
2153  /* ---------------------------------------------------------------
2154  * Take the master spectrum with the bad pixel in the middle and
2155  divide it by each of the neighbor spectra and normalize the
2156  division with the value in the center position.
2157  */
2158  for ( kk = 0 ; kk < 2*n+1 ; kk++ )
2159  {
2160  if ( kk == n ) /* do not divide the master bad pixel */
2161  {
2162  continue ;
2163  }
2164 
2165  /* do not divide bad pixels in the master spectrum */
2166  if ( isnan(spec[1][kk]) )
2167  {
2168  for ( p = 2 ; p <= specn ; p++ )
2169  {
2170  spec[p][kk] = ZERO ;
2171  }
2172  }
2173  else /* all is well, now divide */
2174  {
2175  for ( p = 2 ; p <= specn ; p++ )
2176  {
2177  if ( !isnan(spec[p][kk]) && spec[p][kk] != 0. &&
2178  !isnan(spec[p][n]) )
2179  {
2180  spec[p][kk] = spec[1][kk] /
2181  spec[p][kk] * spec[p][n] ;
2182  }
2183  else
2184  {
2185  spec[p][kk] = ZERO ;
2186  }
2187  }
2188  }
2189  }
2190 
2191  /*-----------------------------------------------------------------
2192  * determine the sinfo_median of all values. With 9 good neighbors
2193  * and at least 2 good values per neighbor we have between 18 and
2194  * 9*14 values for the statistics. If there are not enough good
2195  * neighbors available, only continue if we have collected at
2196  * least 18 values.
2197  */
2198  nspec1 = 0 ;
2199  /* collect the good values in the array spec1 */
2200  for ( p = 2 ; p <= specn ; p++ )
2201  {
2202  for ( kk = 0 ; kk < 2*n+1 ; kk++ )
2203  {
2204  if ( !isnan(spec[p][kk]) && kk != n )
2205  {
2206  spec1[nspec1] = spec[p][kk] ;
2207  nspec1++ ;
2208  }
2209  }
2210  }
2211 
2212  /* now test if we have at least 18 values */
2213  if ( nspec1 < 18 )
2214  {
2215  continue ;
2216  }
2217 
2218  /* interpolate the bad pixel by the sinfo_median of spec1 */
2219  podata[i] = sinfo_new_median(spec1, nspec1) ;
2220  pmdata[i] = 1 ;
2221  }
2222  }
2223  sinfo_new_destroy_2Dfloatarray(&spec,2*n_neighbors+1) ;
2224  cpl_free(spec1);
2225  return returnCube ;
2226 }
2247 cpl_imagelist *
2248 sinfo_new_fine_tune_cube( cpl_imagelist * cube,
2249  float * correct_diff_dist,
2250  int n_order )
2251 {
2252  cpl_imagelist * returnCube ;
2253  float* row_data=NULL ;
2254  float* corrected_row_data=NULL ;
2255  float* xnum=NULL ;
2256  float sum, new_sum ;
2257  float eval/*, dy*/ ;
2258  float * imageptr ;
2259  int row, col ;
2260  int i, z ;
2261  int imsize, n_points ;
2262  int firstpos ;
2263  int flag;
2264  int ilx=0;
2265  int ily=0;
2266  int inp=0;
2267 
2268  float* pidata=NULL;
2269  float* podata=NULL;
2270  cpl_image* i_img=NULL;
2271  cpl_image* o_img=NULL;
2272 
2273 
2274  if ( NULL == cube )
2275  {
2276  sinfo_msg_error("no input cube given!\n") ;
2277  return NULL ;
2278  }
2279  ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
2280  ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
2281  inp=cpl_imagelist_get_size(cube);
2282 
2283  if ( NULL == correct_diff_dist )
2284  {
2285  sinfo_msg_error("no distances array from ns_test given!n") ;
2286  return NULL ;
2287  }
2288 
2289  if ( n_order <= 0 )
2290  {
2291  sinfo_msg_error("wrong order of interpolation polynom given!") ;
2292  returnCube = cpl_imagelist_duplicate(cube);
2293  return returnCube ;
2294  }
2295 
2296  returnCube = cpl_imagelist_duplicate(cube);
2297 
2298  imsize = ily ;
2299  if ( imsize != N_SLITLETS )
2300  {
2301  sinfo_msg_error ("wrong image size\n" ) ;
2302  return NULL ;
2303  }
2304 
2305  n_points = n_order + 1 ;
2306  if ( n_points % 2 == 0 )
2307  {
2308  firstpos = (int)(n_points/2) - 1 ;
2309  }
2310  else
2311  {
2312  firstpos = (int)(n_points/2) ;
2313  }
2314  xnum=cpl_calloc(n_order+1,sizeof(float)) ;
2315 
2316  for ( i = 0 ; i < n_points ; i++ )
2317  {
2318  xnum[i] = i ;
2319  }
2320 
2321  row_data=cpl_calloc(ilx,sizeof(float)) ;
2322  corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
2323 
2324  for ( z = 0 ; z < inp ; z++ )
2325  {
2326  i_img=cpl_imagelist_get(cube,z);
2327  pidata=cpl_image_get_data_float(i_img);
2328  o_img=cpl_imagelist_get(returnCube,z);
2329  podata=cpl_image_get_data_float(o_img);
2330 
2331 
2332  for ( row = 0 ; row < imsize ; row++ )
2333  {
2334  for ( col = 0 ; col < ilx ; col++ )
2335  {
2336  corrected_row_data[col] = 0. ;
2337  }
2338  sum = 0. ;
2339  for ( col = 0 ; col < ilx ; col++ )
2340  {
2341  row_data[col] = pidata[col+row*ilx] ;
2342  if ( isnan(row_data[col]) )
2343  {
2344  row_data[col] = 0. ;
2345  for ( i = col - firstpos ;
2346  i < col -firstpos+n_points ; i++ )
2347  {
2348  if ( i < 0 ) continue ;
2349  if ( i >= ilx) continue ;
2350  corrected_row_data[i] = ZERO ;
2351  }
2352  }
2353  if ( col != 0 && col != ilx - 1 )
2354  {
2355  sum += row_data[col] ;
2356  }
2357  }
2358 
2359 
2360  new_sum = 0. ;
2361  for ( col = 0 ; col < ilx ; col++ )
2362  {
2363 
2364  if ( isnan(corrected_row_data[col]) )
2365  {
2366  continue ;
2367  }
2368  if ( col - firstpos < 0 )
2369  {
2370  imageptr = &row_data[0] ;
2371  eval = correct_diff_dist[row] + col ;
2372  }
2373  else if ( col - firstpos + n_points >= ilx )
2374  {
2375  imageptr = &row_data[ilx - n_points] ;
2376  eval = correct_diff_dist[row] + col + n_points - ilx ;
2377  }
2378  else
2379  {
2380  imageptr = &row_data[col-firstpos] ;
2381  eval = correct_diff_dist[row] + firstpos ;
2382  }
2383 
2384 
2385  flag = 0;
2386  corrected_row_data[col]=sinfo_new_nev_ille(xnum, imageptr,
2387  n_order, eval, &flag);
2388 
2389 
2390  if ( col != 0 && col != ilx - 1 )
2391  {
2392  new_sum += corrected_row_data[col] ;
2393  }
2394  }
2395  for ( col = 0 ; col < ilx ; col++ )
2396  {
2397 
2398  if ( col == 0 )
2399  {
2400  podata[col+row*ilx] = ZERO ;
2401  }
2402  else if ( col == ilx - 1 )
2403  {
2404  podata[col+row*ilx] = ZERO ;
2405  }
2406  else
2407  {
2408  if ( isnan(corrected_row_data[col]) )
2409  {
2410  podata[col+row*ilx] = ZERO ;
2411  }
2412  else
2413  {
2414  if ( new_sum == 0. ) new_sum = 1. ;
2415 
2416  podata[col+row*ilx] = corrected_row_data[col] ;
2417  }
2418  }
2419  }
2420  }
2421  }
2422 
2423  cpl_free(xnum) ;
2424  cpl_free(row_data) ;
2425  cpl_free(corrected_row_data) ;
2426 
2427  return returnCube ;
2428 }
2429 
2449 cpl_imagelist *
2450 sinfo_new_fine_tune_cube_by_FFT( cpl_imagelist * cube,
2451  float * correct_diff_dist )
2452 {
2453  cpl_imagelist * returnCube ;
2454 
2455  float* row_data=NULL ;
2456  dcomplex* data=NULL ;
2457  dcomplex* corrected_data=NULL ;
2458 
2459  unsigned nn[2];
2460  /*float corrected_row_data[cube->lx] ;*/
2461  float phi, pphi ;
2462  float coph, siph ;
2463  int row, col ;
2464  int i, z ;
2465  int imsize ;
2466  int blank_indicator ;
2467 
2468 
2469  int ilx=0;
2470  int ily=0;
2471  int inp=0;
2472 
2473  float* pidata=NULL;
2474  float* podata=NULL;
2475  cpl_image* i_img=NULL;
2476  cpl_image* o_img=NULL;
2477 
2478 
2479 
2480  if ( NULL == cube )
2481  {
2482  sinfo_msg_error(" no input cube given!\n") ;
2483  return NULL ;
2484  }
2485  ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
2486  ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
2487  inp=cpl_imagelist_get_size(cube);
2488 
2489  nn[1] = ilx ;
2490  if ( NULL == correct_diff_dist )
2491  {
2492  sinfo_msg_error("no distances array from ns_test given!") ;
2493  return NULL ;
2494  }
2495 
2496  returnCube = cpl_imagelist_duplicate( cube ) ;
2497 
2498  imsize = ily ;
2499  if ( imsize != N_SLITLETS )
2500  {
2501  sinfo_msg_error ("wrong image size\n" ) ;
2502  return NULL ;
2503  }
2504 
2505  data=cpl_calloc(ilx,sizeof(dcomplex)) ;
2506  corrected_data=cpl_calloc(ilx,sizeof(dcomplex)) ;
2507 
2508  row_data=cpl_calloc(ilx,sizeof(float)) ;
2509  /* loop over the image planes */
2510  for ( z = 0 ; z < inp ; z++ )
2511  {
2512  i_img=cpl_imagelist_get(cube,z);
2513  pidata=cpl_image_get_data_float(i_img);
2514  o_img=cpl_imagelist_get(returnCube,z);
2515  podata=cpl_image_get_data_float(o_img);
2516  /* consider one row at a time */
2517  for ( row = 0 ; row < imsize ; row++ )
2518  {
2519  blank_indicator = 1 ;
2520  for ( col = 0 ; col < ilx ; col++ )
2521  {
2522  /* transfer the row data to a double sized array */
2523  row_data[col] = pidata[col+row*ilx] ;
2524  data[col].x = row_data[col] ;
2525  data[col].y = 0. ;
2526  /* if row contains a blank pixel proceed */
2527  if ( isnan(row_data[col]) )
2528  {
2529  blank_indicator = 0 ;
2530  }
2531  }
2532 
2533  /* if row contains a blank don't apply FFT but proceed */
2534  if ( blank_indicator == 0 )
2535  {
2536  for ( col = 0 ; col < ilx ; col++ )
2537  {
2538  podata[col+row*ilx] = ZERO ;
2539  }
2540  continue ;
2541  }
2542 
2543  /* FFT algorithm of eclipse */
2544  sinfo_fftn( data, nn, 1, 1 ) ;
2545 
2546  /* calculate the corrected phase shift for each frequency */
2547  phi = 2*PI_NUMB/(float)ilx * correct_diff_dist[row] ;
2548  for ( i = 0 ; i < ilx ; i++ )
2549  {
2550  /* positive frequencies */
2551  if ( i <= ilx/2 )
2552  {
2553  /* phase shift */
2554  pphi = phi * (float)(i) ;
2555  /* Euler factor */
2556  coph = cos ( pphi ) ;
2557  siph = sin ( pphi ) ;
2558  }
2559  else /* negative frequencies */
2560  {
2561  /* phase shift */
2562  pphi = phi * (float)(i - ilx/2) ;
2563  /* Euler factor */
2564  coph = cos ( pphi ) ;
2565  siph = sin ( pphi ) ;
2566  }
2567 
2568  /* ------------------------------------------------------------
2569  * now calculate the shift in the pixel space by multiplying
2570  * the fourier transform by the Euler factor of the phase shift
2571  * and inverse fourier transforming.
2572  * used Fourier pair: h(x-x0) <==> H(k)*exp(2*pi*i*k*x0)
2573  */
2574  /* calculate real part */
2575  corrected_data[i].x = data[i].x * coph - data[i].y * siph ;
2576  /* calculate imaginary part */
2577  corrected_data[i].y = data[i].x * siph + data[i].y * coph ;
2578  }
2579 
2580  /* transform back: inverse FFT */
2581  sinfo_fftn( corrected_data, nn, 1, -1 ) ;
2582 
2583  /* normalize */
2584  for ( i = 0 ; i < ilx ; i++ )
2585  {
2586  corrected_data[i].x /= ilx ;
2587  corrected_data[i].y /= ilx ;
2588  }
2589 
2590  /* now transfer row to output, leave the left-most
2591  and right-most pixel column */
2592  for ( col = 0 ; col < ilx ; col++ )
2593  {
2594  if ( col == 0 )
2595  {
2596  podata[col+row*ilx] = ZERO ;
2597  }
2598  else if ( col == ilx - 1 )
2599  {
2600  podata[col+row*ilx] = ZERO ;
2601  }
2602  else
2603  {
2604  podata[col+row*ilx] = corrected_data[col].x ;
2605  }
2606  }
2607  }
2608  }
2609 
2610  cpl_free(data) ;
2611  cpl_free(corrected_data) ;
2612 
2613 
2614  cpl_free(row_data);
2615  return returnCube ;
2616 }
2644 cpl_imagelist * sinfo_new_fine_tune_cube_by_spline ( cpl_imagelist * cube,
2645  float * correct_diff_dist )
2646 {
2647  cpl_imagelist * returnCube ;
2648 
2649  float* row_data=NULL ;
2650  float* corrected_row_data=NULL ;
2651  float* xnum=NULL ;
2652  float* eval=NULL ;
2653 
2654  float sum, new_sum ;
2655  int row, col ;
2656  int i, z ;
2657  int imsize ;
2658  int ilx=0;
2659  int ily=0;
2660  int inp=0;
2661 
2662  float* pidata=NULL;
2663  float* podata=NULL;
2664  cpl_image* i_img=NULL;
2665  cpl_image* o_img=NULL;
2666 
2667 
2668  if ( NULL == cube )
2669  {
2670  sinfo_msg_error("no input cube given!\n") ;
2671  return NULL ;
2672  }
2673  ilx=cpl_image_get_size_x(cpl_imagelist_get(cube,0));
2674  ily=cpl_image_get_size_y(cpl_imagelist_get(cube,0));
2675  inp=cpl_imagelist_get_size(cube);
2676 
2677  if ( NULL == correct_diff_dist )
2678  {
2679  sinfo_msg_error("no distances array from ns_test given!/n") ;
2680  return NULL ;
2681  }
2682 
2683  imsize = ily ;
2684  if ( imsize != N_SLITLETS )
2685  {
2686  sinfo_msg_error ("wrong image size\n" ) ;
2687  return NULL ;
2688  }
2689 
2690  returnCube = cpl_imagelist_duplicate( cube ) ;
2691 
2692  row_data=cpl_calloc(ilx,sizeof(float)) ;
2693  corrected_row_data=cpl_calloc(ilx,sizeof(float)) ;
2694  xnum=cpl_calloc(ilx,sizeof(float)) ;
2695  eval=cpl_calloc(ilx,sizeof(float)) ;
2696 
2697  /* fill the xa[] array for a polynomial interpolation */
2698  for ( i = 0 ; i < ilx ; i++ )
2699  {
2700  xnum[i] = i ;
2701  }
2702 
2703  /* loop over the image planes */
2704  for ( z = 0 ; z < inp ; z++ )
2705  {
2706  i_img=cpl_imagelist_get(cube,z);
2707  pidata=cpl_image_get_data_float(i_img);
2708  o_img=cpl_imagelist_get(returnCube,z);
2709  podata=cpl_image_get_data_float(o_img);
2710  /* consider 1 row at a time */
2711  for ( row = 0 ; row < imsize ; row++ )
2712  {
2713  for ( col = 0 ; col < ilx ; col++ )
2714  {
2715  corrected_row_data[col] = 0. ;
2716  }
2717  sum = 0. ; /* initialize flux for later rescaling */
2718  /* go through the columns and compute the flux for each
2719  row (leave the sinfo_edge points) */
2720  for ( col = 0 ; col < ilx ; col++ )
2721  {
2722  eval[col] = correct_diff_dist[row] + (float)col ;
2723  row_data[col] = pidata[col+row*ilx] ;
2724  if (col != 0 && col != ilx - 1 && !isnan(row_data[col]) )
2725  {
2726  sum += row_data[col] ;
2727  }
2728  if (isnan(row_data[col]) )
2729  {
2730  for ( i = col -1 ; i <= col+1 ; i++ )
2731  {
2732  if ( i < 0 ) continue ;
2733  if ( i >= ilx ) continue ;
2734  corrected_row_data[i] = ZERO ;
2735  }
2736  row_data[col] = 0. ;
2737  }
2738  }
2739 
2740 
2741  /* ---------------------------------------------------------------
2742  * now we do the cubic spline interpolation to achieve the
2743  fractional (see eclipse).
2744  */
2745  if ( -1 == sinfo_function1d_natural_spline(xnum,row_data, ilx,
2746  eval,corrected_row_data,
2747  ilx ) )
2748  {
2749  sinfo_msg_error("error in spline interpolation\n") ;
2750  cpl_imagelist_delete(returnCube) ;
2751  return NULL ;
2752  }
2753 
2754  new_sum = 0. ;
2755  for ( col = 0 ; col < ilx ; col++ )
2756  {
2757  if (isnan(corrected_row_data[col])) continue ;
2758  /* don't take the sinfo_edge points to calculate
2759  the scaling factor */
2760  if ( col != 0 && col != ilx - 1 )
2761  {
2762  new_sum += corrected_row_data[col] ;
2763  }
2764  }
2765  for ( col = 0 ; col < ilx ; col++ )
2766  {
2767  /* ----------------------------------------------------------
2768  * rescale the row data and fill the returned cube,
2769  * leave the left-most and right-most
2770  * pixel column
2771  */
2772  if ( col == 0 )
2773  {
2774  podata[col+row*ilx] = ZERO ;
2775  }
2776  else if ( col == ilx - 1 )
2777  {
2778  podata[col+row*ilx] = ZERO ;
2779  }
2780  else
2781  {
2782  if ( isnan(corrected_row_data[col]) )
2783  {
2784  podata[col+row*ilx] = ZERO ;
2785  }
2786  else
2787  {
2788  if (new_sum == 0.) new_sum = 1. ;
2789  /* rescaling is commented out because it delivers
2790  wrong results
2791  in case of appearance of blanks or bad pixels */
2792  /* corrected_row_data[col] *= sum / new_sum ; */
2793  podata[col+row*ilx] = corrected_row_data[col] ;
2794  }
2795  }
2796  }
2797  }
2798  }
2799 
2800  cpl_free(row_data) ;
2801  cpl_free(corrected_row_data) ;
2802  cpl_free(xnum) ;
2803  cpl_free(eval) ;
2804 
2805  return returnCube ;
2806 }
2807 
2829 float *
2830 sinfo_new_calibrate_ns_test( cpl_image * ns_image,
2831  int n_slitlets,
2832  int halfWidth,
2833  float fwhm,
2834  float minDiff,
2835  float estimated_dist,
2836  float devtol,
2837  int bottom,
2838  int top )
2839 {
2840  int i, j, k, m, row, col, n, ni, na ;
2841  int position, counter, iters ;
2842  int xdim, ndat, its, numpar ;
2843  float sum, mean, maxval ;
2844  float tol, lab ;
2845  float * distances ;
2846  float * ret_distances ;
2847 
2848  float * xdat, * wdat ;
2849  int * mpar ;
2850 
2851  pixelvalue* row_buf=NULL ;
2852  float** distances_buf=NULL ;
2853  float* x_position=NULL ;
2854  int* found=NULL;
2855  int* found_clean=NULL ;
2856  int* found_cleanit=NULL ;
2857 
2858  Vector * line ;
2859  FitParams ** par ;
2860  int foundit, begin, end ;
2861  int zeroindicator ;
2862  int row_index ;
2863 
2864  int ilx=0;
2865  int ily=0;
2866  float* pidata=NULL;
2867 
2868  if ( ns_image == NULL )
2869  {
2870  sinfo_msg_error("sorry, no image given\n") ;
2871  return NULL ;
2872  }
2873  if ( n_slitlets < 1 )
2874  {
2875  sinfo_msg_error("wrong number of slitlets given\n") ;
2876  return NULL ;
2877  }
2878  if ( halfWidth < 0 || halfWidth >= estimated_dist )
2879  {
2880  sinfo_msg_error("wrong half width given\n") ;
2881  return NULL ;
2882  }
2883  if ( fwhm <= 0. )
2884  {
2885  sinfo_msg_error("wrong fwhm given\n") ;
2886  return NULL ;
2887  }
2888  if ( minDiff < 1. )
2889  {
2890  sinfo_msg_error("wrong minDiff given\n") ;
2891  return NULL ;
2892  }
2893 
2894  /* allocate memory for output array */
2895  if (NULL==(distances=(float *)cpl_calloc( n_slitlets , sizeof (float) )))
2896  {
2897  sinfo_msg_error("could not allocate memory\n") ;
2898  return NULL ;
2899  }
2900  /* allocate memory for output array */
2901  if (NULL == (ret_distances = (float *) cpl_calloc ( n_slitlets ,
2902  sizeof (float) )))
2903  {
2904  sinfo_msg_error("could not allocate memory\n") ;
2905  return NULL ;
2906  }
2907 
2908  ilx=cpl_image_get_size_x(ns_image);
2909  ily=cpl_image_get_size_y(ns_image);
2910  pidata=cpl_image_get_data_float(ns_image);
2911 
2912  row_buf=(pixelvalue*)cpl_calloc(ilx,sizeof(pixelvalue)) ;
2913  x_position=cpl_calloc(n_slitlets,sizeof(float)) ;
2914  found=cpl_calloc(3*n_slitlets,sizeof(int));
2915  found_clean=cpl_calloc(3*n_slitlets,sizeof(int)) ;
2916  found_cleanit=cpl_calloc(3*n_slitlets,sizeof(int)) ;
2917  distances_buf=sinfo_new_2Dfloatarray(ily,n_slitlets) ;
2918 
2919  /* go through the image rows */
2920  for ( row = 0 ; row < ily ; row++ )
2921  {
2922  zeroindicator = 0 ;
2923 
2924  /* initialize the distance buffer */
2925  for ( i = 0 ; i < n_slitlets ; i++ )
2926  {
2927  distances_buf[row][i] = ZERO ;
2928  }
2929 
2930  /* fill the row buffer array with image data */
2931  for ( col = 0 ; col < ilx ; col++ )
2932  {
2933  row_buf[col] = pidata[col + row*ilx] ;
2934  }
2935 
2936  /* determine the mean of the row data */
2937  sum = 0. ;
2938  n = 0 ;
2939  for ( i = 0 ; i < ilx ; i++ )
2940  {
2941  if ( isnan(row_buf[i]) )
2942  {
2943  continue ;
2944  }
2945  sum += row_buf[i] ;
2946  n++ ;
2947  }
2948  mean = sum / (float)n ;
2949 
2950  /* store the positions of image values greater than the mean */
2951  n = 0 ;
2952  for ( i = 0 ; i < ilx ; i++ )
2953  {
2954  if (isnan(row_buf[i]))
2955  {
2956  continue ;
2957  }
2958  if ( row_buf[i] > mean + ESTIMATE )
2959  {
2960  found[n] = i ;
2961  n++ ;
2962  }
2963  }
2964 
2965  if ( n < n_slitlets )
2966  {
2967  sinfo_msg_warning("t4 wrong number of intensity columns "
2968  "found in row: %d, found number: %d", row, n) ;
2969  continue ;
2970  }
2971  else
2972  {
2973  /* find the maximum value position around the found columns */
2974  na = 0 ;
2975  for ( i = 1 ; i < n ; i ++ )
2976  {
2977  if ( found[i] - found[i-1] < halfWidth )
2978  {
2979  begin = found[i] - halfWidth ;
2980  if ( begin < 0 )
2981  {
2982  begin = 0 ;
2983  }
2984  end = found[i] + halfWidth ;
2985  if ( end >= ilx )
2986  {
2987  end = ilx - 1 ;
2988  }
2989  /* find the maximum value inside the box around
2990  the found positions*/
2991  maxval = -FLT_MAX ;
2992  foundit = 0 ;
2993  for ( j = begin ; j <= end ; j++ )
2994  {
2995  /* do not consider boxes that contain bad pixels */
2996  if (isnan(row_buf[j]))
2997  {
2998  continue ;
2999  }
3000  if (row_buf[j] >= maxval )
3001  {
3002  maxval = row_buf[j] ;
3003  foundit = j ;
3004  }
3005  }
3006  if (maxval == -FLT_MAX)
3007  {
3008  continue ;
3009  }
3010  for ( k = 0 ; k < na ; k++ )
3011  {
3012  if ( found_cleanit[k] >= begin &&
3013  found_cleanit[k] < foundit )
3014  {
3015  na-- ;
3016  }
3017  }
3018  for ( k = 0 ; k < n ; k++ )
3019  {
3020  if ( found[k] == foundit)
3021  {
3022  if ( found_cleanit[na-1] != found[k] )
3023  {
3024  found_cleanit[na] = found[k] ;
3025  na++ ;
3026  }
3027  }
3028  }
3029  }
3030  else
3031  {
3032  if ( i == 1 )
3033  {
3034  found_cleanit[na] = found[0] ;
3035  na++ ;
3036  found_cleanit[na] = found[1] ;
3037  na++ ;
3038  }
3039  else
3040  {
3041  if ( found_cleanit[na-1] != found[i-1])
3042  {
3043  found_cleanit[na] = found[i-1] ;
3044  na++ ;
3045  }
3046  if ( found_cleanit[na-1] != found[i])
3047  {
3048  found_cleanit[na] = found[i] ;
3049  na++ ;
3050  }
3051  }
3052  }
3053  }
3054 
3055  /* determine only one pixel position for each slitlet intensity */
3056  j = 1 ;
3057  for ( i = 1 ; i < na ; i++ )
3058  {
3059  if ( (float)(found_cleanit[i] - found_cleanit[i-1]) <
3060  (estimated_dist - devtol) ||
3061  (float)(found_cleanit[i] - found_cleanit[i-1]) >
3062  (estimated_dist + devtol) )
3063  {
3064  continue ;
3065  }
3066  else
3067  {
3068  found_clean[j-1] = found_cleanit[i-1] ;
3069  found_clean[j] = found_cleanit[i] ;
3070  j++ ;
3071  }
3072  }
3073  }
3074  if ( j > n_slitlets )
3075  {
3076  /* check the distance again */
3077  ni = 1 ;
3078  for ( i = 1 ; i < j ; i++ )
3079  {
3080  if ( (float)(found_clean[i] - found_clean[i-1]) <
3081  (estimated_dist - devtol ) ||
3082  (float)(found_clean[i] - found_clean[i-1]) >
3083  (estimated_dist + devtol ) )
3084  {
3085  continue ;
3086  }
3087  else
3088  {
3089  found_clean[ni-1] = found_clean[i-1] ;
3090  found_clean[ni] = found_clean[i] ;
3091  ni++ ;
3092  }
3093  }
3094  if ( ni != n_slitlets )
3095  {
3096  sinfo_msg_warning("t5 wrong number of intensity columns "
3097  "found in row: %d, found number: %d",
3098  row,ni) ;
3099  continue ;
3100  }
3101  else
3102  {
3103  j = ni ;
3104  }
3105  }
3106  else if ( j < n_slitlets )
3107  {
3108  sinfo_msg_warning("t6 wrong number of intensity columns found "
3109  "in row: %d , found number: %d\n", row, j) ;
3110  continue ;
3111  }
3112  counter = 0 ;
3113  /* go through the found intensity pixels in one row */
3114  for ( i = 0 ; i < j ; i++ )
3115  {
3116  /* allocate memory for the array where the line is fitted in */
3117  if ( NULL == (line = sinfo_new_vector (2*halfWidth + 1)) )
3118  {
3119  sinfo_msg_error ("cannot allocate new Vector \n") ;
3120  cpl_free(distances) ;
3121  return NULL ;
3122  }
3123 
3124  /* allocate memory */
3125  xdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
3126  wdat = (float *) cpl_calloc( line -> n_elements, sizeof (float) ) ;
3127  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
3128  par = sinfo_new_fit_params(1) ;
3129 
3130  m = 0 ;
3131  for ( k = found_clean[i]-halfWidth ;
3132  k <= found_clean[i]+halfWidth ; k++ )
3133  {
3134  if ( k < 0 )
3135  {
3136  k = 0. ;
3137  }
3138  else if ( k >= ilx )
3139  {
3140  k = ilx - 1 ;
3141  }
3142  else if ( isnan(row_buf[k]) )
3143  {
3144  zeroindicator = 1 ;
3145  break ;
3146  }
3147  else
3148  {
3149  line -> data[m] = row_buf[k] ;
3150  m++ ;
3151  }
3152  }
3153  if ( zeroindicator == 1 )
3154  {
3155  sinfo_new_destroy_vector(line) ;
3156  cpl_free(xdat) ;
3157  cpl_free(wdat) ;
3158  cpl_free(mpar) ;
3159  sinfo_new_destroy_fit_params(&par) ;
3160  break ;
3161  }
3162 
3163  /*-----------------------------------------------------------------
3164  * go through the spectral sinfo_vector
3165  * determine the maximum pixel value in the spectral sinfo_vector
3166  */
3167  maxval = -FLT_MAX ;
3168  position = -INT32_MAX ;
3169  for ( k = 0 ; k < m ; k++ )
3170  {
3171  xdat[k] = k ;
3172  wdat[k] = 1.0 ;
3173  if ( line -> data[k] >= maxval )
3174  {
3175  maxval = line -> data[k] ;
3176  position = k ;
3177  }
3178  }
3179 
3180  /* set initial values for the fitting routine */
3181  xdim = XDIM ;
3182  ndat = line -> n_elements ;
3183  numpar = MAXPAR ;
3184  tol = TOL ;
3185  lab = LAB ;
3186  its = ITS ;
3187  (*par) -> fit_par[1] = fwhm ;
3188  (*par) -> fit_par[2] = (float) position ;
3189  (*par) -> fit_par[3] = (float) (line -> data[0] +
3190  line -> data[line->n_elements - 1]) / 2.0 ;
3191  (*par) -> fit_par[0] = maxval - ((*par) -> fit_par[3]) ;
3192 
3193 
3194  /* exclude negative peaks and low signal cases */
3195  if ( (*par) -> fit_par[0] < minDiff )
3196  {
3197  sinfo_msg_warning ("sorry, signal of line too low to fit "
3198  "in row: %d in slitlet %d\n", row, i) ;
3199  sinfo_new_destroy_vector(line) ;
3200  cpl_free(xdat) ;
3201  cpl_free(wdat) ;
3202  cpl_free(mpar) ;
3203  sinfo_new_destroy_fit_params(&par) ;
3204  continue ;
3205  }
3206 
3207  for ( k = 0 ; k < MAXPAR ; k++ )
3208  {
3209  (*par) -> derv_par[k] = 0.0 ;
3210  mpar[k] = 1 ;
3211  }
3212  /* finally, do the least square fit using a sinfo_gaussian */
3213  if ( 0 > ( iters = sinfo_new_lsqfit_c(xdat, &xdim,
3214  line -> data, wdat,
3215  &ndat, (*par) -> fit_par,
3216  (*par) -> derv_par, mpar,
3217  &numpar, &tol,
3218  &its, &lab )) )
3219  {
3220  /*
3221  cpl_msg_debug ("sinfo_calibrate_ns_test:",
3222  "sinfo_lsqfit_c: least squares fit failed,"
3223  " error no.: %d in row: %d in slitlet %d\n",
3224  iters, row, i) ;
3225  */
3226  sinfo_new_destroy_vector(line) ;
3227  cpl_free(xdat) ;
3228  cpl_free(wdat) ;
3229  cpl_free(mpar) ;
3230  sinfo_new_destroy_fit_params(&par) ;
3231  continue ;
3232  }
3233 
3234  /* check for negative fit results */
3235  if ( (*par) -> fit_par[0] <= 0. || (*par) -> fit_par[1] <= 0. ||
3236  (*par) -> fit_par[2] < 0. )
3237  {
3238  sinfo_msg_warning ("negative parameters as fit result, not "
3239  "used! in row %d in slitlet %d", row, i) ;
3240  sinfo_new_destroy_vector(line) ;
3241  cpl_free(xdat) ;
3242  cpl_free(wdat) ;
3243  cpl_free(mpar) ;
3244  sinfo_new_destroy_fit_params(&par) ;
3245  continue ;
3246  }
3247 
3248  /* correct the fitted position for the given row of the line
3249  in image coordinates */
3250  (*par) -> fit_par[2] = (float) (found_clean[i] - halfWidth) +
3251  (*par) -> fit_par[2] ;
3252  x_position[counter] = (*par) -> fit_par[2] ;
3253  counter ++ ;
3254 
3255  /* free memory */
3256  sinfo_new_destroy_fit_params(&par) ;
3257  sinfo_new_destroy_vector ( line ) ;
3258  cpl_free ( xdat ) ;
3259  cpl_free ( wdat ) ;
3260  cpl_free ( mpar ) ;
3261  }
3262  if (zeroindicator == 1)
3263  {
3264  sinfo_msg_debug ("bad pixel in fitting box in row: %d\n", row) ;
3265  continue ;
3266  }
3267 
3268  if ( counter != n_slitlets )
3269  {
3270  sinfo_msg_warning("wrong number of slitlets found "
3271  "in row: %d", row) ;
3272  continue ;
3273  }
3274  /* store the distances between the sources and the slitlet centers */
3275  for ( i = 0 ; i < n_slitlets ; i++ )
3276  {
3277  distances_buf[row][i] = x_position[i] - (15.5 + 32.*(float)i) ;
3278  }
3279  }
3280 
3281  /* ----------------------------------------------------------------
3282  * go through the rows again and take the mean of the distances,
3283  * throw away the runaways
3284  */
3285  for ( i = 0 ; i < n_slitlets ; i++ )
3286  {
3287  n = 0 ;
3288  sum = 0. ;
3289  for ( row = bottom ; row < top ; row++ )
3290  {
3291  if ( fabs( distances_buf[row][i] ) > devtol ||
3292  isnan(distances_buf[row][i]) )
3293  {
3294  /*
3295  sinfo_msg("dist=%g devtol=%g isan=%d",
3296  distances_buf[row][i],
3297  devtol,
3298  isnan(distances_buf[row][i]));
3299  */
3300  continue ;
3301  }
3302  sum += distances_buf[row][i] ;
3303  n++ ;
3304  }
3305  if ( n < 2 )
3306  {
3307  sinfo_msg_error("distances array could not be determined"
3308  " completely!, deviations of distances from"
3309  " devtol too big" ) ;
3310  cpl_free(distances) ;
3311  return NULL ;
3312  }
3313  else
3314  {
3315  distances[i] = sum / (float)n ;
3316  }
3317  }
3318 
3319  /* now sort the result according to the row sequence in the
3320  reconstructed image*/
3321  for ( i = 0 ; i < n_slitlets ; i++ )
3322  {
3323  if( (row_index=sinfo_sort_slitlets(i)) == -1) {
3324  sinfo_msg_error("wrong number of a slitlet\n") ;
3325  cpl_free (distances) ;
3326  return NULL ;
3327  }
3328  ret_distances[row_index] = distances[i] ;
3329  }
3330  cpl_free(distances) ;
3331 
3332  cpl_free(row_buf) ;
3333  cpl_free(x_position) ;
3334  cpl_free(found);
3335  cpl_free(found_clean) ;
3336  cpl_free(found_cleanit) ;
3337  sinfo_new_destroy_2Dfloatarray(&distances_buf,n_slitlets) ;
3338 
3339 
3340  return ret_distances ;
3341 }
3366 cpl_image *
3367 sinfo_new_make_true_resamp(cpl_image * calibImage,
3368  cpl_image * wavemap)
3369 {
3370  cpl_image * returnImage ;
3371  float edges[33] ;
3372  int imsize, kslit,i,j ;
3373  int slit_index ;
3374  int z;
3375  int col;
3376  //int recol ;
3377  int wlx=0;
3378  //int wly=0;
3379  int clx=0 ;
3380  int cly=0;
3381 
3382  float* pcdata=NULL;
3383  float* pwdata=NULL;
3384  float* prdata=NULL;
3385 
3386 
3387  wlx=cpl_image_get_size_x(wavemap);
3388  //wly=cpl_image_get_size_y(wavemap);
3389  pwdata=cpl_image_get_data_float(wavemap);
3390 
3391  edges[0]=0;
3392  j=1;
3393  for(i=0;i<wlx-1;i++)
3394  {
3395  if((pwdata[i]-pwdata[i+1])>0.0025 || (pwdata[i]-pwdata[i+1])<-0.0025)
3396  {
3397  sinfo_msg_error("wavemap sinfo_edge %d", i+1);
3398  edges[j]=i+1;
3399  j++;
3400  }
3401  }
3402  edges[32]=2048;
3403 
3404  clx=cpl_image_get_size_x(calibImage);
3405  cly=cpl_image_get_size_y(calibImage);
3406  pcdata=cpl_image_get_data_float(calibImage);
3407 
3408  imsize = clx / N_SLITLETS ;
3409 
3410  /* allocate memory */
3411  returnImage = cpl_image_new(clx,cly,CPL_TYPE_FLOAT);
3412  prdata=cpl_image_get_data_float(returnImage);
3413  for ( z = 0 ; z < cly ; z++ ) /* go through the z-axis */
3414  {
3415  for ( col = 0 ; col < clx ; col++ ) /* go through the image columns */
3416  prdata[col+z*clx]=ZERO;
3417  }
3418 
3419 
3420  /* now build the data cube out of the resampled image */
3421  for ( z = 0 ; z < cly ; z++ ) /* go through the z-axis */
3422  {
3423  kslit = 0 ;
3424  slit_index = -1 ;
3425  //recol = -1 ;
3426  for ( col = 0 ; col < clx ; col++ ) /* go through the image columns */
3427  {
3428  /*if ( col % imsize == 0 )
3429  {*/
3430  //recol = 0 ;
3431  /*kslit = col/imsize ;*/
3432  for(i=0;i<32;i++)
3433  {
3434  if(col>=sinfo_new_nint(edges[i]) &&
3435  col<sinfo_new_nint(edges[i+1]))
3436  kslit=i;
3437  }
3438  /* sort the slitlets in the right spiffi specific way */
3439  if( (slit_index=sinfo_sort_slitlets(kslit)) == -1) {
3440  sinfo_msg_error("wrong slitlet index: couldn't be a "
3441  "spiffi image, there must be 32 "
3442  "slitlets!") ;
3443 
3444  }
3445 
3446  /*}*/
3447 
3448  /* fill each cube plane with one image row */
3449  if((col-sinfo_new_nint(edges[kslit]))>0 &&
3450  (col-sinfo_new_nint(edges[kslit]))<imsize-1 )
3451  prdata[(col-sinfo_new_nint(edges[kslit]))+
3452  slit_index*imsize+z*clx] =
3453  pcdata[col+z*clx] ;
3454  else
3455  prdata[(col-sinfo_new_nint(edges[kslit]))+
3456  slit_index*imsize+z*clx] = ZERO;
3457  /*recol++ ;*/
3458 
3459  }
3460  }
3461  return returnImage ;
3462 }
3463 
3464 /*The old slitlet order*/
3465 /*switch (kslit)
3466  {
3467  case 0:
3468  slit_index = 23 ;
3469  break ;
3470  case 1:
3471  slit_index = 24 ;
3472  break ;
3473  case 2:
3474  slit_index = 22 ;
3475  break ;
3476  case 3:
3477  slit_index = 25 ;
3478  break ;
3479  case 4:
3480  slit_index = 21 ;
3481  break ;
3482  case 5:
3483  slit_index = 26 ;
3484  break ;
3485  case 6:
3486  slit_index = 20 ;
3487  break ;
3488  case 7:
3489  slit_index = 27 ;
3490  break ;
3491  case 8:
3492  slit_index = 19 ;
3493  break ;
3494  case 9:
3495  slit_index = 28 ;
3496  break ;
3497  case 10:
3498  slit_index = 18 ;
3499  break ;
3500  case 11:
3501  slit_index = 29 ;
3502  break ;
3503  case 12:
3504  slit_index = 17 ;
3505  break ;
3506  case 13:
3507  slit_index = 30 ;
3508  break ;
3509  case 14:
3510  slit_index = 16 ;
3511  break ;
3512  case 15:
3513  slit_index = 31 ;
3514  break ;
3515  case 16:
3516  slit_index = 0 ;
3517  break ;
3518  case 17:
3519  slit_index = 15 ;
3520  break ;
3521  case 18:
3522  slit_index = 1 ;
3523  break ;
3524  case 19:
3525  slit_index = 14 ;
3526  break ;
3527  case 20:
3528  slit_index = 2 ;
3529  break ;
3530  case 21:
3531  slit_index = 13 ;
3532  break ;
3533  case 22:
3534  slit_index = 3 ;
3535  break ;
3536  case 23:
3537  slit_index = 12 ;
3538  break ;
3539  case 24:
3540  slit_index = 4 ;
3541  break ;
3542  case 25:
3543  slit_index = 11 ;
3544  break ;
3545  case 26:
3546  slit_index = 5 ;
3547  break ;
3548  case 27:
3549  slit_index = 10 ;
3550  break ;
3551  case 28:
3552  slit_index = 6 ;
3553  break ;
3554  case 29:
3555  slit_index = 9 ;
3556  break ;
3557  case 30:
3558  slit_index = 7 ;
3559  break ;
3560  case 31:
3561  slit_index = 8 ;
3562  break ;
3563  default:
3564  sinfo_msg_error("wrong slitlet index: couldn't "
3565  "be a spiffi image, \
3566  there must be 32 slitlets!\n") ;
3567  cpl_imagelist_delete(returnCube) ;
3568  return NULL ;
3569  break ;
3570  }*/
3571 
3572 
3573 /*--------------------------------------------------------------------------*/