## Optical gains with a pyramid wavefront sensor

Detailed information about this problem and the proposed method can be found in this paper.

The very good sensitivity of the pyramid wavefront sensor (PWFS) has lead the AO community to strongly consider this type of WFS in new designs of high performance AO systems on relatively (or extremely) large telescopes.
However, the limited dynamic range of this kind of sensors carries non linearity in the form of a sensitivity reduction that can be modeled as a function of the wavefront spatial frequency.
This non linearity, called *Optical Gains*, can be a problem when one wants to implement algorithms that rely on linearity of the WFS, and the need to find a method to measure and compensate these optical gains arose.

## The CLOSE modal gain optimization algorithm

To overcome the problem of optical gains, COMPASS includes an implementation of the Correlation-Locking Optimization SchEme (CLOSE) algorithm that uses an auto-correlation based self-regulating method that drives the integrator modal gains.

Briefly, this optimizer is based on two equations.

$${N_i^{0}[k] = p\ m_i[k]^{2} + (1-p) N_i^{0}[k-1]}$$ $${N_i^{\delta k}[k] = p\ m_i[k] m_i[k-\delta k] + (1-p) N_i^{\delta k}[k-1]}$$ $${G_i[k] = G_i[k-1] \times \left[1 + q^\pm\left(\dfrac{N_i^{\delta k crit}[k]}{N_i^0[k]} - r\right)\right]}$$

The first one is an auto-covariance estimator of the measurement *m* that is computed for every iterations *k* and for each mode *i*.
This estimator is then used with two different values of *δk*, one being 0 and the other *δkcrit* depending on the simulation overall latency (and automatically computed within the optimizer).
The integrator gain *p* of the covariance estimation can be set by the user.

In the second equation that calculates the new modal gain for each mode *i* at each frame *k*, the *r* parameter is the loop set-point that is by default set to 0, and *q±* is the learning factor applied to the new modal gain. *q±* are in reality two values *q+* and *q-* that are respectively used depending on the sign of ${\dfrac{N_i^{\delta k crit}[k]}{N_i^0[k]} - r}$

This allow to have a different speed to increase and decrease the modal gains, avoiding dramatic instabilities.

An additional feature allows to update the modal gains at a different rate than the loop frequency.
A parameter *update index* is used to give as a integer number of sampling period the interval between to consecutive modal gains updates.
When set to 1 (which is the default value), the modal gains are updated for every loop iteration, but with a greater value N, the auto-correlation estimator ${\dfrac{N_i^{\delta k crit}[k]}{N_i^0[k]} - r}$ is averaged over N iterations and then used to update the modal gains.
This can be used to ensure relatively ‘soft’ modal gain optimization to avoid instabilities.

The parameter $\delta k crit$ is not settable by the user as it is set depending on the loop delay of the simulation as $${\delta k crit = 2\times delay + 1}$$ Note that this value may be not optimal for very high delays.

## COMPASS implementation

The CLOSE modal gain optimization is implemented as an optimizer object.
This object is to be instantiated within `__init__`

function of the the supervisor definition with

```
self.modalgains = ModalGains(self.config, self.rtc)
```

and then within the `loop`

or `next`

function of the supervisor, the modal gains are computed and applied to the command law using the function

```
self.modalgains.update_mgains()
```

Note that by default, the `CompassSupervisor`

already includes this optimizer, whether it is used or not, and in the following it is assumed that this supervisor (or any other supervisor inheriting this one) is used to run a simulation.

Within the parameter file used to run the simulation, CLOSE related parameters are contained in the `Param_controller`

object usually instantiated by

```
p_controller = shesha.config.Param_controller()
```

The following parameters are settable :

```
p_controller.set_close_opti(True) # activates the gain update
p_controller.set_mgain_init(1.0) # initial value of the modal gains
p_controller.set_lfdownup(0.01, 0.01) # respectively q- and q+ parameters above
p_controller.set_close_learning_factor(0.3) # the p parameter above
p_controller.set_close_target(0.0) # the r parameter above
p_controller.set_close_update_index(1) # the modal gain update frame rate
```

### Basic setup and usage

In order to use this implementation, the controller type should be switched to modal integrator with the command

```
supervisor.rtc.set_modal_integrator_law(n_control)
```

To ensure functioning of the loop, the modal basis should be a square matrix of shape (Nactu, Nactu), the mask vector should be of shape (Nactu) and the modal command matrix has the shape (Nactu, Nslopes). This mask is used for both avoiding divisions by zero in auto-correlation estimator (and though should contain no more ones than the number of controllable modes) and for filtering modes (by setting the corresponding value to zero). The matrices should be loaded directly in the optimizer (that will automatically load them in the controller) using the following functions :

```
supervisor.modalgains.set_modal_basis(modalbasis)
supervisor.modalgains.set_cmat_modal(cmatmodal)
supervisor.modalgains.set_mask(mask)
```

To activate the CLOSE algorithm in a simulation, one must set the corresponding flag to True :

```
supervisor.modalgains.adapt_modal_gains(True)
```

The function `supervisor.modalgains.reset_close()`

can be used to reset modal gains to initial value, the auto-correlation estimator to zeros, and disables CLOSE optimisation.

It is also possible to obtain the applied modal gains at any given iteration by using the command

```
supervisor.modalgains.get_modal_gains()
```

### Parameters tweak within the supervisor

It is possible, after the simulation has been initialized, to modify the value of the different parameters.

The function

```
supervisor.modalgains.set_config(p, qminus, qplus, target, up_idx)
```

can be used to set the auto-correlation and modal gain update parameters :

*p*is the`p_controller.close_learning_factor`

*qminus*and*qplus*are combines as an array in`p_controller.lfdownup`

*target*is the`p_controller.close_target`

*up_idx*is the`p_controller.close_update_index`

Another function allows to change the initial value of the modal gains:

```
supervisor.modalgains.set_initial_gain(gain)
```

Note that this function will also reset the modal gains in the optimizer and the RTC to the required value. If the loop is closed and the optimizer running, the modal gains will still be updated according to the CLOSE parameters.