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
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,
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" )
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
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()
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)
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)
# 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(
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