Ejemplo n.º 1
0
    def test__grid_from_grid_slim(self):

        grid = aa.Grid2DIrregularUniform(grid=[(1.0, 1.0), (2.0, 2.0)],
                                         pixel_scales=(1.0, 1.0),
                                         shape_native=(3, 3))

        grid_from_1d = grid.grid_from_grid_slim(
            grid_slim=np.array([[1.0, 1.0], [2.0, 2.0]]))

        assert type(grid_from_1d) == aa.Grid2DIrregularUniform
        assert grid_from_1d.in_list == [(1.0, 1.0), (2.0, 2.0)]
        assert grid.pixel_scales == (1.0, 1.0)
        assert grid.shape_native == (3, 3)

        grid = aa.Grid2DIrregularUniform(
            grid=[(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)],
            pixel_scales=(1.0, 3.0),
            shape_native=(5, 5),
        )

        grid_from_1d = grid.grid_from_grid_slim(
            grid_slim=np.array([[1.0, 1.0], [2.0, 2.0], [3.0, 3.0]]))

        assert type(grid_from_1d) == aa.Grid2DIrregularUniform
        assert grid_from_1d.in_list == [(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)]
        assert grid.pixel_scales == (1.0, 3.0)
        assert grid.shape_native == (5, 5)
Ejemplo n.º 2
0
    def grid_buffed_and_upscaled_around_coordinate_from(
            self, coordinate, pixel_scales, buffer, upscale_factor):
        """
        For an input (y,x) Catersian coordinate create a buffed and upscaled square grid of (y,x) coordinates where:

            - The new grid of coordinates are buffed. For example, if buffer=1, the new grid will correspond to a 3x3 grid
              of coordinates centred on the input (y,x) value with spacings defined by the input pixel_scales.

            - The new grid is upscaled. For example, if upscale=2, the new grid will be at x2 the resolution of the input
              pixel_scale.

            Buffing and upscaling work together, so a buffer=2 and upscale=2 will produce a new 6x6 grid centred around the
            input coordinate.

            The `PositionFinder` works by locating pixels that trace closer to the source galaxy than neighboring pixels
            and iteratively refining the grid to find pixels that trace close at higher and higher resolutions. This
            function is core to producing these upscaled grids.

            Parameters
            ----------
            coordinate : (float, float)
                The (y,x) Cartesian coordinates aroun which the buffed and upscaled grid is created.
            pixel_scales : (float, float)
                The pixel-scale resolution of the buffed and upscaled grid that is formed around the input coordinate. If
                upscale > 1, the pixel_scales are reduced to pixel_scale / upscale_factor.
            buffer
                The number of pixels around the central (y,x) coordinate that the grid is computed on, i.e. how much it is
                buffed. A buffer of 1 puts 1 pixel in every direction around the (y,x) coordinate, creating a 3x3 grid. A
                buffer=2 places two pixels around it in every direction, creating a 5x5 grid. And so on.
            upscale_factor
                The factor by which the resolution of the grid is increased relative to the input pixel-scales.
        """

        if self.use_upscaling:
            upscale_factor = upscale_factor
        else:
            upscale_factor = 1

        grid_buffed = grid_buffed_around_coordinate_from(
            coordinate=coordinate,
            pixel_scales=pixel_scales,
            buffer=buffer,
            upscale_factor=upscale_factor,
        )

        return aa.Grid2DIrregularUniform(
            grid=grid_buffed,
            pixel_scales=(
                pixel_scales[0] / upscale_factor,
                pixel_scales[1] / upscale_factor,
            ),
        )
Ejemplo n.º 3
0
    def test__grid_from_deflection_grid(self):

        grid = aa.Grid2DIrregularUniform(grid=[(1.0, 1.0), (2.0, 2.0)],
                                         pixel_scales=(1.0, 1.0),
                                         shape_native=(3, 3))

        grid = grid.grid_from_deflection_grid(
            deflection_grid=np.array([[1.0, 0.0], [1.0, 1.0]]))

        assert type(grid) == aa.Grid2DIrregularUniform
        assert grid.in_list == [(0.0, 1.0), (1.0, 1.0)]
        assert grid.pixel_scales == (1.0, 1.0)
        assert grid.shape_native == (3, 3)
Ejemplo n.º 4
0
    def test__from_sparse_uniform_upscale(self):

        grid_sparse_uniform = aa.Grid2DIrregularUniform(grid=[[(1.0, 1.0),
                                                               (1.0, 3.0)]],
                                                        pixel_scales=2.0)

        grid_upscale = aa.Grid2DIrregularUniform.from_grid_sparse_uniform_upscale(
            grid_sparse_uniform=grid_sparse_uniform,
            upscale_factor=2,
            pixel_scales=2.0)

        assert (grid_upscale == np.array([
            [1.5, 0.5],
            [1.5, 1.5],
            [0.5, 0.5],
            [0.5, 1.5],
            [1.5, 2.5],
            [1.5, 3.5],
            [0.5, 2.5],
            [0.5, 3.5],
        ])).all()

        grid_sparse_uniform = aa.Grid2DIrregularUniform(grid=[[(1.0, 1.0),
                                                               (1.0, 3.0),
                                                               (1.0, 5.0),
                                                               (3.0, 3.0)]],
                                                        pixel_scales=2.0)

        grid_upscale = aa.Grid2DIrregularUniform.from_grid_sparse_uniform_upscale(
            grid_sparse_uniform=grid_sparse_uniform,
            upscale_factor=4,
            pixel_scales=2.0)

        grid_upscale_util = aa.util.grid_2d.grid_2d_slim_upscaled_from(
            grid_slim=grid_sparse_uniform,
            upscale_factor=4,
            pixel_scales=(2.0, 2.0))

        assert (grid_upscale == grid_upscale_util).all()
Ejemplo n.º 5
0
    def grid_within_distance_of_source_plane_centre(self, deflection_func,
                                                    source_plane_coordinate,
                                                    grid, distance):
        """
        For an input grid of (y,x) coordinates, remove all coordinates that do not trace within a threshold distance
            of the source-plane centre. This is performed by:

             1) Computing the deflection angle of every (y,x) coordinate on the grid using the input lensing object.
             2) Ray tracing these coordinates to the source-plane.
             3) Computing their distance to the centre of the source in the source-plane.
             4) Removing all coordinates that are not within the input distance of the centre.

            This algorithm is optionally used in the _PositionFiner_. It may be required to remove solutions that are
            genuine 'peaks' that tracer closer to a source than their 8 neighboring pixels, but which do not truly
            trace to the centre of the source-centre.

            Parameters
            ----------
            lensing_obj
                An object which has a `deflection_2d_from` method for performing lensing calculations, for example a
                `MassProfile`, _Galaxy_, `Plane` or `Tracer`.
            grid : autoarray.Grid2DIrregularUniform or ndarray
                A grid of (y,x) Cartesian coordinates for which the 'peak' values that trace closer to the source than
                their neighbors are found.
            source_plane_coordinate : (y,x)
                The (y,x) coordinate in the source-plane pixels that the distance of traced grid coordinates are computed
                for.
            distance
                The distance within which a grid coordinate must trace to the source-plane centre to be retained.
        """
        if distance is None:
            return grid

        deflections = deflection_func(grid=grid)
        source_plane_grid = grid.grid_2d_via_deflection_grid_from(
            deflection_grid=deflections)
        source_plane_distances = source_plane_grid.distances_to_coordinate_from(
            coordinate=source_plane_coordinate)

        grid_within_distance_of_centre = grid_within_distance(
            distances_1d=source_plane_distances,
            grid_slim=grid,
            within_distance=distance,
        )

        return aa.Grid2DIrregularUniform(grid=grid_within_distance_of_centre,
                                         pixel_scales=grid.pixel_scales)
Ejemplo n.º 6
0
    def grid_peaks_from(self, deflections_func, grid, source_plane_coordinate):
        """
        Find the 'peaks' of a grid of coordinates, where a peak corresponds to a (y,x) coordinate on the grid which
        traces closer to the input (y,x) source-plane coordinate than any of its 8 adjacent neighbors. This is
        performed by:

         1) Computing the deflection angle of every (y,x) coordinate on the grid using the input lensing object.
         2) Ray tracing these coordinates to the source-plane.
         3) Computing their distance to the centre of the source in the source-plane.
         4) Finding pixels whose source-plane distance is lower than all 8 neighboring pixels.

        The `PositionFinder` works by locating pixels that trace closer to the source galaxy than neighboring pixels
        and iteratively refining the grid to find pixels that trace close at higher and higher resolutions. This
        function is core to finding pixelsl that meet this criteria.

        Parameters
        ----------
        lensing_obj
            An object which has a `deflection_2d_from` method for performing lensing calculations, for example a
            `MassProfile`, _Galaxy_, `Plane` or `Tracer`.
        grid : autoarray.Grid2DIrregularUniform or ndarray
            A grid of (y,x) Cartesian coordinates for which the 'peak' values that trace closer to the source than
            their neighbors are found.
        source_plane_coordinate : (y,x)
            The (y,x) coordinate in the source-plane pixels that the distance of traced grid coordinates are computed
            for.
        """

        deflections = deflections_func(grid=grid)
        source_plane_grid = grid.grid_2d_via_deflection_grid_from(
            deflection_grid=deflections)

        source_plane_distances = source_plane_grid.distances_to_coordinate_from(
            coordinate=source_plane_coordinate)

        neighbors, has_neighbors = grid_square_neighbors_1d_from(
            shape_slim=grid.shape[0])

        grid_peaks = grid_peaks_from(
            distance_1d=source_plane_distances,
            grid_slim=grid,
            neighbors=neighbors.astype("int"),
            has_neighbors=has_neighbors,
        )

        return aa.Grid2DIrregularUniform(grid=grid_peaks,
                                         pixel_scales=grid.pixel_scales)
Ejemplo n.º 7
0
    def grid_with_points_below_magnification_threshold_removed(
            self, lensing_obj, deflections_func, grid):

        magnifications = np.abs(
            lensing_obj.magnification_2d_via_hessian_from(
                grid=grid,
                buffer=grid.pixel_scale,
                deflections_func=deflections_func))

        grid_mag = []

        for index, magnification in enumerate(magnifications):
            if magnification > self.magnification_threshold:
                grid_mag.append(grid[index, :])

        return aa.Grid2DIrregularUniform(grid=grid_mag,
                                         pixel_scales=grid.pixel_scales)
Ejemplo n.º 8
0
    def grid_with_coordinates_to_mass_profile_centre_removed_from(
            self, lensing_obj, grid):
        """Remove all coordinates from a grid which are within the distance_to_mass_profile_centre attribute of any
        mass profile of the lensing object.

        The `PositionFinder` often finds multiple unphyiscal solutions near a mass profile due to the high levels of
        demagnification. These are typically not observable in real galaxies and thus may benefit from being removed
        from the PositionFiner.

        The positions are removed by computing the distance between all grid points and the mass profile centres of
        every mass profile in the lensing object.

        Parameters
        ----------
        lensing_obj
            An object which has a `deflection_2d_from` method for performing lensing calculations, for example a
            `MassProfile`, _Galaxy_, `Plane` or `Tracer`.
        grid : autoarray.Grid2DIrregularUniform or ndarray
            A gridd of (y,x) Cartesian coordinates for which their distances to the mass profile centres are computed,
            with points within the threshold removed.
        """
        if self.distance_to_mass_profile_centre is not None:

            pixel_scales = grid.pixel_scales

            centres = lensing_obj.extract_attribute(cls=ag.mp.MassProfile,
                                                    attr_name="centre")

            for centre in centres.in_list:

                distances_1d = np.sqrt(
                    np.square(grid[:, 0] - centre[0]) +
                    np.square(grid[:, 1] - centre[1]))

                grid = grid_outside_distance_mask_from(
                    distances_1d=distances_1d,
                    grid_slim=grid,
                    outside_distance=self.distance_to_mass_profile_centre,
                )

            return aa.Grid2DIrregularUniform(grid=grid,
                                             pixel_scales=pixel_scales)

        return grid
Ejemplo n.º 9
0
    def solve(self,
              lensing_obj,
              source_plane_coordinate,
              upper_plane_index=None):

        if upper_plane_index is None:
            deflections_func = lensing_obj.deflections_yx_2d_from
        else:
            deflections_func = partial(
                lensing_obj.deflections_between_planes_from,
                plane_i=0,
                plane_j=upper_plane_index,
            )

        coordinates_list = self.grid_peaks_from(
            grid=self.grid,
            source_plane_coordinate=source_plane_coordinate,
            deflections_func=deflections_func,
        )

        coordinates_list = self.grid_with_coordinates_to_mass_profile_centre_removed_from(
            lensing_obj=lensing_obj, grid=coordinates_list)

        coordinates_list = self.grid_with_points_below_magnification_threshold_removed(
            lensing_obj=lensing_obj,
            deflections_func=deflections_func,
            grid=coordinates_list,
        )

        if not self.use_upscaling:

            coordinates_list = self.grid_within_distance_of_source_plane_centre(
                deflection_func=deflections_func,
                grid=aa.Grid2DIrregularUniform(
                    grid=coordinates_list,
                    pixel_scales=self.grid.pixel_scales),
                source_plane_coordinate=source_plane_coordinate,
                distance=self.distance_to_source_centre,
            )

            return aa.Grid2DIrregular(grid=coordinates_list)

        pixel_scale = self.grid.pixel_scale

        while pixel_scale > self.pixel_scale_precision:

            refined_coordinates_list = []

            for coordinate in coordinates_list:

                refined_coordinates = self.refined_coordinates_from(
                    deflections_func=deflections_func,
                    coordinate=coordinate,
                    pixel_scale=pixel_scale,
                    source_plane_coordinate=source_plane_coordinate,
                )

                if refined_coordinates is not None:
                    refined_coordinates_list += refined_coordinates

            refined_coordinates_list = grid_remove_duplicates(
                grid=np.asarray(refined_coordinates_list))

            pixel_scale = pixel_scale / self.upscale_factor

            coordinates_list = refined_coordinates_list

        coordinates_list = self.grid_within_distance_of_source_plane_centre(
            deflection_func=deflections_func,
            grid=aa.Grid2DIrregularUniform(grid=coordinates_list,
                                           pixel_scales=(pixel_scale,
                                                         pixel_scale)),
            source_plane_coordinate=source_plane_coordinate,
            distance=self.distance_to_source_centre,
        )

        coordinates_list = self.grid_with_points_below_magnification_threshold_removed(
            lensing_obj=lensing_obj,
            deflections_func=deflections_func,
            grid=coordinates_list,
        )

        return aa.Grid2DIrregular(grid=coordinates_list)