def testg_initCustomShape(): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) config.sim.pupilSize = 64 config.sim.simSize = 66 mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.ShackHartmann(config, mask=mask) dm = DM.KarhunenLoeve(config, n_dm=1, wfss=[wfs], mask=mask) customShape = dm.iMatShapes # saving temporary shapes fname = os.path.dirname( os.path.abspath(__file__)) + '/tmp_CustomDmShapes.fits' fits.writeto(fname, customShape, overwrite=True) # change size to ensure it tests interpolation config.sim.pupilSize = 100 config.sim.simSize = 104 mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.ShackHartmann(config, mask=mask) config.dms[1].dmShapesFilename = fname dm = DM.CustomShapes(config, n_dm=1, wfss=[wfs], mask=mask) # remove temporary shapes os.remove(fname)
def make_pupil_mask(mask, n_subap, nx_subap, obs_diam, tel_diam): """Generates a SOAPY pupil mask - code has been adapted from SOAPY make_mask.py Parameters: mask (str): must be 'circle' nx_subap (int): number of sub-apertures across telescope's pupil. obs_diam (float): diameter of central obscuration. tel_diam (float): diameter of telescope pupil. Returns: ndarray: mask of SHWFS sub-apertures within the telescope's pupil.""" if mask == "circle": pupil_mask = aotools.circle(nx_subap / 2., nx_subap) if obs_diam != None: pupil_mask -= aotools.circle( nx_subap * ((obs_diam / tel_diam) / 2.), nx_subap) else: raise Exception( 'Only circlular pupil masks have been integrated (sorry).') if n_subap[0] != int(numpy.sum(pupil_mask)): raise Exception( 'Error in the number of sub-apertures within pupil mask.') return pupil_mask.astype(int)
def test_slopecovmat_makecovmat_uneven(): threads = 1 n_wfs = 3 telescope_diameter = 8. nx_subaps = 10 n_layers = 3 layer_altitudes = numpy.linspace(0, 20000, n_layers) layer_r0s = [1] * n_layers layer_L0s = [25.] * n_layers asterism_radius = 10 # What if all WFSs don't have the same number of subaps? pupil_masks = [aotools.circle(4.5, nx_subaps), aotools.circle(nx_subaps / 2., nx_subaps), aotools.circle(nx_subaps / 2., nx_subaps)] subap_diameters = [telescope_diameter / nx_subaps] * n_wfs gs_altitudes = [90000] * n_wfs gs_positions = [ [asterism_radius, 0], [numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-asterism_radius, 0]] wfs_magnifications = [1.] * n_wfs pupil_offsets = [[0, 0]] * n_wfs wfs_rotations = [0] * n_wfs wfs_wavelengths = [550e-9] * n_wfs cov_mat = aotools.CovarianceMatrix(n_wfs, pupil_masks, telescope_diameter, subap_diameters, gs_altitudes, gs_positions, wfs_wavelengths, n_layers, layer_altitudes, layer_r0s, layer_L0s, threads) covariance_matrix = cov_mat.make_covariance_matrix()
def test_slopecovmat_makecovmat_uneven(): threads = 1 n_wfs = 3 telescope_diameter = 8. nx_subaps = 10 n_layers = 3 layer_altitudes = numpy.linspace(0, 20000, n_layers) layer_r0s = [1] * n_layers layer_L0s = [25.] * n_layers asterism_radius = 10 # What if all WFSs don't have the same number of subaps? pupil_masks = [ aotools.circle(4.5, nx_subaps), aotools.circle(nx_subaps / 2., nx_subaps), aotools.circle(nx_subaps / 2., nx_subaps) ] subap_diameters = [telescope_diameter / nx_subaps] * n_wfs gs_altitudes = [90000] * n_wfs gs_positions = [[asterism_radius, 0], [ numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius ], [ numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius ], [ -numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius ], [ -numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius ], [-asterism_radius, 0]] wfs_magnifications = [1.] * n_wfs pupil_offsets = [[0, 0]] * n_wfs wfs_rotations = [0] * n_wfs wfs_wavelengths = [550e-9] * n_wfs cov_mat = aotools.CovarianceMatrix(n_wfs, pupil_masks, telescope_diameter, subap_diameters, gs_altitudes, gs_positions, wfs_wavelengths, n_layers, layer_altitudes, layer_r0s, layer_L0s, threads) covariance_matrix = cov_mat.make_covariance_matrix()
def test_chop_subaps_mask_threads(): """ Tests that the numba routing chops phase into sub-apertures in the same way as using numpy indices Runs with multiple threads many times to detectect potential intermittant errors """ nx_phase = 12 nx_subap_size = 3 nx_subaps = nx_phase // nx_subap_size subap_array = numpy.zeros((nx_subaps * nx_subaps, nx_subap_size, nx_subap_size)).astype("complex64") numpy_subap_array = subap_array.copy() mask = aotools.circle(nx_phase / 2., nx_phase) x_coords, y_coords = numpy.meshgrid( numpy.arange(0, nx_phase, nx_subap_size), numpy.arange(0, nx_phase, nx_subap_size)) subap_coords = numpy.array([y_coords.flatten(), x_coords.flatten()]).T for i in range(50): phase = (numpy.random.random( (nx_phase, nx_phase)) + 1j * numpy.random.random( (nx_phase, nx_phase))).astype("complex64") numpy_chop(phase, subap_coords, nx_subap_size, numpy_subap_array, mask) thread_pool = numbalib.ThreadPool(1) numbalib.wfs.chop_subaps_mask_pool(phase, subap_coords, nx_subap_size, subap_array, mask, thread_pool) assert numpy.array_equal(numpy_subap_array, subap_array)
def test_chop_subaps_mask(): """ Tests that the numba routing chops phase into sub-apertures in the same way as using numpy indices """ nx_phase = 12 nx_subap_size = 3 nx_subaps = nx_phase // nx_subap_size phase = (numpy.random.random( (nx_phase, nx_phase)) + 1j * numpy.random.random( (nx_phase, nx_phase))).astype("complex64") subap_array = numpy.zeros((nx_subaps * nx_subaps, nx_subap_size, nx_subap_size)).astype("complex64") numpy_subap_array = subap_array.copy() mask = aotools.circle(nx_phase / 2., nx_phase) x_coords, y_coords = numpy.meshgrid( numpy.arange(0, nx_phase, nx_subap_size), numpy.arange(0, nx_phase, nx_subap_size)) subap_coords = numpy.array([x_coords.flatten(), y_coords.flatten()]).T numpy_chop(phase, subap_coords, nx_subap_size, numpy_subap_array, mask) numbalib.wfslib.chop_subaps_mask(phase, subap_coords, nx_subap_size, subap_array, mask) assert numpy.array_equal(numpy_subap_array, subap_array)
def testd_LegacySHWfsFrame(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.ShackHartmannLegacy(config, mask=mask) wfs.frame(numpy.zeros((config.atmos.scrnNo, config.sim.simSize, config.sim.simSize)))
def testd_initPhysLgs(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) config.wfss[1].lgs.propagationMode = "Physical" mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) lgs = LGS.LGS_Physical(config.wfss[1], config)
def calcInitParams(self): """ Calculate some useful paramters to be used later """ self.lgsPupilPxls = int( round(self.config.pupilDiam * self.simConfig.pxlScale)) if self.outPxlScale is None: self.outPxlScale_m = 1. / self.simConfig.pxlScale else: # The pixel scale in metres per pixel at the LGS altitude self.outPxlScale_m = (self.outPxlScale / 3600.) * ( numpy.pi / 180.) * self.config.height # Get the angular scale in radians of the output array self.outPxlScale_rad = self.outPxlScale_m / self.config.height # The number of pixels required across the LGS image if self.nOutPxls is None: self.nOutPxls = self.simConfig.simSize # Field of fov of the requested LGS PSF image self.fov = (self.nOutPxls * self.outPxlScale_rad) * RAD2ASEC # The number of points required to get the correct FOV after the FFT fov_rad = self.fov / RAD2ASEC self.nFovPxls = int( round(fov_rad * self.config.pupilDiam / self.config.wavelength)) # The mask to apply before geometric FFTing self.mask = aotools.circle(self.nFovPxls / 2., self.nFovPxls) self.losNOutPxls = self.lgsPupilPxls self.losOutPxlScale = self.config.pupilDiam / self.lgsPupilPxls
def testc_initGradWfs(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) config.sim.pupilSize = 10*config.wfss[0].nxSubaps mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) wfs = WFS.Gradient(config, mask=mask)
def __init__ (self, soapy_config, n_dm=0, wfss=None, mask=None): # Sort out some required attributes self.soapy_config = soapy_config self.n_dm = n_dm self.simConfig = self.soapy_config.sim self.config = self.dmConfig = self.soapy_config.dms[n_dm] self.pupil_size = self.soapy_config.sim.pupilSize self.sim_size = self.soapy_config.sim.simSize self.scrn_size = self.soapy_config.sim.scrnSize self.altitude = self.config.altitude self.diameter = self.config.diameter self.telescope_diameter = self.soapy_config.tel.telDiam self.wfss = wfss # If supplied use the mask if numpy.any(mask): self.mask = mask # Else we'll just make a circle else: self.mask = aotools.circle( self.pupil_size/2., self.sim_size, ) # the number of phase elements at the DM altitude self.nx_dm_elements = int(round(self.pupil_size * self.diameter / self.telescope_diameter)) self.dm_frame = numpy.zeros((self.nx_dm_elements, self.nx_dm_elements)) # An array of phase screen size to be observed by a line of sight self.dm_screen = numpy.zeros((self.scrn_size, self.scrn_size)) # Coordinate required to fit dm size back into screen self.screen_coord = int(round((self.scrn_size - self.nx_dm_elements)/2.)) self.n_acts = self.getActiveActs() self.actCoeffs = numpy.zeros((self.n_acts)) # Sort out which WFS(s) observes the DM (for iMat making) if self.dmConfig.wfs!=None: try: # Make sure the specifed WFS actually exists self.wfss = [wfss[self.dmConfig.wfs]] self.wfs = self.wfss[0] except KeyError: raise KeyError("DM attached to WFS {}, but that WFS is not specifed in config".format(self.dmConfig.wfs)) else: self.wfss = wfss logger.info("Making DM Influence Functions...") self.makeIMatShapes() # If using imatshapes, sclae by imat value if hasattr(self, "iMatShapes"): self.iMatShapes *= self.config.iMatValue # An array of values for each actuator. 1 if actuator is valid, 0 if not self._valid_actuators = numpy.ones((self.n_acts))
def test_Piezo_valid_actuators(): """ Tests that when you set the "valid actuators", the DM doesn't use actuators marked 'invalid' """ config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.ShackHartmann(config, mask=mask) dm = DM.FastPiezo(config, n_dm=1, wfss=[wfs], mask=mask) act_coord1 = dm.valid_act_coords[0] act_coord_last = dm.valid_act_coords[-1] act_coord2 = dm.valid_act_coords[1] valid_actuators = numpy.ones(dm.n_acts, dtype=int) valid_actuators[0] = valid_actuators[-1] = 0 dm.valid_actuators = valid_actuators assert dm.n_valid_actuators == (dm.n_acts - 2) assert not numpy.array_equal(dm.valid_act_coords[0], act_coord1) assert not numpy.array_equal(dm.valid_act_coords[-1], act_coord_last) assert numpy.array_equal(dm.valid_act_coords[0], act_coord2)
def test_chop_subaps_mask(): """ Tests that the numba routing chops phase into sub-apertures in the same way as using numpy indices """ nx_phase = 12 nx_subap_size = 3 nx_subaps = nx_phase // nx_subap_size phase = (numpy.random.random((nx_phase, nx_phase)) + 1j * numpy.random.random((nx_phase, nx_phase)) ).astype("complex64") subap_array = numpy.zeros((nx_subaps * nx_subaps, nx_subap_size, nx_subap_size)).astype("complex64") numpy_subap_array = subap_array.copy() mask = aotools.circle(nx_phase/2., nx_phase) x_coords, y_coords = numpy.meshgrid( numpy.arange(0, nx_phase, nx_subap_size), numpy.arange(0, nx_phase, nx_subap_size)) subap_coords = numpy.array([x_coords.flatten(), y_coords.flatten()]).T numpy_chop(phase, subap_coords, nx_subap_size, numpy_subap_array, mask) thread_pool = numbalib.ThreadPool(1) numbalib.wfs.chop_subaps_mask_pool( phase, subap_coords, nx_subap_size, subap_array, mask, thread_pool) assert numpy.array_equal(numpy_subap_array, subap_array)
def test_findActiveSubaps_with_returnFill(): subapertures = 10 mask = circle(4, 10) threshold = .6 active_subapertures, fill_factors = wfs.findActiveSubaps(subapertures, mask, threshold, returnFill=True) assert active_subapertures.shape == (52, 2) assert len(fill_factors) == 52
def updateAnimation(f, axarr, error, phase, phaseEst, psf, timer): f.suptitle('Algorithm time: {0:.5}s'.format(timer)) cmap = plt.cm.jet error = np.array(error) im1 = axarr[0, 0].plot(error[:, 1], linewidth=2.5) axarr[0, 0].grid(color='lightgrey', linestyle='--') axarr[0, 0].set_title("Wavefront error") axarr[0, 0].set_xlabel('iterations') axarr[0, 0].set_ylabel('RMSE') im2 = axarr[0, 1].imshow(psf**(1/3), cmap=cmap) cb2 = plt.colorbar(im2, ax=axarr[0, 1], fraction=0.046) axarr[0, 1].set_title("Point Spread function (strehl={0:.5f})".format(utils.strehl(phase-phaseEst))) axarr[0, 1].set_axis_off() mask=aotools.circle(64, 128).astype(np.float64) phase[mask<0.1]=None phaseEst[mask<0.1]=None im3 = axarr[1, 0].imshow(phase, cmap=cmap) im3.set_clim(-np.pi,np.pi) cb3 = plt.colorbar(im3, ax=axarr[1, 0], fraction=0.046) axarr[1, 0].set_title("Exact Phase") axarr[1, 0].set_axis_off() im4 = axarr[1, 1].imshow(phaseEst, cmap=cmap) im4.set_clim(-np.pi, np.pi) axarr[1, 1].set_title("Recovered phase") axarr[1, 1].set_axis_off() cb4 = plt.colorbar(im4, ax=axarr[1, 1], fraction=0.046) plt.pause(1e-5) axarr[0, 0].cla() cb2.remove() cb3.remove() cb4.remove() phase[mask<0.1]=0 phaseEst[mask<0.1]=0
def testa_initLgs(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) lgs = LGS.LGS(config.wfss[1], config)
def testc_initLegacySHWfs(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.ShackHartmannLegacy(config, mask=mask)
def test_chop_subaps_mask_threads(): """ Tests that the numba routing chops phase into sub-apertures in the same way as using numpy indices Runs with multiple threads many times to detectect potential intermittant errors """ nx_phase = 12 nx_subap_size = 3 nx_subaps = nx_phase // nx_subap_size subap_array = numpy.zeros((nx_subaps * nx_subaps, nx_subap_size, nx_subap_size)).astype("complex64") numpy_subap_array = subap_array.copy() mask = aotools.circle(nx_phase/2., nx_phase) x_coords, y_coords = numpy.meshgrid( numpy.arange(0, nx_phase, nx_subap_size), numpy.arange(0, nx_phase, nx_subap_size)) subap_coords = numpy.array([y_coords.flatten(),x_coords.flatten()]).T for i in range(50): phase = (numpy.random.random((nx_phase, nx_phase)) + 1j * numpy.random.random((nx_phase, nx_phase)) ).astype("complex64") numpy_chop(phase, subap_coords, nx_subap_size, numpy_subap_array, mask) thread_pool = numbalib.ThreadPool(1) numbalib.wfs.chop_subaps_mask_pool( phase, subap_coords, nx_subap_size, subap_array, mask, thread_pool) assert numpy.array_equal(numpy_subap_array, subap_array)
def testa_initWfs(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) wfs = WFS.WFS(config, mask=mask)
def testa_initDM(): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) wfs = WFS.ShackHartmann(config, mask=mask) dm = DM.DM(config, wfss=[wfs], mask=mask)
def testd_initPhysLgs(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) config.wfss[1].lgs.propagationMode = "Physical" mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) lgs = LGS.LGS_Physical(config.wfss[1], config)
def testa_initLgs(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) lgs = LGS.LGS(config.wfss[1], config)
def testc_geoLgsPsf(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) config.wfss[1].lgs.propagationMode = "Geometric" lgs = LGS.LGS_Geometric(config.wfss[1], config) psf = lgs.getLgsPsf( numpy.zeros((config.atmos.scrnNo, config.sim.simSize, config.sim.simSize)))
def testa_initWfs(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.WFS(config, mask=mask)
def testc_initGradWfs(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) config.sim.pupilSize = 10 * config.wfss[0].nxSubaps mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.Gradient(config, mask=mask)
def testd_SHWfsFrame(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.ShackHartmann(config, mask=mask) wfs.frame(numpy.zeros((config.sim.simSize, config.sim.simSize)))
def testb_wfsFrame(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) wfs = WFS.WFS(config, mask=mask) wfs.frame(numpy.zeros((config.sim.simSize, config.sim.simSize)))
def test_fibreInit(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) sci = SCI.singleModeFibre(config, 0, mask)
def test_sciInit(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) sci = scienceinstrument.PSFCamera(config, 0, mask)
def loadConfig(self): """ Load the Soapy config file """ self.config = confParse.YAML_Configurator(self.configfile) self.config.loadSimParams() self.mask = aotools.circle( self.config.sim.pupilSize/2., self.config.sim.simSize)
def teste_physLgsPsf(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) config.wfss[1].lgs.propagationMode = "Physical" mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) lgs = LGS.LGS_Physical(config.wfss[1], config, nOutPxls=10) psf = lgs.getLgsPsf( numpy.zeros((config.atmos.scrnNo, config.sim.simSize, config.sim.simSize)))
def testd_GradWfsFrame(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) config.sim.pupilSize = 10*config.wfss[0].nxSubaps mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) wfs = WFS.Gradient(config, mask=mask) wfs.frame(numpy.zeros((config.sim.simSize, config.sim.simSize)))
def test_PhysWfs(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) config.wfss[0].propagationMode = "Physical" mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) wfs = WFS.WFS(config, mask=mask) wfs.frame(numpy.zeros((config.atmos.scrnNo, config.sim.scrnSize, config.sim.scrnSize)))
def testd_GradWfsFrame(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) config.sim.pupilSize = 10 * config.wfss[0].nxSubaps mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.Gradient(config, mask=mask) wfs.frame(numpy.zeros((config.sim.simSize, config.sim.simSize)))
def testc_geoLgsPsf(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) config.wfss[1].lgs.propagationMode = "Geometric" lgs = LGS.LGS_Geometric(config.wfss[1], config) psf = lgs.getLgsPsf( numpy.zeros( (config.atmos.scrnNo, config.sim.simSize, config.sim.simSize)))
def test_fibreFrame(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) sci = SCI.singleModeFibre(config, 0, mask) sci.frame( numpy.ones((config.atmos.scrnNo, config.sim.scrnSize, config.sim.scrnSize)))
def make_mask(config): """ Generates a Soapy pupil mask Parameters: config (SoapyConfig): Config object describing Soapy simulation Returns: ndarray: 2-d pupil mask """ if config.tel.mask == "circle": mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) if config.tel.obsDiam != None: mask -= aotools.circle( config.tel.obsDiam * config.sim.pxlScale / 2., config.sim.simSize ) elif isinstance(config.tel.mask, str): maskHDUList = fits.open(config.tel.mask) mask = maskHDUList[0].data.copy() maskHDUList.close() logger.info('load mask "{}", of size: {}'.format(config.tel.mask, mask.shape)) if not numpy.array_equal(mask.shape, (config.sim.pupilSize,) * 2): # interpolate mask to pupilSize if not that size already mask = numpy.round(interp.zoom(mask, config.sim.pupilSize)) else: mask = config.tel.mask.copy() # Check its size is compatible. If its the pupil size, pad to sim size if (not numpy.array_equal(mask.shape, (config.sim.pupilSize,)*2) and not numpy.array_equal(mask.shape, (config.sim.simSize,)*2) ): raise ValueError("Mask Shape {} not compatible. Should be either `pupilSize` or `simSize`".format(mask.shape)) if mask.shape != (config.sim.simSize, )*2: mask = numpy.pad( mask, config.sim.simPad, mode="constant") return mask
def make_mask(config): """ Generates a Soapy pupil mask Parameters: config (SoapyConfig): Config object describing Soapy simulation Returns: ndarray: 2-d pupil mask """ if config.tel.mask == "circle": mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) if config.tel.obsDiam != None: mask -= aotools.circle( config.tel.obsDiam * config.sim.pxlScale / 2., config.sim.simSize) elif isinstance(config.tel.mask, str): maskHDUList = fits.open(config.tel.mask) mask = maskHDUList[0].data.copy() maskHDUList.close() logger.info('load mask "{}", of size: {}'.format( config.tel.mask, mask.shape)) if not numpy.array_equal(mask.shape, (config.sim.pupilSize, ) * 2): # interpolate mask to pupilSize if not that size already mask = numpy.round(interp.zoom(mask, config.sim.pupilSize)) else: mask = config.tel.mask.copy() # Check its size is compatible. If its the pupil size, pad to sim size if (not numpy.array_equal(mask.shape, (config.sim.pupilSize, ) * 2) and not numpy.array_equal(mask.shape, (config.sim.simSize, ) * 2)): raise ValueError( "Mask Shape {} not compatible. Should be either `pupilSize` or `simSize`" .format(mask.shape)) if mask.shape != (config.sim.simSize, ) * 2: mask = numpy.pad(mask, config.sim.simPad, mode="constant") return mask
def teste_physLgsPsf(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8_lgs-uplink.yaml")) config.wfss[1].lgs.propagationMode = "Physical" mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) lgs = LGS.LGS_Physical(config.wfss[1], config, nOutPxls=10) psf = lgs.getLgsPsf( numpy.zeros( (config.atmos.scrnNo, config.sim.simSize, config.sim.simSize)))
def test_sciFrame(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) sci = scienceinstrument.PSFCamera(config, 0, mask) sci.frame( numpy.ones((config.atmos.scrnNo, config.sim.scrnSize, config.sim.scrnSize)))
def strehl(phase): mask = aotools.circle(64, 128) N = 0.0 phase_mean = 0.0 for i in range(128): for j in range(128): if (mask[i, j] >= 0.001): N += 1 phase_mean += phase[i, j] phase_mean = phase_mean / N strehl = np.abs(np.mean(np.exp(1j * (phase - phase_mean))))**2 return strehl
def test_propagation_conserves_intensity(): screen = phasescreen.ft_phase_screen(0.16, 512, 4.2 / 512, 100, 0.01) # Input E Field E = numpy.exp(1j * screen) Em = E * circle(150, 512) sum1 = (abs(Em) ** 2).sum() prop1 = opticalpropagation.angularSpectrum(Em, 500e-9, 4.2 / 512, 4.2 / 512, 10000.) sum2 = (abs(prop1) ** 2).sum() assert numpy.allclose(sum1, sum2)
def test_slopecovmat_makecovmat_multithreaded(): threads = 2 n_wfs = 3 telescope_diameter = 8. nx_subaps = 10 n_layers = 3 layer_altitudes = numpy.linspace(0, 20000, n_layers) layer_r0s = [1] * n_layers layer_L0s = [25.] * n_layers asterism_radius = 10 subap_diameters = [telescope_diameter / nx_subaps] * n_wfs pupil_masks = [aotools.circle(nx_subaps / 2., nx_subaps)] * n_wfs gs_altitudes = [90000] * n_wfs gs_positions = [[asterism_radius, 0], [ numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius ], [ numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius ], [ -numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius ], [ -numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius ], [-asterism_radius, 0]] wfs_magnifications = [1.] * n_wfs pupil_offsets = [[0, 0]] * n_wfs wfs_rotations = [0] * n_wfs wfs_wavelengths = [550e-9] * n_wfs cov_mat = aotools.CovarianceMatrix(n_wfs, pupil_masks, telescope_diameter, subap_diameters, gs_altitudes, gs_positions, wfs_wavelengths, n_layers, layer_altitudes, layer_r0s, layer_L0s, threads) covariance_matrix_multithread = cov_mat.make_covariance_matrix() # Check consistant with single thread implementation cov_mat.threads = 1 covariance_matrix = cov_mat.make_covariance_matrix() assert numpy.array_equal(covariance_matrix, covariance_matrix_multithread)
def test_sciStrehl(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) sci = SCI.PSF(config, 0, mask) sci.frame( numpy.ones((config.atmos.scrnNo, config.sim.scrnSize, config.sim.scrnSize))) self.assertTrue(numpy.allclose(sci.instStrehl, 1.))
def test_PhysWfs(self): config = confParse.loadSoapyConfig( os.path.join(CONFIG_PATH, "sh_8x8.yaml")) config.wfss[0].propagationMode = "Physical" mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.WFS(config, mask=mask) wfs.frame( numpy.zeros((config.atmos.scrnNo, config.sim.scrnSize, config.sim.scrnSize)))
def __init__( self, soapy_config, n_wfs=0, mask=None): self.soapy_config = soapy_config self.config = self.wfsConfig = soapy_config.wfss[n_wfs] # For compatability self.lgsConfig = self.config.lgs # Sort out some required, static, parameters self.pupil_size = self.soapy_config.sim.pupilSize self.sim_size = self.soapy_config.sim.simSize self.phase_scale = 1./self.soapy_config.sim.pxlScale self.sim_pad = self.soapy_config.sim.simPad self.screen_size = self.soapy_config.sim.scrnSize self.telescope_diameter = self.soapy_config.tel.telDiam self.wavelength = self.config.wavelength self.threads = self.soapy_config.sim.threads # If supplied use the mask if numpy.any(mask): self.mask = mask # Else we'll just make a circle else: self.mask = aotools.circle(self.pupil_size/2., self.sim_size) self.iMat = False # Init the line of sight self.initLos() self.calcInitParams() # If GS not at infinity, find meta-pupil radii for each layer # if self.config.GSHeight != 0: # self.radii = self.los.findMetaPupilSizes(self.config.GSHeight) # else: # self.radii = None # Init LGS, FFTs and allocate some data arrays self.initFFTs() if self.lgsConfig and self.config.lgs: self.initLGS() self.allocDataArrays() self.calcTiltCorrect() self.getStatic() # base WFS makes no measurements.... self.n_measurements = 0
def setMask(self, mask): """ Sets the pupil mask as seen by the WFS. This method can be called during a simulation """ # If supplied use the mask if numpy.any(mask): self.mask = mask else: self.mask = aotools.circle( self.pupil_size/2., self.sim_size, )
def test_set_valid_actuators(): """ Tests that when you set the "valid actuators", the DM computes how many valid actuators there are correctly """ config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize/2., config.sim.simSize) wfs = WFS.ShackHartmann(config, mask=mask) dm = DM.DM(config, n_dm=1, wfss=[wfs], mask=mask) valid_actuators = numpy.ones(dm.n_acts, dtype=int) valid_actuators[0] = valid_actuators[-1] = 0 dm.valid_actuators = valid_actuators assert dm.n_valid_actuators == (dm.n_acts - 2)
def test_slopecovmat_makecovmat_multithreaded(): threads = 2 n_wfs = 3 telescope_diameter = 8. nx_subaps = 10 n_layers = 3 layer_altitudes = numpy.linspace(0, 20000, n_layers) layer_r0s = [1] * n_layers layer_L0s = [25.] * n_layers asterism_radius = 10 subap_diameters = [telescope_diameter / nx_subaps] * n_wfs pupil_masks = [aotools.circle(nx_subaps / 2., nx_subaps)] * n_wfs gs_altitudes = [90000] * n_wfs gs_positions = [ [asterism_radius, 0], [numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-asterism_radius, 0]] wfs_magnifications = [1.] * n_wfs pupil_offsets = [[0, 0]] * n_wfs wfs_rotations = [0] * n_wfs wfs_wavelengths = [550e-9] * n_wfs cov_mat = aotools.CovarianceMatrix(n_wfs, pupil_masks, telescope_diameter, subap_diameters, gs_altitudes, gs_positions, wfs_wavelengths, n_layers, layer_altitudes, layer_r0s, layer_L0s, threads) covariance_matrix_multithread = cov_mat.make_covariance_matrix() # Check consistant with single thread implementation cov_mat.threads = 1 covariance_matrix = cov_mat.make_covariance_matrix() assert numpy.array_equal(covariance_matrix, covariance_matrix_multithread)
def test_covtomorecon(): threads = 1 n_wfs = 3 telescope_diameter = 8. nx_subaps = 10 n_layers = 3 layer_altitudes = numpy.linspace(0, 20000, n_layers) layer_r0s = [1] * n_layers layer_L0s = [25.] * n_layers asterism_radius = 10 subap_diameters = [telescope_diameter / nx_subaps] * n_wfs pupil_masks = [aotools.circle(nx_subaps / 2., nx_subaps)] * n_wfs gs_altitudes = [90000] * n_wfs gs_positions = [ [asterism_radius, 0], [numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-asterism_radius, 0]] wfs_magnifications = [1.] * n_wfs pupil_offsets = [[0, 0]] * n_wfs wfs_rotations = [0] * n_wfs wfs_wavelengths = [550e-9] * n_wfs cov_mat = aotools.CovarianceMatrix(n_wfs, pupil_masks, telescope_diameter, subap_diameters, gs_altitudes, gs_positions, wfs_wavelengths, n_layers, layer_altitudes, layer_r0s, layer_L0s, threads) cov_mat.make_covariance_matrix() tomo_recon = cov_mat.make_tomographic_reconstructor()
def testc_initLegacySHWfs(self): config = confParse.loadSoapyConfig(os.path.join(CONFIG_PATH, "sh_8x8.yaml")) mask = aotools.circle(config.sim.pupilSize / 2., config.sim.simSize) wfs = WFS.ShackHartmannLegacy(config, mask=mask)
N = 1 threads = 20 n_wfs = 6 telescope_diameter = 8. nx_subaps = 10 n_layers = 3 layer_altitudes = numpy.linspace(0, 20000, n_layers) layer_r0s = [1] * n_layers layer_L0s = [25.] * n_layers asterism_radius = 10 subap_diameters = [telescope_diameter / nx_subaps] * n_wfs pupil_masks = [aotools.circle(nx_subaps / 2., nx_subaps)] * n_wfs gs_altitudes = [90000] * n_wfs gs_positions = [ [asterism_radius, 0], [numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, numpy.cos(numpy.pi / 3.) * asterism_radius], [-numpy.sin(numpy.pi / 3.) * asterism_radius, -numpy.cos(numpy.pi / 3.) * asterism_radius], [-asterism_radius, 0]] wfs_magnifications = [1.] * n_wfs pupil_offsets = [[0, 0]] * n_wfs wfs_rotations = [0] * n_wfs wfs_wavelengths = [550e-9] * n_wfs t1 = time.time() for i in range(N):
def test_photons_per_mag(): mask = circle(2, 5) photons = astronomy.photons_per_mag(5.56, mask, 0.5, 0.3, 10) assert type(photons) == float
def test_photons_per_band(): photons = astronomy.photons_per_band(5.56, circle(2, 5), 0.5, 0.001) assert type(photons) == float