AOtools -- a Python package for adaptive optics modelling and analysis

AOtools is a Python package which is open-source and aimed at providing tools for adaptive optics users and researchers. We present version 1.0 which contains tools for adaptive optics processing, including analysing data in the pupil plane, images and point spread functions in the focal plane, wavefront sensors, modelling of atmospheric turbulence, physical optical propagation of wavefronts, and conversion between frequently used adaptive optics and astronomical units. The main drivers behind AOtools is that it should be easy to install and use. To achieve this the project features extensive documentation, automated unit testing and is registered on the Python Package Index. AOtools is under continuous active development to expand the features available and we encourage everyone involved in adaptive optics to become involved and contribute to the project.


Introduction
The Python programming language (http://www.python.org) has become a powerful tool for scientific research [1,2]. Currently Python uptake in astronomy and related fields is growing rapidly [3].
Adaptive Optics (AO) has reached a level of maturity where many algorithms and techniques are considered "standard practice", with cookbooks for implementing many standard procedures existing to help users implement functions, such as [4]. There are freely available tools for AO analysis on GPU (MOAO framework [5]). There are also a number of full end-to-end simulations which implement full AO systems in software, such as the C/Python based DASP [6], Matlab ® based OOMAO [7], Yorick based YAO [8] and IDL based CAOS [9].
However, currently there is no freely available, open-source tool which implements a library for use in either simulation or AO data analysis in Python. We propose AOtools as a project and Python package which encompasses this functionality. One example of using AOtools to create a full end-to-end simulation is the SOAPY project [10].
For the project to be successful it is essential that the AOtools package is reliable, easy to install, and easy to use. This mandates the use of automation tools to ensure documentation is up-to-date and that the core functionality of the code is working as expected. To this end infrastructure has been put in place to make the package "pip" installable, with minimal external dependencies. Currently the only dependencies AOtools requires are: Numpy [11], Scipy [12], and Matplotlib [13], all of which are standard tools of the scientific Python ecosystem.
In this paper we outline the major functionality of the software at the current release (v1.0), the structure of the project, the approach used for development of the library, and finally a road map for the future of the project. It is envisaged that this project will be useful beyond the realm of astronomical AO, including microscopy [14,15] and free space optical communications [16].

Functionality
In this section we present the core functionality of the AOtools package, covering functions applied to pupils in Sec. To demonstrate the use of AOtools a snippet of code is presented along with plots which shows how to generate the data for the corresponding figure. Working examples of all of the code used to generate the plots shown in this paper can also be found at https: //github.com/AOtools/aotools_tests. Finally, an example of the documentation provided by AOtools is shown in Fig. 1(c).

Circular masks
Generating circular functions in 2-D arrays is useful in generating pupil masks, as well as other applications. Most lenses can be approximated with a circular pupil mask, and telescope pupil shapes can be approximated simply with one or two circular apertures, to create the obstruction of the secondary mirror. A simple function exists in AOtools to create circular apertures, which can be combined to generate simple telescope pupil masks. An example code snippet for the generation of a telescope pupil mask is shown in Fig. 1(a), with the corresponding generated telescope pupil mask shown in Fig. 1(b).

Zernike modes
It is frequently useful to decompose wavefronts into Zernike modes. This allows for analysis of aberrations and the performance of correction in AO systems, for example atmospheric statistics are frequently decomposed into Zernike modes [17]. AOtools defaults to normalising individual modes using Noll, however, they can also be normalised by peak-to-valley and RMS strength if required. An example snippet for creating an array of Zernike modes is given in Fig. 2(a), with a selection of the generated Zernike modes plotted in Fig. 2(b).

Atmospheric turbulence
AOtools features the functionality to create both finite Kolmogorov [18,19] and von Kármán turbulence phase screens. These functions are based on the example implementations given in [4]. The library also includes methods to create infinite Kolmogorov and von Kármán phase screens using the methods described in [20]. The phase screens created are wavelength independent as the amplitude scale is in nm. An example code snippet using the Fried method for generating infinite phase screens [20,21] is shown in Fig. 3(a), with an image of the corresponding phase screen given in Fig. 3(b). The average Zernike breakdown of 1000 Fried infinite phase screens is shown in Fig. 4 alongside the theoretical amplitudes of each mode from [17].   Fig. 1(a) for the creation of a telescope pupil mask using two circles to create a circular aperture with a cut-out section corresponding to the secondary mirror. The pupil mask created is shown in Fig. 1(b). An example of the documentation provided by AOtools for this function is shown in Fig. 1(c).

Point source
AOtools includes some functions for analysing Point Spread Functions (PSFs). This includes the full encircled energy as a function of radius, and the radius corresponding to a given fraction of encircled energy. There is also the functionality to calculate the azimuthal average of an image. However, currently this is restricted to the PSF being in the centre of the input 2-D image. An example of generating a PSF and then using the azimuthal averaging function is given in Fig. 5(a). The PSF generated from the pupil shown in Fig. 1(b) and the azimuthal averaged intensity is shown in Fig. 5 AOtools also features a number of methods for centroiding images of point sources and elongated Laser Guide Stars (LGSs). These include the centre-of-mass method, including parameters for thresholding within the centroider, and other methods used in WFSs, such as the brightest pixel centroider [22]. Example code snippet for centroiding an image is given in Fig. 6.    Fig. 3(a) shows an example code snippet with the specification and generation of an infinite phase screen using the Fried method [20,21]. The phase screen can be "moved" by using the add_row method which is shown at the end of the snippet. An example phase screen generated using this code is shown in Fig. 3(b). The strength is defined in nm such that the phase screen is wavelength independent.  [20,21], with the theoretical strengths expected from Noll [17].

Extended source
AOtools also includes methods for centroiding extended objects using a cross-correlation technique. The correlation images can be created using a built-in cross-correlation function, then the resulting correlation image centroided using any centroiding function [23]. Or, if a simple centre-of-mass centroider will be applied to the correlation image, there is a correlation_centroid function which will perform both the cross-correlation and the centroiding to output the relative image shifts between images and a reference image. Currently the only available method for cross-correlation is based on Fast Fourier Transforms (FFTs). The use of AOtools to centroid extended objects is shown in Fig 7(a), with the example images, and correlation image generated shown in Fig 7(b). There is also the functionality to measure the contrast of images of extended objects, with both the Michelson [24] and RMS contrast currently implemented.

Wavefront sensors
AOtools includes functions for generating sub-aperture masks for Shack-Hartmann WFSs, based on a simple square grid, by inputting the geometry of the sub-aperture grid and the pupil mask. It is also possible to calculate the fill-factor for a set of sub-apertures for a given pupil mask. Example code for doing both of these are given in Fig. 8(a) and an example set of valid sub-apertures shown on the telescope pupil shown in Fig. 1(b) is shown in Fig. 8(b). As well as creating sub-aperture masks for given pupil shapes, AOtools also includes methods to convert a "stream" of Shack-Hartmann WFS data into a 2-D grid which matches sub-aperture geometry. This allows for the conversion of data which comes out of RTC systems, such as DARC [25,26], for analysis.    Fig. 1(b) and the calculation of the azimuthal average of the resulting PSF. The padding and slicing of the pupil mask is included to oversample the FFT, leading to a smoother PSF for plotting. The PSF corresponding to the pupil shown in Fig. 1(b) is shown alongside the corresponding azimuthal average of the PSF calculated using AOtools in Fig. 5(b).
(b) WFS images and output cross-correlation image. Fig. 7. Example use of AOtools to centroid extended objects. AOtools can be used to centroid using a cross-correlation and a centre-of-mass using a single function call, or the correlation image can be generated in one step then any centroiding technique can be applied to the correlation image, as shown in Fig. 7(a). In Fig. 7(b) the left and middle images show the reference image and a shifted sub-aperture image of solar granulation respectively. The right most image shows the correlation image created from the cross-correlation of the left and centre images. This can then be centroided in order to measure the shift between the sub-aperture and the reference images.

Optical propagation
AOtools includes functions to physically propagate a wavefront through space, leading to the generation of scintillation. Available physical propagation methods include the angular spectrum method, and one and two step Fresnel propagation. An example code snippet of propagating a complex wavefront created from the phase screen created in Fig. 3(a) is shown in Fig. 9(a). The scintillation pattern from propagating the phase screen shown in Fig. 3(b) by 10km is shown in Fig. 9(b). In Fig. 10 we show that the scintillation irradiance power spectrum obtained through AOtools propagation is consistent with the theory outlined in [27].
As well as physical propagation of wavefronts the optical propagation section of AOtools includes a FFT based function to change between the pupil plane and focal plane. This can be used to convert a wavefront which is incident to a telescope pupil into a PSF, as has been shown in the code snippet in Fig. 5(a) and Fig. 5(b).
(a) Code snippet.   Fig. 9(a) shows example code showing the propagation of the phase created shown in Fig. 3(b) for 10km and creation of the resulting scintillation image in the pupil. The generated scintillation pattern is shown in Fig. 9(b). >>> import aotools >>> m = 0# Use Vega as example star >>> exp_time = 30 # 30s exposure >>> waveband = V >>> photon_rate = aotools.magnitude_to_flux(m, waveband) >>> # Calculate photons in an example exposure >>> photons = aotools.photons_per_band(m, pupil_mask, pixel_scale, exp_time) Fig. 11. Example of using AOtoools to convert stellar flux from magnitudes to photon flux. Examples for both a raw conversion to photon rate and also for the telescope pupil shown in Fig. 1(b) and a given exposure time.
flux is required to calculate expected signal levels on WFSs. AOtools includes conversion functions which convert stellar brightness into photon flux for a given waveband, and vice-versa. Example code snippets are given in Fig. 11 which demonstrate converting stellar magnitude to photon flux. As well as converting between astronomical units, AOtools also includes a number of parameter conversion functions which are specific to astronomical AO. These predominantly relate to the conversion between different atmospheric parameters, such as Cn 2 , r 0 , seeing, etc. Examples showing the conversion between these different units are shown in Fig. 12. AOtools also includes methods to calculate integrated atmospheric >>> import aotools >>> r0 = 0.15 >>> cn2 = aotools.r0_to_cn2(r0) >>> seeing = aotools.r0_to_seeing(r0) Fig. 12. Example use of AOtools to convert between different typically used astronomical AO units.
parameters, such as coherence time and isoplanatic angle from atmospheric turbulence and wind speed profile.

Infrastructure and development approach
AOtools is a Python library which has been developed for the AO community by the AO community. It is hoped that this continues, and the involvement of the community will increase over time to include users of AO beyond astronomy and microscopy. In order to achieve this a large focus of AOtools is outside of functionality of the module and instead in infrastructure surrounding the tools. We use the software related expertise of both the AO community and dedicated software engineers to ensure the code is well maintained, written clearly with good documentation, and well tested. The general infrastructure goals for AOtools are to ensure that it is is well tested, documented, and is both easy to install and easy to use.
In order to encourage input to the codebase it is hosted on Github, where it is open-source under a GNU Lesser General Public License v3.0. license [28]. This license allows for any work to use AOtools, including commercial, without forcing any licence on the new software. However, it does insist that any changes to the core AOtools package are made public under a similar license. We utilise the infrastructure available through GitHub and the git software to update the codebase and to manage the release of new versions. Changes to the codebase are submitted though "pull requests", where changes (whether they are bug-fixes or new features) are reviewed by core members of the AOtools team and merged into the main code base once the code has been approved.
Updating the main code base of AOtools is often followed by a release of a new version. The versions are numbered according to the major.minor.micro format as described in PEP440. Major versions are those which contain major changes and may break compatibility with previous versions, minor versions are those which contain new features or enhancements to existing features (these should not break compatibility with versions within the same Major version), and micro versions typically contain bug fixes for issues found within the existing source code. After a new version of AOtools has been created it is then registered with the Python Package Index (PyPI). This allows for AOtools be installed and updated easily by users using 'pip'. AOtools can be installed with Python using pip install aotools.
The AOtools package makes use of continuous integration. This is the automated running of unit tests whenever changes are made to the main code base. As part of this testing AOtools is run on a number of different versions of Python, on a number of different operating systems in an attempt to avoid issues arising due to specific installations and environments. We also keep track of how much of the main code base is covered by this automated testing using code coverage tools from codecov.
AOtools has extensive documentation, which is created using the Sphinx documentation generator [29] to automatically generate documentation for every available function and module based on the docstrings in the source code. This ensures both that the source code itself is well documented, but also generates a complete set of documentation which is then hosted in an interactive format for ease of use at read the docs. An example of the documentation is given in Fig. 1(c) for the circle function which can be used to generate telescope pupil masks.

Future development
AOtools is a relatively young project and in active development. There are many updates and incremental additions to functionality ongoing and planned for the future. Here we summarise the major updates in functionality that are currently planned: Shack-Hartmann WFS slope analysis, and image processing.
Although there are some routines in AOtools for analysing WFS data there are still many techniques which are not implemented. We plan on expanding the Shack-Hartmann WFS analysis routines available in AOtools to include measuring atmospheric parameters from the slopes [30,31] and generation of covariance matrices from both WFS data and atmospheric turbulence profiles. Finally, functionality will be developed for the creation of AO reconstructors based on covariance matrices which have been pre-calculated.
The development of image processing routines is concentrated on PSFs analysis. AOtools will feature simple to use methods for generating PSFs using different inputs, including phase and complex amplitude in a pupil. Building on this we will develop methods for applying a PSF to extended images, to allow for the degradation of wide-field images by the effects of atmospheric turbulence.
The final areas development for AOtools are within the telescope pupil generation and in adding Deformable Mirrors (DMs). Currently this is very simple, based on circular apertures with cut-outs for a central obscuration. We would like to develop this to be more flexible, including the possibility for building segmented telescopes which are not completely circular. As of yet there are no features related to the creation or modelling of DMs within AOtools. However, this is something which could be of use to the community.
We will continue to maintain and improve much of the infrastructure of AOtools, expanding documentation to include example code demonstrating the use of the functions, much as presented in and alongside this paper. Currently AOtools features generic AO functions and data processing methods and functions, and some methods which apply specifically to astronomy. We are looking to expand the functionality of AOtools to include other fields which make use of AO, such as microscopy. Finally, we plan on submitting AOtools to be included as an affiliated package to Astropy [32] to achieve better integration with the features and facilities they offer.

Summary
The AOtools package is aimed to be a core package for AO scientists and users of data taken with AO systems. It is currently in use in a number of astronomical projects and institutions, however, we plan to expand beyond astronomy into the wider AO community. In this paper we have described the major functionality of AOtools in release 1.0, including: In Sec. 3 we outlined the development approach and core ideas behind the AOtools project. This has enabled us to begin to involve the AO community with contributing to the project. Finally, we outlined the future plans for the project in Sec. 4, with the major goals of increasing functionality and becoming affiliated with the Astropy project.