コード例 #1
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
コード例 #2
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().'
コード例 #3
0
ファイル: test_core.py プロジェクト: spacetelescope/poppy
def test_inwave_fraunhofer(plot=False):
    '''Verify basic functionality of the inwave kwarg for a basic OpticalSystem()'''
    npix = 128
    oversample = 2
    diam = 2.4 * u.m
    lambda_m = 0.5e-6 * u.m
    # calculate the Fraunhofer diffraction pattern
    hst = poppy.OpticalSystem(pupil_diameter=diam,
                              npix=npix,
                              oversample=oversample)
    hst.add_pupil(poppy.CircularAperture(radius=diam.value / 2))
    hst.add_pupil(
        poppy.SecondaryObscuration(secondary_radius=0.396,
                                   support_width=0.0264,
                                   support_angle_offset=45.0))
    hst.add_image(
        poppy.ScalarTransmission(planetype=poppy_core.PlaneType.image,
                                 name='focus'))

    if plot:
        plt.figure(figsize=(9, 3))
    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.Wavefront(wavelength=lambda_m,
                           npix=npix,
                           diam=diam,
                           oversample=oversample)
    if plot:
        plt.figure(figsize=(9, 3))
    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 in OpticalSystem().'
コード例 #4
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"
    )
コード例 #5
0
    def _get_optical_system(self,
                            fft_oversample=2,
                            detector_oversample=None,
                            fov_arcsec=2.8,
                            fov_pixels=None,
                            options=dict()):
        """ Return an OpticalSystem instance corresponding to the instrument as currently configured.

        When creating such an OpticalSystem, you must specify the parameters needed to define the
        desired sampling, specifically the oversampling and field of view.


        Parameters
        ----------

        fft_oversample : int
            Oversampling factor for intermediate plane calculations. Default is 2
        detector_oversample: int, optional
            By default the detector oversampling is equal to the intermediate calculation oversampling.
            If you wish to use a different value for the detector, set this parameter.
            Note that if you just want images at detector pixel resolution you will achieve higher fidelity
            by still using some oversampling (i.e. *not* setting `oversample_detector=1`) and instead rebinning
            down the oversampled data.
        fov_pixels : float
            Field of view in pixels. Overrides fov_arcsec if both set.
        fov_arcsec : float
            Field of view, in arcseconds. Default is 2
        options : dict
            Other arbitrary options for optical system creation


        Returns
        -------
        osys : poppy.OpticalSystem
            an optical system instance representing the desired configuration.

        """

        if detector_oversample is None: detector_oversample = fft_oversample

        #poppy_core._log.debug("Oversample: %d  %d " % (fft_oversample, detector_oversample))
        optsys = poppy.OpticalSystem(name=self.name, oversample=fft_oversample)
        if 'source_offset_r' in options.keys():
            optsys.source_offset_r = options['source_offset_r']
        if 'source_offset_theta' in options.keys():
            optsys.source_offset_theta = options['source_offset_theta']

        optsys.npix = self.npix

        #---- set pupil intensity
        pupil_optic = GeminiPrimary(undersized=self._undersized_secondary)
        #if self._undersized_secondary:
        #pupil_optic.obscuration_diameter = 1.02375 # SM outer diameter (vs inner hole projected diameter)

        #---- set pupil OPD
        if isinstance(self.pupilopd, str):  # simple filename
            full_opd_path = self.pupilopd if os.path.exists(
                self.pupilopd) else os.path.join(self._datapath, "OPD",
                                                 self.pupilopd)
        elif hasattr(self.pupilopd, '__getitem__') and isinstance(
                self.pupilopd[0], basestring):  # tuple with filename and slice
            full_opd_path = (self.pupilopd[0] if os.path.exists(
                self.pupilopd[0]) else os.path.join(
                    self._datapath, "OPD", self.pupilopd[0]), self.pupilopd[1])
        elif isinstance(self.pupilopd,
                        fits.HDUList):  # OPD supplied as FITS HDUList object
            full_opd_path = self.pupilopd  # not a path per se but this works correctly to pass it to poppy
        elif self.pupilopd is None:
            full_opd_path = None
        else:
            raise TypeError(
                "Not sure what to do with a pupilopd of that type:" +
                str(type(self.pupilopd)))

        #---- apply pupil intensity and OPD to the optical model
        optsys.add_pupil(name='Gemini Primary',
                         optic=pupil_optic,
                         opd=full_opd_path,
                         opdunits='micron',
                         rotation=self._rotation)

        if self.dms:
            optsys.add_pupil(optic=self.woofer)
            optsys.add_pupil(optic=self.tweeter)

        # GPI Apodizer
        apod = GPI_Apodizer(name=self.apodizer, satspots=self.satspots)
        optsys.add_pupil(optic=apod)

        if self._display_before:
            optsys.add_image(optic=poppy.ScalarTransmission(name='Before FPM',
                                                            transmission=1))

        # GPI FPM
        fpm = GPI_FPM(name=self.occulter)
        optsys.add_image(optic=fpm)

        if self._display_before:
            optsys.add_pupil(optic=poppy.ScalarTransmission(name='Before Lyot',
                                                            transmission=1))

        # GPI Lyot Mask
        lyot = GPI_LyotMask(name=self.lyotmask, tabs=self.lyot_tabs)
        optsys.add_pupil(optic=lyot)

        #--- add the detector element.
        if fov_pixels is None:
            fov_pixels = np.round(fov_arcsec / self.pixelscale)
            if 'parity' in self.options.keys():
                if self.options['parity'].lower() == 'odd' and np.remainder(
                        fov_pixels, 2) == 0:
                    fov_pixels += 1
                if self.options['parity'].lower() == 'even' and np.remainder(
                        fov_pixels, 2) == 1:
                    fov_pixels += 1

        optsys.add_detector(self.pixelscale,
                            fov_pixels=fov_pixels,
                            oversample=detector_oversample,
                            name=self.name + " lenslet array")

        return optsys
コード例 #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.'
    )
コード例 #10
0
    poppy.fresnel.ConicLens(f_lens=m1_fl,
                            K=m1_conic,
                            radius=m1_rad,
                            name="Primary mirror"), 0 * u.m)

# Secondary mirror
toliman.add_optic(
    poppy.fresnel.ConicLens(f_lens=m2_fl,
                            K=m2_conic,
                            radius=m2_rad,
                            name="Secondary mirror"), m1_m2_dist)

# Aperture in primary
toliman.add_optic(poppy.CircularAperture(radius=m1_aperture_rad), m1_m2_dist)

toliman.add_optic(poppy.ScalarTransmission(
    planetype=poppy.fresnel.PlaneType.image, name='focus'),
                  distance=m2_focus_dist)

poppy.describe()
# values = rosette.sample(npix=2048)    # evaluate on 512 x 512 grid

# fig=plt.figure(figsize=(10,5))
# rosette.display(what='both')         # display phase and amplitude transmission;
# pylab.savefig('test.png')
# plt.close(fig)
# plt.show(block=False)

# npix = 1024 # ~512 is minimum to accurately recover the central diffraction spike
# wf = poppy.FresnelWavefront(0.5*u.m,wavelength=2200e-9,npix=npix,oversample=4)
# wf *= poppy.CircularAperture(radius=0.5)
コード例 #11
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