def __new__(cls, arr, mask, *args, **kwargs):

obj = arr.view(cls)<EOL>obj.mask = mask<EOL>obj.interpolator = None<EOL>return obj<EOL>

A regular grid of coordinates, where each entry corresponds to the (y,x) coordinates at the centre of an \
        unmasked pixel. The positive y-axis is upwards and poitive x-axis to the right.

        A *RegularGrid* is ordered such pixels begin from the top-row of the mask and go rightwards and then \
        downwards. Therefore, it is a ndarray of shape [total_unmasked_pixels, 2]. The first element of the ndarray \
        thus corresponds to the regular pixel index and second element the y or x arc -econd coordinates. For example:

        - regular_grid[3,0] = the 4th unmasked pixel's y-coordinate.
        - regular_grid[6,1] = the 7th unmasked pixel's x-coordinate.

        Below is a visual illustration of a regular-grid, where a total of 10 pixels are unmasked and are included in \
        the grid.

        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|     This is an example mask.Mask, where:
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|o|o|x|x|x|x|     x = True (Pixel is masked and excluded from the regular grid)
        |x|x|x|o|o|o|o|x|x|x|     o = False (Pixel is not masked and included in the regular grid)
        |x|x|x|o|o|o|o|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|

        The mask pixel index's will come out like this (and the direction of arc-second coordinates is highlighted
        around the mask.

        pixel_scale = 1.0"

        <--- -ve  x  +ve -->
                                                        y      x
        |x|x|x|x|x|x|x|x|x|x|  ^   regular_grid[0] = [ 1.5, -0.5]
        |x|x|x|x|x|x|x|x|x|x|  |   regular_grid[1] = [ 1.5,  0.5]
        |x|x|x|x|x|x|x|x|x|x|  |   regular_grid[2] = [ 0.5, -1.5]
        |x|x|x|x|0|1|x|x|x|x| +ve  regular_grid[3] = [ 0.5, -0.5]
        |x|x|x|2|3|4|5|x|x|x|  y   regular_grid[4] = [ 0.5,  0.5]
        |x|x|x|6|7|8|9|x|x|x| -ve  regular_grid[5] = [ 0.5,  1.5]
        |x|x|x|x|x|x|x|x|x|x|  |   regular_grid[6] = [-0.5, -1.5]
        |x|x|x|x|x|x|x|x|x|x|  |   regular_grid[7] = [-0.5, -0.5]
        |x|x|x|x|x|x|x|x|x|x| \/   regular_grid[8] = [-0.5,  0.5]
        |x|x|x|x|x|x|x|x|x|x|      regular_grid[9] = [-0.5,  1.5]


def convolve_array_1d_with_psf(self, padded_array_1d, psf):

padded_array_2d = mapping_util.map_unmasked_1d_array_to_2d_array_from_array_1d_and_shape(<EOL>array_1d=padded_array_1d, shape=self.mask.shape)<EOL>blurred_padded_array_2d = psf.convolve(array=padded_array_2d)<EOL>return mapping_util.map_2d_array_to_masked_1d_array_from_array_2d_and_mask(array_2d=blurred_padded_array_2d,<EOL>mask=np.full(self.mask.shape, False))<EOL>

Convolve a 1d padded array of values (e.g. intensities before PSF blurring) with a PSF, and then trim \
        the convolved array to its original 2D shape.

        Parameters
        -----------
        padded_array_1d: ndarray
            A 1D array of values which were computed using the *PaddedRegularGrid*.
        psf : ndarray
            An array describing the PSF kernel of the image.


array = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin(mask=mask,<EOL>pixel_scales=mask.pixel_scales)<EOL>return cls(array, mask)<EOL>

Setup a regular-grid from a mask, wehere the center of every unmasked pixel gives the grid's (y,x) \
        arc-second coordinates.

        Parameters
        -----------
        mask : Mask
            The mask whose unmasked pixels are used to setup the regular-pixel grid.


@classmethod<EOL><INDENT>def from_shape_and_pixel_scale(cls, shape, pixel_scale):<DEDENT>

mask = msk.Mask.unmasked_for_shape_and_pixel_scale(shape=shape, pixel_scale=pixel_scale)<EOL>array = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin(mask=mask,<EOL>pixel_scales=mask.pixel_scales)<EOL>return cls(array, mask)<EOL>

Setup a regular-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.

        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.


@classmethod<EOL><INDENT>def blurring_grid_from_mask_and_psf_shape(cls, mask, psf_shape):<DEDENT>

blurring_mask = mask.blurring_mask_for_psf_shape(psf_shape)<EOL>return RegularGrid.from_mask(blurring_mask)<EOL>

Setup a blurring-grid from a mask, where a blurring grid consists of all pixels that are masked, but they \
        are close enough to the unmasked pixels that a fraction of their light will be blurred into those pixels \
        via PSF convolution. For example, if our mask is as follows:

        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|     This is an ccd.Mask, where:
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|     x = True (Pixel is masked and excluded from lens)
        |x|x|x|o|o|o|x|x|x|x|     o = False (Pixel is not masked and included in lens)
        |x|x|x|o|o|o|x|x|x|x|
        |x|x|x|o|o|o|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|

        For a PSF of shape (3,3), the following blurring mask is computed (noting that only pixels that are direct \
        neighbors of the unmasked pixels above will blur light into an unmasked pixel):

        |x|x|x|x|x|x|x|x|x|     This is an example regular.Mask, where:
        |x|x|x|x|x|x|x|x|x|
        |x|x|o|o|o|o|o|x|x|     x = True (Pixel is masked and excluded from lens)
        |x|x|o|x|x|x|o|x|x|     o = False (Pixel is not masked and included in lens)
        |x|x|o|x|x|x|o|x|x|
        |x|x|o|x|x|x|o|x|x|
        |x|x|o|o|o|o|o|x|x|
        |x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|

        Thus, the blurring grid coordinates and indexes will be as follows:

        pixel_scale = 1.0"

        <--- -ve  x  +ve -->
                                                            y     x
        |x|x|x |x |x |x |x |x|x|  |   blurring_grid[0] = [2.0, -2.0]  blurring_grid[9] =  [-1.0, -2.0]
        |x|x|x |x |x |x |x |x|x|  |   blurring_grid[1] = [2.0, -1.0]  blurring_grid[10] = [-1.0,  2.0]
        |x|x|0 |1 |2 |3 |4 |x|x| +ve  blurring_grid[2] = [2.0,  0.0]  blurring_grid[11] = [-2.0, -2.0]
        |x|x|5 |x |x |x |6 |x|x|  y   blurring_grid[3] = [2.0,  1.0]  blurring_grid[12] = [-2.0, -1.0]
        |x|x|7 |x |x |x |8 |x|x| -ve  blurring_grid[4] = [2.0,  2.0]  blurring_grid[13] = [-2.0,  0.0]
        |x|x|9 |x |x |x |10|x|x|  |   blurring_grid[5] = [1.0, -2.0]  blurring_grid[14] = [-2.0,  1.0]
        |x|x|11|12|13|14|15|x|x|  |   blurring_grid[6] = [1.0,  2.0]  blurring_grid[15] = [-2.0,  2.0]
        |x|x|x |x |x |x |x |x|x| \/   blurring_grid[7] = [0.0, -2.0]
        |x|x|x |x |x |x |x |x|x|      blurring_grid[8] = [0.0,  2.0]

        For a PSF of shape (5,5), the following blurring mask is computed (noting that pixels that are 2 pixels from an
        direct unmasked pixels now blur light into an unmasked pixel):

        |x|x|x|x|x|x|x|x|x|     This is an example regular.Mask, where:
        |x|o|o|o|o|o|o|o|x|
        |x|o|o|o|o|o|o|o|x|     x = True (Pixel is masked and excluded from lens)
        |x|o|o|x|x|x|o|o|x|     o = False (Pixel is not masked and included in lens)
        |x|o|o|x|x|x|o|o|x|
        |x|o|o|x|x|x|o|o|x|
        |x|o|o|o|o|o|o|o|x|
        |x|o|o|o|o|o|o|o|x|
        |x|x|x|x|x|x|x|x|x|


return mapping_util.map_masked_1d_array_to_2d_array_from_array_1d_shape_and_one_to_two(<EOL>array_1d=array_1d, shape=self.mask.shape, one_to_two=self.mask.masked_grid_index_to_pixel)<EOL>

Map a 1D array the same dimension as the grid to its original masked 2D array.

        Parameters
        -----------
        array_1d : ndarray
            The 1D array which is mapped to its masked 2D array.


return scaled_array.ScaledSquarePixelArray(array=self.array_2d_from_array_1d(array_1d),<EOL>pixel_scale=self.mask.pixel_scale,<EOL>origin=self.mask.origin)<EOL>

Map a 1D array the same dimension as the grid to its original masked 2D array and return it as a scaled \
        array.

        Parameters
        -----------
        array_1d : ndarray
            The 1D array of which is mapped to a 2D scaled array.


return np.linspace(np.min(self[:, <NUM_LIT:0>]), np.max(self[:, <NUM_LIT:0>]), <NUM_LIT:4>)<EOL>

Compute the yticks labels of this grid, used for plotting the y-axis ticks when visualizing a regular


return np.linspace(np.min(self[:, <NUM_LIT:1>]), np.max(self[:, <NUM_LIT:1>]), <NUM_LIT:4>)<EOL>

Compute the xticks labels of this grid, used for plotting the x-axis ticks when visualizing a regular


def __init__(self, array, mask, sub_grid_size=<NUM_LIT:1>):

<EOL>super(SubGrid, self).__init__()<EOL>self.mask = mask<EOL>self.sub_grid_size = sub_grid_size<EOL>self.sub_grid_length = int(sub_grid_size ** <NUM_LIT>)<EOL>self.sub_grid_fraction = <NUM_LIT:1.0> / self.sub_grid_length<EOL>

A sub-grid of coordinates, where each entry corresponds to the (y,x) coordinates at the centre of each \
        sub-pixel of an unmasked pixel (e.g. the pixels of a regular-grid). The positive y-axis is upwards and poitive \
        x-axis to the right, and this convention is followed for the sub-pixels in each unmasked pixel.

        A *SubGrid* is ordered such that pixels begin from the first (top-left) sub-pixel in the first unmasked pixel. \
        Indexes then go over the sub-pixels in each unmasked pixel, for every unmasked pixel. Therefore, \
        the sub-grid is an ndarray of shape [total_unmasked_pixels*(sub_grid_shape)**2, 2]. For example:

        - sub_grid[9, 1] - using a 2x2 sub-grid, gives the 3rd unmasked pixel's 2nd sub-pixel x-coordinate.
        - sub_grid[9, 1] - using a 3x3 sub-grid, gives the 2nd unmasked pixel's 1st sub-pixel x-coordinate.
        - sub_grid[27, 0] - using a 3x3 sub-grid, gives the 4th unmasked pixel's 1st sub-pixel y-coordinate.

        Below is a visual illustration of a sub grid. Like the regular grid, the indexing of each sub-pixel goes from \
        the top-left corner. In contrast to the regular grid above, our illustration below restricts the mask to just \
        2 pixels, to keep the illustration brief.

        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|     This is an example mask.Mask, where:
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|     x = True (Pixel is masked and excluded from lens)
        |x|x|x|x|o|o|x|x|x|x|     o = False (Pixel is not masked and included in lens)
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|
        |x|x|x|x|x|x|x|x|x|x|

        Our regular-grid looks like it did before:

        pixel_scale = 1.0"

        <--- -ve  x  +ve -->

        |x|x|x|x|x|x|x|x|x|x|  ^
        |x|x|x|x|x|x|x|x|x|x|  |
        |x|x|x|x|x|x|x|x|x|x|  |                        y     x
        |x|x|x|x|x|x|x|x|x|x| +ve  regular_grid[0] = [0.5,  -1.5]
        |x|x|x|0|1|x|x|x|x|x|  y   regular_grid[1] = [0.5,  -0.5]
        |x|x|x|x|x|x|x|x|x|x| -ve
        |x|x|x|x|x|x|x|x|x|x|  |
        |x|x|x|x|x|x|x|x|x|x|  |
        |x|x|x|x|x|x|x|x|x|x| \/
        |x|x|x|x|x|x|x|x|x|x|

        However, we now go to each unmasked pixel and derive a sub-pixel grid for it. For example, for pixel 0,
        if *sub_grid_size=2*, we use a 2x2 sub-grid:

        Pixel 0 - (2x2):
                                y      x
               sub_grid[0] = [0.66, -1.66]
        |0|1|  sub_grid[1] = [0.66, -1.33]
        |2|3|  sub_grid[2] = [0.33, -1.66]
               sub_grid[3] = [0.33, -1.33]

        Now, we'd normally sub-grid all pixels using the same *sub_grid_size*, but for this illustration lets
        pretend we used a sub_grid_size of 3x3 for pixel 1:

                                  y      x
                 sub_grid[0] = [0.75, -0.75]
                 sub_grid[1] = [0.75, -0.5]
                 sub_grid[2] = [0.75, -0.25]
        |0|1|2|  sub_grid[3] = [0.5,  -0.75]
        |3|4|5|  sub_grid[4] = [0.5,  -0.5]
        |6|7|8|  sub_grid[5] = [0.5,  -0.25]
                 sub_grid[6] = [0.25, -0.75]
                 sub_grid[7] = [0.25, -0.5]
                 sub_grid[8] = [0.25, -0.25]


@classmethod<EOL><INDENT>def from_mask_and_sub_grid_size(cls, mask, sub_grid_size=<NUM_LIT:1>):<DEDENT>

sub_grid_masked = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(<EOL>mask=mask,<EOL>pixel_scales=mask.pixel_scales,<EOL>sub_grid_size=sub_grid_size)<EOL>return SubGrid(sub_grid_masked, mask, sub_grid_size)<EOL>

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.


@classmethod<EOL><INDENT>def from_shape_pixel_scale_and_sub_grid_size(cls, shape, pixel_scale, sub_grid_size):<DEDENT>

mask = msk.Mask.unmasked_for_shape_and_pixel_scale(shape=shape, pixel_scale=pixel_scale)<EOL>sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask=mask,<EOL>pixel_scales=mask.pixel_scales,<EOL>sub_grid_size=sub_grid_size)<EOL>return SubGrid(sub_grid, mask, sub_grid_size)<EOL>

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.


sub_shape = (self.mask.shape[<NUM_LIT:0>] * self.sub_grid_size, self.mask.shape[<NUM_LIT:1>] * self.sub_grid_size)<EOL>sub_one_to_two = self.mask.masked_sub_grid_index_to_sub_pixel(sub_grid_size=self.sub_grid_size)<EOL>return mapping_util.map_masked_1d_array_to_2d_array_from_array_1d_shape_and_one_to_two(<EOL>array_1d=sub_array_1d, shape=sub_shape, one_to_two=sub_one_to_two)<EOL>

Map a 1D sub-array the same dimension as the sub-grid (e.g. including sub-pixels) to its original masked
        2D sub array.

        Parameters
        -----------
        sub_array_1d : ndarray
            The 1D sub_array which is mapped to its masked 2D sub-array.


Map a 1D sub-array the same dimension as the sub-grid to its original masked 2D sub-array and return it as
        a scaled array.

        Parameters
        -----------
        sub_array_1d : ndarray
            The 1D sub-array of which is mapped to a 2D scaled sub-array the dimensions.


return np.multiply(self.sub_grid_fraction, sub_array_1d.reshape(-<NUM_LIT:1>, self.sub_grid_length).sum(axis=<NUM_LIT:1>))<EOL>

For an input sub-gridded array, map its hyper-values from the sub-gridded values to a 1D regular grid of \
        values by summing each set of each set of sub-pixels values and dividing by the total number of sub-pixels.

        Parameters
        -----------
        sub_array_1d : ndarray
            A 1D sub-gridded array of values (e.g. the intensities, surface-densities, potential) which is mapped to
            a 1d regular array.


return mapping_util.sub_to_regular_from_mask(self.mask, self.sub_grid_size).astype('<STR_LIT:int>')<EOL>

The mapping between every sub-pixel and its host regular-pixel.

        For example:

        - sub_to_pixel[8] = 2 -  The ninth sub-pixel is within the 3rd regular pixel.
        - sub_to_pixel[20] = 4 -  The twenty first sub-pixel is within the 5th regular pixel.


def __new__(cls, arr, regular_to_nearest_pix, *args, **kwargs):

obj = arr.view(cls)<EOL>obj.regular_to_nearest_pix = regular_to_nearest_pix<EOL>obj.interpolator = None<EOL>return obj<EOL>

A pix-grid of (y,x) coordinates which are used to form the pixel centres of adaptive pixelizations in the \
        *pixelizations* module.

        A *PixGrid* is ordered such pixels begin from the top-row of the mask and go rightwards and then \
        downwards. Therefore, it is a ndarray of shape [total_pix_pixels, 2]. The first element of the ndarray \
        thus corresponds to the pix pixel index and second element the y or x arc -econd coordinates. For example:

        - pix_grid[3,0] = the 4th unmasked pixel's y-coordinate.
        - pix_grid[6,1] = the 7th unmasked pixel's x-coordinate.

        Parameters
        -----------
        pix_grid : ndarray
            The grid of (y,x) arc-second coordinates of every image-plane pixelization grid used for adaptive source \
            -plane pixelizations.
        regular_to_nearest_pix : ndarray
            A 1D array that maps every regular-grid pixel to its nearest pix-grid pixel.


def __init__(self, unmasked_sparse_grid_shape, pixel_scales, regular_grid, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

self.shape = unmasked_sparse_grid_shape<EOL>self.origin = origin<EOL>self.total_unmasked_sparse_pixels = int(self.shape[<NUM_LIT:0>] * self.shape[<NUM_LIT:1>])<EOL>self.pixel_scales = pixel_scales<EOL>self.regular_grid = regular_grid<EOL>self.unmasked_sparse_grid = self.grid_1d<EOL>self.unmasked_sparse_grid_pixel_centres =regular_grid.mask.grid_arcsec_to_grid_pixel_centres(self.unmasked_sparse_grid)<EOL>self.total_sparse_pixels = mask_util.total_sparse_pixels_from_mask(<EOL>mask=self.regular_grid.mask,<EOL>unmasked_sparse_grid_pixel_centres=self.unmasked_sparse_grid_pixel_centres)<EOL>

A sparse grid of coordinates, where each entry corresponds to the (y,x) coordinates at the centre of a \
        pixel on the sparse grid. To setup the sparse-grid, it is laid over a regular-grid of unmasked pixels, such \
        that all sparse-grid pixels which map inside of an unmasked regular-grid pixel are included on the sparse grid.

        To setup this sparse grid, we thus have two sparse grid_stack:

        - The unmasked sparse-grid, which corresponds to a uniform 2D array of pixels. The edges of this grid \
          correspond to the 4 edges of the mask (e.g. the higher and lowest (y,x) arc-second unmasked pixels) and the \
          grid's shape is speciifed by the unmasked_sparse_grid_shape parameter.

        - The (masked) sparse-grid, which is all pixels on the unmasked sparse-grid above which fall within unmasked \
          regular-grid pixels. These are the pixels which are actually used for other modules in PyAutoLens.

        The origin of the unmasked sparse grid can be changed to allow off-center pairings with sparse-grid pixels, \
        which is necessary when a mask has a centre offset from (0.0", 0.0"). However, the sparse grid itself \
        retains an origin of (0.0", 0.0"), ensuring its arc-second grid uses the same coordinate system as the \
        other grid_stack.

        The sparse grid is used to determine the pixel centers of an adaptive grid pixelization.

        Parameters
        ----------
        unmasked_sparse_grid_shape : (int, int)
            The shape of the unmasked sparse-grid whose centres form the sparse-grid.
        pixel_scales : (float, float)
            The pixel-to-arcsecond scale of a pixel in the y and x directions.
        regular_grid : RegularGrid
            The regular-grid used to determine which pixels are in the sparse grid.
        origin : (float, float)
            The centre of the unmasked sparse grid, which matches the centre of the mask.


The 1D index mappings between the unmasked sparse-grid and masked sparse grid.


The 1D index mappings between the masked sparse-grid and unmasked sparse grid.


return self.grid_arcsec_to_grid_pixel_indexes(grid_arcsec=self.regular_grid)<EOL>

The 1D index mapping between the regular-grid and unmasked sparse-grid.


The 1D index mappings between the regular-grid and masked sparse-grid.


return mapping_util.sparse_grid_from_unmasked_sparse_grid(<EOL>unmasked_sparse_grid=self.unmasked_sparse_grid,<EOL>sparse_to_unmasked_sparse=self.sparse_to_unmasked_sparse)<EOL>

The (y,x) arc-second coordinates of the masked sparse-grid.


def __new__(cls, arr, mask, image_shape, *args, **kwargs):

arr = arr.view(cls)<EOL>arr.mask = mask<EOL>arr.image_shape = image_shape<EOL>return arr<EOL>

A padded regular-grid stores the (y,x) arc-second coordinates of a 2D array, analogous to a *RegularGrid*. \
         Howeve, the padded grid deviates from a regular grid in that:

        - All pixels are used to form the grid (as opposed to just masked pixels)
        - The mask is padded when computing the grid, such that additional pixels beyond its edge are included. This \
          padding extends based on the size of the PSF kernel, such that PSF blurring effects at the edge of the \
          array do not degrade the image.

        Padded-grid_stack are therefore used to compute quantities like light-profile intensities large 2D arrays \
        that span the entire image (as opposed to just the masked region).


@classmethod<EOL><INDENT>def padded_grid_from_shape_psf_shape_and_pixel_scale(cls, shape, psf_shape, pixel_scale):<DEDENT>

padded_shape = (shape[<NUM_LIT:0>] + psf_shape[<NUM_LIT:0>] - <NUM_LIT:1>, shape[<NUM_LIT:1>] + psf_shape[<NUM_LIT:1>] - <NUM_LIT:1>)<EOL>padded_regular_grid = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin(<EOL>mask=np.full(padded_shape, False), pixel_scales=(pixel_scale, pixel_scale))<EOL>padded_mask = msk.Mask.unmasked_for_shape_and_pixel_scale(shape=padded_shape, pixel_scale=pixel_scale)<EOL>return PaddedRegularGrid(arr=padded_regular_grid, mask=padded_mask, image_shape=shape)<EOL>

Setup a regular padded grid from a 2D array shape, psf-shape and pixel-scale.

        The center of every pixel is used to setup the grid's (y,x) arc-second coordinates, including padded pixels \
        which are beyond the input shape but will blurred light into the 2D array's shape due to the psf.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the masked-grid's 2D image in units of pixels.
        psf_shape : (int, int)
           The shape of the psf which defines the blurring region and therefore size of padding.
        pixel_scale : float
            The scale of each pixel in arc seconds


def padded_blurred_image_2d_from_padded_image_1d_and_psf(self, padded_image_1d, psf):

padded_model_image_1d = self.convolve_array_1d_with_psf(padded_array_1d=padded_image_1d, psf=psf)<EOL>return self.scaled_array_2d_from_array_1d(array_1d=padded_model_image_1d)<EOL>

Compute a 2D padded blurred image from a 1D padded image.

        Parameters
        ----------
        padded_image_1d : ndarray
            A 1D unmasked image which is blurred with the PSF.
        psf : ndarray
            An array describing the PSF kernel of the image.


padded_array_2d = self.map_to_2d_keep_padded(padded_array_1d)<EOL>pad_size_0 = self.mask.shape[<NUM_LIT:0>] - self.image_shape[<NUM_LIT:0>]<EOL>pad_size_1 = self.mask.shape[<NUM_LIT:1>] - self.image_shape[<NUM_LIT:1>]<EOL>return (padded_array_2d[pad_size_0 // <NUM_LIT:2>:self.mask.shape[<NUM_LIT:0>] - pad_size_0 // <NUM_LIT:2>,<EOL>pad_size_1 // <NUM_LIT:2>:self.mask.shape[<NUM_LIT:1>] - pad_size_1 // <NUM_LIT:2>])<EOL>

Map a padded 1D array of values to its original 2D array, trimming all edge values.

        Parameters
        -----------
        padded_array_1d : ndarray
            A 1D array of values which were computed using the *PaddedRegularGrid*.


return mapping_util.map_unmasked_1d_array_to_2d_array_from_array_1d_and_shape(array_1d=padded_array_1d,<EOL>shape=self.mask.shape)<EOL>

Map a padded 1D array of values to its padded 2D array.

        Parameters
        -----------
        padded_array_1d : ndarray
            A 1D array of values which were computed using the *PaddedRegularGrid*.


def __init__(self, arr, mask, image_shape, sub_grid_size=<NUM_LIT:1>):

super(PaddedSubGrid, self).__init__(arr, mask, sub_grid_size)<EOL>self.image_shape = image_shape<EOL>

A *PaddedSubGrid* stores the (y,x) arc-second coordinates of a mask's sub-pixels in 1D, in an analogous
        fashion to a *SubGrid*. A *PaddedSubGrid* deviate from a normal grid in that:

        - All pixels are used (as opposed to just masked pixels)
        - The mask is masked when computing the grid, such that additional pixels beyond its edge are included.

        Padded-grid_stack allow quantities like intensities to be computed on large 2D arrays spanning the entire
        image, as opposed to just within the masked region.


@classmethod<EOL><INDENT>def padded_grid_from_mask_sub_grid_size_and_psf_shape(cls, mask, sub_grid_size, psf_shape):<DEDENT>

padded_shape = (mask.shape[<NUM_LIT:0>] + psf_shape[<NUM_LIT:0>] - <NUM_LIT:1>, mask.shape[<NUM_LIT:1>] + psf_shape[<NUM_LIT:1>] - <NUM_LIT:1>)<EOL>padded_sub_grid = grid_util.sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(<EOL>mask=np.full(padded_shape, False), pixel_scales=mask.pixel_scales, sub_grid_size=sub_grid_size)<EOL>padded_mask = msk.Mask.unmasked_for_shape_and_pixel_scale(shape=padded_shape, pixel_scale=mask.pixel_scale)<EOL>return PaddedSubGrid(arr=padded_sub_grid, mask=padded_mask, image_shape=mask.shape,<EOL>sub_grid_size=sub_grid_size)<EOL>

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.


border = arr.view(cls)<EOL>return border<EOL>

The borders of a regular grid, containing the pixel-index's of all masked pixels that are on the \
        mask's border (e.g. they are next to a *True* value in at least one of the surrounding 8 pixels and at one of \
        the exterior edge's of the mask).

        This is used to relocate demagnified pixel's in a grid to its border, so that they do not disrupt an \
        adaptive pixelization's inversion.

        Parameters
        -----------
        arr : ndarray
            A 1D array of the integer indexes of an *RegularGrid*'s borders pixels.


return cls(mask.border_pixels)<EOL>

Setup the regular-grid border using a mask.

        Parameters
        -----------
        mask : Mask
            The mask the masked borders pixel index's are computed from.


border_grid = grid_stack.regular[self]<EOL>return GridStack(regular=self.relocated_grid_from_grid_jit(grid=grid_stack.regular, border_grid=border_grid),<EOL>sub=self.relocated_grid_from_grid_jit(grid=grid_stack.sub, border_grid=border_grid),<EOL>blurring=None,<EOL>pix=self.relocated_grid_from_grid_jit(grid=grid_stack.pix, border_grid=border_grid))<EOL>

Determine a set of relocated grid_stack from an input set of grid_stack, by relocating their pixels based on the \
        borders.

        The blurring-grid does not have its coordinates relocated, as it is only used for computing analytic \
        light-profiles and not inversion-grid_stack.

        Parameters
        -----------
        grid_stack : GridStack
            The grid-stack, whose grid_stack coordinates are relocated.


border_origin = np.zeros(<NUM_LIT:2>)<EOL>border_origin[<NUM_LIT:0>] = np.mean(border_grid[:, <NUM_LIT:0>])<EOL>border_origin[<NUM_LIT:1>] = np.mean(border_grid[:, <NUM_LIT:1>])<EOL>border_grid_radii = np.sqrt(np.add(np.square(np.subtract(border_grid[:, <NUM_LIT:0>], border_origin[<NUM_LIT:0>])),<EOL>np.square(np.subtract(border_grid[:, <NUM_LIT:1>], border_origin[<NUM_LIT:1>]))))<EOL>border_min_radii = np.min(border_grid_radii)<EOL>grid_radii = np.sqrt(np.add(np.square(np.subtract(grid[:, <NUM_LIT:0>], border_origin[<NUM_LIT:0>])),<EOL>np.square(np.subtract(grid[:, <NUM_LIT:1>], border_origin[<NUM_LIT:1>]))))<EOL>for pixel_index in range(grid.shape[<NUM_LIT:0>]):<EOL><INDENT>if grid_radii[pixel_index] > border_min_radii:<EOL><INDENT>closest_pixel_index = np.argmin(np.square(grid[pixel_index, <NUM_LIT:0>] - border_grid[:, <NUM_LIT:0>]) +<EOL>np.square(grid[pixel_index, <NUM_LIT:1>] - border_grid[:, <NUM_LIT:1>]))<EOL>move_factor = border_grid_radii[closest_pixel_index] / grid_radii[pixel_index]<EOL>if move_factor < <NUM_LIT:1.0>:<EOL><INDENT>grid[pixel_index, :] = move_factor * (grid[pixel_index, :] - border_origin[:]) + border_origin[:]<EOL><DEDENT><DEDENT><DEDENT>return grid<EOL>

Relocate the coordinates of a grid to its border if they are outside the border. This is performed as \
        follows:

        1) Use the mean value of the grid's y and x coordinates to determine the origin of the grid.
        2) Compute the radial distance of every grid coordinate from the origin.
        3) For every coordinate, find its nearest pixel in the border.
        4) Determine if it is outside the border, by comparing its radial distance from the origin to its paid \
           border pixel's radial distance.
        5) If its radial distance is larger, use the ratio of radial distances to move the coordinate to the border \
           (if its inside the border, do nothing).


def __init__(self, array, pixel_scale, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

<EOL>super(Mask, self).__init__(array=array, pixel_scale=pixel_scale, origin=origin)<EOL>

A mask, which is applied to a 2D array of hyper to extract a set of unmasked image pixels (i.e. mask entry \
        is *False* or 0) which are then fitted in an analysis.

        The mask retains the pixel scale of the array and has a centre and origin.

        Parameters
        ----------
        array: ndarray
            An array of bools representing the mask.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        origin : (float, float)
            The (y,x) arc-second origin of the mask's coordinate system.
        centre : (float, float)
            The (y,x) arc-second centre of the mask provided it is a standard geometric shape (e.g. a circle).


@classmethod<EOL><INDENT>def unmasked_for_shape_and_pixel_scale(cls, shape, pixel_scale, invert=False):<DEDENT>

mask = np.full(tuple(map(lambda d: int(d), shape)), False)<EOL>if invert: mask = np.invert(mask)<EOL>return cls(array=mask, pixel_scale=pixel_scale)<EOL>

Setup a mask where all pixels are unmasked.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.


@classmethod<EOL><INDENT>def circular(cls, shape, pixel_scale, radius_arcsec, centre=(<NUM_LIT:0.>, <NUM_LIT:0.>), invert=False):<DEDENT>

mask = mask_util.mask_circular_from_shape_pixel_scale_and_radius(shape, pixel_scale, radius_arcsec,<EOL>centre)<EOL>if invert: mask = np.invert(mask)<EOL>return cls(array=mask.astype('<STR_LIT:bool>'), pixel_scale=pixel_scale)<EOL>

Setup a mask where unmasked pixels are within a circle of an input arc second radius and centre.

        Parameters
        ----------
        shape: (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        radius_arcsec : float
            The radius (in arc seconds) of the circle within which pixels unmasked.
        centre: (float, float)
            The centre of the circle used to mask pixels.


@classmethod<EOL><INDENT>def circular_annular(cls, shape, pixel_scale, inner_radius_arcsec, outer_radius_arcsec, centre=(<NUM_LIT:0.>, <NUM_LIT:0.>),<EOL>invert=False):<DEDENT>

mask = mask_util.mask_circular_annular_from_shape_pixel_scale_and_radii(shape, pixel_scale, inner_radius_arcsec,<EOL>outer_radius_arcsec, centre)<EOL>if invert: mask = np.invert(mask)<EOL>return cls(array=mask.astype('<STR_LIT:bool>'), pixel_scale=pixel_scale)<EOL>

Setup a mask where unmasked pixels are within an annulus of input inner and outer arc second radii and \
         centre.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        inner_radius_arcsec : float
            The radius (in arc seconds) of the inner circle outside of which pixels are unmasked.
        outer_radius_arcsec : float
            The radius (in arc seconds) of the outer circle within which pixels are unmasked.
        centre: (float, float)
            The centre of the annulus used to mask pixels.


@classmethod<EOL><INDENT>def circular_anti_annular(cls, shape, pixel_scale, inner_radius_arcsec, outer_radius_arcsec, outer_radius_2_arcsec,<EOL>centre=(<NUM_LIT:0.>, <NUM_LIT:0.>), invert=False):<DEDENT>

mask = mask_util.mask_circular_anti_annular_from_shape_pixel_scale_and_radii(shape, pixel_scale, inner_radius_arcsec,<EOL>outer_radius_arcsec,<EOL>outer_radius_2_arcsec, centre)<EOL>if invert: mask = np.invert(mask)<EOL>return cls(array=mask.astype('<STR_LIT:bool>'), pixel_scale=pixel_scale)<EOL>

Setup a mask where unmasked pixels are outside an annulus of input inner and outer arc second radii, but \
        within a second outer radius, and at a given centre.

        This mask there has two distinct unmasked regions (an inner circle and outer annulus), with an inner annulus \
        of masked pixels.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        inner_radius_arcsec : float
            The radius (in arc seconds) of the inner circle inside of which pixels are unmasked.
        outer_radius_arcsec : float
            The radius (in arc seconds) of the outer circle within which pixels are masked and outside of which they \
            are unmasked.
        outer_radius_2_arcsec : float
            The radius (in arc seconds) of the second outer circle within which pixels are unmasked and outside of \
            which they masked.
        centre: (float, float)
            The centre of the anti-annulus used to mask pixels.


@classmethod<EOL><INDENT>def elliptical(cls, shape, pixel_scale, major_axis_radius_arcsec, axis_ratio, phi, centre=(<NUM_LIT:0.>, <NUM_LIT:0.>),<EOL>invert=False):<DEDENT>

mask = mask_util.mask_elliptical_from_shape_pixel_scale_and_radius(shape, pixel_scale, major_axis_radius_arcsec,<EOL>axis_ratio, phi, centre)<EOL>if invert: mask = np.invert(mask)<EOL>return cls(array=mask.astype('<STR_LIT:bool>'), pixel_scale=pixel_scale)<EOL>

Setup a mask where unmasked pixels are within an ellipse of an input arc second major-axis and centre.

        Parameters
        ----------
        shape: (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        major_axis_radius_arcsec : float
            The major-axis (in arc seconds) of the ellipse within which pixels are unmasked.
        axis_ratio : float
            The axis-ratio of the ellipse within which pixels are unmasked.
        phi : float
            The rotation angle of the ellipse within which pixels are unmasked, (counter-clockwise from the positive \
             x-axis).
        centre: (float, float)
            The centre of the ellipse used to mask pixels.


@classmethod<EOL><INDENT>def elliptical_annular(cls, shape, pixel_scale,inner_major_axis_radius_arcsec, inner_axis_ratio, inner_phi,<EOL>outer_major_axis_radius_arcsec, outer_axis_ratio, outer_phi, centre=(<NUM_LIT:0.0>, <NUM_LIT:0.0>),<EOL>invert=False):<DEDENT>

mask = mask_util.mask_elliptical_annular_from_shape_pixel_scale_and_radius(shape, pixel_scale,<EOL>inner_major_axis_radius_arcsec, inner_axis_ratio, inner_phi,<EOL>outer_major_axis_radius_arcsec, outer_axis_ratio, outer_phi, centre)<EOL>if invert: mask = np.invert(mask)<EOL>return cls(array=mask.astype('<STR_LIT:bool>'), pixel_scale=pixel_scale)<EOL>

Setup a mask where unmasked pixels are within an elliptical annulus of input inner and outer arc second \
        major-axis and centre.

        Parameters
        ----------
        shape: (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        inner_major_axis_radius_arcsec : float
            The major-axis (in arc seconds) of the inner ellipse within which pixels are masked.
        inner_axis_ratio : float
            The axis-ratio of the inner ellipse within which pixels are masked.
        inner_phi : float
            The rotation angle of the inner ellipse within which pixels are masked, (counter-clockwise from the \
            positive x-axis).
        outer_major_axis_radius_arcsec : float
            The major-axis (in arc seconds) of the outer ellipse within which pixels are unmasked.
        outer_axis_ratio : float
            The axis-ratio of the outer ellipse within which pixels are unmasked.
        outer_phi : float
            The rotation angle of the outer ellipse within which pixels are unmasked, (counter-clockwise from the \
            positive x-axis).
        centre: (float, float)
            The centre of the elliptical annuli used to mask pixels.


return mask_util.masked_grid_1d_index_to_2d_pixel_index_from_mask(self).astype('<STR_LIT:int>')<EOL>

A 1D array of mappings between every unmasked pixel and its 2D pixel coordinates.


return mask_util.masked_sub_grid_1d_index_to_2d_sub_pixel_index_from_mask(<EOL>self, sub_grid_size=sub_grid_size).astype('<STR_LIT:int>')<EOL>

A 1D array of mappings between every unmasked sub pixel and its 2D sub-pixel coordinates.


if array_2d is None or isinstance(array_2d, float):<EOL><INDENT>return array_2d<EOL><DEDENT>return mapping_util.map_2d_array_to_masked_1d_array_from_array_2d_and_mask(self, array_2d)<EOL>

For a 2D array (e.g. an image, noise_map, etc.) map it to a masked 1D array of valuees using this mask.

        Parameters
        ----------
        array_2d : ndarray | None | float
            The 2D array to be mapped to a masked 1D array.


if psf_shape[<NUM_LIT:0>] % <NUM_LIT:2> == <NUM_LIT:0> or psf_shape[<NUM_LIT:1>] % <NUM_LIT:2> == <NUM_LIT:0>:<EOL><INDENT>raise exc.MaskException("<STR_LIT>")<EOL><DEDENT>blurring_mask = mask_util.mask_blurring_from_mask_and_psf_shape(self, psf_shape)<EOL>return Mask(blurring_mask, self.pixel_scale)<EOL>

Compute a blurring mask, which represents all masked pixels whose light will be blurred into unmasked \
        pixels via PSF convolution (see grid_stack.RegularGrid.blurring_grid_from_mask_and_psf_shape).

        Parameters
        ----------
        psf_shape : (int, int)
           The shape of the psf which defines the blurring region (e.g. the shape of the PSF)


return mask_util.edge_pixels_from_mask(self).astype('<STR_LIT:int>')<EOL>

The indicies of the mask's edge pixels, where an edge pixel is any unmasked pixel on its edge \
        (next to at least one pixel with a *True* value).


return mask_util.border_pixels_from_mask(self).astype('<STR_LIT:int>')<EOL>

The indicies of the mask's border pixels, where a border pixel is any unmasked pixel on an
        exterior edge (e.g. next to at least one pixel with a *True* value but not central pixels like those within \
        an annulus mask).


<EOL>where = np.array(np.where(np.invert(self.astype('<STR_LIT:bool>'))))<EOL>y0, x0 = np.amin(where, axis=<NUM_LIT:1>)<EOL>y1, x1 = np.amax(where, axis=<NUM_LIT:1>)<EOL>return [y0, y1+<NUM_LIT:1>, x0, x1+<NUM_LIT:1>]<EOL>

The zoomed rectangular region corresponding to the square encompassing all unmasked values.

        This is used to zoom in on the region of an image that is used in an analysis for visualization.


@decorator_util.jit()<EOL>def centres_from_shape_pixel_scales_and_origin(shape, pixel_scales, origin):

y_centre_arcsec = float(shape[<NUM_LIT:0>] - <NUM_LIT:1>) / <NUM_LIT:2> + (origin[<NUM_LIT:0>] / pixel_scales[<NUM_LIT:0>])<EOL>x_centre_arcsec = float(shape[<NUM_LIT:1>] - <NUM_LIT:1>) / <NUM_LIT:2> - (origin[<NUM_LIT:1>] / pixel_scales[<NUM_LIT:1>])<EOL>return (y_centre_arcsec, x_centre_arcsec)<EOL>

Determine the (y,x) arc-second central coordinates of an array from its shape, pixel-scales and origin.

     The coordinate system is defined such that the positive y axis is up and positive x axis is right.

    Parameters
     ----------
    shape : (int, int)
        The (y,x) shape of the 2D array the arc-second centre is computed for.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the 2D array.
    origin : (float, flloat)
        The (y,x) origin of the 2D array, which the centre is shifted to.

    Returns
    --------
    tuple (float, float)
        The (y,x) arc-second central coordinates of the input array.

    Examples
    --------
    centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=(5,5), pixel_scales=(0.5, 0.5), origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def regular_grid_2d_from_shape_pixel_scales_and_origin(shape, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

regular_grid_2d = np.zeros((shape[<NUM_LIT:0>], shape[<NUM_LIT:1>], <NUM_LIT:2>))<EOL>centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=shape, pixel_scales=pixel_scales, origin=origin)<EOL>for y in range(shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(shape[<NUM_LIT:1>]):<EOL><INDENT>regular_grid_2d[y, x, <NUM_LIT:0>] = -(y - centres_arcsec[<NUM_LIT:0>]) * pixel_scales[<NUM_LIT:0>]<EOL>regular_grid_2d[y, x, <NUM_LIT:1>] = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scales[<NUM_LIT:1>]<EOL><DEDENT><DEDENT>return regular_grid_2d<EOL>

Compute the (y,x) arc second coordinates at the centre of every pixel of an array of shape (rows, columns).

    Coordinates are defined from the top-left corner, such that the first pixel at location [0, 0] has negative x \
    and y values in arc seconds.

    The regular grid is returned on an array of shape (total_pixels, total_pixels, 2) where coordinate indexes match \
    those of the original 2D array. y coordinates are stored in the 0 index of the third dimension, x coordinates in \
    the 1 index.

    Parameters
     ----------
    shape : (int, int)
        The (y,x) shape of the 2D array the regular grid of coordinates is computed for.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the 2D array.
    origin : (float, flloat)
        The (y,x) origin of the 2D array, which the regular grid is shifted around.

    Returns
    --------
    ndarray
        A regular grid of (y,x) arc-second coordinates at the centre of every pixel on a 2D array. The regular grid \
        array has dimensions (total_pixels, total_pixels, 2).

    Examples
    --------
    regular_grid_1d = regular_grid_2d_from_shape_pixel_scales_and_origin(shape=(5,5), pixel_scales=(0.5, 0.5), \
                                                                      origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def regular_grid_1d_from_shape_pixel_scales_and_origin(shape, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

regular_grid_1d = np.zeros((shape[<NUM_LIT:0>]*shape[<NUM_LIT:1>], <NUM_LIT:2>))<EOL>centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=shape, pixel_scales=pixel_scales, origin=origin)<EOL>i=<NUM_LIT:0><EOL>for y in range(shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(shape[<NUM_LIT:1>]):<EOL><INDENT>regular_grid_1d[i, <NUM_LIT:0>] = -(y - centres_arcsec[<NUM_LIT:0>]) * pixel_scales[<NUM_LIT:0>]<EOL>regular_grid_1d[i, <NUM_LIT:1>] = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scales[<NUM_LIT:1>]<EOL>i += <NUM_LIT:1><EOL><DEDENT><DEDENT>return regular_grid_1d<EOL>

Compute the (y,x) arc second coordinates at the centre of every pixel of an array of shape (rows, columns).

    Coordinates are defined from the top-left corner, such that the first pixel at location [0, 0] has negative x \
    and y values in arc seconds.

    The regular grid is returned on an array of shape (total_pixels**2, 2) where the 2D dimension of the original 2D \
    array are reduced to one dimension. y coordinates are stored in the 0 index of the second dimension, x coordinates
    in the 1 index.

    Parameters
     ----------
    shape : (int, int)
        The (y,x) shape of the 2D array the regular grid of coordinates is computed for.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the 2D array.
    origin : (float, flloat)
        The (y,x) origin of the 2D array, which the regular grid is shifted around.

    Returns
    --------
    ndarray
        A regular grid of (y,x) arc-second coordinates at the centre of every pixel on a 2D array. The regular grid
        array has dimensions (total_pixels**2, 2).

    Examples
    --------
    regular_grid_1d = regular_grid_1d_from_shape_pixel_scales_and_origin(shape=(5,5), pixel_scales=(0.5, 0.5), \
                                                                      origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def regular_grid_1d_masked_from_mask_pixel_scales_and_origin(mask, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

grid_2d = regular_grid_2d_from_shape_pixel_scales_and_origin(mask.shape, pixel_scales, origin)<EOL>total_regular_pixels = mask_util.total_regular_pixels_from_mask(mask)<EOL>regular_grid_1d = np.zeros(shape=(total_regular_pixels, <NUM_LIT:2>))<EOL>pixel_count = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>regular_grid_1d[pixel_count, :] = grid_2d[y, x]<EOL>pixel_count += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>return regular_grid_1d<EOL>

Compute the (y,x) arc second coordinates at the centre of every pixel of a 2D mask array of shape (rows, columns).

    Coordinates are defined from the top-left corner, where the first unmasked pixel corresponds to index 0. The pixel \
    at the top-left of the array has negative x and y values in arc seconds.

    The regular grid is returned on an array of shape (total_unmasked_pixels, 2). y coordinates are stored in the 0 \
    index of the second dimension, x coordinates in the 1 index.

    Parameters
     ----------
    mask : ndarray
        A 2D array of bools, where *False* values mean unmasked and are therefore included as part of the calculated \
        regular grid.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the 2D mask array.
    origin : (float, flloat)
        The (y,x) origin of the 2D array, which the regular grid is shifted around.

    Returns
    --------
    ndarray
        A regular grid of (y,x) arc-second coordinates at the centre of every pixel unmasked pixel on the 2D mask \
        array. The regular grid array has dimensions (total_unmasked_pixels, 2).

    Examples
    --------
    mask = np.array([[True, False, True],
                     [False, False, False]
                     [True, False, True]])
    regular_grid_1d = regular_grid_1d_masked_from_mask_pixel_scales_and_origin(mask=mask, pixel_scales=(0.5, 0.5),
                                                                            origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def sub_grid_1d_masked_from_mask_pixel_scales_and_sub_grid_size(mask, pixel_scales, sub_grid_size, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

total_sub_pixels = mask_util.total_sub_pixels_from_mask_and_sub_grid_size(mask, sub_grid_size)<EOL>sub_grid_1d = np.zeros(shape=(total_sub_pixels, <NUM_LIT:2>))<EOL>centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=mask.shape, pixel_scales=pixel_scales,<EOL>origin=origin)<EOL>sub_index = <NUM_LIT:0><EOL>y_sub_half = pixel_scales[<NUM_LIT:0>] / <NUM_LIT:2><EOL>y_sub_step = pixel_scales[<NUM_LIT:0>] / (sub_grid_size + <NUM_LIT:1>)<EOL>x_sub_half = pixel_scales[<NUM_LIT:1>] / <NUM_LIT:2><EOL>x_sub_step = pixel_scales[<NUM_LIT:1>] / (sub_grid_size + <NUM_LIT:1>)<EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>y_arcsec = (y - centres_arcsec[<NUM_LIT:0>]) * pixel_scales[<NUM_LIT:0>]<EOL>x_arcsec = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scales[<NUM_LIT:1>]<EOL>for y1 in range(sub_grid_size):<EOL><INDENT>for x1 in range(sub_grid_size):<EOL><INDENT>sub_grid_1d[sub_index, <NUM_LIT:0>] = -(y_arcsec - y_sub_half + (y1 + <NUM_LIT:1>) * y_sub_step)<EOL>sub_grid_1d[sub_index, <NUM_LIT:1>] = x_arcsec - x_sub_half + (x1 + <NUM_LIT:1>) * x_sub_step<EOL>sub_index += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>return sub_grid_1d<EOL>

For the sub-grid, every unmasked pixel of a 2D mask array of shape (rows, columns) is divided into a finer \
    uniform grid of shape (sub_grid_size, sub_grid_size). This routine computes the (y,x) arc second coordinates at \
    the centre of every sub-pixel defined by this grid.

    Coordinates are defined from the top-left corner, where the first unmasked sub-pixel corresponds to index 0. \
    Sub-pixels that are part of the same mask array pixel are indexed next to one another, such that the second \
    sub-pixel in the first pixel has index 1, its next sub-pixel has index 2, and so forth.

    The sub-grid is returned on an array of shape (total_unmasked_pixels*sub_grid_size**2, 2). y coordinates are \
    stored in the 0 index of the second dimension, x coordinates in the 1 index.

    Parameters
     ----------
    mask : ndarray
        A 2D array of bools, where *False* values mean unmasked and are therefore included as part of the calculated \
        regular grid.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the 2D mask array.
    sub_grid_size : int
        The size of the sub-grid that each pixel of the 2D mask array is divided into.
    origin : (float, flloat)
        The (y,x) origin of the 2D array, which the sub-grid is shifted around.

    Returns
    --------
    ndarray
        A sub grid of (y,x) arc-second coordinates at the centre of every pixel unmasked pixel on the 2D mask \
        array. The sub grid array has dimensions (total_unmasked_pixels*sub_grid_size**2, 2).

    Examples
    --------
    mask = np.array([[True, False, True],
                     [False, False, False]
                     [True, False, True]])
    sub_grid_1d = sub_grid_1d_from_mask_pixel_scales_and_origin(mask=mask, pixel_scales=(0.5, 0.5), origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def grid_arcsec_1d_to_grid_pixels_1d(grid_arcsec_1d, shape, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

grid_pixels_1d = np.zeros((grid_arcsec_1d.shape[<NUM_LIT:0>], <NUM_LIT:2>))<EOL>centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=shape, pixel_scales=pixel_scales, origin=origin)<EOL>for i in range(grid_arcsec_1d.shape[<NUM_LIT:0>]):<EOL><INDENT>grid_pixels_1d[i, <NUM_LIT:0>] = (-grid_arcsec_1d[i, <NUM_LIT:0>] / pixel_scales[<NUM_LIT:0>]) + centres_arcsec[<NUM_LIT:0>] + <NUM_LIT:0.5><EOL>grid_pixels_1d[i, <NUM_LIT:1>] = (grid_arcsec_1d[i, <NUM_LIT:1>] / pixel_scales[<NUM_LIT:1>]) + centres_arcsec[<NUM_LIT:1>] + <NUM_LIT:0.5><EOL><DEDENT>return grid_pixels_1d<EOL>

Convert a grid of (y,x) arc second coordinates to a grid of (y,x) pixel coordinate values. Pixel coordinates \
    are returned as floats such that they include the decimal offset from each pixel's top-left corner relative to \
    the input arc-second coordinate.

    The pixel coordinate origin is at the top left corner of the grid, such that the pixel [0,0] corresponds to \
    the highest y arc-second coordinate and lowest x arc-second coordinate on the gird.

    The arc-second grid is defined by an origin and coordinates are shifted to this origin before computing their \
    1D grid pixel coordinate values.

    The input and output grids are both of shape (total_pixels, 2).

    Parameters
    ----------
    grid_arcsec_1d: ndarray
        The grid of (y,x) coordinates in arc seconds which is converted to pixel value coordinates.
    shape : (int, int)
        The (y,x) shape of the original 2D array the arc-second coordinates were computed on.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the original 2D array.
    origin : (float, flloat)
        The (y,x) origin of the grid, which the arc-second grid is shifted to.

    Returns
    --------
    ndarray
        A grid of (y,x) pixel-value coordinates with dimensions (total_pixels, 2).

    Examples
    --------
    grid_arcsec_1d = np.array([[1.0, 1.0], [2.0, 2.0], [3.0, 3.0], [4.0, 4.0]])
    grid_pixels_1d = grid_arcsec_1d_to_grid_pixels_1d(grid_arcsec_1d=grid_arcsec_1d, shape=(2,2),
                                                           pixel_scales=(0.5, 0.5), origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def grid_arcsec_1d_to_grid_pixel_centres_1d(grid_arcsec_1d, shape, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

grid_pixels_1d = np.zeros((grid_arcsec_1d.shape[<NUM_LIT:0>], <NUM_LIT:2>))<EOL>centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=shape, pixel_scales=pixel_scales, origin=origin)<EOL>for i in range(grid_arcsec_1d.shape[<NUM_LIT:0>]):<EOL><INDENT>grid_pixels_1d[i, <NUM_LIT:0>] = int((-grid_arcsec_1d[i, <NUM_LIT:0>] / pixel_scales[<NUM_LIT:0>]) + centres_arcsec[<NUM_LIT:0>] + <NUM_LIT:0.5>)<EOL>grid_pixels_1d[i, <NUM_LIT:1>] = int((grid_arcsec_1d[i, <NUM_LIT:1>] / pixel_scales[<NUM_LIT:1>]) + centres_arcsec[<NUM_LIT:1>] + <NUM_LIT:0.5>)<EOL><DEDENT>return grid_pixels_1d<EOL>

Convert a grid of (y,x) arc second coordinates to a grid of (y,x) pixel values. Pixel coordinates are \
    returned as integers such that they map directly to the pixel they are contained within.

    The pixel coordinate origin is at the top left corner of the grid, such that the pixel [0,0] corresponds to \
    higher y arc-second coordinate value and lowest x arc-second coordinate.

    The arc-second coordinate grid is defined by the class attribute origin, and coordinates are shifted to this \
    origin before computing their 1D grid pixel indexes.

    The input and output grids are both of shape (total_pixels, 2).

    Parameters
    ----------
    grid_arcsec_1d: ndarray
        The grid of (y,x) coordinates in arc seconds which is converted to pixel indexes.
    shape : (int, int)
        The (y,x) shape of the original 2D array the arc-second coordinates were computed on.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the original 2D array.
    origin : (float, flloat)
        The (y,x) origin of the grid, which the arc-second grid is shifted

    Returns
    --------
    ndarray
        A grid of (y,x) pixel indexes with dimensions (total_pixels, 2).

    Examples
    --------
    grid_arcsec_1d = np.array([[1.0, 1.0], [2.0, 2.0], [3.0, 3.0], [4.0, 4.0]])
    grid_pixels_1d = grid_arcsec_1d_to_grid_pixel_centres_1d(grid_arcsec_1d=grid_arcsec_1d, shape=(2,2),
                                                           pixel_scales=(0.5, 0.5), origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def grid_arcsec_1d_to_grid_pixel_indexes_1d(grid_arcsec_1d, shape, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

grid_pixels_1d = grid_arcsec_1d_to_grid_pixel_centres_1d(grid_arcsec_1d=grid_arcsec_1d, shape=shape,<EOL>pixel_scales=pixel_scales, origin=origin)<EOL>grid_pixel_indexes_1d = np.zeros(grid_pixels_1d.shape[<NUM_LIT:0>])<EOL>for i in range(grid_pixels_1d.shape[<NUM_LIT:0>]):<EOL><INDENT>grid_pixel_indexes_1d[i] = int(grid_pixels_1d[i,<NUM_LIT:0>] * shape[<NUM_LIT:1>] + grid_pixels_1d[i,<NUM_LIT:1>])<EOL><DEDENT>return grid_pixel_indexes_1d<EOL>

Convert a grid of (y,x) arc second coordinates to a grid of (y,x) pixel 1D indexes. Pixel coordinates are \
    returned as integers such that they are the pixel from the top-left of the 2D grid going rights and then \
    downwards.

    For example:

    The pixel at the top-left, whose 2D index is [0,0], corresponds to 1D index 0.
    The fifth pixel on the top row, whose 2D index is [0,5], corresponds to 1D index 4.
    The first pixel on the second row, whose 2D index is [0,1], has 1D index 10 if a row has 10 pixels.

    The arc-second coordinate grid is defined by the class attribute origin, and coordinates are shifted to this \
    origin before computing their 1D grid pixel indexes.

    The input and output grids are both of shape (total_pixels, 2).

    Parameters
    ----------
    grid_arcsec_1d: ndarray
        The grid of (y,x) coordinates in arc seconds which is converted to 1D pixel indexes.
    shape : (int, int)
        The (y,x) shape of the original 2D array the arc-second coordinates were computed on.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the original 2D array.
    origin : (float, flloat)
        The (y,x) origin of the grid, which the arc-second grid is shifted.

    Returns
    --------
    ndarray
        A grid of 1d pixel indexes with dimensions (total_pixels, 2).

    Examples
    --------
    grid_arcsec_1d = np.array([[1.0, 1.0], [2.0, 2.0], [3.0, 3.0], [4.0, 4.0]])
    grid_pixels_1d = grid_arcsec_1d_to_grid_pixel_indexes_1d(grid_arcsec_1d=grid_arcsec_1d, shape=(2,2),
                                                           pixel_scales=(0.5, 0.5), origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def grid_pixels_1d_to_grid_arcsec_1d(grid_pixels_1d, shape, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

grid_arcsec_1d = np.zeros((grid_pixels_1d.shape[<NUM_LIT:0>], <NUM_LIT:2>))<EOL>centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=shape, pixel_scales=pixel_scales, origin=origin)<EOL>for i in range(grid_arcsec_1d.shape[<NUM_LIT:0>]):<EOL><INDENT>grid_arcsec_1d[i, <NUM_LIT:0>] = -(grid_pixels_1d[i, <NUM_LIT:0>] - centres_arcsec[<NUM_LIT:0>] - <NUM_LIT:0.5>) * pixel_scales[<NUM_LIT:0>]<EOL>grid_arcsec_1d[i, <NUM_LIT:1>] = (grid_pixels_1d[i, <NUM_LIT:1>] - centres_arcsec[<NUM_LIT:1>] - <NUM_LIT:0.5>) * pixel_scales[<NUM_LIT:1>]<EOL><DEDENT>return grid_arcsec_1d<EOL>

Convert a grid of (y,x) pixel coordinates to a grid of (y,x) arc second values.

    The pixel coordinate origin is at the top left corner of the grid, such that the pixel [0,0] corresponds to \
    higher y arc-second coordinate value and lowest x arc-second coordinate.

    The arc-second coordinate origin is defined by the class attribute origin, and coordinates are shifted to this \
    origin after computing their values from the 1D grid pixel indexes.

    The input and output grids are both of shape (total_pixels, 2).

    Parameters
    ----------
    grid_pixels_1d: ndarray
        The grid of (y,x) coordinates in pixel values which is converted to arc-second coordinates.
    shape : (int, int)
        The (y,x) shape of the original 2D array the arc-second coordinates were computed on.
    pixel_scales : (float, float)
        The (y,x) arc-second to pixel scales of the original 2D array.
    origin : (float, flloat)
        The (y,x) origin of the grid, which the arc-second grid is shifted.

    Returns
    --------
    ndarray
        A grid of 1d arc-second coordinates with dimensions (total_pixels, 2).

    Examples
    --------
    grid_pixels_1d = np.array([[0,0], [0,1], [1,0], [1,1])
    grid_pixels_1d = grid_pixels_1d_to_grid_arcsec_1d(grid_pixels_1d=grid_pixels_1d, shape=(2,2),
                                                           pixel_scales=(0.5, 0.5), origin=(0.0, 0.0))


@decorator_util.jit()<EOL>def grid_arcsec_2d_to_grid_pixel_centres_2d(grid_arcsec_2d, shape, pixel_scales, origin=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

grid_pixels_2d = np.zeros((grid_arcsec_2d.shape[<NUM_LIT:0>], grid_arcsec_2d.shape[<NUM_LIT:1>], <NUM_LIT:2>))<EOL>centres_arcsec = centres_from_shape_pixel_scales_and_origin(shape=shape, pixel_scales=pixel_scales, origin=origin)<EOL>for y in range(grid_arcsec_2d.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(grid_arcsec_2d.shape[<NUM_LIT:1>]):<EOL><INDENT>grid_pixels_2d[y, x, <NUM_LIT:0>] = int((-grid_arcsec_2d[y, x, <NUM_LIT:0>] / pixel_scales[<NUM_LIT:0>]) + centres_arcsec[<NUM_LIT:0>] + <NUM_LIT:0.5>)<EOL>grid_pixels_2d[y, x, <NUM_LIT:1>] = int((grid_arcsec_2d[y, x, <NUM_LIT:1>] / pixel_scales[<NUM_LIT:1>]) + centres_arcsec[<NUM_LIT:1>] + <NUM_LIT:0.5>)<EOL><DEDENT><DEDENT>return grid_pixels_2d<EOL>


@decorator_util.jit()<EOL>def extracted_array_2d_from_array_2d_and_coordinates(array_2d, y0, y1, x0, x1):

new_shape = (y1-y0, x1-x0)<EOL>resized_array = np.zeros(shape=new_shape)<EOL>for y_resized, y in enumerate(range(y0, y1)):<EOL><INDENT>for x_resized, x in enumerate(range(x0, x1)):<EOL><INDENT>resized_array[y_resized, x_resized] = array_2d[y, x]<EOL><DEDENT><DEDENT>return resized_array<EOL>

Resize an array to a new size by extracting a sub-set of the array.

    The extracted input coordinates use NumPy convention, such that the upper values should be specified as +1 the \
    dimensions of the extracted array.

    In the example below, an array of size (5,5) is extracted using the coordinates y0=1, y1=4, x0=1, x1=4. This
    extracts an array of dimensions (2,2) and is equivalent to array_2d[1:4, 1:4]

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is an array is extracted from.
    y0 : int
        The lower row number (e.g. the higher y-coodinate) of the array that is extracted for the resize.
    y1 : int
        The upper row number (e.g. the lower y-coodinate) of the array that is extracted for the resize.
    x0 : int
        The lower column number (e.g. the lower x-coodinate) of the array that is extracted for the resize.
    x1 : int
        The upper column number (e.g. the higher x-coodinate) of the array that is extracted for the resize.

    Returns
    -------
    ndarray
        The extracted 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    extracted_array = extract_array_2d(array_2d=array_2d, y0=1, y1=4, x0=1, x1=4)


@decorator_util.jit()<EOL>def resized_array_2d_from_array_2d_and_resized_shape(array_2d, resized_shape, origin=(-<NUM_LIT:1>, -<NUM_LIT:1>), pad_value=<NUM_LIT:0.0>):

y_is_even = int(array_2d.shape[<NUM_LIT:0>]) % <NUM_LIT:2> == <NUM_LIT:0><EOL>x_is_even = int(array_2d.shape[<NUM_LIT:1>]) % <NUM_LIT:2> == <NUM_LIT:0><EOL>if origin is (-<NUM_LIT:1>, -<NUM_LIT:1>):<EOL><INDENT>if y_is_even:<EOL><INDENT>y_centre = int(array_2d.shape[<NUM_LIT:0>] / <NUM_LIT:2>)<EOL><DEDENT>elif not y_is_even:<EOL><INDENT>y_centre = int(array_2d.shape[<NUM_LIT:0>] / <NUM_LIT:2>)<EOL><DEDENT>if x_is_even:<EOL><INDENT>x_centre = int(array_2d.shape[<NUM_LIT:1>] / <NUM_LIT:2>)<EOL><DEDENT>elif not x_is_even:<EOL><INDENT>x_centre = int(array_2d.shape[<NUM_LIT:1>] / <NUM_LIT:2>)<EOL><DEDENT>origin = (y_centre, x_centre)<EOL><DEDENT>resized_array = np.zeros(shape=resized_shape)<EOL>if y_is_even:<EOL><INDENT>y_min = origin[<NUM_LIT:0>] - int(resized_shape[<NUM_LIT:0>] / <NUM_LIT:2>)<EOL>y_max = origin[<NUM_LIT:0>] + int((resized_shape[<NUM_LIT:0>] / <NUM_LIT:2>)) + <NUM_LIT:1><EOL><DEDENT>elif not y_is_even:<EOL><INDENT>y_min = origin[<NUM_LIT:0>] - int(resized_shape[<NUM_LIT:0>] / <NUM_LIT:2>)<EOL>y_max = origin[<NUM_LIT:0>] + int((resized_shape[<NUM_LIT:0>] / <NUM_LIT:2>)) + <NUM_LIT:1><EOL><DEDENT>if x_is_even:<EOL><INDENT>x_min = origin[<NUM_LIT:1>] - int(resized_shape[<NUM_LIT:1>] / <NUM_LIT:2>)<EOL>x_max = origin[<NUM_LIT:1>] + int((resized_shape[<NUM_LIT:1>] / <NUM_LIT:2>)) + <NUM_LIT:1><EOL><DEDENT>elif not x_is_even:<EOL><INDENT>x_min = origin[<NUM_LIT:1>] - int(resized_shape[<NUM_LIT:1>] / <NUM_LIT:2>)<EOL>x_max = origin[<NUM_LIT:1>] + int((resized_shape[<NUM_LIT:1>] / <NUM_LIT:2>)) + <NUM_LIT:1><EOL><DEDENT>for y_resized, y in enumerate(range(y_min, y_max)):<EOL><INDENT>for x_resized, x in enumerate(range(x_min, x_max)):<EOL><INDENT>if y >= <NUM_LIT:0> and y < array_2d.shape[<NUM_LIT:0>] and x >= <NUM_LIT:0> and x < array_2d.shape[<NUM_LIT:1>]:<EOL><INDENT>if y_resized >= <NUM_LIT:0> and y_resized < resized_shape[<NUM_LIT:0>] and x_resized >= <NUM_LIT:0> and x_resized < resized_shape[<NUM_LIT:1>]:<EOL><INDENT>resized_array[y_resized, x_resized] = array_2d[y, x]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if y_resized >= <NUM_LIT:0> and y_resized < resized_shape[<NUM_LIT:0>] and x_resized >= <NUM_LIT:0> and x_resized < resized_shape[<NUM_LIT:1>]:<EOL><INDENT>resized_array[y_resized, x_resized] = pad_value<EOL><DEDENT><DEDENT><DEDENT><DEDENT>return resized_array<EOL>

Resize an array to a new size around a central pixel.

    If the origin (e.g. the central pixel) of the resized array is not specified, the central pixel of the array is \
    calculated automatically. For example, a (5,5) array's central pixel is (2,2). For even dimensions the central \
    pixel is assumed to be the lower indexed value, e.g. a (6,4) array's central pixel is calculated as (2,1).

    The default origin is (-1, -1) because numba requires that the function input is the same type throughout the \
    function, thus a default 'None' value cannot be used.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is resized.
    resized_shape : (int, int)
        The (y,x) new pixel dimension of the trimmed array.
    origin : (int, int)
        The oigin of the resized array, e.g. the central pixel around which the array is extracted.

    Returns
    -------
    ndarray
        The resized 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    resize_array = resize_array_2d(array_2d=array_2d, new_shape=(2,2), origin=(2, 2))


padded_array_2d = pad_2d_array_for_binning_up_with_bin_up_factor(array_2d=array_2d, bin_up_factor=bin_up_factor)<EOL>binned_array_2d = np.zeros(shape=(padded_array_2d.shape[<NUM_LIT:0>] // bin_up_factor,<EOL>padded_array_2d.shape[<NUM_LIT:1>] // bin_up_factor))<EOL>for y in range(binned_array_2d.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(binned_array_2d.shape[<NUM_LIT:1>]):<EOL><INDENT>value = <NUM_LIT:0.0><EOL>for y1 in range(bin_up_factor):<EOL><INDENT>for x1 in range(bin_up_factor):<EOL><INDENT>padded_y = y*bin_up_factor + y1<EOL>padded_x = x*bin_up_factor + x1<EOL>value += padded_array_2d[padded_y, padded_x]<EOL><DEDENT><DEDENT>binned_array_2d[y,x] = value / (bin_up_factor ** <NUM_LIT>)<EOL><DEDENT><DEDENT>return binned_array_2d<EOL>

Bin up an array to coarser resolution, by binning up groups of pixels and using their mean value to determine \
     the value of the new pixel.

    If an array of shape (8,8) is input and the bin up size is 2, this would return a new array of size (4,4) where \
    every pixel was the mean of each collection of 2x2 pixels on the (8,8) array.

    If binning up the array leads to an edge being cut (e.g. a (9,9) array binned up by 2), an array is first \
    extracted around the centre of that array.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is resized.
    new_shape : (int, int)
        The (y,x) new pixel dimension of the trimmed array.
    origin : (int, int)
        The oigin of the resized array, e.g. the central pixel around which the array is extracted.

    Returns
    -------
    ndarray
        The resized 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    resize_array = resize_array_2d(array_2d=array_2d, new_shape=(2,2), origin=(2, 2))


padded_array_2d = pad_2d_array_for_binning_up_with_bin_up_factor(array_2d=array_2d, bin_up_factor=bin_up_factor)<EOL>binned_array_2d = np.zeros(shape=(padded_array_2d.shape[<NUM_LIT:0>] // bin_up_factor,<EOL>padded_array_2d.shape[<NUM_LIT:1>] // bin_up_factor))<EOL>for y in range(binned_array_2d.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(binned_array_2d.shape[<NUM_LIT:1>]):<EOL><INDENT>value = <NUM_LIT:0.0><EOL>for y1 in range(bin_up_factor):<EOL><INDENT>for x1 in range(bin_up_factor):<EOL><INDENT>padded_y = y*bin_up_factor + y1<EOL>padded_x = x*bin_up_factor + x1<EOL>value += padded_array_2d[padded_y, padded_x] ** <NUM_LIT><EOL><DEDENT><DEDENT>binned_array_2d[y,x] = np.sqrt(value) / (bin_up_factor ** <NUM_LIT>)<EOL><DEDENT><DEDENT>return binned_array_2d<EOL>

Bin up an array to coarser resolution, by binning up groups of pixels and using their quadrature value to determine \
     the value of the new pixel.

    If an array of shape (8,8) is input and the bin up size is 2, this would return a new array of size (4,4) where \
    every pixel was the quadrature of each collection of 2x2 pixels on the (8,8) array.

    If binning up the array leads to an edge being cut (e.g. a (9,9) array binned up by 2), an array is first \
    extracted around the centre of that array.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is resized.
    new_shape : (int, int)
        The (y,x) new pixel dimension of the trimmed array.
    origin : (int, int)
        The oigin of the resized array, e.g. the central pixel around which the array is extracted.

    Returns
    -------
    ndarray
        The resized 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    resize_array = resize_array_2d(array_2d=array_2d, new_shape=(2,2), origin=(2, 2))


padded_array_2d = pad_2d_array_for_binning_up_with_bin_up_factor(array_2d=array_2d, bin_up_factor=bin_up_factor)<EOL>binned_array_2d = np.zeros(shape=(padded_array_2d.shape[<NUM_LIT:0>] // bin_up_factor,<EOL>padded_array_2d.shape[<NUM_LIT:1>] // bin_up_factor))<EOL>for y in range(binned_array_2d.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(binned_array_2d.shape[<NUM_LIT:1>]):<EOL><INDENT>value = <NUM_LIT:0.0><EOL>for y1 in range(bin_up_factor):<EOL><INDENT>for x1 in range(bin_up_factor):<EOL><INDENT>padded_y = y*bin_up_factor + y1<EOL>padded_x = x*bin_up_factor + x1<EOL>value += padded_array_2d[padded_y, padded_x]<EOL><DEDENT><DEDENT>binned_array_2d[y,x] = value<EOL><DEDENT><DEDENT>return binned_array_2d<EOL>

Bin up an array to coarser resolution, by binning up groups of pixels and using their sum value to determine \
     the value of the new pixel.

    If an array of shape (8,8) is input and the bin up size is 2, this would return a new array of size (4,4) where \
    every pixel was the sum of each collection of 2x2 pixels on the (8,8) array.

    If binning up the array leads to an edge being cut (e.g. a (9,9) array binned up by 2), an array is first \
    extracted around the centre of that array.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is resized.
    new_shape : (int, int)
        The (y,x) new pixel dimension of the trimmed array.
    origin : (int, int)
        The oigin of the resized array, e.g. the central pixel around which the array is extracted.

    Returns
    -------
    ndarray
        The resized 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    resize_array = resize_array_2d(array_2d=array_2d, new_shape=(2,2), origin=(2, 2))


def numpy_array_2d_to_fits(array_2d, file_path, overwrite=False):

if overwrite and os.path.exists(file_path):<EOL><INDENT>os.remove(file_path)<EOL><DEDENT>new_hdr = fits.Header()<EOL>hdu = fits.PrimaryHDU(np.flipud(array_2d), new_hdr)<EOL>hdu.writeto(file_path)<EOL>

Write a 2D NumPy array to a .fits file.

    Before outputting a NumPy array, the array is flipped upside-down using np.flipud. This is so that the arrays \
    appear the same orientation as .fits files loaded in DS9.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is written to fits.
    file_path : str
        The full path of the file that is output, including the file name and '.fits' extension.
    overwrite : bool
        If True and a file already exists with the input file_path the .fits file is overwritten. If False, an error \
        will be raised.

    Returns
    -------
    None

    Examples
    --------
    array_2d = np.ones((5,5))
    numpy_array_to_fits(array=array_2d, file_path='/path/to/file/filename.fits', overwrite=True)


hdu_list = fits.open(file_path)<EOL>return np.flipud(np.array(hdu_list[hdu].data))<EOL>

Read a 2D NumPy array to a .fits file.

    After loading the NumPy array, the array is flipped upside-down using np.flipud. This is so that the arrays \
    appear the same orientation as .fits files loaded in DS9.

    Parameters
    ----------
    file_path : str
        The full path of the file that is loaded, including the file name and '.fits' extension.
    hdu : int
        The HDU extension of the array that is loaded from the .fits file.

    Returns
    -------
    ndarray
        The NumPy array that is loaded from the .fits file.

    Examples
    --------
    array_2d = numpy_array_from_fits(file_path='/path/to/file/filename.fits', hdu=0)


self.results = {}<EOL>self.calls = <NUM_LIT:0><EOL>self.arg_names = None<EOL>

Class to store the results of a function given a set of inputs.


if self.arg_names is not None:<EOL><INDENT>raise AssertionError("<STR_LIT>")<EOL><DEDENT>self.arg_names = inspect.getfullargspec(func).args<EOL>@wraps(func)<EOL>def wrapper(*args, **kwargs):<EOL><INDENT>key = "<STR_LIT:U+002CU+0020>".join(<EOL>["<STR_LIT>".format(arg_name, arg) for arg_name, arg in<EOL>list(zip(self.arg_names, args)) + [(k, v) for k, v in kwargs.items()]])<EOL>if key not in self.results:<EOL><INDENT>self.calls += <NUM_LIT:1><EOL><DEDENT>self.results[key] = func(*args, **kwargs)<EOL>return self.results[key]<EOL><DEDENT>return wrapper<EOL>

Memoize decorator. Any time a function is called that a memoizer has been attached to its results are stored in
the results dictionary or retrieved from the dictionary if the function has already been called with those
arguments.

Note that the same memoizer persists over all instances of a class. Any state for a given instance that is not
given in the representation of that instance will be ignored. That is, it is possible that the memoizer will
give incorrect results if instance state does not affect __str__ but does affect the value returned by the
memoized method.

Parameters
----------
func: function
    A function for which results should be memoized

Returns
-------
decorated : function
    A function that memoizes results


total_regular_pixels = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>total_regular_pixels += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>return total_regular_pixels<EOL>

Compute the total number of unmasked regular pixels in a masks.


return total_regular_pixels_from_mask(mask) * sub_grid_size ** <NUM_LIT:2><EOL>

Compute the total number of sub-pixels in unmasked regular pixels in a masks.


total_sparse_pixels = <NUM_LIT:0><EOL>for unmasked_sparse_pixel_index in range(unmasked_sparse_grid_pixel_centres.shape[<NUM_LIT:0>]):<EOL><INDENT>y = unmasked_sparse_grid_pixel_centres[unmasked_sparse_pixel_index, <NUM_LIT:0>]<EOL>x = unmasked_sparse_grid_pixel_centres[unmasked_sparse_pixel_index, <NUM_LIT:1>]<EOL>if not mask[y,x]:<EOL><INDENT>total_sparse_pixels += <NUM_LIT:1><EOL><DEDENT><DEDENT>return total_sparse_pixels<EOL>

Given the full (i.e. without removing pixels which are outside the regular-masks) pixelization grid's pixel centers
    and the regular-masks, compute the total number of pixels which are within the regular-masks and thus used by the
    pixelization grid.

    Parameters
    -----------
    mask : ccd.masks.Mask
        The regular-masks within which pixelization pixels must be inside
    unmasked_sparse_grid_pixel_centres : ndarray
        The centres of the unmasked pixelization grid pixels.


@decorator_util.jit()<EOL>def mask_circular_from_shape_pixel_scale_and_radius(shape, pixel_scale, radius_arcsec, centre=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

mask = np.full(shape, True)<EOL>centres_arcsec = mask_centres_from_shape_pixel_scale_and_centre(shape=mask.shape, pixel_scale=pixel_scale, centre=centre)<EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>y_arcsec = (y - centres_arcsec[<NUM_LIT:0>]) * pixel_scale<EOL>x_arcsec = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scale<EOL>r_arcsec = np.sqrt(x_arcsec ** <NUM_LIT:2> + y_arcsec ** <NUM_LIT:2>)<EOL>if r_arcsec <= radius_arcsec:<EOL><INDENT>mask[y, x] = False<EOL><DEDENT><DEDENT><DEDENT>return mask<EOL>

Compute a circular masks from an input masks radius and regular shape.


@decorator_util.jit()<EOL>def mask_circular_annular_from_shape_pixel_scale_and_radii(shape, pixel_scale, inner_radius_arcsec, outer_radius_arcsec,<EOL>centre=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

mask = np.full(shape, True)<EOL>centres_arcsec = mask_centres_from_shape_pixel_scale_and_centre(shape=mask.shape, pixel_scale=pixel_scale, centre=centre)<EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>y_arcsec = (y - centres_arcsec[<NUM_LIT:0>]) * pixel_scale<EOL>x_arcsec = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scale<EOL>r_arcsec = np.sqrt(x_arcsec ** <NUM_LIT:2> + y_arcsec ** <NUM_LIT:2>)<EOL>if outer_radius_arcsec >= r_arcsec >= inner_radius_arcsec:<EOL><INDENT>mask[y, x] = False<EOL><DEDENT><DEDENT><DEDENT>return mask<EOL>

Compute an annular masks from an input inner and outer masks radius and regular shape.


@decorator_util.jit()<EOL>def mask_circular_anti_annular_from_shape_pixel_scale_and_radii(shape, pixel_scale, inner_radius_arcsec, outer_radius_arcsec,<EOL>outer_radius_2_arcsec, centre=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

mask = np.full(shape, True)<EOL>centres_arcsec = mask_centres_from_shape_pixel_scale_and_centre(shape=mask.shape, pixel_scale=pixel_scale,<EOL>centre=centre)<EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>y_arcsec = (y - centres_arcsec[<NUM_LIT:0>]) * pixel_scale<EOL>x_arcsec = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scale<EOL>r_arcsec = np.sqrt(x_arcsec ** <NUM_LIT:2> + y_arcsec ** <NUM_LIT:2>)<EOL>if  inner_radius_arcsec >= r_arcsec or outer_radius_2_arcsec >= r_arcsec >= outer_radius_arcsec:<EOL><INDENT>mask[y, x] = False<EOL><DEDENT><DEDENT><DEDENT>return mask<EOL>


@decorator_util.jit()<EOL>def mask_elliptical_from_shape_pixel_scale_and_radius(shape, pixel_scale, major_axis_radius_arcsec, axis_ratio, phi,<EOL>centre=(<NUM_LIT:0.0>, <NUM_LIT:0.0>)):

mask = np.full(shape, True)<EOL>centres_arcsec = mask_centres_from_shape_pixel_scale_and_centre(shape=mask.shape, pixel_scale=pixel_scale,<EOL>centre=centre)<EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>y_arcsec = (y - centres_arcsec[<NUM_LIT:0>]) * pixel_scale<EOL>x_arcsec = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scale<EOL>r_arcsec_elliptical = elliptical_radius_from_y_x_phi_and_axis_ratio(y_arcsec, x_arcsec, phi, axis_ratio)<EOL>if r_arcsec_elliptical <= major_axis_radius_arcsec:<EOL><INDENT>mask[y, x] = False<EOL><DEDENT><DEDENT><DEDENT>return mask<EOL>


mask = np.full(shape, True)<EOL>centres_arcsec = mask_centres_from_shape_pixel_scale_and_centre(shape=mask.shape, pixel_scale=pixel_scale,<EOL>centre=centre)<EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>y_arcsec = (y - centres_arcsec[<NUM_LIT:0>]) * pixel_scale<EOL>x_arcsec = (x - centres_arcsec[<NUM_LIT:1>]) * pixel_scale<EOL>inner_r_arcsec_elliptical = elliptical_radius_from_y_x_phi_and_axis_ratio(y_arcsec, x_arcsec,<EOL>inner_phi, inner_axis_ratio)<EOL>outer_r_arcsec_elliptical = elliptical_radius_from_y_x_phi_and_axis_ratio(y_arcsec, x_arcsec,<EOL>outer_phi, outer_axis_ratio)<EOL>if inner_r_arcsec_elliptical >= inner_major_axis_radius_arcsec andouter_r_arcsec_elliptical <= outer_major_axis_radius_arcsec:<EOL><INDENT>mask[y, x] = False<EOL><DEDENT><DEDENT><DEDENT>return mask<EOL>


blurring_mask = np.full(mask.shape, True)<EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>for y1 in range((-psf_shape[<NUM_LIT:0>] + <NUM_LIT:1>) // <NUM_LIT:2>, (psf_shape[<NUM_LIT:0>] + <NUM_LIT:1>) // <NUM_LIT:2>):<EOL><INDENT>for x1 in range((-psf_shape[<NUM_LIT:1>] + <NUM_LIT:1>) // <NUM_LIT:2>, (psf_shape[<NUM_LIT:1>] + <NUM_LIT:1>) // <NUM_LIT:2>):<EOL><INDENT>if <NUM_LIT:0> <= x + x1 <= mask.shape[<NUM_LIT:1>] - <NUM_LIT:1> and <NUM_LIT:0> <= y + y1 <= mask.shape[<NUM_LIT:0>] - <NUM_LIT:1>:<EOL><INDENT>if mask[y + y1, x + x1]:<EOL><INDENT>blurring_mask[y + y1, x + x1] = False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise exc.MaskException(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>return blurring_mask<EOL>

Compute a blurring masks from an input masks and psf shape.

    The blurring masks corresponds to all pixels which are outside of the masks but will have a fraction of their \
    light blur into the masked region due to PSF convolution.


total_regular_pixels = total_regular_pixels_from_mask(mask)<EOL>grid_to_pixel = np.zeros(shape=(total_regular_pixels, <NUM_LIT:2>))<EOL>pixel_count = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>grid_to_pixel[pixel_count, :] = y, x<EOL>pixel_count += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>return grid_to_pixel<EOL>

Compute a 1D array that maps every unmasked pixel to its corresponding 2d pixel using its (y,x) pixel indexes.

    For howtolens if pixel [2,5] corresponds to the second pixel on the 1D array, grid_to_pixel[1] = [2,5]


total_sub_pixels = total_sub_pixels_from_mask_and_sub_grid_size(mask=mask, sub_grid_size=sub_grid_size)<EOL>sub_grid_to_sub_pixel = np.zeros(shape=(total_sub_pixels, <NUM_LIT:2>))<EOL>sub_pixel_count = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>for y1 in range(sub_grid_size):<EOL><INDENT>for x1 in range(sub_grid_size):<EOL><INDENT>sub_grid_to_sub_pixel[sub_pixel_count, :] = (y*sub_grid_size)+y1, (x*sub_grid_size)+x1<EOL>sub_pixel_count += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>return sub_grid_to_sub_pixel<EOL>


border_pixel_total = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>if mask[y + <NUM_LIT:1>, x] or mask[y - <NUM_LIT:1>, x] or mask[y, x + <NUM_LIT:1>] or mask[y, x - <NUM_LIT:1>] ormask[y + <NUM_LIT:1>, x + <NUM_LIT:1>] or mask[y + <NUM_LIT:1>, x - <NUM_LIT:1>] or mask[y - <NUM_LIT:1>, x + <NUM_LIT:1>] or mask[y - <NUM_LIT:1>, x - <NUM_LIT:1>]:<EOL><INDENT>border_pixel_total += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT><DEDENT>return border_pixel_total<EOL>

Compute the total number of borders-pixels in a masks.


edge_pixel_total = total_edge_pixels_from_mask(mask)<EOL>edge_pixels = np.zeros(edge_pixel_total)<EOL>edge_index = <NUM_LIT:0><EOL>regular_index = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>if mask[y + <NUM_LIT:1>, x] or mask[y - <NUM_LIT:1>, x] or mask[y, x + <NUM_LIT:1>] or mask[y, x - <NUM_LIT:1>] ormask[y + <NUM_LIT:1>, x + <NUM_LIT:1>] or mask[y + <NUM_LIT:1>, x - <NUM_LIT:1>] or mask[y - <NUM_LIT:1>, x + <NUM_LIT:1>] or mask[y - <NUM_LIT:1>, x - <NUM_LIT:1>]:<EOL><INDENT>edge_pixels[edge_index] = regular_index<EOL>edge_index += <NUM_LIT:1><EOL><DEDENT>regular_index += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>return edge_pixels<EOL>

Compute a 1D array listing all edge pixel indexes in the masks. An edge pixel is a pixel which is not fully \
    surrounding by False masks values i.e. it is on an edge.


border_pixel_total = <NUM_LIT:0><EOL>for i in range(edge_pixels.shape[<NUM_LIT:0>]):<EOL><INDENT>if check_if_border_pixel(mask, edge_pixels[i], masked_grid_index_to_pixel):<EOL><INDENT>border_pixel_total += <NUM_LIT:1><EOL><DEDENT><DEDENT>return border_pixel_total<EOL>


edge_pixels = edge_pixels_from_mask(mask)<EOL>masked_grid_index_to_pixel = masked_grid_1d_index_to_2d_pixel_index_from_mask(mask)<EOL>border_pixel_total = total_border_pixels_from_mask_and_edge_pixels(mask, edge_pixels, masked_grid_index_to_pixel)<EOL>border_pixels = np.zeros(border_pixel_total)<EOL>border_pixel_index = <NUM_LIT:0><EOL>for edge_pixel_index in range(edge_pixels.shape[<NUM_LIT:0>]):<EOL><INDENT>if check_if_border_pixel(mask, edge_pixels[edge_pixel_index], masked_grid_index_to_pixel):<EOL><INDENT>border_pixels[border_pixel_index] = edge_pixels[edge_pixel_index]<EOL>border_pixel_index += <NUM_LIT:1><EOL><DEDENT><DEDENT>return border_pixels<EOL>

Compute a 1D array listing all borders pixel indexes in the masks. A borders pixel is a pixel which:

     1) is not fully surrounding by False masks values.
     2) Can reach the edge of the array without hitting a masked pixel in one of four directions (upwards, downwards,
     left, right).

     The borders pixels are thus pixels which are on the exterior edge of the masks. For example, the inner ring of edge \
     pixels in an annular masks are edge pixels but not borders pixels.


padded_array_2d = array_util.pad_2d_array_for_binning_up_with_bin_up_factor(<EOL>array_2d=mask_2d, bin_up_factor=bin_up_factor, pad_value=True)<EOL>binned_array_2d = np.zeros(shape=(padded_array_2d.shape[<NUM_LIT:0>] // bin_up_factor,<EOL>padded_array_2d.shape[<NUM_LIT:1>] // bin_up_factor))<EOL>for y in range(binned_array_2d.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(binned_array_2d.shape[<NUM_LIT:1>]):<EOL><INDENT>value = True<EOL>for y1 in range(bin_up_factor):<EOL><INDENT>for x1 in range(bin_up_factor):<EOL><INDENT>padded_y = y*bin_up_factor + y1<EOL>padded_x = x*bin_up_factor + x1<EOL>if padded_array_2d[padded_y, padded_x] == False:<EOL><INDENT>value = False<EOL><DEDENT><DEDENT><DEDENT>binned_array_2d[y,x] = value<EOL><DEDENT><DEDENT>return binned_array_2d<EOL>

Bin up an array to coarser resolution, by binning up groups of pixels and using their sum value to determine \
     the value of the new pixel.

    If an array of shape (8,8) is input and the bin up size is 2, this would return a new array of size (4,4) where \
    every pixel was the sum of each collection of 2x2 pixels on the (8,8) array.

    If binning up the array leads to an edge being cut (e.g. a (9,9) array binned up by 2), an array is first \
    extracted around the centre of that array.

    Parameters
    ----------
    mask_2d : ndarray
        The 2D array that is resized.
    new_shape : (int, int)
        The (y,x) new pixel dimension of the trimmed array.
    origin : (int, int)
        The oigin of the resized array, e.g. the central pixel around which the array is extracted.

    Returns
    -------
    ndarray
        The resized 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    resize_array = resize_array_2d(array_2d=array_2d, new_shape=(2,2), origin=(2, 2))


indexes_2d = np.zeros((indexes_1d.shape[<NUM_LIT:0>], <NUM_LIT:2>))<EOL>for i, index_1d in enumerate(indexes_1d):<EOL><INDENT>indexes_2d[i, <NUM_LIT:0>] = int(index_1d / shape[<NUM_LIT:1>])<EOL>indexes_2d[i, <NUM_LIT:1>] = int(index_1d % shape[<NUM_LIT:1>])<EOL><DEDENT>return indexes_2d<EOL>

For pixels on a 2D array of shape (rows, colums), map an array of 1D pixel indexes to 2D pixel indexes.

    Indexing is defined from the top-left corner rightwards and downwards, whereby the top-left pixel on the 2D array
    corresponds to index 0, the pixel to its right pixel 1, and so on.

    For a 2D array of shape (3,3), 1D pixel indexes are converted as follows:

    - 1D Pixel index 0 maps -> 2D pixel index [0,0].
    - 1D Pixel index 1 maps -> 2D pixel index [0,1].
    - 1D Pixel index 4 maps -> 2D pixel index [1,0].
    - 1D Pixel index 8 maps -> 2D pixel index [2,2].

    Parameters
     ----------
    indexes_1d : ndarray
        The 1D pixel indexes which are mapped to 2D indexes.
    shape : (int, int)
        The shape of the 2D array which the pixels are defined on.

    Returns
    --------
    ndarray
        An array of 2d pixel indexes with dimensions (total_indexes, 2).

    Examples
    --------
    indexes_1d = np.array([0, 1, 2, 5])
    indexes_2d = map_1d_indexes_to_2d_indexes_for_shape(indexes_1d=indexes_1d, shape=(3,3))


indexes_1d = np.zeros(indexes_2d.shape[<NUM_LIT:0>])<EOL>for i in range(indexes_2d.shape[<NUM_LIT:0>]):<EOL><INDENT>indexes_1d[i] = int((indexes_2d[i, <NUM_LIT:0>]) * shape[<NUM_LIT:1>] + indexes_2d[i, <NUM_LIT:1>])<EOL><DEDENT>return indexes_1d<EOL>

For pixels on a 2D array of shape (rows, colums), map an array of 2D pixel indexes to 1D pixel indexes.

    Indexing is defined from the top-left corner rightwards and downwards, whereby the top-left pixel on the 2D array
    corresponds to index 0, the pixel to its right pixel 1, and so on.

    For a 2D array of shape (3,3), 2D pixel indexes are converted as follows:

    - 2D Pixel index [0,0] maps -> 1D pixel index 0.
    - 2D Pixel index [0,1] maps -> 2D pixel index 1.
    - 2D Pixel index [1,0] maps -> 2D pixel index 4.
    - 2D Pixel index [2,2] maps -> 2D pixel index 8.

    Parameters
     ----------
    indexes_2d : ndarray
        The 2D pixel indexes which are mapped to 1D indexes.
    shape : (int, int)
        The shape of the 2D array which the pixels are defined on.

    Returns
    --------
    ndarray
        An array of 1d pixel indexes with dimensions (total_indexes).

    Examples
    --------
    indexes_2d = np.array([[0,0], [1,0], [2,0], [2,2]])
    indexes_1d = map_1d_indexes_to_1d_indexes_for_shape(indexes_2d=indexes_2d, shape=(3,3))


total_sub_pixels = mask_util.total_sub_pixels_from_mask_and_sub_grid_size(mask=mask, sub_grid_size=sub_grid_size)<EOL>sub_to_regular = np.zeros(shape=total_sub_pixels)<EOL>regular_index = <NUM_LIT:0><EOL>sub_index = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>for y1 in range(sub_grid_size):<EOL><INDENT>for x1 in range(sub_grid_size):<EOL><INDENT>sub_to_regular[sub_index] = regular_index<EOL>sub_index += <NUM_LIT:1><EOL><DEDENT><DEDENT>regular_index += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>return sub_to_regular<EOL>

For pixels on a 2D array of shape (rows, colums), compute a 1D array which, for every unmasked pixel on
    this 2D array, maps the 1D sub-pixel indexes to their 1D pixel indexes.

    For example, the following mappings from sub-pixels to 2D array pixels are:

    - sub_to_regular[0] = 0 -> The first sub-pixel maps to the first unmasked pixel on the regular 2D array.
    - sub_to_regular[3] = 0 -> The fourth sub-pixel maps to the first unmaksed pixel on the regular 2D array.
    - sub_to_regular[7] = 1 -> The eighth sub-pixel maps to the second unmasked pixel on the regular 2D array.

    The term 'regular' is used because the regular-grid is defined as the grid of coordinates on the centre of every \
    pixel on the 2D array. Thus, this array maps sub-pixels on a sub-grid to regular-pixels on a regular-grid.

    Parameters
     ----------
    mask : ndarray
        A 2D array of bools, where *False* values mean unmasked and are therefore included as part of the sub-grid 2D \
        array's regular grid and sub-grid.
    sub_grid_size : int
        The size of the sub-grid that each pixel of the 2D array is divided into.

    Returns
    --------
    ndarray
        An array of integers which maps every sub-pixel index to regular-pixel index with dimensions
        (total_unmasked_pixels*sub_grid_size**2).

    Examples
    --------
    mask = np.array([[True, False, True],
                     [False, False, False]
                     [True, False, True]])
    sub_to_regular = sub_to_regular_from_mask(mask=mask, sub_grid_size=2)


total_image_pixels = mask_util.total_regular_pixels_from_mask(mask)<EOL>array_1d = np.zeros(shape=total_image_pixels)<EOL>index = <NUM_LIT:0><EOL>for y in range(mask.shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(mask.shape[<NUM_LIT:1>]):<EOL><INDENT>if not mask[y, x]:<EOL><INDENT>array_1d[index] = array_2d[y, x]<EOL>index += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>return array_1d<EOL>

For a 2D array and mask, map the values of all unmasked pixels to a 1D array.

    The pixel coordinate origin is at the top left corner of the 2D array and goes right-wards and downwards, such
    that for an array of shape (3,3) where all pixels are unmasked:

    - pixel [0,0] of the 2D array will correspond to index 0 of the 1D array.
    - pixel [0,1] of the 2D array will correspond to index 1 of the 1D array.
    - pixel [1,0] of the 2D array will correspond to index 4 of the 1D array.

    Parameters
     ----------
    mask : ndarray
        A 2D array of bools, where *False* values mean unmasked and are included in the mapping.
    array_2d : ndarray
        The 2D array of values which are mapped to a 1D array.

    Returns
    --------
    ndarray
        A 1D array of values mapped from the 2D array with dimensions (total_unmasked_pixels).

    Examples
    --------
    mask = np.array([[True, False, True],
                     [False, False, False]
                     [True, False, True]])

    array_2d = np.array([[1.0, 2.0, 3.0],
                          [4.0, 5.0, 6.0],
                          [7.0, 8.0, 9.0]])

    array_1d = map_2d_array_to_masked_1d_array_from_array_2d_and_mask(mask=mask, array_2d=array_2d)


array_2d = np.zeros(shape)<EOL>for index in range(len(one_to_two)):<EOL><INDENT>array_2d[one_to_two[index, <NUM_LIT:0>], one_to_two[index, <NUM_LIT:1>]] = array_1d[index]<EOL><DEDENT>return array_2d<EOL>

For a 1D array that was computed by mapping unmasked values from a 2D array of shape (rows, columns), map its \
    values back to the original 2D array where masked values are set to zero.

    This uses a 1D array 'one_to_two' where each index gives the 2D pixel indexes of the 1D array's unmasked pixels, \
    for example:

    - If one_to_two[0] = [0,0], the first value of the 1D array maps to the pixel [0,0] of the 2D array.
    - If one_to_two[1] = [0,1], the second value of the 1D array maps to the pixel [0,1] of the 2D array.
    - If one_to_two[4] = [1,1], the fifth value of the 1D array maps to the pixel [1,1] of the 2D array.

    Parameters
     ----------
    array_1d : ndarray
        The 1D array of values which are mapped to a 2D array.
    shape : (int, int)
        The shape of the 2D array which the pixels are defined on.
    one_to_two : ndarray
        An array describing the 2D array index that every 1D array index maps too.

    Returns
    --------
    ndarray
        A 2D array of values mapped from the 1D array with dimensions shape.

    Examples
    --------
    one_to_two = np.array([[0,1], [1,0], [1,1], [1,2], [2,1]])

    array_1d = np.array([[2.0, 4.0, 5.0, 6.0, 8.0])

    array_2d = map_masked_1d_array_to_2d_array_from_array_1d_shape_and_one_to_two(array_1d=array_1d, shape=(3,3),
                                                                                one_to_two=one_to_two)


array_2d = np.zeros(shape)<EOL>index = <NUM_LIT:0><EOL>for y in range(shape[<NUM_LIT:0>]):<EOL><INDENT>for x in range(shape[<NUM_LIT:1>]):<EOL><INDENT>array_2d[y, x] = array_1d[index]<EOL>index += <NUM_LIT:1><EOL><DEDENT><DEDENT>return array_2d<EOL>

For a 1D array that was flattened from a 2D array of shape (rows, columns), map its values back to the \
    original 2D array.

    The pixel coordinate origin is at the top left corner of the 2D array and goes right-wards and downwards, such
    that for an array of shape (3,3):

    - pixel 0 of the 1D array will correspond to index [0,0] of the 2D array.
    - pixel 1 of the 1D array will correspond to index [0,1] of the 2D array.
    - pixel 4 of the 1D array will correspond to index [1,0] of the 2D array.

    Parameters
     ----------
    array_1d : ndarray
        The 1D array of values which are mapped to a 2D array.
    shape : (int, int)
        The shape of the 2D array which the pixels are defined on.

    Returns
    --------
    ndarray
        A 2D array of values mapped from the 1D array with dimensions (shape).

    Examples
    --------
    one_to_two = np.array([[0,1], [1,0], [1,1], [1,2], [2,1]])

    array_1d = np.array([[2.0, 4.0, 5.0, 6.0, 8.0])

    array_2d = map_masked_1d_array_to_2d_array_from_array_1d_shape_and_one_to_two(array_1d=array_1d, shape=(3,3),
                                                                                one_to_two=one_to_two)


pix_to_full_pix = np.zeros(total_sparse_pixels)<EOL>pixel_index = <NUM_LIT:0><EOL>for full_pixel_index in range(unmasked_sparse_grid_pixel_centres.shape[<NUM_LIT:0>]):<EOL><INDENT>y = unmasked_sparse_grid_pixel_centres[full_pixel_index, <NUM_LIT:0>]<EOL>x = unmasked_sparse_grid_pixel_centres[full_pixel_index, <NUM_LIT:1>]<EOL>if not mask[y, x]:<EOL><INDENT>pix_to_full_pix[pixel_index] = full_pixel_index<EOL>pixel_index += <NUM_LIT:1><EOL><DEDENT><DEDENT>return pix_to_full_pix<EOL>

Determine the mapping between every masked pixelization-grid pixel and pixelization-grid pixel. This is
    performed by checking whether each pixelization-grid pixel is within the regular-masks, and mapping the indexes.

    Parameters
    -----------
    total_sparse_pixels : int
        The total number of pixels in the pixelization grid which fall within the regular-masks.
    mask : ccd.masks.Mask
        The regular-masks within which pixelization pixels must be inside
    unmasked_sparse_grid_pixel_centres : ndarray
        The centres of the unmasked pixelization grid pixels.