예제 #1
0
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
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
예제 #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().'
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)

    osys.add_optic(aperture)  # The system pupil

    coefficients = generate_coefficients(wavelength, wf_error_budget)
    zernike_wfe = poppy.ZernikeWFE(radius=radius,
                                   coefficients=coefficients,
                                   name='Aberrated Wavefront')

    osys.add_optic(zernike_wfe)  # Non ideality

    osys.add_optic(objective, distance=fl_obj)

    osys.add_detector(pixelscale=pix_size / u.pixel,
                      fov_pixels=n_pix,
예제 #5
0
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"
    )
예제 #6
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
예제 #7
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()
예제 #8
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)
예제 #9
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.'
    )
Created on Tue Sep  1 10:02:05 2020

@author: Andrea Bassi
"""

import poppy
import astropy.units as u
import matplotlib.pyplot as plt

radius = 6 * u.mm
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)
예제 #11
0
# Can be logging.CRITICAL, logging.WARN, logging.INFO, logging.DEBUG for increasingly verbose output

import toliman_optics

m1 = toliman_optics.phase_rosette(
    m1_rad,  # edge radius
    5,  # 5-fold rotational symmetry
    0.25,  # rosette radius
    0.8,
    0.065,  # 7.5 cm semimajor
    0.5  # phase
)
m1.name = 'TOLIMAN rosette primary mirror'

toliman = poppy.FresnelOpticalSystem(name='TOLIMAN telescope',
                                     pupil_diameter=m1_rad,
                                     npix=1024,
                                     beam_ratio=0.5)

# Secondary mirror obscuration & spider
toliman.add_optic(
    poppy.SecondaryObscuration(name='Secondary mirror support',
                               secondary_radius=m2_rad,
                               n_supports=m2_supports,
                               support_width=m2_strut_width,
                               support_angle_offset=0 * u.deg), pupil_m2_dist)

# Primary mirror
# Rosette components
toliman.add_optic(m1, m1_m2_dist)
# Central aperture - treat as a secondary obscuration with no spider
toliman.add_optic(
예제 #12
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