NFFT Logo 3.2.3
inverse_radon.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002, 2012 Jens Keiner, Stefan Kunis, Daniel Potts
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free Software
6  * Foundation; either version 2 of the License, or (at your option) any later
7  * version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 51
16  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 /* $Id: inverse_radon.c 3896 2012-10-10 12:19:26Z tovo $ */
20 
39 #include "config.h"
40 
41 #include <stdio.h>
42 #include <math.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #ifdef HAVE_COMPLEX_H
46 #include <complex.h>
47 #endif
48 
49 #include "nfft3util.h"
50 #include "nfft3.h"
51 
53 /*#define KERNEL(r) 1.0 */
54 #define KERNEL(r) (1.0-fabs((double)(r))/((double)R/2))
55 
59 static int polar_grid(int T, int R, double *x, double *w)
60 {
61  int t, r;
62  double W=(double)T*(((double)R/2.0)*((double)R/2.0)+1.0/4.0);
63 
64  for(t=-T/2; t<T/2; t++)
65  {
66  for(r=-R/2; r<R/2; r++)
67  {
68  x[2*((t+T/2)*R+(r+R/2))+0] = (double)r/R*cos(PI*t/T);
69  x[2*((t+T/2)*R+(r+R/2))+1] = (double)r/R*sin(PI*t/T);
70  if (r==0)
71  w[(t+T/2)*R+(r+R/2)] = 1.0/4.0/W;
72  else
73  w[(t+T/2)*R+(r+R/2)] = fabs((double)r)/W;
74  }
75  }
76 
77  return 0;
78 }
79 
83 static int linogram_grid(int T, int R, double *x, double *w)
84 {
85  int t, r;
86  double W=(double)T*(((double)R/2.0)*((double)R/2.0)+1.0/4.0);
87 
88  for(t=-T/2; t<T/2; t++)
89  {
90  for(r=-R/2; r<R/2; r++)
91  {
92  if(t<0)
93  {
94  x[2*((t+T/2)*R+(r+R/2))+0] = (double)r/R;
95  x[2*((t+T/2)*R+(r+R/2))+1] = (double)4*(t+T/4)/T*r/R;
96  }
97  else
98  {
99  x[2*((t+T/2)*R+(r+R/2))+0] = -(double)4*(t-T/4)/T*r/R;
100  x[2*((t+T/2)*R+(r+R/2))+1] = (double)r/R;
101  }
102  if (r==0)
103  w[(t+T/2)*R+(r+R/2)] = 1.0/4.0/W;
104  else
105  w[(t+T/2)*R+(r+R/2)] = fabs((double)r)/W;
106  }
107  }
108 
109  return 0;
110 }
111 
116 int Inverse_Radon_trafo(int (*gridfcn)(), int T, int R, double *Rf, int NN, double *f, int max_i)
117 {
118  int j,k;
119  nfft_plan my_nfft_plan;
120  solver_plan_complex my_infft_plan;
122  fftw_complex *fft;
123  fftw_plan my_fftw_plan;
125  int t,r;
126  double *x, *w;
127  int l;
129  int N[2],n[2];
130  int M=T*R;
131 
132  N[0]=NN; n[0]=2*N[0];
133  N[1]=NN; n[1]=2*N[1];
134 
135  fft = (fftw_complex *)nfft_malloc(R*sizeof(fftw_complex));
136  my_fftw_plan = fftw_plan_dft_1d(R,fft,fft,FFTW_FORWARD,FFTW_MEASURE);
137 
138  x = (double *)nfft_malloc(2*T*R*(sizeof(double)));
139  if (x==NULL)
140  return -1;
141 
142  w = (double *)nfft_malloc(T*R*(sizeof(double)));
143  if (w==NULL)
144  return -1;
145 
147  nfft_init_guru(&my_nfft_plan, 2, N, M, n, 4,
148  PRE_PHI_HUT| PRE_PSI| MALLOC_X | MALLOC_F_HAT| MALLOC_F| FFTW_INIT | FFT_OUT_OF_PLACE,
149  FFTW_MEASURE| FFTW_DESTROY_INPUT);
150 
152  solver_init_advanced_complex(&my_infft_plan,(nfft_mv_plan_complex*)(&my_nfft_plan), CGNR | PRECOMPUTE_WEIGHT);
153 
155  gridfcn(T,R,x,w);
156  for(j=0;j<my_nfft_plan.M_total;j++)
157  {
158  my_nfft_plan.x[2*j+0] = x[2*j+0];
159  my_nfft_plan.x[2*j+1] = x[2*j+1];
160  if (j%R)
161  my_infft_plan.w[j] = w[j];
162  else
163  my_infft_plan.w[j] = 0.0;
164  }
165 
167  if(my_nfft_plan.nfft_flags & PRE_LIN_PSI)
168  nfft_precompute_lin_psi(&my_nfft_plan);
169 
170  if(my_nfft_plan.nfft_flags & PRE_PSI)
171  nfft_precompute_psi(&my_nfft_plan);
172 
173  if(my_nfft_plan.nfft_flags & PRE_FULL_PSI)
174  nfft_precompute_full_psi(&my_nfft_plan);
175 
177  for(t=0; t<T; t++)
178  {
179 /* for(r=0; r<R/2; r++)
180  fft[r] = cexp(I*PI*r)*Rf[t*R+(r+R/2)];
181  for(r=0; r<R/2; r++)
182  fft[r+R/2] = cexp(I*PI*r)*Rf[t*R+r];
183  */
184 
185  for(r=0; r<R; r++)
186  fft[r] = Rf[t*R+r] + _Complex_I*0.0;
187 
188  nfft_fftshift_complex(fft, 1, &R);
189  fftw_execute(my_fftw_plan);
190  nfft_fftshift_complex(fft, 1, &R);
191 
192  my_infft_plan.y[t*R] = 0.0;
193  for(r=-R/2+1; r<R/2; r++)
194  my_infft_plan.y[t*R+(r+R/2)] = fft[r+R/2]/KERNEL(r);
195  }
196 
198  for(k=0;k<my_nfft_plan.N_total;k++)
199  my_infft_plan.f_hat_iter[k] = 0.0 + _Complex_I*0.0;
200 
202  solver_before_loop_complex(&my_infft_plan);
203 
204  if (max_i<1)
205  {
206  l=1;
207  for(k=0;k<my_nfft_plan.N_total;k++)
208  my_infft_plan.f_hat_iter[k] = my_infft_plan.p_hat_iter[k];
209  }
210  else
211  {
212  for(l=1;l<=max_i;l++)
213  {
214  solver_loop_one_step_complex(&my_infft_plan);
215  /*if (sqrt(my_infft_plan.dot_r_iter)<=1e-12) break;*/
216  }
217  }
218  /*printf("after %d iteration(s): weighted 2-norm of original residual vector = %g\n",l-1,sqrt(my_infft_plan.dot_r_iter));*/
219 
221  for(k=0;k<my_nfft_plan.N_total;k++)
222  f[k] = creal(my_infft_plan.f_hat_iter[k]);
223 
225  fftw_destroy_plan(my_fftw_plan);
226  nfft_free(fft);
227  solver_finalize_complex(&my_infft_plan);
228  nfft_finalize(&my_nfft_plan);
229  nfft_free(x);
230  nfft_free(w);
231  return 0;
232 }
233 
236 int main(int argc,char **argv)
237 {
238  int (*gridfcn)();
239  int T, R;
240  FILE *fp;
241  int N;
242  double *Rf, *iRf;
243  int max_i;
245  if( argc!=6 )
246  {
247  printf("inverse_radon gridfcn N T R max_i\n");
248  printf("\n");
249  printf("gridfcn \"polar\" or \"linogram\" \n");
250  printf("N image size NxN \n");
251  printf("T number of slopes \n");
252  printf("R number of offsets \n");
253  printf("max_i number of iterations \n");
254  exit(-1);
255  }
256 
257  if (strcmp(argv[1],"polar") == 0)
258  gridfcn = polar_grid;
259  else
260  gridfcn = linogram_grid;
261 
262  N = atoi(argv[2]);
263  T = atoi(argv[3]);
264  R = atoi(argv[4]);
265  /*printf("N=%d, %s grid with T=%d, R=%d. \n",N,argv[1],T,R);*/
266  max_i = atoi(argv[5]);
267 
268  Rf = (double *)nfft_malloc(T*R*(sizeof(double)));
269  iRf = (double *)nfft_malloc(N*N*(sizeof(double)));
270 
272  fp=fopen("sinogram_data.bin","rb");
273  if (fp==NULL)
274  return(-1);
275  fread(Rf,sizeof(double),T*R,fp);
276  fclose(fp);
277 
279  Inverse_Radon_trafo(gridfcn,T,R,Rf,N,iRf,max_i);
280 
282  fp=fopen("output_data.bin","wb+");
283  if (fp==NULL)
284  return(-1);
285  fwrite(iRf,sizeof(double),N*N,fp);
286  fclose(fp);
287 
289  nfft_free(Rf);
290  nfft_free(iRf);
291 
292  return EXIT_SUCCESS;
293 }

Generated on Tue Apr 30 2013 by Doxygen 1.8.1