-
Notifications
You must be signed in to change notification settings - Fork 204
/
Copy pathfiltering.py
94 lines (72 loc) · 3.04 KB
/
filtering.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from __future__ import division
from __future__ import print_function
from numpy.core.arrayprint import dtype_is_implied
from tigre.utilities.parkerweight import parkerweight
import numpy as np
from scipy.fft import fft, ifft
import warnings
import numpy as np
from tigre.utilities.parkerweight import parkerweight
# TODO: Fix parker
def filtering(proj, geo, angles, parker, verbose=False):
if parker:
proj=parkerweight(proj.transpose(0,2,1),geo,angles,parker).transpose(0,2,1)
filt_len=max(64,2**nextpow2(2*max(geo.nDetector)))
ramp_kernel=ramp_flat(filt_len)
d=1
filt=filter(geo.filter,ramp_kernel[0],filt_len,d,verbose=verbose)
filt=np.kron(np.ones((np.int64(geo.nDetector[0]),1),dtype=np.float32),filt)
padding = int((filt_len-geo.nDetector[1])//2 )
scale_factor = (geo.DSD[0]/geo.DSO[0]) * (2 * np.pi/ len(angles)) / ( 4 * geo.dDetector[0] )
#filter 2 projection at a time packing in to complex container
fproj=np.empty((geo.nDetector[0],filt_len),dtype=np.complex64)
for i in range(0,angles.shape[0]-1,2):
fproj.fill(0)
fproj.real[:,padding:padding+geo.nDetector[1]]=proj[i]
fproj.imag[:,padding:padding+geo.nDetector[1]]=proj[i+1]
fproj=fft(fproj,axis=1)
fproj=fproj*filt
fproj=ifft(fproj,axis=1)
proj[i]=fproj.real[:,padding:padding+geo.nDetector[1]] * scale_factor
proj[i+1]=fproj.imag[:,padding:padding+geo.nDetector[1]] * scale_factor
#if odd number of projections filter last solo
if angles.shape[0] % 2:
fproj.fill(0)
fproj.real[:,padding:padding+geo.nDetector[1]]=proj[angles.shape[0]-1]
fproj=fft(fproj,axis=1)
fproj=fproj*filt
fproj=np.real(ifft(fproj,axis=1))
proj[angles.shape[0]-1]=fproj[:,padding:padding+geo.nDetector[1]] * scale_factor
return proj
def ramp_flat(n, verbose=False):
nn = np.arange(-n / 2, n / 2)
h = np.zeros(nn.shape, dtype=np.float32)
h[int(n / 2)] = 1 / 4
odd = nn % 2 == 1
h[odd] = -1 / (np.pi * nn[odd]) ** 2
return h, nn
def filter(filter, kernel, order, d, verbose=False):
f_kernel = abs(np.fft.fft(kernel)) * 2
filt = f_kernel[: int((order / 2) + 1)]
w = 2 * np.pi * np.arange(len(filt)) / order
if filter in {"ram_lak", None}:
if filter is None and verbose:
warnings.warn("no filter selected, using default ram_lak")
elif filter == "shepp_logan":
filt[1:] *= np.sin(w[1:] / (2 * d)) / (w[1:] / (2 * d))
elif filter == "cosine":
filt[1:] *= np.cos(w[1:] / (2 * d))
elif filter == "hamming":
filt[1:] *= 0.54 + 0.46 * np.cos(w[1:] / d)
elif filter == "hann":
filt[1:] *= (1 + np.cos(w[1:] / d)) / 2
else:
raise ValueError("filter not recognized: " + str(filter))
filt[w > np.pi * d] = 0
filt = np.hstack((filt, filt[1:-1][::-1]))
return filt.astype(np.float32)
def nextpow2(n):
i = 1
while (2 ** i) < n:
i += 1
return i