def test_padded_grid_stack(self, lens_data_stack): padded_image_util = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin( mask=np.full((6, 6), False), pixel_scales=lens_data_stack.images[0].pixel_scales) assert (lens_data_stack.padded_grid_stacks[0].regular == padded_image_util).all() assert lens_data_stack.padded_grid_stacks[0].regular.image_shape == (4, 4) assert lens_data_stack.padded_grid_stacks[0].regular.padded_shape == ( 6, 6) padded_sub_util = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size( mask=np.full((6, 6), False), pixel_scales=lens_data_stack.images[0].pixel_scales, sub_grid_size=lens_data_stack.grid_stacks[0].sub.sub_grid_size) assert lens_data_stack.padded_grid_stacks[0].sub == pytest.approx( padded_sub_util, 1e-4) assert lens_data_stack.padded_grid_stacks[0].sub.image_shape == (4, 4) assert lens_data_stack.padded_grid_stacks[0].sub.padded_shape == (6, 6) assert (lens_data_stack.padded_grid_stacks[0].blurring == np.array( [[0.0, 0.0]])).all() padded_image_util = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin( mask=np.full((6, 6), False), pixel_scales=lens_data_stack.images[1].pixel_scales) assert (lens_data_stack.padded_grid_stacks[1].regular == padded_image_util).all() assert lens_data_stack.padded_grid_stacks[1].regular.image_shape == (4, 4) assert lens_data_stack.padded_grid_stacks[1].regular.padded_shape == ( 6, 6) padded_sub_util = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size( mask=np.full((6, 6), False), pixel_scales=lens_data_stack.images[1].pixel_scales, sub_grid_size=lens_data_stack.grid_stacks[1].sub.sub_grid_size) assert lens_data_stack.padded_grid_stacks[1].sub == pytest.approx( padded_sub_util, 1e-4) assert lens_data_stack.padded_grid_stacks[1].sub.image_shape == (4, 4) assert lens_data_stack.padded_grid_stacks[1].sub.padded_shape == (6, 6) assert (lens_data_stack.padded_grid_stacks[1].blurring == np.array( [[0.0, 0.0]])).all() # Pixel scale is doubled, thus the grids of coordinates are doubled. assert (2.0 * lens_data_stack.padded_grid_stacks[0].regular == lens_data_stack.padded_grid_stacks[1].regular).all() assert (2.0 * lens_data_stack.padded_grid_stacks[0].sub == lens_data_stack.padded_grid_stacks[1].sub).all()
def test__4x4_mask_with_one_pixel__4x4_sub_grid(self): mask = np.array([[True, True, True, True], [True, False, False, True], [True, False, False, True], [True, True, True, False]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(2.0, 2.0), sub_grid_size=4) sub_grid = np.round(sub_grid, decimals=1) assert (sub_grid == np.array([[1.6, -1.6], [1.6, -1.2], [1.6, -0.8], [1.6, -0.4], [1.2, -1.6], [1.2, -1.2], [1.2, -0.8], [1.2, -0.4], [0.8, -1.6], [0.8, -1.2], [0.8, -0.8], [0.8, -0.4], [0.4, -1.6], [0.4, -1.2], [0.4, -0.8], [0.4, -0.4], [1.6, 0.4], [1.6, 0.8], [1.6, 1.2], [1.6, 1.6], [1.2, 0.4], [1.2, 0.8], [1.2, 1.2], [1.2, 1.6], [0.8, 0.4], [0.8, 0.8], [0.8, 1.2], [0.8, 1.6], [0.4, 0.4], [0.4, 0.8], [0.4, 1.2], [0.4, 1.6], [-0.4, -1.6], [-0.4, -1.2], [-0.4, -0.8], [-0.4, -0.4], [-0.8, -1.6], [-0.8, -1.2], [-0.8, -0.8], [-0.8, -0.4], [-1.2, -1.6], [-1.2, -1.2], [-1.2, -0.8], [-1.2, -0.4], [-1.6, -1.6], [-1.6, -1.2], [-1.6, -0.8], [-1.6, -0.4], [-0.4, 0.4], [-0.4, 0.8], [-0.4, 1.2], [-0.4, 1.6], [-0.8, 0.4], [-0.8, 0.8], [-0.8, 1.2], [-0.8, 1.6], [-1.2, 0.4], [-1.2, 0.8], [-1.2, 1.2], [-1.2, 1.6], [-1.6, 0.4], [-1.6, 0.8], [-1.6, 1.2], [-1.6, 1.6], [-2.4, 2.4], [-2.4, 2.8], [-2.4, 3.2], [-2.4, 3.6], [-2.8, 2.4], [-2.8, 2.8], [-2.8, 3.2], [-2.8, 3.6], [-3.2, 2.4], [-3.2, 2.8], [-3.2, 3.2], [-3.2, 3.6], [-3.6, 2.4], [-3.6, 2.8], [-3.6, 3.2], [-3.6, 3.6]])).all()
def padded_grid_from_mask_sub_grid_size_and_psf_shape( cls, mask, sub_grid_size, psf_shape): """Setup an *PaddedSubGrid* for an input mask, sub-grid size and psf-shape. The center of every sub-pixel is used to setup the grid's (y,x) arc-second coordinates, including \ masked-pixels which are beyond the input shape but will have light blurred into them given the psf-shape. Parameters ---------- mask : Mask The mask whose masked pixels are used to setup the sub-pixel grid_stack. sub_grid_size : int The size (sub_grid_size x sub_grid_size) of each image-pixels sub-grid. psf_shape : (int, int) The shape of the psf which defines the blurring region and therefore size of padding. """ padded_shape = (mask.shape[0] + psf_shape[0] - 1, mask.shape[1] + psf_shape[1] - 1) padded_sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size( mask=np.full(padded_shape, False), pixel_scales=mask.pixel_scales, sub_grid_size=sub_grid_size) padded_mask = msk.Mask.unmasked_for_shape_and_pixel_scale( shape=padded_shape, pixel_scale=mask.pixel_scale) return PaddedSubGrid(arr=padded_sub_grid, mask=padded_mask, image_shape=mask.shape, sub_grid_size=sub_grid_size)
def test__3x3_mask_with_one_pixel__2x2_sub_grid__include_nonzero_origin(self): mask = np.array([[True, True, True], [True, False, True], [True, True, True]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(3.0, 6.0), sub_grid_size=2, origin=(1.0, 1.0)) assert sub_grid[0:4] == pytest.approx(np.array([[1.5, 0.0], [1.5, 2.0], [0.5, 0.0], [0.5, 2.0]]), 1e-4)
def test__3x3_mask_with_one_pixel__3x3_sub_grid(self): mask = np.array([[True, True, True], [True, False, True], [True, True, True]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(3.0, 3.0), sub_grid_size=3) assert (sub_grid == np.array([[[0.75, -0.75], [0.75, 0.], [0.75, 0.75], [0., -0.75], [0., 0.], [0., 0.75], [-0.75, -0.75], [-0.75, 0.], [-0.75, 0.75]]])).all()
def test__3x3_mask_with_one_pixel__2x2_sub_grid(self): mask = np.array([[True, True, True], [True, False, True], [True, True, True]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(3.0, 6.0), sub_grid_size=2) assert (sub_grid[0:4] == np.array([[0.5, -1.0], [0.5, 1.0], [-0.5, -1.0], [-0.5, 1.0]])).all()
def test__3x4_mask_with_one_pixel__2x2_sub_grid(self): mask = np.array([[True, True, True, False], [True, False, False, True], [False, True, False, True]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(3.0, 3.0), sub_grid_size=2) assert (sub_grid == np.array([[3.5, 4.], [3.5, 5.], [2.5, 4.], [2.5, 5.], [0.5, -2.], [0.5, -1.], [-0.5, -2.], [-0.5, -1.], [0.5, 1.], [0.5, 2.], [-0.5, 1.], [-0.5, 2.], [-2.5, -5.], [-2.5, -4.], [-3.5, -5.], [-3.5, -4.], [-2.5, 1.], [-2.5, 2.], [-3.5, 1.], [-3.5, 2.]])).all()
def test__4x3_mask_with_one_pixel__2x2_sub_grid(self): mask = np.array([[True, True, True], [True, False, True], [True, False, False], [False, True, True]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(3.0, 3.0), sub_grid_size=2) assert (sub_grid == np.array([[2., -0.5], [2., 0.5], [1., -0.5], [1., 0.5], [-1., -0.5], [-1., 0.5], [-2., -0.5], [-2., 0.5], [-1., 2.5], [-1., 3.5], [-2., 2.5], [-2., 3.5], [-4., -3.5], [-4., -2.5], [-5., -3.5], [-5., -2.5]])).all()
def test__3x3_mask_with_row_and_column_of_pixels__2x2_sub_grid(self): mask = np.array([[True, True, False], [False, False, False], [True, True, False]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(3.0, 3.0), sub_grid_size=2) assert (sub_grid == np.array([[3.5, 2.5], [3.5, 3.5], [2.5, 2.5], [2.5, 3.5], [0.5, -3.5], [0.5, -2.5], [-0.5, -3.5], [-0.5, -2.5], [0.5, -0.5], [0.5, 0.5], [-0.5, -0.5], [-0.5, 0.5], [0.5, 2.5], [0.5, 3.5], [-0.5, 2.5], [-0.5, 3.5], [-2.5, 2.5], [-2.5, 3.5], [-3.5, 2.5], [-3.5, 3.5]])).all()
def test__3x3_mask_with_row_and_column_of_pixels__2x2_sub_grid__different_pixel_scale(self): mask = np.array([[True, True, False], [False, False, False], [True, True, False]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(0.3, 0.3), sub_grid_size=2) sub_grid = np.round(sub_grid, decimals=2) np.testing.assert_almost_equal(sub_grid, np.array([[0.35, 0.25], [0.35, 0.35], [0.25, 0.25], [0.25, 0.35], [0.05, -0.35], [0.05, -0.25], [-0.05, -0.35], [-0.05, -0.25], [0.05, -0.05], [0.05, 0.05], [-0.05, -0.05], [-0.05, 0.05], [0.05, 0.25], [0.05, 0.35], [-0.05, 0.25], [-0.05, 0.35], [-0.25, 0.25], [-0.25, 0.35], [-0.35, 0.25], [-0.35, 0.35]]))
def from_mask_and_sub_grid_size(cls, mask, sub_grid_size=1): """Setup a sub-grid of the unmasked pixels, using a mask and a specified sub-grid size. The center of \ every unmasked pixel's sub-pixels give the grid's (y,x) arc-second coordinates. Parameters ----------- mask : Mask The mask whose masked pixels are used to setup the sub-pixel grid_stack. sub_grid_size : int The size (sub_grid_size x sub_grid_size) of each unmasked pixels sub-grid. """ sub_grid_masked = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size( mask=mask, pixel_scales=mask.pixel_scales, sub_grid_size=sub_grid_size) return SubGrid(sub_grid_masked, mask, sub_grid_size)
def test__3x3_mask_with_one_row__3x3_sub_grid__include_nonzero_origin(self): mask = np.array([[True, True, False], [True, False, True], [True, True, False]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(2.0, 2.0), sub_grid_size=3, origin=(1.0, -1.0)) assert sub_grid == pytest.approx(np.array([[3.5, 0.5], [3.5, 1.], [3.5, 1.5], [3., 0.5], [3., 1.], [3., 1.5], [2.5, 0.5], [2.5, 1.], [2.5, 1.5], [1.5, -1.5], [1.5, -1.], [1.5, -0.5], [1., -1.5], [1., -1.], [1., -0.5], [0.5, -1.5], [0.5, -1.], [0.5, -0.5], [-0.5, 0.5], [-0.5, 1.], [-0.5, 1.5], [-1., 0.5], [-1., 1.], [-1., 1.5], [-1.5, 0.5], [-1.5, 1.], [-1.5, 1.5]]), 1e-4)
def test__3x3_mask_with_one_row__3x3_sub_grid(self): mask = np.array([[True, True, False], [True, False, True], [True, True, False]]) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask, pixel_scales=(2.0, 2.0), sub_grid_size=3) assert (sub_grid == np.array([[2.5, 1.5], [2.5, 2.], [2.5, 2.5], [2., 1.5], [2., 2.], [2., 2.5], [1.5, 1.5], [1.5, 2.], [1.5, 2.5], [0.5, -0.5], [0.5, 0.], [0.5, 0.5], [0., -0.5], [0., 0.], [0., 0.5], [-0.5, -0.5], [-0.5, 0.], [-0.5, 0.5], [-1.5, 1.5], [-1.5, 2.], [-1.5, 2.5], [-2., 1.5], [-2., 2.], [-2., 2.5], [-2.5, 1.5], [-2.5, 2.], [-2.5, 2.5]])).all()
def test_padded_grid_stack(self, lens_data): padded_image_util = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin(mask=np.full((6, 6), False), pixel_scales=lens_data.image.pixel_scales) assert (lens_data.padded_grid_stack.regular == padded_image_util).all() assert lens_data.padded_grid_stack.regular.image_shape == (4, 4) assert lens_data.padded_grid_stack.regular.padded_shape == (6, 6) padded_sub_util = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size( mask=np.full((6, 6), False), pixel_scales=lens_data.image.pixel_scales, sub_grid_size=lens_data.grid_stack.sub.sub_grid_size) assert lens_data.padded_grid_stack.sub == pytest.approx(padded_sub_util, 1e-4) assert lens_data.padded_grid_stack.sub.image_shape == (4, 4) assert lens_data.padded_grid_stack.sub.padded_shape == (6, 6) assert (lens_data.padded_grid_stack.blurring == np.array([[0.0, 0.0]])).all()
def test__padded_grid_stack(self, galaxy_data): padded_image_util = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin( mask=np.full((4, 4), False), pixel_scales=galaxy_data.image.pixel_scales) assert ( galaxy_data.padded_grid_stack.regular == padded_image_util).all() assert galaxy_data.padded_grid_stack.regular.image_shape == (4, 4) assert galaxy_data.padded_grid_stack.regular.padded_shape == (4, 4) padded_sub_util = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size( mask=np.full((4, 4), False), pixel_scales=galaxy_data.image.pixel_scales, sub_grid_size=galaxy_data.grid_stack.sub.sub_grid_size) assert galaxy_data.padded_grid_stack.sub == pytest.approx( padded_sub_util, 1e-4) assert galaxy_data.padded_grid_stack.sub.image_shape == (4, 4) assert galaxy_data.padded_grid_stack.sub.padded_shape == (4, 4)
def from_shape_pixel_scale_and_sub_grid_size(cls, shape, pixel_scale, sub_grid_size): """Setup a sub-grid from a 2D array shape and pixel scale. Here, the center of every pixel on the 2D \ array gives the grid's (y,x) arc-second coordinates, where each pixel has sub-pixels specified by the \ sub-grid size. This is equivalent to using a 2D mask consisting entirely of unmasked pixels. Parameters ----------- shape : (int, int) The 2D shape of the array, where all pixels are used to generate the grid-stack's grid_stack. pixel_scale : float The size of each pixel in arc seconds. sub_grid_size : int The size (sub_grid_size x sub_grid_size) of each unmasked pixels sub-grid. """ mask = msk.Mask.unmasked_for_shape_and_pixel_scale( shape=shape, pixel_scale=pixel_scale) sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size( mask=mask, pixel_scales=mask.pixel_scales, sub_grid_size=sub_grid_size) return SubGrid(sub_grid, mask, sub_grid_size)