def spatial(allSF, kernel, npupil=None, norm=False, verbose=False): # mask with nans mask_nan = np.isnan(allSF) + (allSF == 0) allSF[mask_nan] = np.nan # get low and high spatial frequencies with warnings.catch_warnings(): warnings.simplefilter("ignore") # NANs LSF = astroconv.convolve(allSF, kernel, boundary='extend') LSF[mask_nan] = np.nan HSF = allSF - LSF # print rms if verbose is True: print('rms(all SF) = %.2f nm'%(np.nanstd(allSF))) print('rms(LSF) = %.2f nm'%(np.nanstd(LSF))) print('rms(HSF) = %.2f nm'%(np.nanstd(HSF))) # normalize if norm is True: allSF /= np.nanstd(allSF) LSF /= np.nanstd(LSF) HSF /= np.nanstd(HSF) allSF -= np.nanmean(allSF) LSF -= np.nanmean(LSF) HSF -= np.nanmean(HSF) # remove nans allSF = np.nan_to_num(allSF) LSF = np.nan_to_num(LSF) HSF = np.nan_to_num(HSF) # resize outputs if npupil is not None: allSF = resize_cube(allSF, npupil) LSF = resize_cube(LSF, npupil) HSF = resize_cube(HSF, npupil) return allSF, LSF, HSF
def psd_spatial_zernike(cube_name, pup, zpols, nzer, ncube): spsd_name = cube_name[:-5] + '_%s' + '_%s.fits'%nzer try: spsd = fits.getdata(spsd_name%'spsd') print('getdata ' + spsd_name%'spsd') except FileNotFoundError: print('writeto ' + spsd_name%'spsd') cube = fits.getdata(cube_name)[:ncube] nimg = cube.shape[-1] pup = resize_cube(pup, nimg) zpols = zpols[:ncube,:nzer] wf = proper.prop_begin(1, 1, nimg, 1) # initial wavefront LSFs = np.empty((nzer, ncube, nimg, nimg)) HSFs = np.empty((nzer, ncube, nimg, nimg)) HSFs_rms = [] for z in np.arange(nzer) + 1: verbose = True if z == 1 else False LSF, HSF = multiCPU(remove_zernike, posargs=[deepcopy(wf), pup], posvars=[cube, zpols[:,:z]], case='remove zernike', nout=2, verbose=verbose) LSFs[z-1], HSFs[z-1] = LSF, HSF HSFs_rms.append(get_rms(HSF, verbose=verbose)) print(z, end=', ') spsd = [rms**2 for rms in HSFs_rms] spsd = [spsd[0]] + spsd fits.writeto(spsd_name%'spsd', np.float32(spsd)) fits.writeto(spsd_name%'LSFs', np.float32(LSFs)) fits.writeto(spsd_name%'HSFs', np.float32(HSFs)) return spsd
def conv_kernel(Npup, cpp, HR=2**11): ker_range = np.arange(-HR, HR)/HR Xs,Ys = np.meshgrid(ker_range, ker_range) # high res kernel XY grid Rs = np.abs(Xs + 1j*Ys) # high res kernel radii kernel = np.ones((2*HR, 2*HR)) kernel[Rs > 1] = 0 # kernel must have odd dimensions nkernel = int(Npup/cpp) nkernel = nkernel+1 if nkernel%2 == 0 else nkernel # resize kernel kernel = resize_cube(kernel, nkernel) kernel /= np.sum(kernel) # need to normalize the kernel return kernel
def get_zernike(cube_name, pup, nzer): zpols_name = cube_name[:-5] + '_zpols_%s.fits'%nzer try: zpols = fits.getdata(zpols_name) print('getdata ' + zpols_name) except FileNotFoundError: print('writeto ' + zpols_name) cube = fits.getdata(cube_name) nimg = cube.shape[-1] pup = resize_cube(pup, nimg) zpols = multiCPU(fit_zer, posargs=[pup, nimg/2, nzer], posvars=[cube], case='get zpols') fits.writeto(zpols_name, np.float32(zpols)) return zpols
def load_errors(nframes=20, nstep=1, npupil=285, add_phase=True, add_amp=False, f_phase='', f_amp='', add_point_err=False, f_point_err='', add_apo_drift=False, apo_drift=0.02, verbose=False, **conf): ''' Load wavefront errors. nframes (int): number of frames to crop the input data nstep (int): take 1 frame every nstep (cubesize = nframes/nstep) npupil (int): size of pupil lam (float): wavelength in m add_phase (bool): true if adding phase screens add_amp (bool): true if adding amplitude screens f_phase (str): path to phase screens fits file f_amp (str): path to amplitude screens fits file add_point_err (bool): true if adding pointing errors f_point_err (str): path to pointing errors fits file add_apo_drift (bool): true if adding apodizer drift ''' # size of cubes/arrays nscreens = int((nframes / nstep) + 0.5) # load phase screens if add_phase is True: assert(os.path.isfile(f_phase) and os.path.splitext(f_phase)[1] == '.fits'), \ "'f_phase' must be a valid fits file." phase_screens = fits.getdata(f_phase)[:nframes][::nstep] # in meters phase_screens = np.nan_to_num(phase_screens) phase_screens = resize_cube(phase_screens, npupil) if verbose is True: print("Load phase screens from '%s'" % os.path.basename(f_phase)) print(' nscreens=%s (nframes=%s, nstep=%s)' % (len(phase_screens), nframes, nstep)) else: phase_screens = [None] * nscreens # load amp screens if add_amp is True: assert(os.path.isfile(f_amp) and os.path.splitext(f_amp)[1] == '.fits'), \ "'f_amp' must be a valid fits file." amp_screens = np.array(fits.getdata(f_amp), ndmin=3) if len(amp_screens) > 1: # cube amp_screens = amp_screens[:nframes][::nstep] amp_screens = np.nan_to_num(amp_screens) amp_screens = resize_cube(amp_screens, npupil) if verbose is True: print("Load amp screens from '%s'" % os.path.basename(f_amp)) print(' nscreens=%s' % (len(amp_screens))) else: amp_screens = np.array([None] * nscreens) # load pointing errors (in mas) if add_point_err is True: tiptilts = np.array(fits.getdata(f_point_err), ndmin=2) if len(tiptilts) > 1: # cube tiptilts = tiptilts[:nframes][::nstep] # convert mas to rms phase error tiptilts = mas2rms(tiptilts, conf['diam_ext']) if verbose is True: print("Load pointing errors from '%s'" % os.path.basename(f_point_err)) print(' nscreens=%s' % (len(tiptilts))) else: tiptilts = np.array([None] * nscreens) # load apodizer drift if add_apo_drift is True and 'RAVC' in conf['mode']: misaligns = np.array([[x,0,0,0,0,0] \ for x in np.linspace(-apo_drift/2, apo_drift/2, 12000)])[:nframes][::nstep] if verbose is True: print('Load apodizer drit=%s %% ptv' % apo_drift) else: misaligns = np.array([None] * nscreens) return phase_screens, amp_screens, tiptilts, misaligns
fits.writeto(f_petal_screens % (TF, master_seed[TF], band, npupil), np.float32(pp), overwrite=True) piston_Q = fits.getdata(f_piston_Q) piston_DYN = fits.getdata(f_piston_DYN) # All effects ncpa_QLSF = (ncpa_QLSF + piston_Q) / np.sqrt(2) ncpa_QHSF = ncpa_QHSF ncpa_DYN = (ncpa_DYN + piston_DYN) / np.sqrt(2) # norm (almost 1) ncpa_QLSF /= np.mean([np.std(x[mask]) for x in ncpa_QLSF]) ncpa_QHSF /= np.mean([np.std(x[mask]) for x in ncpa_QHSF]) ncpa_DYN /= np.mean([np.std(x[mask]) for x in ncpa_DYN]) # total in meters (values at L band) ncpa_piston_ALL = ncpa_STA * 36e-9 + ncpa_QLSF * 20e-9 + ncpa_QHSF * 20e-9 + ncpa_DYN * 40e-9 # ncpa_piston_ALL = ncpa_QLSF*20e-9 + ncpa_QHSF*20e-9 + ncpa_DYN*40e-9 # ncpa_piston_ALL = ncpa_QLSF*20e-9 + ncpa_QHSF*20e-9 # TOTAL PHASE SCREENS lamL = update_config(**dict(read_config(), band='L'))['lam'] for band in ['L', 'M', 'N1', 'N2']: conf = update_config(**dict(read_config(), band=band)) scaling = 1 #scaling = conf['lam']/lamL #print(scaling, conf['npupil']) f_out = f_scao_screens % (tag, t_max, dt, 'all_ncpa', band, conf['npupil']) fits.writeto(f_out, resize_cube(scao + ncpa_piston_ALL * scaling, conf['npupil']), overwrite=True) print('%s created' % f_out)
fits.writeto(f_petal_screens%(TF, master_seed[TF], 'L', npupil), np.float32(pp), overwrite=True) piston_Q = fits.getdata(f_piston_Q) piston_DYN = fits.getdata(f_piston_DYN) # All effects ncpa_QLSF = (ncpa_QLSF + piston_Q)/np.sqrt(2) ncpa_QHSF = ncpa_QHSF ncpa_DYN = (ncpa_DYN + piston_DYN)/np.sqrt(2) # norm (almost 1) ncpa_QLSF /= np.mean([np.nanstd(x) for x in ncpa_QLSF]) ncpa_QHSF /= np.mean([np.nanstd(x) for x in ncpa_QHSF]) ncpa_DYN /= np.mean([np.nanstd(x) for x in ncpa_DYN]) # total in meters (values at L band) ncpa_piston_ALL = ncpa_STA*36e-9 + ncpa_QLSF*20e-9 + ncpa_QHSF*20e-9 + ncpa_DYN*40e-9 # ncpa_piston_ALL = ncpa_QLSF*20e-9 + ncpa_QHSF*20e-9 + ncpa_DYN*40e-9 # ncpa_piston_ALL = ncpa_QLSF*20e-9 + ncpa_QHSF*20e-9 # TOTAL PHASE SCREENS lamL = update_config(**dict(read_config(), band='L'))['lam'] for band in ['L', 'M', 'N1', 'N2']: conf = update_config(**dict(read_config(), band=band)) <<<<<<< HEAD scaling = conf['lam']/lamL ======= scaling = 1 #scaling = conf['lam']/lamL >>>>>>> origin/master #print(scaling, conf['npupil']) f_out = f_scao_screens%(tag, t_max, dt, 'all_ncpa', band, conf['npupil']) fits.writeto(f_out, resize_cube(scao + ncpa_piston_ALL*scaling, conf['npupil']), overwrite=True) print('%s created'%f_out)
npts = 592 new_size = 285 pad_resize = 39.9988/37 new_name = 'cube_COMPASS_20181008_3600s_300ms_0piston_meters_scao_only_%s.fits'%new_size def is_odd(n): return bool(n % 2) def oversamp(precision, start, end, stop=1e6): scale = end/start size = np.array([(x, x*scale) for x in np.arange(start, stop) \ if x*scale % 1 < precision and is_odd(x) is is_odd(round(x*scale))]) return size[0] if np.any(size) else 0 t0 = time.time() cube[:,mask==0] = np.nan cube = (cube.T - np.nanmean(cube,(1,2))).T # removing piston cube *= 1e-6 # in meters n1,n2 = oversamp(1e-2, npts, npts*39.9988/37) print(npts, n1, n2, int(n2)/int(n1)*37) cube = resize_cube(cube, int(n1), cpu_count=None, verbose=True) cube = np.float32([pad_img(x, int(n2), np.nan) for x in cube]) cube = resize_cube(cube, new_size, cpu_count=None, verbose=True) cube.shape fits.writeto(os.path.join(folder, new_name), np.float32(cube), overwrite=True) print(time.time() - t0)