3 ;; pbourke linearly interpolating points within a box
4 (def-generator (interpolate (rank type
))
5 (let ((params (ecase rank
9 `(defun ,name
(vol ,@params
)
10 "Linear interpolation of a value."
12 ((simple-array ,long-type
,rank
) vol
)
13 (single-float ,@params
)
14 (values ,long-type
&optional
))
15 (let ((zero ,(coerce 0 long-type
))
16 (one ,(coerce 1 long-type
)))
18 (1 `(multiple-value-bind (i x
)
22 (if (array-in-bounds-p vol x
)
30 (2 `(multiple-value-bind (i x
)
32 (multiple-value-bind (j y
)
37 (if (array-in-bounds-p vol y x
)
50 (3 `(multiple-value-bind (i x
)
52 (multiple-value-bind (j y
)
54 (multiple-value-bind (k z
)
60 (if (array-in-bounds-p vol z y x
)
63 (let ((ooo (ref 0 0 0))
81 (* iii x y z
)))))))))))))
83 (def-interpolate-rank-type 1 sf
)
85 (let ((a (make-array 3
86 :element-type
'single-float
87 :initial-contents
'(1.0
2.0 3.0))))
88 (interpolate-1-sf a
1.5))
90 (defmacro def-interpolate-functions
(ranks types
)
93 (loop for rank in ranks do
94 (loop for type in types do
95 (push `(def-interpolate-rank-type ,rank
,type
)
97 (loop for rank in ranks do
98 (loop for type in types do
99 (let ((long-type (get-long-type type
)))
100 (push `((simple-array ,long-type
,rank
)
102 "interpolate-~a-~a" rank type
)
103 a
,@(subseq '(x y z
) 0 rank
)))
105 (store-new-function (format-symbol "interpolate"))
107 (defun interpolate (a x
&optional y z
)
108 (declare ((or null single-float
) x y z
))
111 (t (error "type not supported.")))))))
113 (def-interpolate-functions (1 2 3) (sf df csf cdf
))
117 (a (make-array (list n n n
)
118 :element-type
'single-float
))
119 (a1 (sb-ext:array-storage-vector a
)))
120 (dotimes (i (length a1
))
121 (setf (aref a1 i
) (* 1s0 i
)))
122 (interpolate-3-sf a
1.2s0
1.3s0
1.2s0
)
123 (interpolate a
1.2s0
1.3s0
1.2s0
))
126 (def-generator (resample-half (rank type
))
128 (declare ((simple-array ,long-type
,rank
) vol
)
129 (values (simple-array ,long-type
,rank
) &optional
))
130 (let ((dims (array-dimensions vol
)))
133 (1 `(destructuring-bind (x)
135 (let* ((xx (floor x
2))
136 (small (make-array (list xx
)
137 :element-type
(quote ,long-type
))))
138 (do-region ((i) (xx))
142 (2 `(destructuring-bind (y x
)
144 (let* ((xx (floor x
2))
146 (small (make-array (list yy xx
)
147 :element-type
(quote ,long-type
))))
148 (do-region ((j i
) (yy xx
))
149 (setf (aref small j i
)
150 (aref vol
(* j
2) (* i
2))))
152 (3 `(destructuring-bind (z y x
)
154 (let* ((xx (floor x
2))
157 (small (make-array (list zz yy xx
)
158 :element-type
(quote ,long-type
))))
159 (do-region ((k j i
) (zz yy xx
))
160 (setf (aref small k j i
)
161 (aref vol
(* k
2) (* j
2) (* i
2))))
164 (def-resample-half-rank-type 1 ub8
)
166 (defmacro def-resample-half-functions
(ranks types
)
168 (loop for rank in ranks do
169 (loop for type in types do
170 (push `(def-resample-half-rank-type ,rank
,type
)
175 (def-resample-half-functions (1 2 3) (ub8 sf df cdf csf
))
179 (let ((l '(1 2 3 4 5 6)))
180 (make-array (length l
) :element-type
'(unsigned-byte 8)
181 :initial-contents l
)))
185 ;; The following function is meant to resample an angular PSF that has
186 ;; been calculated with too much resolution. The important thing is
187 ;; that the central sample stays central. Consider a 1D array with n
188 ;; elements and stepsize dx: The length of the array will be
189 ;; X=n*dx. There are c=center(n) samples right of the center and b
190 ;; samples (with b+c=n) left of the center. The new step size dx'
191 ;; suggests that c'=(floor c*dx dx') samples are needed right of the
192 ;; center and analogously b' samples left of the center. The size of
193 ;; the new array is n'=b'+c'. The float coordinate x' for the new
194 ;; sample is (i+b')*dx' where i runs from -b' below c'. The central
195 ;; sample is i=0. This following function implements this scheme for 3
197 (def-generator (resample (rank type
))
198 (let ((par-deltas (ecase rank
(1 `(dx)) (2 `(dx dy
)) (3 `(dx dy dz
))))
199 (par-deltas^
(ecase rank
(1 `(dx^
)) (2 `(dx^ dy^
)) (3 `(dx^ dy^ dz^
)))))
200 `(defun ,name
(vol ,@par-deltas
,@par-deltas^
)
201 "Resample by linear interpolation. Ensure that the
202 former center stays in the center."
203 (declare ((simple-array ,long-type
,rank
) vol
)
204 (single-float ,@par-deltas
,@par-deltas^
)
205 (values (simple-array ,long-type
,rank
) &optional
))
206 (labels ((center (n) ;; give the index of the central sample
208 (values fixnum
&optional
))
209 (let ((c (if (evenp n
)
213 (dims (n d d^
) ;; calculate new array size from old one and deltas
216 (values fixnum fixnum fixnum
&optional
))
217 (let* ((c (center n
))
219 (c^
(floor (* c d
) d^
))
220 (b^
(floor (* b d
) d^
))
223 (macrolet ((coord (i dir
) ;; convert index into float coordinate
224 `(* (/ ,(format-symbol "D~a^" dir
)
225 ,(format-symbol "D~a" dir
))
226 (+ ,i
,(format-symbol "B~a" dir
)))))
229 `(destructuring-bind (x)
230 (array-dimensions vol
)
231 (multiple-value-bind (bx cx nx
)
233 (let ((result (make-array (list nx
)
234 :element-type
(quote ,long-type
))))
235 (do-region ((i) (cx) ((- bx
)))
236 (let ((xx (coord i x
)))
237 (setf (aref result
(+ bx i
))
238 (,(format-symbol "interpolate-~a-~a" rank type
) vol xx
))))
241 `(destructuring-bind (y x
)
242 (array-dimensions vol
)
243 (multiple-value-bind (bx cx nx
)
245 (multiple-value-bind (by cy ny
)
247 (let ((result (make-array (list ny nx
)
248 :element-type
(quote ,long-type
))))
249 (do-region ((j i
) (cy cx
) ((- by
) (- bx
)))
250 (let ((xx (coord i x
))
252 (setf (aref result
(+ by j
) (+ bx i
))
253 (,(format-symbol "interpolate-~a-~a" rank type
) vol xx yy
))))
256 `(destructuring-bind (z y x
)
257 (array-dimensions vol
)
258 (multiple-value-bind (bx cx nx
)
260 (multiple-value-bind (by cy ny
)
262 (multiple-value-bind (bz cz nz
)
264 (let ((result (make-array (list nz ny nx
)
265 :element-type
(quote ,long-type
))))
266 (do-region ((k j i
) (cz cy cx
) ((- bz
) (- by
) (- bx
)))
267 (let ((xx (coord i x
))
270 (setf (aref result
(+ bz k
) (+ by j
) (+ bx i
))
271 (,(format-symbol "interpolate-~a-~a" rank type
) vol xx yy zz
))))
274 (def-resample-rank-type 1 sf
)
276 (let ((a (make-array 3 :element-type
'single-float
:initial-contents
'(1s0 2s0
3s0
))))
277 (resample-1-sf a
1.0 .5))
279 (defmacro def-resample-functions
(ranks types
)
281 (loop for rank in ranks do
282 (loop for type in types do
283 (push `(def-resample-rank-type ,rank
,type
)
287 (def-resample-functions (1 2 3) (sf df csf cdf
))
291 (let* ((s0 (convert3-ub8/cdf-complex
(draw-sphere-ub8 12d0
41 239 232)))
296 (s1 (resample3-cdf s0 dr dr dz ddr ddr ddz
))
297 (s2 (resample3-cdf s1 ddr ddr ddz dr dr dz
)))
298 (save-stack-ub8 "/home/martin/tmp/s0/" (normalize3-cdf/ub8-realpart s0
))
299 (save-stack-ub8 "/home/martin/tmp/s1/" (normalize3-cdf/ub8-realpart s1
))
300 (save-stack-ub8 "/home/martin/tmp/s2/" (normalize3-cdf/ub8-realpart s2
))
301 (save-stack-ub8 "/home/martin/tmp/s2-s0" (normalize3-cdf/ub8-realpart
(.- s0 s2
)))))
304 (def-generator (cross-section-xz (type))
305 `(defun ,name
(a &optional
(y (floor (array-dimension a
1) 2)))
306 (declare ((simple-array ,long-type
3) a
)
308 (values (simple-array ,long-type
2)
310 (destructuring-bind (z y-size x
)
312 (unless (<= 0 y
(1- y-size
))
313 (error "Y is out of bounds."))
314 (let ((b (make-array (list z x
)
315 :element-type
(quote ,long-type
))))
316 (do-region ((j i
) (z x
))
322 (def-cross-section-xz-type sf
)
325 (let ((a (make-array (list 2 2 2) :element-type
'single-float
)))
326 (cross-section-xz-sf a
))
328 (defmacro def-cross-section-xz-functions
(types)
330 ,@(loop for type in types collect
331 `(def-cross-section-xz-type ,type
))
332 (store-new-function (format-symbol "cross-section-xz"))
333 (defun cross-section-xz (a &optional
(y (floor (array-dimension a
1) 2)))
336 ,@(loop for type in types collect
337 (let ((long-type (get-long-type type
)))
338 `((simple-array ,long-type
3) (,(format-symbol
339 "cross-section-xz-~a" type
) a y
))))
340 (t (error "type not supported."))))))
342 (def-cross-section-xz-functions (ub8 sf df csf cdf
))
345 (let ((a (make-array (list 2 2 2) :element-type
'single-float
)))
346 (cross-section-xz a
))
348 (def-generator (decimate-xy (type))
349 `(defun ,name
(dx vol
)
350 "Increase transversal sampling distance by odd integer factor DX."
352 ((simple-array ,long-type
3) vol
)
353 (values (simple-array ,long-type
3) &optional
))
354 (unless (eq (mod dx
2) 1)
355 (error "Factor DX has to be odd."))
356 (destructuring-bind (z y x
)
357 (array-dimensions vol
)
358 (let* ((dx2 (* dx dx
))
361 (result (make-array (list z ny nx
)
362 :element-type
(quote ,long-type
))))
363 (declare (integer nx ny
))
364 (do-region ((k j i
) (nx ny z
))
365 (let ((sum (coerce 0 (quote ,long-type
))))
366 (do-region ((jj ii
) (dx dx
))
371 (setf (aref result k j i
) ,(if (eq type
'ub8
)
376 (defmacro def-decimate-xz-functions
(types)
378 ,@(loop for type in types collect
379 `(def-decimate-xy-type ,type
))))
381 (def-decimate-xz-functions (ub8 sf df csf cdf
))
384 ;; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
391 ;; output size floor(n,dx)=4
392 ;; position of q: ii=3, i=0: dx*i+ii=5*0+3=3
393 ;; position of o: ii=1, i=1: dx*i+ii=5+1=6
396 (decimate-xy-ub8 5 (make-array (list 2 10 10)
397 :element-type
'(unsigned-byte 8)))