예제 #1
0
    def test_add_incompatible_wavefronts():
        """ Test we can't add wavefronts to incompatible things. Verifies fix of #308 """
        import poppy
        import astropy.units as u
        n = 10
        w1 = poppy.Wavefront(npix=n)
        w2 = poppy.Wavefront(npix=n)
        w3 = poppy.Wavefront(npix=n, diam=1 * u.m)
        w4 = poppy.Wavefront(npix=n, pixelscale=1 * u.arcsec / u.pixel)
        w5 = poppy.Wavefront(npix=n * 2)

        fw1 = poppy.FresnelWavefront(1.0 * u.m, npix=n, oversample=1)

        # test a valid addition works:
        output = w1 + w2
        assert isinstance(output,
                          w1.__class__), "couldn't add compatible wavefronts"

        # test the invalid additions are caught:
        inputs_and_errors = ((
            3, "Wavefronts can only be summed with other Wavefronts"
        ), (
            fw1,
            "Wavefronts can only be summed with other Wavefronts of the same class"
        ), (
            w3, "Wavefronts can only be added if they have the same pixelscale"
        ), (
            w4, "Wavefronts can only be added if they have the same pixelscale"
        ), (w5,
            "Wavefronts can only be added if they have the same size and shape"
            ))
        for test_input, expected_error in inputs_and_errors:
            with pytest.raises(ValueError) as excinfo:
                output = w1 + test_input
            assert _exception_message_starts_with(excinfo, expected_error)
예제 #2
0
def test_wavefront_tilt_sign_and_direction_fresnel(plot=False, npix=128):
    """ Test that tilt with increasing WFE towards the +X direction moves the PSF in the -X direction
    Fresnel propagation version

    See also test_core.test_source_offsets_in_OpticalSystem
    """
    # Create a wavefront and apply a tilt
    wave = poppy.FresnelWavefront(beam_radius=0.5 * u.m,
                                  npix=npix,
                                  oversample=8)
    wave *= poppy.CircularAperture(radius=0.5 * u.m)

    # tilt in arcseconds
    tilt_angle = -0.2  # must be a negative number (for -X direction shift), and within the FOV

    wave.tilt(
        Xangle=tilt_angle
    )  # for this function, the input is the desired direction for the image to tilt.
    # A shift to -X is implemented by creating an OPD that increases toward +X
    n = wave.shape[0]
    assert wave.wfe[n // 2, n // 2 -
                    5] < wave.wfe[n // 2, n // 2 +
                                  5], "Wavefront error should increase to +X"

    if plot:
        plt.suptitle("Wavefront tilt sign test (Fresnel propagation)",
                     fontweight='bold')
        wave.display(what='both')

    focal_length = 1 * u.m
    wave *= poppy.QuadraticLens(f_lens=focal_length)

    wave.propagate_fresnel(focal_length)

    if plot:
        plt.figure()
        wave.display(what='both',
                     crosshairs=True,
                     imagecrop=0.00001,
                     scale='log')

    n = wave.shape[0]
    nominal_cen = n // 2  # In Fresnel mode, PSFs are centered on a pixel by default
    # (different from in Fraunhofer mode by half a pixel)

    cen = poppy.measure_centroid(wave.as_fits())
    assert np.allclose(
        cen[0], nominal_cen), "Tilt in X should not displace the PSF in Y"
    assert cen[
        1] < nominal_cen, "WFE tilt increasing to +X should displace the PSF to -X"
    assert np.allclose(
        ((cen[1] - nominal_cen) * u.pixel * wave.pixelscale).to_value(u.m),
        ((tilt_angle * u.arcsec).to_value(u.radian) * focal_length).to_value(
            u.m)), "PSF offset distance did not match expected amount"
예제 #3
0
def test_inwave_fresnel(plot=False):
    '''Verify basic functionality of the inwave kwarg for a basic FresnelOpticalSystem()'''
    npix = 128
    oversample = 2
    # HST example - Following example in PROPER Manual V2.0 page 49.
    lambda_m = 0.5e-6 * u.m
    diam = 2.4 * u.m
    fl_pri = 5.52085 * u.m
    d_pri_sec = 4.907028205 * u.m
    fl_sec = -0.6790325 * u.m
    d_sec_to_focus = 6.3919974 * u.m

    m1 = poppy.QuadraticLens(fl_pri, name='Primary')
    m2 = poppy.QuadraticLens(fl_sec, name='Secondary')

    hst = poppy.FresnelOpticalSystem(pupil_diameter=diam,
                                     npix=npix,
                                     beam_ratio=1 / oversample)
    hst.add_optic(poppy.CircularAperture(radius=diam.value / 2))
    hst.add_optic(
        poppy.SecondaryObscuration(secondary_radius=0.396,
                                   support_width=0.0264,
                                   support_angle_offset=45.0))
    hst.add_optic(m1)
    hst.add_optic(m2, distance=d_pri_sec)
    hst.add_optic(poppy.ScalarTransmission(
        planetype=poppy_core.PlaneType.image, name='focus'),
                  distance=d_sec_to_focus)

    if plot:
        plt.figure(figsize=(12, 8))
    psf1, wfs1 = hst.calc_psf(wavelength=lambda_m,
                              display_intermediates=plot,
                              return_intermediates=True)

    # now test the system by inputting a wavefront first
    wfin = poppy.FresnelWavefront(beam_radius=diam / 2,
                                  wavelength=lambda_m,
                                  npix=npix,
                                  oversample=oversample)
    if plot:
        plt.figure(figsize=(12, 8))
    psf2, wfs2 = hst.calc_psf(wavelength=lambda_m,
                              display_intermediates=plot,
                              return_intermediates=True,
                              inwave=wfin)

    wf = wfs1[-1].wavefront
    wf_no_in = wfs2[-1].wavefront

    assert np.allclose(
        wf, wf_no_in
    ), 'Results differ unexpectedly when using inwave argument for FresnelOpticalSystem().'
예제 #4
0
def test_pupil_orientations_before_and_after_focus_fresnel(
        plot=False, npix_pupil=128, npix_fov=128):
    """ Verify pupil orientations before and after focus, and signs of thin lens defocus

    1. A negative weak lens produces images (before focus) that have consistent orientation with the exit pupil
    2. A positive weak lens produces images (after focus) that have the opposite orientation as the exit pupil
    3. Images with the same magnitude but opposite signs of defocus should be 180 degree rotations of one another.

    """

    wave0 = poppy.FresnelWavefront(beam_radius=1.5 * u.m, oversample=2)
    wave0 *= poppy.LetterFAperture(radius=1 / np.sqrt(2) * u.m)

    focal_length = 1.0 * u.m
    lens = poppy.QuadraticLens(f_lens=focal_length, name="Converging lens")
    wave0 *= lens

    wave1 = wave0.copy()
    wave2 = wave0.copy()

    fov = 0.00003

    wave1.propagate_fresnel(0.99999 * focal_length)

    wave2.propagate_fresnel(1.00001 * focal_length)

    if plot:
        fig, axes = plt.subplots(figsize=(15, 6), ncols=3)
        plt.suptitle("Before and After Focus sign test (Fresnel propagation)",
                     fontweight='bold')

        wave0.display(ax=axes[0])
        wave1.display(imagecrop=fov,
                      title='Intensity at plane before focus',
                      scale='log',
                      ax=axes[1])
        wave2.display(imagecrop=fov,
                      title='Intensity at plane after focus',
                      scale='log',
                      ax=axes[2])

    assert brighter_top_half(wave0.intensity) and brighter_left_half(
        wave0.intensity
    ), "Letter F should be brighter at top and left at pupil"
    assert brighter_top_half(wave1.intensity) and brighter_left_half(
        wave1.intensity
    ), "Image with negative lens (before focus) should have same orientation as the pupil "
    assert (not brighter_top_half(wave2.intensity)) and (
        not brighter_left_half(wave2.intensity)
    ), "Image with positive lens (after focus) should have opposite orientation as the pupil "
예제 #5
0
def test_wavefront_conversions():
    """ Test conversions between Wavefront and FresnelWavefront
    in both directions.
    """
    import poppy

    props = lambda wf: (wf.shape, wf.ispadded, wf.oversample, wf.pixelscale)

    optic = poppy.CircularAperture()
    w = poppy.Wavefront(diam=4 * u.m)
    w *= optic

    fw = poppy.FresnelWavefront(beam_radius=2 * u.m)
    fw *= optic

    # test convert from Fraunhofer to Fresnel
    fw2 = poppy.FresnelWavefront.from_wavefront(w)
    assert props(fw) == props(fw2)
    #np.testing.assert_allclose(fw.wavefront, fw2.wavefront)

    # test convert from Fresnel to Fraunhofer
    w2 = poppy.Wavefront.from_fresnel_wavefront(fw)
    assert props(w) == props(w2)