def generate_maps2(): import random print 'Generating optic aberration maps using Proper' wfo = proper.prop_begin(tp.diam, 1., tp.grid_size, tp.beam_ratio) # rms_error = 5e-6#500.e-9 # RMS wavefront error in meters # c_freq = 0.005 # correlation frequency (cycles/meter) # high_power = 1. # high frewquency falloff (r^-high_power) rms_error = 2.5e-3 # 500.e-9 # RMS wavefront error in meters c_freq = 0.000005 # correlation frequency (cycles/meter) high_power = 1. # high frewquency falloff (r^-high_power) # tp.abertime = [0.5,2,10] # characteristic time for each aberation in secs tp.abertime = [ 100 ] # if beyond numframes then abertime will be auto set to duration of simulation abercubes = [] aber_cube = np.zeros((ap.numframes, tp.grid_size, tp.grid_size)) print 'here' perms = np.random.rand(ap.numframes, tp.grid_size, tp.grid_size) - 0.5 perms *= 1e-7 phase = 2 * np.pi * np.random.uniform(size=(tp.grid_size, tp.grid_size)) - np.pi aber_cube[0] = proper.prop_psd_errormap( wfo, rms_error, c_freq, high_power, MAP="prim_map", PHASE_HISTORY=phase) # FILE=td.aberdir+'/telzPrimary_Map.fits') print 'lol' # quicklook_im(aber_cube[0], logAmp=False) for a in range(1, ap.numframes): # quicklook_im(aber_cube[a], logAmp=False) perms = np.random.rand(tp.grid_size, tp.grid_size) - 0.5 perms *= 0.05 phase += perms # print phase[:5,:5] aber_cube[a] = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, MAP="prim_map", PHASE_HISTORY=phase) plt.plot(aber_cube[:, 20, 20]) plt.show() for a in range(0, ap.numframes - 1, 100): quicklook_im(aber_cube[a], logAmp=False) if not os.path.isdir(iop.aberdir): os.mkdir(iop.aberdir) for f in range(0, ap.numframes, 1): # print 'saving frame #', f if f % 100 == 0: misc.progressBar(value=f, endvalue=ap.numframes) rawImageIO.saveFITS(aber_cube[f], '%stelz%f.fits' % (iop.aberdir, f * cp.frame_time))
def add_IFS_ab(wfo, f_lens, w): # print 'Including Static Aberations' rms_error = 1.e-3 #500.e-9 # RMS wavefront error in meters c_freq = 0.000005 # correlation frequency (cycles/meter) high_power = 1. # high frewquency falloff (r^-high_power) proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, FILE=iop.aberdir + str(w) + '_IFS.fits')
def add_static(wfo, f_lens, loc='CPA', type='phase'): # print 'Including Static Aberations' # rms_error = 1.e-3#500.e-9 # RMS wavefront error in meters # c_freq = 0.000005 # correlation frequency (cycles/meter) # high_power = 1. # high frewquency falloff (r^-high_power) # # prim_map = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power) # quicklook_im(prim_map, logAmp=False, colormap="jet") # # rms_error = 1.e-3#500.e-9 # RMS wavefront error in meters # c_freq = 0.0000005 # correlation frequency (cycles/meter) # high_power = 2. # high frewquency falloff (r^-high_power) # # prim_map = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power) # quicklook_im(prim_map, logAmp=False, colormap="jet") # rms_error = 5.e4#500.e-9 # RMS wavefront error in meters # c_freq = 5e-7 # correlation frequency (cycles/meter) # high_power = 2. # high frewquency falloff (r^-high_power) # rms_error = 1e-12#500.e-9 # RMS wavefront error in meters # c_freq = 0.1 # correlation frequency (cycles/meter) # high_power = 3. # high frewquency falloff (r^-high_power) rms_error = 7.2e-16 #500.e-9 # RMS wavefront error in meters c_freq = 0.35 # correlation frequency (cycles/meter) high_power = 3.1 # high frewquency falloff (r^-high_power) # quicklook_wf(wfo) if type == 'Amp' or type == 'Both': rms_error = 2. # 500.e-9 # RMS wavefront error in meters c_freq = 1 # correlation frequency (cycles/meter) high_power = 3. # high frewquency falloff (r^-high_power) prim_map = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, FILE=iop.aberdir + loc + '_static_amp.fits', AMPLITUDE=1.0) print 'yep' else: prim_map = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, FILE=iop.aberdir + loc + '_static_2.fits', TPF=True)
def modulate(wfo, w, iter): # phase_mod = np.ones((tp.grid_size,tp.grid_size))*(iter%4) * w/4. # phase_arr = proper.prop_get_phase(wfo) # phase_mod[phase_arr == 0] = 0 # # quicklook_wf(wfo) # proper.prop_add_phase(wfo, phase_mod) # phase_mod = (iter % 8) * w / 8. - w/4. # proper.prop_zernikes(wfo, [4], np.array([phase_mod])/4.) # # quicklook_wf(wfo) # import dm_functions as DM # # speck.generate_flatmap(phase) # s_amp = DM.amplitudemodel(0.05, 30, c=1.6) # waffle = DM.make_speckle_kxy(3, 3, s_amp, np.pi/2.) # quicklook_im(waffle, logAmp=False) # proper.prop_add_phase(wfo, waffle) # quicklook_wf(wfo) rms_error = 5e-7 # 500.e-9 # RMS wavefront error in meters c_freq = 0.005 # correlation frequency (cycles/meter) high_power = 2. # high frewquency falloff (r^-high_power) phase_map = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, MAP="prim_map")
## Step 5 # Determine the region of the array corresponding to the DM surface for use in the fitting. mp.dm1.V = np.ones((mp.dm1.Nact,mp.dm1.Nact)) testSurf = falco.dm.gen_surf_from_act(mp.dm1, mp.dm1.compact.dx, mp.dm1.compact.NdmPad) testArea = np.zeros(testSurf.shape) testArea[testSurf >= 0.5*np.max(testSurf)] = 1 #--PROPER initialization pupil_ratio = 1 # beam diameter fraction wl_dummy = 1e-6 # dummy value needed to initialize wavelength in PROPER (meters) wavefront = proper.prop_begin(mp.dm1.compact.NdmPad*mp.dm1.dx, wl_dummy, mp.dm1.compact.NdmPad, pupil_ratio) # PSD Error Map Generation using PROPER amp = 9.6e-19; b = 4.0; c = 3.0; errorMap = proper.prop_psd_errormap( wavefront, amp, b, c, TPF=True ) errorMap = errorMap*testArea; if(flagPlotDebug): plt.figure(1); plt.imshow(testArea); plt.colorbar(); plt.pause(0.1); plt.figure(2); plt.imshow(errorMap); plt.colorbar(); plt.pause(0.1); #--Fit the surface Vout = falco.dm.fit_surf_to_act(mp.dm1,errorMap)/mp.dm1.VtoH mp.dm1.V = Vout DM1Surf = falco.dm.gen_surf_from_act(mp.dm1, mp.dm1.compact.dx, mp.dm1.compact.NdmPad) surfError = errorMap - DM1Surf; rmsError = np.sqrt(np.mean((surfError[testArea==1].flatten()**2))) print('RMS fitting error to voltage map is %.2e meters.\n'%rmsError) if(flagPlotDebug):
def generate_maps(aber_vals, lens_diam, lens_name='lens'): """ generate PSD-defined aberration maps for a lens(mirror) using Proper Use Proper to generate an 2D aberration pattern across an optical element. The amplitude of the error per spatial frequency (cycles/m) across the surface is taken from a power spectral density (PSD) of statistical likelihoods for 'real' aberrations of physical optics. parameters defining the PSD function are specified in tp.aber_vals. These limit the range for the constants of the governing equation given by PSD = a/ [1+(k/b)^c]. This formula assumes the Terrestrial Planet Finder PSD, which is set to TRUE unless manually overridden line-by-line. As stated in the proper manual, this PSD function general under-predicts lower order aberrations, and thus Zernike polynomials can be added to get even more realistic surface maps. more information on a PSD error map can be found in the Proper manual on pgs 55-60 Note: Functionality related to OOPP (out of pupil plane) optics has been removed. There is only one surface simulated for each optical surface :param aber_vals: dictionary? of values to use in the equation that generates the aberration map. The dictionary should contain 3 entries that get sent to proper.prop_psd_errormap. More information can be found on Proper Manual pg 56 :param lens_diam: diameter of the lens/mirror to generate an aberration map for :param lens_name: name of the lens, for file naming :return: will create a FITs file in the folder specified by iop.quasi for each optic (and timestep in the case of quasi-static aberrations) """ # TODO add different timescale aberations dprint('Generating optic aberration maps using Proper') iop.aberdata = f"gridsz{sp.grid_size}_bmratio{sp.beam_ratio}_tsteps{sp.numframes}" iop.aberdir = os.path.join(iop.testdir, iop.aberroot, iop.aberdata) if not os.path.isdir(iop.aberdir): os.makedirs(iop.aberdir, exist_ok=True) dprint(f"Abberation directory = {iop.aberdir}") # create blank lens wavefront for proper to add phase to wfo = proper.prop_begin(lens_diam, 1., sp.grid_size, sp.beam_ratio) aber_cube = np.zeros((sp.numframes, sp.grid_size, sp.grid_size)) # Randomly select a value from the range of values for each constant rms_error = np.random.normal(aber_vals['a'][0], aber_vals['a'][1]) c_freq = np.random.normal( aber_vals['b'][0], aber_vals['b'][1]) # correlation frequency (cycles/meter) high_power = np.random.normal( aber_vals['c'][0], aber_vals['c'][1]) # high frequency falloff (r^-high_power) perms = np.random.rand(sp.numframes, sp.grid_size, sp.grid_size) - 0.5 perms *= 1e-7 phase = 2 * np.pi * np.random.uniform(size=(sp.grid_size, sp.grid_size)) - np.pi aber_cube[0] = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, TPF=True, PHASE_HISTORY=phase) # PHASE_HISTORY stuff is a kwarg Rupert added to a proper.prop_pds_errormap in proper_mod that helps # ennable the small perturbations to the phase aberrations over time (quasi-static aberration evolution) # however, this may not be implemented here, and the functionality may not be robust. It has yet to be # verified in a robust manner. However, I am not sure it is being used....? KD 10-15-19 # TODO verify this and add qusi-static functionality filename = f"{iop.aberdir}/t{0}_{lens_name}.fits" #dprint(f"filename = {filename}") if not os.path.isfile(filename): saveFITS(aber_cube[0], filename) # I think this part does quasi-static aberrations, but not sure if the random error is correct. On 7-10-19 for a in range(1, sp.numframes): perms = np.random.rand(sp.grid_size, sp.grid_size) - 0.5 perms *= 0.05 phase += perms aber_cube[a] = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, MAP="prim_map", TPF=True, PHASE_HISTORY=phase) filename = f"{iop.aberdir}/t{a}_{lens_name}.fits" if not os.path.isfile(filename): saveFITS(aber_cube[0], filename)
def generate_maps(aber_vals, lens_diam, lens_name='lens', quasi_static=False): """ generate PSD-defined aberration maps for a lens(mirror) using Proper Use Proper to generate an 2D aberration pattern across an optical element. The amplitude of the error per spatial frequency (cycles/m) across the surface is taken from a power spectral density (PSD) of statistical likelihoods for 'real' aberrations of physical optics. parameters defining the PSD function are specified in tp.aber_vals. These limit the range for the constants of the governing equation given by PSD = a/ [1+(k/b)^c]. This formula assumes the Terrestrial Planet Finder PSD, which is set to TRUE unless manually overridden line-by-line. As stated in the proper manual, this PSD function general under-predicts lower order aberrations, and thus Zernike polynomials can be added to get even more realistic surface maps. more information on a PSD error map can be found in the Proper manual on pgs 55-60 Note: Functionality related to OOPP (out of pupil plane) optics has been removed. There is only one surface simulated for each optical surface :param aber_vals: dictionary? of values to use in the equation that generates the aberration map. The dictionary should contain 3 entries that get sent to proper.prop_psd_errormap. More information can be found on Proper Manual pg 56 :param lens_diam: diameter of the lens/mirror to generate an aberration map for :param lens_name: name of the lens, for file naming :return: will create a FITs file in the folder specified by iop.quasi for each optic (and timestep in the case of quasi-static aberrations) """ # TODO add different timescale aberations if sp.verbose: dprint( f'Generating optic aberration maps using Proper at directory {iop.aberdir}' ) if not os.path.isdir(iop.aberdir): # todo remove when all test scripts use the new format raise NotImplementedError print( 'aberration maps should be created at the beginng, not on the fly') os.makedirs(iop.aberdir, exist_ok=True) # create blank lens wavefront for proper to add phase to wfo = proper.prop_begin(lens_diam, 1., sp.grid_size, sp.beam_ratio) aber_cube = np.zeros((1, sp.grid_size, sp.grid_size)) # Randomly select a value from the range of values for each constant # rms_error = np.random.normal(aber_vals['a'][0], aber_vals['a'][1]) # c_freq = np.random.normal(aber_vals['b'][0], aber_vals['b'][1]) # correlation frequency (cycles/meter) # high_power = np.random.normal(aber_vals['c'][0], aber_vals['c'][1]) # high frequency falloff (r^-high_power) rms_error, c_freq, high_power = aber_vals # perms = np.random.rand(sp.numframes, sp.grid_size, sp.grid_size)-0.5 # perms *= 1e-7 phase = 2 * np.pi * np.random.uniform(size=(sp.grid_size, sp.grid_size)) - np.pi aber_cube[0] = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, TPF=True, PHASE_HISTORY=phase) # PHASE_HISTORY stuff is a kwarg Rupert added to a proper.prop_pds_errormap in proper_mod that helps # ennable the small perturbations to the phase aberrations over time (quasi-static aberration evolution) # however, this may not be implemented here, and the functionality may not be robust. It has yet to be # verified in a robust manner. However, I am not sure it is being used....? KD 10-15-19 # TODO verify this and add qusi-static functionality filename = f"{iop.aberdir}/t{0}_{lens_name}.fits" #dprint(f"filename = {filename}") if not os.path.isfile(filename): saveFITS(aber_cube[0], filename) if quasi_static: # todo implement monkey patch of proper.prop_psd_error that return phase too so it can be incremented with correlated gaussian noise # See commit 48c77c0babd5c6fcbc681b4fdd0d2db9cf540695 for original implementation of this code raise NotImplementedError
def add_aber(wfo, f_lens, aber_params, aber_vals, step=0, Loc='CPA'): if aber_params['QuasiStatic'] == False: step = 0 # print aber_params if aber_params['Phase']: for surf in range(aber_params['n_surfs']): filename = '%s%s_Phase%f_v%i.fits' % (iop.aberdir, Loc, step * cp.frame_time, surf) # print filename rms_error = np.random.normal(aber_vals['a'][0], aber_vals['a'][1]) # print rms_error c_freq = np.random.normal( aber_vals['b'][0], aber_vals['b'][1]) # correlation frequency (cycles/meter) # print c_freq high_power = np.random.normal( aber_vals['c'][0], aber_vals['c'][1]) # high frewquency falloff (r^-high_power) # print high_power # quicklook_wf(wfo) if aber_params['OOPP']: proper.prop_lens(wfo, f_lens, "OOPP") proper.prop_propagate(wfo, f_lens / aber_params['OOPP'][surf]) # quicklook_wf(wfo) prim_map = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, FILE=filename, TPF=True) if aber_params['OOPP']: proper.prop_propagate( wfo, f_lens + f_lens * (1 - 1. / aber_params['OOPP'][surf])) proper.prop_lens(wfo, f_lens, "OOPP") # quicklook_wf(wfo) # quicklook_im(prim_map*1e9, logAmp=False, colormap="jet", show=True, axis=None, title='nm', pupil=True) if aber_params['Amp']: # filename = '%s%s_Amp%f.fits' % (iop.aberdir, Loc, step * cp.frame_time) for surf in range(aber_params['n_surfs']): filename = '%s%s_Amp%f_v%i.fits' % (iop.aberdir, Loc, step * cp.frame_time, surf) # print filename rms_error = np.random.normal(aber_vals['a_amp'][0], aber_vals['a_amp'][1]) # print rms_error c_freq = np.random.normal( aber_vals['b'][0], aber_vals['b'][1]) # correlation frequency (cycles/meter) # print c_freq high_power = np.random.normal( aber_vals['c'][0], aber_vals['c'][1]) # high frewquency falloff (r^-high_power) # print high_power prim_map = proper.prop_psd_errormap(wfo, rms_error, c_freq, high_power, FILE=filename, AMPLITUDE=1.0)
def generate_maps(): import random print 'Generating optic aberration maps using Proper' wfo = proper.prop_begin(tp.diam, 1., tp.grid_size, tp.beam_ratio) # rms_error = 5e-6#500.e-9 # RMS wavefront error in meters # c_freq = 0.005 # correlation frequency (cycles/meter) # high_power = 1. # high frewquency falloff (r^-high_power) rms_error = 2.5e-3 #500.e-9 # RMS wavefront error in meters c_freq = 0.000005 # correlation frequency (cycles/meter) high_power = 1. # high frewquency falloff (r^-high_power) # tp.abertime = [0.5,2,10] # characteristic time for each aberation in secs tp.abertime = [ 100 ] # if beyond numframes then abertime will be auto set to duration of simulation abercubes = [] for abertime in tp.abertime: # ap.numframes = 100 aberfreq = 1. / abertime # tp.abertime=2 # aberfreq: number of frames goals per sec? num_longframes = aberfreq * ap.numframes * cp.frame_time print num_longframes, ap.numframes, cp.frame_time aber_cube = np.zeros((ap.numframes + 1, tp.grid_size, tp.grid_size)) lin_size = tp.grid_size**2 # spacing = int(ap.numframes/num_longframes) # frame_idx = np.int_(np.linspace(0,ap.numframes,num_longframes+1)) c = range(0, ap.numframes) print num_longframes frame_idx = np.sort(random.sample(c, int(num_longframes + 1 - 2))) # frame_idx = np.int_(np.sort(np.round(np.random.uniform(0,ap.numframes,num_longframes+1-2)))) frame_idx = np.hstack(([0], frame_idx, [ap.numframes])) # frame_idx = [0, 15, 69, 278, 418, 703, 1287, 1900, 3030, 3228, 5000] print frame_idx for f in frame_idx: aber_cube[f] = proper.prop_psd_errormap( wfo, rms_error, c_freq, high_power, MAP="prim_map") #FILE=td.aberdir+'/telzPrimary_Map.fits') # quicklook_im(aber_cube[f], logAmp=False) for i, f in enumerate(frame_idx[:-1]): spacing = int(frame_idx[i + 1] - frame_idx[i]) # quicklook_im(aber_cube[f], logAmp=False, show=False) frame1 = aber_cube[f] frame2 = aber_cube[frame_idx[i + 1]] lin_map = [ np.linspace(f1, f2, spacing) for f1, f2 in zip( frame1.reshape(lin_size), frame2.reshape(lin_size)) ] interval_cube = np.array(lin_map).reshape(tp.grid_size, tp.grid_size, spacing) interval_cube = np.transpose(interval_cube) print i, f, frame_idx[i], frame_idx[i + 1], np.shape(interval_cube) # loop_frames(interval_cube, logAmp=False) aber_cube[f:frame_idx[i + 1]] = interval_cube abercubes.append(aber_cube) plt.plot(aber_cube[:, 20, 20]) plt.show() abercubes = np.array(abercubes) # print abercubes.shape # plt.plot(aber_cube[:,20,20]) aber_cube = np.sum(abercubes, axis=0) plt.plot(aber_cube[:, 20, 20]) plt.show() if not os.path.isdir(iop.aberdir): os.mkdir(iop.aberdir) for f in range(0, ap.numframes, 1): # print 'saving frame #', f if f % 100 == 0: misc.progressBar(value=f, endvalue=ap.numframes) rawImageIO.saveFITS(aber_cube[f], '%stelz%f.fits' % (iop.aberdir, f * cp.frame_time)) # quicklook_im(aber_cube[f], logAmp=False, show=True) plt.show()