SINFONI Pipeline Reference Manual  2.6.0
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 
277  double tempr,
278  tempi;
279 
280  n = (unsigned long)nn << 1;
281  j = 1;
282  for (i=1 ; i<n ; i+=2) {
283  if (j > i) {
284  KERNEL_SW(data[j-1],data[i-1]);
285  KERNEL_SW(data[j],data[i]);
286  }
287  m = n >> 1;
288  while (m>=2 && j>m) {
289  j -= m;
290  m >>= 1;
291  }
292  j += m;
293  }
294  mmax = 2;
295  while (n > mmax) {
296  unsigned long istep = mmax << 1;
297  double theta = 2 * PI_NUMB / mmax;
298  double wtemp = sin(0.5 * theta);
299  double wpr = -2.0 * wtemp * wtemp;
300  double wpi = sin(theta);
301  double wr = 1.0;
302  double wi = 0.0;
303  for (m=1 ; m<mmax ; m+=2) {
304  for (i=m ; i<=n ; i+=istep) {
305  j = i + mmax;
306  tempr = wr * data[j-1] - wi * data[j];
307  tempi = wr * data[j] + wi * data[j-1];
308  data[j-1] = data[i-1] - tempr;
309  data[j] = data[i] - tempi;
310  data[i-1] += tempr;
311  data[i] += tempi;
312  }
313  wr = (wtemp = wr) * wpr - wi * wpi + wr;
314  wi = wi * wpr + wtemp * wpi + wi;
315  }
316  mmax = istep;
317  }
318 }
319 #undef KERNEL_SW
320 
358 double *
359 sinfo_invert_linear_transform(double *trans)
360 {
361  double * i_trans ;
362  double det ;
363 
364  if (trans==NULL) return NULL ;
365  det = (trans[0] * trans[4]) - (trans[1] * trans[3]) ;
366  if (fabs(det) < 1e-6) {
367  sinfo_msg_error("NULL determinant: cannot sinfo_invert transform") ;
368  return NULL ;
369  }
370 
371  i_trans = cpl_calloc(6, sizeof(double)) ;
372 
373  i_trans[0] = trans[4] / det ;
374  i_trans[1] = -trans[1] / det ;
375  i_trans[2] = ((trans[1] * trans[5]) - (trans[2] * trans[4])) / det ;
376  i_trans[3] = -trans[3] / det ;
377  i_trans[4] = trans[0] / det ;
378  i_trans[5] = ((trans[2] * trans[3]) - (trans[0] * trans[5])) / det ;
379 
380  return i_trans ;
381 }
#define sinfo_msg_error(...)
Print an error message.
Definition: sinfo_msg.h:69