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