Adaptive optics with a Shack-Hartmann wavefront sensor ====================================================== We will simulate a closed-loop adaptive optics system, based on the the Spectro-Polarimetric High-contrast Exoplanet REsearch (SPHERE) adaptive optics (AO) system, that uses a Shack-Hartmann WFS. We will simulate calibration and on-sky operation of this simulated AO system. We first start by importing the relevant python modules. .. code:: ipython3 from hcipy import * from progressbar import progressbar import numpy as np import matplotlib.pyplot as plt import scipy.ndimage as ndimage import time import os %matplotlib inline Simulating the VLT pupil ------------------------ We will model here the VLT pupil, of 8m in diameter (the primary mirror is 8.2m but the actual pupil is restricted by M2 to 8m, there is an extra margin used for choping in the infrared). .. code:: ipython3 telescope_diameter = 8. # meter central_obscuration = 1.2 # meter central_obscuration_ratio = central_obscuration / telescope_diameter spider_width = 0.05 # meter oversizing_factor = 16 / 15 We represent the pupil by a grid of 240px. This is the sampling used by the SH WFS of SPHERE, which is an EMCCD of 240x240px (6px per subapertures, with 40 subapertures on one diameter). To avoid some numerical problems at the edges, we oversize the pupil grid by a factor 16 / 15, e.g. the grid is represented by a grid of 240 \* 16 / 15 = 256 px. .. code:: ipython3 num_pupil_pixels = 240 * oversizing_factor pupil_grid_diameter = telescope_diameter * oversizing_factor pupil_grid = make_pupil_grid(num_pupil_pixels, pupil_grid_diameter) VLT_aperture_generator = make_obstructed_circular_aperture(telescope_diameter, central_obscuration_ratio, num_spiders=4, spider_width=spider_width) VLT_aperture = evaluate_supersampled(VLT_aperture_generator, pupil_grid, 4) The factor 4 indicates that each pixel will be evaluated with 4x supersampling, effectively averaging 4x4=16 subpixels for each pixel. .. code:: ipython3 imshow_field(VLT_aperture, cmap='gray') plt.xlabel('x position(m)') plt.ylabel('y position(m)') plt.colorbar() plt.show() .. image:: output_8_0.png As shown above, the pupil is not exactly that of the VLT (the 4 spiders of the VLT intersect on the perimetre of M2, and not at the center), but this is not important here. Incoming wavefront ------------------ Let’s assume we work with monochromatic light at 700nm for wavefront sensing and in the K band at 2.2 micron for the scientific channel .. code:: ipython3 wavelength_wfs = 0.7e-6 wavelength_sci = 2.2e-6 wf = Wavefront(VLT_aperture, wavelength_sci) wf.total_power = 1 Let visualize the corresponding diffraction pattern. To do so, we need to propagate the wavefront from the pupil to a focal plane. We assume here a perfect lens (see :class:``FraunhoferPropagator`` for details on the model). We also need to sample the electric field on a focal plane. We use here 4 pixels per resolution elements and set the field of view to 30 lambda/D in radius at the science wavelength. .. code:: ipython3 spatial_resolution = wavelength_sci / telescope_diameter focal_grid = make_focal_grid(q=4, num_airy=30, spatial_resolution=spatial_resolution) propagator = FraunhoferPropagator(pupil_grid, focal_grid) unaberrated_PSF = propagator.forward(wf).power imshow_field(np.log10(unaberrated_PSF / unaberrated_PSF.max()), cmap='inferno', vmin=-6) plt.colorbar() plt.show() .. image:: output_14_0.png Wavefront sensor ---------------- The WFS is a squared 40x40 Shack Hartmann WFS. The diameter of the beam needs to be reshaped with a magnifier, otherwise the spots are not resolved by the pupil grid: the spots have a size of :math:`F \lambda = 35\mathrm{\mu m}` with a F-ratio of 50. If the beam is 5mm, then 1px is 20 micron and we resolve the spots, albeit barely. .. code:: ipython3 f_number = 50 num_lenslets = 40 # 40 lenslets along one diameter sh_diameter = 5e-3 # m magnification = sh_diameter / telescope_diameter magnifier = Magnifier(magnification) .. code:: ipython3 shwfs = SquareShackHartmannWavefrontSensorOptics(pupil_grid.scaled(magnification), f_number, \ num_lenslets, sh_diameter) shwfse = ShackHartmannWavefrontSensorEstimator(shwfs.mla_grid, shwfs.micro_lens_array.mla_index) We assume a noiseless detector. In practice the EMCCD of SPHERE has RON of about 1 electron. .. code:: ipython3 camera = NoiselessDetector(focal_grid) Let’s look at the SH image for an undisturbed wavefront .. code:: ipython3 wf = Wavefront(VLT_aperture, wavelength_wfs) camera.integrate(shwfs(magnifier(wf)), 1) image_ref = camera.read_out() imshow_field(image_ref, cmap='inferno') plt.colorbar() plt.show() .. image:: output_22_0.png And zooming in a bit on some of the spots to see a little more detail… .. code:: ipython3 imshow_field(image_ref, cmap='inferno') plt.xlim(-0.001, 0.002) plt.ylim(-0.001, 0.002) plt.show() .. image:: output_24_0.png We select subapertures to use for wavefront sensing, based on their flux. The sub-pupils seeing the spiders receive about 75% of the flux of the unobscured sup-apertures. We want to include those, but we do not want to incldues superatures at the edge of the pupil that receive less than 50% of that flux. We therefore use a threshold at 50%. .. code:: ipython3 fluxes = ndimage.measurements.sum(image_ref, shwfse.mla_index, shwfse.estimation_subapertures) flux_limit = fluxes.max() * 0.5 estimation_subapertures = shwfs.mla_grid.zeros(dtype='bool') estimation_subapertures[shwfse.estimation_subapertures[fluxes > flux_limit]] = True shwfse = ShackHartmannWavefrontSensorEstimator(shwfs.mla_grid, shwfs.micro_lens_array.mla_index, estimation_subapertures) .. parsed-literal:: /var/folders/6m/q28z124x4pqff_16c497sx700002n8/T/ipykernel_98854/1645191210.py:1: DeprecationWarning: Please import `sum` from the `scipy.ndimage` namespace; the `scipy.ndimage.measurements` namespace is deprecated and will be removed in SciPy 2.0.0. fluxes = ndimage.measurements.sum(image_ref, shwfse.mla_index, shwfse.estimation_subapertures) Calculate reference slopes. .. code:: ipython3 slopes_ref = shwfse.estimate([image_ref]) Deformable mirror ----------------- Let’s assume we control 500 disk harmonic modes with the DM. .. code:: ipython3 num_modes = 500 dm_modes = make_disk_harmonic_basis(pupil_grid, num_modes, telescope_diameter, 'neumann') dm_modes = ModeBasis([mode / np.ptp(mode) for mode in dm_modes], pupil_grid) deformable_mirror = DeformableMirror(dm_modes) Calibrating the interaction matrix ---------------------------------- Then we need to calibrate the interaction matrix: you excite individually each mode of the DM and estimate the centroids of the spots. .. code:: ipython3 probe_amp = 0.01 * wavelength_wfs response_matrix = [] wf = Wavefront(VLT_aperture, wavelength_wfs) wf.total_power = 1 # Set up animation plt.figure(figsize=(10, 6)) anim = FFMpegWriter('response_matrix.mp4', framerate=5) for i in progressbar(range(num_modes)): slope = 0 # Probe the phase response amps = [-probe_amp, probe_amp] for amp in amps: deformable_mirror.flatten() deformable_mirror.actuators[i] = amp dm_wf = deformable_mirror.forward(wf) wfs_wf = shwfs(magnifier(dm_wf)) camera.integrate(wfs_wf, 1) image = camera.read_out() slopes = shwfse.estimate([image]) slope += amp * slopes / np.var(amps) response_matrix.append(slope.ravel()) # Only show all modes for the first 40 modes if i > 40 and (i + 1) % 20 != 0: continue # Plot mode response plt.clf() plt.suptitle('Mode %d / %d: DM shape' % (i + 1, num_modes)) plt.subplot(1,2,1) plt.title('DM surface') im1 = imshow_field(deformable_mirror.surface, cmap='RdBu', mask=VLT_aperture) plt.subplot(1,2,2) plt.title('SH spots') im2 = imshow_field(image) plt.quiver(shwfs.mla_grid.subset(shwfse.estimation_subapertures).x, shwfs.mla_grid.subset(shwfse.estimation_subapertures).y, slope[0,:], slope[1,:], color='white') anim.add_frame() response_matrix = ModeBasis(response_matrix) plt.close() anim.close() # Show created animation anim .. parsed-literal::  0% (0 of 500) | | Elapsed Time: 0:00:00 ETA: --:--:-- .. parsed-literal::  0% (1 of 500) | | Elapsed Time: 0:00:00 ETA: 0:01:06 .. parsed-literal::  0% (2 of 500) | | Elapsed Time: 0:00:00 ETA: 0:01:02 .. parsed-literal::  0% (3 of 500) | | Elapsed Time: 0:00:00 ETA: 0:01:07 .. parsed-literal::  0% (4 of 500) | | Elapsed Time: 0:00:00 ETA: 0:01:05 .. parsed-literal::  1% (5 of 500) | | Elapsed Time: 0:00:00 ETA: 0:01:04 .. parsed-literal::  1% (6 of 500) | | Elapsed Time: 0:00:00 ETA: 0:01:03 .. parsed-literal::  1% (7 of 500) | | Elapsed Time: 0:00:00 ETA: 0:01:02 .. parsed-literal::  1% (8 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:02 .. parsed-literal::  1% (9 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:02 .. parsed-literal::  2% (10 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:01 .. parsed-literal::  2% (11 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:01 .. parsed-literal::  2% (12 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:02 .. parsed-literal::  2% (13 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:01 .. parsed-literal::  2% (14 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:01 .. parsed-literal::  3% (15 of 500) | | Elapsed Time: 0:00:01 ETA: 0:01:01 .. parsed-literal::  3% (16 of 500) | | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  3% (17 of 500) | | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  3% (18 of 500) | | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  3% (19 of 500) | | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  4% (20 of 500) | | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  4% (21 of 500) | | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  4% (22 of 500) |# | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  4% (23 of 500) |# | Elapsed Time: 0:00:02 ETA: 0:01:00 .. parsed-literal::  4% (24 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  5% (25 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  5% (26 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  5% (27 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  5% (28 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  5% (29 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  6% (30 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  6% (31 of 500) |# | Elapsed Time: 0:00:03 ETA: 0:00:59 .. parsed-literal::  6% (32 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  6% (33 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  6% (34 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  7% (35 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  7% (36 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  7% (37 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  7% (38 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  7% (39 of 500) |# | Elapsed Time: 0:00:04 ETA: 0:00:58 .. parsed-literal::  8% (40 of 500) |# | Elapsed Time: 0:00:05 ETA: 0:00:57 .. parsed-literal::  8% (41 of 500) |# | Elapsed Time: 0:00:05 ETA: 0:00:57 .. parsed-literal::  9% (45 of 500) |## | Elapsed Time: 0:00:05 ETA: 0:00:52 .. parsed-literal::  10% (51 of 500) |## | Elapsed Time: 0:00:05 ETA: 0:00:47 .. parsed-literal::  11% (56 of 500) |## | Elapsed Time: 0:00:05 ETA: 0:00:43 .. parsed-literal::  12% (60 of 500) |## | Elapsed Time: 0:00:05 ETA: 0:00:41 .. parsed-literal::  12% (64 of 500) |## | Elapsed Time: 0:00:05 ETA: 0:00:38 .. parsed-literal::  13% (69 of 500) |### | Elapsed Time: 0:00:05 ETA: 0:00:36 .. parsed-literal::  14% (74 of 500) |### | Elapsed Time: 0:00:05 ETA: 0:00:34 .. parsed-literal::  15% (79 of 500) |### | Elapsed Time: 0:00:06 ETA: 0:00:32 .. parsed-literal::  16% (80 of 500) |### | Elapsed Time: 0:00:06 ETA: 0:00:32 .. parsed-literal::  16% (83 of 500) |### | Elapsed Time: 0:00:06 ETA: 0:00:31 .. parsed-literal::  17% (88 of 500) |#### | Elapsed Time: 0:00:06 ETA: 0:00:29 .. parsed-literal::  18% (93 of 500) |#### | Elapsed Time: 0:00:06 ETA: 0:00:28 .. parsed-literal::  19% (98 of 500) |#### | Elapsed Time: 0:00:06 ETA: 0:00:26 .. parsed-literal::  20% (100 of 500) |#### | Elapsed Time: 0:00:06 ETA: 0:00:26 .. parsed-literal::  21% (105 of 500) |#### | Elapsed Time: 0:00:06 ETA: 0:00:25 .. parsed-literal::  21% (108 of 500) |#### | Elapsed Time: 0:00:06 ETA: 0:00:25 .. parsed-literal::  22% (113 of 500) |#### | Elapsed Time: 0:00:07 ETA: 0:00:23 .. parsed-literal::  23% (118 of 500) |##### | Elapsed Time: 0:00:07 ETA: 0:00:23 .. parsed-literal::  24% (120 of 500) |##### | Elapsed Time: 0:00:07 ETA: 0:00:23 .. parsed-literal::  25% (125 of 500) |##### | Elapsed Time: 0:00:07 ETA: 0:00:22 .. parsed-literal::  26% (130 of 500) |##### | Elapsed Time: 0:00:07 ETA: 0:00:21 .. parsed-literal::  26% (133 of 500) |##### | Elapsed Time: 0:00:07 ETA: 0:00:20 .. parsed-literal::  27% (138 of 500) |###### | Elapsed Time: 0:00:07 ETA: 0:00:20 .. parsed-literal::  28% (140 of 500) |###### | Elapsed Time: 0:00:07 ETA: 0:00:20 .. parsed-literal::  29% (145 of 500) |###### | Elapsed Time: 0:00:07 ETA: 0:00:19 .. parsed-literal::  30% (150 of 500) |###### | Elapsed Time: 0:00:08 ETA: 0:00:18 .. parsed-literal::  31% (155 of 500) |###### | Elapsed Time: 0:00:08 ETA: 0:00:18 .. parsed-literal::  31% (159 of 500) |###### | Elapsed Time: 0:00:08 ETA: 0:00:17 .. parsed-literal::  32% (160 of 500) |####### | Elapsed Time: 0:00:08 ETA: 0:00:17 .. parsed-literal::  33% (165 of 500) |####### | Elapsed Time: 0:00:08 ETA: 0:00:17 .. parsed-literal::  34% (170 of 500) |####### | Elapsed Time: 0:00:08 ETA: 0:00:16 .. parsed-literal::  35% (175 of 500) |####### | Elapsed Time: 0:00:08 ETA: 0:00:16 .. parsed-literal::  35% (178 of 500) |####### | Elapsed Time: 0:00:08 ETA: 0:00:15 .. parsed-literal::  36% (180 of 500) |####### | Elapsed Time: 0:00:08 ETA: 0:00:15 .. parsed-literal::  36% (184 of 500) |######## | Elapsed Time: 0:00:09 ETA: 0:00:15 .. parsed-literal::  37% (189 of 500) |######## | Elapsed Time: 0:00:09 ETA: 0:00:15 .. parsed-literal::  38% (194 of 500) |######## | Elapsed Time: 0:00:09 ETA: 0:00:14 .. parsed-literal::  39% (197 of 500) |######## | Elapsed Time: 0:00:09 ETA: 0:00:14 .. parsed-literal::  40% (200 of 500) |######## | Elapsed Time: 0:00:09 ETA: 0:00:14 .. parsed-literal::  40% (203 of 500) |######## | Elapsed Time: 0:00:09 ETA: 0:00:14 .. parsed-literal::  41% (208 of 500) |######### | Elapsed Time: 0:00:09 ETA: 0:00:13 .. parsed-literal::  42% (213 of 500) |######### | Elapsed Time: 0:00:09 ETA: 0:00:13 .. parsed-literal::  43% (216 of 500) |######### | Elapsed Time: 0:00:09 ETA: 0:00:12 .. parsed-literal::  44% (220 of 500) |######### | Elapsed Time: 0:00:10 ETA: 0:00:12 .. parsed-literal::  45% (225 of 500) |######### | Elapsed Time: 0:00:10 ETA: 0:00:12 .. parsed-literal::  45% (228 of 500) |########## | Elapsed Time: 0:00:10 ETA: 0:00:12 .. parsed-literal::  46% (233 of 500) |########## | Elapsed Time: 0:00:10 ETA: 0:00:11 .. parsed-literal::  47% (238 of 500) |########## | Elapsed Time: 0:00:10 ETA: 0:00:11 .. parsed-literal::  48% (240 of 500) |########## | Elapsed Time: 0:00:10 ETA: 0:00:11 .. parsed-literal::  49% (245 of 500) |########## | Elapsed Time: 0:00:10 ETA: 0:00:11 .. parsed-literal::  50% (251 of 500) |########### | Elapsed Time: 0:00:10 ETA: 0:00:10 .. parsed-literal::  50% (254 of 500) |########### | Elapsed Time: 0:00:10 ETA: 0:00:10 .. parsed-literal::  52% (260 of 500) |########### | Elapsed Time: 0:00:11 ETA: 0:00:10 .. parsed-literal::  53% (266 of 500) |########### | Elapsed Time: 0:00:11 ETA: 0:00:09 .. parsed-literal::  54% (272 of 500) |########### | Elapsed Time: 0:00:11 ETA: 0:00:09 .. parsed-literal::  55% (277 of 500) |############ | Elapsed Time: 0:00:11 ETA: 0:00:09 .. parsed-literal::  56% (280 of 500) |############ | Elapsed Time: 0:00:11 ETA: 0:00:09 .. parsed-literal::  57% (285 of 500) |############ | Elapsed Time: 0:00:11 ETA: 0:00:08 .. parsed-literal::  58% (291 of 500) |############ | Elapsed Time: 0:00:11 ETA: 0:00:08 .. parsed-literal::  59% (297 of 500) |############# | Elapsed Time: 0:00:11 ETA: 0:00:08 .. parsed-literal::  60% (300 of 500) |############# | Elapsed Time: 0:00:12 ETA: 0:00:08 .. parsed-literal::  60% (304 of 500) |############# | Elapsed Time: 0:00:12 ETA: 0:00:07 .. parsed-literal::  62% (310 of 500) |############# | Elapsed Time: 0:00:12 ETA: 0:00:07 .. parsed-literal::  63% (316 of 500) |############# | Elapsed Time: 0:00:12 ETA: 0:00:07 .. parsed-literal::  64% (320 of 500) |############## | Elapsed Time: 0:00:12 ETA: 0:00:07 .. parsed-literal::  64% (323 of 500) |############## | Elapsed Time: 0:00:12 ETA: 0:00:06 .. parsed-literal::  65% (329 of 500) |############## | Elapsed Time: 0:00:12 ETA: 0:00:06 .. parsed-literal::  67% (335 of 500) |############## | Elapsed Time: 0:00:12 ETA: 0:00:06 .. parsed-literal::  68% (340 of 500) |############## | Elapsed Time: 0:00:13 ETA: 0:00:06 .. parsed-literal::  69% (346 of 500) |############### | Elapsed Time: 0:00:13 ETA: 0:00:05 .. parsed-literal::  69% (349 of 500) |############### | Elapsed Time: 0:00:13 ETA: 0:00:05 .. parsed-literal::  70% (354 of 500) |############### | Elapsed Time: 0:00:13 ETA: 0:00:05 .. parsed-literal::  71% (359 of 500) |############### | Elapsed Time: 0:00:13 ETA: 0:00:05 .. parsed-literal::  72% (360 of 500) |############### | Elapsed Time: 0:00:13 ETA: 0:00:05 .. parsed-literal::  73% (365 of 500) |################ | Elapsed Time: 0:00:13 ETA: 0:00:05 .. parsed-literal::  73% (368 of 500) |################ | Elapsed Time: 0:00:13 ETA: 0:00:04 .. parsed-literal::  74% (373 of 500) |################ | Elapsed Time: 0:00:13 ETA: 0:00:04 .. parsed-literal::  75% (378 of 500) |################ | Elapsed Time: 0:00:13 ETA: 0:00:04 .. parsed-literal::  76% (380 of 500) |################ | Elapsed Time: 0:00:14 ETA: 0:00:04 .. parsed-literal::  77% (385 of 500) |################ | Elapsed Time: 0:00:14 ETA: 0:00:04 .. parsed-literal::  78% (390 of 500) |################# | Elapsed Time: 0:00:14 ETA: 0:00:04 .. parsed-literal::  78% (393 of 500) |################# | Elapsed Time: 0:00:14 ETA: 0:00:03 .. parsed-literal::  79% (399 of 500) |################# | Elapsed Time: 0:00:14 ETA: 0:00:03 .. parsed-literal::  80% (400 of 500) |################# | Elapsed Time: 0:00:14 ETA: 0:00:03 .. parsed-literal::  81% (405 of 500) |################# | Elapsed Time: 0:00:14 ETA: 0:00:03 .. parsed-literal::  82% (410 of 500) |################## | Elapsed Time: 0:00:14 ETA: 0:00:03 .. parsed-literal::  83% (415 of 500) |################## | Elapsed Time: 0:00:14 ETA: 0:00:03 .. parsed-literal::  83% (418 of 500) |################## | Elapsed Time: 0:00:15 ETA: 0:00:02 .. parsed-literal::  84% (420 of 500) |################## | Elapsed Time: 0:00:15 ETA: 0:00:02 .. parsed-literal::  85% (425 of 500) |################## | Elapsed Time: 0:00:15 ETA: 0:00:02 .. parsed-literal::  86% (430 of 500) |################## | Elapsed Time: 0:00:15 ETA: 0:00:02 .. parsed-literal::  87% (435 of 500) |################### | Elapsed Time: 0:00:15 ETA: 0:00:02 .. parsed-literal::  88% (440 of 500) |################### | Elapsed Time: 0:00:15 ETA: 0:00:02 .. parsed-literal::  88% (444 of 500) |################### | Elapsed Time: 0:00:15 ETA: 0:00:01 .. parsed-literal::  89% (449 of 500) |################### | Elapsed Time: 0:00:15 ETA: 0:00:01 .. parsed-literal::  90% (454 of 500) |################### | Elapsed Time: 0:00:15 ETA: 0:00:01 .. parsed-literal::  91% (459 of 500) |#################### | Elapsed Time: 0:00:16 ETA: 0:00:01 .. parsed-literal::  92% (460 of 500) |#################### | Elapsed Time: 0:00:16 ETA: 0:00:01 .. parsed-literal::  92% (463 of 500) |#################### | Elapsed Time: 0:00:16 ETA: 0:00:01 .. parsed-literal::  93% (468 of 500) |#################### | Elapsed Time: 0:00:16 ETA: 0:00:01 .. parsed-literal::  94% (473 of 500) |#################### | Elapsed Time: 0:00:16 ETA: 0:00:00 .. parsed-literal::  95% (478 of 500) |##################### | Elapsed Time: 0:00:16 ETA: 0:00:00 .. parsed-literal::  96% (480 of 500) |##################### | Elapsed Time: 0:00:16 ETA: 0:00:00 .. parsed-literal::  97% (485 of 500) |##################### | Elapsed Time: 0:00:16 ETA: 0:00:00 .. parsed-literal::  97% (488 of 500) |##################### | Elapsed Time: 0:00:16 ETA: 0:00:00 .. parsed-literal::  98% (493 of 500) |##################### | Elapsed Time: 0:00:17 ETA: 0:00:00 .. parsed-literal::  99% (498 of 500) |##################### | Elapsed Time: 0:00:17 ETA: 0:00:00 .. parsed-literal:: 100% (500 of 500) |######################| Elapsed Time: 0:00:17 Time: 0:00:17 .. parsed-literal:: .. raw:: html We invert the interaction matrix using Tikhonov regularisation .. code:: ipython3 rcond = 1e-3 reconstruction_matrix = inverse_tikhonov(response_matrix.transformation_matrix, rcond=rcond) print(reconstruction_matrix.shape) .. parsed-literal:: (500, 2432) We initialise the DM with a random position by setting the DM actuators at random values. .. code:: ipython3 # Put actuators at random values, putting a little more power in low-order modes deformable_mirror.actuators = np.random.randn(num_modes) / (np.arange(num_modes) + 10) # Normalize the DM surface so that we get a reasonable surface RMS. deformable_mirror.actuators *= 0.3 * wavelength_sci / np.std(deformable_mirror.surface) imshow_field(deformable_mirror.phase_for(wavelength_wfs), mask=VLT_aperture, cmap='RdBu') plt.colorbar() plt.show() .. image:: output_37_0.png Closing the loop without atmospheric disturbance ------------------------------------------------ .. code:: ipython3 zero_magnitude_flux = 3.9e10 #3.9e10 photon/s for a mag 0 star stellar_magnitude = 5 delta_t = 1e-3 # sec, so a loop speed of 1kHz. wf_wfs = Wavefront(VLT_aperture, wavelength_wfs) wf_sci = Wavefront(VLT_aperture, wavelength_sci) wf_wfs.total_power = zero_magnitude_flux * 10**(-stellar_magnitude / 2.5) wf_sci.total_power = zero_magnitude_flux * 10**(-stellar_magnitude / 2.5) print("Photon flux per WFS frame {:g}".format(wf_wfs.total_power * delta_t)) .. parsed-literal:: Photon flux per WFS frame 390000 .. code:: ipython3 deformable_mirror.actuators = np.random.randn(num_modes) / (np.arange(num_modes) + 10) deformable_mirror.actuators *= 0.3 * wavelength_sci / np.std(deformable_mirror.surface) gain = 0.6 leakage = 0.01 num_iterations = 20 long_exposure = 0 # Set up animation plt.figure(figsize=(8, 8)) anim = FFMpegWriter('AO_simulation_without_turbulence.mp4', framerate=10) for timestep in progressbar(range(num_iterations)): # Propagate through SH-WFS wf_after_sh = shwfs(magnifier(deformable_mirror(wf_wfs))) # Propagate the NIR wavefront wf_sci_after_dm = propagator(deformable_mirror(wf_sci)) # Read out WFS camera camera.integrate(wf_after_sh, delta_t) wfs_image = camera.read_out() wfs_image = large_poisson(wfs_image).astype('float') # Calculate slopes from WFS image slopes = shwfse.estimate([wfs_image + 1e-10]) slopes -= slopes_ref slopes = slopes.ravel() # Perform wavefront control and set DM actuators deformable_mirror.actuators = (1 - leakage) * deformable_mirror.actuators - gain * reconstruction_matrix.dot(slopes) # Plotting plt.clf() plt.suptitle('Timestep %d / %d' % (timestep, num_iterations)) plt.subplot(2,2,1) plt.title('DM surface [$\\mu$m]') imshow_field(deformable_mirror.surface * 1e6, cmap='RdBu', vmin=-1, vmax=1, mask=VLT_aperture) plt.colorbar() plt.subplot(2,2,2) plt.title('WFS image [counts]') imshow_field(wfs_image, cmap='inferno') plt.colorbar() plt.subplot(2,2,3) plt.title('Instantaneous PSF at 2.2$\\mu$m [log]') imshow_field(np.log10(wf_sci_after_dm.power / wf_sci_after_dm.power.max()), vmin=-6, vmax=0, cmap='inferno') plt.colorbar() anim.add_frame() plt.close() anim.close() # Show created animation anim .. parsed-literal::  0% (0 of 20) | | Elapsed Time: 0:00:00 ETA: --:--:-- .. parsed-literal::  5% (1 of 20) |# | Elapsed Time: 0:00:00 ETA: 0:00:05 .. parsed-literal::  10% (2 of 20) |## | Elapsed Time: 0:00:00 ETA: 0:00:04 .. parsed-literal::  15% (3 of 20) |### | Elapsed Time: 0:00:00 ETA: 0:00:03 .. parsed-literal::  20% (4 of 20) |##### | Elapsed Time: 0:00:00 ETA: 0:00:03 .. parsed-literal::  25% (5 of 20) |###### | Elapsed Time: 0:00:01 ETA: 0:00:03 .. parsed-literal::  30% (6 of 20) |####### | Elapsed Time: 0:00:01 ETA: 0:00:02 .. parsed-literal::  35% (7 of 20) |######## | Elapsed Time: 0:00:01 ETA: 0:00:02 .. parsed-literal::  40% (8 of 20) |########## | Elapsed Time: 0:00:01 ETA: 0:00:02 .. parsed-literal::  45% (9 of 20) |########### | Elapsed Time: 0:00:01 ETA: 0:00:02 .. parsed-literal::  50% (10 of 20) |############ | Elapsed Time: 0:00:01 ETA: 0:00:01 .. parsed-literal::  55% (11 of 20) |############# | Elapsed Time: 0:00:02 ETA: 0:00:01 .. parsed-literal::  60% (12 of 20) |############## | Elapsed Time: 0:00:02 ETA: 0:00:01 .. parsed-literal::  65% (13 of 20) |############### | Elapsed Time: 0:00:02 ETA: 0:00:01 .. parsed-literal::  70% (14 of 20) |################ | Elapsed Time: 0:00:02 ETA: 0:00:01 .. parsed-literal::  75% (15 of 20) |################## | Elapsed Time: 0:00:02 ETA: 0:00:00 .. parsed-literal::  80% (16 of 20) |################### | Elapsed Time: 0:00:03 ETA: 0:00:00 .. parsed-literal::  85% (17 of 20) |#################### | Elapsed Time: 0:00:03 ETA: 0:00:00 .. parsed-literal::  90% (18 of 20) |##################### | Elapsed Time: 0:00:03 ETA: 0:00:00 .. parsed-literal::  95% (19 of 20) |###################### | Elapsed Time: 0:00:03 ETA: 0:00:00 .. parsed-literal:: 100% (20 of 20) |########################| Elapsed Time: 0:00:03 Time: 0:00:03 .. parsed-literal:: .. raw:: html Simulating the atmosphere ------------------------- Setting the atmospheric parameters: .. code:: ipython3 seeing = 0.6 # arcsec @ 500nm (convention) outer_scale = 40 # meter tau0 = 0.005 # seconds fried_parameter = seeing_to_fried_parameter(seeing) Cn_squared = Cn_squared_from_fried_parameter(fried_parameter, 500e-9) velocity = 0.314 * fried_parameter / tau0 print('r0 = {0:.1f}cm'.format(fried_parameter * 100)) print('L0 = {0:.1f}m'.format(outer_scale)) print('tau0 = {0:.1f}ms'.format(tau0 * 1000)) print('v = {0:.1f}m/s'.format(velocity)) .. parsed-literal:: r0 = 16.8cm L0 = 40.0m tau0 = 5.0ms v = 10.6m/s And creating the atmospheric model. For simplicity, we will only use a single atmospheric layer in this tutorial. .. code:: ipython3 layer = InfiniteAtmosphericLayer(pupil_grid, Cn_squared, outer_scale, velocity) phase_screen_phase = layer.phase_for(wavelength_wfs) # in radian phase_screen_opd = phase_screen_phase * (wavelength_wfs / (2 * np.pi)) * 1e6 imshow_field(phase_screen_opd, vmin=-6, vmax=6, cmap='RdBu') .. parsed-literal:: .. image:: output_44_1.png And making sure that the atmosphere looks correct. .. code:: ipython3 plt.figure(figsize=(5, 4)) anim = FFMpegWriter('atmospheric_turbulence.mp4', framerate=5) t_end = 1 n = 51 for t in np.linspace(0, t_end, n): layer.t = t phase_screen_phase = layer.phase_for(wavelength_wfs) # in radian phase_screen_opd = phase_screen_phase * (wavelength_wfs / (2 * np.pi)) * 1e6 # in um plt.clf() plt.suptitle('Time %.3f s' % t) plt.subplot(1,1,1) plt.title('Turbulent wavefront [$\\mu$m]') imshow_field(phase_screen_opd, vmin=-6, vmax=6, cmap='RdBu') plt.colorbar() anim.add_frame() plt.close() anim.close() # Show created animation anim .. raw:: html Closing the loop on-sky ----------------------- We can now put everything together. The light at optical wavelengths passes through the turbulent atmospheric layer, reflects off the DM and gets measured by the Shack-Hartmann wavefront sensor. The light at near-infrared wavelengths also passes through the atmosphere and also gets reflected off the DM, but then passes through the coronagraph to finally be detected on the science camera. We will show the current DM surface, the raw wavefront sensor image, the instanteneous non-coronagraphic PSF and an accumulated long-exposure coronagraphic PSF in the animation. .. code:: ipython3 layer.reset() deformable_mirror.flatten() gain = 0.3 leakage = 0.01 num_iterations = 750 burn_in_iterations = 5 coro = PerfectCoronagraph(VLT_aperture, 4) long_exposure = focal_grid.zeros() long_exposure_coro = focal_grid.zeros() # Set up animation plt.figure(figsize=(8, 8)) anim = FFMpegWriter('AO_simulation_with_turbulence.mp4', framerate=10) for timestep in progressbar(range(num_iterations)): layer.t = timestep * delta_t # Propagate through atmosphere and deformable mirror. wf_wfs_after_atmos = layer(wf_wfs) wf_wfs_after_dm = deformable_mirror(wf_wfs_after_atmos) # Propagate through SH-WFS wf_wfs_on_sh = shwfs(magnifier(wf_wfs_after_dm)) # Propagate the NIR wavefront wf_sci_focal_plane = propagator(deformable_mirror(layer(wf_sci))) wf_sci_coro = propagator(coro(deformable_mirror(layer(wf_sci)))) # Read out WFS camera camera.integrate(wf_wfs_on_sh, delta_t) wfs_image = camera.read_out() wfs_image = large_poisson(wfs_image).astype('float') # Accumulate long-exposure image if timestep >= burn_in_iterations: long_exposure += wf_sci_focal_plane.power / (num_iterations - burn_in_iterations) long_exposure_coro += wf_sci_coro.power / (num_iterations - burn_in_iterations) # Calculate slopes from WFS image slopes = shwfse.estimate([wfs_image + 1e-10]) slopes -= slopes_ref slopes = slopes.ravel() # Perform wavefront control and set DM actuators deformable_mirror.actuators = (1 - leakage) * deformable_mirror.actuators - gain * reconstruction_matrix.dot(slopes) # Plotting if timestep % 20 == 0: plt.clf() plt.suptitle('Timestep %d / %d' % (timestep, num_iterations)) plt.subplot(2,2,1) plt.title('DM surface [$\\mu$m]') imshow_field(deformable_mirror.surface * 1e6, cmap='RdBu', vmin=-2, vmax=2, mask=VLT_aperture) plt.colorbar() plt.subplot(2,2,2) plt.title('WFS image [counts]') imshow_field(wfs_image, cmap='inferno') plt.colorbar() plt.subplot(2,2,3) plt.title('Instantaneous PSF at 2.2$\\mu$m [log]') imshow_field(np.log10(wf_sci_focal_plane.power/ wf_sci_focal_plane.power.max()), vmin=-6, vmax=0, cmap='inferno') # plt.colorbar() if timestep >= burn_in_iterations: plt.subplot(2,2,4) plt.title('Average PSF at 2.2$\\mu$m [log]') imshow_field(np.log10(long_exposure_coro / long_exposure.max()), vmin=-6, vmax=0, cmap='inferno') plt.colorbar() anim.add_frame() plt.close() anim.close() # Show created animation anim .. parsed-literal::  0% (0 of 750) | | Elapsed Time: 0:00:00 ETA: --:--:-- .. parsed-literal::  0% (1 of 750) | | Elapsed Time: 0:00:00 ETA: 0:02:39 .. parsed-literal::  0% (4 of 750) | | Elapsed Time: 0:00:00 ETA: 0:00:59 .. parsed-literal::  0% (7 of 750) | | Elapsed Time: 0:00:00 ETA: 0:00:45 .. parsed-literal::  1% (10 of 750) | | Elapsed Time: 0:00:00 ETA: 0:00:39 .. parsed-literal::  1% (13 of 750) | | Elapsed Time: 0:00:00 ETA: 0:00:36 .. parsed-literal::  2% (16 of 750) | | Elapsed Time: 0:00:00 ETA: 0:00:34 .. parsed-literal::  2% (19 of 750) | | Elapsed Time: 0:00:00 ETA: 0:00:33 .. parsed-literal::  2% (21 of 750) | | Elapsed Time: 0:00:01 ETA: 0:00:40 .. parsed-literal::  3% (24 of 750) | | Elapsed Time: 0:00:01 ETA: 0:00:38 .. parsed-literal::  3% (27 of 750) | | Elapsed Time: 0:00:01 ETA: 0:00:36 .. parsed-literal::  3% (29 of 750) | | Elapsed Time: 0:00:01 ETA: 0:00:36 .. parsed-literal::  4% (32 of 750) | | Elapsed Time: 0:00:01 ETA: 0:00:35 .. parsed-literal::  4% (35 of 750) |# | Elapsed Time: 0:00:01 ETA: 0:00:34 .. parsed-literal::  5% (38 of 750) |# | Elapsed Time: 0:00:01 ETA: 0:00:33 .. parsed-literal::  5% (41 of 750) |# | Elapsed Time: 0:00:02 ETA: 0:00:37 .. parsed-literal::  5% (44 of 750) |# | Elapsed Time: 0:00:02 ETA: 0:00:36 .. parsed-literal::  6% (47 of 750) |# | Elapsed Time: 0:00:02 ETA: 0:00:35 .. parsed-literal::  6% (50 of 750) |# | Elapsed Time: 0:00:02 ETA: 0:00:34 .. parsed-literal::  7% (53 of 750) |# | Elapsed Time: 0:00:02 ETA: 0:00:33 .. parsed-literal::  7% (56 of 750) |# | Elapsed Time: 0:00:02 ETA: 0:00:33 .. parsed-literal::  7% (59 of 750) |# | Elapsed Time: 0:00:02 ETA: 0:00:32 .. parsed-literal::  8% (61 of 750) |# | Elapsed Time: 0:00:03 ETA: 0:00:34 .. parsed-literal::  8% (64 of 750) |# | Elapsed Time: 0:00:03 ETA: 0:00:34 .. parsed-literal::  8% (67 of 750) |## | Elapsed Time: 0:00:03 ETA: 0:00:33 .. parsed-literal::  9% (70 of 750) |## | Elapsed Time: 0:00:03 ETA: 0:00:33 .. parsed-literal::  9% (73 of 750) |## | Elapsed Time: 0:00:03 ETA: 0:00:32 .. parsed-literal::  10% (76 of 750) |## | Elapsed Time: 0:00:03 ETA: 0:00:32 .. parsed-literal::  10% (79 of 750) |## | Elapsed Time: 0:00:03 ETA: 0:00:31 .. parsed-literal::  10% (81 of 750) |## | Elapsed Time: 0:00:04 ETA: 0:00:33 .. parsed-literal::  11% (84 of 750) |## | Elapsed Time: 0:00:04 ETA: 0:00:32 .. parsed-literal::  11% (86 of 750) |## | Elapsed Time: 0:00:04 ETA: 0:00:32 .. parsed-literal::  11% (89 of 750) |## | Elapsed Time: 0:00:04 ETA: 0:00:31 .. parsed-literal::  12% (92 of 750) |## | Elapsed Time: 0:00:04 ETA: 0:00:31 .. parsed-literal::  12% (95 of 750) |## | Elapsed Time: 0:00:04 ETA: 0:00:31 .. parsed-literal::  13% (98 of 750) |### | Elapsed Time: 0:00:04 ETA: 0:00:30 .. parsed-literal::  13% (101 of 750) |## | Elapsed Time: 0:00:04 ETA: 0:00:32 .. parsed-literal::  13% (104 of 750) |### | Elapsed Time: 0:00:05 ETA: 0:00:31 .. parsed-literal::  14% (107 of 750) |### | Elapsed Time: 0:00:05 ETA: 0:00:31 .. parsed-literal::  14% (110 of 750) |### | Elapsed Time: 0:00:05 ETA: 0:00:30 .. parsed-literal::  15% (113 of 750) |### | Elapsed Time: 0:00:05 ETA: 0:00:30 .. parsed-literal::  15% (116 of 750) |### | Elapsed Time: 0:00:05 ETA: 0:00:30 .. parsed-literal::  15% (119 of 750) |### | Elapsed Time: 0:00:05 ETA: 0:00:29 .. parsed-literal::  16% (121 of 750) |### | Elapsed Time: 0:00:05 ETA: 0:00:30 .. parsed-literal::  16% (124 of 750) |### | Elapsed Time: 0:00:06 ETA: 0:00:30 .. parsed-literal::  16% (127 of 750) |### | Elapsed Time: 0:00:06 ETA: 0:00:29 .. parsed-literal::  17% (130 of 750) |### | Elapsed Time: 0:00:06 ETA: 0:00:29 .. parsed-literal::  17% (133 of 750) |### | Elapsed Time: 0:00:06 ETA: 0:00:29 .. parsed-literal::  18% (136 of 750) |### | Elapsed Time: 0:00:06 ETA: 0:00:28 .. parsed-literal::  18% (139 of 750) |#### | Elapsed Time: 0:00:06 ETA: 0:00:28 .. parsed-literal::  18% (141 of 750) |#### | Elapsed Time: 0:00:06 ETA: 0:00:29 .. parsed-literal::  19% (143 of 750) |#### | Elapsed Time: 0:00:06 ETA: 0:00:29 .. parsed-literal::  19% (146 of 750) |#### | Elapsed Time: 0:00:06 ETA: 0:00:28 .. parsed-literal::  19% (149 of 750) |#### | Elapsed Time: 0:00:07 ETA: 0:00:28 .. parsed-literal::  20% (152 of 750) |#### | Elapsed Time: 0:00:07 ETA: 0:00:28 .. parsed-literal::  20% (155 of 750) |#### | Elapsed Time: 0:00:07 ETA: 0:00:27 .. parsed-literal::  21% (158 of 750) |#### | Elapsed Time: 0:00:07 ETA: 0:00:27 .. parsed-literal::  21% (161 of 750) |#### | Elapsed Time: 0:00:07 ETA: 0:00:28 .. parsed-literal::  21% (164 of 750) |#### | Elapsed Time: 0:00:07 ETA: 0:00:28 .. parsed-literal::  22% (167 of 750) |#### | Elapsed Time: 0:00:07 ETA: 0:00:27 .. parsed-literal::  22% (170 of 750) |#### | Elapsed Time: 0:00:08 ETA: 0:00:27 .. parsed-literal::  23% (173 of 750) |##### | Elapsed Time: 0:00:08 ETA: 0:00:27 .. parsed-literal::  23% (176 of 750) |##### | Elapsed Time: 0:00:08 ETA: 0:00:27 .. parsed-literal::  23% (179 of 750) |##### | Elapsed Time: 0:00:08 ETA: 0:00:26 .. parsed-literal::  24% (181 of 750) |##### | Elapsed Time: 0:00:08 ETA: 0:00:27 .. parsed-literal::  24% (184 of 750) |##### | Elapsed Time: 0:00:08 ETA: 0:00:27 .. parsed-literal::  24% (187 of 750) |##### | Elapsed Time: 0:00:08 ETA: 0:00:26 .. parsed-literal::  25% (190 of 750) |##### | Elapsed Time: 0:00:09 ETA: 0:00:26 .. parsed-literal::  25% (193 of 750) |##### | Elapsed Time: 0:00:09 ETA: 0:00:26 .. parsed-literal::  26% (196 of 750) |##### | Elapsed Time: 0:00:09 ETA: 0:00:26 .. parsed-literal::  26% (199 of 750) |##### | Elapsed Time: 0:00:09 ETA: 0:00:25 .. parsed-literal::  26% (201 of 750) |##### | Elapsed Time: 0:00:09 ETA: 0:00:26 .. parsed-literal::  27% (204 of 750) |##### | Elapsed Time: 0:00:09 ETA: 0:00:26 .. parsed-literal::  27% (207 of 750) |###### | Elapsed Time: 0:00:09 ETA: 0:00:25 .. parsed-literal::  27% (209 of 750) |###### | Elapsed Time: 0:00:09 ETA: 0:00:25 .. parsed-literal::  28% (212 of 750) |###### | Elapsed Time: 0:00:10 ETA: 0:00:25 .. parsed-literal::  28% (215 of 750) |###### | Elapsed Time: 0:00:10 ETA: 0:00:25 .. parsed-literal::  29% (218 of 750) |###### | Elapsed Time: 0:00:10 ETA: 0:00:25 .. parsed-literal::  29% (221 of 750) |###### | Elapsed Time: 0:00:10 ETA: 0:00:25 .. parsed-literal::  29% (224 of 750) |###### | Elapsed Time: 0:00:10 ETA: 0:00:25 .. parsed-literal::  30% (227 of 750) |###### | Elapsed Time: 0:00:10 ETA: 0:00:24 .. parsed-literal::  30% (230 of 750) |###### | Elapsed Time: 0:00:10 ETA: 0:00:24 .. parsed-literal::  31% (233 of 750) |###### | Elapsed Time: 0:00:11 ETA: 0:00:24 .. parsed-literal::  31% (236 of 750) |###### | Elapsed Time: 0:00:11 ETA: 0:00:24 .. parsed-literal::  31% (238 of 750) |###### | Elapsed Time: 0:00:11 ETA: 0:00:24 .. parsed-literal::  32% (241 of 750) |####### | Elapsed Time: 0:00:11 ETA: 0:00:24 .. parsed-literal::  32% (245 of 750) |####### | Elapsed Time: 0:00:11 ETA: 0:00:24 .. parsed-literal::  32% (247 of 750) |####### | Elapsed Time: 0:00:11 ETA: 0:00:23 .. parsed-literal::  33% (250 of 750) |####### | Elapsed Time: 0:00:11 ETA: 0:00:23 .. parsed-literal::  33% (253 of 750) |####### | Elapsed Time: 0:00:11 ETA: 0:00:23 .. parsed-literal::  34% (256 of 750) |####### | Elapsed Time: 0:00:12 ETA: 0:00:23 .. parsed-literal::  34% (259 of 750) |####### | Elapsed Time: 0:00:12 ETA: 0:00:23 .. parsed-literal::  34% (261 of 750) |####### | Elapsed Time: 0:00:12 ETA: 0:00:23 .. parsed-literal::  35% (264 of 750) |####### | Elapsed Time: 0:00:12 ETA: 0:00:23 .. parsed-literal::  35% (266 of 750) |####### | Elapsed Time: 0:00:12 ETA: 0:00:22 .. parsed-literal::  35% (269 of 750) |####### | Elapsed Time: 0:00:12 ETA: 0:00:22 .. parsed-literal::  36% (272 of 750) |####### | Elapsed Time: 0:00:12 ETA: 0:00:22 .. parsed-literal::  36% (275 of 750) |######## | Elapsed Time: 0:00:12 ETA: 0:00:22 .. parsed-literal::  37% (278 of 750) |######## | Elapsed Time: 0:00:13 ETA: 0:00:22 .. parsed-literal::  37% (281 of 750) |######## | Elapsed Time: 0:00:13 ETA: 0:00:22 .. parsed-literal::  37% (284 of 750) |######## | Elapsed Time: 0:00:13 ETA: 0:00:22 .. parsed-literal::  38% (287 of 750) |######## | Elapsed Time: 0:00:13 ETA: 0:00:21 .. parsed-literal::  38% (290 of 750) |######## | Elapsed Time: 0:00:13 ETA: 0:00:21 .. parsed-literal::  39% (293 of 750) |######## | Elapsed Time: 0:00:13 ETA: 0:00:21 .. parsed-literal::  39% (295 of 750) |######## | Elapsed Time: 0:00:13 ETA: 0:00:21 .. parsed-literal::  39% (298 of 750) |######## | Elapsed Time: 0:00:14 ETA: 0:00:21 .. parsed-literal::  40% (301 of 750) |######## | Elapsed Time: 0:00:14 ETA: 0:00:21 .. parsed-literal::  40% (304 of 750) |######## | Elapsed Time: 0:00:14 ETA: 0:00:21 .. parsed-literal::  40% (307 of 750) |######### | Elapsed Time: 0:00:14 ETA: 0:00:21 .. parsed-literal::  41% (310 of 750) |######### | Elapsed Time: 0:00:14 ETA: 0:00:20 .. parsed-literal::  41% (313 of 750) |######### | Elapsed Time: 0:00:14 ETA: 0:00:20 .. parsed-literal::  42% (316 of 750) |######### | Elapsed Time: 0:00:14 ETA: 0:00:20 .. parsed-literal::  42% (319 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:20 .. parsed-literal::  42% (321 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:20 .. parsed-literal::  43% (323 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:20 .. parsed-literal::  43% (326 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:20 .. parsed-literal::  43% (329 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:19 .. parsed-literal::  44% (332 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:19 .. parsed-literal::  44% (335 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:19 .. parsed-literal::  45% (338 of 750) |######### | Elapsed Time: 0:00:15 ETA: 0:00:19 .. parsed-literal::  45% (341 of 750) |########## | Elapsed Time: 0:00:16 ETA: 0:00:19 .. parsed-literal::  46% (345 of 750) |########## | Elapsed Time: 0:00:16 ETA: 0:00:19 .. parsed-literal::  46% (348 of 750) |########## | Elapsed Time: 0:00:16 ETA: 0:00:18 .. parsed-literal::  46% (351 of 750) |########## | Elapsed Time: 0:00:16 ETA: 0:00:18 .. parsed-literal::  47% (354 of 750) |########## | Elapsed Time: 0:00:16 ETA: 0:00:18 .. parsed-literal::  47% (357 of 750) |########## | Elapsed Time: 0:00:16 ETA: 0:00:18 .. parsed-literal::  48% (360 of 750) |########## | Elapsed Time: 0:00:16 ETA: 0:00:18 .. parsed-literal::  48% (361 of 750) |########## | Elapsed Time: 0:00:17 ETA: 0:00:18 .. parsed-literal::  48% (365 of 750) |########## | Elapsed Time: 0:00:17 ETA: 0:00:18 .. parsed-literal::  49% (368 of 750) |########## | Elapsed Time: 0:00:17 ETA: 0:00:18 .. parsed-literal::  49% (371 of 750) |########## | Elapsed Time: 0:00:17 ETA: 0:00:17 .. parsed-literal::  49% (374 of 750) |########## | Elapsed Time: 0:00:17 ETA: 0:00:17 .. parsed-literal::  50% (377 of 750) |########### | Elapsed Time: 0:00:17 ETA: 0:00:17 .. parsed-literal::  50% (380 of 750) |########### | Elapsed Time: 0:00:17 ETA: 0:00:17 .. parsed-literal::  50% (381 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:17 .. parsed-literal::  51% (384 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:17 .. parsed-literal::  51% (387 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:17 .. parsed-literal::  52% (390 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:16 .. parsed-literal::  52% (393 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:16 .. parsed-literal::  52% (396 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:16 .. parsed-literal::  53% (399 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:16 .. parsed-literal::  53% (401 of 750) |########### | Elapsed Time: 0:00:18 ETA: 0:00:16 .. parsed-literal::  54% (405 of 750) |########### | Elapsed Time: 0:00:19 ETA: 0:00:16 .. parsed-literal::  54% (408 of 750) |########### | Elapsed Time: 0:00:19 ETA: 0:00:16 .. parsed-literal::  54% (411 of 750) |############ | Elapsed Time: 0:00:19 ETA: 0:00:15 .. parsed-literal::  55% (414 of 750) |############ | Elapsed Time: 0:00:19 ETA: 0:00:15 .. parsed-literal::  55% (417 of 750) |############ | Elapsed Time: 0:00:19 ETA: 0:00:15 .. parsed-literal::  56% (420 of 750) |############ | Elapsed Time: 0:00:19 ETA: 0:00:15 .. parsed-literal::  56% (421 of 750) |############ | Elapsed Time: 0:00:19 ETA: 0:00:15 .. parsed-literal::  56% (425 of 750) |############ | Elapsed Time: 0:00:20 ETA: 0:00:15 .. parsed-literal::  57% (428 of 750) |############ | Elapsed Time: 0:00:20 ETA: 0:00:15 .. parsed-literal::  57% (431 of 750) |############ | Elapsed Time: 0:00:20 ETA: 0:00:14 .. parsed-literal::  57% (434 of 750) |############ | Elapsed Time: 0:00:20 ETA: 0:00:14 .. parsed-literal::  58% (437 of 750) |############ | Elapsed Time: 0:00:20 ETA: 0:00:14 .. parsed-literal::  58% (440 of 750) |############ | Elapsed Time: 0:00:20 ETA: 0:00:14 .. parsed-literal::  58% (441 of 750) |############ | Elapsed Time: 0:00:20 ETA: 0:00:14 .. parsed-literal::  59% (444 of 750) |############# | Elapsed Time: 0:00:20 ETA: 0:00:14 .. parsed-literal::  59% (447 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:14 .. parsed-literal::  60% (450 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:14 .. parsed-literal::  60% (453 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:13 .. parsed-literal::  60% (456 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:13 .. parsed-literal::  61% (459 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:13 .. parsed-literal::  61% (461 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:13 .. parsed-literal::  61% (464 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:13 .. parsed-literal::  62% (466 of 750) |############# | Elapsed Time: 0:00:21 ETA: 0:00:13 .. parsed-literal::  62% (469 of 750) |############# | Elapsed Time: 0:00:22 ETA: 0:00:13 .. parsed-literal::  62% (472 of 750) |############# | Elapsed Time: 0:00:22 ETA: 0:00:13 .. parsed-literal::  63% (475 of 750) |############# | Elapsed Time: 0:00:22 ETA: 0:00:12 .. parsed-literal::  63% (478 of 750) |############## | Elapsed Time: 0:00:22 ETA: 0:00:12 .. parsed-literal::  64% (481 of 750) |############## | Elapsed Time: 0:00:22 ETA: 0:00:12 .. parsed-literal::  64% (484 of 750) |############## | Elapsed Time: 0:00:22 ETA: 0:00:12 .. parsed-literal::  64% (487 of 750) |############## | Elapsed Time: 0:00:22 ETA: 0:00:12 .. parsed-literal::  65% (490 of 750) |############## | Elapsed Time: 0:00:23 ETA: 0:00:12 .. parsed-literal::  65% (493 of 750) |############## | Elapsed Time: 0:00:23 ETA: 0:00:12 .. parsed-literal::  66% (496 of 750) |############## | Elapsed Time: 0:00:23 ETA: 0:00:11 .. parsed-literal::  66% (499 of 750) |############## | Elapsed Time: 0:00:23 ETA: 0:00:11 .. parsed-literal::  66% (501 of 750) |############## | Elapsed Time: 0:00:23 ETA: 0:00:11 .. parsed-literal::  67% (504 of 750) |############## | Elapsed Time: 0:00:23 ETA: 0:00:11 .. parsed-literal::  67% (507 of 750) |############## | Elapsed Time: 0:00:23 ETA: 0:00:11 .. parsed-literal::  68% (510 of 750) |############## | Elapsed Time: 0:00:24 ETA: 0:00:11 .. parsed-literal::  68% (513 of 750) |############### | Elapsed Time: 0:00:24 ETA: 0:00:11 .. parsed-literal::  68% (516 of 750) |############### | Elapsed Time: 0:00:24 ETA: 0:00:10 .. parsed-literal::  69% (519 of 750) |############### | Elapsed Time: 0:00:24 ETA: 0:00:10 .. parsed-literal::  69% (521 of 750) |############### | Elapsed Time: 0:00:24 ETA: 0:00:10 .. parsed-literal::  69% (523 of 750) |############### | Elapsed Time: 0:00:24 ETA: 0:00:10 .. parsed-literal::  70% (526 of 750) |############### | Elapsed Time: 0:00:24 ETA: 0:00:10 .. parsed-literal::  70% (529 of 750) |############### | Elapsed Time: 0:00:24 ETA: 0:00:10 .. parsed-literal::  70% (532 of 750) |############### | Elapsed Time: 0:00:25 ETA: 0:00:10 .. parsed-literal::  71% (535 of 750) |############### | Elapsed Time: 0:00:25 ETA: 0:00:10 .. parsed-literal::  71% (538 of 750) |############### | Elapsed Time: 0:00:25 ETA: 0:00:09 .. parsed-literal::  72% (541 of 750) |############### | Elapsed Time: 0:00:25 ETA: 0:00:09 .. parsed-literal::  72% (544 of 750) |############### | Elapsed Time: 0:00:25 ETA: 0:00:09 .. parsed-literal::  72% (547 of 750) |################ | Elapsed Time: 0:00:25 ETA: 0:00:09 .. parsed-literal::  73% (550 of 750) |################ | Elapsed Time: 0:00:25 ETA: 0:00:09 .. parsed-literal::  73% (553 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:09 .. parsed-literal::  74% (556 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:09 .. parsed-literal::  74% (559 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:08 .. parsed-literal::  74% (561 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:08 .. parsed-literal::  75% (565 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:08 .. parsed-literal::  75% (568 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:08 .. parsed-literal::  76% (570 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:08 .. parsed-literal::  76% (573 of 750) |################ | Elapsed Time: 0:00:26 ETA: 0:00:08 .. parsed-literal::  76% (576 of 750) |################ | Elapsed Time: 0:00:27 ETA: 0:00:08 .. parsed-literal::  77% (579 of 750) |################ | Elapsed Time: 0:00:27 ETA: 0:00:08 .. parsed-literal::  77% (581 of 750) |################# | Elapsed Time: 0:00:27 ETA: 0:00:07 .. parsed-literal::  77% (584 of 750) |################# | Elapsed Time: 0:00:27 ETA: 0:00:07 .. parsed-literal::  78% (587 of 750) |################# | Elapsed Time: 0:00:27 ETA: 0:00:07 .. parsed-literal::  78% (589 of 750) |################# | Elapsed Time: 0:00:27 ETA: 0:00:07 .. parsed-literal::  78% (592 of 750) |################# | Elapsed Time: 0:00:27 ETA: 0:00:07 .. parsed-literal::  79% (595 of 750) |################# | Elapsed Time: 0:00:27 ETA: 0:00:07 .. parsed-literal::  79% (598 of 750) |################# | Elapsed Time: 0:00:28 ETA: 0:00:07 .. parsed-literal::  80% (601 of 750) |################# | Elapsed Time: 0:00:28 ETA: 0:00:07 .. parsed-literal::  80% (605 of 750) |################# | Elapsed Time: 0:00:28 ETA: 0:00:06 .. parsed-literal::  81% (608 of 750) |################# | Elapsed Time: 0:00:28 ETA: 0:00:06 .. parsed-literal::  81% (611 of 750) |################# | Elapsed Time: 0:00:28 ETA: 0:00:06 .. parsed-literal::  81% (614 of 750) |################## | Elapsed Time: 0:00:28 ETA: 0:00:06 .. parsed-literal::  82% (617 of 750) |################## | Elapsed Time: 0:00:28 ETA: 0:00:06 .. parsed-literal::  82% (620 of 750) |################## | Elapsed Time: 0:00:29 ETA: 0:00:06 .. parsed-literal::  82% (621 of 750) |################## | Elapsed Time: 0:00:29 ETA: 0:00:06 .. parsed-literal::  83% (625 of 750) |################## | Elapsed Time: 0:00:29 ETA: 0:00:05 .. parsed-literal::  83% (627 of 750) |################## | Elapsed Time: 0:00:29 ETA: 0:00:05 .. parsed-literal::  84% (630 of 750) |################## | Elapsed Time: 0:00:29 ETA: 0:00:05 .. parsed-literal::  84% (633 of 750) |################## | Elapsed Time: 0:00:29 ETA: 0:00:05 .. parsed-literal::  84% (636 of 750) |################## | Elapsed Time: 0:00:29 ETA: 0:00:05 .. parsed-literal::  85% (639 of 750) |################## | Elapsed Time: 0:00:30 ETA: 0:00:05 .. parsed-literal::  85% (641 of 750) |################## | Elapsed Time: 0:00:30 ETA: 0:00:05 .. parsed-literal::  85% (644 of 750) |################## | Elapsed Time: 0:00:30 ETA: 0:00:05 .. parsed-literal::  86% (646 of 750) |################## | Elapsed Time: 0:00:30 ETA: 0:00:04 .. parsed-literal::  86% (649 of 750) |################### | Elapsed Time: 0:00:30 ETA: 0:00:04 .. parsed-literal::  86% (652 of 750) |################### | Elapsed Time: 0:00:30 ETA: 0:00:04 .. parsed-literal::  87% (655 of 750) |################### | Elapsed Time: 0:00:30 ETA: 0:00:04 .. parsed-literal::  87% (658 of 750) |################### | Elapsed Time: 0:00:30 ETA: 0:00:04 .. parsed-literal::  88% (661 of 750) |################### | Elapsed Time: 0:00:31 ETA: 0:00:04 .. parsed-literal::  88% (664 of 750) |################### | Elapsed Time: 0:00:31 ETA: 0:00:04 .. parsed-literal::  88% (667 of 750) |################### | Elapsed Time: 0:00:31 ETA: 0:00:03 .. parsed-literal::  89% (670 of 750) |################### | Elapsed Time: 0:00:31 ETA: 0:00:03 .. parsed-literal::  89% (673 of 750) |################### | Elapsed Time: 0:00:31 ETA: 0:00:03 .. parsed-literal::  90% (675 of 750) |################### | Elapsed Time: 0:00:31 ETA: 0:00:03 .. parsed-literal::  90% (678 of 750) |################### | Elapsed Time: 0:00:31 ETA: 0:00:03 .. parsed-literal::  90% (681 of 750) |################### | Elapsed Time: 0:00:32 ETA: 0:00:03 .. parsed-literal::  91% (684 of 750) |#################### | Elapsed Time: 0:00:32 ETA: 0:00:03 .. parsed-literal::  91% (687 of 750) |#################### | Elapsed Time: 0:00:32 ETA: 0:00:02 .. parsed-literal::  92% (690 of 750) |#################### | Elapsed Time: 0:00:32 ETA: 0:00:02 .. parsed-literal::  92% (693 of 750) |#################### | Elapsed Time: 0:00:32 ETA: 0:00:02 .. parsed-literal::  92% (696 of 750) |#################### | Elapsed Time: 0:00:32 ETA: 0:00:02 .. parsed-literal::  93% (699 of 750) |#################### | Elapsed Time: 0:00:32 ETA: 0:00:02 .. parsed-literal::  93% (701 of 750) |#################### | Elapsed Time: 0:00:33 ETA: 0:00:02 .. parsed-literal::  93% (703 of 750) |#################### | Elapsed Time: 0:00:33 ETA: 0:00:02 .. parsed-literal::  94% (706 of 750) |#################### | Elapsed Time: 0:00:33 ETA: 0:00:02 .. parsed-literal::  94% (709 of 750) |#################### | Elapsed Time: 0:00:33 ETA: 0:00:01 .. parsed-literal::  94% (712 of 750) |#################### | Elapsed Time: 0:00:33 ETA: 0:00:01 .. parsed-literal::  95% (715 of 750) |#################### | Elapsed Time: 0:00:33 ETA: 0:00:01 .. parsed-literal::  95% (718 of 750) |##################### | Elapsed Time: 0:00:33 ETA: 0:00:01 .. parsed-literal::  96% (721 of 750) |##################### | Elapsed Time: 0:00:34 ETA: 0:00:01 .. parsed-literal::  96% (724 of 750) |##################### | Elapsed Time: 0:00:34 ETA: 0:00:01 .. parsed-literal::  96% (727 of 750) |##################### | Elapsed Time: 0:00:34 ETA: 0:00:01 .. parsed-literal::  97% (730 of 750) |##################### | Elapsed Time: 0:00:34 ETA: 0:00:00 .. parsed-literal::  97% (732 of 750) |##################### | Elapsed Time: 0:00:34 ETA: 0:00:00 .. parsed-literal::  98% (735 of 750) |##################### | Elapsed Time: 0:00:34 ETA: 0:00:00 .. parsed-literal::  98% (738 of 750) |##################### | Elapsed Time: 0:00:34 ETA: 0:00:00 .. parsed-literal::  98% (741 of 750) |##################### | Elapsed Time: 0:00:35 ETA: 0:00:00 .. parsed-literal::  99% (744 of 750) |##################### | Elapsed Time: 0:00:35 ETA: 0:00:00 .. parsed-literal::  99% (747 of 750) |##################### | Elapsed Time: 0:00:35 ETA: 0:00:00 .. parsed-literal:: 100% (750 of 750) |######################| Elapsed Time: 0:00:35 Time: 0:00:35 .. parsed-literal:: .. raw:: html In the long-exposure coronagraphic PSF, we can clearly see the wind-driven halo, due to the time lag of our simulated AO system, and the edge of the control region, outside of which the DM is not able to corrected the seeing. We could now start to modify parameters of our atmosphere, tune parameters of our AO control loop or wavefront sensor, or even change out the wavefront sensor or coronagraph completely. However this falls outside of the scope of this tutorial. We will however do some simple analysis of the images. We can calculate the Strehl ratio for this run using a built-in HCIPy function: .. code:: ipython3 strehl = get_strehl_from_focal(long_exposure, unaberrated_PSF * wf_wfs.total_power) print('Strehl = %.1f%%' % (strehl * 100)) .. parsed-literal:: Strehl = 77.2% We can also compute and display radial profiles of the coronagraphic and non-coronagraphic PSFs. .. code:: ipython3 r, y_coro, yerr, n = radial_profile(long_exposure_coro / long_exposure.max(), 0.25 * spatial_resolution) _, y_noncoro, _, _ = radial_profile(long_exposure / long_exposure.max(), 0.25 * spatial_resolution) _, y_unaber, _, _ = radial_profile(unaberrated_PSF / unaberrated_PSF.max(), 0.25 * spatial_resolution) rad_to_arcsec = 206265 plt.plot(r * rad_to_arcsec, y_noncoro, label='Non-coronagraphic') plt.plot(r * rad_to_arcsec, y_coro, label='Coronagraphic') plt.plot(r * rad_to_arcsec, y_unaber, label='Unaberrated') plt.yscale('log') plt.xlim(0, 1.3) plt.ylim(3e-6, 1) plt.xlabel('Angular separation [arcsec]') plt.ylabel('Raw contrast') plt.legend() plt.show() .. image:: output_52_0.png .. code:: ipython3 # Cleanup created movie files os.remove('response_matrix.mp4') os.remove('AO_simulation_without_turbulence.mp4') os.remove('atmospheric_turbulence.mp4') os.remove('AO_simulation_with_turbulence.mp4')