99from tigre .utilities .filtering import filtering
1010
1111
12-
1312def 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