API
 
Loading...
Searching...
No Matches
utils.py
Go to the documentation of this file.
1import hcipy as hp
2import numpy as np
3import time
4import datetime
5import os
6
7### Make the save directory
8def make_savedir_for_today(start_path='./Data/'):
9 ct = datetime.datetime.now()
10 savedir = start_path + '{:>04d}{:>02d}{:>02d}/'.format(ct.year, ct.month, ct.day)
11 make_savedir(savedir)
12 return savedir
13
14def make_savedir(new_path):
15 try:
16 os.makedirs(new_path, exist_ok=True)
17 except FileExistsError:
18 print("Directory already exists.")
19
21 t = time.time()
22 t_seconds = int(t)
23 ms = int(1000 * (t - t_seconds))
24 stamp = '{:d}{:d}'.format(t_seconds, ms)
25 return stamp
26
27def wait_for_ready(client, device, timeout=0.1):
28 time.sleep(timeout)
29 while client[device + '.fsm.state'] != 'READY':
30 time.sleep(timeout)
31
32def make_horizontal_probe(grid, direction='left'):
33 probe = grid.zeros()
34 probe = probe.shaped
35
36 width = 4
37 height = 4
38 x = (-1.0)**(np.arange(width) - width//2)
39 y = (-1.0)**(np.arange(height) - height//2)
40
41 # 34 - 15 16 17 18 19 20
42 probe[15:19, 6:10] = np.outer(x, y)
43 probe[15:19, 6:10] = np.outer(y, x)
44 if direction == 'right':
45 probe = probe[:,::-1]
46
47 return probe.ravel()
48
49def make_vertical_probe(grid, direction='down'):
50 probe = grid.zeros()
51 probe = probe.shaped
52
53 width = 4
54 height = 4
55 x = (-1.0)**(np.arange(width) - width//2)
56 y = (-1.0)**(np.arange(height) - height//2)
57
58 # 34 - 15 16 17 18 19 20
59 probe[8:12, 15:19] = np.outer(y, x)
60 probe[8:12, 15:19] = np.outer(x, y)
61 probe = np.sign(probe)
62 if direction == 'up':
63 probe = probe[::-1,:]
64
65 return probe.ravel()
66
68 ncpc_act_grid = hp.make_pupil_grid(34, 34/30.0 * np.array([1.0, np.sqrt(2)]))
69 probe = make_vertical_probe(ncpc_act_grid) + make_vertical_probe(ncpc_act_grid, 'up')
70 probe += make_horizontal_probe(ncpc_act_grid) + make_horizontal_probe(ncpc_act_grid, 'right')
71 return probe
72
73
74def wait_for_state(client, indi_property, value, wait_time=1, tolerance=None):
75 if tolerance is None:
76 while not (client[indi_property] == value):
77 print("Waiting...")
78 time.sleep(wait_time)
79 else:
80 while not abs(client[indi_property] - value) < tolerance:
81 print("Waiting...")
82 time.sleep(wait_time)
83
84def calibrate_indi_device(client, device_name, device_property, delta_pertubation, camera, measurement_function, num_stack=50, do_wait=False):
85 client.get_properties('{:s}'.format(device_name))
86
87 property_current = '{:s}.{:s}.current'.format(device_name, device_property)
88 property_target = '{:s}.{:s}.target'.format(device_name, device_property)
89 current_position = client[property_current]
90 print("Probe to {:f} +- {:f}".format(current_position, delta_pertubation))
91 slope = 0
92 for s in [-1, 1]:
93 client[property_target] = current_position + s * delta_pertubation
94 if do_wait:
95 wait_for_state(client, property_current, current_position + s * delta_pertubation, tolerance=0.1 * delta_pertubation)
96 else:
97 time.sleep(5)
98
99 # Take measurement
100 camera.grab_stack(3)
101 im = camera.grab_stack(num_stack)
102
103 measurement = measurement_function(im)
104 slope += s * measurement / (2 * delta_pertubation)
105
106 client[property_target] = current_position
107 if do_wait:
108 wait_for_state(client, property_current, current_position, tolerance=0.1 * delta_pertubation)
109 else:
110 time.sleep(2)
111
112 return slope
113
115 def __init__(self, reference_image, domain_pixels=480, domain_size=40, filter_size=None, reference_point=np.array([0,0])):
116 self._reference_image = reference_image
117 self._xgrid = hp.make_pupil_grid(domain_pixels, domain_size).shifted(reference_point)
118
119 self._fft = hp.FastFourierTransform(self._reference_image.grid)
120 self._mft = hp.MatrixFourierTransform(self._xgrid, self._fft.output_grid)
121
122 self._filter_size = filter_size
123 if filter_size is not None:
124 # Change this to a super gaussian filter to remove ringing.
125 self._spatial_filter = hp.make_circular_aperture(self._filter_size)(self._fft.output_grid)
126 else:
127 self._spatial_filter = 1
128
129 self._kernel = np.conj(self._fft.forward(self._reference_image + 0j))
130
131 def cross_correlate(self, image, local_reference_point=np.array([0,0])):
132 tilt = np.exp(1j * local_reference_point @ self._fft.output_grid.points.T)
133 xcorr = np.real(self._mft.backward(self._fft.forward(image + 0j) * self._spatial_filter * self._kernel * tilt))
134 return xcorr
135
136 def _subpixel_offset_from_quadratic(self, xcorr_2d, ix, iy):
137 ny, nx = xcorr_2d.shape
138 if ix < 1 or ix > nx - 2 or iy < 1 or iy > ny - 2:
139 return None
140
141 patch = xcorr_2d[iy-1:iy+2, ix-1:ix+2]
142 dx, dy = np.meshgrid(np.arange(-1, 2), np.arange(-1, 2))
143 A = np.vstack([
144 dx.ravel()**2,
145 dy.ravel()**2,
146 (dx * dy).ravel(),
147 dx.ravel(),
148 dy.ravel(),
149 np.ones(9)
150 ]).T
151 z = patch.ravel()
152
153 coeff, *_ = np.linalg.lstsq(A, z, rcond=None)
154 a, b, c, d, e, _ = coeff
155
156 denom = 4*a*b - c*c
157 if abs(denom) < 1e-12:
158 return None
159
160 x0 = (c*e - 2*b*d)/denom
161 y0 = (c*d - 2*a*e)/denom
162
163 if abs(x0) > 1.0 or abs(y0) > 1.0:
164 return None
165
166 return np.array([x0, y0])
167
168 def _subpixel_peak_position(self, xcorr):
169 xcorr_arr = np.asarray(xcorr)
170 grid_shape = tuple(self._xgrid.shape)
171 xcorr_2d = xcorr_arr.reshape(grid_shape)
172
173 idx_max = np.argmax(xcorr_2d)
174 iy, ix = np.unravel_index(idx_max, grid_shape)
175
176 offset = self._subpixel_offset_from_quadratic(xcorr_2d, ix, iy)
177 if offset is None:
178 return self._xgrid.points[idx_max]
179
180 dx, dy = offset
181 x_center = self._xgrid.x.reshape(grid_shape)[iy, ix]
182 y_center = self._xgrid.y.reshape(grid_shape)[iy, ix]
183
184 return np.array([
185 x_center + dx * self._xgrid.delta[0],
186 y_center + dy * self._xgrid.delta[1]
187 ])
188
189 def measure(self, image, local_reference_point=np.array([0,0]), subpixel=True):
190 xcorr = self.cross_correlate(image, local_reference_point)
191
192 if subpixel:
193 peak = self._subpixel_peak_position(xcorr)
194 else:
195 indx_max = np.argmax(np.asarray(xcorr))
196 peak = self._xgrid.points[indx_max]
197
198 return peak + local_reference_point
_subpixel_peak_position(self, xcorr)
Definition utils.py:168
cross_correlate(self, image, local_reference_point=np.array([0, 0]))
Definition utils.py:131
__init__(self, reference_image, domain_pixels=480, domain_size=40, filter_size=None, reference_point=np.array([0, 0]))
Definition utils.py:115
_subpixel_offset_from_quadratic(self, xcorr_2d, ix, iy)
Definition utils.py:136
measure(self, image, local_reference_point=np.array([0, 0]), subpixel=True)
Definition utils.py:189
calibrate_indi_device(client, device_name, device_property, delta_pertubation, camera, measurement_function, num_stack=50, do_wait=False)
Definition utils.py:84
wait_for_state(client, indi_property, value, wait_time=1, tolerance=None)
Definition utils.py:74
make_horizontal_probe(grid, direction='left')
Definition utils.py:32
wait_for_ready(client, device, timeout=0.1)
Definition utils.py:27
make_savedir(new_path)
Definition utils.py:14
make_ncpc_alignment_poke_pattern()
Definition utils.py:67
make_vertical_probe(grid, direction='down')
Definition utils.py:49
make_savedir_for_today(start_path='./Data/')
Make the save directory.
Definition utils.py:8