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__values_from_array_slim(self): values = aa.ValuesIrregular(values=[1.0, 2.0]) values_from_1d = values.values_from_array_slim( array_slim=np.array([1.0, 2.0])) assert values_from_1d.in_list == [1.0, 2.0] values = aa.ValuesIrregular(values=[1.0, 2.0, 3.0]) values_from_1d = values.values_from_array_slim( array_slim=np.array([1.0, 2.0, 3.0])) assert values_from_1d.in_list == [1.0, 2.0, 3.0]
def test__output_values_to_json(self): values = aa.ValuesIrregular(values=[6.0, 7.0, 8.0]) output_values_dir = path.join( "{}".format(path.dirname(path.realpath(__file__))), "files", "values", "output_test", ) if path.exists(output_values_dir): shutil.rmtree(output_values_dir) os.makedirs(output_values_dir) file_path = path.join(output_values_dir, "values_test.dat") values.output_to_json(file_path=file_path) values = aa.ValuesIrregular.from_file(file_path=file_path) assert values.in_list == [6.0, 7.0, 8.0] with pytest.raises(FileExistsError): values.output_to_json(file_path=file_path) values.output_to_json(file_path=file_path, overwrite=True)
def test__coordinates_from_grid_1d(self): values = aa.ValuesIrregular(values=[1.0, 2.0]) coordinate_from_1d = values.grid_from_grid_slim( grid_slim=np.array([[1.0, 1.0], [2.0, 2.0]])) assert coordinate_from_1d.in_list == [(1.0, 1.0), (2.0, 2.0)] values = aa.ValuesIrregular(values=[[1.0, 2.0, 3.0]]) coordinate_from_1d = values.grid_from_grid_slim( grid_slim=np.array([[1.0, 1.0], [2.0, 2.0], [3.0, 3.0]])) assert coordinate_from_1d.in_list == [(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)]
def test__input_as_list__convert_correctly(self): values = aa.ValuesIrregular(values=[1.0, -1.0]) assert type(values) == aa.ValuesIrregular assert (values == np.array([1.0, -1.0])).all() assert values.in_list == [1.0, -1.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. """ 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 ellipticities(self) -> aa.ValuesIrregular: """ If we treat this vector field as a set of weak lensing shear measurements, the galaxy ellipticity each vector corresponds too. """ return aa.ValuesIrregular(values=np.sqrt(self.slim[:, 0]**2 + self.slim[:, 1]**2.0))
def __init__( self, name: str, fluxes: aa.ValuesIrregular, noise_map: aa.ValuesIrregular, positions: aa.Grid2DIrregular, tracer: Tracer, point_profile: Optional[ag.ps.Point] = None, ): self.tracer = tracer self.name = name self.positions = positions if point_profile is None: point_profile = tracer.extract_profile(profile_name=name) self.point_profile = point_profile if self.point_profile is None: raise exc.PointExtractionException( f"For the point-source named {name} there was no matching point source profile " f"in the tracer (make sure your tracer's point source name is the same the dataset name." ) elif not hasattr(self.point_profile, "flux"): raise exc.PointExtractionException( f"For the point-source named {name} the extracted point source was the " f"class {self.point_profile.__class__.__name__} and therefore does " f"not contain a flux component.") if len(tracer.planes) > 2: upper_plane_index = tracer.extract_plane_index_of_profile( profile_name=name) deflections_func = partial( tracer.deflections_between_planes_from, plane_i=0, plane_j=upper_plane_index, ) else: deflections_func = tracer.deflections_yx_2d_from self.magnifications = abs( self.tracer.magnification_2d_via_hessian_from( grid=positions, deflections_func=deflections_func)) model_fluxes = aa.ValuesIrregular(values=[ magnification * self.point_profile.flux for magnification in self.magnifications ]) super().__init__( data=fluxes, noise_map=noise_map, model_data=model_fluxes, mask=None, inversion=None, )
def phis(self) -> aa.ValuesIrregular: """ If we treat this vector field as a set of weak lensing shear measurements, the position angle defined counter clockwise from the positive x-axis of each galaxy ellipticity that each vector corresponds too. """ return aa.ValuesIrregular( values=np.arctan2(self.slim[:, 0], self.slim[:, 1]) * 180.0 / np.pi / 2.0)
def residual_map(self) -> aa.ValuesIrregular: """ Returns the residual map, over riding the parent method so that the result is converted to a `ValuesIrregular` object. """ residual_map = super().residual_map return aa.ValuesIrregular(values=residual_map)
def model_data(self): """ The model-fluxes of the tracer at each of the image-plane positions. Only point sources which are a `PointFlux` type, and therefore which include a model parameter for its flux, are used. """ return aa.ValuesIrregular(values=[ magnification * self.point_profile.flux for magnification in self.magnifications ])
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 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 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 semi_minor_axes(self) -> aa.ValuesIrregular: """ If we treat this vector field as a set of weak lensing shear measurements, the semi-minor axis of each galaxy ellipticity that each vector corresponds too. """ return aa.ValuesIrregular(values=3 * (1 - self.ellipticities))