SINFONI Pipeline Reference Manual  2.5.2
sinfo_resampling.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 
21  File name : resampling.c
22  Author : Nicolas Devillard
23  Created on : Jan 04, 1996
24  Description : resampling routines
25 
26  ---------------------------------------------------------------------------*/
27 
28 /*
29  $Id: sinfo_resampling.c,v 1.6 2012-03-03 10:18:26 amodigli Exp $
30  $Author: amodigli $
31  $Date: 2012-03-03 10:18:26 $
32  $Revision: 1.6 $
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 # include <config.h>
37 #endif
38 /*---------------------------------------------------------------------------
39  Includes
40  ---------------------------------------------------------------------------*/
41 #include <string.h>
42 #include "sinfo_resampling.h"
43 #include <math.h>
44 #include "sinfo_globals.h"
45 /*---------------------------------------------------------------------------
46  Private functions
47  ---------------------------------------------------------------------------*/
48 static void reverse_tanh_kernel(double * data, int nn) ;
49 static double * sinfo_generate_tanh_kernel(double steep);
50 
60 /*---------------------------------------------------------------------------
61  Function codes
62  ---------------------------------------------------------------------------*/
63 
88 double *
89 sinfo_generate_interpolation_kernel(const char * kernel_type)
90 {
91  double * tab ;
92  int i ;
93  double x ;
94  double alpha ;
95  double inv_norm ;
96  int samples = KERNEL_SAMPLES ;
97 
98  if (kernel_type==NULL) {
99  tab = sinfo_generate_interpolation_kernel("tanh") ;
100  } else if (!strcmp(kernel_type, "default")) {
101  tab = sinfo_generate_interpolation_kernel("tanh") ;
102  } else if (!strcmp(kernel_type, "sinc")) {
103  tab = cpl_malloc(samples * sizeof(double)) ;
104  tab[0] = 1.0 ;
105  tab[samples-1] = 0.0 ;
106  for (i=1 ; i<samples ; i++) {
107  x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
108  tab[i] = sinfo_sinc(x) ;
109  }
110  } else if (!strcmp(kernel_type, "sinc2")) {
111  tab = cpl_malloc(samples * sizeof(double)) ;
112  tab[0] = 1.0 ;
113  tab[samples-1] = 0.0 ;
114  for (i=1 ; i<samples ; i++) {
115  x = 2.0 * (double)i/(double)(samples-1) ;
116  tab[i] = sinfo_sinc(x) ;
117  tab[i] *= tab[i] ;
118  }
119  } else if (!strcmp(kernel_type, "lanczos")) {
120  tab = cpl_malloc(samples * sizeof(double)) ;
121  for (i=0 ; i<samples ; i++) {
122  x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
123  if (fabs(x)<2) {
124  tab[i] = sinfo_sinc(x) * sinfo_sinc(x/2) ;
125  } else {
126  tab[i] = 0.00 ;
127  }
128  }
129  } else if (!strcmp(kernel_type, "hamming")) {
130  tab = cpl_malloc(samples * sizeof(double)) ;
131  alpha = 0.54 ;
132  inv_norm = 1.00 / (double)(samples - 1) ;
133  for (i=0 ; i<samples ; i++) {
134  x = (double)i ;
135  if (i<(samples-1)/2) {
136  tab[i] = alpha + (1-alpha) * cos(2.0*PI_NUMB*x*inv_norm) ;
137  } else {
138  tab[i] = 0.0 ;
139  }
140  }
141  } else if (!strcmp(kernel_type, "hann")) {
142  tab = cpl_malloc(samples * sizeof(double)) ;
143  alpha = 0.50 ;
144  inv_norm = 1.00 / (double)(samples - 1) ;
145  for (i=0 ; i<samples ; i++) {
146  x = (double)i ;
147  if (i<(samples-1)/2) {
148  tab[i] = alpha + (1-alpha) * cos(2.0*PI_NUMB*x*inv_norm) ;
149  } else {
150  tab[i] = 0.0 ;
151  }
152  }
153  } else if (!strcmp(kernel_type, "tanh")) {
154  tab = sinfo_generate_tanh_kernel(TANH_STEEPNESS) ;
155  } else {
156  sinfo_msg_error("unrecognized kernel type [%s]: aborting generation",
157  kernel_type) ;
158  return NULL ;
159  }
160 
161  return tab ;
162 }
163 
175 double
176 sinfo_sinc(double x)
177 {
178  if (fabs(x)<1e-4)
179  return (double)1.00 ;
180  else
181  return ((sin(x * (double)PI_NUMB)) / (x * (double)PI_NUMB)) ;
182 }
183 
205 #define hk_gen(x,s) (((tanh(s*(x+0.5))+1)/2)*((tanh(s*(-x+0.5))+1)/2))
206 
207 static double *
208 sinfo_generate_tanh_kernel(double steep)
209 {
210  double * kernel ;
211  double * x ;
212  double width ;
213  double inv_np ;
214  double ind ;
215  int i ;
216  int np ;
217  int samples ;
218 
219  width = (double)TABSPERPIX / 2.0 ;
220  samples = KERNEL_SAMPLES ;
221  np = 32768 ; /* Hardcoded: should never be changed */
222  inv_np = 1.00 / (double)np ;
223 
224  /*
225  * Generate the kernel expression in Fourier space
226  * with a correct frequency ordering to allow standard FT
227  */
228  x = cpl_malloc((2*np+1)*sizeof(double)) ;
229  for (i=0 ; i<np/2 ; i++) {
230  ind = (double)i * 2.0 * width * inv_np ;
231  x[2*i] = hk_gen(ind, steep) ;
232  x[2*i+1] = 0.00 ;
233  }
234  for (i=np/2 ; i<np ; i++) {
235  ind = (double)(i-np) * 2.0 * width * inv_np ;
236  x[2*i] = hk_gen(ind, steep) ;
237  x[2*i+1] = 0.00 ;
238  }
239 
240  /*
241  * Reverse Fourier to come back to image space
242  */
243  reverse_tanh_kernel(x, np) ;
244 
245  /*
246  * Allocate and fill in returned array
247  */
248  kernel = cpl_malloc(samples * sizeof(double)) ;
249  for (i=0 ; i<samples ; i++) {
250  kernel[i] = 2.0 * width * x[2*i] * inv_np ;
251  }
252  cpl_free(x) ;
253  return kernel ;
254 }
255 
268 #define KERNEL_SW(a,b) tempr=(a);(a)=(b);(b)=tempr
269 static void
270 reverse_tanh_kernel(double * data, int nn)
271 {
272  unsigned long n,
273  mmax,
274  m,
275  i, j,
276  istep ;
277  double wtemp,
278  wr,
279  wpr,
280  wpi,
281  wi,
282  theta;
283  double tempr,
284  tempi;
285 
286  n = (unsigned long)nn << 1;
287  j = 1;
288  for (i=1 ; i<n ; i+=2) {
289  if (j > i) {
290  KERNEL_SW(data[j-1],data[i-1]);
291  KERNEL_SW(data[j],data[i]);
292  }
293  m = n >> 1;
294  while (m>=2 && j>m) {
295  j -= m;
296  m >>= 1;
297  }
298  j += m;
299  }
300  mmax = 2;
301  while (n > mmax) {
302  istep = mmax << 1;
303  theta = 2 * PI_NUMB / mmax;
304  wtemp = sin(0.5 * theta);
305  wpr = -2.0 * wtemp * wtemp;
306  wpi = sin(theta);
307  wr = 1.0;
308  wi = 0.0;
309  for (m=1 ; m<mmax ; m+=2) {
310  for (i=m ; i<=n ; i+=istep) {
311  j = i + mmax;
312  tempr = wr * data[j-1] - wi * data[j];
313  tempi = wr * data[j] + wi * data[j-1];
314  data[j-1] = data[i-1] - tempr;
315  data[j] = data[i] - tempi;
316  data[i-1] += tempr;
317  data[i] += tempi;
318  }
319  wr = (wtemp = wr) * wpr - wi * wpi + wr;
320  wi = wi * wpr + wtemp * wpi + wi;
321  }
322  mmax = istep;
323  }
324 }
325 #undef KERNEL_SW
326 
364 double *
365 sinfo_invert_linear_transform(double *trans)
366 {
367  double * i_trans ;
368  double det ;
369 
370  if (trans==NULL) return NULL ;
371  det = (trans[0] * trans[4]) - (trans[1] * trans[3]) ;
372  if (fabs(det) < 1e-6) {
373  sinfo_msg_error("NULL determinant: cannot sinfo_invert transform") ;
374  return NULL ;
375  }
376 
377  i_trans = cpl_calloc(6, sizeof(double)) ;
378 
379  i_trans[0] = trans[4] / det ;
380  i_trans[1] = -trans[1] / det ;
381  i_trans[2] = ((trans[1] * trans[5]) - (trans[2] * trans[4])) / det ;
382  i_trans[3] = -trans[3] / det ;
383  i_trans[4] = trans[0] / det ;
384  i_trans[5] = ((trans[2] * trans[3]) - (trans[0] * trans[5])) / det ;
385 
386  return i_trans ;
387 }