def wavefront_abberations(wfo, npupil, atm_screen, NCPA, Island_Piston, TILT=[0, 0], Debug='False', Debug_print='False', prefix='test'): lamda = proper.prop_get_wavelength(wfo) if (isinstance(atm_screen, (list, tuple, np.ndarray)) == True) and ( atm_screen.ndim >= 2): # when the atmosphere is present atmosphere(wfo, npupil, atm_screen, Debug_print, Debug) if (isinstance(NCPA, (list, tuple, np.ndarray)) == True) and (NCPA.ndim >= 2): # when the atmosphere is present NCPA_application(wfo, npupil, NCPA, Debug_print, Debug) if (all(v == 0 for v in Island_Piston) == False): # when the piston is present island_effect_piston(wfo, npupil, Island_Piston, Debug_print, Debug) if (TILT.any != 0.): # when tip/tilt if (Debug_print == True): print("TILT: ", TILT) print("lamda: ", lamda) tiptilt = (np.multiply( TILT, lamda )) / 4 # translate the tip/tilt from lambda/D into RMS phase errors proper.prop_zernikes(wfo, [2, 3], tiptilt) # 2-->xtilt, 3-->ytilt return wfo
def atmosphere(wf, npupil, atm_screen, Debug_print, Debug): n = int(proper.prop_get_gridsize(wf)) lamda=proper.prop_get_wavelength(wf) #save the wavelength value [m] into lamda screen = atm_screen # read the phase screen if (Debug_print == True): print ("screen", screen.shape) screen_pixels = (screen.shape)[0] # size of the phase screen scaling_factor_screen = float(npupil)/float(screen_pixels) # scaling factor the phase screen to the simulation pupil size if (Debug_print == True): print ("scaling_factor_screen: ", scaling_factor_screen) screen_scale = cv2.resize(screen.astype(np.float32), (0,0), fx=scaling_factor_screen, fy=scaling_factor_screen, interpolation=cv2.INTER_LINEAR) # scale the the phase screen to the simulation pupil size if (Debug_print == True): print ("screen_resample", screen_scale.shape) screen_large = np.zeros((n,n)) # define an array of n-0s, where to insert the screen if (Debug_print == True): print("n: ", n) print("npupil: ", npupil) screen_large[int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2),int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2)] =screen_scale # insert the scaled screen into the 0s grid lambda2=lamda/(1e-6) # need to use lambda in microns screen_atm = np.exp(1j*screen_large/lambda2*2*math.pi) proper.prop_multiply(wf, screen_atm) # multiply the atm screen to teh wavefront return wf
def NCPA_application(wf, npupil, NCPA, path, Debug_print, Debug): n = int(proper.prop_get_gridsize(wf)) lamda=proper.prop_get_wavelength(wf) #save the wavelength value [m] into lamda if (Debug_print == True): print ("NCPA", NCPA.shape) NCPA_pixels = (NCPA.shape)[0] # size of the phase screen scaling_factor_NCPA = float(npupil)/float(NCPA_pixels) # scaling factor the phase screen to the simulation pupil size if (Debug_print == True): print ("scaling_factor_NCPA: ", scaling_factor_NCPA) NCPA_scale = cv2.resize(NCPA.astype(np.float32), (0,0), fx=scaling_factor_NCPA, fy=scaling_factor_NCPA, interpolation=cv2.INTER_LINEAR) # scale the the phase screen to the simulation pupil size if (Debug_print == True): print ("NCPA_resample", NCPA_scale.shape) NCPA_large = np.zeros((n,n)) # define an array of n-0s, where to insert the screen if (Debug_print == True): print("n: ", n) print("npupil: ", npupil) NCPA_large[int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2),int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2)] =NCPA_scale # insert the scaled screen into the 0s grid if (Debug == 1): fits.writeto(path + 'NCPA_large.fits', NCPA_large, overwrite=True) # fits file for the screen lambda2=lamda/(1e-6) # need to use lambda in microns screen_atm = np.exp(1j*NCPA_large/lambda2*2*math.pi) proper.prop_multiply(wf, screen_atm) # multiply the atm screen to teh wavefront #rms_error = NCPA[0]#30nm-- RMS wavefront error in meters #c_freq = NCPA[1]# 5 ;-- correlation frequency (cycles/meter) #high_power = NCPA[2]#3.0 ;-- high frequency falloff (r^-high_power) #RANDOM_MAP = readfits('RANDOM_MAP.fits') #proper.prop_psd_errormap_mod( wf, rms_error, c_freq, high_power, RMS=True) return
def coronagraph(wfo, f_lens, occulter_type, diam): proper.prop_lens(wfo, f_lens, "coronagraph imaging lens") proper.prop_propagate(wfo, f_lens, "occulter") # occulter sizes are specified here in units of lambda/diameter; # convert lambda/diam to radians then to meters lamda = proper.prop_get_wavelength(wfo) occrad = 4. # occulter radius in lam/D occrad_rad = occrad * lamda / diam # occulter radius in radians dx_m = proper.prop_get_sampling(wfo) dx_rad = proper.prop_get_sampling_radians(wfo) occrad_m = occrad_rad * dx_m / dx_rad # occulter radius in meters plt.figure(figsize=(12,8)) if occulter_type == "GAUSSIAN": r = proper.prop_radius(wfo) h = np.sqrt(-0.5 * occrad_m**2 / np.log(1 - np.sqrt(0.5))) gauss_spot = 1 - np.exp(-0.5 * (r/h)**2) proper.prop_multiply(wfo, gauss_spot) plt.suptitle("Gaussian spot", fontsize = 18) elif occulter_type == "SOLID": proper.prop_circular_obscuration(wfo, occrad_m) plt.suptitle("Solid spot", fontsize = 18) elif occulter_type == "8TH_ORDER": proper.prop_8th_order_mask(wfo, occrad, CIRCULAR = True) plt.suptitle("8th order band limited spot", fontsize = 18) # After occulter plt.subplot(1,2,1) plt.imshow(np.sqrt(proper.prop_get_amplitude(wfo)), origin = "lower", cmap = plt.cm.gray) plt.text(200, 10, "After Occulter", color = "w") proper.prop_propagate(wfo, f_lens, "pupil reimaging lens") proper.prop_lens(wfo, f_lens, "pupil reimaging lens") proper.prop_propagate(wfo, 2*f_lens, "lyot stop") plt.subplot(1,2,2) plt.imshow(proper.prop_get_amplitude(wfo)**0.2, origin = "lower", cmap = plt.cm.gray) plt.text(200, 10, "Before Lyot Stop", color = "w") plt.show() if occulter_type == "GAUSSIAN": proper.prop_circular_aperture(wfo, 0.25, NORM = True) elif occulter_type == "SOLID": proper.prop_circular_aperture(wfo, 0.84, NORM = True) elif occulter_type == "8TH_ORDER": proper.prop_circular_aperture(wfo, 0.50, NORM = True) proper.prop_propagate(wfo, f_lens, "reimaging lens") proper.prop_lens(wfo, f_lens, "reimaging lens") proper.prop_propagate(wfo, f_lens, "final focus") return
def quick_ao(wfo, iwf, f_lens, beam_ratio, iter, CPA_map): nact = tp.ao_act # 49 # number of DM actuators along one axis nact_across_pupil = nact - 2 # 47 # number of DM actuators across pupil dm_xc = (nact / 2) - 0.5 dm_yc = (nact / 2) - 0.5 d_beam = 2 * proper.prop_get_beamradius(wfo) # beam diameter act_spacing = d_beam / nact_across_pupil # actuator spacing # map_spacing = proper.prop_get_sampling(wfo) # map sampling # dm_map = np.zeros((65, 65)) # quicklook_im(CPA_map, logAmp=False, vmin=-3.14, vmax=3.14) dm_map = CPA_map[tp.grid_size / 2 - (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 + (beam_ratio * tp.grid_size / 2) + 1, tp.grid_size / 2 - (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 + (beam_ratio * tp.grid_size / 2) + 1] # quicklook_im(dm_map, logAmp=False) f = interpolate.interp2d(range(dm_map.shape[0]), range(dm_map.shape[0]), dm_map) dm_map = f(np.linspace(0, dm_map.shape[0], nact), np.linspace(0, dm_map.shape[0], nact)) # dm_map = proper.prop_magnify(CPA_map, map_spacing / act_spacing, nact) # quicklook_im(CPA_map, logAmp=False) # quicklook_im(dm_map, logAmp=False) # quicklook_wf(wfo) if tp.piston_error: # dprint('doing this') mean_dm_map = np.mean(np.abs(dm_map)) # var = mean_dm_map/50. var = 0.001 # 1e-11 dm_map = dm_map + np.random.normal(0, var, (dm_map.shape[0], dm_map.shape[1])) dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (4 * np.pi ) # <--- here # dmap = proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, N_ACT_ACROSS_PUPIL=nact, FIT=True) # <-- here dmap = proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, act_spacing, FIT=True) # <-- here # quicklook_wf(wfo) # I = np.real(wfo.wfarr) # Q = np.imag(wfo.wfarr) # I = proper.prop_shift_center(I) # Q = proper.prop_shift_center(Q) # # anomaly = int(np.round(beam_ratio*tp.grid_size/2 + tp.grid_size/2)) # # dprint((anomaly)) # Q[anomaly] = 0 # 89 # Q[:, anomaly] = 0 # I[anomaly] = 0 # I[:, anomaly] = 0 # I = proper.prop_shift_center(I) # Q = proper.prop_shift_center(Q) # wfo.wfarr = I + 1j * Q return
def island_effect_piston(wf, npupil, Island_Piston, path, Debug_print, Debug): n = int(proper.prop_get_gridsize(wf)) lamda=proper.prop_get_wavelength(wf) #save the wavelength value [m] into lamda PACKAGE_PATH = os.path.abspath(os.path.join(__file__, os.pardir)) petal1 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal1_243px.fits') petal2 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal2_243px.fits') petal3 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal3_243px.fits') petal4 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal4_243px.fits') petal5 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal5_243px.fits') petal6 = fits.getdata(PACKAGE_PATH+'/1024_pixelsize5mas_petal6_243px.fits') piston_petal1 = Island_Piston[0]*petal1 piston_petal2 = Island_Piston[1]*petal2 piston_petal3 = Island_Piston[2]*petal3 piston_petal4 = Island_Piston[3]*petal4 piston_petal5 = Island_Piston[4]*petal5 piston_petal6 = Island_Piston[5]*petal6 piston = piston_petal1 + piston_petal2 + piston_petal3 + piston_petal4 + piston_petal5 + piston_petal6 piston_pixels = (piston.shape)[0]## fits file size scaling_factor = float(npupil)/float(piston_pixels) ## scaling factor between the fits file size and the pupil size of the simulation if (Debug_print==True): print ("scaling_factor: ", scaling_factor) piston_scale = cv2.resize(piston.astype(np.float32), (0,0), fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_LINEAR) # scale the pupil to the pupil size of the simualtions if (Debug_print==True): print ("piston_resample", piston_scale.shape) piston_large = np.zeros((n,n)) # define an array of n-0s, where to insert the pupuil if (Debug_print==True): print("n: ", n) print("npupil: ", npupil) piston_large[int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2),int(n/2)+1-int(npupil/2)-1:int(n/2)+1+int(npupil/2)] =piston_scale # insert the scaled pupil into the 0s grid if (Debug == 1): fits.writeto(path+'piston_phase.fits', piston_large, overwrite=True) # fits file for the screen lambda2=lamda/(1e-6) # need to use lambda in microns piston_phase = np.exp(1j*piston_large/lambda2*2*math.pi) proper.prop_multiply(wf, piston_phase) # multiply the atm screen to teh wavefront return
def set_size(self, wf, size_in_lambda_d=0, size_in_m=0): """ sets size of occulter in m, depending on if input is in units of lambda/D or in m :param wf: 2D wavefront :param size_in_lambda_d: desired occulter size in units of lambda/D :param size_in_m: desired occulter size in m :return: occulter size in m """ lamda = proper.prop_get_wavelength(wf) dx_m = proper.prop_get_sampling(wf) dx_rad = proper.prop_get_sampling_radians(wf) if size_in_lambda_d is not 0: occrad_rad = size_in_lambda_d * lamda / tp.entrance_d # occulter radius in radians self.size = occrad_rad * dx_m / dx_rad # occulter radius in meters elif size_in_m is not 0: self.size = size_in_m else: raise ValueError('must set occulter size in either m or lambda/D units')
def polmap( wavefront, polfile, pupil_diam_pix, condition, MUF=1.0 ): n = proper.prop_get_gridsize( wavefront ) lambda_m = proper.prop_get_wavelength(wavefront) if condition <= 2: (amp, pha) = polab( polfile, lambda_m, pupil_diam_pix, condition ) elif condition == 5: (amp_m45_x, pha_m45_x) = polab( polfile, lambda_m, pupil_diam_pix, -1 ) (amp_p45_x, pha_p45_x) = polab( polfile, lambda_m, pupil_diam_pix, +1 ) amp = (amp_m45_x + amp_p45_x) / 2 pha = (pha_m45_x + pha_p45_x) / 2 elif condition == 6: (amp_m45_y, pha_m45_y) = polab( polfile, lambda_m, pupil_diam_pix, -2 ) (amp_p45_y, pha_p45_y) = polab( polfile, lambda_m, pupil_diam_pix, +2 ) amp = (amp_m45_y + amp_p45_y) / 2 pha = (pha_m45_y + pha_p45_y) / 2 elif condition == 10: (amp_m45_x, pha_m45_x) = polab( polfile, lambda_m, pupil_diam_pix, -1 ) (amp_p45_x, pha_p45_x) = polab( polfile, lambda_m, pupil_diam_pix, +1 ) (amp_m45_y, pha_m45_y) = polab( polfile, lambda_m, pupil_diam_pix, -2 ) (amp_p45_y, pha_p45_y) = polab( polfile, lambda_m, pupil_diam_pix, +2 ) amp = (amp_m45_x + amp_p45_x + amp_m45_y + amp_p45_y) / 4 pha = (pha_m45_x + pha_p45_x + pha_m45_y + pha_p45_y) / 4 else: raise Exception( 'POLMAP: unmatched condition' ) proper.prop_multiply( wavefront, trim(amp,n) ) proper.prop_add_phase( wavefront, trim(MUF*pha,n) ) amp = 0 phase = 0 amp_p45x = 0 amp_m45x = 0 amp_p45y = 0 amp_m45y = 0 pha_p45x = 0 pha_m45x = 0 pha_p45y = 0 pha_m45y = 0 return
def wavefront_abberations(wfo, conf,atm_screen, TILT): diam = conf['DIAM'] gridsize = conf['GRIDSIZE'] pixelsize = conf['PIXEL_SCALE'] wavelength = conf['WAVELENGTH'] lamda = proper.prop_get_wavelength(wfo) Debug = conf['DEBUG'] Debug_print = conf['DEBUG_PRINT'] Island_Piston = np.array(conf['ISLAND_PISTON']) # atm_screen = fits.getdata(input_dir + '/' + atm_screen) beam_ratio = pixelsize*4.85e-9/(wavelength/diam) npupil = np.ceil(gridsize*beam_ratio) # compute the pupil size --> has to be ODD (proper puts the center in the up right pixel next to the grid center) if npupil % 2 == 0: npupil = npupil + 1 if (isinstance(atm_screen, (list, tuple, np.ndarray)) == True) and (atm_screen.ndim >= 2): # when the atmosphere is present atmosphere(wfo, npupil, atm_screen, Debug_print, Debug) if (all(v == 0 for v in Island_Piston) == False): # when the piston is present island_effect_piston(wfo, npupil, Island_Piston, Debug_print, Debug) if conf['STATIC_NCPA'] == True: filename = conf['IMG_LM_SCAO'] phase_screen = fits.getdata(conf['INPUT_DIR'] + filename) phase_screen = np.nan_to_num(phase_screen) phase_screen *= 10**-9 # scale the wavelenth to nm static_ncpa(wfo, npupil, phase_screen) if (TILT.any != 0.): # when tip/tilt if (Debug_print==True): print("TILT: ", TILT) print("lamda: ", lamda) tiptilt = (np.multiply(TILT, lamda))/4 # translate the tip/tilt from lambda/D into RMS phase errors proper.prop_zernikes(wfo, [2,3], tiptilt) # 2-->xtilt, 3-->ytilt return wfo
def telescope( wavelength, gridsize, PASSVALUE={ 'prefix': 'prova', 'path': os.path.abspath(os.path.join(__file__, os.pardir)), 'charge': 0, 'CAL': 0, 'diam': 37., 'spiders_width': 0.60, 'spiders_angle': [0., 60., 120.], 'beam_ratio': 0.25, 'f_lens': 658.6, 'npupil': 243, 'r_obstr': 0.3, 'pupil_file': 0, 'phase_apodizer_file': 0, 'amplitude_apodizer_file': 0, 'TILT': [0., 0.], 'LS': False, 'RAVC': False, 'LS_phase_apodizer_file': 0, 'LS_amplitude_apodizer_file': 0, 'LS_parameters': [0.0, 0.0, 0.0], 'atm_screen': 0, 'missing_segments_number': 0, 'apodizer_misalignment': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 'LS_misalignment': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 'Island_Piston': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 'NCPA': 0, 'Debug_print': False, 'Debug': False }): ## call all the vues passed via passvalue prefix = PASSVALUE['prefix'] path = PASSVALUE['path'] charge = PASSVALUE['charge'] CAL = PASSVALUE['CAL'] diam = PASSVALUE['diam'] spiders_width = PASSVALUE['spiders_width'] spiders_angle = PASSVALUE['spiders_angle'] beam_ratio = PASSVALUE['beam_ratio'] f_lens = PASSVALUE['f_lens'] npupil = PASSVALUE['npupil'] r_obstr = PASSVALUE['r_obstr'] pupil_file = PASSVALUE['pupil_file'] phase_apodizer_file = PASSVALUE['phase_apodizer_file'] amplitude_apodizer_file = PASSVALUE['amplitude_apodizer_file'] TILT = PASSVALUE['TILT'] LS = PASSVALUE['LS'] RAVC = PASSVALUE['RAVC'] LS_phase_apodizer_file = PASSVALUE['LS_phase_apodizer_file'] LS_amplitude_apodizer_file = PASSVALUE['LS_amplitude_apodizer_file'] LS_parameters = PASSVALUE['LS_parameters'] atm_screen = PASSVALUE['atm_screen'] missing_segments_number = PASSVALUE['missing_segments_number'] apodizer_misalignment = PASSVALUE['apodizer_misalignment'] LS_misalignment = PASSVALUE['LS_misalignment'] Island_Piston = PASSVALUE['Island_Piston'] NCPA = PASSVALUE['NCPA'] Debug_print = PASSVALUE['Debug_print'] Debug = PASSVALUE['Debug'] TILT = np.array(TILT) apodizer_misalignment = np.array(apodizer_misalignment) LS_misalignment = np.array(LS_misalignment) Island_Piston = np.array(Island_Piston) ## call the size of the grid n = int(gridsize) wfo = proper.prop_begin(diam, wavelength, gridsize, beam_ratio) # define the simualtion pupil lamda = proper.prop_get_wavelength( wfo) #save the wavelength value [m] into lamda if (Debug_print == True): print("lambda: ", lamda) pupil(wfo, CAL, npupil, diam, r_obstr, spiders_width, spiders_angle, pupil_file, missing_segments_number, Debug, Debug_print) if (Debug == True): fits.writeto( path + prefix + '_pupil_pre_define.fits', proper.prop_get_amplitude(wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) proper.prop_define_entrance(wfo) #define the entrance wavefront #wfo.wfarr *= 1./np.amax(wfo._wfarr) # max(amplitude)=1 if (isinstance(atm_screen, (list, tuple, np.ndarray)) == True) and ( atm_screen.ndim >= 2): # when the atmosphere is present print('atmosphere') atmosphere(wfo, npupil, atm_screen, Debug_print, Debug) if (isinstance(NCPA, (list, tuple, np.ndarray)) == True) and (NCPA.ndim >= 2): # when the atmosphere is present NCPA_application(wfo, npupil, NCPA, path, Debug_print, Debug) if (RAVC == True) or (isinstance(phase_apodizer_file, (list, tuple, np.ndarray)) == True) or (isinstance(amplitude_apodizer_file, (list, tuple, np.ndarray)) == True): # when tha apodizer is present apodization(wfo, r_obstr, npupil, RAVC, phase_apodizer_file, amplitude_apodizer_file, apodizer_misalignment, Debug_print, Debug) if (all(v == 0 for v in Island_Piston) == False): # when the piston is present island_effect_piston(wfo, npupil, Island_Piston, path, Debug_print, Debug) if (TILT.any != 0.): # when tip/tilt if (Debug_print == True): print("TILT: ", TILT) print("lamda: ", lamda) tiptilt = (np.multiply( TILT, lamda )) / 4 # translate the tip/tilt from lambda/D into RMS phase errors proper.prop_zernikes(wfo, [2, 3], tiptilt) # 2-->xtilt, 3-->ytilt if (Debug == True): if CAL == 1: fits.writeto(path + prefix + '_pupil_amplitude_CAL1.fits', proper.prop_get_amplitude(wfo) [int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) fits.writeto( path + prefix + '_pupil_phase_CAL1.fits', proper.prop_get_phase(wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) else: fits.writeto( path + prefix + '_pupil_amplitude_CAL0_RA' + str(int(RAVC)) + '_charge' + str(charge) + '_ATM' + str( int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)) + '.fits', proper.prop_get_amplitude( wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) fits.writeto( path + prefix + '_pupil_phase_CAL0_RA' + str(int(RAVC)) + '_charge' + str(charge) + '_ATM' + str( int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)) + '.fits', proper.prop_get_phase(wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) proper.prop_propagate(wfo, f_lens, 'inizio') # propagate wavefront proper.prop_lens(wfo, f_lens, 'focusing lens vortex') # propagate through a lens proper.prop_propagate(wfo, f_lens, 'VC') # propagate wavefront vortex(wfo, CAL, charge, f_lens, path, Debug_print) if (Debug == True): if CAL == 1: fits.writeto(path + prefix + '_afterVortex_CAL1.fits', proper.prop_get_amplitude(wfo) [int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) fits.writeto( path + prefix + '_afterVortex_CAL1_phase.fits', proper.prop_get_phase(wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) else: print( 'ATM: ', str( int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True))) if ((((int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)))) == 1): print('atm_screen: ', atm_screen.shape) print( 'ATM: ', int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)) fits.writeto( path + prefix + '_afterVortex_CAL0_RA' + str(int(RAVC)) + '_charge' + str(charge) + '_ATM' + str( int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)) + '.fits', proper.prop_get_amplitude( wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) fits.writeto( path + prefix + '_afterVortex_phase_CAL0_RA' + str(int(RAVC)) + '_charge' + str(charge) + '_ATM' + str( int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)) + '.fits', proper.prop_get_phase(wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) proper.prop_propagate(wfo, f_lens, 'Lyot Collimetor') # propagate wavefront proper.prop_lens(wfo, f_lens, 'Lyot Collimetor') # propagate wavefront through a lens proper.prop_propagate(wfo, f_lens, 'Lyot Stop') # propagate wavefront if (Debug == True): if CAL == 1: fits.writeto(path + prefix + '_beforeLS_CAL1.fits', proper.prop_get_amplitude(wfo) [int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) else: fits.writeto( path + prefix + '_beforeLS_CAL0_charge' + str(charge) + '_ATM' + str( int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)) + '.fits', proper.prop_get_amplitude( wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) lyotstop(wfo, diam, r_obstr, npupil, RAVC, LS, LS_parameters, spiders_angle, LS_phase_apodizer_file, LS_amplitude_apodizer_file, LS_misalignment, path, Debug_print, Debug) if (Debug == True): if CAL == 1: fits.writeto(path + prefix + '_afterLS_CAL1.fits', proper.prop_get_amplitude(wfo) [int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) else: fits.writeto( path + prefix + '_afterLS_CAL0_charge' + str(charge) + '_LS' + str(int(LS)) + '_RA' + str(int(RAVC)) + '_ATM' + str( int( isinstance(atm_screen, (list, tuple, np.ndarray)) == True)) + '.fits', proper.prop_get_amplitude( wfo)[int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50), int(n / 2) - int(npupil / 2 + 50):int(n / 2) + int(npupil / 2 + 50)], overwrite=True) proper.prop_propagate(wfo, f_lens) # propagate wavefront proper.prop_lens(wfo, f_lens) # propagate wavefront through a lens proper.prop_propagate(wfo, f_lens) # propagate wavefront (wfo, sampling) = proper.prop_end( wfo, NOABS=True ) # conclude the simulation --> noabs= the wavefront array will be complex return (wfo, sampling) # return the wavefront
def quick_ao(wf, nact, WFS_map): """ calculate the offset map to send to the DM from the WFS map The main idea is to apply the DM only to the region of the wavefront that contains the beam. The phase map from the wfs saved the whole wavefront, so that must be cropped. During the wavefront initialization in wavefront.initialize_proper, the beam ratio set in sp.beam_ratio is scaled per wavelength (to achieve constant sampling sto create white light images), so the cropped value must also be scaled by wavelength. Note, beam ratio is scaled differently depending on if sp.focused_sys is True or not. See params-->sp.focused_sys and Proper manual pg 36 for more info. Then, we interpolate the cropped beam onto a grid of (n_actuators,n_actuators), such that the DM can apply a actuator height to each represented actuator, not a over or sub-sampled form. If the number of actuators is low compared to the number of samples on the beam, you should anti-alias the WFS map via a lowpass filter before interpolating. There is a discrepancy between the sampling of the wavefront at this location (the size you cropped) vs the size of the DM. proper.prop_dm handles this, so just plug in the n_actuator sized DM map with specified parameters, and assume that prop_dm handles the resampling correctly via the spacing or n_act_across_pupil flag. FYI the resampling is done via a c library you installed/compiled when installing proper. The WFS map is a map of real values in units of phase delay in radians. However, the AO map that gets passed to proper.prop_dm wants input in nm height of each actuator. Therefore, you need to convert the phase delay to a DM height. For the ideal AO, you would do this individually for each wavelength. However, for a 'real' AO system you do this for the median wavelength. You also need to account for a factor of 2, since the DM is modeled as a mirror so it travels the length of the phase delay twice. much of this code copied over from example from Proper manual on pg 94 :param wfo: wavefront object created by optics.Wavefronts() [n_wavelengths, n_objects] of tp.gridsize x tp.gridsize :param WFS_map: returned from quick_wfs (as of Aug 2019, its an idealized image) :return: ao_map: map of DM actuator command heights in units of m """ nact_across_pupil = nact - 2 # number of full DM actuators across pupil (oversizing DM extent) # Note: oversample by 2 actuators hardcoded here, check if this is appropriate ############################ # Creating AO Surface Map ############################ d_beam = 2 * proper.prop_get_beamradius(wf) # beam diameter act_spacing = d_beam / nact_across_pupil # actuator spacing [m] # map_spacing = proper.prop_get_sampling(wfo.wf_collection[iw,0]) ################################### # Cropping the Beam from WFS map ################################### # cropping here by beam_ratio rather than d_beam is valid since the beam size was initialized # using the scaled beam_ratios when the wfo was created # dprint(f"{WFS_map[0,0,0]}") ao_map = WFS_map[ sp.grid_size // 2 - np.int_(wf.beam_ratio * sp.grid_size // 2):sp.grid_size // 2 + np.int_(wf.beam_ratio * sp.grid_size // 2) + 1, sp.grid_size // 2 - np.int_(wf.beam_ratio * sp.grid_size // 2):sp.grid_size // 2 + np.int_(wf.beam_ratio * sp.grid_size // 2) + 1] ######################################################## # Interpolating the WFS map onto the actuator spacing # (tp.nact,tp.nact) ######################################################## # Lowpass Filter- prevents aliasing; uses Gaussian filter nyquist_dm = tp.ao_act / 2 * act_spacing # [m] sigma = [nyquist_dm / 2.355, nyquist_dm / 2.355] # assume we want sigma to be twice the HWHM ao_map = ndimage.gaussian_filter(ao_map, sigma=sigma, mode='nearest') f = interpolate.interp2d(range(ao_map.shape[0]), range(ao_map.shape[0]), ao_map, kind='cubic') ao_map = f(np.linspace(0, ao_map.shape[0], nact), np.linspace(0, ao_map.shape[0], nact)) # dm_map = proper.prop_magnify(dm_map, map_spacing / act_spacing, nact) ################################################ # Converting phase delay to DM actuator height ################################################ # Apply the inverse of the WFS image to the DM, so use -dm_map (dm_map is in phase units, divide by k=2pi/lambda) surf_height = proper.prop_get_wavelength(wf) / (4 * np.pi) # [m/rad] ao_map = -ao_map * surf_height # Converts DM map to units of [m] of actuator heights return ao_map
def occulter(self, wf): n = int(proper.prop_get_gridsize(wf)) ofst = 0 # no offset ramp_sign = 1 # sign of charge is positive ramp_oversamp = 11. # vortex is oversampled for a better discretization # f_lens = tp.f_lens #conf['F_LENS'] # diam = tp.diam#conf['DIAM'] charge = 2 #conf['CHARGE'] pixelsize = 5 #conf['PIXEL_SCALE'] Debug_print = False #conf['DEBUG_PRINT'] coron_temp = os.path.join(iop.testdir, 'coron_maps/') if not os.path.exists(coron_temp): os.mkdir(coron_temp) if charge != 0: wavelength = proper.prop_get_wavelength(wf) gridsize = proper.prop_get_gridsize(wf) beam_ratio = pixelsize * 4.85e-9 / (wavelength / tp.entrance_d) # dprint((wavelength,gridsize,beam_ratio)) calib = str(charge) + str('_') + str(int( beam_ratio * 100)) + str('_') + str(gridsize) my_file = str(coron_temp + 'zz_perf_' + calib + '_r.fits') if (os.path.isfile(my_file) == True): if (Debug_print == True): print("Charge ", charge) vvc = self.readfield( coron_temp, 'zz_vvc_' + calib) # read the theoretical vortex field vvc = proper.prop_shift_center(vvc) scale_psf = wf._wfarr[0, 0] psf_num = self.readfield(coron_temp, 'zz_psf_' + calib) # read the pre-vortex field psf0 = psf_num[0, 0] psf_num = psf_num / psf0 * scale_psf perf_num = self.readfield( coron_temp, 'zz_perf_' + calib) # read the perfect-result vortex field perf_num = perf_num / psf0 * scale_psf wf._wfarr = ( wf._wfarr - psf_num ) * vvc + perf_num # the wavefront takes into account the real pupil with the perfect-result vortex field else: # CAL==1: # create the vortex for a perfectly circular pupil if (Debug_print == True): dprint(f"Vortex Charge= {charge}") f_lens = 200.0 * tp.entrance_d wf1 = proper.prop_begin(tp.entrance_d, wavelength, gridsize, beam_ratio) proper.prop_circular_aperture(wf1, tp.entrance_d / 2) proper.prop_define_entrance(wf1) proper.prop_propagate(wf1, f_lens, 'inizio') # propagate wavefront proper.prop_lens( wf1, f_lens, 'focusing lens vortex') # propagate through a lens proper.prop_propagate(wf1, f_lens, 'VC') # propagate wavefront self.writefield(coron_temp, 'zz_psf_' + calib, wf1.wfarr) # write the pre-vortex field nramp = int(n * ramp_oversamp) # oversamp # create the vortex by creating a matrix (theta) representing the ramp (created by atan 2 gradually varying matrix, x and y) y1 = np.ones((nramp, ), dtype=np.int) y2 = np.arange(0, nramp, 1.) - (nramp / 2) - int(ramp_oversamp) / 2 y = np.outer(y2, y1) x = np.transpose(y) theta = np.arctan2(y, x) x = 0 y = 0 vvc_tmp = np.exp(1j * (ofst + ramp_sign * charge * theta)) theta = 0 vvc_real_resampled = cv2.resize( vvc_tmp.real, (0, 0), fx=1 / ramp_oversamp, fy=1 / ramp_oversamp, interpolation=cv2.INTER_LINEAR ) # scale the pupil to the pupil size of the simualtions vvc_imag_resampled = cv2.resize( vvc_tmp.imag, (0, 0), fx=1 / ramp_oversamp, fy=1 / ramp_oversamp, interpolation=cv2.INTER_LINEAR ) # scale the pupil to the pupil size of the simualtions vvc = np.array(vvc_real_resampled, dtype=complex) vvc.imag = vvc_imag_resampled vvcphase = np.arctan2(vvc.imag, vvc.real) # create the vortex phase vvc_complex = np.array(np.zeros((n, n)), dtype=complex) vvc_complex.imag = vvcphase vvc = np.exp(vvc_complex) vvc_tmp = 0. self.writefield(coron_temp, 'zz_vvc_' + calib, vvc) # write the theoretical vortex field proper.prop_multiply(wf1, vvc) proper.prop_propagate(wf1, f_lens, 'OAP2') proper.prop_lens(wf1, f_lens) proper.prop_propagate(wf1, f_lens, 'forward to Lyot Stop') proper.prop_circular_obscuration( wf1, 1., NORM=True) # null the amplitude iside the Lyot Stop proper.prop_propagate(wf1, -f_lens) # back-propagation proper.prop_lens(wf1, -f_lens) proper.prop_propagate(wf1, -f_lens) self.writefield( coron_temp, 'zz_perf_' + calib, wf1.wfarr) # write the perfect-result vortex field vvc = self.readfield(coron_temp, 'zz_vvc_' + calib) vvc = proper.prop_shift_center(vvc) scale_psf = wf._wfarr[0, 0] psf_num = self.readfield(coron_temp, 'zz_psf_' + calib) # read the pre-vortex field psf0 = psf_num[0, 0] psf_num = psf_num / psf0 * scale_psf perf_num = self.readfield( coron_temp, 'zz_perf_' + calib) # read the perfect-result vortex field perf_num = perf_num / psf0 * scale_psf wf._wfarr = ( wf._wfarr - psf_num ) * vvc + perf_num # the wavefront takes into account the real pupil with the perfect-result vortex field return wf
def vortex(wfo, charge, f_lens, diam, pixelsize, Debug_print=False): n = int(proper.prop_get_gridsize(wfo)) ofst = 0 # no offset ramp_sign = 1 #sign of charge is positive ramp_oversamp = 11. # vortex is oversampled for a better discretization if charge != 0: wavelength = proper.prop_get_wavelength(wfo) gridsize = proper.prop_get_gridsize(wfo) beam_ratio = pixelsize * 4.85e-9 / (wavelength / diam) calib = str(charge) + str('_') + str(int( beam_ratio * 100)) + str('_') + str(gridsize) my_file = str(tmp_dir + 'zz_perf_' + calib + '_r.fits') proper.prop_propagate(wfo, f_lens, 'inizio') # propagate wavefront proper.prop_lens(wfo, f_lens, 'focusing lens vortex') # propagate through a lens proper.prop_propagate(wfo, f_lens, 'VC') # propagate wavefront if (os.path.isfile(my_file) == True): if (Debug_print == True): print("Charge ", charge) vvc = readfield(tmp_dir, 'zz_vvc_' + calib) # read the theoretical vortex field vvc = proper.prop_shift_center(vvc) scale_psf = wfo._wfarr[0, 0] psf_num = readfield(tmp_dir, 'zz_psf_' + calib) # read the pre-vortex field psf0 = psf_num[0, 0] psf_num = psf_num / psf0 * scale_psf perf_num = readfield(tmp_dir, 'zz_perf_' + calib) # read the perfect-result vortex field perf_num = perf_num / psf0 * scale_psf wfo._wfarr = ( wfo._wfarr - psf_num ) * vvc + perf_num # the wavefront takes into account the real pupil with the perfect-result vortex field else: # CAL==1: # create the vortex for a perfectly circular pupil if (Debug_print == True): print("Charge ", charge) wfo1 = proper.prop_begin(diam, wavelength, gridsize, beam_ratio) proper.prop_circular_aperture(wfo1, diam / 2) proper.prop_define_entrance(wfo1) proper.prop_propagate(wfo1, f_lens, 'inizio') # propagate wavefront proper.prop_lens( wfo1, f_lens, 'focusing lens vortex') # propagate through a lens proper.prop_propagate(wfo1, f_lens, 'VC') # propagate wavefront writefield(tmp_dir, 'zz_psf_' + calib, wfo1.wfarr) # write the pre-vortex field nramp = int(n * ramp_oversamp) #oversamp # create the vortex by creating a matrix (theta) representing the ramp (created by atan 2 gradually varying matrix, x and y) y1 = np.ones((nramp, ), dtype=np.int) y2 = np.arange(0, nramp, 1.) - (nramp / 2) - int(ramp_oversamp) / 2 y = np.outer(y2, y1) x = np.transpose(y) theta = np.arctan2(y, x) x = 0 y = 0 vvc_tmp = np.exp(1j * (ofst + ramp_sign * charge * theta)) theta = 0 vvc_real_resampled = cv2.resize( vvc_tmp.real, (0, 0), fx=1 / ramp_oversamp, fy=1 / ramp_oversamp, interpolation=cv2.INTER_LINEAR ) # scale the pupil to the pupil size of the simualtions vvc_imag_resampled = cv2.resize( vvc_tmp.imag, (0, 0), fx=1 / ramp_oversamp, fy=1 / ramp_oversamp, interpolation=cv2.INTER_LINEAR ) # scale the pupil to the pupil size of the simualtions vvc = np.array(vvc_real_resampled, dtype=complex) vvc.imag = vvc_imag_resampled vvcphase = np.arctan2(vvc.imag, vvc.real) # create the vortex phase vvc_complex = np.array(np.zeros((n, n)), dtype=complex) vvc_complex.imag = vvcphase vvc = np.exp(vvc_complex) vvc_tmp = 0. writefield(tmp_dir, 'zz_vvc_' + calib, vvc) # write the theoretical vortex field proper.prop_multiply(wfo1, vvc) proper.prop_propagate(wfo1, f_lens, 'OAP2') proper.prop_lens(wfo1, f_lens) proper.prop_propagate(wfo1, f_lens, 'forward to Lyot Stop') proper.prop_circular_obscuration( wfo1, 1., NORM=True) # null the amplitude iside the Lyot Stop proper.prop_propagate(wfo1, -f_lens) # back-propagation proper.prop_lens(wfo1, -f_lens) proper.prop_propagate(wfo1, -f_lens) writefield(tmp_dir, 'zz_perf_' + calib, wfo1.wfarr) # write the perfect-result vortex field vvc = readfield(tmp_dir, 'zz_vvc_' + calib) vvc = proper.prop_shift_center(vvc) scale_psf = wfo._wfarr[0, 0] psf_num = readfield(tmp_dir, 'zz_psf_' + calib) # read the pre-vortex field psf0 = psf_num[0, 0] psf_num = psf_num / psf0 * scale_psf perf_num = readfield(tmp_dir, 'zz_perf_' + calib) # read the perfect-result vortex field perf_num = perf_num / psf0 * scale_psf wfo._wfarr = ( wfo._wfarr - psf_num ) * vvc + perf_num # the wavefront takes into account the real pupil with the perfect-result vortex field proper.prop_propagate(wfo, f_lens, "propagate to pupil reimaging lens") proper.prop_lens(wfo, f_lens, "apply pupil reimaging lens") proper.prop_propagate(wfo, f_lens, "lyot stop") return wfo
def adaptive_optics(wfo, iwf, iw, f_lens, beam_ratio, iter): # print 'Including Adaptive Optics' # PSF = proper.prop_shift_center(np.abs(wfo.wfarr)**2) # quicklook_im(obj_map, logAmp=False) # code to distort measured phase map goes here.... # print 'add code to distort phase measurment' nact = tp.ao_act #49 # number of DM actuators along one axis nact_across_pupil = nact - 2 #/1.075#nact #47 # number of DM actuators across pupil dm_xc = (nact / 2) - 0.5 #-1#0.5#- 0.5 dm_yc = (nact / 2) - 0.5 #-1#0.5#- 0.5 d_beam = 2 * proper.prop_get_beamradius(wfo) # beam diameter # dprint((d_beam, d_beam/nact_across_pupil)) act_spacing = d_beam / (nact_across_pupil) # actuator spacing map_spacing = proper.prop_get_sampling(wfo) # map sampling # have passed through focus, so pupil has rotated 180 deg; # need to rotate error map (also need to shift due to the way # the rotate() function operates to recenter map) # obj_map = np.roll(np.roll(np.rot90(obj_map, 2), 1, 0), 1, 1) # obj_map = np.roll(obj_map, 1, -1) # quicklook_im(obj_map[45:83,45:83], logAmp=False, show=False) # plt.figure() # plt.plot(range(44, 84), obj_map[64, 44:84]) # print map_spacing # interpolate map to match number of DM actuators # print map_spacing/act_spacing # print 'Interpolation boundary uncertainty is likely because of beam ratio causing a non-integer' # print '128*0.3 ~ 38 so thats what is being used for now. Needs some T.L.C.' # true_width = tp.grid_size*beam_ratio # width = int(np.ceil(true_width)) # # width = int(np.ceil(tp.grid_size*beam_ratio)) # if width%2 != 0: # width += 1 # exten = width/true_width # print exten # mid = int(tp.grid_size/2.) # lower = int(mid-width/2.) # upper = int(mid+width/2.) # print width, mid, lower, upper # # # # f= interpolate.interp2d(range(width+1), range(width+1), obj_map[lower:upper, lower:upper]) # # dm_map = f(np.linspace(0,width+1,nact),np.linspace(0,width+1,nact)) # # import skimage.transform # dm_map = skimage.transform.resize(obj_map[lower:upper, lower:upper], (nact,nact)) # print map_spacing, act_spacing, map_spacing/act_spacing try: with open(iop.CPA_meas, 'rb') as handle: CPA_maps, iters = pickle.load(handle) except EOFError: print 'CPA file not ready?' import time time.sleep(10) with open(iop.CPA_meas, 'rb') as handle: CPA_maps, iters = pickle.load(handle) # loop_frames(CPA_maps, logAmp=False) if iwf[:9] == 'companion': CPA_map = CPA_maps[1, iw] else: CPA_map = CPA_maps[0, iw] # loop_frames(CPA_maps, logAmp=False) # quicklook_im(CPA_map, logAmp=False) # dprint((map_spacing, act_spacing, map_spacing/act_spacing)) # dm_map = proper.prop_magnify(CPA_map, map_spacing/act_spacing, nact) dm_map = CPA_map[tp.grid_size / 2 - (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 + (beam_ratio * tp.grid_size / 2) + 1, tp.grid_size / 2 - (beam_ratio * tp.grid_size / 2):tp.grid_size / 2 + (beam_ratio * tp.grid_size / 2) + 1] f = interpolate.interp2d(range(dm_map.shape[0]), range(dm_map.shape[0]), dm_map) dm_map = f(np.linspace(0, dm_map.shape[0], nact), np.linspace(0, dm_map.shape[0], nact)) # quicklook_im(dm_map, logAmp=False, show=True) dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (4 * np.pi ) #<--- here # dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (2 * np.pi) # dm_map = np.zeros((65,65)) # quicklook_im(dm_map, logAmp=False, show=True, colormap='jet') # if tp.piston_error: # mean_dm_map = np.mean(np.abs(dm_map)) # var = mean_dm_map/200.#40. # print var # # var = 0.001#1e-11 # if var != 0.0: # dm_map = dm_map + np.random.normal(0, var, (dm_map.shape[0], dm_map.shape[1])) # quicklook_im(dm_map, logAmp=False, show=True, colormap='jet') # plt.figure() # quicklook_wf(wfo) # plt.plot(np.linspace(44, 84, nact),dm_map[16]) # plt.figure() # quicklook_im( obj_map[lower:upper, lower:upper], logAmp=False, show=True) # act_spacing /= 0.625 # print act_spacing, proper.prop_get_beamradius(wfo) # Need to put on opposite pattern; convert wavefront error to surface height # plt.plot(range(44,84), proper.prop_get_phase(wfo)[64, 44:84]) # proper.prop_add_phase(wfo, waffle) # quicklook_im(dm_map) if tp.active_null: with open(iop.NCPA_meas, 'rb') as handle: _, null_map, _ = pickle.load(handle) # dprint('null_map') # quicklook_im(null_map, logAmp=False) # dm_NCPA = -proper.prop_magnify(NCPA_map, map_spacing / act_spacing, nact) dm_NCPA = null_map * proper.prop_get_wavelength(wfo) / (4 * np.pi) # quicklook_im(dm_map, logAmp=False) dm_map += dm_NCPA # quicklook_im(dm_map, logAmp=False, show=True, colormap ='jet') # dm_map /= 2 # if tp.speckle_kill: # with open(iop.NCPA_meas, 'rb') as handle: # Imaps, NCPA_map,_ = pickle.load(handle) # quicklook_im(NCPA_map, logAmp=False) # loop_frames(Imaps+1e-9, logAmp=True) # with open(iop.NCPA_meas, 'rb') as handle: # _, NCPA_map,_ = pickle.load(handle) # quicklook_im(NCPA_map, logAmp=False) # # dm_NCPA = -proper.prop_magnify(NCPA_map, map_spacing / act_spacing, nact) # dm_NCPA = dm_NCPA*proper.prop_get_wavelength(wfo)/(4*np.pi) # # # quicklook_im(dm_map, logAmp=False) # dm_map = dm_NCPA if tp.active_modulate and iter >= 8: # import dm_functions as DM # # speck.generate_flatmap(phase) # s_amp = DM.amplitudemodel(0.05, 30, c=1.6) # tp.null_ao_act = tp.ao_act # xloc, yloc = 4, 0 # # rotate_angle = iter%30 * 360/30 # # rotate_angle = np.pi * rotate_angle / 180. # # rot_matrix = [[np.cos(rotate_angle), -np.sin(rotate_angle)], [np.sin(rotate_angle), np.cos(rotate_angle)]] # # xloc, yloc = np.matmul(rot_matrix, [xloc, yloc]) # # phase = iter % 10 * 2 * np.pi / 10. # s_amp = iter % 5 * s_amp/ 5. # print xloc, yloc, phase # waffle = DM.make_speckle_kxy(xloc, yloc, s_amp, phase) / 1e6 # waffle += DM.make_speckle_kxy(yloc, xloc, s_amp, -phase) / 1e6 # waffle += DM.make_speckle_kxy(0.71 * xloc, 0.71 * xloc, s_amp, -phase) / 1e6 # waffle += DM.make_speckle_kxy(0.71 * xloc, -0.71 * xloc, s_amp, -phase) / 1e6 # waffle /= 4 # # quicklook_im(waffle, logAmp=False) # # print dm_map.shape # # print waffle.shape # # dmap =proper.prop_dm(wfo, waffle, dm_xc, dm_yc, N_ACT_ACROSS_PUPIL=nact, FIT = True) # dm_map = -dm_map * proper.prop_get_wavelength(wfo) / (4 * np.pi * 5) * (iter % 10 - 5) print 1 / 5. * (iter % 10 - 5) dm_map = dm_map / 5. * (iter % 10 - 5) # dmap = proper.prop_dm(wfo, pattern, dm_xc, dm_yc, # N_ACT_ACROSS_PUPIL=nact, FIT=True) # quicklook_wf(wfo) # quicklook_wf(wfo) # dmap =proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, N_ACT_ACROSS_PUPIL=nact, FIT = True) #<-- here dmap = proper.prop_dm(wfo, dm_map, dm_xc, dm_yc, act_spacing, FIT=True) #<-- here # quicklook_im(dmap, logAmp=False, show=True) # quicklook_im(CPA_map*proper.prop_get_wavelength(wfo)/(4*np.pi), logAmp=False) # quicklook_im(CPA_map*proper.prop_get_wavelength(wfo)/(4*np.pi) + dmap, logAmp=False, show=True) # # # There's a boundary effect that needs to be mitigated # phase_map = proper.prop_get_phase(wfo) # artefacts = np.abs(phase_map) > 1 # # print np.shape(artefacts), np.shape(phase_map) # # quicklook_im(phase_map, logAmp=False) # # width = round(tp.grid_size*beam_ratio) # mid = int(tp.grid_size/2.) # lower = int(mid-width/2.) # upper = int(mid+width/2.) # mask = np.zeros((tp.grid_size, tp.grid_size)) # mask[upper,:] = 1 # mask[:, upper] = 1 # mask[lower,:] = 1 # mask[:,lower] = 1 # mask = mask*artefacts # # # print width, upper # # # wfo.wfarr[upper] = phase_map[tp.grid_size/2,tp.grid_size/2] # # quicklook_im( phase_map*mask, logAmp=False) # # proper.prop_add_phase(wfo,-phase_map*mask*proper.prop_get_wavelength(wfo)/(2*np.pi)) # quicklook_IQ(wfo) # I = np.real(wfo.wfarr) # Q = np.imag(wfo.wfarr) # I = proper.prop_shift_center(I) # Q = proper.prop_shift_center(Q) # Q[89] = 0 # Q[:,89] = 0 # # Q[39] = 0 # # Q[:,39] = 0 # I = proper.prop_shift_center(I) # Q = proper.prop_shift_center(Q) # wfo.wfarr = I+1j*Q # quicklook_wf(wfo) # quicklook_IQ(wfo) # print phase_map[artefacts] # plt.imshow(phase_map) # # plt.figure() # # plt.imshow(dmap) # # # plt.show() # # # proper.prop_propagate(wfo, f_lens, "coronagraph lens") # quicklook_wf(wfo) return
def coronagraph(wfo, f_lens, occulter_type, occult_loc, diam): # proper.prop_lens(wfo, f_lens, "coronagraph imaging lens") # proper.prop_propagate(wfo, f_lens, "occulter") # quicklook_wf(wfo) # occulter sizes are specified here in units of lambda/diameter; # convert lambda/diam to radians then to meters lamda = proper.prop_get_wavelength(wfo) # print lamda occrad = 3 # occulter radius in lam/D occrad_rad = occrad * lamda / diam # occulter radius in radians dx_m = proper.prop_get_sampling(wfo) dx_rad = proper.prop_get_sampling_radians(wfo) occrad_m = occrad_rad * dx_m / dx_rad # occulter radius in meters # print occrad_m, occulter_type # print 'line 22.', occulter_type #plt.figure(figsize=(12,8)) # quicklook_wf(wfo) if occulter_type == "Gaussian": r = proper.prop_radius(wfo) h = np.sqrt(-0.5 * occrad_m**2 / np.log(1 - np.sqrt(0.5))) #*0.8 gauss_spot = 1 - np.exp(-0.5 * (r / h)**2) # print occult_loc # gauss_spot = np.roll(gauss_spot,occult_loc,(0,1)) gauss_spot = shift(gauss_spot, shift=occult_loc, mode='wrap') proper.prop_multiply(wfo, gauss_spot) # quicklook_wf(wfo) #plt.suptitle("Gaussian spot", fontsize = 18) elif occulter_type == "Solid": proper.prop_circular_obscuration(wfo, occrad_m * 4. / 3) #plt.suptitle("Solid spot", fontsize = 18) # quicklook_wf(wfo) elif occulter_type == "8th_Order": proper.prop_8th_order_mask(wfo, occrad * 3. / 4., CIRCULAR=True) # quicklook_wf(wfo) elif occulter_type == 'Vortex': # print('lol') # apodization(wfo, True) vortex(wfo) # lyotstop(wfo, True) #plt.suptitle("8th order band limited spot", fontsize = 18) # quicklook_wf(wfo, logAmp=False, show=True) # After occulter # plt.subplot(1,2,1) # plt.imshow(np.sqrt(proper.prop_get_amplitude(wfo)), origin = "lower", cmap = plt.cm.gray) # plt.text(200, 10, "After Occulter", color = "w") # plt.show() # quicklook_wf(wfo) proper.prop_propagate(wfo, f_lens, "pupil reimaging lens") # quicklook_wf(wfo) proper.prop_lens(wfo, f_lens, "pupil reimaging lens") # quicklook_wf(wfo) proper.prop_propagate(wfo, 2 * f_lens, "lyot stop") # quicklook_wf(wfo) # from numpy.fft import fft2, ifft2 # wfo.wfarr = fft2(wfo.wfarr) #/ np.size(wfo.wfarr) # quicklook_wf(wfo) # plt.subplot(1,2,2) # plt.imshow(proper.prop_get_amplitude(wfo)**0.2, origin = "lower", cmap = plt.cm.gray) # plt.text(200, 10, "Before Lyot Stop", color = "w") # plt.show() # quicklook_wf(wfo,logAmp=False, show=True) if occulter_type == "Gaussian": # quicklook_wf(wfo) proper.prop_circular_aperture(wfo, 0.75, NORM=True) elif occulter_type == "Solid": # quicklook_wf(wfo) proper.prop_circular_aperture(wfo, 0.84, NORM=True) elif occulter_type == "8th_Order": # quicklook_wf(wfo) proper.prop_circular_aperture(wfo, 0.75, NORM=True) #0.5 elif occulter_type == "Vortex": # proper.prop_circular_aperture(wfo, 0.98, NORM = True) #0.5 lyotstop(wfo, True) # quicklook_wf(wfo) elif occulter_type == "None (Lyot Stop)": proper.prop_circular_aperture(wfo, 0.8, NORM=True) proper.prop_propagate(wfo, f_lens, "reimaging lens") # errs = np.sqrt(proper.prop_get_amplitude(wfo)) # # plt.figure() # # plt.imshow(errs) # # plt.show() # quicklook_wf(wfo) proper.prop_lens(wfo, f_lens, "reimaging lens") # quicklook_wf(wfo) proper.prop_propagate(wfo, f_lens, "final focus") # from numpy.fft import fft2, ifft2 # wfo.wfarr = fft2(wfo.wfarr) / np.size(wfo.wfarr) # quicklook_wf(wfo) return