Loading CpicImgSim/psf_simulation.py 0 → 100644 +106 −0 Original line number Diff line number Diff line import numpy as np from astropy.io import fits from hcipy import Field, Wavefront, DeformableMirror, FraunhoferPropagator from hcipy import SurfaceApodizer, SurfaceAberrationAtDistance from hcipy import make_pupil_grid, make_circular_aperture, make_focal_grid from hcipy import make_xinetics_influence_functions from hcipy import read_fits from .config import cpism_refdata, S from .optics import filter_throughput # initial psf simulation apm, apm_header = fits.getdata( f'{cpism_refdata}/optics/apm.fits', header=True) actuator = read_fits(f'{cpism_refdata}/optics/actuator.fits') surface_aberration = read_fits( f'{cpism_refdata}/optics/initial_phase_aberration.fits') wavelength = 625e-9 # m pupil_diameter = 2 # m focal_length = pupil_diameter * 83 pupil_grid = make_pupil_grid(apm.shape[0], apm.shape[0] * apm_header['PHRATE']) aperture = make_circular_aperture(pupil_diameter)(pupil_grid) aperture = aperture * Field(apm.flatten(), pupil_grid) emccd_pixel_size = 13e-6 # m arcsec2rad = np.radians(1 / 3600) emccd_pixel_scale = emccd_pixel_size / \ (arcsec2rad * focal_length) # arcsec / pixel spatial_resolution = focal_length * wavelength / \ pupil_diameter # meter per airy disk q = spatial_resolution / emccd_pixel_size # pixels per airy disk num_airy = 512 / q # airy disk per frame (2 * 512 = 1024 pix) focal_full_frame = make_focal_grid( q, num_airy, spatial_resolution=spatial_resolution) prop_full_frame = FraunhoferPropagator( pupil_grid, focal_full_frame, focal_length) num_airy = 128 / q # make a small frame for the planets focal_sub_frame = make_focal_grid( q, num_airy, spatial_resolution=spatial_resolution) prop_sub_frame = FraunhoferPropagator( pupil_grid, focal_sub_frame, focal_length) num_actuators_across = 32 # dm spacing is little smaller than pupil actuator_spacing = 0.95 / 32 * pupil_diameter influence_functions = make_xinetics_influence_functions( pupil_grid, num_actuators_across, actuator_spacing) deformable_mirror = DeformableMirror(influence_functions) aberration = SurfaceApodizer( surface_sag=surface_aberration.flatten(), refractive_index=-1) # arbitrary distance for the aberration to propagate aberration_distance = 80 * focal_length aberration = SurfaceAberrationAtDistance(aberration, aberration_distance) def simulate_psf(error_value, band, spectrum, nsample=5, cstar=True, aber_phase=None): filter = filter_throughput(band) wave = filter.wave throughput = filter.throughput min_wave = wave[0] max_wave = wave[-1] sed = [] sed_center_wavelength = [] for i_wave in range(nsample): d_wave = (max_wave - min_wave) / nsample wave0 = min_wave + i_wave * d_wave wave1 = min_wave + (i_wave + 1) * d_wave sed_center_wavelength.append((wave0 + wave1) / 2 * 1e-10) i_throughput = throughput.copy() i_throughput[(wave > wave1) | (wave < wave0)] = 0 i_band = S.ArrayBandpass(wave, i_throughput, waveunits='angstrom') i_sed = (spectrum * i_band).integrate() sed.append(i_sed) error = np.random.normal(0, error_value*1e-9, actuator.shape) imgs = [] deformable_mirror.actuators = actuator + error prop = prop_full_frame if not cstar: prop = prop_sub_frame for i_sample in range(nsample): wf = Wavefront(aperture, sed_center_wavelength[i_sample]) wf = aberration(wf) if aber_phase is not None: other_error = SurfaceApodizer( surface_sag=aber_phase.flatten(), refractive_index=-1) wf = other_error(wf) img = prop(deformable_mirror(wf)).intensity.shaped imgs.append(img / img.sum() * sed[i_sample]) return np.array(imgs).sum(axis=0) Loading
CpicImgSim/psf_simulation.py 0 → 100644 +106 −0 Original line number Diff line number Diff line import numpy as np from astropy.io import fits from hcipy import Field, Wavefront, DeformableMirror, FraunhoferPropagator from hcipy import SurfaceApodizer, SurfaceAberrationAtDistance from hcipy import make_pupil_grid, make_circular_aperture, make_focal_grid from hcipy import make_xinetics_influence_functions from hcipy import read_fits from .config import cpism_refdata, S from .optics import filter_throughput # initial psf simulation apm, apm_header = fits.getdata( f'{cpism_refdata}/optics/apm.fits', header=True) actuator = read_fits(f'{cpism_refdata}/optics/actuator.fits') surface_aberration = read_fits( f'{cpism_refdata}/optics/initial_phase_aberration.fits') wavelength = 625e-9 # m pupil_diameter = 2 # m focal_length = pupil_diameter * 83 pupil_grid = make_pupil_grid(apm.shape[0], apm.shape[0] * apm_header['PHRATE']) aperture = make_circular_aperture(pupil_diameter)(pupil_grid) aperture = aperture * Field(apm.flatten(), pupil_grid) emccd_pixel_size = 13e-6 # m arcsec2rad = np.radians(1 / 3600) emccd_pixel_scale = emccd_pixel_size / \ (arcsec2rad * focal_length) # arcsec / pixel spatial_resolution = focal_length * wavelength / \ pupil_diameter # meter per airy disk q = spatial_resolution / emccd_pixel_size # pixels per airy disk num_airy = 512 / q # airy disk per frame (2 * 512 = 1024 pix) focal_full_frame = make_focal_grid( q, num_airy, spatial_resolution=spatial_resolution) prop_full_frame = FraunhoferPropagator( pupil_grid, focal_full_frame, focal_length) num_airy = 128 / q # make a small frame for the planets focal_sub_frame = make_focal_grid( q, num_airy, spatial_resolution=spatial_resolution) prop_sub_frame = FraunhoferPropagator( pupil_grid, focal_sub_frame, focal_length) num_actuators_across = 32 # dm spacing is little smaller than pupil actuator_spacing = 0.95 / 32 * pupil_diameter influence_functions = make_xinetics_influence_functions( pupil_grid, num_actuators_across, actuator_spacing) deformable_mirror = DeformableMirror(influence_functions) aberration = SurfaceApodizer( surface_sag=surface_aberration.flatten(), refractive_index=-1) # arbitrary distance for the aberration to propagate aberration_distance = 80 * focal_length aberration = SurfaceAberrationAtDistance(aberration, aberration_distance) def simulate_psf(error_value, band, spectrum, nsample=5, cstar=True, aber_phase=None): filter = filter_throughput(band) wave = filter.wave throughput = filter.throughput min_wave = wave[0] max_wave = wave[-1] sed = [] sed_center_wavelength = [] for i_wave in range(nsample): d_wave = (max_wave - min_wave) / nsample wave0 = min_wave + i_wave * d_wave wave1 = min_wave + (i_wave + 1) * d_wave sed_center_wavelength.append((wave0 + wave1) / 2 * 1e-10) i_throughput = throughput.copy() i_throughput[(wave > wave1) | (wave < wave0)] = 0 i_band = S.ArrayBandpass(wave, i_throughput, waveunits='angstrom') i_sed = (spectrum * i_band).integrate() sed.append(i_sed) error = np.random.normal(0, error_value*1e-9, actuator.shape) imgs = [] deformable_mirror.actuators = actuator + error prop = prop_full_frame if not cstar: prop = prop_sub_frame for i_sample in range(nsample): wf = Wavefront(aperture, sed_center_wavelength[i_sample]) wf = aberration(wf) if aber_phase is not None: other_error = SurfaceApodizer( surface_sag=aber_phase.flatten(), refractive_index=-1) wf = other_error(wf) img = prop(deformable_mirror(wf)).intensity.shaped imgs.append(img / img.sum() * sed[i_sample]) return np.array(imgs).sum(axis=0)