From a81587bcaeb1d9c206724f3862f3f081eeaefbdd Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 7 Nov 2024 08:47:49 -0500 Subject: [PATCH 01/33] added a z_max in galaxy draw in Galaxies class. --- slsim/Sources/galaxies.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/slsim/Sources/galaxies.py b/slsim/Sources/galaxies.py index 52100beca..90c2e2b1e 100644 --- a/slsim/Sources/galaxies.py +++ b/slsim/Sources/galaxies.py @@ -120,14 +120,24 @@ def source_number_selected(self): """ return self._num_select - def draw_source(self): - """Choose source at random. + def draw_source(self, z_max=None): + """Choose source at random. :param z_max: maximum redshift for source to be + drawn. + :param z_max: maximum redshift limit for the galaxy to be drawn. If no galaxy is + found for this limit, None will be returned. :return: dictionary of source """ - - index = random.randint(0, self._num_select - 1) - galaxy = self._galaxy_select[index] + if z_max is not None: + filtered_galaxies = self._galaxy_select[self._galaxy_select["z"] < z_max] + if len(filtered_galaxies) == 0: + return None + else: + index = random.randint(0, len(filtered_galaxies) - 1) + galaxy = filtered_galaxies[index] + else: + index = random.randint(0, self._num_select - 1) + galaxy = self._galaxy_select[index] if "a_rot" in galaxy.colnames: phi_rot = galaxy["a_rot"] else: From 5c7987ec4b91acba8b6619c5c881f82ac6323b42 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 7 Nov 2024 08:57:05 -0500 Subject: [PATCH 02/33] created a FalsePositives folder. --- slsim/FalsePositives/false_positive.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 slsim/FalsePositives/false_positive.py diff --git a/slsim/FalsePositives/false_positive.py b/slsim/FalsePositives/false_positive.py new file mode 100644 index 000000000..e69de29bb From fef6b24f3e84ef0a7fadd94a12e474aaa2301bf7 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 7 Nov 2024 09:00:46 -0500 Subject: [PATCH 03/33] added a FalsePositive class --- slsim/FalsePositives/false_positive.py | 315 +++++++++++++++++++++++++ 1 file changed, 315 insertions(+) diff --git a/slsim/FalsePositives/false_positive.py b/slsim/FalsePositives/false_positive.py index e69de29bb..4de231ea7 100644 --- a/slsim/FalsePositives/false_positive.py +++ b/slsim/FalsePositives/false_positive.py @@ -0,0 +1,315 @@ +import numpy as np +from lenstronomy.Cosmo.lens_cosmo import LensCosmo +from slsim.ParamDistributions.los_config import LOSConfig +from slsim.lens import Lens +from slsim.Util.param_util import ellipticity_slsim_to_lenstronomy +from slsim.lens import theta_e_when_source_infinity + + +class FalsePositive(object): + """Class to manage individual false positive.""" + + def __init__( + self, + source_class, + deflector_class, + cosmo, + test_area=4 * np.pi, + los_config=None, + los_dict=None, + ): + """ + :param source_class: A Source class instance or list of Source class instance + :type source_class: Source class instance from slsim.Sources.source + :param deflector_class: deflector instance + :type deflector_class: Deflector class instance from slsim.Deflectors.deflector + :param cosmo: astropy.cosmology instance + :param test_area: area of disk around one lensing galaxies to be investigated + on (in arc-seconds^2). + :param los_config: LOSConfig instance which manages line-of-sight (LOS) effects + and Gaussian mixture models in a simulation or analysis context. + :param los_dict: line of sight dictionary (optional, takes these values instead + of drawing from distribution) Takes "gamma" = [gamma1, gamma2] and + "kappa" = kappa as entries + :type los_dict: dict + """ + self.deflector = deflector_class + self.source = source_class + self.test_area = test_area + self.cosmo = cosmo + if isinstance(self.source, list): + source_z = self.source[0].redshift + self._source_type = self.source[0].source_type + self.source_number = len(self.source) + self.single_source_class = self.source[0] # to access some common kwargs. + else: + source_z = self.source.redshift + self._source_type = self.source.source_type + self.source_number = 1 + self.single_source_class = self.source + self._lens_cosmo = LensCosmo( + z_lens=float(self.deflector.redshift), + z_source=float(source_z), + cosmo=self.cosmo, + ) + + self._los_linear_distortions_cache = None + self.los_config = los_config + if self.los_config is None: + if los_dict is None: + los_dict = {} + self.los_config = LOSConfig(**los_dict) + + @property + def deflector_position(self): + """Center of the deflector position. + + :return: [x_pox, y_pos] in arc seconds + """ + return self.deflector.deflector_center + + @property + def deflector_redshift(self): + """ + + :return: lens redshift + """ + return self.deflector.redshift + + @property + def source_redshift(self): + """ + + :return: a source redshift or list of source redshift + """ + if self.source_number == 1: + source_redshift = self.source.redshift + else: + source_redshift = [] + for i in range(self.source_number): + source_redshift.append(self.source[i].redshift) + return source_redshift + + @property + def external_convergence(self): + """ + + :return: external convergence + """ + _, _, kappa_ext = self.los_linear_distortions + return kappa_ext + + @property + def external_shear(self): + """ + + :return: the absolute external shear + """ + gamma1, gamma2, _ = self.los_linear_distortions + return (gamma1**2 + gamma2**2) ** 0.5 + + @property + def einstein_radius(self): + """Einstein radius, from SIS approximation (coming from velocity dispersion) + + external convergence effect. + + :return: Einstein radius [arc seconds] + """ + theta_E = theta_e_when_source_infinity( + v_sigma=self.deflector_velocity_dispersion() + ) + _, _, kappa_ext = self.los_linear_distortions + return theta_E / (1 - kappa_ext) + + def deflector_ellipticity(self): + """ + + :return: e1_light, e2_light, e1_mass, e2_mass + """ + e1_light, e2_light = self.deflector.light_ellipticity + e1_mass, e2_mass = self.deflector.mass_ellipticity + return e1_light, e2_light, e1_mass, e2_mass + + def deflector_stellar_mass(self): + """ + + :return: stellar mass of deflector + """ + return self.deflector.stellar_mass + + def deflector_velocity_dispersion(self): + """ + + :return: velocity dispersion [km/s] + """ + return self.deflector.velocity_dispersion(cosmo=self.cosmo) + + @property + def los_linear_distortions(self): + if self._los_linear_distortions_cache is None: + self._los_linear_distortions_cache = ( + self._calculate_los_linear_distortions() + ) + return self._los_linear_distortions_cache + + def _calculate_los_linear_distortions(self): + """Line-of-sight distortions in shear and convergence. + + :return: kappa, gamma1, gamma2 + """ + if self.source_number == 1: + source_z = self.source_redshift + else: + source_z = self.source_redshift[0] + return self.los_config.calculate_los_linear_distortions( + source_redshift=source_z, + deflector_redshift=self.deflector_redshift, + ) + + def deflector_magnitude(self, band): + """Apparent magnitude of the deflector for a given band. + + :param band: imaging band + :type band: string + :return: magnitude of deflector in given band + """ + return self.deflector.magnitude(band=band) + + def extended_source_magnitude(self, band): + """Unlensed apparent magnitude of the extended source for a given band (assumes + that size is the same for different bands) + + :param band: imaging band + :type band: string + :param lensed: if True, returns the lensed magnified magnitude + :type lensed: bool + :return: magnitude of source in given band + """ + # band_string = str("mag_" + band) + # TODO: might have to change conventions between extended and point source + source_mag = self.source.extended_source_magnitude(band) + return source_mag + + def lenstronomy_kwargs(self, band=None): + """Generates lenstronomy dictionary conventions for the class object. + + :param band: imaging band, if =None, will result in un-normalized amplitudes + :type band: string or None + :return: lenstronomy model and parameter conventions + """ + lens_mass_model_list, kwargs_lens = self.deflector_mass_model_lenstronomy() + ( + lens_light_model_list, + kwargs_lens_light, + ) = self.deflector.light_model_lenstronomy(band=band) + + sources, sources_kwargs = self.source_light_model_lenstronomy(band=band) + combined_lens_light_model_list = ( + lens_light_model_list + sources["source_light_model_list"] + ) + combined_kwargs_lens_light = kwargs_lens_light + sources_kwargs["kwargs_source"] + + kwargs_model = { + "lens_light_model_list": combined_lens_light_model_list, + "lens_model_list": lens_mass_model_list, + } + + kwargs_source = None + kwargs_ps = sources_kwargs["kwargs_ps"] + + kwargs_params = { + "kwargs_lens": kwargs_lens, + "kwargs_source": kwargs_source, + "kwargs_lens_light": combined_kwargs_lens_light, + "kwargs_ps": kwargs_ps, + } + + return kwargs_model, kwargs_params + + def deflector_mass_model_lenstronomy(self): + """Returns lens model instance and parameters in lenstronomy conventions. + + :return: lens_model_list, kwargs_lens + """ + if self.deflector.deflector_type in ["EPL", "NFW_HERNQUIST", "NFW_CLUSTER"]: + lens_mass_model_list, kwargs_lens = self.deflector.mass_model_lenstronomy( + lens_cosmo=self._lens_cosmo + ) + else: + raise ValueError( + "Deflector model %s not supported for lenstronomy model" + % self.deflector.deflector_type + ) + # adding line-of-sight structure + gamma1, gamma2, kappa_ext = self.los_linear_distortions + gamma1_lenstronomy, gamma2_lenstronomy = ellipticity_slsim_to_lenstronomy( + e1_slsim=gamma1, e2_slsim=gamma2 + ) + kwargs_lens.append( + { + "gamma1": gamma1_lenstronomy, + "gamma2": gamma2_lenstronomy, + "ra_0": 0, + "dec_0": 0, + } + ) + kwargs_lens.append({"kappa": kappa_ext, "ra_0": 0, "dec_0": 0}) + lens_mass_model_list.append("SHEAR") + lens_mass_model_list.append("CONVERGENCE") + + return lens_mass_model_list, kwargs_lens + + def deflector_light_model_lenstronomy(self, band): + """Returns lens model instance and parameters in lenstronomy conventions. + + :param band: imaging band + :type band: str + :return: lens_light_model_list, kwargs_lens_light + """ + return self.deflector.light_model_lenstronomy(band=band) + + def source_light_model_lenstronomy(self, band=None): + """Returns source light model instance and parameters in lenstronomy + conventions. + + :return: source_light_model_list, kwargs_source_light + """ + source_models = {} + all_source_kwarg_dict = {} + """If ( self._source_type == "extended". + + or self._source_type == "point_plus_extended" ): + """ + if self.source_number == 1: + source_class = self.source + else: + source_class = self.source[0] + if source_class.light_profile == "single_sersic": + source_models["source_light_model_list"] = [ + "SERSIC_ELLIPSE" + ] * self.source_number + # In this case we will consider a single source with double sersic profile. + else: + raise ValueError( + "Provided light profile is not supported. Supported" + " light profile is single_sersic" + ) + if self.source_number == 1: + kwargs_source = self.source.kwargs_extended_source_light( + draw_area=self.test_area, center_lens=self.deflector_position, band=band + ) + else: + kwargs_source = [] + for i in range(self.source_number): + kwargs_source.append( + self.source[i].kwargs_extended_source_light( + draw_area=self.test_area, + center_lens=self.deflector_position, + band=band, + )[0] + ) + + kwargs_ps = None + all_source_kwarg_dict["kwargs_source"] = kwargs_source + all_source_kwarg_dict["kwargs_ps"] = kwargs_ps + return source_models, all_source_kwarg_dict \ No newline at end of file From 2db1083a4e14d7078592879de45ca648f38406d8 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 7 Nov 2024 09:03:53 -0500 Subject: [PATCH 04/33] added a FalsePositivePop class. --- slsim/FalsePositives/false_positive_pop.py | 112 +++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 slsim/FalsePositives/false_positive_pop.py diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py new file mode 100644 index 000000000..99e403961 --- /dev/null +++ b/slsim/FalsePositives/false_positive_pop.py @@ -0,0 +1,112 @@ +from slsim.FalsePositives.false_positive import FalsePositive +from typing import Optional +from astropy.cosmology import Cosmology +from slsim.Sources.source_pop_base import SourcePopBase +from slsim.ParamDistributions.los_config import LOSConfig +from slsim.Deflectors.deflectors_base import DeflectorsBase +from slsim.Sources.source import Source +from slsim.Deflectors.deflector import Deflector +from slsim.lens_pop import draw_test_area +import random + + +class FalsePositivePop(object): + """Class to perform samples of false positive population.""" + + def __init__( + self, + elliptical_galaxy_population: DeflectorsBase, + blue_galaxy_population: SourcePopBase, + cosmo: Optional[Cosmology] = None, + los_config: Optional[LOSConfig] = None, + source_number_choice: Optional[list[int]] = [1, 2, 3], + weights_for_source_number: Optional[list[int]] = None, + ): + """ + Args: + deflector_population (DeflectorsBase): Deflector population as an instance of a DeflectorsBase subclass. + source_population (SourcePopBase): Source population as an instance of a SourcePopBase subclass + cosmo (Optional[Cosmology], optional): AstroPy Cosmology instance. If None, defaults to flat LCDM with h0=0.7 and Om0=0.3. + Defaults to None. + los_config (Optional[LOSConfig], optional): Configuration for line of sight distribution. Defaults to None. + source_number_choice (Optional[list[int]], optional): A list of integers to choose source number from. If None, defaults to [1, 2, 3]. + weights (Optional[list[int]], optional): A list of weights corresponding to the probabilities of selecting each value + in source_number_choice. If None, all choices are equally likely. + Defaults to None. + """ + + self.cosmo = cosmo + self._lens_galaxies = elliptical_galaxy_population + self._sources = blue_galaxy_population + self._choice = source_number_choice + self._weights = weights_for_source_number + self.los_config = los_config + if self.los_config is None: + self.los_config = LOSConfig() + + def draw_false_positive(self, number=1): + """Draw given number of false positives within the cuts of the lens and source. + + :param number: number of false positive requested. The default value is 1. + :return: list of FalsePositive() instance with parameters of a pair of + elliptical and blue galaxy. + """ + false_positive_population = [] + + for _ in range(number): + successful = False + while not successful: + # Sample a lens (deflector) + lens = self._lens_galaxies.draw_deflector() + _lens = Deflector( + deflector_type=self._lens_galaxies.deflector_profile, + deflector_dict=lens, + ) + tolerance = 0.002 + z_max = _lens.redshift + tolerance + # Try to draw a source with the z_max based on the lens redshift and + # source number choice. + source_number = random.choices(self._choice, weights=self._weights)[ + 0 + ] + source_list = [] + valid_sources = True + for _ in range(source_number): + source = self._sources.draw_source(z_max=z_max) + # If the source is None, mark sources as invalid and break to retry + if source is None: + valid_sources = False + break + source_list.append( + Source( + source_dict=source, + cosmo=self.cosmo, + source_type=self._sources.source_type, + light_profile=self._sources.light_profile, + ) + ) + if not valid_sources: + continue + if source_number == 1: + _source = source_list[0] + else: + _source = source_list + # Compute test area for false positive position. + # This area will be used to determine the position of false positive. + test_area = 3 * draw_test_area(deflector=lens) + + # Create a FalsePositive instance with the lens and source information + false_positive = FalsePositive( + deflector_class=_lens, + source_class=_source, + cosmo=self.cosmo, + test_area=test_area, + ) + + # Add the false positive to the population + false_positive_population.append(false_positive) + successful = True + if number == 1: + return false_positive_population[0] + else: + return false_positive_population \ No newline at end of file From 79425f96e9a5a772772b15980ee0882eae03a943 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 7 Nov 2024 09:24:31 -0500 Subject: [PATCH 05/33] added a folder for false positive test --- tests/test_FalsePositives/test_false_positive.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/test_FalsePositives/test_false_positive.py diff --git a/tests/test_FalsePositives/test_false_positive.py b/tests/test_FalsePositives/test_false_positive.py new file mode 100644 index 000000000..e69de29bb From eeb10d2897f9c0c9c98f7e803a1d534b183a4a75 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 7 Nov 2024 09:25:47 -0500 Subject: [PATCH 06/33] added test functions for FalsePositive class. --- .../test_false_positive.py | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/tests/test_FalsePositives/test_false_positive.py b/tests/test_FalsePositives/test_false_positive.py index e69de29bb..e4ae372c2 100644 --- a/tests/test_FalsePositives/test_false_positive.py +++ b/tests/test_FalsePositives/test_false_positive.py @@ -0,0 +1,158 @@ +import pytest +import numpy as np +from astropy.cosmology import FlatLambdaCDM +from slsim.ParamDistributions.los_config import LOSConfig +from slsim.Sources.source import Source +from slsim.Deflectors.deflector import Deflector +import slsim.Sources as sources +import slsim.Deflectors as deflectors +import slsim.Pipelines as pipelines +from slsim.FalsePositives.false_positive import FalsePositive +from astropy.units import Quantity + +sky_area = Quantity(value=0.01, unit="deg2") +galaxy_simulation_pipeline = pipelines.SkyPyPipeline( + skypy_config=None, + sky_area=sky_area, + filters=None, +) +kwargs_deflector_cut = {"band": "g", "band_max": 28, "z_min": 0.01, "z_max": 2.5} +kwargs_source_cut = {"band": "g", "band_max": 28, "z_min": 0.1, "z_max": 5.0} + + +def test_false_positive(): + # Mock objects for source_class and deflector_class + + # Initialize a cosmology instance + cosmo = FlatLambdaCDM(H0=70, Om0=0.3) + lens_galaxies = deflectors.EllipticalLensGalaxies( + galaxy_list=galaxy_simulation_pipeline.red_galaxies, + kwargs_cut=kwargs_deflector_cut, + kwargs_mass2light=0.1, + cosmo=cosmo, + sky_area=sky_area, + ) + source_galaxies = sources.Galaxies( + galaxy_list=galaxy_simulation_pipeline.blue_galaxies, + kwargs_cut=kwargs_source_cut, + cosmo=cosmo, + sky_area=sky_area, + catalog_type="skypy", + ) + single_deflector = lens_galaxies.draw_deflector() + single_source1 = source_galaxies.draw_source() + single_source2 = source_galaxies.draw_source() + lens = Deflector(deflector_type="EPL", deflector_dict=single_deflector) + source = Source( + source_dict=single_source1, + cosmo=cosmo, + source_type="extended", + light_profile="single_sersic", + ) + source2 = Source( + source_dict=single_source1, + cosmo=cosmo, + source_type="extended", + light_profile="double_sersic", + ) + source_list = [ + Source( + source_dict=single_source1, + cosmo=cosmo, + source_type="extended", + light_profile="single_sersic", + ), + Source( + source_dict=single_source2, + cosmo=cosmo, + source_type="extended", + light_profile="single_sersic", + ), + ] + # LOS configuration + los_config = LOSConfig() + + # Create an instance of FalsePositive + false_positive_instance_1 = FalsePositive( + source_class=source, + deflector_class=lens, + cosmo=cosmo, + test_area=4 * np.pi, + ) + false_positive_instance_2 = FalsePositive( + source_class=source_list, + deflector_class=lens, + cosmo=cosmo, + test_area=4 * np.pi, + los_config=los_config, + ) + false_positive_instance_3 = FalsePositive( + source_class=source2, + deflector_class=lens, + cosmo=cosmo, + test_area=4 * np.pi, + los_config=los_config, + ) + required_keys = { + "magnitude", + "R_sersic", + "n_sersic", + "e1", + "e2", + "center_x", + "center_y", + } + assert false_positive_instance_1.source_number == 1 + assert false_positive_instance_2.source_number == 2 + assert ( + false_positive_instance_1.lenstronomy_kwargs("i")[0]["lens_light_model_list"][0] + == "SERSIC_ELLIPSE" + ) + assert ( + len( + false_positive_instance_2.lenstronomy_kwargs("i")[0][ + "lens_light_model_list" + ] + ) + == 3 + ) + assert ( + len(false_positive_instance_2.lenstronomy_kwargs("i")[1]["kwargs_lens_light"]) + == 3 + ) + assert len(false_positive_instance_2.deflector_position) == 2 + assert false_positive_instance_2.deflector_redshift == single_deflector["z"] + assert false_positive_instance_1.source_redshift == single_source1["z"] + assert np.all(false_positive_instance_2.source_redshift) == np.all( + np.array([single_source1["z"], single_source2["z"]]) + ) + assert false_positive_instance_1.external_convergence < 0.1 + assert false_positive_instance_1.external_shear < 0.2 + assert false_positive_instance_1.einstein_radius < 2.5 + assert ( + false_positive_instance_1.deflector_magnitude(band="i") + == single_deflector["mag_i"] + ) + assert ( + false_positive_instance_1.extended_source_magnitude(band="i") + == single_source1["mag_i"] + ) + assert len(false_positive_instance_1.deflector_ellipticity()) == 4 + assert ( + false_positive_instance_1.deflector_stellar_mass() + == single_deflector["stellar_mass"] + ) + assert ( + set( + false_positive_instance_1.deflector_light_model_lenstronomy(band="i")[1][ + 0 + ].keys() + ) + == required_keys + ) + with pytest.raises(ValueError): + false_positive_instance_3.source_light_model_lenstronomy(band="i") + + +if __name__ == "__main__": + pytest.main() \ No newline at end of file From 6bc8bafa455ef8fcc2a76b9bc2d6f27678dec195 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 7 Nov 2024 09:31:30 -0500 Subject: [PATCH 07/33] added test functions for FalsePositivePop class. --- .../test_false_positive_pop.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tests/test_FalsePositives/test_false_positive_pop.py diff --git a/tests/test_FalsePositives/test_false_positive_pop.py b/tests/test_FalsePositives/test_false_positive_pop.py new file mode 100644 index 000000000..e49e65c68 --- /dev/null +++ b/tests/test_FalsePositives/test_false_positive_pop.py @@ -0,0 +1,59 @@ +import pytest +from astropy.cosmology import FlatLambdaCDM +import slsim.Sources as sources +import slsim.Deflectors as deflectors +import slsim.Pipelines as pipelines +from slsim.FalsePositives.false_positive_pop import FalsePositivePop +from astropy.units import Quantity + +sky_area = Quantity(value=0.01, unit="deg2") +cosmo = FlatLambdaCDM(H0=70, Om0=0.3) +galaxy_simulation_pipeline = pipelines.SkyPyPipeline( + skypy_config=None, + sky_area=sky_area, + filters=None, +) +kwargs_deflector_cut = {"band": "g", "band_max": 28, "z_min": 0.01, "z_max": 2.5} +kwargs_source_cut = {"band": "g", "band_max": 28, "z_min": 0.1, "z_max": 5.0} +red_galaxy_list = galaxy_simulation_pipeline.red_galaxies +blue_galaxy_list = galaxy_simulation_pipeline.blue_galaxies +lens_galaxies = deflectors.EllipticalLensGalaxies( + galaxy_list=red_galaxy_list, + kwargs_cut=kwargs_deflector_cut, + kwargs_mass2light=0.1, + cosmo=cosmo, + sky_area=sky_area, +) +source_galaxies = sources.Galaxies( + galaxy_list=blue_galaxy_list, + kwargs_cut=kwargs_source_cut, + cosmo=cosmo, + sky_area=sky_area, + catalog_type="skypy", +) + + +def test_draw_false_positive_single(): + fp_pop1 = FalsePositivePop( + elliptical_galaxy_population=lens_galaxies, + blue_galaxy_population=source_galaxies, + cosmo=cosmo, + source_number_choice=[1], + ) + draw_fp1 = fp_pop1.draw_false_positive() + assert isinstance(draw_fp1, object) + + +def test_draw_false_positive_multiple(): + fp_pop2 = FalsePositivePop( + elliptical_galaxy_population=lens_galaxies, + blue_galaxy_population=source_galaxies, + cosmo=cosmo, + source_number_choice=[2], + ) + draw_fp2 = fp_pop2.draw_false_positive(number=2) + assert isinstance(draw_fp2, list) + + +if __name__ == "__main__": + pytest.main() \ No newline at end of file From ff17c9c3e26cae05016ce898c52d3abcf6d78e47 Mon Sep 17 00:00:00 2001 From: narayan Date: Mon, 11 Nov 2024 11:43:48 -0500 Subject: [PATCH 08/33] minor change --- slsim/FalsePositives/false_positive_pop.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py index 99e403961..3cc9438e3 100644 --- a/slsim/FalsePositives/false_positive_pop.py +++ b/slsim/FalsePositives/false_positive_pop.py @@ -66,11 +66,10 @@ def draw_false_positive(self, number=1): z_max = _lens.redshift + tolerance # Try to draw a source with the z_max based on the lens redshift and # source number choice. - source_number = random.choices(self._choice, weights=self._weights)[ - 0 - ] + source_number = random.choices(self._choice, weights=self._weights)[0] source_list = [] valid_sources = True + for _ in range(source_number): source = self._sources.draw_source(z_max=z_max) # If the source is None, mark sources as invalid and break to retry @@ -85,14 +84,18 @@ def draw_false_positive(self, number=1): light_profile=self._sources.light_profile, ) ) - if not valid_sources: - continue + + # Skip the rest of the loop if sources are invalid + if not valid_sources: + continue + + # Handle single or multiple sources if source_number == 1: _source = source_list[0] else: _source = source_list + # Compute test area for false positive position. - # This area will be used to determine the position of false positive. test_area = 3 * draw_test_area(deflector=lens) # Create a FalsePositive instance with the lens and source information @@ -106,6 +109,7 @@ def draw_false_positive(self, number=1): # Add the false positive to the population false_positive_population.append(false_positive) successful = True + if number == 1: return false_positive_population[0] else: From ebb6f6f17c4201ef5da90e32a1364519c4f0763e Mon Sep 17 00:00:00 2001 From: narayan Date: Mon, 11 Nov 2024 12:14:16 -0500 Subject: [PATCH 09/33] added test function for slight changes in Galaxies class. --- tests/test_Source/test_galaxies.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_Source/test_galaxies.py b/tests/test_Source/test_galaxies.py index ee7229cb6..cfa14b4ce 100644 --- a/tests/test_Source/test_galaxies.py +++ b/tests/test_Source/test_galaxies.py @@ -283,10 +283,14 @@ def test_source_number(self): def test_draw_source(self): galaxy = self.galaxies.draw_source() galaxy_1 = self.galaxies4.draw_source() + galaxy_2 = self.galaxies.draw_source(z_max=1) + galaxy_3 = self.galaxies5.draw_source(z_max=0.4) assert len(galaxy) > 0 assert galaxy_1["n_sersic"] == 1 + assert galaxy_2["z"] < 1 + 0.002 with pytest.raises(ValueError): self.galaxies5.draw_source() + assert galaxy_3 is None def test_draw_source_double_sersic(self): galaxy1 = self.galaxies2.draw_source() @@ -336,4 +340,4 @@ def test_galaxy_projected_eccentricity(): if __name__ == "__main__": - pytest.main() + pytest.main() \ No newline at end of file From 90a86db083626c08ebe8e0c6505b233ba5499e22 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 12:41:33 -0500 Subject: [PATCH 10/33] removed some of the duplications in false positive class. --- slsim/FalsePositives/false_positive.py | 259 +----------------- .../test_false_positive.py | 6 +- 2 files changed, 12 insertions(+), 253 deletions(-) diff --git a/slsim/FalsePositives/false_positive.py b/slsim/FalsePositives/false_positive.py index 4de231ea7..b9bf67e2a 100644 --- a/slsim/FalsePositives/false_positive.py +++ b/slsim/FalsePositives/false_positive.py @@ -1,12 +1,7 @@ import numpy as np -from lenstronomy.Cosmo.lens_cosmo import LensCosmo -from slsim.ParamDistributions.los_config import LOSConfig from slsim.lens import Lens -from slsim.Util.param_util import ellipticity_slsim_to_lenstronomy -from slsim.lens import theta_e_when_source_infinity - -class FalsePositive(object): +class FalsePositive(Lens): """Class to manage individual false positive.""" def __init__( @@ -33,162 +28,14 @@ def __init__( "kappa" = kappa as entries :type los_dict: dict """ - self.deflector = deflector_class - self.source = source_class - self.test_area = test_area - self.cosmo = cosmo - if isinstance(self.source, list): - source_z = self.source[0].redshift - self._source_type = self.source[0].source_type - self.source_number = len(self.source) - self.single_source_class = self.source[0] # to access some common kwargs. - else: - source_z = self.source.redshift - self._source_type = self.source.source_type - self.source_number = 1 - self.single_source_class = self.source - self._lens_cosmo = LensCosmo( - z_lens=float(self.deflector.redshift), - z_source=float(source_z), - cosmo=self.cosmo, - ) - - self._los_linear_distortions_cache = None - self.los_config = los_config - if self.los_config is None: - if los_dict is None: - los_dict = {} - self.los_config = LOSConfig(**los_dict) - - @property - def deflector_position(self): - """Center of the deflector position. - - :return: [x_pox, y_pos] in arc seconds - """ - return self.deflector.deflector_center - - @property - def deflector_redshift(self): - """ - - :return: lens redshift - """ - return self.deflector.redshift - - @property - def source_redshift(self): - """ - - :return: a source redshift or list of source redshift - """ - if self.source_number == 1: - source_redshift = self.source.redshift - else: - source_redshift = [] - for i in range(self.source_number): - source_redshift.append(self.source[i].redshift) - return source_redshift - - @property - def external_convergence(self): - """ - - :return: external convergence - """ - _, _, kappa_ext = self.los_linear_distortions - return kappa_ext - - @property - def external_shear(self): - """ - - :return: the absolute external shear - """ - gamma1, gamma2, _ = self.los_linear_distortions - return (gamma1**2 + gamma2**2) ** 0.5 - - @property - def einstein_radius(self): - """Einstein radius, from SIS approximation (coming from velocity dispersion) + - external convergence effect. - - :return: Einstein radius [arc seconds] - """ - theta_E = theta_e_when_source_infinity( - v_sigma=self.deflector_velocity_dispersion() - ) - _, _, kappa_ext = self.los_linear_distortions - return theta_E / (1 - kappa_ext) - - def deflector_ellipticity(self): - """ - - :return: e1_light, e2_light, e1_mass, e2_mass - """ - e1_light, e2_light = self.deflector.light_ellipticity - e1_mass, e2_mass = self.deflector.mass_ellipticity - return e1_light, e2_light, e1_mass, e2_mass - - def deflector_stellar_mass(self): - """ - - :return: stellar mass of deflector - """ - return self.deflector.stellar_mass - - def deflector_velocity_dispersion(self): - """ - - :return: velocity dispersion [km/s] - """ - return self.deflector.velocity_dispersion(cosmo=self.cosmo) - - @property - def los_linear_distortions(self): - if self._los_linear_distortions_cache is None: - self._los_linear_distortions_cache = ( - self._calculate_los_linear_distortions() + Lens.__init__(self, + source_class=source_class, + deflector_class=deflector_class, + cosmo=cosmo, + test_area=test_area, + los_config=los_config, + los_dict=los_dict, ) - return self._los_linear_distortions_cache - - def _calculate_los_linear_distortions(self): - """Line-of-sight distortions in shear and convergence. - - :return: kappa, gamma1, gamma2 - """ - if self.source_number == 1: - source_z = self.source_redshift - else: - source_z = self.source_redshift[0] - return self.los_config.calculate_los_linear_distortions( - source_redshift=source_z, - deflector_redshift=self.deflector_redshift, - ) - - def deflector_magnitude(self, band): - """Apparent magnitude of the deflector for a given band. - - :param band: imaging band - :type band: string - :return: magnitude of deflector in given band - """ - return self.deflector.magnitude(band=band) - - def extended_source_magnitude(self, band): - """Unlensed apparent magnitude of the extended source for a given band (assumes - that size is the same for different bands) - - :param band: imaging band - :type band: string - :param lensed: if True, returns the lensed magnified magnitude - :type lensed: bool - :return: magnitude of source in given band - """ - # band_string = str("mag_" + band) - # TODO: might have to change conventions between extended and point source - source_mag = self.source.extended_source_magnitude(band) - return source_mag def lenstronomy_kwargs(self, band=None): """Generates lenstronomy dictionary conventions for the class object. @@ -224,92 +71,4 @@ def lenstronomy_kwargs(self, band=None): "kwargs_ps": kwargs_ps, } - return kwargs_model, kwargs_params - - def deflector_mass_model_lenstronomy(self): - """Returns lens model instance and parameters in lenstronomy conventions. - - :return: lens_model_list, kwargs_lens - """ - if self.deflector.deflector_type in ["EPL", "NFW_HERNQUIST", "NFW_CLUSTER"]: - lens_mass_model_list, kwargs_lens = self.deflector.mass_model_lenstronomy( - lens_cosmo=self._lens_cosmo - ) - else: - raise ValueError( - "Deflector model %s not supported for lenstronomy model" - % self.deflector.deflector_type - ) - # adding line-of-sight structure - gamma1, gamma2, kappa_ext = self.los_linear_distortions - gamma1_lenstronomy, gamma2_lenstronomy = ellipticity_slsim_to_lenstronomy( - e1_slsim=gamma1, e2_slsim=gamma2 - ) - kwargs_lens.append( - { - "gamma1": gamma1_lenstronomy, - "gamma2": gamma2_lenstronomy, - "ra_0": 0, - "dec_0": 0, - } - ) - kwargs_lens.append({"kappa": kappa_ext, "ra_0": 0, "dec_0": 0}) - lens_mass_model_list.append("SHEAR") - lens_mass_model_list.append("CONVERGENCE") - - return lens_mass_model_list, kwargs_lens - - def deflector_light_model_lenstronomy(self, band): - """Returns lens model instance and parameters in lenstronomy conventions. - - :param band: imaging band - :type band: str - :return: lens_light_model_list, kwargs_lens_light - """ - return self.deflector.light_model_lenstronomy(band=band) - - def source_light_model_lenstronomy(self, band=None): - """Returns source light model instance and parameters in lenstronomy - conventions. - - :return: source_light_model_list, kwargs_source_light - """ - source_models = {} - all_source_kwarg_dict = {} - """If ( self._source_type == "extended". - - or self._source_type == "point_plus_extended" ): - """ - if self.source_number == 1: - source_class = self.source - else: - source_class = self.source[0] - if source_class.light_profile == "single_sersic": - source_models["source_light_model_list"] = [ - "SERSIC_ELLIPSE" - ] * self.source_number - # In this case we will consider a single source with double sersic profile. - else: - raise ValueError( - "Provided light profile is not supported. Supported" - " light profile is single_sersic" - ) - if self.source_number == 1: - kwargs_source = self.source.kwargs_extended_source_light( - draw_area=self.test_area, center_lens=self.deflector_position, band=band - ) - else: - kwargs_source = [] - for i in range(self.source_number): - kwargs_source.append( - self.source[i].kwargs_extended_source_light( - draw_area=self.test_area, - center_lens=self.deflector_position, - band=band, - )[0] - ) - - kwargs_ps = None - all_source_kwarg_dict["kwargs_source"] = kwargs_source - all_source_kwarg_dict["kwargs_ps"] = kwargs_ps - return source_models, all_source_kwarg_dict \ No newline at end of file + return kwargs_model, kwargs_params \ No newline at end of file diff --git a/tests/test_FalsePositives/test_false_positive.py b/tests/test_FalsePositives/test_false_positive.py index e4ae372c2..7db789970 100644 --- a/tests/test_FalsePositives/test_false_positive.py +++ b/tests/test_FalsePositives/test_false_positive.py @@ -122,13 +122,13 @@ def test_false_positive(): ) assert len(false_positive_instance_2.deflector_position) == 2 assert false_positive_instance_2.deflector_redshift == single_deflector["z"] - assert false_positive_instance_1.source_redshift == single_source1["z"] - assert np.all(false_positive_instance_2.source_redshift) == np.all( + assert false_positive_instance_1.source_redshift_list[0] == single_source1["z"] + assert np.all(false_positive_instance_2.source_redshift_list) == np.all( np.array([single_source1["z"], single_source2["z"]]) ) assert false_positive_instance_1.external_convergence < 0.1 assert false_positive_instance_1.external_shear < 0.2 - assert false_positive_instance_1.einstein_radius < 2.5 + assert false_positive_instance_1.einstein_radius[0] < 2.5 assert ( false_positive_instance_1.deflector_magnitude(band="i") == single_deflector["mag_i"] From 398770a0cf870d3ee3a226b81b8abb142a058862 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 12:54:18 -0500 Subject: [PATCH 11/33] minor change --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 120e9fa60..41f416023 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,6 +9,7 @@ ci: autoupdate_schedule: weekly skip: [] submodules: false + pre-commit: migrate-config repos: - repo: https://github.com/astral-sh/ruff-pre-commit From 02d39a00716a11453188b4ee92289a9cb64702d6 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:08:15 -0500 Subject: [PATCH 12/33] minor change --- .pre-commit-config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 41f416023..120e9fa60 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,6 @@ ci: autoupdate_schedule: weekly skip: [] submodules: false - pre-commit: migrate-config repos: - repo: https://github.com/astral-sh/ruff-pre-commit From c8597e05a989f7d3e216d336a260de455f8c38e4 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:12:05 -0500 Subject: [PATCH 13/33] minor change --- .pre-commit-config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 120e9fa60..4e27ae243 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,3 +43,5 @@ repos: - id: docformatter additional_dependencies: [tomli] args: [-r, --black, --in-place] + language: python # Change 'python_venv' to 'python' + From 9cf6a7e2fbe66c557638f2f9199bc2e5d28bd340 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:12:33 -0500 Subject: [PATCH 14/33] minor change --- .pre-commit-config.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4e27ae243..120e9fa60 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,5 +43,3 @@ repos: - id: docformatter additional_dependencies: [tomli] args: [-r, --black, --in-place] - language: python # Change 'python_venv' to 'python' - From aaf669e6830de2d9252534c8aa7c970206bcb4a3 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:14:03 -0500 Subject: [PATCH 15/33] minor change --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 120e9fa60..e93c003b8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,3 +43,4 @@ repos: - id: docformatter additional_dependencies: [tomli] args: [-r, --black, --in-place] + language: python From 7720b3f1305ff6468a907d9f952ef2702344e0f3 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:24:13 -0500 Subject: [PATCH 16/33] minor change --- .pre-commit-config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e93c003b8..120e9fa60 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,4 +43,3 @@ repos: - id: docformatter additional_dependencies: [tomli] args: [-r, --black, --in-place] - language: python From 52d4711b85a796fa60c07f2fe9a432b776e60e2a Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:50:40 -0500 Subject: [PATCH 17/33] delete cache file. --- .github/workflows/pre-commit.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 54ea5f083..8cda7968b 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,4 +11,11 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 + - name: Cache Pre-commit + uses: actions/cache@v3 + with: + path: ~/.cache/pre-commit + key: ${{ runner.os }}-pre-commit-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-pre-commit- - uses: pre-commit/action@v3.0.0 \ No newline at end of file From aab0e9f9fb2c76dcf2ba99c6c3cf635ea16a660b Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:51:56 -0500 Subject: [PATCH 18/33] minor change --- .github/workflows/pre-commit.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 8cda7968b..54ea5f083 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,11 +11,4 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 - - name: Cache Pre-commit - uses: actions/cache@v3 - with: - path: ~/.cache/pre-commit - key: ${{ runner.os }}-pre-commit-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-pre-commit- - uses: pre-commit/action@v3.0.0 \ No newline at end of file From 492fa37ee0c592eb30ba96e7ad9467f74fd686d1 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:54:11 -0500 Subject: [PATCH 19/33] minor change --- .github/workflows/pre-commit.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 54ea5f083..8cda7968b 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,4 +11,11 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 + - name: Cache Pre-commit + uses: actions/cache@v3 + with: + path: ~/.cache/pre-commit + key: ${{ runner.os }}-pre-commit-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-pre-commit- - uses: pre-commit/action@v3.0.0 \ No newline at end of file From ddead4cabdceae18844ceae9c15ffad197b7c9aa Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 13:55:08 -0500 Subject: [PATCH 20/33] minor change --- .github/workflows/pre-commit.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 8cda7968b..54ea5f083 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,11 +11,4 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 - - name: Cache Pre-commit - uses: actions/cache@v3 - with: - path: ~/.cache/pre-commit - key: ${{ runner.os }}-pre-commit-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-pre-commit- - uses: pre-commit/action@v3.0.0 \ No newline at end of file From 821ec957c872b66f5dfb0043767a5d9299716691 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 16:23:01 -0500 Subject: [PATCH 21/33] worked on Simon's comments --- slsim/FalsePositives/false_positive.py | 4 +- slsim/FalsePositives/false_positive_pop.py | 120 +++++++++++---------- slsim/lens_pop.py | 10 +- tests/test_lens_pop.py | 2 +- 4 files changed, 72 insertions(+), 64 deletions(-) diff --git a/slsim/FalsePositives/false_positive.py b/slsim/FalsePositives/false_positive.py index b9bf67e2a..1f01b2f4c 100644 --- a/slsim/FalsePositives/false_positive.py +++ b/slsim/FalsePositives/false_positive.py @@ -2,7 +2,9 @@ from slsim.lens import Lens class FalsePositive(Lens): - """Class to manage individual false positive.""" + """Class to manage individual false positive. Here, false positives refer to a + configuration that includes an elliptical galaxy at the center with blue galaxies + surrounding the central elliptical galaxy.""" def __init__( self, diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py index 3cc9438e3..9dea77f57 100644 --- a/slsim/FalsePositives/false_positive_pop.py +++ b/slsim/FalsePositives/false_positive_pop.py @@ -11,7 +11,10 @@ class FalsePositivePop(object): - """Class to perform samples of false positive population.""" + """Class to perform samples of false positive population. Here, Here, false + positives refer to a configuration that includes an elliptical galaxy at the center + with blue galaxies surrounding the central elliptical galaxy. This class generates + specified number of false positives.""" def __init__( self, @@ -43,74 +46,77 @@ def __init__( self.los_config = los_config if self.los_config is None: self.los_config = LOSConfig() + + def draw_deflector(self): + """Draw and prepare a deflector (lens) with tolerance-based z_max. + + :return: a deflector instance and deflector redshift with tolerance added. + """ + lens = self._lens_galaxies.draw_deflector() + deflector = Deflector( + deflector_type=self._lens_galaxies.deflector_profile, + deflector_dict=lens, + ) + z_max = deflector.redshift + 0.002 # Adding tolerance to redshift + return deflector, z_max + + def draw_sources(self, z_max): + """Draw source(s) within the redshift limit of z_max. + :param z_max: maximum redshift for drawn source. + :return: A Source instance or a list of Source instance. + + """ + source_number = random.choices(self._choice, weights=self._weights)[0] + source_list = [] + + for _ in range(source_number): + source = self._sources.draw_source(z_max=z_max) + # If no source is available, return None + if source is None: + return None + source_list.append( + Source( + source_dict=source, + cosmo=self.cosmo, + source_type=self._sources.source_type, + light_profile=self._sources.light_profile, + ) + ) + if source_number==1: + sources = source_list[0] + else: + sources = source_list + return sources def draw_false_positive(self, number=1): + """Draw given number of false positives within the cuts of the lens and source. :param number: number of false positive requested. The default value is 1. - :return: list of FalsePositive() instance with parameters of a pair of - elliptical and blue galaxy. - """ + :return: list of FalsePositive() instance. + """ false_positive_population = [] for _ in range(number): successful = False while not successful: - # Sample a lens (deflector) - lens = self._lens_galaxies.draw_deflector() - _lens = Deflector( - deflector_type=self._lens_galaxies.deflector_profile, - deflector_dict=lens, - ) - tolerance = 0.002 - z_max = _lens.redshift + tolerance - # Try to draw a source with the z_max based on the lens redshift and - # source number choice. - source_number = random.choices(self._choice, weights=self._weights)[0] - source_list = [] - valid_sources = True + # Step 1: Draw deflector + lens, z_max = self.draw_deflector() + # Step 2: Draw sources + source = self.draw_sources(z_max) + if source is None: + continue # Retry if sources are invalid - for _ in range(source_number): - source = self._sources.draw_source(z_max=z_max) - # If the source is None, mark sources as invalid and break to retry - if source is None: - valid_sources = False - break - source_list.append( - Source( - source_dict=source, + # Step 3: Create false positive + vd=lens.velocity_dispersion(cosmo=self.cosmo) + test_area = 3 * draw_test_area( + v_sigma=vd) + false_positive = FalsePositive( + deflector_class=lens, + source_class=source, cosmo=self.cosmo, - source_type=self._sources.source_type, - light_profile=self._sources.light_profile, + test_area=test_area, ) - ) - - # Skip the rest of the loop if sources are invalid - if not valid_sources: - continue - - # Handle single or multiple sources - if source_number == 1: - _source = source_list[0] - else: - _source = source_list - - # Compute test area for false positive position. - test_area = 3 * draw_test_area(deflector=lens) - - # Create a FalsePositive instance with the lens and source information - false_positive = FalsePositive( - deflector_class=_lens, - source_class=_source, - cosmo=self.cosmo, - test_area=test_area, - ) - - # Add the false positive to the population false_positive_population.append(false_positive) successful = True - - if number == 1: - return false_positive_population[0] - else: - return false_positive_population \ No newline at end of file + return false_positive_population[0] if number==1 else false_positive_population diff --git a/slsim/lens_pop.py b/slsim/lens_pop.py index 26e56dc47..01d7e6e56 100644 --- a/slsim/lens_pop.py +++ b/slsim/lens_pop.py @@ -92,7 +92,7 @@ def select_lens_at_random(self, test_area=None, **kwargs_lens_cut): deflector_dict=lens, ) if test_area is None: - test_area = draw_test_area(deflector=lens) + test_area = draw_test_area(deflector_dict=lens) else: test_area = test_area _source = Source( @@ -184,7 +184,7 @@ def draw_population(self, kwargs_lens_cuts, speed_factor=1): # Draw a population of galaxy-galaxy lenses within the area. for _ in range(int(num_lenses / speed_factor)): lens = self._lens_galaxies.draw_deflector() - test_area = draw_test_area(deflector=lens) + test_area = draw_test_area(deflector_dict=lens) num_sources_tested = self.get_num_sources_tested( testarea=test_area * speed_factor ) @@ -241,12 +241,12 @@ def draw_population(self, kwargs_lens_cuts, speed_factor=1): return lens_population -def draw_test_area(deflector): +def draw_test_area(**kwargs): """Draw a test area around the deflector. - :param deflector: deflector dictionary + :param kwargs: Either deflector dictionary or v_sigma for velocity dispersion. :return: test area in arcsec^2 """ - theta_e_infinity = theta_e_when_source_infinity(deflector) + theta_e_infinity = theta_e_when_source_infinity(**kwargs) test_area = np.pi * (theta_e_infinity * 2.5) ** 2 return test_area diff --git a/tests/test_lens_pop.py b/tests/test_lens_pop.py index 42b7f6e75..b38599b00 100644 --- a/tests/test_lens_pop.py +++ b/tests/test_lens_pop.py @@ -397,7 +397,7 @@ def test_num_lenses_and_sources(gg_lens_pop_instance): def test_num_sources_tested_and_test_area(gg_lens_pop_instance): lens = gg_lens_pop_instance._lens_galaxies.draw_deflector() - test_area = draw_test_area(deflector=lens) + test_area = draw_test_area(deflector_dict=lens) assert ( 0.01 < test_area < 100 * np.pi ), "Expected test_area to be between 0.1 and 100*pi," From bb42685ce3e63342929392795806927c3fd82e95 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 16:33:02 -0500 Subject: [PATCH 22/33] added tests --- tests/test_FalsePositives/test_false_positive_pop.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_FalsePositives/test_false_positive_pop.py b/tests/test_FalsePositives/test_false_positive_pop.py index e49e65c68..1ab67a501 100644 --- a/tests/test_FalsePositives/test_false_positive_pop.py +++ b/tests/test_FalsePositives/test_false_positive_pop.py @@ -41,7 +41,12 @@ def test_draw_false_positive_single(): source_number_choice=[1], ) draw_fp1 = fp_pop1.draw_false_positive() + draw_deflector = fp_pop1.draw_deflector() + draw_source = fp_pop1.draw_sources(z_max=draw_deflector[1]) assert isinstance(draw_fp1, object) + assert isinstance(draw_deflector[0], object) + assert draw_deflector[1] == draw_deflector[0].redshift + 0.002 + assert isinstance(draw_source, object) def test_draw_false_positive_multiple(): From 3e532fdf3fcd88634d9aad03c14e8df30b7db6b5 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 16:45:02 -0500 Subject: [PATCH 23/33] changes doc formating --- slsim/FalsePositives/false_positive_pop.py | 32 ++++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py index 9dea77f57..fca339598 100644 --- a/slsim/FalsePositives/false_positive_pop.py +++ b/slsim/FalsePositives/false_positive_pop.py @@ -18,24 +18,26 @@ class FalsePositivePop(object): def __init__( self, - elliptical_galaxy_population: DeflectorsBase, - blue_galaxy_population: SourcePopBase, - cosmo: Optional[Cosmology] = None, - los_config: Optional[LOSConfig] = None, - source_number_choice: Optional[list[int]] = [1, 2, 3], - weights_for_source_number: Optional[list[int]] = None, + elliptical_galaxy_population, + blue_galaxy_population, + cosmo=None, + los_config=None, + source_number_choice=[1, 2, 3], + weights_for_source_number=None, ): """ Args: - deflector_population (DeflectorsBase): Deflector population as an instance of a DeflectorsBase subclass. - source_population (SourcePopBase): Source population as an instance of a SourcePopBase subclass - cosmo (Optional[Cosmology], optional): AstroPy Cosmology instance. If None, defaults to flat LCDM with h0=0.7 and Om0=0.3. - Defaults to None. - los_config (Optional[LOSConfig], optional): Configuration for line of sight distribution. Defaults to None. - source_number_choice (Optional[list[int]], optional): A list of integers to choose source number from. If None, defaults to [1, 2, 3]. - weights (Optional[list[int]], optional): A list of weights corresponding to the probabilities of selecting each value - in source_number_choice. If None, all choices are equally likely. - Defaults to None. + :param deflector_population: Deflector population as an deflectors class + instance. + :param source_population: Source population as an sources class inatnce. + :param cosmo: astropy.cosmology instance + :param los_config: LOSConfig instance which manages line-of-sight (LOS) effects + and Gaussian mixture models in a simulation or analysis context. + :param source_number_choice: A list of integers to choose source number from. If + None, defaults to [1, 2, 3]. + :param weights: A list of weights corresponding to the probabilities of + selecting each value in source_number_choice. If None, all choices are equally + likely. Defaults to None. """ self.cosmo = cosmo From e83839c85de7615bd7be2fc1f9c63512baadfd78 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 20:36:54 -0500 Subject: [PATCH 24/33] minor change --- slsim/FalsePositives/false_positive_pop.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py index fca339598..bf11bdada 100644 --- a/slsim/FalsePositives/false_positive_pop.py +++ b/slsim/FalsePositives/false_positive_pop.py @@ -11,7 +11,7 @@ class FalsePositivePop(object): - """Class to perform samples of false positive population. Here, Here, false + """Class to perform samples of false positive population. Here, false positives refer to a configuration that includes an elliptical galaxy at the center with blue galaxies surrounding the central elliptical galaxy. This class generates specified number of false positives.""" @@ -24,6 +24,7 @@ def __init__( los_config=None, source_number_choice=[1, 2, 3], weights_for_source_number=None, + test_area_factor=1 ): """ Args: @@ -38,6 +39,9 @@ def __init__( :param weights: A list of weights corresponding to the probabilities of selecting each value in source_number_choice. If None, all choices are equally likely. Defaults to None. + :param test_area_factor: A multiplicative factor of a test_area. A test area is + computed using a velocity dispersion of a central galaxy and that area is + multiplied by this factor. A default value is 1. """ self.cosmo = cosmo @@ -45,6 +49,7 @@ def __init__( self._sources = blue_galaxy_population self._choice = source_number_choice self._weights = weights_for_source_number + self._test_area_factor = test_area_factor self.los_config = los_config if self.los_config is None: self.los_config = LOSConfig() @@ -103,18 +108,18 @@ def draw_false_positive(self, number=1): successful = False while not successful: # Step 1: Draw deflector - lens, z_max = self.draw_deflector() + deflector, z_max = self.draw_deflector() # Step 2: Draw sources source = self.draw_sources(z_max) if source is None: continue # Retry if sources are invalid # Step 3: Create false positive - vd=lens.velocity_dispersion(cosmo=self.cosmo) - test_area = 3 * draw_test_area( + vd=deflector.velocity_dispersion(cosmo=self.cosmo) + test_area = self._test_area_factor * draw_test_area( v_sigma=vd) false_positive = FalsePositive( - deflector_class=lens, + deflector_class=deflector, source_class=source, cosmo=self.cosmo, test_area=test_area, From b0bd19411b9335a5bc6799e2541917cdf65529a0 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 12 Nov 2024 20:37:45 -0500 Subject: [PATCH 25/33] minor change --- slsim/FalsePositives/false_positive_pop.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py index bf11bdada..6990cc703 100644 --- a/slsim/FalsePositives/false_positive_pop.py +++ b/slsim/FalsePositives/false_positive_pop.py @@ -1,9 +1,5 @@ from slsim.FalsePositives.false_positive import FalsePositive -from typing import Optional -from astropy.cosmology import Cosmology -from slsim.Sources.source_pop_base import SourcePopBase from slsim.ParamDistributions.los_config import LOSConfig -from slsim.Deflectors.deflectors_base import DeflectorsBase from slsim.Sources.source import Source from slsim.Deflectors.deflector import Deflector from slsim.lens_pop import draw_test_area From ff1f1d181501bd885c873bc881a46d9c52ff734b Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 11:53:10 -0500 Subject: [PATCH 26/33] change draw_deflector function in deflector population classes. --- slsim/Deflectors/all_lens_galaxies.py | 5 +- slsim/Deflectors/cluster_deflectors.py | 5 +- .../compound_lens_halos_galaxies.py | 8 ++- slsim/Deflectors/elliptical_lens_galaxies.py | 5 +- slsim/FalsePositives/false_positive_pop.py | 4 +- slsim/lens_pop.py | 55 +++++++++---------- tests/test_lens_pop.py | 6 +- 7 files changed, 48 insertions(+), 40 deletions(-) diff --git a/slsim/Deflectors/all_lens_galaxies.py b/slsim/Deflectors/all_lens_galaxies.py index 3c2133671..cbe99cff6 100644 --- a/slsim/Deflectors/all_lens_galaxies.py +++ b/slsim/Deflectors/all_lens_galaxies.py @@ -8,6 +8,7 @@ from slsim.Deflectors.deflectors_base import DeflectorsBase from astropy.table import vstack from slsim.Util.param_util import catalog_with_angular_size_in_arcsec +from slsim.Deflectors.deflector import Deflector class AllLensGalaxies(DeflectorsBase): @@ -125,7 +126,9 @@ def draw_deflector(self): deflector["e2_mass"] = e2_mass if deflector["n_sersic"] == -1: deflector["n_sersic"] = 4 # TODO make a better estimate with scatter - return deflector + deflector_class = Deflector(deflector_type=self.deflector_profile, + deflector_dict=deflector) + return deflector_class def fill_table(galaxy_list): diff --git a/slsim/Deflectors/cluster_deflectors.py b/slsim/Deflectors/cluster_deflectors.py index f1e231907..75b69516f 100644 --- a/slsim/Deflectors/cluster_deflectors.py +++ b/slsim/Deflectors/cluster_deflectors.py @@ -12,6 +12,7 @@ ) from slsim.Deflectors.velocity_dispersion import vel_disp_nfw from slsim.Deflectors.deflectors_base import DeflectorsBase +from slsim.Deflectors.deflector import Deflector from lenstronomy.Util.param_util import phi_q2_ellipticity from astropy import units as u from astropy.table import hstack @@ -120,7 +121,9 @@ def draw_deflector(self): deflector = self.draw_cluster(index) members = self.draw_members(deflector["cluster_id"], **self.kwargs_draw_members) deflector["subhalos"] = members - return deflector + deflector_class = Deflector(deflector_type=self.deflector_profile, + deflector_dict=deflector) + return deflector_class def draw_cluster(self, index): """ diff --git a/slsim/Deflectors/compound_lens_halos_galaxies.py b/slsim/Deflectors/compound_lens_halos_galaxies.py index 4a91a85f5..8a5f7e820 100644 --- a/slsim/Deflectors/compound_lens_halos_galaxies.py +++ b/slsim/Deflectors/compound_lens_halos_galaxies.py @@ -5,7 +5,7 @@ from slsim.Deflectors.deflectors_base import DeflectorsBase from lenstronomy.Util import constants from slsim.Deflectors.elliptical_lens_galaxies import elliptical_projected_eccentricity - +from slsim.Deflectors.deflector import Deflector class CompoundLensHalosGalaxies(DeflectorsBase): """Class describing compound lens model in which the mass distribution of individual @@ -36,7 +36,7 @@ def __init__( cosmo=cosmo, sky_area=sky_area, ) - + self.deflector_profile = "NFW_HERNQUIST" n = len(halo_galaxy_list) column_names = halo_galaxy_list.columns if "vel_disp" not in column_names: @@ -121,4 +121,6 @@ def draw_deflector(self): deflector["e2_light"] = e2_light deflector["e1_mass"] = e1_mass deflector["e2_mass"] = e2_mass - return deflector + deflector_class = Deflector(deflector_type=self.deflector_profile, + deflector_dict=deflector) + return deflector_class diff --git a/slsim/Deflectors/elliptical_lens_galaxies.py b/slsim/Deflectors/elliptical_lens_galaxies.py index 9699a5211..407aa8cd8 100644 --- a/slsim/Deflectors/elliptical_lens_galaxies.py +++ b/slsim/Deflectors/elliptical_lens_galaxies.py @@ -4,6 +4,7 @@ from slsim.Util import param_util from slsim.Deflectors.deflectors_base import DeflectorsBase from slsim.Deflectors.velocity_dispersion import vel_disp_abundance_matching +from slsim.Deflectors.deflector import Deflector class EllipticalLensGalaxies(DeflectorsBase): @@ -110,7 +111,9 @@ def draw_deflector(self): deflector["e2_mass"] = e2_mass if deflector["n_sersic"] == -1: deflector["n_sersic"] = 4 # TODO make a better estimate with scatter - return deflector + deflector_class = Deflector(deflector_type=self.deflector_profile, + deflector_dict=deflector) + return deflector_class def elliptical_projected_eccentricity( diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py index 6990cc703..94603497f 100644 --- a/slsim/FalsePositives/false_positive_pop.py +++ b/slsim/FalsePositives/false_positive_pop.py @@ -24,9 +24,9 @@ def __init__( ): """ Args: - :param deflector_population: Deflector population as an deflectors class + :param elliptical_galaxy_population: Deflector population as an deflectors class instance. - :param source_population: Source population as an sources class inatnce. + :param blue_galaxy_population: Source population as an sources class inatnce. :param cosmo: astropy.cosmology instance :param los_config: LOSConfig instance which manages line-of-sight (LOS) effects and Gaussian mixture models in a simulation or analysis context. diff --git a/slsim/lens_pop.py b/slsim/lens_pop.py index 01d7e6e56..a696f3bc3 100644 --- a/slsim/lens_pop.py +++ b/slsim/lens_pop.py @@ -30,23 +30,22 @@ def __init__( sn_modeldir: Optional[str] = None, ): """ - Args: - deflector_population (DeflectorsBase): Deflector population as an instance of a DeflectorsBase subclass. - source_population (SourcePopBase): Source population as an instance of a SourcePopBase subclass - cosmo (Optional[Cosmology], optional): AstroPy Cosmology instance. If None, defaults to flat LCDM with h0=0.7 and Om0=0.3. - Defaults to None. - lightcurve_time (Optional[np.ndarray], optional): Lightcurve observation time array in units of days. Defaults to None. - sn_type (Optional[str], optional): Supernova type (Ia, Ib, Ic, IIP, etc.). Defaults to None. - sn_absolute_mag_band (Optional[Union[str,sncosmo.Bandpass]], optional): Band used to normalize to absolute magnitude. - Defaults to None. - sn_absolute_zpsys (Optional[str], optional): Zero point system, either AB or Vega, with None defaulting to AB. - Defaults to None. - los_config (Optional[LOSConfig], optional): Configuration for line of sight distribution. Defaults to None. - sn_modeldir (Optional[str], optional): sn_modeldir is the path to the directory containing files needed to initialize - the sncosmo.model class. For example, sn_modeldir = - 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can be downloaded - from https://github.com/LSST-strong-lensing/data_public. For more detail, - please look at the documentation of RandomizedSupernovae class. Defaults to None. + :param deflector_population: Deflector population as an deflectors class + instance. + Source population as an sources class inatnce. + :param cosmo: astropy.cosmology instance + :param lightcurve_time: Lightcurve observation time array in units of days. Defaults to None. + :param sn_type: Supernova type (Ia, Ib, Ic, IIP, etc.). Defaults to None. + :param sn_absolute_mag_band: Band used to normalize to absolute magnitude. + Defaults to None. + :param sn_absolute_zpsys: Zero point system, either AB or Vega, with None defaulting to AB. + Defaults to None. + :param los_config: Configuration for line of sight distribution. Defaults to None. + :param sn_modeldir: sn_modeldir is the path to the directory containing files needed to initialize + the sncosmo.model class. For example, sn_modeldir = + 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can be downloaded + from https://github.com/LSST-strong-lensing/data_public. For more detail, + please look at the documentation of RandomizedSupernovae class. Defaults to None. """ # TODO: ADD EXCEPTION FOR DEFLECTOR AND SOURCE POP FILTER MISMATCH @@ -85,14 +84,13 @@ def select_lens_at_random(self, test_area=None, **kwargs_lens_cut): """ while True: #This creates a single deflector - single_source lens. + #-------------------------- source = self._sources.draw_source() - lens = self._lens_galaxies.draw_deflector() - _lens = Deflector( - deflector_type=self._lens_galaxies.deflector_profile, - deflector_dict=lens, - ) + #---------------------------- + _lens = self._lens_galaxies.draw_deflector() if test_area is None: - test_area = draw_test_area(deflector_dict=lens) + vel_disp=_lens.velocity_dispersion(cosmo=self.cosmo) + test_area = draw_test_area(v_sigma=vel_disp) else: test_area = test_area _source = Source( @@ -110,6 +108,7 @@ def select_lens_at_random(self, test_area=None, **kwargs_lens_cut): source_type=self._sources.source_type, light_profile=self._sources.light_profile, ) + #-------------------------------- gg_lens = Lens( deflector_class=_lens, source_class=_source, @@ -183,15 +182,13 @@ def draw_population(self, kwargs_lens_cuts, speed_factor=1): # Draw a population of galaxy-galaxy lenses within the area. for _ in range(int(num_lenses / speed_factor)): - lens = self._lens_galaxies.draw_deflector() - test_area = draw_test_area(deflector_dict=lens) + _lens = self._lens_galaxies.draw_deflector() + vel_disp=_lens.velocity_dispersion(cosmo=self.cosmo) + test_area = draw_test_area(v_sigma=vel_disp) num_sources_tested = self.get_num_sources_tested( testarea=test_area * speed_factor ) - _lens = Deflector( - deflector_type=self._lens_galaxies.deflector_profile, - deflector_dict=lens, - ) + if num_sources_tested > 0: valid_sources = [] n = 0 diff --git a/tests/test_lens_pop.py b/tests/test_lens_pop.py index b38599b00..3cfed2dd8 100644 --- a/tests/test_lens_pop.py +++ b/tests/test_lens_pop.py @@ -21,7 +21,6 @@ filters=None, ) - def create_lens_pop_instance(return_kext=False): cosmo = FlatLambdaCDM(H0=70, Om0=0.3) @@ -140,7 +139,7 @@ def test_galaxies_lens_pop_halo_model_instance(): cosmo=cosmo, sky_area=sky_area, ) - assert g_lens_halo_model_pop._lens_galaxies.draw_deflector()["halo_mass"] != 0 + assert g_lens_halo_model_pop._lens_galaxies.draw_deflector().halo_properties[0] != 0 def test_cluster_lens_pop_instance(): @@ -396,8 +395,9 @@ def test_num_lenses_and_sources(gg_lens_pop_instance): def test_num_sources_tested_and_test_area(gg_lens_pop_instance): + cosmo = FlatLambdaCDM(H0=70, Om0=0.3) lens = gg_lens_pop_instance._lens_galaxies.draw_deflector() - test_area = draw_test_area(deflector_dict=lens) + test_area = draw_test_area(v_sigma=lens.velocity_dispersion(cosmo=cosmo)) assert ( 0.01 < test_area < 100 * np.pi ), "Expected test_area to be between 0.1 and 100*pi," From 56905d1e8bd8dd604e72add04e75e43859fec401 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 12:33:20 -0500 Subject: [PATCH 27/33] adjusted test functions in deflectors classes. --- .../test_Deflectors/test_all_lens_galaxies.py | 8 +++---- .../test_cluster_deflectors.py | 15 +++++++----- .../test_compound_lens_halos_galaxies.py | 23 +++++++++++++------ .../test_elliptical_lens_galaxies.py | 8 +++---- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/tests/test_Deflectors/test_all_lens_galaxies.py b/tests/test_Deflectors/test_all_lens_galaxies.py index e99ff4870..ca9bbace0 100644 --- a/tests/test_Deflectors/test_all_lens_galaxies.py +++ b/tests/test_Deflectors/test_all_lens_galaxies.py @@ -42,7 +42,7 @@ def test_deflector_number_draw_deflector(all_lens_galaxies): galaxy_pop = all_lens_galaxies num_deflectors = galaxy_pop.deflector_number() deflector = galaxy_pop.draw_deflector() - assert deflector["z"] != 0 + assert deflector.redshift != 0 assert num_deflectors >= 0 @@ -109,9 +109,9 @@ def test_all_lens_galaxies_2(): sky_area=sky_area, gamma_pl={"gamma_min": 1.95, "gamma_max": 2.26} ) - assert galaxy_class1.draw_deflector()["gamma_pl"] == 2.05 - assert 1.6 <= galaxy_class2.draw_deflector()["gamma_pl"] <= 2.6 - assert 1.95 <= galaxy_class3.draw_deflector()["gamma_pl"] <= 2.26 + assert galaxy_class1.draw_deflector().halo_properties == 2.05 + assert 1.6 <= galaxy_class2.draw_deflector().halo_properties <= 2.6 + assert 1.95 <= galaxy_class3.draw_deflector().halo_properties <= 2.26 with pytest.raises(ValueError): AllLensGalaxies( red_galaxies4, diff --git a/tests/test_Deflectors/test_cluster_deflectors.py b/tests/test_Deflectors/test_cluster_deflectors.py index f3cdc2cbb..d75059cc4 100644 --- a/tests/test_Deflectors/test_cluster_deflectors.py +++ b/tests/test_Deflectors/test_cluster_deflectors.py @@ -57,12 +57,14 @@ def test_deflector_number(cluster_deflectors_instance): def test_draw_deflector(cluster_deflectors_instance): cluster_pop = cluster_deflectors_instance deflector = cluster_pop.draw_deflector() + cluster = cluster_pop.draw_cluster(index=0) + members = cluster_pop.draw_members(cluster_id=cluster["cluster_id"]) # test if the properties of the deflector are # as expected from the input catalog - assert (deflector["z"] > 0.2) and (deflector["z"] < 1.0) - assert (deflector["halo_mass"] > 1e12) and (deflector["halo_mass"] < 3e15) - assert (deflector["concentration"] > 1) and (deflector["concentration"] < 15) - assert (len(deflector["subhalos"]) >= 1) and (len(deflector["subhalos"]) < 100) + assert (deflector.redshift > 0.2) and (deflector.redshift < 1.0) + assert (deflector.halo_properties[0] > 1e12) and (deflector.halo_properties[0] < 3e15) + assert (deflector.halo_properties[1] > 1) and (deflector.halo_properties[1] < 15) + assert (len(members) >= 1) and (len(members) < 100) def test_missing_id(cluster_deflectors_input): @@ -161,8 +163,9 @@ def test_with_centers(cluster_deflectors_input): cosmo=cosmo, sky_area=sky_area, ) - deflector = cluster_pop.draw_deflector() - assert deflector["subhalos"]["center_x"][0] == 0.0 + cluster = cluster_pop.draw_cluster(index=0) + members = cluster_pop.draw_members(cluster_id=cluster["cluster_id"]) + assert members["center_x"][0] == 0.0 def test_missing_magnitudes(cluster_deflectors_input): diff --git a/tests/test_Deflectors/test_compound_lens_halos_galaxies.py b/tests/test_Deflectors/test_compound_lens_halos_galaxies.py index ea1e3ec46..8df027958 100644 --- a/tests/test_Deflectors/test_compound_lens_halos_galaxies.py +++ b/tests/test_Deflectors/test_compound_lens_halos_galaxies.py @@ -3,7 +3,7 @@ from slsim.Pipelines.sl_hammocks_pipeline import SLHammocksPipeline from astropy.units import Quantity from slsim.Deflectors.compound_lens_halos_galaxies import CompoundLensHalosGalaxies - +from lenstronomy.Cosmo.lens_cosmo import LensCosmo # Assuming other imports are already defined, we continue from here. @@ -33,16 +33,25 @@ def compound_lens_halos_galaxies(): def test_deflector_number_draw_deflector(compound_lens_halos_galaxies): # Mocking the deflector_cut function to return a subset of the galaxy list + cosmo = FlatLambdaCDM(H0=70, Om0=0.3, Ob0=0.05, Tcmb0=2.725) halo_galaxy_pop = compound_lens_halos_galaxies # Example subset num_deflectors = halo_galaxy_pop.deflector_number() deflector = halo_galaxy_pop.draw_deflector() - assert deflector["z"] > 0 + lens_cosmo = LensCosmo( + z_lens=float(deflector.redshift), + z_source=float(deflector.redshift+0.5), + cosmo=cosmo, + ) + light_lenstronomy = deflector.light_model_lenstronomy() + mass_lenstronomy = deflector.mass_model_lenstronomy(lens_cosmo) + expected_mass_model = ["NFW_ELLIPSE_CSE", "HERNQUIST_ELLIPSE_CSE"] + expected_light_model = ["HERNQUIST_ELLIPSE"] + assert deflector.redshift > 0 assert num_deflectors >= 0 - assert deflector["vel_disp"] > 0 - assert deflector["e1_light"] != -1 - assert deflector["e2_light"] != -1 - assert deflector["e1_mass"] != -1 - assert deflector["e2_mass"] != -1 + assert deflector.velocity_dispersion(cosmo=cosmo) > 0 + assert mass_lenstronomy[0][0] in expected_mass_model + assert mass_lenstronomy[0][1] in expected_mass_model + assert light_lenstronomy[0][0] in expected_light_model # The following decorator and function are needed to run the tests with pytest diff --git a/tests/test_Deflectors/test_elliptical_lens_galaxies.py b/tests/test_Deflectors/test_elliptical_lens_galaxies.py index e35e75a25..8ecc9f2bc 100644 --- a/tests/test_Deflectors/test_elliptical_lens_galaxies.py +++ b/tests/test_Deflectors/test_elliptical_lens_galaxies.py @@ -37,7 +37,7 @@ def test_deflector_number_draw_deflector(elliptical_lens_galaxies): galaxy_pop = elliptical_lens_galaxies num_deflectors = galaxy_pop.deflector_number() deflector = galaxy_pop.draw_deflector() - assert deflector["z"] != 0 + assert deflector.redshift != 0 assert num_deflectors >= 0 @@ -78,9 +78,9 @@ def test_elliptical_lens_galaxies_2(): sky_area=sky_area, gamma_pl={"gamma_min": 1.8, "gamma_max": 2.3} ) - assert galaxy_class1.draw_deflector()["gamma_pl"] == 2.15 - assert 1.5 <= galaxy_class2.draw_deflector()["gamma_pl"] <= 2.5 - assert 1.8 <= galaxy_class3.draw_deflector()["gamma_pl"] <= 2.3 + assert galaxy_class1.draw_deflector().halo_properties == 2.15 + assert 1.5 <= galaxy_class2.draw_deflector().halo_properties <= 2.5 + assert 1.8 <= galaxy_class3.draw_deflector().halo_properties <= 2.3 with pytest.raises(ValueError): EllipticalLensGalaxies( red_galaxies4, From bcdda6dae24c0599d5ce06969deb81f113bfe05f Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 14:24:23 -0500 Subject: [PATCH 28/33] changed draw_source function in source population classes. --- slsim/Sources/galaxies.py | 18 ++++++- slsim/Sources/point_plus_extended_sources.py | 23 ++++++++- slsim/Sources/point_sources.py | 41 ++++++++++++++- slsim/Sources/source_pop_base.py | 21 ++++++++ slsim/lens_pop.py | 54 ++------------------ tests/test_Source/test_galaxies.py | 14 ++--- tests/test_lens_pop.py | 21 ++++---- 7 files changed, 119 insertions(+), 73 deletions(-) diff --git a/slsim/Sources/galaxies.py b/slsim/Sources/galaxies.py index 90c2e2b1e..0c1d126fe 100644 --- a/slsim/Sources/galaxies.py +++ b/slsim/Sources/galaxies.py @@ -6,6 +6,7 @@ from astropy.table import Column from slsim.Util.param_util import average_angular_size, axis_ratio, eccentricity from astropy import units as u +from slsim.Sources.source import Source # TODO: Use type to determine galaxy_list type @@ -221,7 +222,22 @@ def draw_source(self, z_max=None): "Provided number of light profiles is not supported. It should be" "either 'single or 'double' " ) - return galaxy + source_class = Source( + source_dict=galaxy, + variability_model=self.variability_model, + kwargs_variability=self.kwargs_variability, + sn_type=self.sn_type, + sn_absolute_mag_band=self.sn_absolute_mag_band, + sn_absolute_zpsys=self.sn_absolute_zpsys, + cosmo=self._cosmo, + lightcurve_time=self.lightcurve_time, + sn_modeldir=self.sn_modeldir, + agn_driving_variability_model=self.agn_driving_variability_model, + agn_driving_kwargs_variability=self.agn_driving_kwargs_variability, + source_type=self.source_type, + light_profile=self.light_profile, + ) + return source_class def galaxy_projected_eccentricity(ellipticity, rotation_angle=None): diff --git a/slsim/Sources/point_plus_extended_sources.py b/slsim/Sources/point_plus_extended_sources.py index 3b727ee46..4156d72e0 100644 --- a/slsim/Sources/point_plus_extended_sources.py +++ b/slsim/Sources/point_plus_extended_sources.py @@ -19,6 +19,11 @@ def __init__( light_profile="single_sersic", list_type="astropy_table", catalog_type=None, + lightcurve_time=None, + sn_type=None, + sn_absolute_mag_band=None, + sn_absolute_zpsys=None, + sn_modeldir=None ): """ @@ -52,6 +57,17 @@ def __init__( :param catalog_type: type of the catalog. If someone wants to use scotch catalog, they need to specify it. :type catalog_type: str. eg: "scotch" or None + :param lightcurve_time: Lightcurve observation time array in units of days. Defaults to None. + :param sn_type: Supernova type (Ia, Ib, Ic, IIP, etc.). Defaults to None. + :param sn_absolute_mag_band: Band used to normalize to absolute magnitude. + Defaults to None. + :param sn_absolute_zpsys: Zero point system, either AB or Vega, with None defaulting to AB. + Defaults to None. + :param sn_modeldir: sn_modeldir is the path to the directory containing files needed to initialize + the sncosmo.model class. For example, sn_modeldir = + 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can be downloaded + from https://github.com/LSST-strong-lensing/data_public. For more detail, + please look at the documentation of RandomizedSupernovae class. Defaults to None. """ object_list = object_cut( @@ -78,5 +94,10 @@ def __init__( kwargs_variability_model=kwargs_variability_model, agn_driving_variability_model=agn_driving_variability_model, agn_driving_kwargs_variability=agn_driving_kwargs_variability, - ) + lightcurve_time=lightcurve_time, + sn_type=sn_type, + sn_absolute_mag_band=sn_absolute_mag_band, + sn_absolute_zpsys=sn_absolute_zpsys, + sn_modeldir=sn_modeldir + ) self.source_type = "point_plus_extended" diff --git a/slsim/Sources/point_sources.py b/slsim/Sources/point_sources.py index cc8ba298e..8828cd1c5 100644 --- a/slsim/Sources/point_sources.py +++ b/slsim/Sources/point_sources.py @@ -2,6 +2,7 @@ from slsim.Sources.source_pop_base import SourcePopBase import warnings from slsim.selection import object_cut +from slsim.Sources.source import Source class PointSources(SourcePopBase): @@ -19,6 +20,11 @@ def __init__( agn_driving_kwargs_variability=None, light_profile=None, list_type="astropy_table", + lightcurve_time=None, + sn_type=None, + sn_absolute_mag_band=None, + sn_absolute_zpsys=None, + sn_modeldir=None ): """ @@ -55,6 +61,17 @@ def __init__( light model. Always None for this class. :param list_type: type of the format of the source catalog. It should be either astropy_table or list of astropy table. + :param lightcurve_time: Lightcurve observation time array in units of days. Defaults to None. + :param sn_type: Supernova type (Ia, Ib, Ic, IIP, etc.). Defaults to None. + :param sn_absolute_mag_band: Band used to normalize to absolute magnitude. + Defaults to None. + :param sn_absolute_zpsys: Zero point system, either AB or Vega, with None defaulting to AB. + Defaults to None. + :param sn_modeldir: sn_modeldir is the path to the directory containing files needed to initialize + the sncosmo.model class. For example, sn_modeldir = + 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can be downloaded + from https://github.com/LSST-strong-lensing/data_public. For more detail, + please look at the documentation of RandomizedSupernovae class. Defaults to None. """ self.n = len(point_source_list) @@ -78,7 +95,12 @@ def __init__( kwargs_variability_model=kwargs_variability_model, agn_driving_variability_model=agn_driving_variability_model, agn_driving_kwargs_variability=agn_driving_kwargs_variability, - ) + lightcurve_time=lightcurve_time, + sn_type=sn_type, + sn_absolute_mag_band=sn_absolute_mag_band, + sn_absolute_zpsys=sn_absolute_zpsys, + sn_modeldir=sn_modeldir + ) self.source_type = "point_source" @property @@ -106,5 +128,20 @@ def draw_source(self): index = random.randint(0, self._num_select - 1) point_source = self._point_source_select[index] + source_class = Source( + source_dict=point_source, + variability_model=self.variability_model, + kwargs_variability=self.kwargs_variability, + sn_type=self.sn_type, + sn_absolute_mag_band=self.sn_absolute_mag_band, + sn_absolute_zpsys=self.sn_absolute_zpsys, + cosmo=self._cosmo, + lightcurve_time=self.lightcurve_time, + sn_modeldir=self.sn_modeldir, + agn_driving_variability_model=self.agn_driving_variability_model, + agn_driving_kwargs_variability=self.agn_driving_kwargs_variability, + source_type=self.source_type, + light_profile=self.light_profile, + ) - return point_source + return source_class diff --git a/slsim/Sources/source_pop_base.py b/slsim/Sources/source_pop_base.py index a36ba858b..54bafe231 100644 --- a/slsim/Sources/source_pop_base.py +++ b/slsim/Sources/source_pop_base.py @@ -13,6 +13,11 @@ def __init__( kwargs_variability_model=None, agn_driving_variability_model=None, agn_driving_kwargs_variability=None, + lightcurve_time=None, + sn_type=None, + sn_absolute_mag_band=None, + sn_absolute_zpsys=None, + sn_modeldir=None ): """ @@ -37,6 +42,17 @@ def __init__( "high_frequency_slope": 3, "normal_magnitude_variance": 0.1}. For the detailed explanation of these parameters, see generate_signal() function in astro_util.py. + :param lightcurve_time: Lightcurve observation time array in units of days. Defaults to None. + :param sn_type: Supernova type (Ia, Ib, Ic, IIP, etc.). Defaults to None. + :param sn_absolute_mag_band: Band used to normalize to absolute magnitude. + Defaults to None. + :param sn_absolute_zpsys: Zero point system, either AB or Vega, with None defaulting to AB. + Defaults to None. + :param sn_modeldir: sn_modeldir is the path to the directory containing files needed to initialize + the sncosmo.model class. For example, sn_modeldir = + 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can be downloaded + from https://github.com/LSST-strong-lensing/data_public. For more detail, + please look at the documentation of RandomizedSupernovae class. Defaults to None. """ self.source_type = None self.sky_area = sky_area @@ -45,6 +61,11 @@ def __init__( self._kwargs_variab_model = kwargs_variability_model self.agn_driving_variability_model = agn_driving_variability_model self.agn_driving_kwargs_variability = agn_driving_kwargs_variability + self.lightcurve_time = lightcurve_time + self.sn_type = sn_type + self.sn_absolute_mag_band = sn_absolute_mag_band + self.sn_absolute_zpsys = sn_absolute_zpsys + self.sn_modeldir = sn_modeldir @property @abstractmethod diff --git a/slsim/lens_pop.py b/slsim/lens_pop.py index a696f3bc3..7bb47ae94 100644 --- a/slsim/lens_pop.py +++ b/slsim/lens_pop.py @@ -1,16 +1,13 @@ -import sncosmo import numpy as np from slsim.lens import Lens -from typing import Optional, Union +from typing import Optional from astropy.cosmology import Cosmology from slsim.lens import theta_e_when_source_infinity from slsim.Sources.source_pop_base import SourcePopBase from slsim.ParamDistributions.los_config import LOSConfig from slsim.Deflectors.deflectors_base import DeflectorsBase from slsim.lensed_population_base import LensedPopulationBase -from slsim.Sources.source import Source -from slsim.Deflectors.deflector import Deflector class LensPop(LensedPopulationBase): @@ -22,12 +19,7 @@ def __init__( source_population: SourcePopBase, cosmo: Optional[Cosmology] = None, sky_area: Optional[float] = None, - lightcurve_time: Optional[np.ndarray] = None, - sn_type: Optional[str] = None, - sn_absolute_mag_band: Optional[Union[str, sncosmo.Bandpass]] = None, - sn_absolute_zpsys: Optional[str] = None, los_config: Optional[LOSConfig] = None, - sn_modeldir: Optional[str] = None, ): """ :param deflector_population: Deflector population as an deflectors class @@ -51,12 +43,7 @@ def __init__( # TODO: ADD EXCEPTION FOR DEFLECTOR AND SOURCE POP FILTER MISMATCH super().__init__( sky_area=sky_area, - cosmo=cosmo, - lightcurve_time=lightcurve_time, - sn_type=sn_type, - sn_absolute_mag_band=sn_absolute_mag_band, - sn_absolute_zpsys=sn_absolute_zpsys, - sn_modeldir=sn_modeldir, + cosmo=cosmo ) self.cosmo = cosmo self._lens_galaxies = deflector_population @@ -84,31 +71,13 @@ def select_lens_at_random(self, test_area=None, **kwargs_lens_cut): """ while True: #This creates a single deflector - single_source lens. - #-------------------------- - source = self._sources.draw_source() - #---------------------------- + _source = self._sources.draw_source() _lens = self._lens_galaxies.draw_deflector() if test_area is None: vel_disp=_lens.velocity_dispersion(cosmo=self.cosmo) test_area = draw_test_area(v_sigma=vel_disp) else: test_area = test_area - _source = Source( - source_dict=source, - variability_model=self._sources.variability_model, - kwargs_variability=self._sources.kwargs_variability, - sn_type=self.sn_type, - sn_absolute_mag_band=self.sn_absolute_mag_band, - sn_absolute_zpsys=self.sn_absolute_zpsys, - cosmo=self.cosmo, - lightcurve_time=self.lightcurve_time, - sn_modeldir=self.sn_modeldir, - agn_driving_variability_model=self._sources.agn_driving_variability_model, - agn_driving_kwargs_variability=self._sources.agn_driving_kwargs_variability, - source_type=self._sources.source_type, - light_profile=self._sources.light_profile, - ) - #-------------------------------- gg_lens = Lens( deflector_class=_lens, source_class=_source, @@ -193,22 +162,7 @@ def draw_population(self, kwargs_lens_cuts, speed_factor=1): valid_sources = [] n = 0 while n < num_sources_tested: - source = self._sources.draw_source() - _source = Source( - source_dict=source, - variability_model=self._sources.variability_model, - kwargs_variability=self._sources.kwargs_variability, - sn_type=self.sn_type, - sn_absolute_mag_band=self.sn_absolute_mag_band, - sn_absolute_zpsys=self.sn_absolute_zpsys, - cosmo=self.cosmo, - lightcurve_time=self.lightcurve_time, - sn_modeldir=self.sn_modeldir, - agn_driving_variability_model=self._sources.agn_driving_variability_model, - agn_driving_kwargs_variability=self._sources.agn_driving_kwargs_variability, - source_type=self._sources.source_type, - light_profile=self._sources.light_profile, - ) + _source = self._sources.draw_source() lens_class = Lens( deflector_class=_lens, source_class=_source, diff --git a/tests/test_Source/test_galaxies.py b/tests/test_Source/test_galaxies.py index cfa14b4ce..4dfd23f46 100644 --- a/tests/test_Source/test_galaxies.py +++ b/tests/test_Source/test_galaxies.py @@ -285,9 +285,9 @@ def test_draw_source(self): galaxy_1 = self.galaxies4.draw_source() galaxy_2 = self.galaxies.draw_source(z_max=1) galaxy_3 = self.galaxies5.draw_source(z_max=0.4) - assert len(galaxy) > 0 - assert galaxy_1["n_sersic"] == 1 - assert galaxy_2["z"] < 1 + 0.002 + assert len(galaxy.source_dict) > 0 + assert galaxy_1.source_dict["n_sersic"] == 1 + assert galaxy_2.redshift < 1 + 0.002 with pytest.raises(ValueError): self.galaxies5.draw_source() assert galaxy_3 is None @@ -295,10 +295,10 @@ def test_draw_source(self): def test_draw_source_double_sersic(self): galaxy1 = self.galaxies2.draw_source() galaxy2 = self.galaxies3.draw_source() - assert galaxy1["n_sersic_0"] == 1 - assert galaxy1["n_sersic_1"] == 4 - assert galaxy2["n_sersic_0"] == 1 - assert galaxy2["n_sersic_1"] == 4 + assert galaxy1.source_dict["n_sersic_0"] == 1 + assert galaxy1.source_dict["n_sersic_1"] == 4 + assert galaxy2.source_dict["n_sersic_0"] == 1 + assert galaxy2.source_dict["n_sersic_1"] == 4 with pytest.raises(ValueError): self.galaxies6.draw_source() with pytest.raises(ValueError): diff --git a/tests/test_lens_pop.py b/tests/test_lens_pop.py index 3cfed2dd8..71f1658ce 100644 --- a/tests/test_lens_pop.py +++ b/tests/test_lens_pop.py @@ -282,16 +282,17 @@ def test_supernovae_plus_galaxies_lens_pop_instance_2(): kwargs_cut=kwargs_source_cut, variability_model="light_curve", kwargs_variability_model={"supernovae_lightcurve", "i"}, + lightcurve_time=time_range, + sn_type="Ia", + sn_absolute_mag_band="bessellb", + sn_absolute_zpsys="ab", + sn_modeldir=None ) pes_lens_pop = LensPop( deflector_population=lens_galaxies, source_population=source_galaxies, cosmo=cosmo, - lightcurve_time=time_range, - sn_type="Ia", - sn_absolute_mag_band="bessellb", - sn_absolute_zpsys="ab", sky_area=sky_area, ) kwargs_lens_cut = {} @@ -343,16 +344,16 @@ def test_supernovae_lens_pop_instance(): kwargs_cut=kwargs_source_cut, variability_model="light_curve", kwargs_variability_model={"supernovae_lightcurve", "r"}, + lightcurve_time=time_range, + sn_type="Ia", + sn_absolute_mag_band="bessellb", + sn_absolute_zpsys="ab", ) ps_lens_pop_1 = LensPop( deflector_population=lens_galaxies_1, source_population=source_galaxies_1, cosmo=cosmo, - lightcurve_time=time_range, - sn_type="Ia", - sn_absolute_mag_band="bessellb", - sn_absolute_zpsys="ab", sky_area=sky_area_pop, ) # drawing population @@ -374,10 +375,6 @@ def test_supernovae_lens_pop_instance(): deflector_population=lens_galaxies_1, source_population=source_galaxies_1, cosmo=cosmo, - lightcurve_time=time_range, - sn_type="Ia", - sn_absolute_mag_band="bessellb", - sn_absolute_zpsys="ab", ) From 8520b948df4e09a5c10b87776cd531b3be0a81fb Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 14:29:38 -0500 Subject: [PATCH 29/33] adjusted a test function in point source case. --- tests/test_Source/test_quasar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_Source/test_quasar.py b/tests/test_Source/test_quasar.py index 8f596fa03..a94d2ab76 100644 --- a/tests/test_Source/test_quasar.py +++ b/tests/test_Source/test_quasar.py @@ -34,7 +34,7 @@ def test_source_number(Quasar_class): def test_draw_source(Quasar_class): quasar = Quasar_class.draw_source() - assert len(quasar) > 0 + assert len(quasar.source_dict) > 0 def test_source_number_selected(Quasar_class): From e152181ab389df55fed7453415b7e2ae55e24853 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 14:33:46 -0500 Subject: [PATCH 30/33] adjusted test functions. --- tests/test_Source/test_galaxies.py | 1 + tests/test_Source/test_point_plus_extended_source.py | 3 ++- tests/test_Source/test_quasar.py | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_Source/test_galaxies.py b/tests/test_Source/test_galaxies.py index 4dfd23f46..bc6e5c037 100644 --- a/tests/test_Source/test_galaxies.py +++ b/tests/test_Source/test_galaxies.py @@ -285,6 +285,7 @@ def test_draw_source(self): galaxy_1 = self.galaxies4.draw_source() galaxy_2 = self.galaxies.draw_source(z_max=1) galaxy_3 = self.galaxies5.draw_source(z_max=0.4) + assert isinstance(galaxy, object) assert len(galaxy.source_dict) > 0 assert galaxy_1.source_dict["n_sersic"] == 1 assert galaxy_2.redshift < 1 + 0.002 diff --git a/tests/test_Source/test_point_plus_extended_source.py b/tests/test_Source/test_point_plus_extended_source.py index 1555bbdf1..9156fa349 100644 --- a/tests/test_Source/test_point_plus_extended_source.py +++ b/tests/test_Source/test_point_plus_extended_source.py @@ -29,7 +29,8 @@ def test_source_number(self): def test_draw_source(self): point_plus_extended_sources = self.pe_source.draw_source() - assert len(point_plus_extended_sources) > 0 + assert isinstance(point_plus_extended_sources, object) + assert len(point_plus_extended_sources.source_dict) > 0 if __name__ == "__main__": diff --git a/tests/test_Source/test_quasar.py b/tests/test_Source/test_quasar.py index a94d2ab76..0d05080be 100644 --- a/tests/test_Source/test_quasar.py +++ b/tests/test_Source/test_quasar.py @@ -34,6 +34,7 @@ def test_source_number(Quasar_class): def test_draw_source(Quasar_class): quasar = Quasar_class.draw_source() + assert isinstance(quasar, object) assert len(quasar.source_dict) > 0 From 0bc6305d2f763c228193e92cc35c03e0f93c898a Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 14:37:35 -0500 Subject: [PATCH 31/33] adjusted inputs in LensedPopulationBase class. --- slsim/lensed_population_base.py | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/slsim/lensed_population_base.py b/slsim/lensed_population_base.py index ebf24c63e..220b98137 100644 --- a/slsim/lensed_population_base.py +++ b/slsim/lensed_population_base.py @@ -12,11 +12,6 @@ def __init__( self, sky_area=None, cosmo=None, - lightcurve_time=None, - sn_type=None, - sn_absolute_mag_band=None, - sn_absolute_zpsys=None, - sn_modeldir=None, ): """ @@ -24,31 +19,8 @@ def __init__( :type sky_area: `~astropy.units.Quantity` :param cosmo: cosmology :type cosmo: ~astropy.cosmology instance - :param lightcurve_time: observation time array for lightcurve in unit of days. - :type lightcurve_time: array - :param sn_type: Supernova type (Ia, Ib, Ic, IIP, etc.) - :type sn_type: str - :param sn_absolute_mag_band: Band used to normalize to absolute magnitude - :type sn_absolute_mag_band: str or `~sncosmo.Bandpass` - :param sn_absolute_zpsys: Optional, AB or Vega (AB default) - :type sn_absolute_zpsys: str - :param sn_modeldir: sn_modeldir is the path to the directory containing files - needed to initialize the sncosmo.model class. For example, - sn_modeldir = 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can - be downloaded from https://github.com/LSST-strong-lensing/data_public . - For more detail, please look at the documentation of RandomizedSupernovae - class. - :type sn_modeldir: str - :param agn_driving_variability_model: Variability model with light_curve output - which drives the variability across all bands of the agn. - :type agn_driving_kwargs_variability: dict """ - self.lightcurve_time = lightcurve_time - self.sn_type = sn_type - self.sn_absolute_mag_band = sn_absolute_mag_band - self.sn_absolute_zpsys = sn_absolute_zpsys - self.sn_modeldir = sn_modeldir if sky_area is None: # sky_area = Quantity(value=0.1, unit="deg2") raise ValueError("No sky area provided. Please provide needed sky area.") From 647a4a4b62ead22d9b0e07057488098c9cfa7fc8 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 14:40:30 -0500 Subject: [PATCH 32/33] minor change --- slsim/lens_pop.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/slsim/lens_pop.py b/slsim/lens_pop.py index 7bb47ae94..cf022ed5a 100644 --- a/slsim/lens_pop.py +++ b/slsim/lens_pop.py @@ -24,20 +24,11 @@ def __init__( """ :param deflector_population: Deflector population as an deflectors class instance. - Source population as an sources class inatnce. + :param source_population: Source population as an sources class inatnce. :param cosmo: astropy.cosmology instance - :param lightcurve_time: Lightcurve observation time array in units of days. Defaults to None. - :param sn_type: Supernova type (Ia, Ib, Ic, IIP, etc.). Defaults to None. - :param sn_absolute_mag_band: Band used to normalize to absolute magnitude. - Defaults to None. - :param sn_absolute_zpsys: Zero point system, either AB or Vega, with None defaulting to AB. - Defaults to None. + :param sky_area: Sky area (solid angle) over which Lens population is sampled. + :type sky_area: `~astropy.units.Quantity` :param los_config: Configuration for line of sight distribution. Defaults to None. - :param sn_modeldir: sn_modeldir is the path to the directory containing files needed to initialize - the sncosmo.model class. For example, sn_modeldir = - 'C:/Users/username/Documents/SALT3.NIR_WAVEEXT'. These data can be downloaded - from https://github.com/LSST-strong-lensing/data_public. For more detail, - please look at the documentation of RandomizedSupernovae class. Defaults to None. """ # TODO: ADD EXCEPTION FOR DEFLECTOR AND SOURCE POP FILTER MISMATCH From d69b6db7463db6245d352d7fd7f44b557a379dcd Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 14 Nov 2024 15:14:14 -0500 Subject: [PATCH 33/33] adjusted test functions of False Positive class --- slsim/FalsePositives/false_positive_pop.py | 17 ++------------ .../test_false_positive.py | 22 +++++++++---------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/slsim/FalsePositives/false_positive_pop.py b/slsim/FalsePositives/false_positive_pop.py index 94603497f..390f362ed 100644 --- a/slsim/FalsePositives/false_positive_pop.py +++ b/slsim/FalsePositives/false_positive_pop.py @@ -1,7 +1,5 @@ from slsim.FalsePositives.false_positive import FalsePositive from slsim.ParamDistributions.los_config import LOSConfig -from slsim.Sources.source import Source -from slsim.Deflectors.deflector import Deflector from slsim.lens_pop import draw_test_area import random @@ -55,11 +53,7 @@ def draw_deflector(self): :return: a deflector instance and deflector redshift with tolerance added. """ - lens = self._lens_galaxies.draw_deflector() - deflector = Deflector( - deflector_type=self._lens_galaxies.deflector_profile, - deflector_dict=lens, - ) + deflector = self._lens_galaxies.draw_deflector() z_max = deflector.redshift + 0.002 # Adding tolerance to redshift return deflector, z_max @@ -77,14 +71,7 @@ def draw_sources(self, z_max): # If no source is available, return None if source is None: return None - source_list.append( - Source( - source_dict=source, - cosmo=self.cosmo, - source_type=self._sources.source_type, - light_profile=self._sources.light_profile, - ) - ) + source_list.append(source) if source_number==1: sources = source_list[0] else: diff --git a/tests/test_FalsePositives/test_false_positive.py b/tests/test_FalsePositives/test_false_positive.py index 7db789970..8faf7072a 100644 --- a/tests/test_FalsePositives/test_false_positive.py +++ b/tests/test_FalsePositives/test_false_positive.py @@ -42,28 +42,28 @@ def test_false_positive(): single_deflector = lens_galaxies.draw_deflector() single_source1 = source_galaxies.draw_source() single_source2 = source_galaxies.draw_source() - lens = Deflector(deflector_type="EPL", deflector_dict=single_deflector) + lens = single_deflector source = Source( - source_dict=single_source1, + source_dict=single_source1.source_dict, cosmo=cosmo, source_type="extended", light_profile="single_sersic", ) source2 = Source( - source_dict=single_source1, + source_dict=single_source1.source_dict, cosmo=cosmo, source_type="extended", light_profile="double_sersic", ) source_list = [ Source( - source_dict=single_source1, + source_dict=single_source1.source_dict, cosmo=cosmo, source_type="extended", light_profile="single_sersic", ), Source( - source_dict=single_source2, + source_dict=single_source2.source_dict, cosmo=cosmo, source_type="extended", light_profile="single_sersic", @@ -121,26 +121,26 @@ def test_false_positive(): == 3 ) assert len(false_positive_instance_2.deflector_position) == 2 - assert false_positive_instance_2.deflector_redshift == single_deflector["z"] - assert false_positive_instance_1.source_redshift_list[0] == single_source1["z"] + assert false_positive_instance_2.deflector_redshift == single_deflector.redshift + assert false_positive_instance_1.source_redshift_list[0] == single_source1.redshift assert np.all(false_positive_instance_2.source_redshift_list) == np.all( - np.array([single_source1["z"], single_source2["z"]]) + np.array([single_source1.redshift, single_source2.redshift]) ) assert false_positive_instance_1.external_convergence < 0.1 assert false_positive_instance_1.external_shear < 0.2 assert false_positive_instance_1.einstein_radius[0] < 2.5 assert ( false_positive_instance_1.deflector_magnitude(band="i") - == single_deflector["mag_i"] + == single_deflector.magnitude(band="i") ) assert ( false_positive_instance_1.extended_source_magnitude(band="i") - == single_source1["mag_i"] + == single_source1.source_dict["mag_i"] ) assert len(false_positive_instance_1.deflector_ellipticity()) == 4 assert ( false_positive_instance_1.deflector_stellar_mass() - == single_deflector["stellar_mass"] + == single_deflector.stellar_mass ) assert ( set(