From yao 5.0, the SHWFS has gained a new feature so called "extended field" capability (wfs.extfield [arcsec]). Here is how it works: Up to now the subaperture field of view was wfs.pixsize*wfs.npixels. This was limited to a certain value, namely wfs.lambda/pupil_plane_pixel_size_in_meter, constrained by the laws of the FFT. For instance at 500nm and with 10cm per pixel in the pupil plane, you get one arcsec field of view. Period. This limits still applies with the new model, but now this 1x1 arcsec "imagelet" is embedded into a larger image, with shifts computed from the average input tilt in front of the given subaperture (of course the said tilt is removed from the input phase as it is effectively taken care of by the shift). This opens the possibility of much larger dynamical ranges without having to use a very large number of pixels in the input pupil. As far as turbulence goes, this also relieves the constraint of having 2-3 pixels per r0: Now that tip-tilt is "removed" before doing the FFT to compute the subaperture spot, the wrapping limit of 2pi per pixel is pushed further away (about 3 times further if we trust Noll, as the Tip-tilt-removed Noll residual is 13% of the phase variance, thus 36% in rms). Thus one can now safely go to one pixel per r0 before hitting the wrapping/aliasing limit on the image formation in each subaperture. This means 2 times lower sim.pupildiam are needed, and typically translate into a factor of 4 gain in speed
From yao 5.0, the SHWFS has gained a few features. On top of the general shnxsub, etc, the spots and subaperture geometry can be controlled as illustrated by the figure on the left, where:
wfs.pixsize
is the desired pixel size in the final SHWFS image [arcsec].wfs.npixels
is the number of pixel in the direct image computed from the subaperture phaselet (see next section).wfs.extfield
is the extended field of the subaperture [arcsec].wfs.fssize
is the field stop size [arcsec].wfs.spotpitch
is the separation between spots in the final image.All the yao 5.0 additional parameters (extfield, spotpitch) have sane defaults, so the old parfiles should not be affected. By default, wfs.extfield=0
(which means in fact that the field is not extended, thus has a size of wfs.npixels*wfs.pixsize
), and wfs.spotpitch=wfs.npixels*wfs.pixsize
too.
Why all this fine tuning and all these available parameters? Well, extfield was primarily conceived -as its name suggest- to enlarge the SHWFS field of view to deal with large TT/focus signal, or to deal with LGS elongation (see next section). In combination with wfs.fssize
and wfs.spotpitch
, it can also conveniently be used to avoid wrapping, a situation where -by property of the FFT-, the spot can wrap from one edge of a subaperture to the opposite edge, which is clearly not what happened in nature. Finally, by making wfs.spotpitch
smaller than wfs.extfield
and wfs.fssize
, one can easily simulate cross coupling between subaperture, a situation that should be avoided in real system by properly setting the field stop size, but that can be interesting and funny to simulate (hint: it may introduce funny meta-stable resonances).
In this section, I will attempt to explain how the SHWFS spots are computed from the input phase. I will particularly concentrate on how the extended field version works.
Step 1: Let's assume a SHWFS with sim.pupildiam=64
and wfs.shnxsub=8
.
This means every subaperture will see a phaselet of dimension 64/8=8x8 pixels.
This phaselet is cut out and embedded into an array of dimension equal to twice
the power of 2 immediately larger than the phaselet dimension. That is, it's got to be
at least twice as large as the phaselet (for Nyquist in the image plane) and has got
to be a power of 2 for speed consideration of the FFT. So, for instance, for subapertures
of size up to and including 8x8 pixels, the phase is embedded into an array of size 16x16.
The image on the left shows the image corresponding to this wavefront (in this case, the subaperture
is effectively 8x8 pixels, embedded into a 16x16 array thus the image is 16x16 and we call it "sim").
In this example, the "quantum pixel size", i.e. the pixel size in this image, is approximately 0.1 arcsec.
Step 2: If the SHWFS "extended field" option is excercized (by assigning to wfs.extfield
a larger value than
wfs.pixsize*wfs.npixels
), then the SHWFS subaperture field of view is enlarged by effectively embedding sim into a larger image, that we will call xim (more below). What happen immediately is that TT is removed from the input phaselet, so that the imagelet is effectively re-centered (in fact re-centered to the closest pixel, as to counteract this TT removal, we will embed sim to a different location in xim, and we want this shift to be an integer number of pixels). So the immediate effect is to have the PSF centered within 0.5 pixels in sim. This of course has the advantage to reduce aliasing in sim.
Step 3: sim (in our example 16x16) is then placed into xim (here 64x64), with the shift corresponding to the TT that has been removed from the input phaselet. The pixel size in xim is the same than in sim, but of course the field of view is enlarged. If NOT using a LGS profile, then the next step is to convolve with a kernel (wfs.kernel), bin and embed into the final image (go to step 7, where the kernel would be a gaussian instead of the uplink seeing for the laser).
Step 4: If using a LGS profile, then the operation is repeated for the next point of the user-defined vector wfs.lgs_prof_amp and wfs.lgs_prof_alt. Each altitude is modelled as an additional defocus of the input phase (exactly as it is in the real world), and this defocus will move the spot in xim. Here, we show xim after processing of the first 2 points on the lgs profile vectors.
Step 5: xim after processing of all lgs profile points in lgs_prof_amp and alt. Each point is of course weighted by lgs_prof_amp.
Step 6: We then convolve xim by a kernel which will blur the dotty profile above by a kernel align with the LGS elongation. The LGS profile is now the combination of a number of weighted diracs, convolved by a small kernel of FWHM defined by wfs.gsdepth and typically equal to the separation between the diracs (separation between two points in lgs_prof_alt). I call that an hybrid approach. In yao version < 5.0, the LGS elongation was modelled as a gaussian profile, and I was just convolving a unique spot by a gaussian kernel along the direction of elongation (radially w.r.t. the LLT position). In yao >= 5.0, one could not use the kernel and just choose to have a large number fo points in lgs_prof_amp/alt, but that would take a heavy toll on computing time. Using the hybrid lgs_prof_amp/alt + small elongation kernel gives the best of both world: One can have any arbitrary LGS profile, and still keep limit computing time requirements. Note that there is a utility function, called fit_lgs_profile()
, which return the lgs_prof_amp/alt vectors, together with wfs.gsdepth. For most profiles, a fit with 5 to 7 points is sufficient.
Step 7: From version 5.1, yao includes the option of modelling the effect of the uplink seeing (and laser M2). This is controlled by wfs.LLT_uplink_turb
(0|1), with relevant parameters being wfs.LLTr0
(r0 at the LLT and at wfs.lambda
wavelength), wfs.LLTdiam
and wfs.LLT1overe2diam
(the LLT diameter and the laser beam 1/e2 diameter) and wfs.LLTlaserM2
(the laser M2). If wfs.LLT_uplink_turb
is set, then all of these effects are computed and an overall kernel is generated (image on left).
Step 8: xim is convolved with the uplink seeing/M2 kernel. If wfs.LLT_uplink_turb
is NOT set, but wfs.kernel
is non-zero, then the kernel is a 2D gaussian of FWHM wfs.kernel
(arcsec). This was the way yao simulated the LGS extent before version 5.1.
Step 9: This is the field stop, defined by wfs.fstop ("none", "square" or "round") and wfs.fssize (in arcsec).
Step 10: xim is multiplied by the field stop.
Step 11: xim is binned to the final image desired pixel size. Note that the binning factor has to be a integer number, so that the final pixel size has to be a multiple of the quatum pixel size (see more on that in the main manual).
Step 12: All spots (here, an example with 2 of these) are placed in the final SHWFS image, with pitch/separation defined by wfs.spotpitch
. Note that now (5.0+) the field of view (extfield), the field stop size and the spot pitch are independently defined, so that one can easily model subaperture interaction, or make sure there's no wrapping possible by using a large enough extfield and keeping the field stop size and spotpitch to the desired value (i.e. a spot can not wrap back, disapearing on the left to appear on the right by property of the FFT), etc...
Step 13: Add noise, darkcurrent, take into account effects of bias & flat, etc...
Sometimes pseudo code is easier to understand than words. Here is the pseudo code for the shwfs processes described above:
:for each subapertures for each defocus values (=each point in LGS profile) * extract phaselet in front of subaperture * fit tiptilt at best * remove fitted tiptilt from phaselet * embed in larger array (power of two greater than size*2) * compute image sim * embed sim in xim at coordinate computed from previous tiptilt fit (note: accumulate/add to xim content) end loop on defocus value * convolve xim by elongation kernel (subaperture dependent) * convolve xim by uplink/M2 or gaussian kernel (common to all subapertures) (note: the last 2 operations are in fact done together) * normalize for flux * apply field stop * bin * embed bin image into final SHWFS spot image end loop on subapertures