started more sophisticated sampling of bfp window
[woropt.git] / frontend / merit.lisp
blob920d948f41790d05762278ff2034a3883c98113d
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 (with-slots ((r lens::bfp-radius)
145 (ri lens::immersion-index)
146 (f lens::focal-length)) objective
147 (loop for (f b) in positions collect
148 (let ((fr (move-complex-circle f r win-x/r win-y/r win-r/r))
149 (br (move-complex-circle b 1d0 (vec-x center) (vec-y center)
150 radius)))
151 (multiple-value-bind (exit enter)
152 (lens:get-ray-behind-objective
153 objective
154 (realpart fr) (imagpart fr)
155 (realpart br) (imagpart br))
156 (list exit enter))))))))
158 #+nil
159 (make-rays (lens:make-objective) *model* 0 (sample-circles 2 2 4)
160 .2d0 0d0 .1d0)
163 (defun merit-function (vec2 params)
164 (declare ((simple-array double-float (2)) vec2)
165 (cons params)
166 (values double-float &optional))
167 (destructuring-bind (objective model nucleus-index window-radius)
168 params
169 (let* ((border-value 0d0) ;; value to return when outside of bfp
170 ;; this has to be considerably bigger than the maxima on the bfp
171 (border-width window-radius) ;; in this range to the
172 ;; border of the bfp
173 ;; enforce bad merit
174 ;; function
175 (sum 0d0)
176 (radius (norm2 vec2)))
177 (if (< radius (- .99d0 border-width))
178 ;; inside
179 (loop for dirs in '((:right :left)
180 (:top :bottom)) do
181 (loop for dir in dirs do
182 (loop for bfp-dir in dirs do
183 (let ((ray (make-ray objective
184 model
185 nucleus-index dir
186 (vec2-x vec2) (vec2-y vec2)
187 window-radius bfp-dir)))
188 (incf sum
189 (raytrace:ray-spheres-intersection
190 ray model nucleus-index))))))
191 ;; in the border-width or outside of bfp
192 (incf sum border-value))
193 sum)))
195 (defun find-optimal-bfp-window-center (nucleus params)
196 (declare (fixnum nucleus)
197 (cons params)
198 (values vec2 &optional))
199 (setf (elt params 2) nucleus)
200 (loop
201 (multiple-value-bind (min point)
202 (simplex-anneal:anneal (simplex-anneal:make-simplex
203 (make-vec2 :x -1d0 :y -1d0) 1d0)
204 #'merit-function
205 ;; set temperature bigger than the
206 ;; maxima in the bfp but smaller
207 ;; than border-value
208 :start-temperature 2.4d0
209 :eps/m .02d0
210 :itmax 1000
211 :ftol 1d-3
212 :params params)
213 (when (< min 100d0)
214 (return-from find-optimal-bfp-window-center point)))))
216 #+nil
217 (find-optimal-bfp-window-center 0)