2 (:use
:cl
:sb-alien
:sb-c-call
)
26 ;; for i in `cat vol.lisp|grep defconst|cut -d " " -f 2`;do echo \#:$i ;done
30 #+nil
(declaim (optimize (speed 3) (debug 1) (safety 1)))
31 (declaim (optimize (speed 2) (debug 3) (safety 3)))
33 (load-shared-object "/usr/lib/libfftw3.so.3")
35 (define-alien-routine ("fftw_plan_dft_3d" plan-dft-3d
)
41 (out (* double-float
))
45 ;; C-standard "row-major" order, so that the last dimension has the
46 ;; fastest-varying index in the array.
50 (defmacro do-rectangle
((j i ymin ymax xmin xmax
) &body body
)
51 "Loop through 2d points in ymin .. ymax-1. e.g. call with 0 y 0 x to
53 `(loop for
,j from
,ymin below
,ymax do
54 (loop for
,i from
,xmin below
,xmax do
57 (defmacro do-box
((k j i zmin zmax ymin ymax xmin xmax
) &body body
)
58 "Loop through 3d points e.g. call with 0 z 0 y 0 x to visit every
60 `(loop for
,k from
,zmin below
,zmax do
61 (loop for
,j from
,ymin below
,ymax do
62 (loop for
,i from
,xmin below
,xmax do
66 ;; fftshift3 /home/martin/usb/y2009/1123/1.lisp
67 (declaim (ftype (function ((simple-array (complex double-float
) (* * *)))
68 (values (simple-array (complex double-float
) (* * *))
72 (let ((out (make-array (array-dimensions in
)
73 :element-type
'(complex double-float
))))
74 (destructuring-bind (w2 w1 w0
)
79 (let* ((ii (if (> i
(/ w0
2))
82 (jj (if (> j
(/ w1
2))
85 (kk (if (> k
(/ w2
2))
88 (setf (aref out k j i
)
93 (define-alien-routine ("fftw_execute" execute
)
97 (defconstant +forward
+ 1)
98 (defconstant +backward
+ -
1)
99 (defconstant +estimate
+ (ash 1 6))
101 (declaim (ftype (function ((simple-array (complex double-float
) (* * *))
102 &key
(:forward boolean
))
103 (values (simple-array (complex double-float
) (* * *))
106 (defun ft3 (in &key
(forward t
))
107 (let ((dims (array-dimensions in
)))
108 (destructuring-bind (z y x
)
110 (let* ((out (make-array dims
:element-type
'(complex double-float
))))
111 (sb-sys:with-pinned-objects
(in out
)
112 (let ((p (plan-dft-3d z y x
114 (sb-ext:array-storage-vector in
))
116 (sb-ext:array-storage-vector out
))
122 (when forward
;; normalize if forward
123 (let ((1/n
(/ 1d0
(* x y z
))))
124 (do-box (k j i
0 z
0 y
0 x
)
125 (setf (aref out k j i
) (* 1/n
(aref out k j i
))))))
129 `(ft3 ,in
:forward nil
))
134 (values (simple-array (unsigned-byte 8) (* *))
137 (defun read-pgm (filename)
138 (with-open-file (s filename
)
139 (unless (equal (symbol-name (read s
)) "P5")
140 (error "no PGM file"))
144 (pos (file-position s
))
147 :element-type
'(unsigned-byte 8)))
150 :element-type
'(unsigned-byte 8)
151 :displaced-to data
)))
152 (declare ((simple-array (unsigned-byte 8) (* *)) data
)
153 ((array (unsigned-byte 8) (*)) data-1d
)
154 ((integer 0 65535) grays w h
))
155 (unless (= grays
255)
156 (error "image has wrong bitdepth"))
157 (with-open-file (s filename
158 :element-type
'(unsigned-byte 8))
159 (file-position s pos
)
160 (read-sequence data-1d s
))
165 ((array (unsigned-byte 8) 2)
167 (values null
&optional
))
169 (defun write-pgm (img filename
)
170 (destructuring-bind (h w
)
171 (array-dimensions img
)
172 (declare ((integer 0 65535) w h
))
173 (with-open-file (s filename
175 :if-exists
:supersede
176 :if-does-not-exist
:create
)
178 (format s
"P5~%~D ~D~%255~%" w h
))
179 (with-open-file (s filename
180 :element-type
'(unsigned-byte 8)
183 (let ((data-1d (make-array
185 :element-type
'(unsigned-byte 8)
187 (write-sequence data-1d s
)))
192 ((array (unsigned-byte 8) (*)) &optional fixnum
)
193 (values (simple-array fixnum
(*)) (unsigned-byte 8) (unsigned-byte 8) (unsigned-byte 8)
196 (defun histogram (img &optional
(bins 30))
197 (let* ((maxval (aref img
0))
201 (let ((v (aref img i
)))
206 (let* ((len (1+ (- maxval minval
)))
207 (result (make-array len
:element-type
'fixnum
))
208 (binsm (min (- maxval minval
) bins
)))
209 (when (eq maxval minval
)
210 #+nil
(error "data is too boring.")
211 (return-from histogram
(values result minval maxval binsm
)))
213 (incf (aref result
(floor (* binsm
216 (- maxval minval
)))))
217 (values result minval maxval binsm
))))
219 (declaim (ftype (function ((array * (* *)))
220 (values (simple-array * (*)) &optional
))
222 (defun get-linear-array (img)
223 (sb-ext:array-storage-vector img
)
224 #+nil
(make-array (* (array-dimension img
0)
225 (array-dimension img
1))
226 :element-type
(array-element-type img
)
230 (declaim (ftype (function (string)
231 (values (simple-array (unsigned-byte 8) (* * *))
234 (defun read-stack (fn)
235 (let* ((files (directory fn
))
236 (slices (length files
))
237 (a (read-pgm (first files
))))
238 (destructuring-bind (h w
)
240 (let* ((result (make-array (list slices h w
)
241 :element-type
'(unsigned-byte 8))))
243 (let* ((a (read-pgm (elt files k
))))
246 (setf (aref result k j i
)
250 (defmacro with-slice
((slice-array array slice-nr
) &body body
)
251 "Returns SLICE-NRth slice of ARRAY as the 2D SLICE-ARRAY."
255 `(destructuring-bind (,z
,y
,x
)
256 (array-dimensions ,array
)
257 (when (or (< ,slice-nr
0) (<= ,z
,slice-nr
))
258 (error "slice-nr=~d out of range [0,~d]" ,slice-nr
(1- ,z
)))
259 (let* ((,slice-array
(make-array (list ,y
,x
)
260 :element-type
'(unsigned-byte 8)
262 :displaced-index-offset
(* ,slice-nr
,x
,y
))))
265 (declaim (ftype (function (double-float) (values double-float
&optional
))
270 (declaim (ftype (function ((array double-float
*)
272 (array double-float
*))
273 (values double-float double-float
274 double-float double-float
&optional
))
276 ;; chernov/book.pdf p. 20
277 (defun linear-regression (y &optional
278 (x (let* ((n (length y
)))
281 :element-type
'double-float
283 (loop for i below n collect
(* 1d0 i
))))))
284 "Linear regression of the values in Y with the function y=a*x+b. If
285 X isn't supplied its assumed to be 0,1,2, ... . Returned are the
286 fitting parameters A and B and their errors DELTA_A and DELTA_B."
287 (let* ((n (length y
))
288 (xmean (/ (loop for xi across x sum xi
) n
))
289 (ymean (/ (loop for xi across y sum xi
) n
))
290 (sxx (loop for xi across x sum
(square (- xi xmean
))))
291 #+nil
(syy (loop for xi across y sum
(square (- xi ymean
))))
292 (sxy (loop for i below n sum
(* (- (aref x i
) xmean
)
293 (- (aref y i
) ymean
))))
295 (ahat (- ymean
(* bhat xmean
)))
296 (var (/ (loop for i below n sum
(square (- (aref y i
) ahat
297 (* bhat
(aref x i
)))))
299 (vara (* var
(+ (/ (square xmean
)
303 (values ahat bhat
(sqrt vara
) (sqrt varb
))))
306 (linear-regression (let* ((ll (list 1d0
2.01d0
3d0
4d0
)))
307 (make-array (length ll
)
308 :element-type
'double-float
309 :initial-contents ll
)))
311 (declaim (ftype (function (integer)
312 (values (unsigned-byte 8) &optional
))
316 (return-from clamp
0))
318 (return-from clamp
255))
322 (declaim (ftype (function ((simple-array (unsigned-byte 8) 2)
324 (values (unsigned-byte 8) &optional
))
326 (defun aref2-zero-ub8 (a j i
)
327 "Like AREF but return zero if subscripts J and I point outside of
329 (if (array-in-bounds-p a j i
)
333 (declaim (ftype (function ((simple-array double-float
2)
335 (values double-float
&optional
))
337 (defun aref2-zero-df (a j i
)
338 "Like AREF but return zero if subscripts J and I point outside of
340 (if (array-in-bounds-p a j i
)
344 (declaim (ftype (function ((simple-array (complex double-float
) 2)
346 (values (complex double-float
) &optional
))
348 (defun aref2-zero-cdf (a j i
)
349 "Like AREF but return zero if subscripts J and I point outside of
351 (if (array-in-bounds-p a j i
)
356 (declaim (ftype (function ((unsigned-byte 8)
359 (values double-float
&optional
))
361 (inline interp1-ub8
))
362 (defun interp1-ub8 (a b xi
)
363 "Interpolate between values A and B. Returns A for xi=0 and B for
365 (+ (* (- 1d0 xi
) a
) (* xi b
)))
367 (declaim (ftype (function (double-float double-float double-float
)
368 (values double-float
&optional
))
371 (defun interp1-df (a b xi
)
372 "Interpolate between values A and B. Returns A for xi=0 and B for
374 (+ (* (- 1d0 xi
) a
) (* xi b
)))
376 (declaim (ftype (function ((complex double-float
)
377 (complex double-float
) double-float
)
378 (values (complex double-float
) &optional
))
380 (inline interp1-cdf
))
381 (defun interp1-cdf (a b xi
)
382 "Interpolate between values A and B. Returns A for xi=0 and B for
384 (+ (* (- 1d0 xi
) a
) (* xi b
)))
386 (declaim (ftype (function ((or (unsigned-byte 8)
388 (complex double-float
))
389 (or (unsigned-byte 8)
391 (complex double-float
))
393 (values (or double-float
394 (complex double-float
)) &optional
))
397 (defun interp1 (a b xi
)
399 ((unsigned-byte 8) (interp1-ub8 a b xi
))
400 (double-float (interp1-df a b xi
))
401 ((complex double-float
) (interp1-cdf a b xi
))))
403 (declaim (ftype (function ((simple-array (unsigned-byte 8) 2)
404 double-float double-float
)
405 (values double-float
&optional
))
407 (defun interpolate2-ub8 (img x y
)
408 "Bilinear interpolation on an image IMG. The coordinates X and Y can
409 be floating point values. If they point outside of IMG 0 is returned."
410 (multiple-value-bind (i ix
)
412 (multiple-value-bind (j jx
)
414 ;; values on grid points, top left is i,j and stored in a
419 (let ((a (aref img i j
))
420 (b (aref2-zero-ub8 img
(1+ i
) j
))
421 (c (aref2-zero-ub8 img i
(1+ j
)))
422 (d (aref2-zero-ub8 img
(1+ i
) (1+ j
))))
423 ;; now interpolate verticals
429 (let ((e (interp1-ub8 a c jx
))
430 (f (interp1-ub8 b d jx
)))
431 ;; and now horizontal
433 (let ((g (interp1-df e f ix
)))
436 (declaim (ftype (function ((simple-array double-float
2)
437 double-float double-float
)
438 (values double-float
&optional
))
440 (defun interpolate2-df (img x y
)
441 "Bilinear interpolation on an image IMG. The coordinates X and Y can
442 be floating point values. If they point outside of IMG 0 is returned."
443 (multiple-value-bind (i ix
)
445 (multiple-value-bind (j jx
)
447 (let ((a (aref img i j
))
448 (b (aref2-zero-df img
(1+ i
) j
))
449 (c (aref2-zero-df img i
(1+ j
)))
450 (d (aref2-zero-df img
(1+ i
) (1+ j
))))
451 (let ((e (interp1-df a c jx
))
452 (f (interp1-df b d jx
)))
453 (let ((g (interp1-df e f ix
)))
456 (declaim (ftype (function ((simple-array (complex double-float
) 2)
457 double-float double-float
)
458 (values (complex double-float
) &optional
))
460 (defun interpolate2-cdf (img x y
)
461 "Bilinear interpolation on an image IMG. The coordinates X and Y can
462 be floating point values. If they point outside of IMG 0 is returned."
463 (multiple-value-bind (i ix
)
465 (multiple-value-bind (j jx
)
467 (let ((a (aref img i j
))
468 (b (aref2-zero-cdf img
(1+ i
) j
))
469 (c (aref2-zero-cdf img i
(1+ j
)))
470 (d (aref2-zero-cdf img
(1+ i
) (1+ j
))))
471 (let ((e (interp1-cdf a c jx
))
472 (f (interp1-cdf b d jx
)))
473 (let ((g (interp1-cdf e f ix
)))
477 (declaim (ftype (function ((simple-array * 2) double-float double-float
)
478 (values (or double-float
479 (complex double-float
)) &optional
))
481 (defun interpolate2 (img x y
)
482 "Bilinear interpolation on an image IMG. The coordinates X and Y can
483 be floating point values. If they point outside of IMG 0 is returned."
485 ((simple-array (unsigned-byte 8) 2) (interpolate2-ub8 img x y
))
486 ((simple-array double-float
2) (interpolate2-df img x y
))
487 ((simple-array (complex double-float
) 2) (interpolate2-cdf img x y
))))
490 (let ((a (make-array (list 2 2) :element-type
'(unsigned-byte 8)
491 :initial-contents
'((1 2) (2 3)))))
492 (interpolate2 a
.5d0
.2d0
))