def get_jwst_coords(outDir): #-# Generate the pupil with segments and spiders # Use poppy to create JWST aperture without spiders log.info('Creating and saving aperture') jwst_pup = poppy.MultiHexagonAperture(rings=2, flattoflat=FLAT_TO_FLAT) # Create JWST pupil without spiders jwst_pup.display(colorbar=False) # Show pupil (will be saved to file) plt.title('JWST telescope pupil') # Number the segments for i in range(NB_SEG+1): ycen, xcen = jwst_pup._hex_center(i) plt.annotate(str(i), size='x-large', xy=(xcen-0.1, ycen-0.1)) # -0.1 is for shifting the numbers closer to the segment centers # Save a PDF version of the pupil plt.savefig(os.path.join(outDir, 'JWST_aperture.pdf')) # Since WebbPSF creates images by controlling the exit pupil, # let's also create the exit pupil instead of the entrance pupil. # I do this by flipping the y-coordinates of the segments. plt.clf() jwst_pup.display(colorbar=False) # Show pupil plt.title('JWST telescope exit pupil') # Number the segments for i in range(NB_SEG+1): ycen, xcen = jwst_pup._hex_center(i) ycen *= -1 plt.annotate(str(i), size='x-large', xy=(xcen-0.1, ycen-0.1)) # -0.1 is for shifting the number labels closer to the segment centers # Save a PDF version of the exit pupil plt.savefig(os.path.join(outDir, 'JWST_exit_pupil.pdf')) # Get pupil as fits image pupil_dir = jwst_pup.sample(wavelength=WVLN, npix=IM_SIZE_PUPIL, grid_size=FLAT_DIAM, return_scale=True) # If the image size is equivalent to the total diameter of the telescope, we don't have to worry about sampling later # But for the JWST case with poppy it makes such a small difference that I am skipping it for now util.write_fits(pupil_dir[0], os.path.join(outDir, 'pupil.fits')) #-# Get the coordinates of the central pixel of each segment seg_position = np.zeros((NB_SEG, 2)) # holds x and y position of each central pixel for i in range(NB_SEG+1): # our pupil is still counting the central segment as seg 0, so we need to include it # in the loop, however, we will just discard the values for the center if i == 0: # Segment 0 is the central segment, which we want to skip and not put into seg_position continue # Continues with the next iteration of the loop else: seg_position[i-1, 1], seg_position[i-1, 0] = jwst_pup._hex_center(i) # y, x = center position seg_position[i - 1, 1] *= -1 # inverting the y-axis because we want to work with the EXIT PUPIL!!! # Units are meters!!! return seg_position
def multi_hexagon(rings_number, sec_rad, side_dist = 1.0, segment_gap = 0.01): """ multi_hexagon(rings_number, sec_rad, side_dist = 1.0, segment_gap = 0.01) # rings : The number of rings of hexagons to include, not counting the central segment # side_dist : Distance between sides (flat-to-flat) of the hexagon, in meters. Default is 1.0 # segment_gap : Gap between adjacent segments, in meters. Default is 0.01 m = 1 cm # sec_rad : scondary obstacle radius """ ap = poppy.MultiHexagonAperture(name='ApertureHex', flattoflat = side_dist, gap = segment_gap,rings =rings_number) # 3 rings of 2 m segments yields 14.1 m circumscribed diameter sec = poppy.SecondaryObscuration(secondary_radius = float(sec_rad), n_supports = 4, support_width = 0.1) # secondary with spiders atlast = poppy.CompoundAnalyticOptic( opticslist=[ap, sec], name='Mock ATLAST') # combine into one optic plt.figure(figsize=(12,8)) atlast.display(npix=1024, colorbar_orientation='vertical') return atlast
def test_segment_tilt_sign_and_direction(display=False): hexdm = poppy.HexSegmentedDeformableMirror(flattoflat=0.5 * u.m, rings=1) osys2 = poppy.OpticalSystem(pupil_diameter=2 * u.m, npix=128, oversample=1) osys2.add_pupil( poppy.MultiHexagonAperture(flattoflat=0.5 * u.m, rings=1, center=True)) osys2.add_pupil(hexdm) osys2.add_detector(0.10, fov_arcsec=10) psf_ref = osys2.calc_psf() # reference, with no tilts hexdm.set_actuator(0, 0.2 * u.micron, 0, 0) # piston hexdm.set_actuator(1, 0, 2 * u.arcsec, 0) # tip hexdm.set_actuator(2, 0, 0, 1 * u.arcsec) # tilt if display: import matplotlib.pyplot as plt hexdm.display(what='opd', colorbar_orientation='vertical', opd_vmax=2e-6) plt.figure(figsize=(14, 5)) plt.suptitle("Segment tilt sign test (Fraunhofer propagation)", fontweight='bold') psf2 = osys2.calc_psf(display_intermediates=display) diff_psf = psf2[0].data - psf_ref[0].data if display: plt.figure() poppy.display_psf_difference(psf2, psf_ref) assert brighter_left_half( diff_psf ), 'Tilting a segment with +X tilt WFE should move its PSF to -X' assert not brighter_top_half( diff_psf ), 'Tilting a segment with +Y tilt WFE should move its PSF to -Y'
import poppy import numpy as np import matplotlib.pyplot as plt import logging logging.basicConfig(level=logging.DEBUG) np.seterr(divide='ignore', invalid='ignore') osys = poppy.OpticalSystem() osys.add_pupil(poppy.CircularAperture(radius=3)) # pupil radius in meters osys.add_detector(pixelscale=0.010, fov_arcsec=5.0) plt.figure(figsize=(16, 12)) ap = poppy.MultiHexagonAperture( rings=3, flattoflat=2 ) # 3 rings of 2 m segments yields 14.1 m circumscribed diameter sec = poppy.SecondaryObscuration(secondary_radius=1.5, n_supports=4, support_width=0.1) # secondary with spiders atlast = poppy.CompoundAnalyticOptic( opticslist=[ap, sec], name='Mock ATLAST') # combine into one optic atlast.display(npix=1024, colorbar_orientation='vertical') plt.savefig('example_atlast_pupil.png', dpi=100) plt.figure(figsize=(8, 6)) osys = poppy.OpticalSystem() osys.add_pupil(atlast) osys.add_detector(pixelscale=0.010, fov_arcsec=2.0) psf = osys.calc_psf(1e-6)