def test_type_exception(): """ Test type exception. """ with pytest.raises(TypeError) as exc: discretize_model(float(0), (-10, 11)) assert exc.value.args[0] == 'Model must be callable.'
def test_type_exception(): """ Test type exception. """ with pytest.raises(TypeError) as exc: discretize_model(float(0), (-10, 11)) assert exc.value.args[0] == 'Model must be callable.'
def test_discretize_oversample(): gauss_2D = Gaussian2D(amplitude=1.0, x_mean=5., y_mean=125., x_stddev=0.75, y_stddev=3) values = discretize_model(gauss_2D, x_range=[0, 10], y_range=[100, 135], mode='oversample', factor=10) vmax = np.max(values) vmax_yx = np.unravel_index(values.argmax(), values.shape) values_osf1 = discretize_model(gauss_2D, x_range=[0, 10], y_range=[100, 135], mode='oversample', factor=1) values_center = discretize_model(gauss_2D, x_range=[0, 10], y_range=[100, 135], mode='center') assert values.shape == (35, 10) assert_allclose(vmax, 0.927, atol=1e-3) assert vmax_yx == (25, 5) assert_allclose(values_center, values_osf1)
def test_float_y_range_exception(): def f(x, y): return x ** 2 + y ** 2 with pytest.raises(ValueError) as exc: discretize_model(f, (-10, 11), (-10.002, 11.23)) assert exc.value.args[0] == ("The difference between the upper an lower" " limit of 'y_range' must be a whole number.")
def test_gaussian_sum_moments(): """Check analytical against numerical solution. """ # We define three components with different flux, position and size F_1, F_2, F_3 = 100, 200, 300 sigma_1, sigma_2, sigma_3 = 15, 10, 5 x_1, x_2, x_3 = 100, 120, 70 y_1, y_2, y_3 = 100, 90, 120 # Convert into non-normalized amplitude for astropy model def A(F, sigma): return F * 1 / (2 * np.pi * sigma ** 2) # Define and evaluate models f_1 = Gaussian2D(A(F_1, sigma_1), x_1, y_1, sigma_1, sigma_1) f_2 = Gaussian2D(A(F_2, sigma_2), x_2, y_2, sigma_2, sigma_2) f_3 = Gaussian2D(A(F_3, sigma_3), x_3, y_3, sigma_3, sigma_3) F_1_image = discretize_model(f_1, (0, 200), (0, 200)) F_2_image = discretize_model(f_2, (0, 200), (0, 200)) F_3_image = discretize_model(f_3, (0, 200), (0, 200)) moments_num = measure_image_moments(F_1_image + F_2_image + F_3_image) # Compute analytical values cov_matrix = np.zeros((12, 12)) F = [F_1, F_2, F_3] sigma = [sigma_1, sigma_2, sigma_3] x = [x_1, x_2, x_3] y = [y_1, y_2, y_3] moments_ana, uncertainties = gaussian_sum_moments(F, sigma, x, y, cov_matrix) assert_allclose(moments_ana, moments_num, 1e-6) assert_allclose(uncertainties, 0)
def test_dim_exception_2d(): """ Test dimension exception 2d. """ def f(x, y): return x ** 2 + y ** 2 with pytest.raises(ValueError) as exc: discretize_model(f, (-10, 11)) assert exc.value.args[0] == "y range not specified, but model is 2-d"
def test_dim_exception_1d(): """ Test dimension exception 1d. """ def f(x): return x ** 2 with pytest.raises(ValueError) as exc: discretize_model(f, (-10, 11), (-10, 11)) assert exc.value.args[0] == "y range specified, but model is only 1-d."
def test_subpixel_gauss_2D(): """ Test subpixel accuracy of the integrate mode with gaussian 2D model. """ gauss_2D = Gaussian2D(1, 0, 0, 0.1, 0.1) values = discretize_model(gauss_2D, (-1, 2), (-1, 2), mode='integrate', factor=100) assert_allclose(values.sum(), 2 * np.pi * 0.01, atol=0.00001)
def model_to_image(model, size, mode='center', factor=1, center=None): """ Converts 2D models into images using `astropy.convolution.utils.discretize_model`. Parameters ---------- model : `~astropy.modeling.FittableModel` or callable. Analytic model function to be discretized. Callables, which are not an instances of `~astropy.modeling.FittableModel` are passed to `~astropy.modeling.custom_model` and then evaluated. size : int or tuple The x and y size (in pixels) of the image in pixels (must be an whole number). If only a single integer is provided, an image of equal x and y size is generated. If tuple is provided (x_size, y_size) is assumed (N.B reverse of `numpy.array.shape` output). mode : str, optional One of the following modes (`astropy.convolution.utils.discretize_model`): * ``'center'`` (default) Discretize model by taking the value at the center of the bin. * ``'linear_interp'`` Discretize model by linearly interpolating between the values at the corners of the bin. For 2D models interpolation is bilinear. * ``'oversample'`` Discretize model by taking the average on an oversampled grid. * ``'integrate'`` Discretize model by integrating the model over the bin using `scipy.integrate.quad`. Very slow. factor : float or int Factor of oversampling. Default = 1 (no oversampling). center : tuple (x, y) Coordinate of the center of the image (in pixels). The origin of the image is defined as `origin = center - floor_divide(size, 2)` (i.e the image will range from (origin -> origin + size)). If None, the origin of the image is assumed to be at (0, 0) (i.e `center = floor_divide(size, 2)`). Returns ------- array : `numpy.array` Model image """ x_size, y_size = _validate_image_size(size) if center is None: x_origin, y_origin = (0, 0) else: x_origin, y_origin = model_center_to_image_origin(center, size) return discretize_model(model=model, x_range=[x_origin, x_origin + x_size], y_range=[y_origin, y_origin + y_size], mode=mode, factor=factor)
def test_subpixel_gauss_1D(): """ Test subpixel accuracy of the integrate mode with gaussian 1D model. """ gauss_1D = Gaussian1D(1, 0, 0.1) values = discretize_model(gauss_1D, (-1, 2), mode='integrate', factor=100) assert_allclose(values.sum(), np.sqrt(2 * np.pi) * 0.1, atol=0.00001)
def test_discretize_callable_1d(): """ Test discretize when a 1d function is passed. """ def f(x): return x ** 2 y = discretize_model(f, (-5, 6)) assert_allclose(y, np.arange(-5, 6) ** 2)
def test_discretize_callable_2d(): """ Test discretize when a 2d function is passed. """ def f(x, y): return x ** 2 + y ** 2 actual = discretize_model(f, (-5, 6), (-5, 6)) y, x = (np.indices((11, 11)) - 5) desired = x ** 2 + y ** 2 assert_allclose(actual, desired)
def test_gaussian_eval_1D(mode): """ Discretize Gaussian with different modes and check if result is at least similar to Gaussian1D.eval(). """ model = Gaussian1D(1, 0, 20) x = np.arange(-100, 101) values = model(x) disc_values = discretize_model(model, (-100, 101), mode=mode) assert_allclose(values, disc_values, atol=0.001)
def test_gaussian_eval_1D(mode): """ Discretize Gaussian with different modes and check if result is at least similar to Gaussian1D.eval(). """ model = Gaussian1D(1, 0, 20) x = np.arange(-100, 101) values = model(x) disc_values = discretize_model(model, (-100, 101), mode=mode) assert_allclose(values, disc_values, atol=0.001)
def test_pixel_sum_1D(model_class, mode): """ Test if the sum of all pixels corresponds nearly to the integral. """ if model_class == Box1D and mode == "center": pytest.skip("Non integrating mode. Skip integral test.") parameters = models_1D[model_class] model = create_model(model_class, parameters) values = discretize_model(model, models_1D[model_class]['x_lim'], mode=mode) assert_allclose(values.sum(), models_1D[model_class]['integral'], atol=0.0001)
def test_gaussian_eval_2D(mode): """ Discretize Gaussian with different modes and check if result is at least similar to Gaussian2D.eval() """ model = Gaussian2D(0.01, 0, 0, 1, 1) x = np.arange(-2, 3) y = np.arange(-2, 3) x, y = np.meshgrid(x, y) values = model(x, y) disc_values = discretize_model(model, (-2, 3), (-2, 3), mode=mode) assert_allclose(values, disc_values, atol=1e-2)
def test_gaussian_eval_2D(mode): """ Discretize Gaussian with different modes and check if result is at least similar to Gaussian2D.eval() """ model = Gaussian2D(0.01, 0, 0, 1, 1) x = np.arange(-2, 3) y = np.arange(-2, 3) x, y = np.meshgrid(x, y) values = model(x, y) disc_values = discretize_model(model, (-2, 3), (-2, 3), mode=mode) assert_allclose(values, disc_values, atol=1e-2)
def test_gaussian_eval_2D_integrate_mode(): """ Discretize Gaussian with integrate mode """ model_list = [Gaussian2D(.01, 0, 0, 2, 2), Gaussian2D(.01, 0, 0, 1, 2), Gaussian2D(.01, 0, 0, 2, 1)] x = np.arange(-2, 3) y = np.arange(-2, 3) x, y = np.meshgrid(x, y) for model in model_list: values = model(x, y) disc_values = discretize_model(model, (-2, 3), (-2, 3), mode='integrate') assert_allclose(values, disc_values, atol=1e-2)
def overlap_image(request): if request.param == 2: close_tab = Table([[50., 53.], [50., 50.], [25., 25.]], names=['x_0', 'y_0', 'flux_0']) elif request.param == 3: close_tab = Table([[50., 55., 50.], [50., 50., 55.], [25., 25., 25.]], names=['x_0', 'y_0', 'flux_0']) else: raise ValueError # Add sources to test image close_image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) for x, y, flux in close_tab: close_model = Gaussian2D(flux / (2 * np.pi * GAUSSIAN_WIDTH ** 2), x, y, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) close_image += discretize_model(close_model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') return close_image
def evaluate_model(self, **kwargs): """Evaluate model by oversampling or taking the value at the center of the pixel. """ self._setup_model() self.model_image = np.zeros_like(self.exposure, dtype=np.float64) from astropy.convolution import utils height, width = self.exposure.shape for source_model in self.source_models: source_model_image = utils.discretize_model( source_model, (0, width), (0, height), **kwargs) self.model_image += source_model_image if self._compute_excess: self.model_image = self.model_image * self.exposure if self._apply_psf: psf = self._create_psf(**kwargs) from astropy.convolution import convolve self.model_image = convolve(self.model_image, psf) self.model_image *= self._flux_factor
def simulate_image(images): '''pick image, pick source parameters, add gaussian source''' n = np.random.choice(images.shape[2]) halfwidth = images.shape[0] // 2 theta = np.random.uniform() * 2. * np.pi r = np.random.uniform() * halfwidth # pix x_in = halfwidth + r * np.sin(theta) # pix y_in = halfwidth + r * np.cos(theta) # pix flux_in = 10 ** (np.random.uniform() * 7 + 1) sigma_in = np.random.uniform() * 0.5 + 1. val_in = {'id': [n], 'theta': [theta], 'r': [r], 'x': [x_in], 'y': [y_in], 'flux': [flux_in], 'sigma': [sigma_in]} # Create test psf psf_model = Gaussian2D(flux_in / (2 * np.pi * sigma_in ** 2), x_in, y_in, sigma_in, sigma_in) test_image = images[:, :, n] + discretize_model(psf_model, (0, images.shape[0]), (0, images.shape[1]), mode='oversample') return Table(val_in), test_image
def evaluate_model(self, **kwargs): """Evaluate model by oversampling or taking the value at the center of the pixel. """ self._setup_model() self.model_image = np.zeros_like(self.exposure, dtype=np.float64) from astropy.convolution import utils height, width = self.exposure.shape for source_model in self.source_models: source_model_image = utils.discretize_model(source_model, (0, width), (0, height), **kwargs) self.model_image += source_model_image if self._compute_excess: self.model_image = self.model_image * self.exposure if self._apply_psf: psf = self._create_psf(**kwargs) from astropy.convolution import convolve self.model_image = convolve(self.model_image, psf) self.model_image *= self._flux_factor
# tests previously written to psf_photometry PSF_SIZE = 11 GAUSSIAN_WIDTH = 1.0 IMAGE_SIZE = 101 # Position and FLUXES of test sources INTAB = Table( [[50.0, 23, 12, 86], [50.0, 83, 80, 84], [np.pi * 10, 3.654, 20.0, 80 / np.sqrt(3)]], names=["x_0", "y_0", "flux_0"] ) # Create test psf psf_model = Gaussian2D( 1.0 / (2 * np.pi * GAUSSIAN_WIDTH ** 2), PSF_SIZE // 2, PSF_SIZE // 2, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH ) test_psf = discretize_model(psf_model, (0, PSF_SIZE), (0, PSF_SIZE), mode="oversample") # Set up grid for test image image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in INTAB: model = Gaussian2D(flux / (2 * np.pi * GAUSSIAN_WIDTH ** 2), x, y, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode="oversample") # Some tests require an image with wider sources. WIDE_GAUSSIAN_WIDTH = 3.0 WIDE_INTAB = Table([[50, 23.2], [50.5, 1], [10, 20]], names=["x_0", "y_0", "flux_0"]) wide_image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image
HAS_SCIPY = False PSF_SIZE = 11 GAUSSIAN_WIDTH = 1. IMAGE_SIZE = 101 # Position and FLUXES of test sources INTAB = Table([[50., 23, 12, 86], [50., 83, 80, 84], [np.pi * 10, 3.654, 20., 80 / np.sqrt(3)]], names=['x_0', 'y_0', 'flux_0']) # Create test psf psf_model = Gaussian2D(1. / (2 * np.pi * GAUSSIAN_WIDTH ** 2), PSF_SIZE // 2, PSF_SIZE // 2, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) test_psf = discretize_model(psf_model, (0, PSF_SIZE), (0, PSF_SIZE), mode='oversample') # Set up grid for test image image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in INTAB: model = Gaussian2D(flux / (2 * np.pi * GAUSSIAN_WIDTH ** 2), x, y, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') @pytest.mark.skipif('not HAS_SCIPY') def test_subtract_psf(): """Test subtract_psf."""
# tests previously written to psf_photometry PSF_SIZE = 11 GAUSSIAN_WIDTH = 1. IMAGE_SIZE = 101 # Position and FLUXES of test sources INTAB = Table([[50., 23, 12, 86], [50., 83, 80, 84], [np.pi * 10, 3.654, 20., 80 / np.sqrt(3)]], names=['x_0', 'y_0', 'flux_0']) # Create test psf psf_model = Gaussian2D(1. / (2 * np.pi * GAUSSIAN_WIDTH**2), PSF_SIZE // 2, PSF_SIZE // 2, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) test_psf = discretize_model(psf_model, (0, PSF_SIZE), (0, PSF_SIZE), mode='oversample') # Set up grid for test image image = np.zeros((IMAGE_SIZE, IMAGE_SIZE)) # Add sources to test image for x, y, flux in INTAB: model = Gaussian2D(flux / (2 * np.pi * GAUSSIAN_WIDTH**2), x, y, GAUSSIAN_WIDTH, GAUSSIAN_WIDTH) image += discretize_model(model, (0, IMAGE_SIZE), (0, IMAGE_SIZE), mode='oversample') # Some tests require an image with wider sources. WIDE_GAUSSIAN_WIDTH = 3. WIDE_INTAB = Table([[50, 23.2], [50.5, 1], [10, 20]], names=['x_0', 'y_0', 'flux_0'])
except ImportError: HAS_SCIPY = False psf_size = 11 gaussian_width = 1. image_size = 101. # Position and fluxes of tes sources positions = [(50, 50), (23, 83), (12, 80), (86, 84)] fluxes = [np.pi * 10, 3.654, 20., 80 / np.sqrt(3)] # Create test psf psf_model = Gaussian2D(1. / (2 * np.pi * gaussian_width ** 2), psf_size // 2, psf_size // 2, gaussian_width, gaussian_width) test_psf = discretize_model(psf_model, (0, psf_size), (0, psf_size), mode='oversample') # Set up grid for test image image = np.zeros((image_size, image_size)) # Add sources to test image for i, position in enumerate(positions): x, y = position model = Gaussian2D(fluxes[i] / (2 * np.pi * gaussian_width ** 2), x, y, gaussian_width, gaussian_width) image += discretize_model(model, (0, image_size), (0, image_size), mode='oversample') def test_create_prf_mean(): """ Check if create_prf works correctly on simulated data.