OMEGA Pipeline Reference Manual  1.0.5
omega_fftw.c
1 /* $Id: omega_fftw.c,v 1.3 2012-01-31 13:38:50 agabasch Exp $
2  *
3  * This file is part of the OMEGA Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: agabasch $
23  * $Date: 2012-01-31 13:38:50 $
24  * $Revision: 1.3 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <math.h>
39 #include <errno.h>
40 #include <complex.h>
41 
42 #include "omega_bpm.h"
43 
44 #include "omega_utils.h"
58 /*----------------------------------------------------------------------------*/
62 /*-----------------------------------------------------------------------------
63  Defines
64  -----------------------------------------------------------------------------*/
65 cpl_image *omega_mirror_edges(cpl_image *image, int dx, int dy);
66 
67 /*-------------------------------------------------------------------------*/
83 /*--------------------------------------------------------------------------*/
84 cpl_image * omega_gen_lowpass(int xs, int ys, double sigma_x, double sigma_y)
85 {
86 
87  int i= 0.0;
88  int j= 0.0;
89  int hlx= 0.0;
90  int hly = 0.0;
91  double x= 0.0;
92  double y= 0.0;
93  double gaussval= 0.0;
94  float *data;
95 
96  cpl_image *lowpass_image;
97 
98 
99  lowpass_image = cpl_image_new (xs, ys, CPL_TYPE_FLOAT);
100  if (lowpass_image == NULL) {
101  cpl_msg_error (cpl_func, "Cannot generate lowpass filter <%s>",cpl_error_get_message());
102  return NULL;
103  }
104 
105  hlx = xs/2;
106  hly = ys/2;
107 
108  data = cpl_image_get_data_float(lowpass_image);
109 
110  /* Given an image with pixels 0<=i<N, 0<=j<M then the convolution image
111  has the following properties:
112 
113  ima[0][0] = 1
114  ima[i][0] = ima[N-i][0] = exp (-0.5 * (i/sig_i)^2) 1<=i<N/2
115  ima[0][j] = ima[0][M-j] = exp (-0.5 * (j/sig_j)^2) 1<=j<M/2
116  ima[i][j] = ima[N-i][j] = ima[i][M-j] = ima[N-i][M-j]
117  = exp (-0.5 * ((i/sig_i)^2 + (j/sig_j)^2))
118  */
119 
120  data[0] = (float)1.0;
121 
122  /* first row */
123  for (i=1 ; i<=hlx ; i++) {
124  x = (double)i / sigma_x;
125  gaussval = (double)exp(-0.5*x*x);
126  data[i] = gaussval;
127  data[xs-i] = gaussval;
128  }
129 
130  for (j=1; j<=hly ; j++) {
131  y = (double)j / sigma_y;
132  /* first column */
133  data[j*xs] = (double)exp(-0.5*y*y);
134  data[(ys-j)*xs] = (double)exp(-0.5*y*y);
135 
136  for (i=1 ; i<=hlx ; i++) {
137  /* Use internal symetries */
138  x = (double) i / sigma_x;
139  gaussval = (double)exp (-0.5*(x*x+y*y));
140  data[j*xs+i] = gaussval;
141  data[(j+1)*xs-i] = gaussval;
142  data[(ys-j)*xs+i] = gaussval;
143  data[(ys+1-j)*xs-i] = gaussval;
144 
145  }
146  }
147 
148  /* FIXME: for the moment, reset errno which is coming from exp()
149  in first for-loop at i=348. This is causing cfitsio to
150  fail when loading an extension image (bug in cfitsio too).
151  */
152  if(errno != 0)
153  errno = 0;
154 
155  return lowpass_image;
156 }
157 
171 cpl_image * omega_get_spatial_freq(cpl_image *flat, cpl_mask *bpm,
172  double gausfilt, int mirrorx, int mirrory){
173 
174  int xsize=0, ysize=0;
175 
176  double sigma_x = 0.;
177  double sigma_y = 0.;
178 
179  cpl_image *clean_flat=NULL;
180  cpl_image *eflat=NULL;
181  cpl_image *eflat_complex=NULL;
182  cpl_image *eflat_real=NULL;
183 
184  cpl_image *filter_image=NULL;
185  cpl_image *filter_image_complex=NULL;
186  cpl_image *flat_real;
187 
188 
189  /*Clean flat from bad pixels if bpm exists*/
190  clean_flat = cpl_image_duplicate(flat);
191  if (bpm != NULL) {
192  cpl_image_reject_from_mask(clean_flat,bpm);
193  cpl_detector_interpolate_rejected(clean_flat);
194  }
195 
196  /* Expand the flat image using the mirror edges function */
197  eflat = omega_mirror_edges(clean_flat, mirrorx, mirrory);
198  if(eflat == NULL){
199  freeimage(clean_flat);
200  cpl_msg_error(cpl_func,"Filter image is NULL");
201  return NULL;
202  }
203 
204  freeimage(clean_flat);
205 
206  xsize = cpl_image_get_size_x(eflat);
207  ysize = cpl_image_get_size_y(eflat);
208 
209  sigma_x = gausfilt;
210  sigma_y = (double)(sigma_x * ysize) / xsize;
211 
212 
213  /* Generate a lowpass filter to be used in the FFT convolution */
214  filter_image = omega_gen_lowpass(xsize, ysize, sigma_x, sigma_y);
215  if(filter_image == NULL){
216  cpl_msg_error(cpl_func,"Filter image is NULL");
217  return NULL;
218  }
219 
220  eflat_complex = cpl_image_new(xsize,ysize, CPL_TYPE_FLOAT_COMPLEX);
221  eflat_real = cpl_image_new(xsize,ysize, CPL_TYPE_FLOAT);
222  filter_image_complex =cpl_image_cast(filter_image,CPL_TYPE_FLOAT_COMPLEX);
223 
224  /*Free memory*/
225  cpl_image_delete(filter_image);
226 
227 
228  /* Apply a forward FFT on the images */
229  cpl_fft_image(eflat_complex, eflat, CPL_FFT_FORWARD);
230  /*Free memory*/
231  cpl_image_delete(eflat);
232 
233  /*Multiply the filter with the the FFT image */
234  cpl_image_multiply(eflat_complex,filter_image_complex);
235 
236 
237  /* Apply a backward FFT on the images */
238  cpl_fft_image(eflat_real, eflat_complex,CPL_FFT_BACKWARD);
239  /*Free memory*/
240  cpl_image_delete(eflat_complex);
241  cpl_image_delete(filter_image_complex);
242 
243  /* Extract original image from the expanded image. */
244  flat_real = cpl_image_extract(eflat_real, mirrorx+1, mirrory+1,
245  xsize-mirrorx, ysize-mirrory);
246 
247  if (flat_real == NULL) {
248  cpl_msg_error (cpl_func,"Real extracted image is NULL. <%s>", cpl_error_get_message());
249  return NULL;
250  }
251  cpl_image_delete(eflat_real);
252 
253 
254  return flat_real;
255 }
256 
257 
265 /*--------------------------------------------------------------------------*/
266 cpl_image *omega_mirror_edges(cpl_image *image, int dx, int dy)
267 {
268 
269  int xx = 0;
270  int yy = 0;
271  int xs = 0;
272  int ys = 0;
273  int inrow = 1;
274  int outrow = 1;
275  int i =0;
276  int j = 0;
277 
278  float *data;
279  float *out_data;
280 
281 
282  cpl_image *big_image;
283 
284 
285 
286  xs = cpl_image_get_size_x(image);
287  ys = cpl_image_get_size_y(image);
288 
289  xx = xs+(2*dx);
290  yy = ys+(2*dy);
291 
292  data = cpl_image_get_data_float(image);
293 
294  big_image = cpl_image_new(xx, yy, CPL_TYPE_FLOAT);
295  out_data = cpl_image_get_data_float(big_image);
296 
297  for (j=0; j<ys ; j++){
298  inrow = j*xs;
299  outrow = (j+dy)*xx;
300 
301  for (i=0; i<xs ; i++){
302  out_data[outrow+dx+i] = data[inrow+i];
303  }
304 
305  for (i=0; i<dx; i++){
306  out_data[outrow+i] = data[inrow+dx-i-1];
307  out_data[outrow+xs+dx+i] = data[inrow+xs-i-1];
308 
309  }
310  }
311 
312  for (j=0; j<dy ; j++) {
313 
314  for (i=0; i<xx; i++) {
315  out_data[j*xx+i] = out_data[(2*dy-j-1)*xx+i];
316  out_data[(yy-j-1)*xx+i] = out_data[(yy-2*dy+j)*xx+i];
317  }
318  }
319 
320  return big_image;
321 }
322 
323