Ejemplo n.º 1
0
def ptf(array_shape=(256, 256), dx=1., lam_over_diam=2., defocus=0., astig1=0., astig2=0., coma1=0.,
        coma2=0., trefoil1=0., trefoil2=0., spher=0., circular_pupil=True, obscuration=0.,
        nstruts=0, strut_thick=0.05, strut_angle=0.*galsim.degrees):
    """Return NumPy array containing the PTF [radians] of a circular (default) or square pupil with
    low-order aberrations.

    PTF array element ordering follows the DFT standard of kxky(array_shape), and has
    ptf[0, 0] = 0. by default.

    To ensure properly Nyquist sampled output any user should set lam_over_diam >= 2. * dx.

    Output double NumPy array is C-contiguous.

    @param array_shape     the NumPy array shape desired for the output array.
    @param dx              grid spacing of PSF in real space units
    @param lam_over_diam   lambda / telescope diameter in the physical units adopted for dx 
                           (user responsible for consistency).
    @param defocus         defocus in units of incident light wavelength.
    @param astig1          astigmatism (like e2) in units of incident light wavelength.
    @param astig2          astigmatism (like e1) in units of incident light wavelength.
    @param coma1           coma along y in units of incident light wavelength.
    @param coma2           coma along x in units of incident light wavelength.
    @param trefoil1        trefoil (one of the arrows along y) in units of incident light
                           wavelength.
    @param trefoil2        trefoil (one of the arrows along x) in units of incident light
                           wavelength.
    @param spher           spherical aberration in units of incident light wavelength.
    @param circular_pupil  adopt a circular pupil?
    @param obscuration     linear dimension of central obscuration as fraction of pupil linear
                           dimension, [0., 1.)
    @param nstruts         Number of radial support struts to add to the central obscuration
                           [default `nstruts = 0`].
    @param strut_thick     Thickness of support struts as a fraction of pupil diameter
                           [default `strut_thick = 0.05`].
    @param strut_angle     Angle made between the vertical and the strut starting closest to it,
                           defined to be positive in the counter-clockwise direction; must be a
                           galsim.Angle instance [default `strut_angle = 0. * galsim.degrees`].
    """
    kx, ky = utilities.kxky(array_shape)
    k2 = (kx**2 + ky**2)
    ptf = np.zeros(array_shape)
    kmax_internal = dx * 2. * np.pi / lam_over_diam # INTERNAL kmax in units of array grid spacing
    # Try to handle where both real and imag tend to zero...
    ptf[k2 < kmax_internal**2] = np.angle(otf(
        array_shape=array_shape, dx=dx, lam_over_diam=lam_over_diam, defocus=defocus, astig1=astig1,
        astig2=astig2, coma1=coma1, coma2=coma2, trefoil1=trefoil1, trefoil2=trefoil2, spher=spher,
        circular_pupil=circular_pupil, obscuration=obscuration, nstruts=nstruts,
        strut_thick=strut_thick, strut_angle=strut_angle)[k2 < kmax_internal**2]) 
    return ptf
Ejemplo n.º 2
0
def generate_pupil_plane(array_shape=(256, 256),
                         dx=1.,
                         lam_over_diam=2.,
                         circular_pupil=True,
                         obscuration=0.):
    """Generate a pupil plane, including a central obscuration such as caused by a secondary mirror.

    @param array_shape     the NumPy array shape desired for the output array.
    @param dx              grid spacing of PSF in real space units.
    @param lam_over_diam   lambda / telescope diameter in the physical units adopted for dx 
                           (user responsible for consistency).
    @param circular_pupil  adopt a circular pupil?
    @param obscuration     linear dimension of central obscuration as fraction of pupil linear
                           dimension, [0., 1.)

    Returns a tuple (rho, theta, in_pupil), the first two of which are the coordinates of the
    pupil in unit disc-scaled coordinates for use by Zernike polynomials for describing the
    wavefront across the pupil plane.  The array in_pupil is a vector of Bools used to specify
    where in the pupil plane described by rho, theta is illuminated.  See also optics.wavefront. 
    """
    kmax_internal = dx * 2. * np.pi / lam_over_diam  # INTERNAL kmax in units of array grid spacing
    # Build kx, ky coords
    kx, ky = utilities.kxky(array_shape)
    # Then define unit disc rho and theta pupil coords for Zernike polynomials
    rho = np.sqrt((kx**2 + ky**2) / (.5 * kmax_internal)**2)
    theta = np.arctan2(ky, kx)
    # Cut out circular pupil if desired (default, square pupil optionally supported) and include
    # central obscuration
    if obscuration >= 1.:
        raise ValueError("Pupil fully obscured! obscuration =" +
                         str(obscuration) + " (>= 1)")
    if circular_pupil:
        in_pupil = (rho < 1.)
        if obscuration > 0.:
            in_pupil = in_pupil * (rho >= obscuration
                                   )  # * acts like "and" for boolean arrays
    else:
        in_pupil = (np.abs(kx) < .5 * kmax_internal) * (np.abs(ky) <
                                                        .5 * kmax_internal)
        if obscuration > 0.:
            in_pupil = in_pupil * (
                (np.abs(kx) >= .5 * obscuration * kmax_internal) *
                (np.abs(ky) >= .5 * obscuration * kmax_internal))
    return rho, theta, in_pupil
Ejemplo n.º 3
0
def ptf(array_shape=(256, 256), dx=1., lam_over_diam=2., defocus=0., astig1=0., astig2=0., coma1=0.,
        coma2=0., trefoil1=0., trefoil2=0., spher=0., circular_pupil=True, obscuration=0.):
    """Return NumPy array containing the PTF [radians] of a circular (default) or square pupil with
    low-order aberrations.

    PTF array element ordering follows the DFT standard of kxky(array_shape), and has
    ptf[0, 0] = 0. by default.

    To ensure properly Nyquist sampled output any user should set lam_over_diam >= 2. * dx.

    Output double NumPy array is C-contiguous.

    @param array_shape     the NumPy array shape desired for the output array.
    @param dx              grid spacing of PSF in real space units
    @param lam_over_diam   lambda / telescope diameter in the physical units adopted for dx 
                           (user responsible for consistency).
    @param defocus         defocus in units of incident light wavelength.
    @param astig1          astigmatism (like e2) in units of incident light wavelength.
    @param astig2          astigmatism (like e1) in units of incident light wavelength.
    @param coma1           coma along y in units of incident light wavelength.
    @param coma2           coma along x in units of incident light wavelength.
    @param trefoil1        trefoil (one of the arrows along y) in units of incident light
                           wavelength.
    @param trefoil2        trefoil (one of the arrows along x) in units of incident light
                           wavelength.
    @param spher           spherical aberration in units of incident light wavelength.
    @param circular_pupil  adopt a circular pupil?
    @param obscuration     linear dimension of central obscuration as fraction of pupil linear
                           dimension, [0., 1.)
    """
    kx, ky = utilities.kxky(array_shape)
    k2 = (kx**2 + ky**2)
    ptf = np.zeros(array_shape)
    kmax_internal = dx * 2. * np.pi / lam_over_diam # INTERNAL kmax in units of array grid spacing
    # Try to handle where both real and imag tend to zero...
    ptf[k2 < kmax_internal**2] = np.angle(otf(
        array_shape=array_shape, dx=dx, lam_over_diam=lam_over_diam, defocus=defocus, astig1=astig1,
        astig2=astig2, coma1=coma1, coma2=coma2, trefoil1=trefoil1, trefoil2=trefoil2, spher=spher,
        circular_pupil=circular_pupil, obscuration=obscuration)[k2 < kmax_internal**2])
    return ptf
Ejemplo n.º 4
0
def generate_pupil_plane(array_shape=(256, 256), dx=1., lam_over_diam=2., circular_pupil=True,
                         obscuration=0.):
    """Generate a pupil plane, including a central obscuration such as caused by a secondary mirror.

    @param array_shape     the NumPy array shape desired for the output array.
    @param dx              grid spacing of PSF in real space units.
    @param lam_over_diam   lambda / telescope diameter in the physical units adopted for dx 
                           (user responsible for consistency).
    @param circular_pupil  adopt a circular pupil?
    @param obscuration     linear dimension of central obscuration as fraction of pupil linear
                           dimension, [0., 1.)

    Returns a tuple (rho, theta, in_pupil), the first two of which are the coordinates of the
    pupil in unit disc-scaled coordinates for use by Zernike polynomials for describing the
    wavefront across the pupil plane.  The array in_pupil is a vector of Bools used to specify
    where in the pupil plane described by rho, theta is illuminated.  See also optics.wavefront. 
    """
    kmax_internal = dx * 2. * np.pi / lam_over_diam # INTERNAL kmax in units of array grid spacing
    # Build kx, ky coords
    kx, ky = utilities.kxky(array_shape)
    # Then define unit disc rho and theta pupil coords for Zernike polynomials
    rho = np.sqrt((kx**2 + ky**2) / (.5 * kmax_internal)**2)
    theta = np.arctan2(ky, kx)
    # Cut out circular pupil if desired (default, square pupil optionally supported) and include 
    # central obscuration
    if obscuration >= 1.:
        raise ValueError("Pupil fully obscured! obscuration ="+str(obscuration)+" (>= 1)")
    if circular_pupil:
        in_pupil = (rho < 1.)
        if obscuration > 0.:
            in_pupil = in_pupil * (rho >= obscuration)  # * acts like "and" for boolean arrays
    else:
        in_pupil = (np.abs(kx) < .5 * kmax_internal) * (np.abs(ky) < .5 * kmax_internal)
        if obscuration > 0.:
            in_pupil = in_pupil * (
                (np.abs(kx) >= .5 * obscuration * kmax_internal) *
                (np.abs(ky) >= .5 * obscuration * kmax_internal))
    return rho, theta, in_pupil
Ejemplo n.º 5
0
def generate_pupil_plane(array_shape=(256, 256), dx=1., lam_over_diam=2., circular_pupil=True,
                         obscuration=0., nstruts=0, strut_thick=0.05, 
                         strut_angle=0.*galsim.degrees):
    """Generate a pupil plane, including a central obscuration such as caused by a secondary mirror.

    @param array_shape     the NumPy array shape desired for the output array.
    @param dx              grid spacing of PSF in real space units.
    @param lam_over_diam   lambda / telescope diameter in the physical units adopted for dx 
                           (user responsible for consistency).
    @param circular_pupil  adopt a circular pupil?
    @param obscuration     linear dimension of central obscuration as fraction of pupil linear
                           dimension, [0., 1.).
    @param nstruts         Number of radial support struts to add to the central obscuration
                           [default `nstruts = 0`].
    @param strut_thick     Thickness of support struts as a fraction of pupil diameter
                           [default `strut_thick = 0.05`].
    @param strut_angle     Angle made between the vertical and the strut starting closest to it,
                           defined to be positive in the counter-clockwise direction; must be a
                           galsim.Angle instance [default `strut_angle = 0. * galsim.degrees`].
 
    Returns a tuple (rho, in_pupil), the first of which is the coordinates of the pupil
    in unit disc-scaled coordinates for use by Zernike polynomials (as a complex number)
    for describing the wavefront across the pupil plane.  The array in_pupil is a vector of 
    Bools used to specify where in the pupil plane described by rho is illuminated.  See also 
    optics.wavefront. 
    """
    kmax_internal = dx * 2. * np.pi / lam_over_diam # INTERNAL kmax in units of array grid spacing
    # Build kx, ky coords
    kx, ky = utilities.kxky(array_shape)
    # Then define unit disc rho pupil coords for Zernike polynomials
    rho = (kx + 1j * ky) / (.5 * kmax_internal)
    rhosq = np.abs(rho)**2
    # Amazingly, the above line is faster than the following. (~ 35% faster)
    # See the longer comment about this in psf function.
    #rhosq = rho.real**2 + rho.imag**2

    # Cut out circular pupil if desired (default, square pupil optionally supported) and include 
    # central obscuration
    if obscuration >= 1.:
        raise ValueError("Pupil fully obscured! obscuration ="+str(obscuration)+" (>= 1)")
    if circular_pupil:
        in_pupil = (rhosq < 1.)
        if obscuration > 0.:
            in_pupil *= rhosq >= obscuration**2  # * acts like "and" for boolean arrays
    else:
        in_pupil = (np.abs(kx) < .5 * kmax_internal) * (np.abs(ky) < .5 * kmax_internal)
        if obscuration > 0.:
            in_pupil *= ( (np.abs(kx) >= .5 * obscuration * kmax_internal) *
                          (np.abs(ky) >= .5 * obscuration * kmax_internal) )
    if nstruts > 0:
        if not isinstance(strut_angle, galsim.Angle):
            raise TypeError("Input kwarg strut_angle must be a galsim.Angle instance.")
        # Add the initial rotation if requested, converting to radians
        if strut_angle.rad != 0.:
            kxs, kys = utilities.rotate_xy(kx, ky, -strut_angle) # strut rotation +=ve, so coords
                                                                 # rotation -ve!
        else:
            kxs, kys = kx, ky
        # Define the angle between struts for successive use below
        rotang = 360. * galsim.degrees / float(nstruts)
        # Then loop through struts setting to zero in the pupil regions which lie under the strut
        in_pupil *= (
            (np.abs(kxs) >= .5 * strut_thick * kmax_internal) +
            ((kys < 0.) * (np.abs(kxs) < .5 * strut_thick * kmax_internal)))
        for istrut in range(nstruts)[1:]:
            kxs, kys = utilities.rotate_xy(kxs, kys, -rotang)
            in_pupil *= (
                (np.abs(kxs) >= .5 * strut_thick * kmax_internal) +
                ((kys < 0.) * (np.abs(kxs) < .5 * strut_thick * kmax_internal)))
    return rho, in_pupil
Ejemplo n.º 6
0
def ptf(array_shape=(256, 256),
        dx=1.,
        lam_over_diam=2.,
        defocus=0.,
        astig1=0.,
        astig2=0.,
        coma1=0.,
        coma2=0.,
        trefoil1=0.,
        trefoil2=0.,
        spher=0.,
        circular_pupil=True,
        obscuration=0.):
    """Return NumPy array containing the PTF [radians] of a circular (default) or square pupil with
    low-order aberrations.

    PTF array element ordering follows the DFT standard of kxky(array_shape), and has
    ptf[0, 0] = 0. by default.

    To ensure properly Nyquist sampled output any user should set lam_over_diam >= 2. * dx.

    Output double NumPy array is C-contiguous.

    @param array_shape     the NumPy array shape desired for the output array.
    @param dx              grid spacing of PSF in real space units
    @param lam_over_diam   lambda / telescope diameter in the physical units adopted for dx 
                           (user responsible for consistency).
    @param defocus         defocus in units of incident light wavelength.
    @param astig1          astigmatism (like e2) in units of incident light wavelength.
    @param astig2          astigmatism (like e1) in units of incident light wavelength.
    @param coma1           coma along y in units of incident light wavelength.
    @param coma2           coma along x in units of incident light wavelength.
    @param trefoil1        trefoil (one of the arrows along y) in units of incident light
                           wavelength.
    @param trefoil2        trefoil (one of the arrows along x) in units of incident light
                           wavelength.
    @param spher           spherical aberration in units of incident light wavelength.
    @param circular_pupil  adopt a circular pupil?
    @param obscuration     linear dimension of central obscuration as fraction of pupil linear
                           dimension, [0., 1.)
    """
    kx, ky = utilities.kxky(array_shape)
    k2 = (kx**2 + ky**2)
    ptf = np.zeros(array_shape)
    kmax_internal = dx * 2. * np.pi / lam_over_diam  # INTERNAL kmax in units of array grid spacing
    # Try to handle where both real and imag tend to zero...
    ptf[k2 < kmax_internal**2] = np.angle(
        otf(array_shape=array_shape,
            dx=dx,
            lam_over_diam=lam_over_diam,
            defocus=defocus,
            astig1=astig1,
            astig2=astig2,
            coma1=coma1,
            coma2=coma2,
            trefoil1=trefoil1,
            trefoil2=trefoil2,
            spher=spher,
            circular_pupil=circular_pupil,
            obscuration=obscuration)[k2 < kmax_internal**2])
    return ptf