4
4
import numpy as np
5
5
import matplotlib .pyplot as plt
6
6
from matplotlib .ticker import FormatStrFormatter
7
- import pdb
7
+ try :
8
+ import ipdb
9
+ except :
10
+ #The following ling is dodgy, but still enables set_trace()
11
+ import pdb as ipdb
8
12
import scipy .ndimage as nd
9
13
import scipy .linalg as la
10
14
import matplotlib .cm as cm
@@ -87,6 +91,8 @@ def __init__(self,
87
91
self .wfs = wfs
88
92
self .atm = atm
89
93
self .dm_poke_scale = dm_poke_scale
94
+ self .response_matrix = None
95
+ self .reconstructor = None
90
96
91
97
#Add an atmosphere to all wavefronts.
92
98
for wf in self .wavefronts :
@@ -95,7 +101,6 @@ def __init__(self,
95
101
#############################################################################################################
96
102
def psf_dl (self , plate_scale_as_px ,
97
103
psf_ix = None ,
98
- band = None ,
99
104
crop = True , # Whether or not to crop the PSF. If set to False, the below two arguments are irrelevant.
100
105
psf_sz_cropped = None , # Size of the PSF. By default cropped at the 10th Airy ring
101
106
psf_sigma_limit_N_os = TENTH_AIRY_RING , # Corresponds to 10 Airy rings
@@ -163,7 +168,7 @@ def find_response_matrix(self,mode='onebyone',amplitude=1e-7):
163
168
#Check that poking in both directions is equivalent!
164
169
if (np .sum (wfs_plus * wfs_minus )/ np .sum (wfs_plus * wfs_plus ) > - 0.9 ):
165
170
print ("WARNING: Poking the DM is assymetric!!!" )
166
- # pdb .set_trace()
171
+ # ipdb .set_trace()
167
172
168
173
# Taking the mean response value.
169
174
self .response_matrix [i ] = 0.5 * (wfs_plus - wfs_minus ).flatten ()
@@ -264,8 +269,6 @@ def correct_twice(self,plotit=False):
264
269
return [measurements0 ,measurements1 ,measurements2 ],[im0 ,im1 ,im2 ]
265
270
266
271
267
-
268
-
269
272
#############################################################################################################
270
273
def run_loop (self , dt ,
271
274
mode = 'integrator' ,
@@ -339,19 +342,30 @@ def run_loop(self, dt,
339
342
else :
340
343
psf_sz_cropped = psf_sz
341
344
345
+ #Make plate_scale_as_px for Nyquist sampling of the full size.
346
+ #See XXX below for a bug.
347
+ if not plate_scale_as_px :
348
+ plate_scale_rad_px = self .wavefronts [psf_ix ].wave / (self .wavefronts [psf_ix ].sz * self .wavefronts [psf_ix ].m_per_px )
349
+ plate_scale_as_px = np .degrees (plate_scale_rad_px ) * 3600
350
+ plate_scale_as_px_in = None
351
+ else :
352
+ plate_scale_as_px_in = plate_scale_as_px
353
+
342
354
# Arrays to hold images
343
355
psfs_cropped = np .zeros ((niter , psf_sz_cropped , psf_sz_cropped ))# at the psf_ix wavelength
344
356
345
357
""" AO Control loop """
346
358
print ("Starting the AO control loop with control logic mode '%s'..." % mode )
347
359
for k in range (niter ):
348
- #------------------ AO CONTROL ------------------#
349
- print ("Iteration %d..." % (k + 1 ))
350
- # Evolve the atmosphere & update the wavefront fields to reflect the new atmosphere.
360
+ #------------------ EVOLVING THE ATMOSPHERE ------------------#
361
+ if ((k / niter ) * 100 ) % 10 == 0 :
362
+ print ("{:d}% done..." .format (int ((k / niter ) * 100 )))
363
+ # Evolve the atmosphere & update the wavefront fields to reflect the new atmosphere.
351
364
self .atm .evolve (dt * k )
352
365
for wf in self .wavefronts :
353
366
wf .atm_field ()
354
367
368
+ #------------------ AO CONTROL ------------------#
355
369
if mode == 'open loop' :
356
370
# We still measure the wavefront for plotting.
357
371
self .wfs .sense ()
@@ -374,13 +388,14 @@ def run_loop(self, dt,
374
388
raise UserWarning
375
389
coefficients_current = coefficients_next ; # Update the DM coefficients.
376
390
391
+ #-------------------- SAVING PSF ----------------------#
377
392
# Create the PSF
378
- psf = self . wavefronts [ psf_ix ]. image ( plate_scale_as_px = plate_scale_as_px )
379
- psf /= sum ( psf . flatten ())
380
- # Saving the PSF.
393
+ # NB if the following line has non-none, then we have a uint 8 error XXX
394
+ psf = self . wavefronts [ psf_ix ]. image ( plate_scale_as_px = plate_scale_as_px_in )
395
+ psf /= np . sum ( psf . flatten ())
381
396
psfs_cropped [k ] = centre_crop (psf , psf_sz_cropped )
382
397
383
- # Plotting
398
+ #------------------ PLOTTING ------------------#
384
399
if plotit & ((k % nframesbetweenplots ) == 0 ):
385
400
if k == 0 :
386
401
axes = []
@@ -405,6 +420,7 @@ def run_loop(self, dt,
405
420
plt .gca ().xaxis .set_major_formatter (FormatStrFormatter ('%.2f\" ' ))
406
421
plt .gca ().yaxis .set_major_formatter (FormatStrFormatter ('%.2f\" ' ))
407
422
plt .colorbar (plots [- 1 ],fraction = COLORBAR_FRACTION , pad = COLORBAR_PAD )
423
+ ipdb .set_trace ()
408
424
else :
409
425
# Update the plots
410
426
plot_wfs .set_data (self .wfs .im )
@@ -416,51 +432,5 @@ def run_loop(self, dt,
416
432
417
433
return psfs_cropped
418
434
419
- #############################################################################################################
420
- def _plot_ao_loop_iteration (self , k , plot_sz_px ):
421
- """ Plot the WFS detector image, phase and psf in an iteration of the AO loop. """
422
- if k == 0 :
423
- axes = []
424
- plots = []
425
- plt .rc ('text' , usetex = True )
426
-
427
- # WFS plot
428
- fig_wfs = mu .newfigure (2 ,2 )
429
- ax_wfs = fig_wfs .add_subplot (111 ) # WFS detector image
430
- ax_wfs .title .set_text (r'WFS detector' )
431
- ax_wfs .axis ( [0 ,self .wavefronts [0 ].sz ,0 ,self .wavefronts [0 ].sz ] )
432
- plot_wfs = ax_wfs .imshow (self .wfs .im ,interpolation = 'nearest' ,cmap = cm .gray )
433
-
434
- fig = mu .newfigure (width = 2 ,height = 1 )
435
-
436
- # Phase
437
- axes .append (fig .add_subplot (N_science_imgs ,2 ,2 * j + 1 ))
438
- axes [- 1 ].title .set_text (r'Corrected phase ($\lambda$ = %d nm)' % (self .wavefronts [self .image_ixs [j ]].wave * 1e9 ))
439
- plots .append (axes [- 1 ].imshow (np .angle (self .wavefronts [self .image_ixs [j ]].field )* self .wavefronts [self .image_ixs [j ]].pupil ,interpolation = 'nearest' , cmap = cm .gist_rainbow , vmin = - np .pi , vmax = np .pi ))
440
- mu .colourbar (plots [- 1 ])
441
-
442
- # Science image
443
- axes .append (fig .add_subplot (N_science_imgs ,2 ,2 * j + 2 ))
444
- axes [- 1 ].title .set_text (r'Science Image ($\lambda$ = %d nm)' % (self .wavefronts [self .image_ixs [j ]].wave * 1e9 ))
445
- pad_x = max ((imsize - plot_sz_px [0 ]) // 2 , 0 )
446
- pad_y = max ((imsize - plot_sz_px [1 ]) // 2 , 0 )
447
- im_cropped = psf_science [j ,pad_x :pad_x + min (imsize , plot_sz_px [0 ]),pad_y :pad_y + min (imsize , plot_sz_px [1 ])]
448
- plots .append (axes [- 1 ].imshow (im_cropped ,interpolation = 'nearest' , cmap = cm .gist_heat , norm = LogNorm ()))
449
- mu .colourbar (plots [- 1 ])
450
- else :
451
- # Update the plots
452
- plot_wfs .set_data (self .wfs .im )
453
- fig .suptitle (r'AO-corrected phase and science images, $k = %d, K_i = %.2f, K_{leak} = %.2f$' % (k , K_i , K_leak ))
454
- for j in range (N_science_imgs ):
455
- plots [2 * j ].set_data (np .angle (self .wavefronts [self .image_ixs [j ]].field )* self .wavefronts [self .image_ixs [j ]].pupil )
456
- pad_x = max ((imsize - plot_sz_px [0 ]) // 2 , 0 )
457
- pad_y = max ((imsize - plot_sz_px [1 ]) // 2 , 0 )
458
- im_cropped = im_science [j ,pad_x :pad_x + min (imsize , plot_sz_px [0 ]),pad_y :pad_y + min (imsize , plot_sz_px [1 ])]
459
- plots [2 * j + 1 ].set_data (im_cropped )
460
-
461
- plt .draw ()
462
- plt .pause (0.00001 ) # Need this to plot on some machines.
463
-
464
-
465
435
466
436
0 commit comments