Skip to content

Commit dfa6c65

Browse files
authored
Merge pull request #519 from sysiphus511/patch-1
Update single_pass_algorithms.py
2 parents 74e9659 + 6eb92bf commit dfa6c65

File tree

1 file changed

+94
-7
lines changed

1 file changed

+94
-7
lines changed

Python/tigre/algorithms/single_pass_algorithms.py

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from tigre.utilities.filtering import filtering
1010

1111

12-
1312
def FDK(proj, geo, angles, **kwargs):
1413
"""
1514
solves CT image reconstruction.
@@ -73,24 +72,111 @@ def FDK(proj, geo, angles, **kwargs):
7372
verbose = kwargs["verbose"] if "verbose" in kwargs else False
7473

7574
gpuids = kwargs["gpuids"] if "gpuids" in kwargs else None
76-
parker = kwargs["parker"] if "parker" in kwargs else False
75+
dowang = kwargs["dowang"] if "dowang" in kwargs else False
76+
77+
def zeropadding(proj, geo):
78+
zgeo = copy.deepcopy(geo)
79+
padwidth = int(2 * geo.offDetector[1] / geo.dDetector[1])
80+
zgeo.offDetector[1] = geo.offDetector[1] - \
81+
padwidth / 2 * geo.dDetector[1]
82+
zgeo.nDetector[1] = abs(padwidth) + geo.nDetector[1]
83+
zgeo.sDetector[1] = zgeo.nDetector[1] * zgeo.dDetector[1]
84+
85+
theta = (geo.sDetector[1] / 2 - abs(geo.offDetector[1])
86+
) * np.sign(geo.offDetector[1])
87+
88+
print(padwidth, zgeo.nDetector[1], zgeo.offDetector[1], theta)
89+
if geo.offDetector[1] > 0:
90+
zproj = np.zeros(
91+
(proj.shape[0] , proj.shape[1], proj.shape[2]+ padwidth), dtype=proj.dtype)
92+
for ii in range(proj.shape[0]):
93+
zproj[ii,:, :] = np.concatenate(
94+
(np.zeros((proj.shape[1], padwidth)), proj[:, :, ii]), axis=1)
95+
else:
96+
zproj = np.zeros(
97+
(proj.shape[0] , proj.shape[1] , proj.shape[2]+ abs(padwidth)), dtype=proj.dtype)
98+
for ii in range(proj.shape[0]):
99+
zproj[ii, :, :] = np.concatenate(
100+
(proj[ ii,:, :], np.zeros((proj.shape[1], abs(padwidth)))), axis=1)
101+
102+
return zproj, zgeo, theta
103+
104+
def preweighting2(proj, geo, theta):
105+
"""
106+
Preweighting using Wang function
107+
108+
:param proj: np.array(dtype=float32),
109+
Data input in the form of 3d
110+
111+
:param geo: tigre.utilities.geometry.Geometry
112+
Geometry of detector and image (see examples/Demo code)
113+
114+
:param theta: np.array(dtype=float32)
115+
Angles of projection, shape = (nangles,3) or (nangles,)
116+
117+
:return: np.array(dtype=float32), np.array(dtype=float32)
118+
119+
"""
120+
offset = geo.offDetector[1]
121+
offset = offset + (geo.DSD / geo.DSO) #* geo.COR
122+
123+
us = np.arange(-geo.nDetector[1]/2 + 0.5, geo.nDetector[1] /
124+
2 - 0.5 + 1) * geo.dDetector[1] + abs(offset)
125+
us = us * geo.DSO / geo.DSD
126+
abstheta = np.abs(theta * geo.DSO / geo.DSD)
127+
128+
w = np.ones(proj[0, :, :].shape)
129+
130+
for ii in range(geo.nDetector[1]):
131+
t = us[ii]
132+
if np.abs(t) <= abstheta:
133+
w[:,ii] = 0.5 * (np.sin((np.pi / 2) * np.arctan(t /
134+
geo.DSO) / (np.arctan(abstheta / geo.DSO))) + 1)
135+
if t < -abstheta:
136+
w[:,ii] = 0
137+
138+
if theta < 0:
139+
w = np.fliplr(w)
140+
141+
proj_w = proj.copy() # preallocation
142+
for ii in range(proj.shape[0]):
143+
proj_w[ii, :, :,] = proj[ii, :, :] * w * 2
144+
145+
return proj_w, w
146+
147+
148+
if dowang:
149+
print('FDK: applying detector offset weights')
150+
# Zero-padding to avoid FFT-induced aliasing
151+
zproj, zgeo, theta = zeropadding(proj, geo)
152+
# Preweighting using Wang function to save memory
153+
proj, _ = preweighting2(zproj, zgeo, theta)
154+
155+
# Replace original proj and geo
156+
# proj = proj_w;
157+
geo = zgeo
158+
159+
print(geo)
160+
print(proj.shape)
77161
geo = copy.deepcopy(geo)
78162
geo.check_geo(angles)
79163
geo.checknans()
80164
geo.filter = kwargs["filter"] if "filter" in kwargs else None
81165
# Weight
82166
proj_filt = np.zeros(proj.shape, dtype=np.float32)
83167
xv = np.arange((-geo.nDetector[1] / 2) + 0.5,
84-
1 + (geo.nDetector[1] / 2) - 0.5) * geo.dDetector[1]
168+
1 + (geo.nDetector[1] / 2) - 0.5) * geo.dDetector[1]
85169
yv = np.arange((-geo.nDetector[0] / 2) + 0.5,
86-
1 + (geo.nDetector[0] / 2) - 0.5) * geo.dDetector[0]
170+
1 + (geo.nDetector[0] / 2) - 0.5) * geo.dDetector[0]
87171
(yy, xx) = np.meshgrid(xv, yv)
88172

89173
w = geo.DSD[0] / np.sqrt((geo.DSD[0] ** 2 + xx ** 2 + yy ** 2))
90174
np.multiply(proj, w, out=proj_filt)
91175

92-
proj_filt = filtering(proj_filt, geo, angles, parker=parker, verbose=verbose)
93-
176+
proj_filt = filtering(proj_filt, geo, angles,
177+
parker=False, verbose=verbose)
178+
# geo.proj = proj_filt
179+
94180
return Atb(proj_filt, geo, geo.angles, "FDK", gpuids=gpuids)
95181

96182

@@ -105,5 +191,6 @@ def fbp(proj, geo, angles, **kwargs): # noqa: D103
105191
geox.check_geo(angles)
106192
verbose = kwargs["verbose"] if "verbose" in kwargs else False
107193
gpuids = kwargs["gpuids"] if "gpuids" in kwargs else None
108-
proj_filt = filtering(copy.deepcopy(proj), geox, angles, parker=False, verbose=verbose)
194+
proj_filt = filtering(copy.deepcopy(proj), geox,
195+
angles, parker=False, verbose=verbose)
109196
return Atb(proj_filt, geo, angles, gpuids=gpuids) * geo.DSO / geo.DSD

0 commit comments

Comments
 (0)