def test__plot_grid_list(self): line = aplt.GridPlot(linewidth=2, linestyle="--", c="k") line.plot_grid_list( grid_list=[aa.Grid2DIrregular([(1.0, 1.0), (2.0, 2.0)])]) line.plot_grid_list(grid_list=[ aa.Grid2DIrregular([(1.0, 1.0), (2.0, 2.0)]), aa.Grid2DIrregular([(3.0, 3.0)]), ])
def test__values_from_value(self): grid = aa.Grid2DIrregular(grid=[(1.0, 1.0), (2.0, 2.0)]) values_from_value = grid.values_from_value(value=1.0) assert values_from_value.in_list == [1.0, 1.0]
def test__input_grids_as_different_types__all_converted_to_grid_irregular_correctly( ): # Input tuples vector_field = aa.VectorField2DIrregular( vectors=[(1.0, -1.0), (1.0, 1.0)], grid=aa.Grid2DIrregular([[1.0, -1.0], [1.0, 1.0]]), ) assert type(vector_field.grid) == aa.Grid2DIrregular assert (vector_field.grid == np.array([[1.0, -1.0], [1.0, 1.0]])).all() # Input np array vector_field = aa.VectorField2DIrregular(vectors=[(1.0, -1.0), (1.0, 1.0)], grid=[[1.0, -1.0], [1.0, 1.0]]) assert type(vector_field.grid) == aa.Grid2DIrregular assert (vector_field.grid == np.array([[1.0, -1.0], [1.0, 1.0]])).all() # Input list vector_field = aa.VectorField2DIrregular(vectors=[(1.0, -1.0), (1.0, 1.0)], grid=[(1.0, -1.0), (1.0, 1.0)]) assert type(vector_field.grid) == aa.Grid2DIrregular assert (vector_field.grid == np.array([[1.0, -1.0], [1.0, 1.0]])).all()
def caustics_from( self, grid, pixel_scale: Union[Tuple[float, float], float] = 0.05 ) -> List[aa.Grid2DIrregular]: """ Returns the both the tangential and radial caustics of lensing object as a two entry list of irregular 2D grids. The calculation of each caustic is described in the functions `tangential_caustic_from()` and `radial_caustic_from()`. Due to the use of a marching squares algorithm used in each function, caustics can only be calculated using the Jacobian and a uniform 2D grid. Parameters ---------- grid The 2D grid of (y,x) arc-second coordinates the deflection angles used to calculate the caustics are computed on. pixel_scale If input, the `evaluation_grid` decorator creates the 2D grid at this resolution, therefore enabling the caustic to be computed more accurately using a higher resolution grid. """ try: return aa.Grid2DIrregular([ self.tangential_caustic_from(grid=grid, pixel_scale=pixel_scale), self.radial_caustic_from(grid=grid, pixel_scale=pixel_scale), ]) except (IndexError, ValueError): return []
def test__from_and_to_file_json(self): grid = aa.Grid2DIrregular(grid=[(6.0, 6.0), (7.0, 7.0), (8.0, 8.0)]) output_grid_dir = path.join( "{}".format(os.path.dirname(os.path.realpath(__file__))), "files", "grid", "output_test", ) file_path = path.join(output_grid_dir, "grid_test.json") if os.path.exists(output_grid_dir): shutil.rmtree(output_grid_dir) os.makedirs(output_grid_dir) grid.output_to_json(file_path=file_path) grid = aa.Grid2DIrregular.from_json(file_path=file_path) assert grid.in_list == [(6.0, 6.0), (7.0, 7.0), (8.0, 8.0)] with pytest.raises(FileExistsError): grid.output_to_json(file_path=file_path) grid.output_to_json(file_path=file_path, overwrite=True)
def extract_attribute(self, cls, attr_name): """ Returns an attribute of a class and its children profiles in the the galaxy as a `ValueIrregular` or `Grid2DIrregular` object. For example, if a galaxy has two light profiles and we want the `LightProfile` axis-ratios, the following: `galaxy.extract_attribute(cls=LightProfile, name="axis_ratio"` would return: ValuesIrregular(values=[axis_ratio_0, axis_ratio_1]) If a galaxy has three mass profiles and we want the `MassProfile` centres, the following: `galaxy.extract_attribute(cls=MassProfile, name="centres"` would return: GridIrregular2D(grid=[(centre_y_0, centre_x_0), (centre_y_1, centre_x_1), (centre_y_2, centre_x_2)]) This is used for visualization, for example plotting the centres of all light profiles colored by their profile. """ if isinstance(self, cls): if hasattr(self, attr_name): attribute = getattr(self, attr_name) if isinstance(attribute, float): return aa.ValuesIrregular(values=[attribute]) if isinstance(attribute, tuple): return aa.Grid2DIrregular(grid=[attribute])
def test__values_from_array_slim(self): grid = aa.Grid2DIrregular(grid=[(1.0, 1.0), (2.0, 2.0)]) values_from_1d = grid.values_from_array_slim( array_slim=np.array([1.0, 2.0])) assert isinstance(values_from_1d, aa.ValuesIrregular) assert values_from_1d.in_list == [1.0, 2.0] grid = aa.Grid2DIrregular(grid=[(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)]) values_from_1d = grid.values_from_array_slim( array_slim=np.array([1.0, 2.0, 3.0])) assert isinstance(values_from_1d, aa.ValuesIrregular) assert values_from_1d.in_list == [1.0, 2.0, 3.0]
def test__grid_from_grid_slim(self): grid = aa.Grid2DIrregular(grid=[(1.0, 1.0), (2.0, 2.0)]) 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.Grid2DIrregular assert grid_from_1d.in_list == [(1.0, 1.0), (2.0, 2.0)] grid = aa.Grid2DIrregular(grid=[(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)]) 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.Grid2DIrregular assert grid_from_1d.in_list == [(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)]
def test__grid_from_deflection_grid(self): grid = aa.Grid2DIrregular(grid=[(1.0, 1.0), (2.0, 2.0)]) grid = grid.grid_from_deflection_grid( deflection_grid=np.array([[1.0, 0.0], [1.0, 1.0]])) assert type(grid) == aa.Grid2DIrregular assert grid.in_list == [(0.0, 1.0), (1.0, 1.0)]
def __init__( self, name: str, positions: Union[aa.Grid2DIrregular, List[List], List[Tuple]], positions_noise_map: Union[aa.ValuesIrregular, List[float]], fluxes: Optional[Union[aa.ValuesIrregular, List[float]]] = None, fluxes_noise_map: Optional[Union[aa.ValuesIrregular, List[float]]] = None, ): """ A collection of the data component that can be used for point-source model-fitting, for example fitting the observed positions of a a strongly lensed quasar or supernovae or in strong lens cluster modeling, where there may be many tens or hundreds of individual source galaxies each of which are modeled as a point source. The name of the dataset is required for point-source model-fitting, as it pairs a point-source dataset with its corresponding point-source in the model-fit. For example, if a dataset has the name `source_1`, it will be paired with the `Point` model-component which has the name `source_1`. If a dataset component is not successfully paired with a model-component, an error is raised. Parameters ---------- name The name of the point source dataset which is paired to a `Point` in the `Model`. positions The image-plane (y,x) positions of the point-source. positions_noise_map The noise-value of every (y,x) position, which is typically the pixel-scale of the data. fluxes The image-plane flux of each observed point-source of light. fluxes_noise_map The noise-value of every observed flux. """ self.name = name if not isinstance(positions, aa.Grid2DIrregular): positions = aa.Grid2DIrregular(grid=positions) self.positions = positions if not isinstance(positions_noise_map, aa.ValuesIrregular): positions_noise_map = aa.ValuesIrregular( values=positions_noise_map) self.positions_noise_map = positions_noise_map if fluxes is not None: if not isinstance(fluxes, aa.ValuesIrregular): fluxes = aa.ValuesIrregular(values=fluxes) self.fluxes = fluxes if fluxes_noise_map is not None: if not isinstance(fluxes_noise_map, aa.ValuesIrregular): fluxes_noise_map = aa.ValuesIrregular(values=fluxes_noise_map) self.fluxes_noise_map = fluxes_noise_map
def test__errorbar_coordinates(self): errorbar = aplt.GridErrorbar(marker="x", c="k") errorbar.errorbar_grid_list( grid_list=[aa.Grid2DIrregular([(1.0, 1.0), (2.0, 2.0)])], y_errors=[1.0] * 2, x_errors=[1.0] * 2, )
def test__grid_2d_irregular_in__output_values_projected_format(self): grid_2d = aa.Grid2DIrregular(grid=[[0.0, 0.0], [0.0, 1.0], [0.0, 2.0]]) grid_like_object = MockGrid1DLikeObj() array_output = grid_like_object.ndarray_1d_from_grid(grid=grid_2d) assert isinstance(array_output, aa.ValuesIrregular) assert (array_output == np.array([1.0, 1.0, 1.0])).all()
def tracer_via_instance_from( self, instance: af.ModelInstance, profiling_dict: Optional[Dict] = None ) -> Tracer: """ Create a `Tracer` from the galaxies contained in a model instance. If PyAutoFit's profiling tools are used with the analsyis class, this function may receive a `profiling_dict` which times how long each set of the model-fit takes to perform. Parameters ---------- instance An instance of the model that is fitted to the data by this analysis (whose parameters may have been set via a non-linear search). Returns ------- Tracer An instance of the Tracer class that is used to then fit the dataset. """ if hasattr(instance, "perturbation"): instance.galaxies.subhalo = instance.perturbation # TODO : Need to think about how we do this without building it into the model attribute names. # TODO : A Subhalo class that extends the Galaxy class maybe? if hasattr(instance.galaxies, "subhalo"): subhalo_centre = ray_tracing_util.grid_2d_at_redshift_from( galaxies=instance.galaxies, redshift=instance.galaxies.subhalo.redshift, grid=aa.Grid2DIrregular(grid=[instance.galaxies.subhalo.mass.centre]), cosmology=self.cosmology, ) instance.galaxies.subhalo.mass.centre = tuple(subhalo_centre.in_list[0]) if hasattr(instance, "clumps"): return Tracer.from_galaxies( galaxies=instance.galaxies + instance.clumps, cosmology=self.cosmology, profiling_dict=profiling_dict, ) if hasattr(instance, "cosmology"): cosmology = instance.cosmology else: cosmology = self.cosmology return Tracer.from_galaxies( galaxies=instance.galaxies, cosmology=cosmology, profiling_dict=profiling_dict, )
def test__furthest_distances_from_other_coordinates(self): grid = aa.Grid2DIrregular(grid=[(0.0, 0.0), (0.0, 1.0)]) assert grid.furthest_distances_from_other_coordinates.in_list == [ 1.0, 1.0 ] grid = aa.Grid2DIrregular(grid=[(2.0, 4.0), (3.0, 6.0)]) assert grid.furthest_distances_from_other_coordinates.in_list == [ np.sqrt(5), np.sqrt(5), ] grid = aa.Grid2DIrregular(grid=[(0.0, 0.0), (0.0, 1.0), (0.0, 3.0)]) assert grid.furthest_distances_from_other_coordinates.in_list == [ 3.0, 2.0, 3.0 ]
def source_plane_light_profile_centre(self) -> aa.Grid2DIrregular: """ Return a light profile centre of one of the a galaxies in the maximum log likelihood `Tracer`'s source-plane. If there are multiple light profiles, the first light profile's centre is returned. These centres are used by automatic position updating to determine the best-fit lens model's image-plane multiple-image positions. """ centre = self.max_log_likelihood_tracer.source_plane.extract_attribute( cls=ag.lp.LightProfile, attr_name="centre") if centre is not None: return aa.Grid2DIrregular(grid=[np.asarray(centre[0])])
def test__with_mask__converts_to_and_from_pixels(self): mask = aa.Mask2D.manual(mask=np.full(fill_value=False, shape=(2, 2)), pixel_scales=(2.0, 2.0)) grid = aa.Grid2DIrregular(grid=[(1.0, -1.0), (1.0, 1.0)]) assert grid.in_list == [(1.0, -1.0), (1.0, 1.0)] grid = aa.Grid2DIrregular.from_pixels_and_mask(pixels=[(0, 0), (0, 1)], mask=mask) assert grid.in_list == [(1.0, -1.0), (1.0, 1.0)]
def test__grid_2d_irregular_in__output_values_same_format(self): grid_like_object = MockGrid2DLikeObj() grid_2d = aa.Grid2DIrregular(grid=[(1.0, 2.0), (3.0, 4.0), (5.0, 6.0)]) values_output = grid_like_object.ndarray_1d_from_grid(grid=grid_2d) assert values_output.in_list == [1.0, 1.0, 1.0] grid_output = grid_like_object.ndarray_2d_from_grid(grid=grid_2d) assert grid_output.in_list == [(2.0, 4.0), (6.0, 8.0), (10.0, 12.0)]
def test__input_as_list_or_list_of_other_types__all_convert_correctly( self): # Input tuple grid = aa.Grid2DIrregular(grid=[(1.0, -1.0)]) assert type(grid) == aa.Grid2DIrregular assert (grid == np.array([[1.0, -1.0]])).all() assert grid.in_list == [(1.0, -1.0)] # Input tuples grid = aa.Grid2DIrregular(grid=[(1.0, -1.0), (1.0, 1.0)]) assert type(grid) == aa.Grid2DIrregular assert (grid == np.array([[1.0, -1.0], [1.0, 1.0]])).all() assert grid.in_list == [(1.0, -1.0), (1.0, 1.0)] # Input np array grid = aa.Grid2DIrregular( grid=[np.array([1.0, -1.0]), np.array([1.0, 1.0])]) assert type(grid) == aa.Grid2DIrregular assert (grid == np.array([[1.0, -1.0], [1.0, 1.0]])).all() assert grid.in_list == [(1.0, -1.0), (1.0, 1.0)] # Input list grid = aa.Grid2DIrregular(grid=[[1.0, -1.0], [1.0, 1.0]]) assert type(grid) == aa.Grid2DIrregular assert (grid == np.array([[1.0, -1.0], [1.0, 1.0]])).all() assert grid.in_list == [(1.0, -1.0), (1.0, 1.0)]
def test__structure_2d_from_result__maps_numpy_array_to__auto_array_or_grid( self): grid = aa.Grid2DIrregular(grid=[(1.0, -1.0), (1.0, 1.0)]) result = grid.structure_2d_from_result(result=np.array([1.0, 2.0])) assert isinstance(result, aa.ValuesIrregular) assert result.in_list == [1.0, 2.0] result = grid.structure_2d_from_result( result=np.array([[1.0, 1.0], [2.0, 2.0]])) assert isinstance(result, aa.Grid2DIrregular) assert result.in_list == [(1.0, 1.0), (2.0, 2.0)]
def test__structure_2d_list_from_result_list__maps_list_to_auto_arrays_or_grids( self): grid = aa.Grid2DIrregular(grid=[(1.0, -1.0), (1.0, 1.0)]) result = grid.structure_2d_list_from_result_list( result_list=[np.array([1.0, 2.0])]) assert isinstance(result[0], aa.ValuesIrregular) assert result[0].in_list == [1.0, 2.0] result = grid.structure_2d_list_from_result_list( result_list=[np.array([[1.0, 1.0], [2.0, 2.0]])]) assert isinstance(result[0], aa.Grid2DIrregular) assert result[0].in_list == [(1.0, 1.0), (2.0, 2.0)]
def extract_attribute(self, cls, attr_name): """ Returns an attribute of a class and its children profiles in the the galaxy as a `ValueIrregular` or `Grid2DIrregular` object. For example, if a galaxy has two light profiles and we want the `LightProfile` axis-ratios, the following: `galaxy.extract_attribute(cls=LightProfile, name="axis_ratio"` would return: ValuesIrregular(values=[axis_ratio_0, axis_ratio_1]) If a galaxy has three mass profiles and we want the `MassProfile` centres, the following: `galaxy.extract_attribute(cls=MassProfile, name="centres"` would return: GridIrregular2D(grid=[(centre_y_0, centre_x_0), (centre_y_1, centre_x_1), (centre_y_2, centre_x_2)]) This is used for visualization, for example plotting the centres of all light profiles colored by their profile. """ def extract(value, name): try: return getattr(value, name) except (AttributeError, IndexError): return None attributes = [ extract(value, attr_name) for value in self.__dict__.values() if isinstance(value, cls) ] attributes = list(filter(None, attributes)) if attributes == []: return None elif isinstance(attributes[0], float): return aa.ValuesIrregular(values=attributes) elif isinstance(attributes[0], tuple): return aa.Grid2DIrregular(grid=attributes)
def test__scatter_colored_grid__lists_of_coordinates_or_equivalent_2d_grids__with_color_array( self, ): scatter = aplt.GridScatter(s=2, marker="x", c="k") cmap = plt.get_cmap("jet") scatter.scatter_grid_colored( grid=aa.Grid2DIrregular([(1.0, 1.0), (2.0, 2.0), (3.0, 3.0), (4.0, 4.0), (5.0, 5.0)]), color_array=np.array([2.0, 2.0, 2.0, 2.0, 2.0]), cmap=cmap, ) scatter.scatter_grid_colored( grid=aa.Grid2D.uniform(shape_native=(3, 2), pixel_scales=1.0), color_array=np.array([2.0, 2.0, 2.0, 2.0, 2.0, 2.0]), cmap=cmap, )
def image_plane_multiple_image_positions(self) -> aa.Grid2DIrregular: """ Backwards ray-trace the source-plane centres (see above) to the image-plane via the mass model, to determine the multiple image position of the source(s) in the image-plane. These image-plane positions are used by the next search in a pipeline if automatic position updating is turned on.""" # TODO : In the future, the multiple image positions functioon wil use an in-built adaptive grid. grid = self.analysis.dataset.mask.unmasked_grid_sub_1 solver = PointSolver(grid=grid, pixel_scale_precision=0.001) multiple_images = solver.solve( lensing_obj=self.max_log_likelihood_tracer, source_plane_coordinate=self.source_plane_centre.in_list[0], ) return aa.Grid2DIrregular(grid=multiple_images)
def extract_attribute(self, cls, attr_name): """ Returns an attribute of a class in the tracer as a `ValueIrregular` or `Grid2DIrregular` object. For example, if a tracer has an image-plane with a galaxy with two light profiles, the following: `tracer.extract_attribute(cls=LightProfile, name="axis_ratio")` would return: ValuesIrregular(values=[axis_ratio_0, axis_ratio_1]) If the image plane has has two galaxies with two mass profiles and the source plane another galaxy with a mass profile, the following: `tracer.extract_attribute(cls=MassProfile, name="centre")` would return: GridIrregular2D(grid=[(centre_y_0, centre_x_0), (centre_y_1, centre_x_1), (centre_y_2, centre_x_2)]) This is used for visualization, for example plotting the centres of all mass profiles colored by their profile. """ def extract(value, name): try: return getattr(value, name) except (AttributeError, IndexError): return None attributes = [ extract(value, attr_name) for galaxy in self.galaxies for value in galaxy.__dict__.values() if isinstance(value, cls) ] if attributes == []: return None elif isinstance(attributes[0], float): return aa.ValuesIrregular(values=attributes) elif isinstance(attributes[0], tuple): return aa.Grid2DIrregular(grid=attributes)
def test__grid_of_closest_from_grid(self): grid = aa.Grid2DIrregular(grid=[(0.0, 0.0), (0.0, 1.0)]) grid_of_closest = grid.grid_of_closest_from_grid_pair( grid_pair=np.array([[0.0, 0.1]])) assert (grid_of_closest == np.array([[0.0, 0.0]])).all() grid_of_closest = grid.grid_of_closest_from_grid_pair( grid_pair=np.array([[0.0, 0.1], [0.0, 0.2], [0.0, 0.3]])) assert (grid_of_closest == np.array([[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]])).all() grid_of_closest = grid.grid_of_closest_from_grid_pair( grid_pair=np.array([[0.0, 0.1], [0.0, 0.2], [0.0, 0.9], [0.0, -0.1]])) assert (grid_of_closest == np.array([[0.0, 0.0], [0.0, 0.0], [0.0, 1.0], [0.0, 0.0]])).all()
def radial_critical_curve_from( self, grid, pixel_scale: Union[Tuple[float, float], float] = 0.05 ) -> aa.Grid2DIrregular: """ Returns the radial critical curve of lensing object, which is computed as follows: 1) Compute the radial eigen values for every coordinate on the input grid via the Jacobian. 2) Find contours of all values in the radial eigen values that are zero using a marching squares algorithm. Due to the use of a marching squares algorithm that requires the zero values of the radial eigen values to be computed, this critical curves can only be calculated using the Jacobian and a uniform 2D grid. Parameters ---------- grid The 2D grid of (y,x) arc-second coordinates the deflection angles and radial eigen values are computed on. pixel_scale If input, the `evaluation_grid` decorator creates the 2D grid at this resolution, therefore enabling the critical curve to be computed more accurately using a higher resolution grid. """ radial_eigen_values = self.radial_eigen_value_from(grid=grid) radial_critical_curve_indices = measure.find_contours( radial_eigen_values.native, 0) if len(radial_critical_curve_indices) == 0: return [] radial_critical_curve = grid.mask.grid_scaled_for_marching_squares_from( grid_pixels_1d=radial_critical_curve_indices[0], shape_native=radial_eigen_values.sub_shape_native, ) try: return aa.Grid2DIrregular(radial_critical_curve) except IndexError: return []
def test__errorbar_colored_grid__lists_of_coordinates_or_equivalent_2d_grids__with_color_array( self, ): errorbar = aplt.GridErrorbar(marker="x", c="k") cmap = plt.get_cmap("jet") errorbar.errorbar_grid_colored( grid=aa.Grid2DIrregular([(1.0, 1.0), (2.0, 2.0), (3.0, 3.0), (4.0, 4.0), (5.0, 5.0)]), color_array=np.array([2.0, 2.0, 2.0, 2.0, 2.0]), y_errors=[1.0] * 5, x_errors=[1.0] * 5, cmap=cmap, ) errorbar.errorbar_grid_colored( grid=aa.Grid2D.uniform(shape_native=(3, 2), pixel_scales=1.0), color_array=np.array([2.0, 2.0, 2.0, 2.0, 2.0, 2.0]), cmap=cmap, y_errors=[1.0] * 6, x_errors=[1.0] * 6, )
def from_dict(cls, dict_: dict) -> "PointDataset": """ Create a point source dataset from a dictionary representation. Parameters ---------- dict_ A dictionary. Arrays are represented as lists or lists of lists. Returns ------- An instance """ return cls( name=dict_["name"], positions=aa.Grid2DIrregular(dict_["positions"]), positions_noise_map=aa.ValuesIrregular( dict_["positions_noise_map"]), fluxes=aa.ValuesIrregular(dict_["fluxes"]) if dict_["fluxes"] is not None else None, fluxes_noise_map=aa.ValuesIrregular(dict_["fluxes_noise_map"]) if dict_["fluxes_noise_map"] is not None else None, )
def via_tracer_from(self, tracer: Tracer, grid: aa.type.Grid2DLike, plane_index: int) -> aplt.Visuals2D: """ From a `Tracer` get the attributes that can be plotted and returns them in a `Visuals2D` object. Only attributes with `True` entries in the `Include` object are extracted. From a tracer the following attributes can be extracted for plotting: - origin: the (y,x) origin of the coordinate system used to plot the light object's quantities in 2D. - border: the border of the mask of the grid used to plot the light object's quantities in 2D. - light profile centres: the (y,x) centre of every `LightProfile` in the object. - mass profile centres: the (y,x) centre of every `MassProfile` in the object. - critical curves: the critical curves of all of the tracer's mass profiles combined. - caustics: the caustics of all of the tracer's mass profiles combined. When plotting a `Tracer` it is common for plots to only display quantities corresponding to one plane at a time (e.g. the convergence in the image plane, the source in the source plane). Therefore, quantities are only extracted from one plane, specified by the input `plane_index`. Parameters ---------- tracer The `Tracer` object which has attributes extracted for plotting. grid The 2D grid of (y,x) coordinates used to plot the tracer's quantities in 2D. plane_index The index of the plane in the tracer which is used to extract quantities, as only one plane is plotted at a time. Returns ------- vis.Visuals2D A collection of attributes that can be plotted by a `Plotter` object. """ origin = self.get("origin", value=aa.Grid2DIrregular(grid=[grid.origin])) border = self.get("border", value=grid.mask.border_grid_sub_1.binned) if border is not None and len(border) > 0 and plane_index > 0: border = tracer.traced_grid_2d_list_from(grid=border)[plane_index] light_profile_centres = self.get( "light_profile_centres", tracer.planes[plane_index].extract_attribute( cls=ag.lp.LightProfile, attr_name="centre"), ) mass_profile_centres = self.get( "mass_profile_centres", tracer.planes[plane_index].extract_attribute(cls=ag.mp.MassProfile, attr_name="centre"), ) if plane_index == 0: critical_curves = self.get( "critical_curves", tracer.critical_curves_from(grid=grid), "critical_curves", ) else: critical_curves = None if plane_index == 1: caustics = self.get("caustics", tracer.caustics_from(grid=grid), "caustics") else: caustics = None return self.visuals + self.visuals.__class__( origin=origin, border=border, light_profile_centres=light_profile_centres, mass_profile_centres=mass_profile_centres, critical_curves=critical_curves, caustics=caustics, )
def test__3x3_simple_grid(self): mask = aa.Mask2D.manual( mask=[ [True, True, True, True, True], [True, False, False, False, True], [True, False, False, False, True], [True, False, False, False, True], [True, True, True, True, True], ], pixel_scales=1.0, sub_size=1, ) grid = np.array([ [1.0, -1.0], [1.0, 0.0], [1.0, 1.0], [0.0, -1.0], [0.0, 0.0], [0.0, 1.0], [-1.0, -1.0], [-1.0, 0.0], [-1.0, 1.0], ]) grid = aa.Grid2D.manual_mask(grid=grid, mask=mask) pix = aa.pix.VoronoiMagnification(shape=(3, 3)) sparse_grid = aa.Grid2DSparse.from_grid_and_unmasked_2d_grid_shape( grid=grid, unmasked_sparse_shape=pix.shape) sparse_image_plane_grid = aa.Grid2DIrregular(grid=[(0.0, 0.0)]) mapper = pix.mapper_from_grid_and_sparse_grid( grid=grid, sparse_grid=sparse_grid, settings=aa.SettingsPixelization(use_border=False), sparse_image_plane_grid=sparse_image_plane_grid, hyper_image=np.ones((2, 2)), ) assert (mapper.source_pixelization_grid. nearest_pixelization_index_for_slim_index == sparse_grid.sparse_index_for_slim_index).all() assert (mapper.data_pixelization_grid == sparse_image_plane_grid).all() assert mapper.source_pixelization_grid.shape_native_scaled == pytest.approx( (2.0, 2.0), 1.0e-4) assert (mapper.source_pixelization_grid == sparse_grid).all() # assert mapper.pixelization_grid.origin == pytest.approx((0.0, 0.0), 1.0e-4) assert (mapper.hyper_image == np.ones((2, 2))).all() assert isinstance(mapper, mappers.MapperVoronoi) assert (mapper.mapping_matrix == np.array([ [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], ])).all() reg = aa.reg.Constant(coefficient=1.0) regularization_matrix = reg.regularization_matrix_from_mapper( mapper=mapper) assert (regularization_matrix == np.array([ [2.00000001, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0], [-1.0, 3.00000001, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0], [0.0, -1.0, 2.00000001, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0], [-1.0, 0.0, 0.0, 3.00000001, -1.0, 0.0, -1.0, 0.0, 0.0], [0.0, -1.0, 0.0, -1.0, 4.00000001, -1.0, 0.0, -1.0, 0.0], [0.0, 0.0, -1.0, 0.0, -1.0, 3.00000001, 0.0, 0.0, -1.0], [0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 2.00000001, -1.0, 0.0], [0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0, 3.00000001, -1.0], [0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0, 2.00000001], ])).all() image = aa.Array2D.ones(shape_native=(5, 5), pixel_scales=1.0) noise_map = aa.Array2D.ones(shape_native=(5, 5), pixel_scales=1.0) psf = aa.Kernel2D.no_blur(pixel_scales=1.0) imaging = aa.Imaging(image=image, noise_map=noise_map, psf=psf) masked_imaging = imaging.apply_mask(mask=mask) inversion = aa.Inversion( dataset=masked_imaging, mapper=mapper, regularization=reg, settings=aa.SettingsInversion(check_solution=False), ) assert ( inversion.blurred_mapping_matrix == mapper.mapping_matrix).all() assert (inversion.regularization_matrix == regularization_matrix).all() assert inversion.mapped_reconstructed_image == pytest.approx( np.ones(9), 1.0e-4)