Exemple #1
0
def generate_psf(coeffs):
    coeffs = np.insert(coeffs, 0, 0)
    # Declare physical constants
    radius = 2e-3
    wavelength = 1500e-9
    FOV_pixels = 512  #Increase this (finer) 1st.
    h = 60e-6 / 2  #Increase this (wider) 2nd
    f = 4.5e-3 * 2
    theta = np.arctan(h / f) / np.pi * 180 * 60 * 60  # in arcsec
    pixscale = theta / FOV_pixels  #somehow resize this after - bilinear reduction of resolution

    coeffs = (np.asarray(coeffs) / 2) * 1e-6
    # Create PSF
    osys = poppy.OpticalSystem()
    circular_aperture = poppy.CircularAperture(radius=radius)
    osys.add_pupil(circular_aperture)
    thinlens = poppy.ZernikeWFE(radius=radius, coefficients=coeffs)
    osys.add_pupil(thinlens)
    osys.add_detector(pixelscale=pixscale, fov_pixels=FOV_pixels)
    psf_with_zernikewfe, all_wfs = osys.calc_psf(wavelength=wavelength,
                                                 display_intermediates=False,
                                                 return_intermediates=True)
    pupil_wf = all_wfs[1]  #this one ***
    final_wf = all_wfs[-1]  #sometimes referred to as wf
    # psf = psf_with_zernikewfe[0].data
    return pupil_wf.phase, final_wf.amplitude**2
    def makePSF(self, makePSFInputDict: dict, makePSFOptions: zernikeoptions):
        coeffs = makePSFInputDict["coeffs"]
        show = makePSFOptions["show"]
        units = makePSFOptions["units"]
        extraPlots = makePSFOptions["extraPlots"]

        if units is "microns":
            coeffs = np.asarray(coeffs) * 1e-6

        osys = poppy.OpticalSystem()
        circular_aperture = poppy.CircularAperture(radius=self.radius)
        osys.add_pupil(circular_aperture)
        thinlens = poppy.ZernikeWFE(radius=self.radius, coefficients=coeffs)
        osys.add_pupil(thinlens)
        # osys.add_detector(pixelscale=self.pixscale, fov_arcsec=self.FOV)
        osys.add_detector(pixelscale=self.pixscale, fov_pixels=self.FOV_pixels)

        if extraPlots:
            plt.figure(1)
        # psf_with_zernikewfe, final_wf = osys.calc_psf(wavelength=self.wavelength, display_intermediates=show,
        #                                               return_final=True)
        psf_with_zernikewfe, all_wfs = osys.calc_psf(
            wavelength=self.wavelength,
            display_intermediates=show,
            return_intermediates=True,
        )
        final_wf = all_wfs[-1]
        pupil_wf = all_wfs[1]

        if extraPlots:
            psf = psf_with_zernikewfe
            psfImage = psf[0].data
            # plt.figure(2)
            # plt.clf()
            # poppy.display_psf(psf, normalize='peak', cmap='viridis', scale='linear', vmin=0, vmax=1)
            plt.figure(3)

            wf = final_wf
            wf = pupil_wf

            plt.clf()
            plt.pause(0.001)
            plt.subplot(1, 2, 1)
            plt.imshow(wf.amplitude**2)
            plt.title("Amplitude ^2")
            plt.colorbar()
            plt.subplot(1, 2, 2)
            plt.imshow(wf.phase)
            plt.title("Phase")
            plt.colorbar()
            plt.tight_layout()
            poppy.display_psf(psf_with_zernikewfe, title="PSF")

        self.psf = psf_with_zernikewfe
        self.wf = final_wf
        self.complex_psf = self.wf.amplitude * np.exp(1j * self.wf.phase)
        self.osys_obj = osys
        self.pupil_wf = pupil_wf
    def makeZernikePSF(self, coeffs=(0, 0, 0, 0, 0), show=False, units='microns',
                       extraPlots=False):
        # RADIUS = 1.0 # meters
        # WAVELENGTH = 1500e-9 # meters
        # PIXSCALE = 0.01 # arcsec / pix
        # FOV = 1 # arcsec
        # NWAVES = 1.0
        # FOV_PIXELS = 128

        if units == 'microns':
            coeffs = np.asarray(coeffs) * 1e-6

        osys = poppy.OpticalSystem()
        circular_aperture = poppy.CircularAperture(radius=self.radius)
        osys.add_pupil(circular_aperture)
        thinlens = poppy.ZernikeWFE(radius=self.radius, coefficients=coeffs)
        osys.add_pupil(thinlens)
        #osys.add_detector(pixelscale=self.pixscale, fov_arcsec=self.FOV)
        osys.add_detector(pixelscale=self.pixscale, fov_pixels=self.FOV_pixels)

        if extraPlots:
            plt.figure(1)
        # psf_with_zernikewfe, final_wf = osys.calc_psf(wavelength=self.wavelength, display_intermediates=show,
        #                                               return_final=True)
        psf_with_zernikewfe, all_wfs = osys.calc_psf(wavelength=self.wavelength, display_intermediates=show,
                                                      return_intermediates=True)
        final_wf = all_wfs[-1]
        pupil_wf = all_wfs[1] #this one ***

        if extraPlots:
            psf = psf_with_zernikewfe
            psfImage = psf[0].data
            plt.figure(2)
            plt.clf()
            poppy.display_psf(psf, normalize='peak', cmap='viridis', scale='linear', vmin=0, vmax=1)
            plt.pause(0.001)
            plt.figure(3)

            wf = final_wf
            wf = pupil_wf

            plt.clf()
            plt.pause(0.001)
            plt.subplot(1, 2, 1)
            plt.imshow(wf.amplitude ** 2)
            plt.title('Amplitude ^2')
            plt.colorbar()
            plt.subplot(1, 2, 2)
            plt.imshow(wf.phase)
            plt.title('Phase')
            plt.colorbar()
            plt.tight_layout()

        self.psf = psf_with_zernikewfe
        self.wf = final_wf
        self.osys_obj = osys
        self.pupil_wf = pupil_wf
 def __init__(self,
              optic=None,
              radius=1 * u.m,
              include_factor_of_two=False,
              **kwargs):
     name = optic.name + " on a tip/tilt stage"
     super().__init__(name=name, **kwargs)
     self.optic = optic
     self.include_factor_of_two = include_factor_of_two
     self.tilt_optic = poppy.ZernikeWFE(coefficients=[0, 0, 0],
                                        radius=radius)
     self.pupil_diam = 2 * radius
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,
                      distance=fl_obj + delta)

    # System description just one time
    if image_idx == 1:
        print('\nOptical System description:')
        osys.describe()
        print('\n')
Exemple #6
0
def calculate_rms(number_of_zerinke_modes, number_of_scans, max_coeff_value,
                  seed):
    # create_coeffs_list(number_of_scans, number_of_zerinke_modes, max_coeff_value, seed)
    coeffs_list = create_coeffs_list(number_of_scans, number_of_zerinke_modes,
                                     max_coeff_value, seed)
    # coeffs_list = specify_coeffs_list()
    radius = 2e-3
    wavelength = 1500e-9
    FOV_pixels = 512
    h = 60e-6 / 2
    f = 4.5e-3 * 2
    theta = np.arctan(h / f) / np.pi * 180 * 60 * 60  # in arcsec
    pixscale = theta / FOV_pixels

    rms_list = []
    peak_to_valley_list = []
    plot = False
    # rms_list.append(poppy.ZernikeWFE(radius=2e-3, coefficients=coeffs).peaktovalley())
    for coeffs in coeffs_list:
        # print(coeffs)
        coeffs = np.asarray(coeffs) * 1e-6
        osys = poppy.OpticalSystem()
        circular_aperture = poppy.CircularAperture(radius=radius)
        osys.add_pupil(circular_aperture)
        thinlens = poppy.ZernikeWFE(radius=radius, coefficients=coeffs)
        osys.add_pupil(thinlens)
        osys.add_detector(pixelscale=pixscale, fov_pixels=FOV_pixels)
        psf_with_zernikewfe, all_wfs = osys.calc_psf(
            wavelength=wavelength,
            display_intermediates=False,
            return_intermediates=True)
        pupil_wf = all_wfs[1]  #this one ***
        if plot:
            final_wf = all_wfs[-1]  #sometimes referred to as wf

            psf = psf_with_zernikewfe[0].data
            # plt.figure(1)
            # plt.imshow(psf)
            # plt.figure(2)
            # poppy.display_psf(psf_with_zernikewfe, normalize='peak', cmap='viridis', scale='linear', vmin=0, vmax=1)
            # plt.show()

            plt.figure(1, figsize=[9, 3])
            plt.subplot(131)
            plt.imshow(pupil_wf.phase)
            plt.title('Pupil Phase')
            plt.colorbar()
            plt.subplot(132)
            plt.imshow(final_wf.amplitude**2)
            plt.title('PSF intensity')
            plt.colorbar()
            plt.subplot(133)
            plt.imshow(final_wf.phase)
            plt.title('PSF phase')
            plt.colorbar()
            plt.figure(2)
            plt.imshow(psf)
            plt.title('PSF')
            plt.colorbar()
            plt.show()
        # print(np.std(pupil_wf.phase))
        rms_list += [np.std(pupil_wf.phase)]
        peak_to_valley_list += [
            np.amax(pupil_wf.phase) - np.amin(pupil_wf.phase)
        ]
        # input('')

    # print(len(rms_list))
    # print(max(rms_list), min(rms_list))
    # print(np.average(rms_list))
    return rms_list, peak_to_valley_list
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)
#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)
Exemple #8
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
Exemple #9
0
def make_coronagraph(wfe_coeffs,npix_pupil=512,npix_detector=128,wavelength=1e-6*u.m,oversample=4,pixelscale=0.01,sensor_defocus=0.5,vortex_charge=2,llowfs=False,mask_type='fqpm',obscuration=False,lyot_factor=0.9):
    #sensor_defocus: defocus of llowfs detector in waves peak-to-valley
    
    #these values are picked rather arbitrarily, but seem to work
    aperture_radius = 3*u.m
    #lyot_radius=2.6*u.m
    lyot_radius=lyot_factor*aperture_radius
    pupil_radius = 3*aperture_radius

    
    #create the optical system
    osys = poppy.OpticalSystem("LLOWFS", oversample=oversample, npix=npix_pupil, pupil_diameter=2*pupil_radius)
    
    ap = poppy.CircularAperture(radius=aperture_radius)
    if obscuration:
        obsc = poppy.SecondaryObscuration(secondary_radius=0.5*u.m, n_supports=0)
        osys.add_pupil(poppy.CompoundAnalyticOptic(opticslist=[ap,obsc])) #osys.add_pupil(poppy.AsymmetricSecondaryObscuration(secondary_radius=0.5,support_width=0.2*u.meter,support_angle=(0,120,240)))
    else:
        osys.add_pupil(ap)
        
    error = poppy.ZernikeWFE(radius=aperture_radius, coefficients=wfe_coeffs)
    osys.add_pupil(error)
    
    #inject wavefrotn error at the pupil
    
    
    #correct for fqpm (and vvc) alignment
    osys.add_pupil(poppy.FQPM_FFT_aligner())
    osys.add_image() #helper for plotting intermediates
    
    #select mask type
    if mask_type is 'fqpm':
        cgph_mask = poppy.IdealFQPM(wavelength=wavelength,name='FQPM Mask')
    elif mask_type is 'vortex':
        cgph_mask = VortexMask(charge=vortex_charge,wavelength=wavelength,name='Vortex Mask')
    else:
        raise ValueError("mask_type must be 'fqpm' or 'vortex'")
    cgph_mask._wavefront_display_hint='phase'
    osys.add_image(cgph_mask)
    
    #correct alignment back the other way
    osys.add_pupil(poppy.FQPM_FFT_aligner(direction='backward'))
    #osys.add_pupil()
    
    lyot = poppy.CircularAperture(radius=lyot_radius,name='Lyot Stop')
    lyot._wavefront_display_hint='intensity'
    if obscuration:
        lyot_obsc = poppy.InverseTransmission(poppy.SquareAperture(size=1.4*u.m))
        lyot = poppy.CompoundAnalyticOptic(opticslist=[lyot,lyot_obsc])

    if llowfs:
        #take the rejected light for the LLOWFS
        lyot_reflection = poppy.InverseTransmission(lyot)
        lyot_extent = poppy.CircularAperture(radius=pupil_radius)
        lyot = poppy.CompoundAnalyticOptic(opticslist = [lyot_reflection,lyot_extent])
        lyot._wavefront_display_hint='intensity'
        osys.add_pupil(lyot)
        #if obscuration:
        #    obsc = poppy.InverseTransmission(obsc)
        #    osys.add_pupil(obsc)

        
        #Add a defocus term to the sensor
        #Calc of peak-to-valley WFE: https://poppy-optics.readthedocs.io/en/stable/wfe.html
        defocus_coeff = sensor_defocus*wavelength.to(u.m).value
        sensor_defocus_wfe = poppy.ZernikeWFE(radius=pupil_radius,coefficients=[0,0,0,defocus_coeff])
        osys.add_pupil(sensor_defocus_wfe)
        

        #osys.add_pupil()
        osys.add_detector(pixelscale=pixelscale, fov_pixels=npix_detector, oversample=1)
    else:
        #add lyot stop
        osys.add_pupil(lyot)
        osys.add_detector(pixelscale=pixelscale, fov_arcsec=1)
        
    return osys