def test_frozen_flow(): """Test that frozen flow screen really is frozen, i.e., phase(x=0, t=0) == phase(x=v*t, t=t).""" rng = galsim.BaseDeviate(1234) vx = 1.0 # m/s t = 0.05 # s x = vx*t # 0.05 m dx = x alt = x/1000 # -> 0.00005 km; silly example, but yields exact results... screen = galsim.AtmosphericScreen(1.0, dx, alt, vx=vx, rng=rng) with assert_warns(galsim.GalSimWarning): aper = galsim.Aperture(diam=1, pupil_plane_size=20., pupil_plane_scale=20./dx) wf0 = screen.wavefront(aper.u, aper.v, None, theta0) dwdu0, dwdv0 = screen.wavefront_gradient(aper.u, aper.v, t=screen._time) screen._seek(t) assert screen._time == t, "Wrong time for AtmosphericScreen" wf1 = screen.wavefront(aper.u, aper.v, None, theta=(45*galsim.degrees, 0*galsim.degrees)) dwdu1, dwdv1 = screen.wavefront_gradient(aper.u, aper.v, t=screen._time, theta=(45*galsim.degrees, 0*galsim.degrees)) np.testing.assert_array_almost_equal(wf0, wf1, 5, "Flow is not frozen") np.testing.assert_array_almost_equal(dwdu0, dwdu1, 5, "Flow is not frozen") np.testing.assert_array_almost_equal(dwdu0, dwdu1, 5, "Flow is not frozen") # We should be able to rewind too. screen._seek(0.01) np.testing.assert_allclose(screen._time, 0.01, err_msg="Wrong time for AtmosphericScreen") wf2 = screen.wavefront(aper.u, aper.v, 0.0) np.testing.assert_array_almost_equal(wf0, wf2, 5, "Flow is not frozen")
def test_input(): """Check that exceptions are raised for invalid input""" # Specifying only one of alpha and time_step is an error. try: np.testing.assert_raises(ValueError, galsim.AtmosphericScreen, screen_size=10.0, time_step=0.01) np.testing.assert_raises(ValueError, galsim.AtmosphericScreen, screen_size=10.0, alpha=0.997) except ImportError: print('The assert_raises tests require nose') # But specifying both is alright. galsim.AtmosphericScreen(screen_size=10.0, alpha=0.997, time_step=0.01) # Try some variations for Atmosphere try: np.testing.assert_raises(ValueError, galsim.Atmosphere, screen_size=10.0, altitude=[0., 1.], r0_500=[0.2, 0.3, 0.2]) np.testing.assert_raises(ValueError, galsim.Atmosphere, screen_size=10.0, r0_500=[0.4, 0.4, 0.4], r0_weights=[0.1, 0.3, 0.6]) except ImportError: print('The assert_raises tests require nose')
def test_structure_function(): """Test that AtmosphericScreen generates approximately the right structure function for infinite outer scale. """ rng = galsim.BaseDeviate(4815162342) r0_500 = 0.2 L0 = None screen_scale = 0.05 screen_size = 100.0 # Theoretical pure Kolmogorov structure function (at 500 nm!): D_kolm = lambda r: 6.8839 * (r/r0_500)**(5./3) atm = galsim.AtmosphericScreen(screen_size=screen_size, screen_scale=screen_scale, r0_500=r0_500, L0=L0, rng=rng) phase = atm.tab2d.table.getVals()[:-1, :-1].copy() phase *= 2 * np.pi / 500.0 # nm -> radians im = galsim.Image(phase, scale=screen_scale) D_sim = galsim.utilities.structure_function(im) print("r D_kolm D_sim") for r in [0.5, 2.0, 5.0]: # Only check values far from the screen size and scale. # We're only attempting to verify that we haven't missed a factor of 2 or pi or # something like that here, so set the rtol below to be *very* forgiving. Since the # structure function varies quite quickly as r**(5./3), this is still a useful test. # For the parameters above (including the random seed), D_kolm(r) and D_sim(r) are actually # consistent at about the 15% level in the test below. It's difficult to predict how # consistent they *should* be though, since the simulated structure function estimate is # sensitive to resolution and edge effects, as well as the particular realization of the # field. print(r, D_kolm(r), D_sim(r)) np.testing.assert_allclose(D_kolm(r), D_sim(r), rtol=0.5, err_msg="Simulated structure function not close to prediction.")
def test_atm_screen_size(): """Test for consistent AtmosphericScreen size and scale.""" screen_size = 10.0 screen_scale = 0.1 atm = galsim.AtmosphericScreen(screen_size=screen_size, screen_scale=screen_scale) # AtmosphericScreen will preserve screen_scale, but will adjust screen_size as necessary to get # a good FFT size. assert atm.screen_scale == screen_scale assert screen_size < atm.screen_size < 1.5*screen_size np.testing.assert_equal(atm.screen_size, atm.npix * atm.screen_scale, "Inconsistent atmospheric screen size and scale.")
def test_structure_function(): """Test that AtmosphericScreen generates the right structure function. """ if __name__ == '__main__': L0s = [10.0, 25.0, 100.0] screen_size = 300.0 else: L0s = [10.0] screen_size = 100.0 rng = galsim.BaseDeviate(4815162342) lam = 500.0 r0_500 = 0.2 screen_scale = 0.05 for L0 in L0s: screen = galsim.AtmosphericScreen(screen_size=screen_size, screen_scale=screen_scale, r0_500=r0_500, L0=L0, rng=rng) screen.instantiate() vk = galsim.VonKarman(lam=lam, r0=r0_500 * (lam / 500.0)**1.2, L0=L0) phase = screen._tab2d.getVals( )[:-1, :-1] * 2 * np.pi / 500.0 # nm -> radians var = np.var(phase) # Conan 2008 eq 16 # 0.0863 ~= Gamma(11/6) Gamma(5/6) / (2 pi^(8/3)) (24/5 Gamma(6/5))^(5/6) expected_var = 0.0863 * (r0_500 / L0)**(-5 / 3.) np.testing.assert_allclose( var, expected_var, rtol=0.025, err_msg="Simulated variance disagrees with expected variance.") im = galsim.Image(phase, scale=screen_scale) D_sim = galsim.utilities.structure_function(im) print("r D_VK D_sim") for r in [0.1, 1.0, 10.0]: analytic_SF = vk._structure_function(r) simulated_SF = D_sim(r) print(r, analytic_SF, simulated_SF) np.testing.assert_allclose( analytic_SF, simulated_SF, rtol=0.05, err_msg="Simulated structure function not close to prediction." )
def test_frozen_flow(): """Test that frozen flow screen really is frozen, i.e., phase(x=0, t=0) == phase(x=v*t, t=t).""" rng = galsim.BaseDeviate(1234) vx = 1.0 # m/s dt = 0.01 # s t = 0.05 # s x = vx*t # 0.05 m dx = x alt = x/1000 # -> 0.00005 km; silly example, but yields exact results... screen = galsim.AtmosphericScreen(1.0, dx, alt, vx=vx, time_step=dt, rng=rng) import warnings with warnings.catch_warnings(): warnings.simplefilter("ignore") aper = galsim.Aperture(diam=1, pupil_plane_size=20., pupil_plane_scale=20./dx) wf0 = screen.wavefront(aper) screen.advance_by(t) wf1 = screen.wavefront(aper, theta=(45*galsim.degrees, 0*galsim.degrees)) np.testing.assert_array_almost_equal(wf0, wf1, 5, "Flow is not frozen")
def test_ne(): """Test Apertures, PhaseScreens, PhaseScreenLists, and PhaseScreenPSFs for not-equals.""" pupil_plane_im = galsim.fits.read(os.path.join(imgdir, pp_file)) # Test galsim.Aperture __ne__ objs = [galsim.Aperture(diam=1.0), galsim.Aperture(diam=1.1), galsim.Aperture(diam=1.0, oversampling=1.5), galsim.Aperture(diam=1.0, pad_factor=1.5), galsim.Aperture(diam=1.0, circular_pupil=False), galsim.Aperture(diam=1.0, obscuration=0.3), galsim.Aperture(diam=1.0, nstruts=3), galsim.Aperture(diam=1.0, nstruts=3, strut_thick=0.2), galsim.Aperture(diam=1.0, nstruts=3, strut_angle=15*galsim.degrees), galsim.Aperture(diam=1.0, pupil_plane_im=pupil_plane_im), galsim.Aperture(diam=1.0, pupil_plane_im=pupil_plane_im, pupil_angle=10.0*galsim.degrees)] all_obj_diff(objs) # Test AtmosphericScreen __ne__ rng = galsim.BaseDeviate(1) objs = [galsim.AtmosphericScreen(10.0, rng=rng), galsim.AtmosphericScreen(1.0, rng=rng), galsim.AtmosphericScreen(10.0, rng=rng, vx=1.0), galsim.AtmosphericScreen(10.0, rng=rng, vy=1.0), galsim.AtmosphericScreen(10.0, rng=rng, alpha=0.999, time_step=0.01), galsim.AtmosphericScreen(10.0, rng=rng, altitude=1.0), galsim.AtmosphericScreen(10.0, rng=rng, alpha=0.999, time_step=0.02), galsim.AtmosphericScreen(10.0, rng=rng, alpha=0.998, time_step=0.02), galsim.AtmosphericScreen(10.0, rng=rng, r0_500=0.1), galsim.AtmosphericScreen(10.0, rng=rng, L0=10.0), galsim.AtmosphericScreen(10.0, rng=rng, vx=10.0), ] all_obj_diff(objs) objs.append(galsim.AtmosphericScreen(10.0, rng=rng)) objs[-1].instantiate() # Should still all be __ne__, but first and last will have the same hash this time. assert hash(objs[0]) == hash(objs[-1]) all_obj_diff(objs, check_hash=False) # Test OpticalScreen __ne__ objs = [galsim.OpticalScreen(diam=1.0), galsim.OpticalScreen(diam=1.0, tip=1.0), galsim.OpticalScreen(diam=1.0, tilt=1.0), galsim.OpticalScreen(diam=1.0, defocus=1.0), galsim.OpticalScreen(diam=1.0, astig1=1.0), galsim.OpticalScreen(diam=1.0, astig2=1.0), galsim.OpticalScreen(diam=1.0, coma1=1.0), galsim.OpticalScreen(diam=1.0, coma2=1.0), galsim.OpticalScreen(diam=1.0, trefoil1=1.0), galsim.OpticalScreen(diam=1.0, trefoil2=1.0), galsim.OpticalScreen(diam=1.0, spher=1.0), galsim.OpticalScreen(diam=1.0, spher=1.0, lam_0=100.0), galsim.OpticalScreen(diam=1.0, aberrations=[0,0,1.1]), # tip=1.1 ] all_obj_diff(objs) # Test PhaseScreenList __ne__ atm = galsim.Atmosphere(10.0, vx=1.0) objs = [galsim.PhaseScreenList(atm), galsim.PhaseScreenList(objs), # Reuse list of OpticalScreens above galsim.PhaseScreenList(objs[0:2])] all_obj_diff(objs) # Test PhaseScreenPSF __ne__ psl = galsim.PhaseScreenList(atm) objs = [galsim.PhaseScreenPSF(psl, 500.0, exptime=0.03, diam=1.0)] objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0)] objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.1)] objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, flux=1.1)] objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, interpolant='linear')] stepk = objs[0].stepk maxk = objs[0].maxk objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, _force_stepk=stepk/1.5)] objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, _force_maxk=maxk*2.0)] all_obj_diff(objs)
def test_phase_screen_list(): """Test list-like behaviors of PhaseScreenList.""" rng = galsim.BaseDeviate(1234) rng2 = galsim.BaseDeviate(123) aper = galsim.Aperture(diam=1.0) ar1 = galsim.AtmosphericScreen(10, 1, alpha=0.997, L0=None, time_step=0.01, rng=rng) assert ar1._time == 0.0, "AtmosphericScreen initialized with non-zero time." do_pickle(ar1) do_pickle(ar1, func=lambda x: x.wavefront(aper.u, aper.v, 0.0).sum()) do_pickle(ar1, func=lambda x: np.sum(x.wavefront_gradient(aper.u, aper.v, 0.0))) t = np.empty_like(aper.u) ud = galsim.UniformDeviate(rng.duplicate()) ud.generate(t.ravel()) t *= 0.1 # Only do a few boiling steps do_pickle(ar1, func=lambda x: x.wavefront(aper.u, aper.v, t).sum()) do_pickle(ar1, func=lambda x: np.sum(x.wavefront_gradient(aper.u, aper.v, t))) # Try seeking backwards assert ar1._time > 0.0 ar1._seek(0.0) # But not before t=0.0 with assert_raises(ValueError): ar1._seek(-1.0) # Check that L0=np.inf and L0=None yield the same thing here too. ar2 = galsim.AtmosphericScreen(10, 1, alpha=0.997, L0=np.inf, time_step=0.01, rng=rng) # Before ar2 is instantiated, it's unequal to ar1, even though they were initialized with the # same arguments (the hashes are the same though). After both have been instantiated with the # same range of k (ar1 through use of .wavefront() and ar2 explicitly), then they are equal ( # and the hashes are still the same). assert hash(ar1) == hash(ar2) assert ar1 != ar2 ar2.instantiate() assert ar1 == ar2 assert hash(ar1) == hash(ar2) # Create a couple new screens with different types/parameters ar2 = galsim.AtmosphericScreen(10, 1, alpha=0.995, time_step=0.015, rng=rng2) ar2.instantiate() assert ar1 != ar2 ar3 = galsim.OpticalScreen(diam=1.0, aberrations=[0, 0, 0, 0, 0, 0, 0, 0, 0.1], obscuration=0.3, annular_zernike=True) do_pickle(ar3) do_pickle(ar3, func=lambda x:x.wavefront(aper.u, aper.v).sum()) do_pickle(ar3, func=lambda x:np.sum(x.wavefront_gradient(aper.u, aper.v))) atm = galsim.Atmosphere(screen_size=30.0, altitude=[0.0, 1.0], speed=[1.0, 2.0], direction=[0.0*galsim.degrees, 120*galsim.degrees], r0_500=0.15, rng=rng) atm.append(ar3) do_pickle(atm) do_pickle(atm, func=lambda x:x.wavefront(aper.u, aper.v, 0.0, theta0).sum()) do_pickle(atm, func=lambda x:np.sum(x.wavefront_gradient(aper.u, aper.v, 0.0))) # testing append, extend, __getitem__, __setitem__, __delitem__, __eq__, __ne__ atm2 = atm[:-1] # Refers to first n-1 screens assert atm != atm2 # Append a different screen to the end of atm2 atm2.append(ar2) assert atm != atm2 # Swap the last screen in atm2 for the one that should match atm. del atm2[-1] atm2.append(atm[-1]) assert atm == atm2 with assert_raises(TypeError): atm['invalid'] with assert_raises(IndexError): atm[3] # Test building from empty PhaseScreenList atm3 = galsim.PhaseScreenList() atm3.extend(atm2) assert atm == atm3 # Test constructing from existing PhaseScreenList atm4 = galsim.PhaseScreenList(atm3) del atm4[-1] assert atm != atm4 atm4.append(atm[-1]) assert atm == atm4 # Test swap atm4[0], atm4[1] = atm4[1], atm4[0] assert atm != atm4 atm4[0], atm4[1] = atm4[1], atm4[0] assert atm == atm4 wf = atm.wavefront(aper.u, aper.v, None, theta0) wf2 = atm2.wavefront(aper.u, aper.v, None, theta0) wf3 = atm3.wavefront(aper.u, aper.v, None, theta0) wf4 = atm4.wavefront(aper.u, aper.v, None, theta0) np.testing.assert_array_equal(wf, wf2, "PhaseScreenLists are inconsistent") np.testing.assert_array_equal(wf, wf3, "PhaseScreenLists are inconsistent") np.testing.assert_array_equal(wf, wf4, "PhaseScreenLists are inconsistent") # Check copy import copy # Shallow copy copies by reference. atm5 = copy.copy(atm) assert atm[0] == atm5[0] assert atm[0] is atm5[0] atm._seek(1.0) assert atm[0]._time == 1.0, "Wrong time for AtmosphericScreen" assert atm[0] == atm5[0] assert atm[0] is atm5[0] # Deepcopy actually makes an indepedent object in memory. atm5 = copy.deepcopy(atm) assert atm[0] == atm5[0] assert atm[0] is not atm5[0] atm._seek(2.0) assert atm[0]._time == 2.0, "Wrong time for AtmosphericScreen" # But we still get equality, since this doesn't depend on mutable internal state: assert atm[0] == atm5[0] # Constructor should accept both list and indiv layers as arguments. atm6 = galsim.PhaseScreenList(atm[0]) atm7 = galsim.PhaseScreenList([atm[0]]) assert atm6 == atm7 do_pickle(atm6, func=lambda x:x.wavefront(aper.u, aper.v, None, theta0).sum()) do_pickle(atm6, func=lambda x:np.sum(x.wavefront_gradient(aper.u, aper.v, 0.0))) atm6 = galsim.PhaseScreenList(atm[0], atm[1]) atm7 = galsim.PhaseScreenList([atm[0], atm[1]]) atm8 = galsim.PhaseScreenList(atm[0:2]) # Slice returns PhaseScreenList, so this works too. assert atm6 == atm7 assert atm6 == atm8 # Check some actual derived PSFs too, not just phase screens. Use a small pupil_plane_size and # relatively large pupil_plane_scale to speed up the unit test. atm._reset() assert atm[0]._time == 0.0, "Wrong time for AtmosphericScreen" kwargs = dict(exptime=0.05, time_step=0.01, diam=1.1, lam=1000.0) psf = atm.makePSF(**kwargs) do_pickle(psf) do_pickle(psf, func=lambda x:x.drawImage(nx=20, ny=20, scale=0.1)) psf2 = atm2.makePSF(**kwargs) psf3 = atm3.makePSF(**kwargs) psf4 = atm4.makePSF(**kwargs) np.testing.assert_array_equal(psf, psf2, "PhaseScreenPSFs are inconsistent") np.testing.assert_array_equal(psf, psf3, "PhaseScreenPSFs are inconsistent") np.testing.assert_array_equal(psf, psf4, "PhaseScreenPSFs are inconsistent") # Check errors in u,v,t shapes. assert_raises(ValueError, ar1.wavefront, aper.u, aper.v[:-1,:-1]) assert_raises(ValueError, ar1.wavefront, aper.u[:-1,:-1], aper.v) assert_raises(ValueError, ar1.wavefront, aper.u, aper.v, 0.1 * aper.u[:-1,:-1]) assert_raises(ValueError, ar1.wavefront_gradient, aper.u, aper.v[:-1,:-1]) assert_raises(ValueError, ar1.wavefront_gradient, aper.u[:-1,:-1], aper.v) assert_raises(ValueError, ar1.wavefront_gradient, aper.u, aper.v, 0.1 * aper.u[:-1,:-1]) assert_raises(ValueError, ar3.wavefront, aper.u, aper.v[:-1,:-1]) assert_raises(ValueError, ar3.wavefront, aper.u[:-1,:-1], aper.v) assert_raises(ValueError, ar3.wavefront_gradient, aper.u, aper.v[:-1,:-1]) assert_raises(ValueError, ar3.wavefront_gradient, aper.u[:-1,:-1], aper.v)
def test_ne(): """Test Apertures, PhaseScreens, PhaseScreenLists, and PhaseScreenPSFs for not-equals.""" import copy pupil_plane_im = galsim.fits.read(os.path.join(imgdir, pp_file)) # Test galsim.Aperture __ne__ objs = [galsim.Aperture(diam=1.0), galsim.Aperture(diam=1.1), galsim.Aperture(diam=1.0, oversampling=1.5), galsim.Aperture(diam=1.0, pad_factor=1.5), galsim.Aperture(diam=1.0, circular_pupil=False), galsim.Aperture(diam=1.0, obscuration=0.3), galsim.Aperture(diam=1.0, nstruts=3), galsim.Aperture(diam=1.0, nstruts=3, strut_thick=0.2), galsim.Aperture(diam=1.0, nstruts=3, strut_angle=15*galsim.degrees), galsim.Aperture(diam=1.0, pupil_plane_im=pupil_plane_im), galsim.Aperture(diam=1.0, pupil_plane_im=pupil_plane_im, pupil_angle=10.0*galsim.degrees)] all_obj_diff(objs) # Test AtmosphericScreen __ne__ rng = galsim.BaseDeviate(1) objs = [galsim.AtmosphericScreen(10.0, rng=rng), galsim.AtmosphericScreen(10.0, rng=rng, vx=1.0), galsim.AtmosphericScreen(10.0, rng=rng, vx=1.0), # advance this one below galsim.AtmosphericScreen(10.0, rng=rng, vy=1.0), galsim.AtmosphericScreen(10.0, rng=rng, alpha=0.999), galsim.AtmosphericScreen(10.0, rng=rng, altitude=1.0), galsim.AtmosphericScreen(10.0, rng=rng, time_step=0.1), galsim.AtmosphericScreen(10.0, rng=rng, r0_500=0.1), galsim.AtmosphericScreen(10.0, rng=rng, L0=10.0), galsim.AtmosphericScreen(10.0, rng=rng, vx=10.0), ] objs[2].advance() all_obj_diff(objs) # Test OpticalScreen __ne__ objs = [galsim.OpticalScreen(), galsim.OpticalScreen(tip=1.0), galsim.OpticalScreen(tilt=1.0), galsim.OpticalScreen(defocus=1.0), galsim.OpticalScreen(astig1=1.0), galsim.OpticalScreen(astig2=1.0), galsim.OpticalScreen(coma1=1.0), galsim.OpticalScreen(coma2=1.0), galsim.OpticalScreen(trefoil1=1.0), galsim.OpticalScreen(trefoil2=1.0), galsim.OpticalScreen(spher=1.0), galsim.OpticalScreen(spher=1.0, lam_0=100.0), galsim.OpticalScreen(aberrations=[0,0,1.1]), # tip=1.1 ] all_obj_diff(objs) # Test PhaseScreenList __ne__ atm = galsim.Atmosphere(10.0, vx=1.0) objs = [galsim.PhaseScreenList(atm), galsim.PhaseScreenList(copy.deepcopy(atm)), # advance down below galsim.PhaseScreenList(objs), # Reuse list of OpticalScreens above galsim.PhaseScreenList(objs[0:2])] objs[1].advance() all_obj_diff(objs) # Test PhaseScreenPSF __ne__ objs[0].reset() psl = galsim.PhaseScreenList(atm) objs = [galsim.PhaseScreenPSF(psl, 500.0, exptime=0.03, diam=1.0), galsim.PhaseScreenPSF(psl, 500.0, exptime=0.03, diam=1.0)] # advanced so differs psl.reset() objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0)] psl.reset() objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.1)] psl.reset() objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, flux=1.1)] psl.reset() objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, interpolant='linear')] stepk = objs[0].stepK() maxk = objs[0].maxK() psl.reset() objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, _force_stepk=stepk/1.5)] psl.reset() objs += [galsim.PhaseScreenPSF(psl, 700.0, exptime=0.03, diam=1.0, _force_maxk=maxk*2.0)] all_obj_diff(objs)
def test_phase_screen_list(): """Test list-like behaviors of PhaseScreenList.""" rng = galsim.BaseDeviate(1234) rng2 = galsim.BaseDeviate(123) aper = galsim.Aperture(diam=1.0) ar1 = galsim.AtmosphericScreen(10, 1, alpha=0.997, L0=None, rng=rng) do_pickle(ar1) do_pickle(ar1, func=lambda x: x.tab2d(12.3, 45.6)) do_pickle(ar1, func=lambda x: x.wavefront(aper).sum()) # Check that L0=np.inf and L0=None yield the same thing here too. ar2 = galsim.AtmosphericScreen(10, 1, alpha=0.997, L0=np.inf, rng=rng) assert ar1 == ar2 # Create a couple new screens with different types/parameters ar2 = galsim.AtmosphericScreen(10, 1, alpha=0.995, rng=rng2) assert ar1 != ar2 ar3 = galsim.OpticalScreen(aberrations=[0, 0, 0, 0, 0, 0, 0, 0, 0.1]) do_pickle(ar3) do_pickle(ar3, func=lambda x:x.wavefront(aper).sum()) atm = galsim.Atmosphere(screen_size=30.0, altitude=[0.0, 1.0], speed=[1.0, 2.0], direction=[0.0*galsim.degrees, 120*galsim.degrees], r0_500=0.15, rng=rng) atm.append(ar3) do_pickle(atm) do_pickle(atm, func=lambda x:x.wavefront(aper).sum()) # testing append, extend, __getitem__, __setitem__, __delitem__, __eq__, __ne__ atm2 = galsim.PhaseScreenList(atm[:-1]) # Refers to first n-1 screens assert atm != atm2 # Append a different screen to the end of atm2 atm2.append(ar2) assert atm != atm2 # Swap the last screen in atm2 for the one that should match atm. del atm2[-1] atm2.append(atm[-1]) assert atm == atm2 # Test building from empty PhaseScreenList atm3 = galsim.PhaseScreenList() atm3.extend(atm2) assert atm == atm2 # Test constructing from existing PhaseScreenList atm4 = galsim.PhaseScreenList(atm3) del atm4[-1] assert atm != atm4 atm4.append(atm[-1]) assert atm == atm4 # Test swap atm4[0], atm4[1] = atm4[1], atm4[0] assert atm != atm4 atm4[0], atm4[1] = atm4[1], atm4[0] assert atm == atm4 wf = atm.wavefront(aper) wf2 = atm2.wavefront(aper) wf3 = atm3.wavefront(aper) wf4 = atm4.wavefront(aper) np.testing.assert_array_equal(wf, wf2, "PhaseScreenLists are inconsistent") np.testing.assert_array_equal(wf, wf3, "PhaseScreenLists are inconsistent") np.testing.assert_array_equal(wf, wf4, "PhaseScreenLists are inconsistent") # Check copy import copy # Shallow copy copies by reference. atm5 = copy.copy(atm) assert atm[0] == atm5[0] assert atm[0] is atm5[0] atm.advance() assert atm[0] == atm5[0] assert atm[0] is atm5[0] # Deepcopy actually makes an indepedent object in memory. atm5 = copy.deepcopy(atm) assert atm[0] == atm5[0] assert atm[0] is not atm5[0] atm.advance() assert atm[0] != atm5[0] # Constructor should accept both list and indiv layers as arguments. atm6 = galsim.PhaseScreenList(atm[0]) atm7 = galsim.PhaseScreenList([atm[0]]) assert atm6 == atm7 atm6 = galsim.PhaseScreenList(atm[0], atm[1]) atm7 = galsim.PhaseScreenList([atm[0], atm[1]]) atm8 = galsim.PhaseScreenList(atm[0:2]) # Slice returns PhaseScreenList, so this works too. assert atm6 == atm7 assert atm6 == atm8 # Check some actual derived PSFs too, not just phase screens. Use a small pupil_plane_size and # relatively large pupil_plane_scale to speed up the unit test. atm.advance_by(1.0) do_pickle(atm) atm.reset() kwargs = dict(exptime=0.06, diam=1.0, lam=1000.0) psf = atm.makePSF(**kwargs) do_pickle(psf) do_pickle(psf, func=lambda x:x.drawImage(nx=20, ny=20, scale=0.1)) # Need to reset atm2 since both atm and atm2 reference the same layer objects (not copies). # Not sure if this is a feature or a bug, but it's also how regular python lists work. atm2.reset() psf2 = atm2.makePSF(**kwargs) atm3.reset() psf3 = atm3.makePSF(**kwargs) atm4.reset() psf4 = atm4.makePSF(**kwargs) np.testing.assert_array_equal(psf, psf2, "PhaseScreenPSFs are inconsistent") np.testing.assert_array_equal(psf, psf3, "PhaseScreenPSFs are inconsistent") np.testing.assert_array_equal(psf, psf4, "PhaseScreenPSFs are inconsistent")