コード例 #1
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().'
コード例 #2
0
ファイル: test_fresnel.py プロジェクト: laurenmarietta/poppy
def test_CompoundOpticalSystem_fresnel(npix=128, display=False):
    """ Test that the CompoundOpticalSystem container works for Fresnel systems

    Parameters
    ----------
    npix : int
        Number of pixels for the pupil sampling. Kept small by default to
        reduce test run time.
    """

    import poppy

    opt1 = poppy.SquareAperture()
    opt2 = poppy.CircularAperture(radius=0.55)

    # a single optical system
    osys = poppy.FresnelOpticalSystem(beam_ratio=0.25, npix=npix)
    osys.add_optic(opt1)
    osys.add_optic(opt2, distance=10 * u.cm)
    osys.add_optic(poppy.QuadraticLens(1.0 * u.m))
    osys.add_optic(poppy.Detector(pixelscale=0.25 * u.micron / u.pixel,
                                  fov_pixels=512),
                   distance=1 * u.m)

    psf = osys.calc_psf(display_intermediates=display)

    if display:
        plt.figure()

    # a Compound Fresnel optical system
    osys1 = poppy.FresnelOpticalSystem(beam_ratio=0.25, npix=npix)
    osys1.add_optic(opt1)
    osys2 = poppy.FresnelOpticalSystem(beam_ratio=0.25)
    osys2.add_optic(opt2, distance=10 * u.cm)
    osys2.add_optic(poppy.QuadraticLens(1.0 * u.m))
    osys2.add_optic(poppy.Detector(pixelscale=0.25 * u.micron / u.pixel,
                                   fov_pixels=512),
                    distance=1 * u.m)

    cosys = poppy.CompoundOpticalSystem([osys1, osys2])

    psf2 = cosys.calc_psf(display_intermediates=display)

    assert np.allclose(
        psf[0].data, psf2[0].data
    ), "Results from simple and compound Fresnel systems differ unexpectedly."

    return psf, psf2
コード例 #3
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"
コード例 #4
0
def WFIRSTSPC(npix=256, ratio=0.25):
    Tel_fname = os.path.join(os.environ['WEBBPSF_PATH'],
                             "AFTA_CGI_C5_Pupil_onax_256px_flip.fits")
    SP_fname = os.path.join(os.environ['WEBBPSF_PATH'],
                            "CGI/optics/CHARSPC_SP_256pix.fits.gz")
    FPM_fname = os.path.join(
        os.environ['WEBBPSF_PATH'],
        "CGI/optics/CHARSPC_FPM_25WA90_2x65deg_-_FP1res4_evensamp_D072_F770.fits.gz"
    )
    LS_fname = os.path.join(os.environ['WEBBPSF_PATH'],
                            "CGI/optics/SPC_LS_30D88_256pix.fits.gz")

    D_prim = 2.37 * u.m
    D_relay = 20 * u.mm
    fr_pri = 7.8
    fl_pri = D_prim * fr_pri
    fl_m2 = fl_pri * D_relay / D_prim
    fr_m3 = 20.
    fl_m3 = fr_m3 * D_relay

    oversamp = 4
    wfirst_optsys = poppy.FresnelOpticalSystem(pupil_diameter=D_prim,
                                               beam_ratio=ratio,
                                               npix=npix)

    telap = poppy.FITSOpticalElement(transmission=Tel_fname)
    SP = poppy.FITSOpticalElement(transmission=SP_fname)

    #default FPM pixelscale is in arcsecs
    FPM = poppy.FITSOpticalElement(
        transmission=FPM_fname,
        planetype=poppy.poppy_core.PlaneType.intermediate,
        pixelscale=0.005)
    SP.pixelscale = 0.5 * u.cm / SP.shape[0] / u.pix
    FPM.pixelscale = 0.5 * u.cm / SP.shape[0] / u.pix
    m1 = poppy.QuadraticLens(fl_pri, name='Primary')
    m2 = poppy.QuadraticLens(fl_m2, name='M2')
    m3 = poppy.QuadraticLens(fl_m3, name='M3')
    m4 = poppy.QuadraticLens(fl_m3, name='M4')
    m5 = poppy.QuadraticLens(fl_m3, name='M5')
    m6 = poppy.QuadraticLens(fl_m3, name='M6')

    wfirst_optsys.add_optic(telap)
    wfirst_optsys.add_optic(m1)
    wfirst_optsys.add_optic(m2, distance=fl_pri + fl_m2)
    wfirst_optsys.add_optic(m3, distance=fl_m2 + fl_m3)
    wfirst_optsys.add_optic(m4, distance=2 * fl_m3)
    wfirst_optsys.add_optic(SP, distance=fl_m3)
    wfirst_optsys.add_optic(m5, distance=fl_m3)
    wfirst_optsys.add_optic(FPM, distance=fl_m3)
    wfirst_optsys.add_optic(m5, distance=2 * fl_m3)

    wfirst_optsys.add_optic(poppy.ScalarTransmission(
        planetype=poppy.poppy_core.PlaneType.intermediate,
        name='focus',
    ),
                            distance=fl_m3 + 0.39999923 * u.m)
    return wfirst_optsys
コード例 #5
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 "
コード例 #6
0
print('Select desired coefficient distribution (default Sigmoid):')
print('Sigmoid: 1 \nGaussian: 2 \nExponential: 3 \n')
distribution = input()

if distribution == 2:
    wf_error_budget = gaussian_budget(n_coeff)
elif distribution == 3:
    wf_error_budget = exponential_budget(n_coeff)
else:
    wf_error_budget = sigmoid_budget(n_coeff)

#%% --------------------------------- OPTICAL ELEMENTS ----------------------------------------------

aperture = poppy.CircularAperture(radius=radius, name='Pupil')

objective = poppy.QuadraticLens(fl_obj, name='Objective lens')

# ----------------------------------- OPTICAL SYSTEM ------------------------------------------------

# Initialize results as lists
psf_results = []
zernike_coeff = []

file_h5, group_h5 = init_h5(save_dir)

for image_idx in range(n_set):

    osys = poppy.FresnelOpticalSystem(pupil_diameter=10 * radius,
                                      npix=256,
                                      beam_ratio=SAMPLING)
コード例 #7
0
ファイル: test_fresnel.py プロジェクト: laurenmarietta/poppy
def test_CompoundOpticalSystem_hybrid(npix=128):
    """ Test that the CompoundOpticalSystem container works for hybrid Fresnel+Fraunhofer systems

    Defining "works correctly" here is a bit arbitrary given the different physical assumptions.
    For the purpose of this test we consider a VERY simple case, mostly a Fresnel system. We split
    out the first optic and put that in a Fraunhofer system. We then test that a compound hybrid
    system yields the same results as the original fully-Fresnel system.

    Parameters
    ----------
    npix : int
        Number of pixels for the pupil sampling. Kept small by default to
        reduce test run time.
    """

    import poppy

    opt1 = poppy.SquareAperture()
    opt2 = poppy.CircularAperture(radius=0.55)

    ###### Simple test case to exercise the conversion functions, with only trivial propagation
    osys1 = poppy.OpticalSystem()
    osys1.add_pupil(opt1)
    osys2 = poppy.FresnelOpticalSystem()
    osys2.add_optic(poppy.ScalarTransmission())
    osys3 = poppy.OpticalSystem()
    osys3.add_pupil(poppy.ScalarTransmission())
    osys3.add_detector(fov_pixels=64, pixelscale=0.01)
    cosys = poppy.CompoundOpticalSystem([osys1, osys2, osys3])
    psf, ints = cosys.calc_psf(return_intermediates=True)
    assert len(ints) == 4, "Unexpected number of intermediate  wavefronts"
    assert isinstance(ints[0], poppy.Wavefront), "Unexpected output type"
    assert isinstance(ints[1],
                      poppy.FresnelWavefront), "Unexpected output type"
    assert isinstance(ints[2], poppy.Wavefront), "Unexpected output type"

    ###### Harder case involving more complex actual propagations

    #===== a single Fresnel optical system =====
    osys = poppy.FresnelOpticalSystem(beam_ratio=0.25,
                                      npix=128,
                                      pupil_diameter=2 * u.m)
    osys.add_optic(opt1)
    osys.add_optic(opt2, distance=10 * u.cm)
    osys.add_optic(poppy.QuadraticLens(1.0 * u.m))
    osys.add_optic(poppy.Detector(pixelscale=0.125 * u.micron / u.pixel,
                                  fov_pixels=512),
                   distance=1 * u.m)

    #===== two systems, joined into a CompoundOpticalSystem =====
    # First part is Fraunhofer then second is Fresnel
    osys1 = poppy.OpticalSystem(npix=128,
                                oversample=4,
                                name="FIRST PART, FRAUNHOFER")
    # Note for strict consistency we need to apply a half pixel shift to optics in the Fraunhofer part;
    # this accomodates the differences between different types of image centering.
    pixscl = osys.input_wavefront().pixelscale
    halfpixshift = (pixscl * 0.5 * u.pixel).to(u.m).value
    opt1shifted = poppy.SquareAperture(shift_x=halfpixshift,
                                       shift_y=halfpixshift)
    osys1.add_pupil(opt1shifted)

    osys2 = poppy.FresnelOpticalSystem(name='SECOND PART, FRESNEL')
    osys2.add_optic(opt2, distance=10 * u.cm)
    osys2.add_optic(poppy.QuadraticLens(1.0 * u.m))
    osys2.add_optic(poppy.Detector(pixelscale=0.125 * u.micron / u.pixel,
                                   fov_pixels=512),
                    distance=1 * u.m)

    cosys = poppy.CompoundOpticalSystem([osys1, osys2])

    #===== PSF calculations =====
    psf_simple = osys.calc_psf(return_intermediates=False)
    poppy.poppy_core._log.info(
        "******=========calculation divider============******")
    psf_compound = cosys.calc_psf(return_intermediates=False)

    np.testing.assert_allclose(
        psf_simple[0].data,
        psf_compound[0].data,
        err_msg=
        "PSFs do not match between equivalent simple and compound/hybrid optical systems"
    )
コード例 #8
0
def csvFresnel(rx_csv, samp, oversamp, break_plane):
    M1_radius = rx_csv['Radius_m'][
        1] * u.m  # Element [1] is M1 because Element [0] is the pupil mask

    sys_build = poppy.FresnelOpticalSystem(pupil_diameter=2 * M1_radius,
                                           npix=samp,
                                           beam_ratio=oversamp)

    # Entrance Aperture
    sys_build.add_optic(poppy.CircularAperture(radius=M1_radius))

    # Build MagAO-X optical system from CSV file to the Lyot plane
    for n_optic, optic in enumerate(rx_csv):  # n_optic: count, optic: value

        dz = optic[
            'Distance_m'] * u.m  # Propagation distance from the previous optic (n_optic-1)
        fl = optic[
            'Focal_Length_m'] * u.m  # Focal length of the current optic (n_optic)

        #print('Check PSD file for %s: %s' % (optic['Name'], optic['surf_PSD']))
        # if PSD file present
        if optic['surf_PSD_filename'] != 'none':
            # make a string insertion for the file location
            surf_file_loc = optic['surf_PSD_folder'] + optic[
                'surf_PSD_filename'] + '.fits'
            # call surfFITS to send out surface map
            optic_surface = surfFITS(file_loc=surf_file_loc,
                                     optic_type=optic['optic_type'],
                                     opdunit=optic['OPD_unit'],
                                     name=optic['Name'] + ' surface')
            # Add generated surface map to optical system
            sys_build.add_optic(optic_surface, distance=dz)

            if fl != 0:  # powered optic with PSD file present
                sys_build.add_optic(poppy.QuadraticLens(fl,
                                                        name=optic['Name']))
                # no distance; surface comes first
                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

            elif optic[
                    'Type'] != 'pupil':  # non-powered optic but has PSD present that is NOT the pupil
                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

        # if no PSD file present (DM, focal plane, testing optical surface)
        else:
            # if powered optic is being tested
            if fl != 0:
                sys_build.add_optic(poppy.QuadraticLens(fl,
                                                        name=optic['Name']),
                                    distance=dz)
                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

            # for DM, flat mirrors
            elif optic['Type'] == 'mirror' or optic['Type'] == 'DM':
                sys_build.add_optic(poppy.ScalarTransmission(
                    planetype=PlaneType.intermediate, name=optic['Name']),
                                    distance=dz)
                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

            else:  # for focal plane, science plane, lyot plane
                sys_build.add_optic(poppy.ScalarTransmission(
                    planetype=PlaneType.intermediate, name=optic['Name']),
                                    distance=dz)

        # if the most recent optic studied was the break plane, break out of loop.
        if optic['Type'] == break_plane:
            #print('Finish building FresnelOpticalSystem at %s' % break_plane)
            break

    return sys_build
コード例 #9
0
ファイル: optics.py プロジェクト: idiap/cbi_toolbox
def openspim_illumination(wavelength=500e-9,
                          refr_index=1.333,
                          laser_radius=1.2e-3,
                          objective_na=0.3,
                          objective_focal=18e-3,
                          slit_opening=10e-3,
                          pixelscale=635e-9,
                          npix_fov=512,
                          rel_thresh=None,
                          simu_size=2048,
                          oversample=16):
    """
    Compute the illumination function of an OpenSPIM device

    Parameters
    ----------
    wavelength : float, optional
        illumination wavelength in meters, by default 500e-9
    refr_index : float, optional
        imaging medium refraction index, by default 1.333
    laser_radius : float, optional
        source laser radius in meters, by default 1.2e-3
    objective_na : float, optional
        illumination objective NA, by default 0.3
    objective_focal : float, optional
        illumination objective focal length in meters, by default 18e-3
    slit_opening : float, optional
        vertical slit opening in meters, by default 10e-3
    pixelscale : float, optional
        target pixelscale in meters per pixel, by default 1.3e-3/2048
    npix_fov : int, optional
        target size in pixels, by default 512
    rel_thresh: float, optional
        relative threshold to crop the beam thickness
        if a full row is below this theshold, all rows after are removed
        will be computed as compared to the maximum pixel
    simu_size : int, optional
        size of the arrays used for simulation, by default 2048
    oversample : int, optional
        oversampling used for the simulation (must be increased sith simu_size), by default 16

    Returns
    -------
    array [ZXY]
        the illumination function
    """

    pixel_width = 1
    wavelength *= u.m
    laser_radius *= u.m
    objective_focal *= u.m
    pixelscale *= (u.m / u.pixel)
    slit_opening *= u.m

    noop = poppy.ScalarTransmission()
    beam_ratio = 1 / oversample

    fov_pixels = npix_fov * u.pixel
    detector = poppy.FresnelOpticalSystem()
    detector.add_detector(fov_pixels=fov_pixels, pixelscale=pixelscale)

    # We approximate the objective aperture with a square one to make it separable
    # Given the shape of the wavefront, we estimate the generated error to be negligible
    objective_radius = math.tan(math.asin(
        objective_na / refr_index)) * objective_focal
    objective_aperture = poppy.RectangleAperture(name='objective aperture',
                                                 width=2 * objective_radius,
                                                 height=2 * objective_radius)
    objective_lens = poppy.QuadraticLens(f_lens=objective_focal,
                                         name='objective lens')

    obj_aperture = poppy.FresnelOpticalSystem()
    obj_aperture.add_optic(objective_aperture, objective_focal)

    # Implement the objective lens separately to be able to account for refractive index change
    obj_lens = poppy.FresnelOpticalSystem()
    obj_lens.add_optic(objective_lens)

    # Computed as following: going through T1 then CLens then T2
    # is equivalent to going through CLens with focal/4
    # Then the radius is computed as the Fourier transform of the input beam, per 2F lens system
    w0_y = (12.5e-3 * u.m * wavelength) / (2 * np.pi**2 * laser_radius)
    laser_shape_y = poppy.GaussianAperture(w=w0_y, pupil_diam=5 * w0_y)
    path_y = poppy.FresnelOpticalSystem(pupil_diameter=2 * w0_y,
                                        npix=pixel_width,
                                        beam_ratio=beam_ratio)
    path_y.add_optic(laser_shape_y)

    # Going through T1, slit and T2 is equivalent to going through a half-sized slit,
    # then propagating 1/4 the distance
    # Since we use 1D propagation, we can increase oversampling a lot for better results
    laser_shape_z = poppy.GaussianAperture(w=laser_radius,
                                           pupil_diam=slit_opening / 2)
    slit = poppy.RectangleAperture(name='Slit',
                                   width=slit_opening / 2,
                                   height=slit_opening / 2)
    path_z = poppy.FresnelOpticalSystem(pupil_diameter=slit_opening / 2,
                                        npix=pixel_width,
                                        beam_ratio=beam_ratio)
    path_z.add_optic(laser_shape_z)
    path_z.add_optic(slit)
    path_z.add_optic(noop, 0.25 * 100e-3 * u.m)

    # Propagate 1D signals
    wf_z = path_z.input_wavefront(wavelength=wavelength)
    create_wf_1d(wf_z, upsampling=simu_size)
    path_z.propagate(wf_z)

    wf_y = path_y.input_wavefront(wavelength=wavelength)
    create_wf_1d(wf_y, upsampling=simu_size, scale=10)
    path_y.propagate(wf_y)

    obj_aperture.propagate(wf_z)
    obj_aperture.propagate(wf_y)

    wf_z.wavelength /= refr_index
    wf_y.wavelength /= refr_index

    obj_lens.propagate(wf_z)
    obj_lens.propagate(wf_y)

    illumination = np.empty((npix_fov, npix_fov, npix_fov),
                            dtype=wf_z.intensity.dtype)

    # Make sure it is centered even if pixels are odd or even
    offset = 0 if npix_fov % 2 else 0.5

    for pix in range(npix_fov):
        pixel = pix - npix_fov // 2 + offset
        distance = pixel * pixelscale * u.pixel

        psf = poppy.FresnelOpticalSystem()
        psf.add_optic(noop, objective_focal + distance)

        wfc_y = wf_y.copy()
        wfc_z = wf_z.copy()

        psf.propagate(wfc_y)
        psf.propagate(wfc_z)

        resample_wavefront(wfc_y, pixelscale, fov_pixels)
        resample_wavefront(wfc_z, pixelscale, fov_pixels)

        mix = wf_mix(wfc_y, wfc_z)
        mix.normalize()

        illumination[:, pix, :] = mix.intensity

    if rel_thresh is not None:
        illumination = utils.threshold_crop(illumination, rel_thresh, 0)

    return illumination / illumination.sum(0).mean()
コード例 #10
0
def test_FixedSamplingImagePlaneElement(display=False):
    poppy_tests_fpath = os.path.dirname(os.path.abspath(
        poppy.__file__)) + '/tests/'

    # HST example - Following example in PROPER Manual V2.0 page 49.
    # This is an idealized case and does not correspond precisely to the real telescope
    # Define system with units
    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  # This is what's used in the PROPER example
    #d_pri_sec = 4.9069 * u.m      # however Lallo 2012 gives this value, which differs slightly
    # from what is used in the PROPER example case.
    fl_sec = -0.6790325 * u.m
    d_sec_to_focus = 6.3916645 * u.m  # place focal plane right at the beam waist after the SM
    fl_oap = 0.5 * u.m

    sampling = 2
    hst = poppy.FresnelOpticalSystem(npix=128,
                                     pupil_diameter=2.4 * u.m,
                                     beam_ratio=1. / sampling)
    g1 = poppy.QuadraticLens(fl_pri,
                             name='Primary',
                             planetype=poppy.poppy_core.PlaneType.pupil)
    g2 = poppy.QuadraticLens(fl_sec, name='Secondary')
    fpm = poppy.FixedSamplingImagePlaneElement(
        'BOWTIE FPM', poppy_tests_fpath + 'bowtie_fpm_0.05lamD.fits')
    oap = poppy.QuadraticLens(fl_oap, name='OAP')

    hst.add_optic(poppy.CircularAperture(radius=diam.value / 2))
    hst.add_optic(g1)
    hst.add_optic(g2, distance=d_pri_sec)
    hst.add_optic(fpm, distance=d_sec_to_focus)
    hst.add_optic(oap, distance=fl_oap)
    hst.add_optic(oap, distance=fl_oap)
    hst.add_optic(poppy.ScalarTransmission(
        planetype=poppy.poppy_core.PlaneType.intermediate, name='Image'),
                  distance=fl_oap)

    # Create a PSF
    if display: fig = plt.figure(figsize=(10, 5))
    psf, waves = hst.calc_psf(wavelength=lambda_m,
                              display_intermediates=display,
                              return_intermediates=True)

    # still have to do comparison of arrays
    psf_result = fits.open(poppy_tests_fpath +
                           'FITSFPMElement_test_result.fits')
    psf_result_data = psf_result[0].data
    psf_result_pxscl = psf_result[0].header['PIXELSCL']
    psf_result.close()

    np.testing.assert_allclose(
        psf[0].data,
        psf_result_data,
        rtol=1e-6,
        err_msg="PSF of this test does not match the saved result.",
        verbose=True)
    np.testing.assert_allclose(
        waves[-1].pixelscale.value,
        psf_result_pxscl,
        err_msg="PSF pixelscale of this test does not match the saved result.",
        verbose=True)
コード例 #11
0
def test_fresnel_noninteger_oversampling(display_intermediates=False):
    '''Test for noninteger oversampling for basic FresnelOpticalSystem() using HST example system'''
    lambda_m = 0.5e-6 * u.m
    # lambda_m = np.linspace(0.475e-6, 0.525e-6, 3) * 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')
    image_plane = poppy.ScalarTransmission(
        planetype=poppy_core.PlaneType.image, name='focus')

    npix = 128

    oversample1 = 2
    hst1 = poppy.FresnelOpticalSystem(pupil_diameter=diam,
                                      npix=npix,
                                      beam_ratio=1 / oversample1)
    hst1.add_optic(poppy.CircularAperture(radius=diam.value / 2))
    hst1.add_optic(
        poppy.SecondaryObscuration(secondary_radius=0.396,
                                   support_width=0.0264,
                                   support_angle_offset=45.0))
    hst1.add_optic(m1)
    hst1.add_optic(m2, distance=d_pri_sec)
    hst1.add_optic(image_plane, distance=d_sec_to_focus)

    if display_intermediates: plt.figure(figsize=(12, 8))
    psf1 = hst1.calc_psf(wavelength=lambda_m,
                         display_intermediates=display_intermediates)

    # now test the second system which has a different oversampling factor
    oversample2 = 2.0
    hst2 = poppy.FresnelOpticalSystem(pupil_diameter=diam,
                                      npix=npix,
                                      beam_ratio=1 / oversample2)
    hst2.add_optic(poppy.CircularAperture(radius=diam.value / 2))
    hst2.add_optic(
        poppy.SecondaryObscuration(secondary_radius=0.396,
                                   support_width=0.0264,
                                   support_angle_offset=45.0))
    hst2.add_optic(m1)
    hst2.add_optic(m2, distance=d_pri_sec)
    hst2.add_optic(image_plane, distance=d_sec_to_focus)

    if display_intermediates: plt.figure(figsize=(12, 8))
    psf2 = hst2.calc_psf(wavelength=lambda_m,
                         display_intermediates=display_intermediates)

    # Now test a 3rd HST system with oversample of 2.5 and compare to hardcoded result
    oversample3 = 2.5
    hst3 = poppy.FresnelOpticalSystem(pupil_diameter=diam,
                                      npix=npix,
                                      beam_ratio=1 / oversample3)
    hst3.add_optic(poppy.CircularAperture(radius=diam.value / 2))
    hst3.add_optic(
        poppy.SecondaryObscuration(secondary_radius=0.396,
                                   support_width=0.0264,
                                   support_angle_offset=45.0))
    hst3.add_optic(m1)
    hst3.add_optic(m2, distance=d_pri_sec)
    hst3.add_optic(image_plane, distance=d_sec_to_focus)

    if display_intermediates: plt.figure(figsize=(12, 8))
    psf3 = hst3.calc_psf(wavelength=lambda_m,
                         display_intermediates=display_intermediates)

    assert np.allclose(
        psf1[0].data, psf2[0].data
    ), 'PSFs with oversampling 2 and 2.0 are surprisingly different.'
    np.testing.assert_almost_equal(
        psf3[0].header['PIXELSCL'],
        0.017188733797782272,
        decimal=7,
        err_msg=
        'pixelscale for the PSF with oversample of 2.5 is surprisingly different from expected result.'
    )
コード例 #12
0
f = 20 * u.mm

coefficients_sequence = [0.0, 0.0, 0.0, 0, 0.0, 0, 0.0, 0.0, 0.0] * u.um

osys = poppy.FresnelOpticalSystem(pupil_diameter=2 * radius,
                                  npix=256,
                                  beam_ratio=0.25)

osys.add_optic(poppy.CircularAperture(radius=radius,
                                      name='pupil'))  # The system pupil

zernikewfe = poppy.ZernikeWFE(radius=radius,
                              coefficients=coefficients_sequence)
osys.add_optic(zernikewfe)

m1 = poppy.QuadraticLens(f, name='objective lens')
osys.add_optic(m1, distance=f)

#osys.add_optic(poppy.CircularAperture(radius=diam/2, name='aperture0'), distance = 0*u.mm)
#m2 = poppy.QuadraticLens(fl_sec, name='Secondary')
#osys.add_optic(m2, distance=d_pri_sec)
#osys.add_optic(poppy.ScalarTransmission(name='free space'), distance=f1);

delta = 8 * u.um

osys.add_detector(pixelscale=0.1 * u.um / u.pixel,
                  fov_pixels=256,
                  distance=f + delta)

osys.describe()
コード例 #13
0
def csvFresnel(rx_csv, samp, oversamp, axis, break_plane, source_ZWFE_coeff,
               irisAOmap, irisAOstatus):
    EP_radius = rx_csv['Radius_m'][
        2] * u.m  # Element [2] is IrisAO because Element [0] is the diverging source, [1] is OAP1
    irisAO_radius = rx_csv['Radius_m'][6] * u.m

    sys_build = poppy.FresnelOpticalSystem(pupil_diameter=2 * EP_radius,
                                           npix=samp,
                                           beam_ratio=oversamp)
    #sys_build = poppy.OpticalSystem(pupil_diameter=2*EP_radius, npix=samp, beam_ratio=oversamp)

    # Entrance Aperture
    sys_build.add_optic(poppy.CircularAperture(radius=EP_radius))

    # Apply if off-axis LGS is used
    if axis == 'LGS':
        src_aberr = poppy.ZernikeWFE(radius=irisAO_radius.value,
                                     coefficients=source_ZWFE_coeff)
        sys_build.add_optic(src_aberr)
    # if the on-axis target is used, then a source aberration will not be applied (hence on-axis and at infinity)

    # Build LGS optical system from CSV file to the break plane
    for n_optic, optic in enumerate(rx_csv):  # n_optic: count, optic: value
        #print('n_optic = ', n_optic)

        dz = optic[
            'Distance_m'] * u.m  # Propagation distance from the previous optic (n_optic-1)
        fl = optic[
            'Focal_Length_m'] * u.m  # Focal length of the current optic (n_optic)

        #print('Check PSD file for %s: %s' % (optic['Name'], optic['surf_PSD']))
        # if PSD file present
        if optic['surf_PSD_filename'] != 'none':
            # make a string insertion for the file location
            surf_file_loc = optic['surf_PSD_folder'] + optic[
                'surf_PSD_filename'] + '.fits'
            # call surfFITS to send out surface map
            optic_surface = mf.surfFITS(file_loc=surf_file_loc,
                                        optic_type=optic['optic_type'],
                                        opdunit=optic['OPD_unit'],
                                        name=optic['Name'] + ' surface')
            # Add generated surface map to optical system
            sys_build.add_optic(optic_surface, distance=dz)

            if fl != 0:  # powered optic with PSD file present
                sys_build.add_optic(poppy.QuadraticLens(fl,
                                                        name=optic['Name']))
                # no distance; surface comes first
                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

            elif optic[
                    'Type'] != 'pupil':  # non-powered optic but has PSD present that is NOT the pupil
                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

        # if no PSD file present (DM, focal plane, testing optical surface)
        else:
            #print('Enter no PSD file condition')
            # if powered optic is being tested
            if fl != 0:
                #print('Enter powered optic condition')
                sys_build.add_optic(poppy.QuadraticLens(fl,
                                                        name=optic['Name']),
                                    distance=dz)
                if n_optic > 0:
                    sys_build.add_optic(
                        poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                               name=optic['Name'] +
                                               " aperture"))

            # if building IrisAO segmented DM
            elif optic['Name'] == 'IrisAO':
                #print('Enter build IrisAO map')
                if irisAOstatus == True:
                    #print('IrisAO present')
                    #sys_build.add_optic(poppy.MultiHexagonAperture(name='IrisAO DM', rings=3, side=7e-4, gap=7e-6, center=True), distance=dz)
                    sys_build.add_optic(irisAOmap)
                else:
                    #print('IrisAO not present')
                    sys_build.add_optic(poppy.ScalarTransmission(
                        planetype=PlaneType.intermediate, name=optic['Name']),
                                        distance=dz)

                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

            # for DM, flat mirrors
            elif optic['Type'] == 'mirror' or optic['Type'] == 'DM':
                #print('Enter mirror or DM conditon')
                sys_build.add_optic(poppy.ScalarTransmission(
                    planetype=PlaneType.intermediate, name=optic['Name']),
                                    distance=dz)
                sys_build.add_optic(
                    poppy.CircularAperture(radius=optic['Radius_m'] * u.m,
                                           name=optic['Name'] + " aperture"))

            else:  # for focal plane, science plane, lyot plane
                #print('Enter focal plane conditon')
                if optic['Type'] == 'fplane':
                    # Apply focal plane correction distance
                    dz = optic['Distance_m'] * u.m + optic['Correction_m'] * u.m

                sys_build.add_optic(poppy.ScalarTransmission(
                    planetype=PlaneType.intermediate, name=optic['Name']),
                                    distance=dz)

        # if the most recent optic studied was the break plane, break out of loop.
        if optic['Name'] == break_plane:
            #print('Finish building FresnelOpticalSystem at %s' % break_plane)
            break

    return sys_build