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
9 ;; ---/ \--- xy-cross section through a
10 ;; / \ nucleus in the sample plane
12 ;; / \ choose s points along a line
21 ;; ---\ /-- -----------
22 ;; --------- ---/ \---
29 ;; b points .... a b c d e f
32 ;; inclination theta \ /
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
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
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))))
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
))))
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
))
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
)
83 (when (and (oddp nr-ffp
) (oddp nr-bfp
)) ;; central ray was omitted above
84 (push (list (complex 0d0
) (complex 0d0
)) result
))
88 (sample-circles 2 2 4)
96 ;; / |y +---+------+ \
101 ;; -+--------------------+---+----------------+--
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
)
113 (values (complex double-float
) &optional
))
114 (+ (complex (* x
/rr rr
) (* y
/rr rr
))
118 (move-complex-circle (complex 1d0
0d0
) 2d0
.9d0
0d0
.1d0
)
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
)
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
142 (let ((center (elt centers-mm nucleus
))
143 (radius (elt radii-mm nucleus
))
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
)
153 (multiple-value-bind (exit enter
)
154 (lens:get-ray-behind-objective
156 (realpart fr
) (imagpart fr
)
157 (realpart br
) (imagpart br
))
158 (push (list exit enter
) result
))
160 (nreverse result
)))))
163 (make-rays (lens:make-objective
) *model
* 0 (sample-circles 2 2 4)
166 (defun merit-function (vec2 params
)
167 (declare ((simple-array double-float
(2)) vec2
)
169 (values double-float
&optional
))
170 (destructuring-bind (objective model nucleus-index window-radius
)
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
179 (radius (norm2 vec2
)))
180 (if (< radius
(- .99d0 border-width
))
182 (loop for dirs in
'((:right
:left
)
184 (loop for dir in dirs do
185 (loop for bfp-dir in dirs do
186 (let ((ray (make-ray objective
189 (vec2-x vec2
) (vec2-y vec2
)
190 window-radius bfp-dir
)))
192 (raytrace:ray-spheres-intersection
193 ray model nucleus-index
))))))
194 ;; in the border-width or outside of bfp
195 (incf sum border-value
))
198 (defun find-optimal-bfp-window-center (nucleus params
)
199 (declare (fixnum nucleus
)
201 (values vec2
&optional
))
202 (setf (elt params
2) nucleus
)
204 (multiple-value-bind (min point
)
205 (simplex-anneal:anneal
(simplex-anneal:make-simplex
206 (make-vec2 :x -
1d0
:y -
1d0
) 1d0
)
208 ;; set temperature bigger than the
209 ;; maxima in the bfp but smaller
211 :start-temperature
2.4d0
217 (return-from find-optimal-bfp-window-center point
)))))
220 (find-optimal-bfp-window-center 0)