def structure_function(image): """Estimate the angularly-averaged structure function of a 2D random field. The angularly-averaged structure function D(r) of the 2D field phi is defined as: D(|r|) = <|phi(x) - phi(x+r)|^2> where the x and r on the RHS are 2D vectors, but the |r| on the LHS is just a scalar length. @param image Image containing random field realization. The `.scale` attribute here *is* used in the calculation. If it's `None`, then the code will use 1.0 for the scale. @returns A python callable mapping a separation length r to the estimate of the structure function D(r). """ array = image.array nx, ny = array.shape scale = image.scale if scale is None: scale = 1.0 # The structure function can be derived from the correlation function B(r) as: # D(r) = 2 * [B(0) - B(r)] corr = np.fft.ifft2(np.abs(np.fft.fft2(np.fft.fftshift(array)))**2).real / (nx * ny) # Check that the zero-lag correlation function is equal to the variance before doing the # ifftshift. assert (corr[0, 0] / np.var(array) - 1.0) < 1e-6 corr = np.fft.ifftshift(corr) x = scale * (np.arange(nx) - nx//2) y = scale * (np.arange(ny) - ny//2) tab = galsim.LookupTable2D(x, y, corr) thetas = np.arange(0., 2*np.pi, 100) # Average over these angles. return lambda r: 2*(tab(0.0, 0.0) - np.mean(tab(r*np.cos(thetas), r*np.sin(thetas))))
def shrink_layer(layer, factor): tab2d = layer._tab2d orig = tab2d.f[:-1, :-1] new = orig[::factor, ::factor] ret = galsim.AtmosphericScreen.__new__(galsim.AtmosphericScreen) ret.npix = new.shape[0] ret.screen_scale = layer.screen_scale * factor ret.screen_size = layer.screen_size ret.altitude = layer.altitude ret.time_step = layer.time_step ret.r0_500 = layer.r0_500 ret.L0 = layer.L0 ret.vx = layer.vx ret.vy = layer.vy ret.alpha = layer.alpha ret._time = layer._time ret._orig_rng = layer._orig_rng.duplicate() ret.dynamic = layer.dynamic ret.reversible = layer.reversible ret.rng = layer.rng.duplicate() ret._xs = layer._xs[::factor] ret._ys = layer._ys[::factor] ret._tab2d = galsim.LookupTable2D(ret._xs, ret._ys, new, interpolant='linear', edge_mode='wrap') ret.kmin = layer.kmin ret.kmax = layer.kmax return ret
def _seek(self, t): """Set layer's internal clock to time t.""" if t == self._time: return if not self.reversible: # Can't reverse, so reset and move forward. if t < self._time: if t < 0.0: raise ValueError( "Can't rewind irreversible screen to t < 0.0") self._reset() # Find number of boiling updates we need to perform. previous_update_number = int(self._time // self.time_step) final_update_number = int(t // self.time_step) n_updates = final_update_number - previous_update_number if n_updates > 0: for _ in range(n_updates): self._screen *= self.alpha self._screen += np.sqrt( 1. - self.alpha**2) * self._random_screen() self._tab2d = galsim.LookupTable2D(self._xs, self._ys, self._screen, edge_mode='wrap') self._time = float(t)
def advance(self): """Advance phase screen realization by self.time_step.""" # Moving the origin of the aperture in the opposite direction of the wind is equivalent to # moving the screen with the wind. self.origin -= (self.vx*self.time_step, self.vy*self.time_step) # "Boil" the atmsopheric screen if alpha not 1. if self.alpha != 1.0: self.screen = self.alpha*self.screen + np.sqrt(1.-self.alpha**2)*self._random_screen() self.tab2d = galsim.LookupTable2D(self._xs, self._ys, self.screen, edge_mode='wrap')
def _reset(self): """Reset phase screen back to time=0.""" self.rng = self._orig_rng.duplicate() self._time = 0.0 # Only need to reset/create tab2d if not frozen or doesn't already exist if not self.reversible or not hasattr(self, '_tab2d'): self._screen = self._random_screen() self._xs = np.linspace(-0.5*self.screen_size, 0.5*self.screen_size, self.npix, endpoint=False) self._ys = self._xs self._tab2d = galsim.LookupTable2D(self._xs, self._ys, self._screen, edge_mode='wrap')
def test_ne(): """ Check that inequality works as expected.""" # These should all compare as unequal. x = [1, 2, 3] f = [4, 5, 6] x2 = [1.1, 2.2, 3.3] f2 = [4.4, 5.5, 6.6] lts = [ galsim.LookupTable(x, f), galsim.LookupTable(x, f2), galsim.LookupTable(x2, f), galsim.LookupTable(x, f, interpolant='floor'), galsim.LookupTable(x, f, x_log=True), galsim.LookupTable(x, f, f_log=True) ] ff = f + np.array(f)[:, None] ff2 = f2 + np.array(f2)[:, None] lts.extend([ galsim.LookupTable2D(x, x, ff), galsim.LookupTable2D(x2, x, ff), galsim.LookupTable2D(x, x2, ff), galsim.LookupTable2D(x, x2, ff2), galsim.LookupTable2D(x, x, ff, interpolant='nearest'), galsim.LookupTable2D(x, x, ff, interpolant=galsim.Nearest()), galsim.LookupTable2D(x, x, ff, edge_mode='wrap'), galsim.LookupTable2D(x, x, ff, constant=1), galsim.LookupTable2D(x, x, ff, interpolant='spline'), galsim.LookupTable2D(x, x, ff, interpolant='spline', dfdx=ff, dfdy=ff, d2fdxdy=ff) ]) all_obj_diff(lts)
def test_table2d(): """Check LookupTable2D functionality. """ has_scipy = False try: import scipy from distutils.version import LooseVersion if LooseVersion(scipy.__version__) < LooseVersion('0.11'): raise ImportError except ImportError: print("SciPy tests require SciPy version 0.11 or greater") else: from scipy.interpolate import interp2d has_scipy = True def f(x_, y_): return np.sin(x_) * np.cos(y_) + x_ x = np.linspace(0.1, 3.3, 25) y = np.linspace(0.2, 10.4, 75) yy, xx = np.meshgrid(y, x) # Note the ordering of both input and output here! z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) do_pickle(tab2d) do_pickle(tab2d.table) newx = np.linspace(0.2, 3.1, 45) newy = np.linspace(0.3, 10.1, 85) newyy, newxx = np.meshgrid(newy, newx) # Compare different ways of evaluating Table2D ref = tab2d(newxx, newyy) np.testing.assert_array_almost_equal( ref, np.array([[tab2d(x0, y0) for y0 in newy] for x0 in newx])) if has_scipy: scitab2d = interp2d(x, y, np.transpose(z)) np.testing.assert_array_almost_equal( ref, np.transpose(scitab2d(newx, newy))) # Test non-equally-spaced table. x = np.delete(x, 10) y = np.delete(y, 10) yy, xx = np.meshgrid(y, x) z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) ref = tab2d(newxx, newyy) np.testing.assert_array_almost_equal( ref, np.array([[tab2d(x0, y0) for y0 in newy] for x0 in newx])) if has_scipy: scitab2d = interp2d(x, y, np.transpose(z)) np.testing.assert_array_almost_equal( ref, np.transpose(scitab2d(newx, newy))) # Try a simpler interpolation function. We should be able to interpolate a (bi-)linear function # exactly with a linear interpolant. def f(x_, y_): return 2 * x_ + 3 * y_ z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) np.testing.assert_array_almost_equal(f(newxx, newyy), tab2d(newxx, newyy)) np.testing.assert_array_almost_equal( f(newxx, newyy), np.array([[tab2d(x0, y0) for y0 in newy] for x0 in newx])) # Test edge exception try: np.testing.assert_raises(ValueError, tab2d, 1e6, 1e6) except ImportError: print('The assert_raises tests require nose') # Test edge wrapping # Check that can't construct table with edge-wrapping if edges don't match try: np.testing.assert_raises(ValueError, galsim.LookupTable, (x, y, z), dict(edge_mode='wrap')) except ImportError: print('The assert_warns tests require nose') # Extend edges and make vals match x = np.append(x, x[-1] + (x[-1] - x[-2])) y = np.append(y, y[-1] + (y[-1] - y[-2])) z = np.pad(z, [(0, 1), (0, 1)], mode='wrap') tab2d = galsim.LookupTable2D(x, y, z, edge_mode='wrap') np.testing.assert_array_almost_equal( tab2d(newxx, newyy), tab2d(newxx + 3 * (x[-1] - x[0]), newyy)) np.testing.assert_array_almost_equal( tab2d(newxx, newyy), tab2d(newxx, newyy + 13 * (y[-1] - y[0]))) # Test edge_mode='constant' tab2d = galsim.LookupTable2D(x, y, z, edge_mode='constant', constant=42) assert type(tab2d(x[0] - 1, y[0] - 1)) == float assert tab2d(x[0] - 1, y[0] - 1) == 42.0 # One in-bounds, one out-of-bounds np.testing.assert_array_almost_equal( tab2d([x[0], x[0] - 1], [y[0], y[0] - 1]), [tab2d(x[0], y[0]), 42.0]) # Test floor/ceil/nearest interpolant x = y = np.arange(5) z = x + y[:, np.newaxis] tab2d = galsim.LookupTable2D(x, y, z, interpolant='ceil') assert tab2d(2.4, 3.6) == 3 + 4, "Ceil interpolant failed." tab2d = galsim.LookupTable2D(x, y, z, interpolant='floor') assert tab2d(2.4, 3.6) == 2 + 3, "Floor interpolant failed." tab2d = galsim.LookupTable2D(x, y, z, interpolant='nearest') assert tab2d(2.4, 3.6) == 2 + 4, "Nearest interpolant failed." # Test that x,y arrays need to be strictly increasing. try: x[0] = x[1] np.testing.assert_raises(ValueError, galsim.LookupTable2D, x, y, z) x[0] = x[1] + 1 np.testing.assert_raises(ValueError, galsim.LookupTable2D, x, y, z) x[0] = x[1] - 1 y[0] = y[1] np.testing.assert_raises(ValueError, galsim.LookupTable2D, x, y, z) y[0] = y[1] + 1 np.testing.assert_raises(ValueError, galsim.LookupTable2D, x, y, z) except ImportError: print('The assert_raises tests require nose')
def test_table2d_cubic(): # A few functions that should be exactly interpolatable with bicubic # interpolation def f1(x_, y_): return 2 * x_ + 3 * y_ def df1dx(x_, y_): return np.ones_like(x_) * 2 def df1dy(x_, y_): return np.ones_like(x_) * 3 def f2(x_, y_): return 2 * x_ * x_ def df2dx(x_, y_): return 4 * x_ def df2dy(x_, y_): return np.zeros_like(x_) def f3(x_, y_): return 2 * y_ * y_ def df3dx(x_, y_): return np.zeros_like(x_) def df3dy(x_, y_): return 4 * y_ def f4(x_, y_): return 2 * y_ * y_ + 3 * x_ * x_ def df4dx(x_, y_): return 6 * x_ def df4dy(x_, y_): return 4 * y_ def f5(x_, y_): return 2 * y_ * y_ + 3 * x_ * x_ + 4 * x_ * y_ def df5dx(x_, y_): return 6 * x_ + 4 * y_ def df5dy(x_, y_): return 4 * y_ + 4 * x_ fs = [f1, f2, f3, f4, f5] dfdxs = [df1dx, df2dx, df3dx, df4dx, df5dx] dfdys = [df1dy, df2dy, df3dy, df4dy, df5dy] x = np.linspace(0.1, 3.3, 250) y = np.linspace(0.2, 10.4, 750) yy, xx = np.meshgrid(y, x) # Note the ordering of both input and output here! for f, dfdx, dfdy in zip(fs, dfdxs, dfdys): z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z, interpolant='spline') # Check single value functionality. x1, y1 = 2.3, 1.2 np.testing.assert_allclose(tab2d(x1, y1), f(x1, y1), atol=1e-11, rtol=0) ref_dfdx = dfdx(x1, y1) ref_dfdy = dfdy(x1, y1) test_dfdx, test_dfdy = tab2d.gradient(x1, y1) np.testing.assert_allclose(test_dfdx, ref_dfdx, atol=1e-11, rtol=0) np.testing.assert_allclose(test_dfdy, ref_dfdy, atol=1e-11, rtol=0) # Check vectorized output newx = np.linspace(0.2, 3.1, 45) newy = np.linspace(0.3, 10.1, 85) newyy, newxx = np.meshgrid(newy, newx) np.testing.assert_allclose(tab2d(newxx, newyy), f(newxx, newyy), atol=1e-11, rtol=0) ref_dfdx = dfdx(newxx, newyy) ref_dfdy = dfdy(newxx, newyy) test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy) np.testing.assert_allclose(test_dfdx, ref_dfdx, atol=1e-11, rtol=0) np.testing.assert_allclose(test_dfdy, ref_dfdy, atol=1e-11, rtol=0) # I think it ought to be possible to exactly interpolate the following, # provided the exact derivatives are provided. Use slightly looser tolerances, # which seems reasonable since these are varying more rapidly. def f6(x_, y_): return y_ * y_ * y_ def df6dx(x_, y_): return np.zeros_like(x_) def df6dy(x_, y_): return 3 * y_ * y_ def d2f6dxdy(x_, y_): return np.zeros_like(x_) def f7(x_, y_): return 2 * y_ * y_ * y_ + 3 * x_ * x_ * x_ + 4 * x_ * y_ * y_ def df7dx(x_, y_): return 9 * x_ * x_ + 4 * y_ * y_ def df7dy(x_, y_): return 6 * y_ * y_ + 8 * x_ * y_ def d2f7dxdy(x_, y_): return 8 * y_ fs = [f6, f7] dfdxs = [df6dx, df7dx] dfdys = [df6dy, df7dy] d2fdxdys = [d2f6dxdy, d2f7dxdy] for f, dfdx, dfdy, d2fdxdy in zip(fs, dfdxs, dfdys, d2fdxdys): z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z, interpolant='spline', dfdx=dfdx(xx, yy), dfdy=dfdy(xx, yy), d2fdxdy=d2fdxdy(xx, yy)) # Check single value functionality. x1, y1 = 2.3, 1.2 np.testing.assert_allclose(tab2d(x1, y1), f(x1, y1), atol=1e-10, rtol=0) ref_dfdx = dfdx(x1, y1) ref_dfdy = dfdy(x1, y1) test_dfdx, test_dfdy = tab2d.gradient(x1, y1) np.testing.assert_allclose(test_dfdx, ref_dfdx, atol=1e-10, rtol=0) np.testing.assert_allclose(test_dfdy, ref_dfdy, atol=1e-10, rtol=0) # Check vectorized output newx = np.linspace(0.2, 3.1, 45) newy = np.linspace(0.3, 10.1, 85) newyy, newxx = np.meshgrid(newy, newx) np.testing.assert_allclose(tab2d(newxx, newyy), f(newxx, newyy), atol=1e-10, rtol=0) ref_dfdx = dfdx(newxx, newyy) ref_dfdy = dfdy(newxx, newyy) test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy) np.testing.assert_allclose(test_dfdx, ref_dfdx, atol=1e-10, rtol=0) np.testing.assert_allclose(test_dfdy, ref_dfdy, atol=1e-10, rtol=0)
def test_table2d_gradient(): """Check LookupTable2D gradient function """ # Same function as the above test def f(x_, y_): return np.sin(x_) * np.cos(y_) + x_ # The gradient is analytic for this: def dfdx(x_, y_): return np.cos(x_) * np.cos(y_) + 1. def dfdy(x_, y_): return -np.sin(x_) * np.sin(y_) x = np.linspace(0.1, 3.3, 250) y = np.linspace(0.2, 10.4, 750) yy, xx = np.meshgrid(y, x) # Note the ordering of both input and output here! z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) newx = np.linspace(0.2, 3.1, 45) newy = np.linspace(0.3, 10.1, 85) newyy, newxx = np.meshgrid(newy, newx) # Check single value functionality. x1, y1 = 1.1, 4.9 np.testing.assert_almost_equal(tab2d.gradient(x1, y1), (dfdx(x1, y1), dfdy(x1, y1)), decimal=2) # Check that the gradient function comes out close to the analytic derivatives. ref_dfdx = dfdx(newxx, newyy) ref_dfdy = dfdy(newxx, newyy) test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy) np.testing.assert_almost_equal(test_dfdx, ref_dfdx, decimal=2) np.testing.assert_almost_equal(test_dfdy, ref_dfdy, decimal=2) test2_dfdx, test2_dfdy = tab2d.gradient(newx, newy, grid=True) np.testing.assert_almost_equal(test2_dfdx, ref_dfdx, decimal=2) np.testing.assert_almost_equal(test2_dfdy, ref_dfdy, decimal=2) # Check edge wrapping tab2d = galsim.LookupTable2D(x, y, z, edge_mode='wrap') test_dfdx, test_dfdy = tab2d.gradient(newxx + 13 * tab2d.xperiod, newyy) test2_dfdx, test2_dfdy = tab2d.gradient(newx + 13 * tab2d.xperiod, newy, grid=True) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx, decimal=2) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy, decimal=2) np.testing.assert_array_almost_equal(ref_dfdx, test2_dfdx, decimal=2) np.testing.assert_array_almost_equal(ref_dfdy, test2_dfdy, decimal=2) test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy + 12 * tab2d.yperiod) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx, decimal=2) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy, decimal=2) # Test single value: np.testing.assert_almost_equal(tab2d.gradient(x1, y1), tab2d.gradient(x1 - 9 * tab2d.xperiod, y1)) np.testing.assert_almost_equal(tab2d.gradient(x1, y1), tab2d.gradient(x1, y1 - 7 * tab2d.yperiod)) # Check constant edge_mode tab2d = galsim.LookupTable2D(x, y, z, edge_mode='constant') # Should work the same inside original boundary test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy) test2_dfdx, test2_dfdy = tab2d.gradient(newx, newy, grid=True) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx, decimal=2) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy, decimal=2) np.testing.assert_array_almost_equal(ref_dfdx, test2_dfdx, decimal=2) np.testing.assert_array_almost_equal(ref_dfdy, test2_dfdy, decimal=2) # Should come out zero outside original boundary test_dfdx, test_dfdy = tab2d.gradient(newxx + 2 * np.max(newxx), newyy + 2 * np.max(newyy)) test2_dfdx, test2_dfdy = tab2d.gradient(newx + 2 * np.max(newx), newy + 2 * np.max(newy), grid=True) np.testing.assert_array_equal(0.0, test_dfdx) np.testing.assert_array_equal(0.0, test_dfdy) np.testing.assert_array_equal(0.0, test2_dfdx) np.testing.assert_array_equal(0.0, test2_dfdy) # Test single value np.testing.assert_almost_equal(tab2d.gradient(x1, y1), (dfdx(x1, y1), dfdy(x1, y1)), decimal=2) np.testing.assert_equal(tab2d.gradient(x1 + 2 * np.max(newxx), y1), (0.0, 0.0)) # Try a simpler interpolation function. Derivatives should be exact. def f(x_, y_): return 2 * x_ + 3 * y_ - 4 * x_ * y_ z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy) test2_dfdx, test2_dfdy = tab2d.gradient(newx, newy, grid=True) np.testing.assert_almost_equal(test_dfdx, 2. - 4 * newyy, decimal=7) np.testing.assert_almost_equal(test_dfdy, 3. - 4 * newxx, decimal=7) np.testing.assert_almost_equal(test2_dfdx, 2. - 4 * newyy, decimal=7) np.testing.assert_almost_equal(test2_dfdy, 3. - 4 * newxx, decimal=7) # Check single value functionality. np.testing.assert_almost_equal(tab2d.gradient(x1, y1), (2. - 4 * y1, 3. - 4 * x1)) # Check edge wrapping tab2d = galsim.LookupTable2D(x, y, z, edge_mode='wrap') ref_dfdx, ref_dfdy = tab2d.gradient(newxx, newyy) test_dfdx, test_dfdy = tab2d.gradient(newxx + 3 * tab2d.xperiod, newyy) test2_dfdx, test2_dfdy = tab2d.gradient(newx + 3 * tab2d.xperiod, newy, grid=True) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy) np.testing.assert_array_almost_equal(ref_dfdx, test2_dfdx) np.testing.assert_array_almost_equal(ref_dfdy, test2_dfdy) test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy + 13 * tab2d.yperiod) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy) # Test single value np.testing.assert_almost_equal(tab2d.gradient(x1, y1), (2 - 4 * y1, 3 - 4 * x1)) np.testing.assert_almost_equal(tab2d.gradient(x1 + 2 * tab2d.xperiod, y1), (2 - 4 * y1, 3 - 4 * x1)) # Test mix of inside and outside original boundary test_dfdx, test_dfdy = tab2d.gradient( np.dstack([newxx, newxx + 3 * tab2d.xperiod]), np.dstack([newyy, newyy])) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx[:, :, 0]) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy[:, :, 0]) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx[:, :, 1]) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy[:, :, 1]) # Check that edge_mode='constant' behaves as expected. # Should work the same inside original boundary tab2d = galsim.LookupTable2D(x, y, z, edge_mode='constant') test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy) # Should come out zero outside original boundary test_dfdx, test_dfdy = tab2d.gradient(newxx + 2 * np.max(newxx), newyy) np.testing.assert_array_equal(0.0, test_dfdx) np.testing.assert_array_equal(0.0, test_dfdy) # Test single value np.testing.assert_almost_equal(tab2d.gradient(x1, y1), (2 - 4 * y1, 3 - 4 * x1)) np.testing.assert_equal(tab2d.gradient(x1 + 2 * np.max(newxx), y1), (0.0, 0.0)) # Test mix of inside and outside original boundary test_dfdx, test_dfdy = tab2d.gradient( np.dstack([newxx, newxx + 2 * np.max(newxx)]), np.dstack([newyy, newyy])) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx[:, :, 0]) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy[:, :, 0]) np.testing.assert_array_equal(0.0, test_dfdx[:, :, 1]) np.testing.assert_array_equal(0.0, test_dfdy[:, :, 1])
def test_table2d(): """Check LookupTable2D functionality. """ has_scipy = False try: import scipy from distutils.version import LooseVersion if LooseVersion(scipy.__version__) < LooseVersion('0.11'): raise ImportError except ImportError: print("SciPy tests require SciPy version 0.11 or greater") else: from scipy.interpolate import interp2d has_scipy = True def f(x_, y_): return np.sin(x_) * np.cos(y_) + x_ x = np.linspace(0.1, 3.3, 25) y = np.linspace(0.2, 10.4, 75) yy, xx = np.meshgrid(y, x) # Note the ordering of both input and output here! z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) do_pickle(tab2d) np.testing.assert_array_equal(tab2d.getXArgs(), x) np.testing.assert_array_equal(tab2d.getYArgs(), y) np.testing.assert_array_equal(tab2d.getVals(), z) assert tab2d.interpolant == 'linear' assert tab2d.edge_mode == 'raise' newx = np.linspace(0.2, 3.1, 45) newy = np.linspace(0.3, 10.1, 85) newyy, newxx = np.meshgrid(newy, newx) # Compare different ways of evaluating Table2D ref = tab2d(newxx, newyy) np.testing.assert_array_almost_equal(ref, tab2d(newx, newy, grid=True)) np.testing.assert_array_almost_equal( ref, np.array([[tab2d(x0, y0) for y0 in newy] for x0 in newx])) if has_scipy: scitab2d = interp2d(x, y, np.transpose(z)) np.testing.assert_array_almost_equal( ref, np.transpose(scitab2d(newx, newy))) # Try using linear GSInterp tab2d2 = galsim.LookupTable2D(x, y, z, interpolant=galsim.Linear()) np.testing.assert_array_almost_equal(tab2d(newxx, newyy), tab2d2(newxx, newyy)) np.testing.assert_array_almost_equal(tab2d(newxx.T, newyy.T), tab2d2(newxx.T, newyy.T)) # Try again using Nearest() tab2d2 = galsim.LookupTable2D(x, y, z, interpolant=galsim.Nearest()) tab2d3 = galsim.LookupTable2D(x, y, z, interpolant='nearest') np.testing.assert_array_almost_equal(tab2d2(newxx, newyy), tab2d3(newxx, newyy)) np.testing.assert_array_almost_equal(tab2d2(newxx.T, newyy.T), tab2d3(newxx.T, newyy.T)) # Make sure we exercise the special case in T2DInterpolant2D::interp np.testing.assert_array_almost_equal(tab2d2(0.3, 0.4), tab2d3(0.3, 0.4)) np.testing.assert_array_almost_equal(tab2d2(0.3, 0.4), tab2d3(0.3, 0.4)) # Test non-equally-spaced table. x = np.delete(x, 10) y = np.delete(y, 10) yy, xx = np.meshgrid(y, x) z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) ref = tab2d(newxx, newyy) np.testing.assert_array_almost_equal(ref, tab2d(newx, newy, grid=True)) np.testing.assert_array_almost_equal( ref, np.array([[tab2d(x0, y0) for y0 in newy] for x0 in newx])) if has_scipy: scitab2d = interp2d(x, y, np.transpose(z)) np.testing.assert_array_almost_equal( ref, np.transpose(scitab2d(newx, newy))) # Using a galsim.Interpolant should raise an exception if x/y are not equal spaced. with assert_raises(galsim.GalSimIncompatibleValuesError): tab2d2 = galsim.LookupTable2D(x, y, z, interpolant=galsim.Linear()) # Try a simpler interpolation function. We should be able to interpolate a (bi-)linear function # exactly with a linear interpolant. def f(x_, y_): return 2 * x_ + 3 * y_ z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z) np.testing.assert_array_almost_equal(f(newxx, newyy), tab2d(newxx, newyy)) np.testing.assert_array_almost_equal( f(newxx, newyy), np.array([[tab2d(x0, y0) for y0 in newy] for x0 in newx])) # Test edge exception with assert_raises(ValueError): tab2d(1e6, 1e6) with assert_raises(ValueError): tab2d(np.array([1e5, 1e6]), np.array([1e5, 1e6])) with assert_raises(ValueError): tab2d(np.array([1e5, 1e6]), np.array([1e5, 1e6]), grid=True) with assert_raises(ValueError): tab2d.gradient(1e6, 1e6) with assert_raises(ValueError): tab2d.gradient(np.array([1e5, 1e6]), np.array([1e5, 1e6])) with assert_raises(ValueError): tab2d.gradient(np.array([1e5, 1e6]), np.array([1e5, 1e6]), grid=True) with assert_raises(galsim.GalSimError): galsim.utilities.find_out_of_bounds_position( np.array([1, 3]), np.array([2, 4]), galsim.BoundsD(0, 5, 0, 5)) with assert_raises(galsim.GalSimError): galsim.utilities.find_out_of_bounds_position(np.array([1, 3]), np.array([2, 4]), galsim.BoundsD( 0, 5, 0, 5), grid=True) # Check warning mode tab2dw = galsim.LookupTable2D(x, y, z, edge_mode='warn', constant=1) with assert_warns(galsim.GalSimWarning): assert tab2dw(1e6, 1e6) == 1 with assert_warns(galsim.GalSimWarning): np.testing.assert_array_equal( tab2dw(np.array([1e5, 1e6]), np.array([1e5, 1e6])), np.array([1.0, 1.0])) with assert_warns(galsim.GalSimWarning): np.testing.assert_array_equal( tab2dw(np.array([1e5, 1e6]), np.array([1e5, 1e6]), grid=True), np.array([[1.0, 1.0], [1.0, 1.0]])) with assert_warns(galsim.GalSimWarning): assert tab2dw.gradient(1e6, 1e6) == (0.0, 0.0) with assert_warns(galsim.GalSimWarning): np.testing.assert_array_equal( tab2dw.gradient(np.array([1e5, 1e6]), np.array([1e5, 1e6])), np.zeros((2, 2), dtype=float)) with assert_warns(galsim.GalSimWarning): np.testing.assert_array_equal( tab2dw.gradient(np.array([1e5, 1e6]), np.array([1e5, 1e6]), grid=True), np.zeros((2, 2, 2), dtype=float)) # But doesn't warn if in bounds tab2dw(1.0, 1.0) tab2dw(np.array([1.0]), np.array([1.0])) tab2dw(np.array([1.0]), np.array([1.0]), grid=True) tab2dw.gradient(1.0, 1.0) tab2dw.gradient(np.array([1.0]), np.array([1.0])) # Test edge wrapping # Check that can't construct table with edge-wrapping if edges don't match with assert_raises(ValueError): galsim.LookupTable2D(x, y, z, edge_mode='wrap') # Extend edges and make vals match x = np.append(x, x[-1] + (x[-1] - x[-2])) y = np.append(y, y[-1] + (y[-1] - y[-2])) z = np.pad(z, [(0, 1), (0, 1)], mode='wrap') tab2d = galsim.LookupTable2D(x, y, z, edge_mode='wrap') np.testing.assert_array_almost_equal( tab2d(newxx, newyy), tab2d(newxx + 3 * (x[-1] - x[0]), newyy)) np.testing.assert_array_almost_equal( tab2d(newx, newy, grid=True), tab2d(newxx + 3 * (x[-1] - x[0]), newyy)) np.testing.assert_array_almost_equal( tab2d(newxx, newyy), tab2d(newxx, newyy + 13 * (y[-1] - y[0]))) np.testing.assert_array_almost_equal( tab2d(newxx, newyy), tab2d(newx, newy + 13 * (y[-1] - y[0]), grid=True)) # Test edge_mode='constant' tab2d = galsim.LookupTable2D(x, y, z, edge_mode='constant', constant=42) assert type(tab2d(x[0] - 1, y[0] - 1)) in [float, np.float64] assert tab2d(x[0] - 1, y[0] - 1) == 42.0 # One in-bounds, one out-of-bounds np.testing.assert_array_almost_equal( tab2d([x[0], x[0] - 1], [y[0], y[0] - 1]), [tab2d(x[0], y[0]), 42.0]) # Test floor/ceil/nearest interpolant x = np.arange(5) y = np.arange(5) z = x + y[:, np.newaxis] tab2d = galsim.LookupTable2D(x, y, z, interpolant='ceil') assert tab2d(2.4, 3.6) == 3 + 4, "Ceil interpolant failed." tab2d = galsim.LookupTable2D(x, y, z, interpolant='floor') assert tab2d(2.4, 3.6) == 2 + 3, "Floor interpolant failed." tab2d = galsim.LookupTable2D(x, y, z, interpolant='nearest') assert tab2d(2.4, 3.6) == 2 + 4, "Nearest interpolant failed." tab2d = galsim.LookupTable2D(x, y, z, interpolant=galsim.Nearest()) assert tab2d(2.4, 3.6) == 2 + 4, "Nearest interpolant failed." assert_raises(ValueError, galsim.LookupTable2D, x, y, z, interpolant='invalid') assert_raises(ValueError, galsim.LookupTable2D, x, y, z, edge_mode='invalid') assert_raises(ValueError, galsim.LookupTable2D, x, y, z[:-1, :-1]) # Test that x,y arrays need to be strictly increasing. x[0] = x[1] assert_raises(ValueError, galsim.LookupTable2D, x, y, z) x[0] = x[1] + 1 assert_raises(ValueError, galsim.LookupTable2D, x, y, z) x[0] = x[1] - 1 y[0] = y[1] assert_raises(ValueError, galsim.LookupTable2D, x, y, z) y[0] = y[1] + 1 assert_raises(ValueError, galsim.LookupTable2D, x, y, z) # Test that x,y arrays are larger than interpolant x = y = np.arange(2) z = x[:, None] + y assert_raises(ValueError, galsim.LookupTable2D, x, y, z, interpolant='spline', edge_mode='wrap') # Check dfdx input x = y = np.arange(20) z = x[:, None] + y # Not using interpolant='spline' assert_raises(ValueError, galsim.LookupTable2D, x, y, z, dfdx=z) # Only specifying one derivative assert_raises(ValueError, galsim.LookupTable2D, x, y, z, dfdx=z, interpolant='spline') # Derivative is wrong shape assert_raises(ValueError, galsim.LookupTable2D, x, y, z, dfdx=z, dfdy=z, d2fdxdy=z[::2], interpolant='spline') # Check private shortcut instantiation new_tab2d = galsim.table._LookupTable2D(tab2d.x, tab2d.y, tab2d.f, tab2d.interpolant, tab2d.edge_mode, tab2d.constant, tab2d.dfdx, tab2d.dfdy, tab2d.d2fdxdy) assert tab2d == new_tab2d assert tab2d(2.4, 3.6) == new_tab2d(2.4, 3.6)
def test_table2d_GSInterp(): def f(x_, y_): return 2 * y_ * y_ + 3 * x_ * x_ + 4 * x_ * y_ - np.cos(x_) x = np.linspace(0.1, 3.3, 25) y = np.linspace(0.2, 10.4, 75) yy, xx = np.meshgrid(y, x) # Note the ordering of both input and output here! interpolants = ['lanczos3', 'lanczos3F', 'lanczos7', 'sinc', 'quintic'] for interpolant in interpolants: z = f(xx, yy) tab2d = galsim.LookupTable2D(x, y, z, interpolant=interpolant) do_pickle(tab2d) # Make sure precomputed-hash gets covered hash(tab2d) # Use InterpolatedImage to validate wcs = galsim.JacobianWCS( (max(x) - min(x)) / (len(x) - 1), 0, 0, (max(y) - min(y)) / (len(y) - 1), ) img = galsim.Image(z.T, wcs=wcs) ii = galsim.InterpolatedImage( img, use_true_center=True, offset=(galsim.PositionD(img.xmin, img.ymin) - img.true_center), x_interpolant=interpolant, normalization='sb', calculate_maxk=False, calculate_stepk=False).shift(min(x), min(y)) # Check single value functionality. x1, y1 = 2.3, 3.2 np.testing.assert_allclose(tab2d(x1, y1), ii.xValue(x1, y1), atol=1e-10, rtol=0) # Check vectorized output newx = np.linspace(0.2, 3.1, 15) newy = np.linspace(0.3, 10.1, 25) newyy, newxx = np.meshgrid(newy, newx) np.testing.assert_allclose( tab2d(newxx, newyy).ravel(), np.array([ ii.xValue(x_, y_) for x_, y_ in zip(newxx.ravel(), newyy.ravel()) ]).ravel(), atol=1e-10, rtol=0) np.testing.assert_array_almost_equal(tab2d(newxx, newyy), tab2d(newx, newy, grid=True)) # Check that edge_mode='wrap' works tab2d = galsim.LookupTable2D(x, y, z, edge_mode='wrap') ref_dfdx, ref_dfdy = tab2d.gradient(newxx, newyy) test_dfdx, test_dfdy = tab2d.gradient(newxx + 3 * tab2d.xperiod, newyy) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy) test_dfdx, test_dfdy = tab2d.gradient(newxx, newyy + 13 * tab2d.yperiod) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy) test_dfdx, test_dfdy = tab2d.gradient(newx, newy + 13 * tab2d.yperiod, grid=True) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy) # Test mix of inside and outside original boundary test_dfdx, test_dfdy = tab2d.gradient( np.dstack([newxx, newxx + 3 * tab2d.xperiod]), np.dstack([newyy, newyy])) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx[:, :, 0]) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy[:, :, 0]) np.testing.assert_array_almost_equal(ref_dfdx, test_dfdx[:, :, 1]) np.testing.assert_array_almost_equal(ref_dfdy, test_dfdy[:, :, 1])