SINFONI Pipeline Reference Manual  2.6.0
sinfo_shift_images.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 05/03/03 created
27 */
28 
29 /************************************************************************
30 * NAME
31 * sinfo_shift_images.c -
32 * some procedures to shift images in spectral direction
33 *
34 * SYNOPSIS
35 * #include "sinfo_shift_images.h"
36 *
37 * 1) double sinfo_new_determine_shift_by_correlation ( cpl_image * refImage,
38 * cpl_image * shiftedImage )
39 * 2) cpl_image * sinfo_new_shift_image_in_spec ( cpl_image * shiftedImage,
40  double shift,
41  double * sub_shift )
42 * 3) cpl_image *
43  sinfo_new_fine_shift_image_in_spec_poly(cpl_image * shiftedImage,
44  double sub_shift,
45  int order )
46 * 4) cpl_image *
47  sinfo_new_fine_shift_image_in_spec_cubicspline(cpl_image * shiftedImage,
48  double sub_shift )
49 * 5) cpl_imagelist * sinfo_align_cube_to_reference(cpl_imagelist * cube,
50 * cpl_image * refIm,
51 * int order,
52 * int shift_indicator )
53 *
54 *
55 * DESCRIPTION
56 *
57 * 1) determines the sub-pixel shift of to emission line
58 * frames by cross sinfo_correlation and fitting the sinfo_correlation
59 * function by a Gaussian
60 * 2) shifts an image by a given amount to integer pixel accuracy
61 * 3) shifts an image by a given amount to sub-pixel accuracy
62 * 4) shifts an image by a given amount to sub-pixel accuracy
63 * 5) shifts images stacked in a cube by a given amount to sub-pixel accuracy
64 *
65 * FILES
66 *
67 * ENVIRONMENT
68 *
69 * RETURN VALUES
70 *
71 * CAUTIONS
72 *
73 * EXAMPLES
74 *
75 * SEE ALSO
76 *
77 * BUGS
78 *
79 *------------------------------------------------------------------------
80 */
81 
82 /*
83  * System Headers
84  */
85 
86 #ifdef HAVE_CONFIG_H
87 # include <config.h>
88 #endif
89 #include "sinfo_vltPort.h"
90 #define POSIX_SOURCE 1
91 /*
92  * Local Headers
93  */
94 #include "sinfo_function_1d.h"
95 #include "sinfo_shift_images.h"
96 #include "sinfo_new_resampling.h"
97 #include "sinfo_globals.h"
98 
99 
100 static int filecounter ;
108 /*----------------------------------------------------------------------------
109  * Function codes
110  *--------------------------------------------------------------------------*/
111 
123 double sinfo_new_determine_shift_by_correlation ( cpl_image * refImage,
124  cpl_image * shiftedImage )
125 {
126  int col, row ;
127  int i, j, k, width;
128  unsigned long convsize ;
129  float * lineref ;
130  float * line ;
131  float * offset2 ;
132  double * result ;
133  double mean_offset2 ;
134  /*int magFactor ;*/
135  int maxlag ;
136  int delta ;
137  double xcorr_max ;
138  /*float arg ;*/
139  float par[MAXPAR] ;
140  float derv_par[MAXPAR] ;
141  int iters, xdim, ndat ;
142  int numpar, its ;
143  int * mpar ;
144  float tol, lab ;
145  float * xdat, * wdat ;
146  Vector * peak;
147  char filename[FILE_NAME_SZ] ;
148  FILE * fp ;
149 
150  int rlx=0;
151  int rly=0;
152  int slx=0;
153  int sly=0;
154  float* prdata=NULL;
155  float* psdata=NULL;
156 
157  if ( NULL == refImage || NULL == shiftedImage )
158  {
159  sinfo_msg_error("image not given!") ;
160  return ZERO ;
161  }
162  rlx=cpl_image_get_size_x(refImage);
163  rly=cpl_image_get_size_x(refImage);
164  prdata=cpl_image_get_data_float(refImage);
165  slx=cpl_image_get_size_x(shiftedImage);
166  sly=cpl_image_get_size_x(shiftedImage);
167  psdata=cpl_image_get_data_float(shiftedImage);
168 
169  if ( rlx != slx || rly != sly )
170  {
171  sinfo_msg_error("image size not compatible!") ;
172  return ZERO ;
173  }
174  snprintf(filename, MAX_NAME_SIZE-1,"offset%d.list", filecounter) ;
175 
176  fp = fopen(filename, "w") ;
177 
178  convsize = sly;
179 
180  lineref = (float*) cpl_calloc(convsize, sizeof(float) ) ;
181  line = (float*) cpl_calloc(convsize, sizeof(float) ) ;
182 
183  offset2 = (float*) cpl_calloc(slx, sizeof(float) ) ;
184 
185  for ( col = 0 ; col < slx ; col++ )
186  {
187  /* initialize arrays */
188  for ( row = 0 ; row < (int) convsize ; row++ )
189  {
190  lineref[row] = 0. ;
191  line[row] = 0. ;
192  }
193 
194  /* magnify spectral sinfo_vector by magFactor */
195  for ( row = 0 ; row < (sly) ; row++ )
196  {
197  lineref[row] = prdata[col+row*slx] ; /* AM: why slx? */
198  line[row] = psdata[col+row*slx] ;
199  }
200 
201  float* myres = sinfo_function1d_filter_lowpass(line, convsize,
202  LOW_PASS_GAUSSIAN, 3) ;
203  float* refres = sinfo_function1d_filter_lowpass(lineref, convsize,
204  LOW_PASS_GAUSSIAN, 4) ;
205 
206  /* now do a cross correlaton of both convolved spectral vectors */
207  int halfsearch = convsize / 2 ;
208  result = sinfo_new_xcorrel( myres, convsize, refres, convsize,
209  halfsearch, &delta, &maxlag, &xcorr_max ) ;
210 
211  if ( xcorr_max < 0. )
212  {
213  sinfo_function1d_del ( refres ) ;
214  sinfo_function1d_del ( myres ) ;
215  cpl_free (result) ;
216  continue ;
217  }
218 
219  /* in this section, we fit the sinfo_correlation function with a
220  gauss, and find its peak, th
221  us getting subpixel-accuracy */
222 
223  i = maxlag; j = i+1;
224  while (result[j] < result[i])
225  {
226  i++; j++;
227  }
228  i = maxlag; k = i-1;
229  while (result[k] < result[i])
230  {
231  i--; k--;
232  }
233  width = j-k+1;
234  /* allocate memory for the spectral sinfo_vector */
235  if ( NULL == (peak = sinfo_new_vector (width)) )
236  {
237  sinfo_msg_error ("cannot allocate new Vector ") ;
238  fclose(fp);
239  cpl_free ( offset2 ) ;
240  return ZERO ;
241  }
242 
243 
244  /* allocate memory */
245  xdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
246  wdat = (float *) cpl_calloc( peak -> n_elements, sizeof (float) ) ;
247  mpar = (int *) cpl_calloc( MAXPAR, sizeof (int) ) ;
248 
249  /* determine the values of the spectral sinfo_vector given as input */
250  /* go through the chosen column */
251 
252  for ( i = 0 ; i < width ; i++ )
253  {
254  peak -> data[i] = result[k+i] ;
255  xdat[i] = i;
256  wdat[i] = 1.0;
257  }
258 
259  /* set initial values for the fitting routine */
260  xdim = XDIM;
261  ndat = peak -> n_elements ;
262  numpar = MAXPAR ;
263  tol = TOL ;
264  lab = LAB ;
265  its = ITS ;
266  par[1] = width/2.0 ;
267  par[2] = (float) (maxlag - k) ;
268  par[3] = (peak -> data[0] + peak -> data[peak->n_elements - 1]) / 2.0 ;
269  par[0] = result[maxlag] - (par[3]) ;
270 
271  for ( i = 0 ; i < MAXPAR ; i++ )
272  {
273  derv_par[i] = 0.0 ;
274  mpar[i] = 1 ;
275  }
276 
277  /* finally, do the least square fit using a sinfo_gaussian */
278  if ( 0 > ( iters = sinfo_new_lsqfit_c( xdat, &xdim, peak -> data, wdat,
279  &ndat, par, derv_par, mpar,
280  &numpar, &tol, &its, &lab )) )
281  {
282  sinfo_msg_warning ("sinfo_new_lsqfit_c: least squares fit failed "
283  "in col: %d, error no.: %d", col, iters) ;
284  sinfo_new_destroy_vector ( peak ) ;
285  cpl_free ( xdat ) ;
286  cpl_free ( wdat ) ;
287  cpl_free ( mpar ) ;
288  sinfo_function1d_del ( refres ) ;
289  sinfo_function1d_del ( myres ) ;
290  cpl_free (result) ;
291  continue ;
292  }
293 
294  sinfo_new_destroy_vector ( peak ) ;
295  cpl_free (xdat) ;
296  cpl_free (wdat) ;
297  cpl_free (mpar) ;
298  sinfo_function1d_del ( refres ) ;
299  sinfo_function1d_del ( myres ) ;
300  cpl_free (result) ;
301 
302  offset2[col] = (float)( k+par[2] - sly/2) ;
303  fprintf(fp, "offset: %f in col: %d\n", offset2[col], col) ;
304  }
305 
306  mean_offset2 = (double)sinfo_new_clean_mean (offset2, slx, 15., 15. ) ;
307  fprintf(fp, "mean offset: %f\n", mean_offset2) ;
308  fclose(fp) ;
309 
310  cpl_free ( lineref ) ;
311  cpl_free ( line ) ;
312  cpl_free ( offset2 ) ;
313  filecounter++ ;
314  if (filecounter > 100 ) filecounter = 0 ;
315 
316  return mean_offset2 ;
317 }
318 
319 
330 cpl_image *
331 sinfo_new_shift_image_in_spec ( cpl_image * shiftedImage,
332  double shift,
333  double * sub_shift )
334 {
335  cpl_image * retIm ;
336  int col, row ;
337  int intshift ;
338  int ilx=0;
339  int ily=0;
340  int olx=0;
341  int oly=0;
342 
343  float* pidata=NULL;
344  float* podata=NULL;
345 
346  if ( shiftedImage == NULL )
347  {
348  sinfo_msg_error("no image given!") ;
349  return NULL ;
350  }
351 
352  ilx=cpl_image_get_size_x(shiftedImage);
353  ily=cpl_image_get_size_y(shiftedImage);
354  pidata=cpl_image_get_data_float(shiftedImage);
355 
356  intshift = sinfo_new_nint (shift) ;
357  *sub_shift = shift - (double) intshift ;
358  if ( intshift == 0 )
359  {
360  retIm =cpl_image_duplicate ( shiftedImage ) ;
361  return retIm ;
362  }
363  else
364  {
365  if ( NULL == (retIm = cpl_image_new(ilx,ily,CPL_TYPE_FLOAT)) )
366  {
367  sinfo_msg_error ("could not allocate memory!") ;
368  return NULL ;
369  }
370  }
371 
372  olx=cpl_image_get_size_x(retIm);
373  oly=cpl_image_get_size_y(retIm);
374  podata=cpl_image_get_data_float(retIm);
375 
376  for ( col = 0 ; col < ilx ; col++ )
377  {
378  for ( row = 0 ; row < ily ; row++ )
379  {
380  if ( (row-intshift >= 0 ) && (row - intshift < oly) )
381  {
382  podata[col+(row-intshift)*olx] = pidata[col+row*olx] ;
383  }
384  }
385  }
386  return retIm ;
387 }
388 
398 cpl_image *
399 sinfo_new_fine_shift_image_in_spec_poly ( cpl_image * shiftedImage,
400  double sub_shift,
401  int order )
402 {
403  cpl_image * retIm ;
404 
405  float* spec=NULL ;
406  float* corrected_spec=NULL ;
407  float* xnum=NULL ;
408 
409  float new_sum ;
410  float eval/*, dy*/ ;
411  float * imageptr ;
412  int row, col ;
413  int firstpos ;
414  int n_points ;
415  int i ;
416  int flag;
417  int ilx=0;
418  int ily=0;
419  int olx=0;
420  /* int oly=0; */
421 
422  float* pidata=NULL;
423  float* podata=NULL;
424 
425  if ( shiftedImage == NULL )
426  {
427  sinfo_msg_error("no image given!") ;
428  return NULL ;
429  }
430  ilx=cpl_image_get_size_x(shiftedImage);
431  ily=cpl_image_get_size_y(shiftedImage);
432  pidata=cpl_image_get_data_float(shiftedImage);
433 
434  if ( order <= 0 )
435  {
436  sinfo_msg_error("wrong order of interpolation polynom given!") ;
437  return NULL ;
438  }
439 
440  /* allocate memory */
441  if ( NULL == (retIm = cpl_image_new(ilx, ily,CPL_TYPE_FLOAT)) )
442  {
443  sinfo_msg_error ("could not allocate memory!") ;
444  return NULL ;
445  }
446 
447  olx=cpl_image_get_size_x(retIm);
448  /* oly=cpl_image_get_size_y(retIm); */
449  podata=cpl_image_get_data_float(retIm);
450 
451  n_points = order + 1 ;
452  if ( n_points % 2 == 0 )
453  {
454  firstpos = (int)(n_points/2) - 1 ;
455  }
456  else
457  {
458  firstpos = (int)(n_points/2) ;
459  }
460 
461  spec=cpl_calloc(ily,sizeof(float)) ;
462  corrected_spec=cpl_calloc(ily,sizeof(float)) ;
463  xnum=cpl_calloc(order+1,sizeof(float)) ;
464 
465 
466  /* fill the xa[] array for the polint function */
467  for ( i = 0 ; i < n_points ; i++ )
468  {
469  xnum[i] = i ;
470  }
471 
472  for ( col = 0 ; col < ilx ; col++ )
473  {
474  for ( row = 0 ; row < ily ; row++ )
475  {
476  corrected_spec[row] = 0. ;
477  }
478  float sum = 0. ;
479  for ( row = 0 ; row < ily ; row++ )
480  {
481  spec[row] = pidata[col + row*ilx] ;
482  if (isnan(spec[row]) )
483  {
484  spec[row] = 0. ;
485 
486  for ( i = row - firstpos ; i < row-firstpos+n_points ; i++ )
487  {
488  if ( i < 0 ) continue ;
489  if ( i >= ily) continue ;
490  corrected_spec[i] = ZERO ;
491  }
492  }
493  if ( row != 0 && row != ily - 1 )
494  {
495  sum += spec[row] ;
496  }
497  }
498 
499  new_sum = 0. ;
500  for ( row = 0 ; row < ily ; row++ )
501  {
502  /* ---------------------------------------------------------------
503  * now determine the arrays of size n_points with which the
504  * polynom is determined and determine the position eval
505  * where the polynom is evaluated in polynomial interpolation.
506  * Take care of the points near the row edges!
507  */
508  if (isnan(corrected_spec[row])) continue ;
509  if ( row - firstpos < 0 )
510  {
511  imageptr = &spec[0] ;
512  eval = sub_shift + row ;
513  }
514  else if ( row - firstpos + n_points >= ily )
515  {
516  imageptr = &spec[ily - n_points] ;
517  eval = sub_shift + row + n_points - ily ;
518  }
519  else
520  {
521  imageptr = &spec[row-firstpos] ;
522  eval = sub_shift + firstpos ;
523  }
524 
525  flag=0;
526  corrected_spec[row]=sinfo_new_nev_ille( xnum, imageptr,
527  order, eval, &flag) ;
528  if ( row != 0 && row != ily - 1 )
529  {
530  new_sum += corrected_spec[row] ;
531  }
532  }
533 
534  for ( row = 0 ; row < ily ; row++ )
535  {
536  if ( new_sum == 0. )
537  {
538  new_sum = 1. ;
539  }
540  if ( row == 0 )
541  {
542  podata[col+row*olx] = ZERO ;
543  }
544  else if ( row == ily - 1 )
545  {
546  podata[col+row*olx] = ZERO ;
547  }
548  else if ( isnan(corrected_spec[row]) )
549  {
550  podata[col+row*olx] = ZERO ;
551  }
552  else
553  {
554  corrected_spec[row] *= sum / new_sum ;
555  podata[col+row*olx] = corrected_spec[row] ;
556  }
557  }
558  }
559  cpl_free(spec) ;
560  cpl_free(corrected_spec) ;
561  cpl_free(xnum) ;
562  return retIm ;
563 }
572 cpl_image *
573 sinfo_new_fine_shift_image_in_spec_cubic_spline ( cpl_image * shiftedImage,
574  double sub_shift )
575 {
576  cpl_image * retIm ;
577  /*float second_deriv[shiftedImage -> ly] ;*/
578  float* spec=NULL ;
579  float* corrected_spec=NULL ;
580  float* xnum=NULL ;
581  float* eval=NULL ;
582  float new_sum ;
583  int row, col ;
584  int i ;
585  int ilx=0;
586  int ily=0;
587  int olx=0;
588  /* int oly=0; */
589 
590  float* pidata=NULL;
591  float* podata=NULL;
592 
593  if ( shiftedImage == NULL )
594  {
595  sinfo_msg_error("no image given!") ;
596  return NULL ;
597  }
598  ilx=cpl_image_get_size_x(shiftedImage);
599  ily=cpl_image_get_size_y(shiftedImage);
600  pidata=cpl_image_get_data_float(shiftedImage);
601 
602  /* allocate memory */
603  if ( NULL == (retIm = cpl_image_new(ilx,ily,CPL_TYPE_FLOAT)) )
604  {
605  sinfo_msg_error ("could not allocate memory!") ;
606  return NULL ;
607  }
608  olx=cpl_image_get_size_x(retIm);
609  /* oly=cpl_image_get_size_y(retIm); */
610  podata=cpl_image_get_data_float(retIm);
611 
612  xnum=cpl_calloc(ily,sizeof(float)) ;
613  /* fill the xa[] array for the spline function */
614  for ( i = 0 ; i < ily ; i++ )
615  {
616  xnum[i] = i ;
617  }
618 
619  spec=cpl_calloc(ily,sizeof(float)) ;
620  corrected_spec=cpl_calloc(ily,sizeof(float)) ;
621  eval=cpl_calloc(ily,sizeof(float)) ;
622 
623  for ( col = 0 ; col < ilx ; col++ )
624  {
625  float sum = 0. ;
626  for ( row = 0 ; row < ily ; row++ )
627  {
628  spec[row] = pidata[col + row*ilx] ;
629  if (isnan(spec[row]) )
630  {
631  for ( i = row-1 ; i <= row+1 ; i++ )
632  {
633  if ( i < 0 ) continue ;
634  if ( i >= ily) continue ;
635  corrected_spec[i] = ZERO ;
636  }
637  spec[row] = 0. ;
638  }
639  sum += spec[row] ;
640  eval[row] = (float)sub_shift+(float)row ;
641  }
642  /* now we do the spline interpolation*/
643  if ( -1 == sinfo_function1d_natural_spline( xnum, spec, ily, eval,
644  corrected_spec, ily ) )
645  {
646  sinfo_msg_error("error in spline interpolation!") ;
647  return NULL ;
648  }
649 
650  new_sum = 0. ;
651  for ( row = 0 ; row < ily ; row++ )
652  {
653  if ( isnan(corrected_spec[row]) )
654  {
655  continue ;
656  }
657  new_sum += corrected_spec[row] ;
658  }
659 
660  for ( row = 0 ; row < ily ; row++ )
661  {
662  if ( new_sum == 0. ) new_sum =1. ;
663  {
664  if ( isnan(corrected_spec[row]) )
665  {
666  podata[col+row*olx] = ZERO ;
667  }
668  else
669  {
670  corrected_spec[row] *= sum / new_sum ;
671  podata[col+row*olx] = corrected_spec[row] ;
672  }
673  }
674  }
675  }
676  cpl_free(xnum);
677  cpl_free(spec) ;
678  cpl_free(corrected_spec) ;
679  cpl_free(eval) ;
680 
681  return retIm ;
682 }
683 
695 cpl_imagelist * sinfo_align_cube_to_reference (cpl_imagelist * cube,
696  cpl_image * refIm,
697  int order,
698  int shift_indicator )
699 {
700  cpl_imagelist * retCube=NULL ;
701  cpl_image * fineShiftedIm=NULL ;
702  int z=0;
703  double * ker=NULL ;
704 
705  if (cube == NULL)
706  {
707  sinfo_msg_error("no input cube given!") ;
708  return NULL ;
709  }
710  if (refIm == NULL)
711  {
712  sinfo_msg_error("no input ref. image given!") ;
713  return NULL ;
714  }
715 
716  /* allocation for a cube structure without the image planes */
717  retCube = cpl_imagelist_new() ;
718 
719  if ( shift_indicator != 0 && shift_indicator != 1 )
720  {
721  ker = sinfo_new_generate_interpolation_kernel("tanh") ;
722  if (ker == NULL)
723  {
724  sinfo_msg_error("kernel generation failure: aborting resampling") ;
725  cpl_imagelist_delete(retCube);
726  return NULL ;
727  }
728  }
729 
730  for ( z = 0 ; z < cpl_imagelist_get_size(cube) ; z++ )
731  {
732  /* first determine the shift by correlation with the reference image */
733  cpl_image* img=cpl_imagelist_get(cube,z);
734  double shift;
735  if (isnan( shift=sinfo_new_determine_shift_by_correlation(refIm,img)))
736  {
737  sinfo_msg_error("error in sinfo_determineShiftByCorrelation()!") ;
738  return NULL ;
739  }
740 
741  cpl_image * shiftedIm=NULL ;
742  double sub_shift=0 ;
743  if ( NULL == (shiftedIm = sinfo_new_shift_image_in_spec(img,shift,
744  &sub_shift)) )
745  {
746  sinfo_msg_error("error in sinfo_shiftImageInSpec()!") ;
747  return NULL ;
748  }
749  if ( shift_indicator == 0 )
750  {
751  if ( NULL == (fineShiftedIm =
752  sinfo_new_fine_shift_image_in_spec_poly (shiftedIm,
753  sub_shift, order)))
754  {
755  sinfo_msg_error("error in sinfo_fineShiftImageInSpecPoly()!") ;
756  return NULL ;
757  }
758  }
759  else if ( shift_indicator == 1)
760  {
761  if ( NULL == (fineShiftedIm =
762  sinfo_new_fine_shift_image_in_spec_cubic_spline (shiftedIm,
763  sub_shift)))
764  {
765  sinfo_msg_error("error in fineShiftImageInSpecCubicspline()!") ;
766  return NULL ;
767  }
768  }
769 
770  else
771  {
772  if ( NULL == (fineShiftedIm =
773  sinfo_new_shift_image(shiftedIm,0.,sub_shift, ker ) ) )
774  {
775  sinfo_msg_error("error in fineShiftImageInSpecCubicspline()!") ;
776  return NULL ;
777  }
778  }
779  cpl_imagelist_set(retCube,fineShiftedIm,z);
780  cpl_image_delete (shiftedIm) ;
781  cpl_image_delete (fineShiftedIm) ;
782  }
783  if ( shift_indicator != 0 && shift_indicator != 1 ) cpl_free(ker) ;
784  return retCube ;
785 }
786 
787 /*--------------------------------------------------------------------------*/
#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