i mixed f and b in the calculation
[woropt.git] / frontend / merit.lisp
blobe39f6c3b87144ba2e55a1d6ceb5307753e82f73b
1 (in-package :frontend)
3 ;; it turns out that using a few points on the border of the circles
4 ;; is too sparse. the following scheme should sample the space a bit
5 ;; better and therefore give a better approximation of the exposure
6 ;; integral
7 ;;
8 ;; ---------
9 ;; ---/ \--- xy-cross section through a
10 ;; / \ nucleus in the sample plane
11 ;; -/ \-
12 ;; / \ choose s points along a line
13 ;; | | .
14 ;; / \ .
15 ;; 0 1 2 ...
16 ;; \ /
17 ;; | |
18 ;; \ /
19 ;; -\ /-
20 ;; \ /
21 ;; ---\ /-- -----------
22 ;; --------- ---/ \---
23 ;; -/ \-
24 ;; -/ back focal \-
25 ;; / plane \
26 ;; / \
27 ;; | |
28 ;; choose / \
29 ;; b points .... a b c d e f
30 ;; along a lin \ /
31 ;; with the same | |
32 ;; inclination theta \ /
33 ;; \ /
34 ;; -\ /-
35 ;; -\ /-
36 ;; ---\ /---
37 ;; -----------
39 ;; now shoot rays from each o the points in the bfp to each of the
40 ;; points in the sample plane. we have to make sure that a nucleus
41 ;; inside the illumination cone convolved with the cross section of
42 ;; the illuminated nucleus is hit by at least one ray. the necessary
43 ;; number of points s and b depends on the size of the nuclei as well
44 ;; as the furthest distance to the border of the stack. for now i
45 ;; don't want to think too hard about that. i guess it will be
46 ;; sufficient to sample with .01 in the back focal plane and 3 points
47 ;; in the nucleus.
48 ;; two dimensional coordinates will be represented as complex numbers.
50 (defun sample-line (nr-ffp nr-bfp)
51 "Create two lists like -1 0 1 and -1 -.5 0 .5 1. Here nr-ffp would
52 be 3 and nr-bfp would be 5. The result is the outer product -1 -1, -1
53 -.5, -1, 0, ..., a list with all interconnections. Note that the pair
54 0,0 isn't emitted as it would result in duplications when turned by
55 theta."
56 (declare (fixnum nr-ffp nr-bfp))
57 (let ((ffps (loop for i below nr-ffp collect
58 (complex (- (/ (* 2d0 i) (1- nr-ffp)) 1))))
59 (bfps (loop for i below nr-bfp collect
60 (complex (- (/ (* 2d0 i) (1- nr-bfp)) 1))))
61 (result nil))
62 (loop for f in ffps do
63 (loop for b in bfps do
64 (unless (= (complex 0d0) f b) ;; prevent duplication of central ray
65 (push (list f b) result))))
66 (nreverse result)))
68 #+nil
69 (sample-line 3 3)
71 (defun sample-circles (nr-ffp nr-bfp nr-theta)
72 "Create coordinates in front and backfocal plane that sample circles
73 in a regular pattern."
74 (declare (fixnum nr-ffp nr-bfp nr-theta))
75 (let ((line (sample-line nr-ffp nr-bfp))
76 (result nil))
77 (loop for theta below nr-theta do
78 (let ((rotator (exp (complex 0d0 (/ (* 2d0 pi theta) nr-theta)))))
79 (loop for (f b) in line do
80 (push (list (* rotator f)
81 (* rotator b))
82 result))))
83 (when (and (oddp nr-ffp) (oddp nr-bfp)) ;; central ray was omitted above
84 (push (list (complex 0d0) (complex 0d0)) result))
85 (nreverse result)))
87 #+nil
88 (sample-circles 2 2 4)
90 ;; ------+------
91 ;; ---/ | \---
92 ;; --/ |---+--- \--
93 ;; -/ -| | \- \-
94 ;; / / | z | \ \
95 ;; -/ / | | r \ \-
96 ;; / |y +---+------+ \
97 ;; / \ | | / \
98 ;; | \ | | / |
99 ;; / -| | /- \
100 ;; | |---+--- |
101 ;; -+--------------------+---+----------------+--
102 ;; | | x rr |
103 ;; \ | /
105 (defun move-complex-circle (z rr x/rr y/rr r/rr)
106 "Given a complex number Z inside the unit circle, move the unit
107 circle to position X,Y inside the BFP with radius RR. Scale the unit
108 circle to the window-radius R."
109 (declare ((complex double-float) z)
110 ((double-float -1d0 1d0) x/rr y/rr)
111 ((double-float 0d0 1d0) r/rr)
112 (double-float rr)
113 (values (complex double-float) &optional))
114 (+ (complex (* x/rr rr) (* y/rr rr))
115 (* r/rr rr z)))
117 #+nil
118 (move-complex-circle (complex 1d0 0d0) 2d0 .9d0 0d0 .1d0)
120 #+nil
121 (move-complex-circle (complex 1d0 0d0) 1d0 .9d0 0d0 .1d0)
123 (defmethod make-rays ((objective lens::objective) (model sphere-model)
124 nucleus positions win-x/r win-y/r win-r/r)
125 "Given an objective and a nucleus in a model generate rays from a
126 circle on the back focal plane into the front focal plane. The pattern
127 of the rays is given as a list of 2-lists of complex numbers. The
128 first complex number gives the relative position inside the central
129 cross section of the nucleus and the second number gives the relative
130 position in the bfp. The coordinates and size of the window in the
131 back focal plane are given relative to the radius of the bfp. The
132 return value is a list of 2-lists of rays, where the first ray starts
133 from the principal sphere and the second ray from the bfp."
134 (declare (fixnum nucleus)
135 (cons positions)
136 (double-float win-x/r win-y/r win-r/r)
137 (values cons &optional))
138 (assert (subtypep (type-of (first (first positions))) '(complex double-float)))
139 (assert (subtypep (type-of (second (first positions))) '(complex double-float)))
140 (with-slots (centers-mm
141 radii-mm) model
142 (let ((center (elt centers-mm nucleus))
143 (radius (elt radii-mm nucleus))
144 (result nil))
145 (with-slots ((r lens::bfp-radius)
146 (ri lens::immersion-index)
147 (f lens::focal-length)) objective
148 (loop for (f b) in positions do
149 (let ((br (move-complex-circle b r win-x/r win-y/r win-r/r))
150 (fr (move-complex-circle f 1d0 (vec-x center) (vec-y center)
151 radius)))
152 (handler-case
153 (multiple-value-bind (exit enter)
154 (lens:get-ray-behind-objective
155 objective
156 (realpart fr) (imagpart fr)
157 (realpart br) (imagpart br))
158 (push (list exit enter) result))
159 (ray-lost () nil))))
160 (nreverse result)))))
162 #+nil
163 (make-rays (lens:make-objective) *model* 0 (sample-circles 2 2 4)
164 .2d0 0d0 .1d0)
166 (defun merit-function (vec2 params)
167 (declare ((simple-array double-float (2)) vec2)
168 (cons params)
169 (values double-float &optional))
170 (destructuring-bind (objective model nucleus-index window-radius)
171 params
172 (let* ((border-value 0d0) ;; value to return when outside of bfp
173 ;; this has to be considerably bigger than the maxima on the bfp
174 (border-width window-radius) ;; in this range to the
175 ;; border of the bfp
176 ;; enforce bad merit
177 ;; function
178 (sum 0d0)
179 (radius (norm2 vec2)))
180 (if (< radius (- .99d0 border-width))
181 ;; inside
182 (loop for dirs in '((:right :left)
183 (:top :bottom)) do
184 (loop for dir in dirs do
185 (loop for bfp-dir in dirs do
186 (let ((ray (make-ray objective
187 model
188 nucleus-index dir
189 (vec2-x vec2) (vec2-y vec2)
190 window-radius bfp-dir)))
191 (incf sum
192 (raytrace:ray-spheres-intersection
193 ray model nucleus-index))))))
194 ;; in the border-width or outside of bfp
195 (incf sum border-value))
196 sum)))
198 (defun find-optimal-bfp-window-center (nucleus params)
199 (declare (fixnum nucleus)
200 (cons params)
201 (values vec2 &optional))
202 (setf (elt params 2) nucleus)
203 (loop
204 (multiple-value-bind (min point)
205 (simplex-anneal:anneal (simplex-anneal:make-simplex
206 (make-vec2 :x -1d0 :y -1d0) 1d0)
207 #'merit-function
208 ;; set temperature bigger than the
209 ;; maxima in the bfp but smaller
210 ;; than border-value
211 :start-temperature 2.4d0
212 :eps/m .02d0
213 :itmax 1000
214 :ftol 1d-3
215 :params params)
216 (when (< min 100d0)
217 (return-from find-optimal-bfp-window-center point)))))
219 #+nil
220 (find-optimal-bfp-window-center 0)