Skip to content

Commit

Permalink
Merge pull request #273 from nkhadka21/false_positives
Browse files Browse the repository at this point in the history
False positive routine
  • Loading branch information
nkhadka21 authored Nov 14, 2024
2 parents 5cc87c5 + d69b6db commit d5b01a4
Show file tree
Hide file tree
Showing 22 changed files with 623 additions and 167 deletions.
5 changes: 4 additions & 1 deletion slsim/Deflectors/all_lens_galaxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down
5 changes: 4 additions & 1 deletion slsim/Deflectors/cluster_deflectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
"""
Expand Down
8 changes: 5 additions & 3 deletions slsim/Deflectors/compound_lens_halos_galaxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
5 changes: 4 additions & 1 deletion slsim/Deflectors/elliptical_lens_galaxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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(
Expand Down
76 changes: 76 additions & 0 deletions slsim/FalsePositives/false_positive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import numpy as np
from slsim.lens import Lens

class FalsePositive(Lens):
"""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,
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
"""
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,
)

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
112 changes: 112 additions & 0 deletions slsim/FalsePositives/false_positive_pop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from slsim.FalsePositives.false_positive import FalsePositive
from slsim.ParamDistributions.los_config import LOSConfig
from slsim.lens_pop import draw_test_area
import random


class FalsePositivePop(object):
"""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."""

def __init__(
self,
elliptical_galaxy_population,
blue_galaxy_population,
cosmo=None,
los_config=None,
source_number_choice=[1, 2, 3],
weights_for_source_number=None,
test_area_factor=1
):
"""
Args:
:param elliptical_galaxy_population: Deflector population as an deflectors class
instance.
: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.
: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.
: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
self._lens_galaxies = elliptical_galaxy_population
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()

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.
"""
deflector = self._lens_galaxies.draw_deflector()
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)
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.
"""
false_positive_population = []

for _ in range(number):
successful = False
while not successful:
# Step 1: 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=deflector.velocity_dispersion(cosmo=self.cosmo)
test_area = self._test_area_factor * draw_test_area(
v_sigma=vd)
false_positive = FalsePositive(
deflector_class=deflector,
source_class=source,
cosmo=self.cosmo,
test_area=test_area,
)
false_positive_population.append(false_positive)
successful = True
return false_positive_population[0] if number==1 else false_positive_population
38 changes: 32 additions & 6 deletions slsim/Sources/galaxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -120,14 +121,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:
Expand Down Expand Up @@ -211,7 +222,22 @@ def draw_source(self):
"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):
Expand Down
23 changes: 22 additions & 1 deletion slsim/Sources/point_plus_extended_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
):
"""
Expand Down Expand Up @@ -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(
Expand All @@ -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"
Loading

0 comments on commit d5b01a4

Please sign in to comment.