NFFT  3.3.0
inverse_radon.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002, 2015 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$ */
20 
40 #include <stdio.h>
41 #include <math.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <complex.h>
45 
46 #define NFFT_PRECISION_DOUBLE
47 
48 #include "nfft3mp.h"
49 
51 /*#define KERNEL(r) 1.0 */
52 #define KERNEL(r) (NFFT_K(1.0)-NFFT_M(fabs)((NFFT_R)(r))/((NFFT_R)S/2))
53 
57 static int polar_grid(int T, int S, NFFT_R *x, NFFT_R *w)
58 {
59  int t, r;
60  NFFT_R W = (NFFT_R) T * (((NFFT_R) S / NFFT_K(2.0)) * ((NFFT_R) S / NFFT_K(2.0)) + NFFT_K(1.0) / NFFT_K(4.0));
61 
62  for (t = -T / 2; t < T / 2; t++)
63  {
64  for (r = -S / 2; r < S / 2; r++)
65  {
66  x[2 * ((t + T / 2) * S + (r + S / 2)) + 0] = (NFFT_R) r / (NFFT_R)(S) * NFFT_M(cos)(NFFT_KPI * (NFFT_R)(t) / (NFFT_R)(T));
67  x[2 * ((t + T / 2) * S + (r + S / 2)) + 1] = (NFFT_R) r / (NFFT_R)(S) * NFFT_M(sin)(NFFT_KPI * (NFFT_R)(t) / (NFFT_R)(T));
68  if (r == 0)
69  w[(t + T / 2) * S + (r + S / 2)] = NFFT_K(1.0) / NFFT_K(4.0) / W;
70  else
71  w[(t + T / 2) * S + (r + S / 2)] = NFFT_M(fabs)((NFFT_R) r) / W;
72  }
73  }
74 
75  return 0;
76 }
77 
81 static int linogram_grid(int T, int S, NFFT_R *x, NFFT_R *w)
82 {
83  int t, r;
84  NFFT_R W = (NFFT_R) T * (((NFFT_R) S / NFFT_K(2.0)) * ((NFFT_R) S / NFFT_K(2.0)) + NFFT_K(1.0) / NFFT_K(4.0));
85 
86  for (t = -T / 2; t < T / 2; t++)
87  {
88  for (r = -S / 2; r < S / 2; r++)
89  {
90  if (t < 0)
91  {
92  x[2 * ((t + T / 2) * S + (r + S / 2)) + 0] = (NFFT_R) r / (NFFT_R)(S);
93  x[2 * ((t + T / 2) * S + (r + S / 2)) + 1] = NFFT_K(4.0) * ((NFFT_R)(t) + (NFFT_R)(T) / NFFT_K(4.0)) / (NFFT_R)(T) * (NFFT_R)(r)
94  / (NFFT_R)(S);
95  }
96  else
97  {
98  x[2 * ((t + T / 2) * S + (r + S / 2)) + 0] = -NFFT_K(4.0) * ((NFFT_R)(t) - (NFFT_R)(T) / NFFT_K(4.0)) / (NFFT_R)(T)
99  * (NFFT_R)(r) / (NFFT_R)(S);
100  x[2 * ((t + T / 2) * S + (r + S / 2)) + 1] = (NFFT_R) r / (NFFT_R)(S);
101  }
102  if (r == 0)
103  w[(t + T / 2) * S + (r + S / 2)] = NFFT_K(1.0) / NFFT_K(4.0) / W;
104  else
105  w[(t + T / 2) * S + (r + S / 2)] = NFFT_M(fabs)((NFFT_R) r) / W;
106  }
107  }
108 
109  return 0;
110 }
111 
116 static int inverse_radon_trafo(int (*gridfcn)(), int T, int S, NFFT_R *Rf, int NN, NFFT_R *f,
117  int max_i)
118 {
119  int j, k;
120  NFFT(plan) my_nfft_plan;
121  SOLVER(plan_complex) my_infft_plan;
123  NFFT_C *fft;
124  FFTW(plan) my_fftw_plan;
126  int t, r;
127  NFFT_R *x, *w;
128  int l;
130  int N[2], n[2];
131  int M = T * S;
132 
133  N[0] = NN;
134  n[0] = 2 * N[0];
135  N[1] = NN;
136  n[1] = 2 * N[1];
137 
138  fft = (NFFT_C *) NFFT(malloc)((size_t)(S) * sizeof(NFFT_C));
139  my_fftw_plan = FFTW(plan_dft_1d)(S, fft, fft, FFTW_FORWARD, FFTW_MEASURE);
140 
141  x = (NFFT_R *) NFFT(malloc)((size_t)(2 * T * S) * (sizeof(NFFT_R)));
142  if (x == NULL)
143  return EXIT_FAILURE;
144 
145  w = (NFFT_R *) NFFT(malloc)((size_t)(T * S) * (sizeof(NFFT_R)));
146  if (w == NULL)
147  return EXIT_FAILURE;
148 
150  NFFT(init_guru)(&my_nfft_plan, 2, N, M, n, 4,
151  PRE_PHI_HUT | PRE_PSI | MALLOC_X | MALLOC_F_HAT | MALLOC_F | FFTW_INIT
152  | FFT_OUT_OF_PLACE,
153  FFTW_MEASURE | FFTW_DESTROY_INPUT);
154 
156  SOLVER(init_advanced_complex)(&my_infft_plan,
157  (NFFT(mv_plan_complex)*) (&my_nfft_plan), CGNR | PRECOMPUTE_WEIGHT);
158 
160  gridfcn(T, S, x, w);
161  for (j = 0; j < my_nfft_plan.M_total; j++)
162  {
163  my_nfft_plan.x[2 * j + 0] = x[2 * j + 0];
164  my_nfft_plan.x[2 * j + 1] = x[2 * j + 1];
165  if (j % S)
166  my_infft_plan.w[j] = w[j];
167  else
168  my_infft_plan.w[j] = NFFT_K(0.0);
169  }
170 
172  if (my_nfft_plan.flags & PRE_LIN_PSI)
173  NFFT(precompute_lin_psi)(&my_nfft_plan);
174 
175  if (my_nfft_plan.flags & PRE_PSI)
176  NFFT(precompute_psi)(&my_nfft_plan);
177 
178  if (my_nfft_plan.flags & PRE_FULL_PSI)
179  NFFT(precompute_full_psi)(&my_nfft_plan);
180 
182  for (t = 0; t < T; t++)
183  {
184  /* for(r=0; r<R/2; r++)
185  fft[r] = cexp(I*NFFT_KPI*r)*Rf[t*R+(r+R/2)];
186  for(r=0; r<R/2; r++)
187  fft[r+R/2] = cexp(I*NFFT_KPI*r)*Rf[t*R+r];
188  */
189 
190  for (r = 0; r < S; r++)
191  fft[r] = Rf[t * S + r] + _Complex_I * NFFT_K(0.0);
192 
193  NFFT(fftshift_complex_int)(fft, 1, &S);
194  FFTW(execute)(my_fftw_plan);
195  NFFT(fftshift_complex_int)(fft, 1, &S);
196 
197  my_infft_plan.y[t * S] = NFFT_K(0.0);
198  for (r = -S / 2 + 1; r < S / 2; r++)
199  my_infft_plan.y[t * S + (r + S / 2)] = fft[r + S / 2] / KERNEL(r);
200  }
201 
203  for (k = 0; k < my_nfft_plan.N_total; k++)
204  my_infft_plan.f_hat_iter[k] = NFFT_K(0.0) + _Complex_I * NFFT_K(0.0);
205 
207  SOLVER(before_loop_complex)(&my_infft_plan);
208 
209  if (max_i < 1)
210  {
211  l = 1;
212  for (k = 0; k < my_nfft_plan.N_total; k++)
213  my_infft_plan.f_hat_iter[k] = my_infft_plan.p_hat_iter[k];
214  }
215  else
216  {
217  for (l = 1; l <= max_i; l++)
218  {
219  SOLVER(loop_one_step_complex)(&my_infft_plan);
220  /*if (sqrt(my_infft_plan.dot_r_iter)<=1e-12) break;*/
221  }
222  }
223  /*printf("after %d iteration(s): weighted 2-norm of original residual vector = %g\n",l-1,sqrt(my_infft_plan.dot_r_iter));*/
224 
226  for (k = 0; k < my_nfft_plan.N_total; k++)
227  f[k] = NFFT_M(creal)(my_infft_plan.f_hat_iter[k]);
228 
230  FFTW(destroy_plan)(my_fftw_plan);
231  NFFT(free)(fft);
232  SOLVER(finalize_complex)(&my_infft_plan);
233  NFFT(finalize)(&my_nfft_plan);
234  NFFT(free)(x);
235  NFFT(free)(w);
236  return 0;
237 }
238 
241 int main(int argc, char **argv)
242 {
243  int (*gridfcn)();
244  int T, S;
245  FILE *fp;
246  int N;
247  NFFT_R *Rf, *iRf;
248  int max_i;
250  if (argc != 6)
251  {
252  printf("inverse_radon gridfcn N T R max_i\n");
253  printf("\n");
254  printf("gridfcn \"polar\" or \"linogram\" \n");
255  printf("N image size NxN \n");
256  printf("T number of slopes \n");
257  printf("R number of offsets \n");
258  printf("max_i number of iterations \n");
259  exit(EXIT_FAILURE);
260  }
261 
262  if (strcmp(argv[1], "polar") == 0)
263  gridfcn = polar_grid;
264  else
265  gridfcn = linogram_grid;
266 
267  N = atoi(argv[2]);
268  T = atoi(argv[3]);
269  S = atoi(argv[4]);
270  /*printf("N=%d, %s grid with T=%d, R=%d. \n",N,argv[1],T,R);*/
271  max_i = atoi(argv[5]);
272 
273  Rf = (NFFT_R *) NFFT(malloc)((size_t)(T * S) * (sizeof(NFFT_R)));
274  iRf = (NFFT_R *) NFFT(malloc)((size_t)(N * N) * (sizeof(NFFT_R)));
275 
277  fp = fopen("sinogram_data.bin", "rb");
278  if (fp == NULL)
279  return EXIT_FAILURE;
280  fread(Rf, sizeof(NFFT_R), (size_t)(T * S), fp);
281  fclose(fp);
282 
284  inverse_radon_trafo(gridfcn, T, S, Rf, N, iRf, max_i);
285 
287  fp = fopen("output_data.bin", "wb+");
288  if (fp == NULL)
289  return EXIT_FAILURE;
290  fwrite(iRf, sizeof(NFFT_R), (size_t)(N * N), fp);
291  fclose(fp);
292 
294  NFFT(free)(Rf);
295  NFFT(free)(iRf);
296 
297  return EXIT_SUCCESS;
298 }
static int max_i(int a, int b)
max
Definition: fastsum.c:48
static int polar_grid(int T, int S, NFFT_R *x, NFFT_R *w)
generates the points x with weights w for the polar grid with T angles and R offsets ...
Definition: inverse_radon.c:57
static void fft(int N, int M, int Z, fftw_complex *mem)
fft makes an 1D-ftt for every knot through all layers
static int linogram_grid(int T, int S, NFFT_R *x, NFFT_R *w)
generates the points x with weights w for the linogram grid with T slopes and R offsets ...
Definition: inverse_radon.c:81
#define KERNEL(r)
define weights of kernel function for discrete Radon transform
Definition: inverse_radon.c:52
static int inverse_radon_trafo(int(*gridfcn)(), int T, int S, NFFT_R *Rf, int NN, NFFT_R *f, int max_i)
computes the inverse discrete Radon transform of Rf on the grid given by gridfcn() with T angles and ...