aopera 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
aopera/control.py ADDED
@@ -0,0 +1,355 @@
1
+ """
2
+ Number of controlled modes and transfer functions management
3
+ """
4
+
5
+ import math
6
+ import numpy as np
7
+ import logging
8
+ from aopera.readconfig import read_config_file, read_config_tiptop, check_dictionary, INFO_RTC
9
+ from scipy.linalg import solve_discrete_are
10
+
11
+ #%% TEMPORAL FILTERING FUNCTION
12
+ def open_loop_transfer(freq, ao_freq, ki, nb_frame_delay, kp=0, discrete=False, leak=1.0):
13
+ """
14
+ Return the temporal open loop transfer function for a proportional-integrator controller.
15
+
16
+ Parameters
17
+ ----------
18
+ freq : np.array
19
+ Array of temporal frequencies to evaluate the CLTF on.
20
+ ao_freq : float
21
+ The sampling temporal frequency of the AO loop.
22
+ ki : float
23
+ Integrator gain.
24
+ nb_frame_delay : float
25
+ Number of frame delay.
26
+ Must include: RTC, pixel transfert, DM rise.
27
+ Must not include: WFS integration, DM zero-order-hold.
28
+ kp : float (default:0)
29
+ Proportional gain.
30
+ discrete : bool (default:False)
31
+ Choose to use discrete formalism.
32
+ leak : float (default=1.0)
33
+ Leaky integrator.
34
+ """
35
+
36
+ if not discrete:
37
+ Tp = 2j*np.pi*freq/ao_freq
38
+ H = kp + ki/(Tp+(1.0-leak)) # controler
39
+ H *= np.exp(-Tp*nb_frame_delay) # delay
40
+ H *= (1-np.exp(-Tp))/Tp # WFS
41
+ H *= 1 # zero order holder
42
+ else:
43
+ # Tp = 2j*np.pi*freq/ao_freq
44
+ z = np.exp(2j*np.pi*freq/ao_freq) # it is one method to pass from Tp to z
45
+ H = kp + ki/(1-leak/z) # controler
46
+ H *= 1/z**(nb_frame_delay+1) # delay + WFS + zero order hold
47
+
48
+ return H
49
+
50
+
51
+ def closed_loop_transfer(*args, **kwargs):
52
+ """
53
+ Return the temporal closed loop transfer function.
54
+ See the open_loop_transfer arguments.
55
+ """
56
+ return 1/(1+open_loop_transfer(*args, **kwargs))
57
+
58
+
59
+ def noise_transfer(*args, **kwargs):
60
+ """
61
+ Return the noise transfer function.
62
+ See the open_loop_transfer arguments.
63
+ """
64
+ return open_loop_transfer(*args, **kwargs) * closed_loop_transfer(*args, **kwargs)
65
+
66
+
67
+ def bandwidth(ki, nb_frame_delay, ao_freq, db=0):
68
+ """
69
+ Compute the AO bandwidth for an integrator control law.
70
+
71
+ .. math::
72
+ BW_{db} = \\frac{F}{2\\pi}\\frac{k_i}{\\sqrt{k_i(2N_d+1)+10^{-db}-1}}
73
+
74
+ Parameters
75
+ ----------
76
+ ki : float
77
+ Gain of the integrator law
78
+ nb_frame_delay : float
79
+ Number of frame delay (exposure frame excluded)
80
+ ao_freq : float
81
+ Loop frequency [Hz]
82
+
83
+ Keywords
84
+ --------
85
+ db : float (≤0)
86
+ The cutoff in decibel (default=0).
87
+
88
+ References
89
+ ----------
90
+ Thierry Fusco (ONERA), 2005, internal document, "AO temporal behavior".
91
+ Completed by R.Fetick.
92
+ """
93
+ cst = 10**(db/10)
94
+ alpha = (nb_frame_delay+0.5)*ki
95
+ # The polynomial equation comes from the development of `sin((nd+0.5)wT)`
96
+ p0 = 1
97
+ p1 = 1 - 1/cst - 2*alpha**1 / math.factorial(1)
98
+ # p2 = 2*alpha**3 / math.factorial(3)
99
+ # delta = p1**2 - 4*p0*p2
100
+ # rsol = (np.sqrt(delta)-p1)/(2*p2) # order 2 solution
101
+ rsol = -p0/p1 # order 1 solution
102
+ bw = np.sqrt(rsol)*ki*ao_freq/(2*np.pi)
103
+
104
+ # Check afterwards if the 1st order development of sine was valid
105
+ sine_argu = (nb_frame_delay+0.5)*2*np.pi*bw/ao_freq
106
+ rel_error = np.abs(sine_argu - np.sin(sine_argu))/sine_argu
107
+ if np.max(rel_error) > 0.07:
108
+ logging.warning('Bandwidth computation might be unconsistent')
109
+
110
+ return bw
111
+
112
+
113
+ def bandwidth_noise(ki, nb_frame_delay, ao_freq, db=-4):
114
+ """
115
+ Compute the noise bandwidth for an integrator control law.
116
+
117
+ Parameters
118
+ ----------
119
+ ki : float
120
+ Gain of the integrator law
121
+ nb_frame_delay : float
122
+ Number of frame delay (exposure frame excluded)
123
+ ao_freq : float
124
+ Loop frequency [Hz]
125
+
126
+ Keywords
127
+ --------
128
+ db : float (<0)
129
+ The cutoff in decibel (default=-4).
130
+
131
+ Note
132
+ ----
133
+ A bandwidth at -4 dB is chosen so we get the equality between the integration
134
+ of |NTF|² (in the discrete domain) and the bandwidth_noise expression.
135
+
136
+ .. math::
137
+ BW_{noise} \\simeq \\int_0^{+\\infty}|NTF(f)|^2 df
138
+
139
+ So it has to be multiplied by 2 to account for both positive and negative frequencies.
140
+
141
+ Reference
142
+ ---------
143
+ R.Fetick, personnal work.
144
+ """
145
+ cst = 10**(db/10)
146
+ alpha = (nb_frame_delay+0.5)*ki
147
+ # The polynomial equation comes from the development of `sin((nd+0.5)wT)`
148
+ p3 = - 2 * alpha**5 / math.factorial(5)
149
+ p2 = 2 * alpha**3 / math.factorial(3)
150
+ p1 = 1 - 2 * alpha**1 / math.factorial(1)
151
+ p0 = 1 - 1/cst
152
+ r = np.roots([p3,p2,p1,p0])
153
+ rsol = min(r[r>0]) # the bandwidth is >0, and I choose the min solution (justified?)
154
+ bwn = np.sqrt(rsol)*ki*ao_freq/(2*np.pi)
155
+ return bwn
156
+
157
+
158
+ #%% LQG
159
+ def lqg_controller(fx, fy, phase_psd, noise_psd, cn2dh_ratio, wind_speed, wind_direction, ao_freq, delta_wind_speed=0.1, diameter=np.inf, verbose=False):
160
+ """
161
+ Compute LQG controller for each spatial frequency (fx,fy).
162
+ Only valid for two frames delay (1 for WFS integration, 1 for pixel transfer and RTC computation).
163
+
164
+ Parameters
165
+ ----------
166
+ fx : list of floats
167
+ Spatial frequencies [1/m] along X.
168
+ fy : list of floats
169
+ Spatial frequencies [1/m] along Y.
170
+ phase_psd : list of floats
171
+ PSD of the turbulent phase [rad²m²] at (fx,fy).
172
+ noise_psd : list of floats
173
+ PSD of the noise [rad²m²] at (fx,fy).
174
+ cn2dh_ratio : list of floats
175
+ Cn²*dh ratio (sum=1) of turbulence layers.
176
+ wind_speed : list of floats
177
+ Wind speed [m/s] of turbulence layers.
178
+ wind_direction : list of floats
179
+ Wind direction [deg] of turbulence layers.
180
+ ao_freq : float
181
+ AO loop frequency [Hz].
182
+
183
+ Keywords
184
+ --------
185
+ delta_wind_speed : float
186
+ Uncertainty on wind speed estimation [m/s].
187
+ diameter : float
188
+ Telescope diameter [m].
189
+ verbose : bool
190
+ Print iterations while you drink a cup of tea.
191
+
192
+ Return
193
+ ------
194
+ List of LQG controllers (functions) for each spatial frequency, to be evaluated on Z transform domain.
195
+ Thus `output[i](z)` is the LQG controller of (fx[i], fy[i]) evaluated at `z`.
196
+
197
+ Reference
198
+ ---------
199
+ Correia et al, 2017,
200
+ Modelling astronomical adaptive optics performance with temporally-filtered Wiener reconstruction of slope data
201
+ """
202
+
203
+ logging.warning('Check LQG state covariance V and command regularization R')
204
+
205
+ controllers = []
206
+ RG = 1.0 # Measurement and reconstructor
207
+ eigval_dump = 0.99999 # ensure solution for LQG
208
+ Ts = 1/ao_freq
209
+ # ff = np.sqrt(np.array(fx)**2+np.array(fy)**2)
210
+ nfreq = len(fx)
211
+ nlayer = len(wind_speed)
212
+ dk = 1/diameter # aocutoff / (pupil.nact-1) / 2 # attempt to account for integral over frequencies for one mode
213
+
214
+ # DISCRETE ARE
215
+ # x{k+1} = A.x{k} + B.u{k} + v{k} (state evolution)
216
+ # y{k} = C.x{k} + w{k} (measurement)
217
+ # J = ||xT.Q.x + uT.R.u|| (criterion)
218
+
219
+ A = np.zeros((nlayer+5, nlayer+5), dtype=complex)
220
+ B = np.zeros((nlayer+5,1))
221
+ C = np.zeros((1,nlayer+5))
222
+ Q = np.zeros((nlayer+5,nlayer+5))
223
+ V = np.zeros((nlayer+5,nlayer+5), dtype=complex)
224
+
225
+ vx = wind_speed*np.cos(wind_direction*np.pi/180)
226
+ vy = wind_speed*np.sin(wind_direction*np.pi/180)
227
+ poke_freq_avg = np.sinc(Ts*vx*dk) * np.sinc(Ts*vy*dk) # frequency averaging (modal frequencial width)
228
+ # cvx = 2 - np.cos(2*np.pi*Ts*vx*dk/2)
229
+ # cvy = 2 - np.cos(2*np.pi*Ts*vy*dk/2)
230
+ # poke_avg_x = cvx - np.sqrt(cvx**2 - 1)
231
+ # poke_avg_y = cvy - np.sqrt(cvy**2 - 1)
232
+ # poke_freq_avg = poke_avg_x * poke_avg_y
233
+
234
+ # FILL MATRICES with CONSTANT TERMS
235
+ Q[nlayer+2, nlayer+2] = 1
236
+ Q[nlayer+4, nlayer+4] = 1
237
+ Q[nlayer+4, nlayer+2] = -1
238
+ Q[nlayer+2, nlayer+4] = -1
239
+
240
+ A[nlayer+1,nlayer] = 1
241
+ A[nlayer+2,nlayer+1] = 1
242
+ A[nlayer+4,nlayer+3] = 1
243
+
244
+ B[nlayer+3,0] = 1
245
+
246
+ C[0,nlayer+2] = RG
247
+ C[0,nlayer+4] = -RG
248
+
249
+ # DEFINE LQG CONTROLLER (cf. Correia et al, 2017)
250
+ class CTRL:
251
+ def __init__(self, A, B, C, K, L):
252
+ self.I = np.eye(nlayer+5)
253
+ self.K = np.copy(K)
254
+ self.L = np.copy(L)
255
+ self.B_KCB = B - self.K @ C @ B
256
+ self.KCA_A = self.K @ C @ A - A
257
+ def __call__(self, z):
258
+ if hasattr(z, '__len__'): # object is iterable
259
+ return [self.__call__(elem) for elem in z]
260
+ else:
261
+ L_Lambda_e = self.L @ np.linalg.pinv(self.I + self.KCA_A/z) # Eq 44 du papier
262
+ return - (L_Lambda_e@self.K)[0,0] / (1+L_Lambda_e@self.B_KCB/z)[0,0]
263
+
264
+ # ITERATE OVER SPATIAL FREQUENCIES
265
+ for i in range(nfreq):
266
+
267
+ if verbose and ((((i+1)%10) == 0) or (i == (nfreq-1))):
268
+ print('\rLQG controller %4u/%u'%(i+1,nfreq), end='')
269
+
270
+ nu = vx*fx[i] + vy*fy[i]
271
+ ccx = 2 - np.cos(2*np.pi*Ts*fx[i]*delta_wind_speed/2)
272
+ ccy = 2 - np.cos(2*np.pi*Ts*fy[i]*delta_wind_speed/2)
273
+ wind_avg_x = ccx - np.sqrt(ccx**2 - 1) # np.sinc(Ts*fx[i]*delta_wind_speed) * np.sinc(Ts*fy[i]*delta_wind_speed) # windspeed averaging (uncertainty)
274
+ wind_avg_y = ccy - np.sqrt(ccy**2 - 1)
275
+ a_jj = np.exp(2j*np.pi*Ts*nu) * eigval_dump * poke_freq_avg * wind_avg_x * wind_avg_y
276
+
277
+ np.fill_diagonal(A[0:nlayer,0:nlayer], a_jj)
278
+ A[nlayer,0:nlayer] = a_jj
279
+
280
+ # MODEL NOISE (EXCITATION)
281
+ V[0:nlayer, 0:nlayer] = phase_psd[i] * np.diag(cn2dh_ratio) * (1-np.abs(a_jj)**2) # Yule-Walker
282
+
283
+ # MEASUREMENT NOISE
284
+ W = np.eye(1) * noise_psd[i]
285
+
286
+ # REGUL COMMANDE #TODO: pondérer par rapport à Q
287
+ logging.debug('LQG command matrix should be properly scaled.')
288
+ R = np.ones(1) * 1e-3
289
+
290
+ P = solve_discrete_are(np.conjugate(A.T), C.T, V, W, balanced=True)
291
+ K = P@C.T@np.linalg.pinv(C@P@C.T+W) # Kalman estimation gain
292
+
293
+ S = solve_discrete_are(A, B, Q, R, balanced=True)
294
+ L = np.linalg.pinv(B.T@S@B+R)@B.T@S@A # command gain
295
+
296
+ controllers += [CTRL(A, B, C, K, L)]
297
+
298
+ return controllers
299
+
300
+
301
+ #%% RTC CLASS
302
+ class RTC:
303
+ def __init__(self, dictionary):
304
+ self.kp = 0.0 # proportional gain
305
+ self.leak = 1.0 # leaky gain (default = no leaky)
306
+ self.discrete = True # discrete time controler
307
+ self.predictive_factor = 1 # temporal PSD reducing due to predictive controler
308
+ check_dictionary(dictionary, 'rtc')
309
+ for k in INFO_RTC.keys():
310
+ setattr(self, k, INFO_RTC[k][0](dictionary[k]))
311
+
312
+ def __repr__(self):
313
+ s = 'aopera.RTC\n'
314
+ s += '-----------\n'
315
+ s += 'freq : %u Hz\n'%self.freq
316
+ s += 'delay : %.1f ms\n'%self.delay
317
+ s += 'ki : %.2f\n'%self.ki
318
+ if self.predictive_factor != 1:
319
+ s += 'predic: %.2f\n'%self.predictive_factor
320
+ return s
321
+
322
+ @staticmethod
323
+ def from_file(filepath, category='rtc'):
324
+ return RTC(read_config_file(filepath, category))
325
+
326
+ @staticmethod
327
+ def from_file_tiptop(filepath):
328
+ return RTC(read_config_tiptop(filepath)[3])
329
+
330
+ @staticmethod
331
+ def from_oopao(ao_freq, oopao_frame_delay, gainCL, leak=1):
332
+ rtc = RTC({'freq':ao_freq, 'ki':gainCL, 'delay':(oopao_frame_delay-1)/ao_freq*1000})
333
+ rtc.leak = leak
334
+ return rtc
335
+
336
+ @property
337
+ def nb_frame_delay(self):
338
+ return self.delay*1e-3 * self.freq
339
+
340
+ @property
341
+ def bandwidth(self):
342
+ return bandwidth(self.ki, self.nb_frame_delay, self.freq)
343
+
344
+ @property
345
+ def bandwidth_noise(self):
346
+ return bandwidth_noise(self.ki, self.nb_frame_delay, self.freq)
347
+
348
+ def open_loop_transfer(self, ft):
349
+ return open_loop_transfer(ft, self.freq, self.ki, self.nb_frame_delay, kp=self.kp, discrete=self.discrete, leak=self.leak)
350
+
351
+ def closed_loop_transfer(self, ft):
352
+ return closed_loop_transfer(ft, self.freq, self.ki, self.nb_frame_delay, kp=self.kp, discrete=self.discrete, leak=self.leak)
353
+
354
+ def noise_transfer(self, ft):
355
+ return noise_transfer(ft, self.freq, self.ki, self.nb_frame_delay, kp=self.kp, discrete=self.discrete, leak=self.leak)
aopera/data/ekarus.ini ADDED
@@ -0,0 +1,45 @@
1
+ [source_science]
2
+ ; central wavelength [nm]
3
+ wvl_nm = 1400
4
+ ; zenithal angle [deg]
5
+ zenith_deg = 30
6
+
7
+ [source_wfs]
8
+ ; central wavelength [nm]
9
+ wvl_nm = 635
10
+ ; flux [ph/m²/s]
11
+ flux = 1e8
12
+ ; source size [arcsec]
13
+ size = 0
14
+ ; separation distance [arcsec]
15
+ separation = 0.
16
+ ; separation angle [deg]
17
+ angle = 0
18
+
19
+ [pupil]
20
+ ; diameter [m]
21
+ diameter = 1.8
22
+ ; central obstruction diameter ratio
23
+ occultation = 0.3
24
+ ; number of actuators across diameter
25
+ nact = 32
26
+ ; ratio of number of controlled modes vs total nb of modes
27
+ nmode_ratio = 0.9
28
+
29
+ [rtc]
30
+ ; AO loop frequency [Hz]
31
+ freq = 1000
32
+ ; RTC delay [ms]
33
+ delay = 1
34
+ ; integrator gain
35
+ ki = 0.5
36
+
37
+ [pwfs]
38
+ ; number of lenslet across diameter
39
+ lenslet = 50
40
+ ; readout noise [e-/pix]
41
+ ron = 0.3
42
+ ; is the camera an EMCCD
43
+ emccd = true
44
+ ; modulation radius [lambda/D]
45
+ modulation = 3
@@ -0,0 +1,43 @@
1
+ [source_science]
2
+ ; central wavelength [nm]
3
+ wvl_nm = 2200
4
+ ; zenithal angle [deg]
5
+ zenith_deg = 30
6
+
7
+ [source_wfs]
8
+ ; central wavelength [nm]
9
+ wvl_nm = 850
10
+ ; flux [ph/m²/s] magnitude 8, donc fort flux, je me base sur AO analysis : 84 ph/frame/sous-pupille @ 500Hz
11
+ flux = 7e6
12
+ ; source size [arcsec]
13
+ size = 2.5
14
+ ; separation distance [arcsec]
15
+ separation = 0.
16
+ ; separation angle [deg]
17
+ angle = 0
18
+
19
+ [pupil]
20
+ ; diameter [m]
21
+ diameter = 38.
22
+ ; central obstruction diameter ratio
23
+ occultation = 0.3
24
+ ; number of actuators across diameter
25
+ nact = 74
26
+
27
+ [rtc]
28
+ ; AO loop frequency [Hz]
29
+ freq = 500
30
+ ; RTC delay [ms]
31
+ delay = 2
32
+ ; integrator gain
33
+ ki = 0.5
34
+
35
+ [pwfs]
36
+ ; number of lenslet across diameter
37
+ lenslet = 100
38
+ ; readout noise [e-/pix]
39
+ ron = 1.0
40
+ ; is the camera an EMCCD
41
+ emccd = true
42
+ ; modulation radius [lambda/D]
43
+ modulation = 3
aopera/data/ohp.ini ADDED
@@ -0,0 +1,13 @@
1
+ [atmosphere]
2
+ ; seeing at 550 nm [arcsec]
3
+ seeing = 2.0
4
+ ; layers turbulence ratio
5
+ cn2dh_ratio = [8.672e-01, 3.480e-02, 9.700e-03, 1.180e-02, 5.700e-03, 4.300e-03, 3.700e-03, 3.200e-03, 2.500e-03, 1.800e-03, 1.200e-03, 1.100e-03, 1.100e-03, 1.800e-03, 4.100e-03, 1.000e-02, 1.490e-02, 9.600e-03, 4.700e-03, 3.100e-03, 1.900e-03, 9.000e-04, 5.000e-04, 2.000e-04, 1.000e-04, 1.000e-04, 1.000e-04]
6
+ ; layers altitudes [m]
7
+ altitude = [0, 40, 84, 212, 477, 839, 1321, 1948, 2728, 3650, 4673, 5735, 6801, 7869, 8939, 10028, 11175, 12381, 13629, 14910, 16228, 17626, 19142, 20814, 22685, 24773, 27135]
8
+ ; turbulence external scale [m]
9
+ lext = 30
10
+ ; wind speed [m/s]
11
+ wind_speed = [ 5.39, 5.4, 5.42, 5.47, 5.59, 5.79, 6.15, 6.81, 8.05, 10.26, 13.8 , 18.65, 24.23, 29.57, 33.47, 34.87, 33.14, 28.4 , 21.95, 15.6 , 10.65, 7.47, 5.84, 5.21, 5.03, 5. , 5. ]
12
+ ; wind direction [deg]
13
+ wind_direction = [ 0, 3, 6, 10, 13, 17, 20, 24, 27, 31, 34, 38, 41, 45, 48, 51, 55, 58, 62, 65, 69, 72, 76, 79, 83, 86, 90]
@@ -0,0 +1,45 @@
1
+ [source_science]
2
+ ; central wavelength [nm]
3
+ wvl_nm = 1400
4
+ ; zenithal angle [deg]
5
+ zenith_deg = 30
6
+
7
+ [source_wfs]
8
+ ; central wavelength [nm]
9
+ wvl_nm = 635
10
+ ; flux [ph/m²/s]
11
+ flux = 1e9
12
+ ; source size [arcsec]
13
+ size = 0
14
+ ; separation distance [arcsec]
15
+ separation = 0.
16
+ ; separation angle [deg]
17
+ angle = 0
18
+
19
+ [pupil]
20
+ ; diameter [m]
21
+ diameter = 1.52
22
+ ; central obstruction diameter ratio
23
+ occultation = 0.3
24
+ ; number of actuators across diameter
25
+ nact = 16
26
+ ; ratio of number of controlled modes vs total nb of modes
27
+ nmode_ratio = 0.9
28
+
29
+ [rtc]
30
+ ; AO loop frequency [Hz]
31
+ freq = 500
32
+ ; RTC delay [ms]
33
+ delay = 1.7
34
+ ; integrator gain
35
+ ki = 0.5
36
+
37
+ [pwfs]
38
+ ; number of lenslet across diameter
39
+ lenslet = 77
40
+ ; readout noise [e-/pix]
41
+ ron = 0.5
42
+ ; is the camera an EMCCD
43
+ emccd = true
44
+ ; modulation radius [lambda/D]
45
+ modulation = 5
@@ -0,0 +1,13 @@
1
+ [atmosphere]
2
+ ; seeing at 550 nm [arcsec]
3
+ seeing = 0.8
4
+ ; layers turbulence ratio
5
+ cn2dh_ratio = [0.241954, 0.119977, 0.0968817, 0.0589889, 0.0472911, 0.0472911, 0.0472911, 0.0472911, 0.0398925, 0.0323939, 0.0161969, 0.0260951, 0.0155971, 0.0103980, 0.00999811, 0.0119977, 0.00400924, 0.0139974, 0.0129975, 0.00700868, 0.0159970, 0.0258951, 0.0190964, 0.00986813, 0.00616883, 0.00400924, 0.00246953, 0.00215959, 0.00184965, 0.00135974, 0.00110979, 0.000616883, 0.000925825, 0.000493907, 0.000431918]
6
+ ; layers altitudes [m]
7
+ altitude = [30, 90, 150, 200, 245, 300, 390, 600, 1130, 1880, 2630, 3500, 4500, 5500, 6500, 7500, 8500, 9500, 10500, 11500, 12500, 13500, 14500, 15500, 16500, 17500, 18500, 19500, 20500, 21500, 22500, 23500, 24500, 25500, 26500]
8
+ ; turbulence external scale [m]
9
+ lext = 50
10
+ ; wind speed [m/s]
11
+ wind_speed = [5.5, 5.5, 5.1, 5.5, 5.6, 5.7, 5.8, 6.0, 6.5, 7.0, 7.5, 8.5, 9.5, 11.5, 17.5, 23.0, 26.0, 29.0, 32.0, 27.0, 22.0, 14.5, 9.5, 6.3, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.0]
12
+ ; wind direction [deg]
13
+ wind_direction = [0, -10, 0, 0, 10, 20, 0, 0, 0, -20, 0, 0, -10, 0, 10, -20, 10, 0, -20, -20, 0, -20, 0, 0, 80, 80, 70, 60, 90, 80, 80, 100, 70, 80, 70]
aopera/data/sphere.ini ADDED
@@ -0,0 +1,45 @@
1
+ [source_science]
2
+ ; central wavelength with Zimpol filter N_R [nm]
3
+ wvl_nm = 646
4
+ ; zenithal angle [deg]
5
+ zenith_deg = 30
6
+
7
+ [source_wfs]
8
+ ; central wavelength [nm]
9
+ wvl_nm = 600
10
+ ; flux [ph/m²/s]
11
+ flux = 1e9
12
+ ; source size [arcsec]
13
+ size = 0
14
+ ; separation distance [arcsec]
15
+ separation = 0.
16
+ ; separation angle [deg]
17
+ angle = 0
18
+
19
+ [pupil]
20
+ ; diameter [m]
21
+ diameter = 8
22
+ ; central obstruction diameter ratio
23
+ occultation = 0.14
24
+ ; number of actuators across diameter
25
+ nact = 41
26
+
27
+ [rtc]
28
+ ; AO loop frequency [Hz]
29
+ freq = 1200
30
+ ; RTC delay [ms]
31
+ delay = 1.14
32
+ ; integrator gain
33
+ ki = 0.4
34
+
35
+ [shwfs]
36
+ ; number of lenslet across diameter
37
+ lenslet = 40
38
+ ; readout noise [e-/pix]
39
+ ron = 0.3
40
+ ; is the camera an EMCCD
41
+ emccd = true
42
+ ; spot sampling
43
+ samp = 2
44
+ ; total nb pixels for center of gravity
45
+ npix_cog = 10