From fdd04554d061e7e95e87078a8852005b5a1a23fb Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 18 Jun 2024 18:27:02 -0400 Subject: [PATCH 01/19] added interpolated image lightcurves to point_source_magnitude_with_micro_lensing() function --- slsim/lens.py | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 6d5c9b78d..952c80b6f 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -11,6 +11,8 @@ from slsim.ParamDistributions.gaussian_mixture_model import GaussianMixtureModel from lenstronomy.Util import util, data_util from slsim.lensed_system_base import LensedSystemBase +from slsim.Sources.SourceVariability.light_curve_interpolation import \ + LightCurveInterpolation import warnings @@ -422,7 +424,32 @@ def image_observer_times(self, t_obs): return observer_times - def point_source_magnitude(self, band, lensed=False, time=None, molet=False): + def point_source_magnitude(self, band, lensed=False, time=None, + micro_lensing=False): + """Point source magnitude, either unlensed (single value) or lensed (array) with + macro- and micro model magnifications. + :param band: imaging band + :type band: string + :param lensed: if True, returns the lensed magnified magnitude + :type lensed: bool + :param time: time is an image observation time in units of days. If None, + provides magnitude without variability. + :param micro_lensing: if using micro-lensing code to produce the lensed + magnification + :type micro_lensing: bool + :return: point source magnitude + """ + if micro_lensing is True: + if lensed is False: + raise ValueError("The input variable lensed cannot be False while the" + "the input variable micro_lensing is True.") + else: + return self.point_source_magnitude_with_micro_lensing(band=band, + time=time) + else: + return self._point_source_magnitude(self, band, lensed=False, time=None) + + def _point_source_magnitude(self, band, lensed=False, time=None): """Point source magnitude, either unlensed (single value) or lensed (array) with macro-model magnifications. @@ -434,14 +461,10 @@ def point_source_magnitude(self, band, lensed=False, time=None, molet=False): :type lensed: bool :param time: time is an image observation time in units of days. If None, provides magnitude without variability. - :param molet: if using MOLET to produce the lensed magnification - :type molet: bool :return: point source magnitude """ # TODO: might have to change conventions between extended and point source if lensed: - if molet: - return self.point_source_magnitude_molet(band=band, time=time) magnif = self.point_source_magnification() magnif_log = 2.5 * np.log10(abs(magnif)) if time is not None: @@ -463,7 +486,7 @@ def point_source_magnitude(self, band, lensed=False, time=None, molet=False): return np.array(magnified_mag_list) return self.source.point_source_magnitude(band) - def point_source_magnitude_molet(self, band, time, **kwargs_molet): + def point_source_magnitude_with_micro_lensing(self, band, time, **kwargs_molet): """Return image magnitudes at a given observer time. :param band: imaging band @@ -502,6 +525,21 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # TODO: in what format should be the 2d source profile be stored (as it is time- and wavelength dependent) # TODO: do we create full light curves (and save it in cache) or call it each time + + magnitude_without_microlensing = self._point_source_magnitude(band=band, + lensed=True, time=self.source.lightcurve_time) + #list of interpolated lightcurves. 1st lightcurve corresponds to the first + # ariving image, 2nd lightcurve corresponds to the second ariving image and + # so on. + interpolated_lightcurves = [] + for i in range(len(magnitude_without_microlensing)): + light_curve_image = { + "MJD": self.source.lightcurve_time, + f"ps_mag_image{i}": magnitude_without_microlensing[i] + } + # Create the interpolated lightcurve and add it to the list + interpolated_lightcurves.append( + LightCurveInterpolation(light_curve_image).interpolation) return 0 def extended_source_magnitude(self, band, lensed=False): From 58e87dc625ff5546d802bf23ca8f093d38fae347 Mon Sep 17 00:00:00 2001 From: narayan Date: Tue, 18 Jun 2024 18:28:27 -0400 Subject: [PATCH 02/19] made lightcurve_time a self variable in source class. --- slsim/Sources/source.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slsim/Sources/source.py b/slsim/Sources/source.py index cccdd9f5a..aa1c46248 100644 --- a/slsim/Sources/source.py +++ b/slsim/Sources/source.py @@ -89,15 +89,15 @@ def __init__( ]: provided_band = element name = "ps_mag_" + element - times = lightcurve_time + self.lightcurve_time = lightcurve_time magnitudes = lightcurve_class.get_apparent_magnitude( - time=times, band=provided_band, zpsys=sn_absolute_zpsys + time=self.lightcurve_time, band=provided_band, zpsys=sn_absolute_zpsys ) new_column = Column([float(min(magnitudes))], name=name) self._source_dict = Table(self.source_dict) self._source_dict.add_column(new_column) self.source_dict = self._source_dict[0] - self.kwargs_variab_extracted["MJD"] = times + self.kwargs_variab_extracted["MJD"] = self.lightcurve_time self.kwargs_variab_extracted[name] = magnitudes else: # With this condition we extract values for kwargs_variability from the From 42c99e9b411a0c7841d4c16e632e2d5368e323d1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 22:32:05 +0000 Subject: [PATCH 03/19] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- slsim/Sources/source.py | 4 +++- slsim/lens.py | 44 ++++++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/slsim/Sources/source.py b/slsim/Sources/source.py index aa1c46248..817d96ee9 100644 --- a/slsim/Sources/source.py +++ b/slsim/Sources/source.py @@ -91,7 +91,9 @@ def __init__( name = "ps_mag_" + element self.lightcurve_time = lightcurve_time magnitudes = lightcurve_class.get_apparent_magnitude( - time=self.lightcurve_time, band=provided_band, zpsys=sn_absolute_zpsys + time=self.lightcurve_time, + band=provided_band, + zpsys=sn_absolute_zpsys, ) new_column = Column([float(min(magnitudes))], name=name) self._source_dict = Table(self.source_dict) diff --git a/slsim/lens.py b/slsim/lens.py index 952c80b6f..9302fdf4d 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -11,8 +11,9 @@ from slsim.ParamDistributions.gaussian_mixture_model import GaussianMixtureModel from lenstronomy.Util import util, data_util from slsim.lensed_system_base import LensedSystemBase -from slsim.Sources.SourceVariability.light_curve_interpolation import \ - LightCurveInterpolation +from slsim.Sources.SourceVariability.light_curve_interpolation import ( + LightCurveInterpolation, +) import warnings @@ -424,31 +425,36 @@ def image_observer_times(self, t_obs): return observer_times - def point_source_magnitude(self, band, lensed=False, time=None, - micro_lensing=False): + def point_source_magnitude( + self, band, lensed=False, time=None, micro_lensing=False + ): """Point source magnitude, either unlensed (single value) or lensed (array) with macro- and micro model magnifications. + :param band: imaging band :type band: string :param lensed: if True, returns the lensed magnified magnitude :type lensed: bool :param time: time is an image observation time in units of days. If None, provides magnitude without variability. - :param micro_lensing: if using micro-lensing code to produce the lensed - magnification + :param micro_lensing: if using micro-lensing code to produce the lensed + magnification :type micro_lensing: bool :return: point source magnitude """ if micro_lensing is True: if lensed is False: - raise ValueError("The input variable lensed cannot be False while the" - "the input variable micro_lensing is True.") + raise ValueError( + "The input variable lensed cannot be False while the" + "the input variable micro_lensing is True." + ) else: - return self.point_source_magnitude_with_micro_lensing(band=band, - time=time) + return self.point_source_magnitude_with_micro_lensing( + band=band, time=time + ) else: return self._point_source_magnitude(self, band, lensed=False, time=None) - + def _point_source_magnitude(self, band, lensed=False, time=None): """Point source magnitude, either unlensed (single value) or lensed (array) with macro-model magnifications. @@ -525,21 +531,23 @@ def point_source_magnitude_with_micro_lensing(self, band, time, **kwargs_molet): # TODO: in what format should be the 2d source profile be stored (as it is time- and wavelength dependent) # TODO: do we create full light curves (and save it in cache) or call it each time - - magnitude_without_microlensing = self._point_source_magnitude(band=band, - lensed=True, time=self.source.lightcurve_time) - #list of interpolated lightcurves. 1st lightcurve corresponds to the first - # ariving image, 2nd lightcurve corresponds to the second ariving image and + + magnitude_without_microlensing = self._point_source_magnitude( + band=band, lensed=True, time=self.source.lightcurve_time + ) + # list of interpolated lightcurves. 1st lightcurve corresponds to the first + # ariving image, 2nd lightcurve corresponds to the second ariving image and # so on. interpolated_lightcurves = [] for i in range(len(magnitude_without_microlensing)): light_curve_image = { "MJD": self.source.lightcurve_time, - f"ps_mag_image{i}": magnitude_without_microlensing[i] + f"ps_mag_image{i}": magnitude_without_microlensing[i], } # Create the interpolated lightcurve and add it to the list interpolated_lightcurves.append( - LightCurveInterpolation(light_curve_image).interpolation) + LightCurveInterpolation(light_curve_image).interpolation + ) return 0 def extended_source_magnitude(self, band, lensed=False): From de925e8b60757f39a87ca92ca6e8a72a0ca4ee40 Mon Sep 17 00:00:00 2001 From: narayan Date: Wed, 19 Jun 2024 14:05:08 -0400 Subject: [PATCH 04/19] minor change. --- slsim/lens.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 952c80b6f..a574a0fc1 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -447,7 +447,7 @@ def point_source_magnitude(self, band, lensed=False, time=None, return self.point_source_magnitude_with_micro_lensing(band=band, time=time) else: - return self._point_source_magnitude(self, band, lensed=False, time=None) + return self._point_source_magnitude(self, band, lensed=lensed, time=time) def _point_source_magnitude(self, band, lensed=False, time=None): """Point source magnitude, either unlensed (single value) or lensed (array) with @@ -484,7 +484,7 @@ def _point_source_magnitude(self, band, lensed=False, time=None): for i in range(len(magnif_log)): magnified_mag_list.append(source_mag_unlensed - magnif_log[i]) return np.array(magnified_mag_list) - return self.source.point_source_magnitude(band) + return self.source.point_source_magnitude(band, image_observation_times=time) def point_source_magnitude_with_micro_lensing(self, band, time, **kwargs_molet): """Return image magnitudes at a given observer time. @@ -526,8 +526,8 @@ def point_source_magnitude_with_micro_lensing(self, band, time, **kwargs_molet): # TODO: in what format should be the 2d source profile be stored (as it is time- and wavelength dependent) # TODO: do we create full light curves (and save it in cache) or call it each time - magnitude_without_microlensing = self._point_source_magnitude(band=band, - lensed=True, time=self.source.lightcurve_time) + intrinsic_lightcurve = self._point_source_magnitude(band=band, + lensed=False, time=self.source.lightcurve_time) #list of interpolated lightcurves. 1st lightcurve corresponds to the first # ariving image, 2nd lightcurve corresponds to the second ariving image and # so on. From 856017fdd01af16aa2b2062af9970510aac389d0 Mon Sep 17 00:00:00 2001 From: narayan Date: Wed, 19 Jun 2024 15:13:28 -0400 Subject: [PATCH 05/19] minor change. --- slsim/lens.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index a574a0fc1..f904cd25c 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -425,7 +425,7 @@ def image_observer_times(self, t_obs): return observer_times def point_source_magnitude(self, band, lensed=False, time=None, - micro_lensing=False): + molet=False): """Point source magnitude, either unlensed (single value) or lensed (array) with macro- and micro model magnifications. :param band: imaging band @@ -434,17 +434,17 @@ def point_source_magnitude(self, band, lensed=False, time=None, :type lensed: bool :param time: time is an image observation time in units of days. If None, provides magnitude without variability. - :param micro_lensing: if using micro-lensing code to produce the lensed + :param molet: if using molet to produce the lensed magnification - :type micro_lensing: bool + :type molet: bool :return: point source magnitude """ - if micro_lensing is True: + if molet is True: if lensed is False: raise ValueError("The input variable lensed cannot be False while the" "the input variable micro_lensing is True.") else: - return self.point_source_magnitude_with_micro_lensing(band=band, + return self.point_source_magnitude_molet(band=band, time=time) else: return self._point_source_magnitude(self, band, lensed=lensed, time=time) @@ -486,7 +486,7 @@ def _point_source_magnitude(self, band, lensed=False, time=None): return np.array(magnified_mag_list) return self.source.point_source_magnitude(band, image_observation_times=time) - def point_source_magnitude_with_micro_lensing(self, band, time, **kwargs_molet): + def point_source_magnitude_molet(self, band, time, **kwargs_molet): """Return image magnitudes at a given observer time. :param band: imaging band @@ -526,6 +526,7 @@ def point_source_magnitude_with_micro_lensing(self, band, time, **kwargs_molet): # TODO: in what format should be the 2d source profile be stored (as it is time- and wavelength dependent) # TODO: do we create full light curves (and save it in cache) or call it each time + #we can use to get intrinsic brightness of a source at image observation time. intrinsic_lightcurve = self._point_source_magnitude(band=band, lensed=False, time=self.source.lightcurve_time) #list of interpolated lightcurves. 1st lightcurve corresponds to the first From fef2635edd2bf0a31a5bb44d4c7825b4f00cc0e8 Mon Sep 17 00:00:00 2001 From: narayan Date: Wed, 19 Jun 2024 15:21:29 -0400 Subject: [PATCH 06/19] minor change --- slsim/lens.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index f904cd25c..813c5a1ac 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -526,21 +526,12 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # TODO: in what format should be the 2d source profile be stored (as it is time- and wavelength dependent) # TODO: do we create full light curves (and save it in cache) or call it each time - #we can use to get intrinsic brightness of a source at image observation time. - intrinsic_lightcurve = self._point_source_magnitude(band=band, - lensed=False, time=self.source.lightcurve_time) - #list of interpolated lightcurves. 1st lightcurve corresponds to the first - # ariving image, 2nd lightcurve corresponds to the second ariving image and - # so on. - interpolated_lightcurves = [] - for i in range(len(magnitude_without_microlensing)): - light_curve_image = { - "MJD": self.source.lightcurve_time, - f"ps_mag_image{i}": magnitude_without_microlensing[i] - } - # Create the interpolated lightcurve and add it to the list - interpolated_lightcurves.append( - LightCurveInterpolation(light_curve_image).interpolation) + #we can use this to get intrinsic brightness of a source at image observation + # time. + source_profile = {"time":self.source.lightcurve_time, + "magnitude":self._point_source_magnitude(band=band, + lensed=False, time=self.source.lightcurve_time)} + #using source profile, kappa, gamma, kappa_star, image_observed_time produce return 0 def extended_source_magnitude(self, band, lensed=False): From e11abfc94c76b61ce43e9bb06e64968e23585f8a Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 20 Jun 2024 18:21:27 -0400 Subject: [PATCH 07/19] added some magnitude structure for molet. --- slsim/Util/param_util.py | 37 +++++++++++++++++++++++++++++++++++++ slsim/lens.py | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/slsim/Util/param_util.py b/slsim/Util/param_util.py index 58439d23e..627557497 100644 --- a/slsim/Util/param_util.py +++ b/slsim/Util/param_util.py @@ -1,6 +1,7 @@ import numpy as np from scipy.signal import convolve2d, fftconvolve import scipy +from scipy.interpolate import interp1d def epsilon2e(epsilon): @@ -216,3 +217,39 @@ def eccentricity(q): :return: eccentricity """ return (1 - q) / (1 + q) + + +def check_quantity(quantity): + """This function checks whether a quantity is a interpolated function or a + dictionary. If the quantity is an interpolated function, it returns the quantity + and if it is a dictionary, it creates a interpolated function between two + different element of the dictionary. + + :param quantity: quantity that needs to be checked. + :return: interpolated function. If given quantity is a dictionary, first key is the + x-axis of the interpolation function and second key is the y-axis of the + interpolation function. + """ + if callable(quantity): + interpolation_function = quantity + elif isinstance(quantity, dict): + keys = list(quantity.keys()) + term1 = quantity[keys[0]] + term2 = quantity[keys[1]] + if isinstance(term1, (list, np.ndarray)) and isinstance(term2, + (list, np.ndarray)): + if len(term1) == len(term2): + interpolation_function=interp1d( + term1, + term2, + kind="linear", + fill_value=(0, 0), + bounds_error=False, + ) + else: + raise ValueError(f"Length of {keys[0]} and {keys[1]} must be" + " the same.") + else: + raise ValueError("Input must be a callable or a dictionary with at list 2" + " specified keys") + return interpolation_function diff --git a/slsim/lens.py b/slsim/lens.py index 813c5a1ac..1e2d7f3a5 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -13,6 +13,7 @@ from slsim.lensed_system_base import LensedSystemBase from slsim.Sources.SourceVariability.light_curve_interpolation import \ LightCurveInterpolation +from slsim.Util.param_util import check_quantity import warnings @@ -527,12 +528,35 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # TODO: do we create full light curves (and save it in cache) or call it each time #we can use this to get intrinsic brightness of a source at image observation - # time. - source_profile = {"time":self.source.lightcurve_time, - "magnitude":self._point_source_magnitude(band=band, - lensed=False, time=self.source.lightcurve_time)} - #using source profile, kappa, gamma, kappa_star, image_observed_time produce - return 0 + # time. Here, we are storing source profile as dictionary of observation time + # and magnitude but need to decide what format molet needs. I checked with molet + # and it says format should be in the form given below. + source_profile = [{"time":list(self.source.lightcurve_time), + "signal":list(self._point_source_magnitude(band=band, + lensed=False, time=self.source.lightcurve_time))}] + #using source profile, kappa, gamma, kappa_star, image_observed_time molet + # should return lightcurve of each images. The lightcurve can be a interpolated + # function or a dictionary of observation time and magnitudes in specified band + # as given below. + #This molet_output is temporary. Once we call molet, this will be actual molet + # output. + molet_output = [{"time": list(self.source.lightcurve_time), + "magnitude": np.lnspace( + 23, 34, len(self.source.lightcurve_time))}, + {"time": list(self.source.lightcurve_time), + "magnitude": np.lnspace( + 24, 36, len(self.source.lightcurve_time))}] + # molet_output can be molet_output = [interp_lightcurve_image1, + # interp_lightcurve_image2] + + #calls interpolated functions for each images and saves magnitudes at given + # observation time. + variable_magnitudes = [] + for i in range(len(molet_output)): + variable_magnitudes.append(check_quantity(molet_output[i])( + image_observed_times[i])) + return np.array(variable_magnitudes) + def extended_source_magnitude(self, band, lensed=False): """Unlensed apparent magnitude of the extended source for a given band (assumes From 43c9cf8e9945525486c1051293668a9d3afe925c Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 20 Jun 2024 18:23:26 -0400 Subject: [PATCH 08/19] renamed a function in Util. --- slsim/Util/param_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsim/Util/param_util.py b/slsim/Util/param_util.py index 627557497..eb7095eb8 100644 --- a/slsim/Util/param_util.py +++ b/slsim/Util/param_util.py @@ -219,7 +219,7 @@ def eccentricity(q): return (1 - q) / (1 + q) -def check_quantity(quantity): +def function_or_dictionary(quantity): """This function checks whether a quantity is a interpolated function or a dictionary. If the quantity is an interpolated function, it returns the quantity and if it is a dictionary, it creates a interpolated function between two From 5f3c3510883fef3db4d77e6b93250082bc475ffe Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 20 Jun 2024 18:24:14 -0400 Subject: [PATCH 09/19] minor change. --- slsim/lens.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 1e2d7f3a5..b45052ae3 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -13,7 +13,7 @@ from slsim.lensed_system_base import LensedSystemBase from slsim.Sources.SourceVariability.light_curve_interpolation import \ LightCurveInterpolation -from slsim.Util.param_util import check_quantity +from slsim.Util.param_util import function_or_dictionary import warnings @@ -553,7 +553,7 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # observation time. variable_magnitudes = [] for i in range(len(molet_output)): - variable_magnitudes.append(check_quantity(molet_output[i])( + variable_magnitudes.append(function_or_dictionary(molet_output[i])( image_observed_times[i])) return np.array(variable_magnitudes) From e7a54371b7ca366d6ade2e739690e6c40cffb4d7 Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 20 Jun 2024 18:34:14 -0400 Subject: [PATCH 10/19] added test function for a util function. --- slsim/lens.py | 2 +- tests/test_param_util.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/slsim/lens.py b/slsim/lens.py index b45052ae3..220601984 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -443,7 +443,7 @@ def point_source_magnitude(self, band, lensed=False, time=None, if molet is True: if lensed is False: raise ValueError("The input variable lensed cannot be False while the" - "the input variable micro_lensing is True.") + "the input variable molet is True.") else: return self.point_source_magnitude_molet(band=band, time=time) diff --git a/tests/test_param_util.py b/tests/test_param_util.py index fabe44300..3cfef644f 100644 --- a/tests/test_param_util.py +++ b/tests/test_param_util.py @@ -1,6 +1,7 @@ import numpy as np import os from numpy import testing as npt +from scipy.interpolate import interp1d from slsim.Util.param_util import ( epsilon2e, e2epsilon, @@ -13,6 +14,7 @@ transformmatrix_to_pixelscale, magnitude_to_amplitude, amplitude_to_magnitude, + function_or_dictionary ) from slsim.Sources.SourceVariability.variability import Variability import pytest @@ -161,6 +163,19 @@ def test_magnitude_to_amplitude(): assert low_mag == new_low_mag assert high_mag == new_high_mag +def test_function_or_dictionary(): + quantity = {"time": np.linspace(-20, 50, 100), + "magnitude": np.linspace( + 23, 34, 100)} + x=np.linspace(10, 15, 100) + y=np.linspace(30, 40, 100) + interpolation_function = interp1d(x, y) + result = function_or_dictionary(quantity) + result2 = function_or_dictionary(interpolation_function) + assert result(-20) == 23 + assert result(50) == 34 + assert result2(12) == interpolation_function(12) + if __name__ == "__main__": pytest.main() From 3f629ceaa35c94898e82d7b75814a20389efc87d Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 20 Jun 2024 18:40:50 -0400 Subject: [PATCH 11/19] minor change. --- slsim/lens.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 220601984..65372b094 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -445,10 +445,9 @@ def point_source_magnitude(self, band, lensed=False, time=None, raise ValueError("The input variable lensed cannot be False while the" "the input variable molet is True.") else: - return self.point_source_magnitude_molet(band=band, - time=time) + return self.point_source_magnitude_molet(band=band, time=time) else: - return self._point_source_magnitude(self, band, lensed=lensed, time=time) + return self._point_source_magnitude(band=band, lensed=lensed, time=time) def _point_source_magnitude(self, band, lensed=False, time=None): """Point source magnitude, either unlensed (single value) or lensed (array) with From ef4b1bcf9e3809fae019cc6158d867f78938762d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 20 Jun 2024 22:43:50 +0000 Subject: [PATCH 12/19] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- slsim/Util/param_util.py | 35 ++++++++++--------- slsim/lens.py | 74 +++++++++++++++++++++++----------------- tests/test_param_util.py | 14 ++++---- 3 files changed, 70 insertions(+), 53 deletions(-) diff --git a/slsim/Util/param_util.py b/slsim/Util/param_util.py index eb7095eb8..9f956845d 100644 --- a/slsim/Util/param_util.py +++ b/slsim/Util/param_util.py @@ -220,15 +220,15 @@ def eccentricity(q): def function_or_dictionary(quantity): - """This function checks whether a quantity is a interpolated function or a - dictionary. If the quantity is an interpolated function, it returns the quantity - and if it is a dictionary, it creates a interpolated function between two - different element of the dictionary. - - :param quantity: quantity that needs to be checked. - :return: interpolated function. If given quantity is a dictionary, first key is the - x-axis of the interpolation function and second key is the y-axis of the - interpolation function. + """This function checks whether a quantity is a interpolated function or a + dictionary. If the quantity is an interpolated function, it returns the quantity and + if it is a dictionary, it creates a interpolated function between two different + element of the dictionary. + + :param quantity: quantity that needs to be checked. + :return: interpolated function. If given quantity is a dictionary, first key is the + x-axis of the interpolation function and second key is the y-axis of the + interpolation function. """ if callable(quantity): interpolation_function = quantity @@ -236,10 +236,11 @@ def function_or_dictionary(quantity): keys = list(quantity.keys()) term1 = quantity[keys[0]] term2 = quantity[keys[1]] - if isinstance(term1, (list, np.ndarray)) and isinstance(term2, - (list, np.ndarray)): + if isinstance(term1, (list, np.ndarray)) and isinstance( + term2, (list, np.ndarray) + ): if len(term1) == len(term2): - interpolation_function=interp1d( + interpolation_function = interp1d( term1, term2, kind="linear", @@ -247,9 +248,11 @@ def function_or_dictionary(quantity): bounds_error=False, ) else: - raise ValueError(f"Length of {keys[0]} and {keys[1]} must be" - " the same.") + raise ValueError( + f"Length of {keys[0]} and {keys[1]} must be" " the same." + ) else: - raise ValueError("Input must be a callable or a dictionary with at list 2" - " specified keys") + raise ValueError( + "Input must be a callable or a dictionary with at list 2" " specified keys" + ) return interpolation_function diff --git a/slsim/lens.py b/slsim/lens.py index 28f06fc46..f33b6f9f8 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -11,8 +11,9 @@ from slsim.ParamDistributions.gaussian_mixture_model import GaussianMixtureModel from lenstronomy.Util import util, data_util from slsim.lensed_system_base import LensedSystemBase -from slsim.Sources.SourceVariability.light_curve_interpolation import \ - LightCurveInterpolation +from slsim.Sources.SourceVariability.light_curve_interpolation import ( + LightCurveInterpolation, +) from slsim.Util.param_util import function_or_dictionary import warnings @@ -425,8 +426,7 @@ def image_observer_times(self, t_obs): return observer_times - def point_source_magnitude(self, band, lensed=False, time=None, - molet=False): + def point_source_magnitude(self, band, lensed=False, time=None, molet=False): """Point source magnitude, either unlensed (single value) or lensed (array) with macro- and micro model magnifications. @@ -436,20 +436,21 @@ def point_source_magnitude(self, band, lensed=False, time=None, :type lensed: bool :param time: time is an image observation time in units of days. If None, provides magnitude without variability. - :param molet: if using molet to produce the lensed - magnification + :param molet: if using molet to produce the lensed magnification :type molet: bool :return: point source magnitude """ if molet is True: if lensed is False: - raise ValueError("The input variable lensed cannot be False while the" - "the input variable molet is True.") + raise ValueError( + "The input variable lensed cannot be False while the" + "the input variable molet is True." + ) else: return self.point_source_magnitude_molet(band=band, time=time) else: return self._point_source_magnitude(band=band, lensed=lensed, time=time) - + def _point_source_magnitude(self, band, lensed=False, time=None): """Point source magnitude, either unlensed (single value) or lensed (array) with macro-model magnifications. @@ -526,37 +527,48 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # TODO: in what format should be the 2d source profile be stored (as it is time- and wavelength dependent) # TODO: do we create full light curves (and save it in cache) or call it each time - - #we can use this to get intrinsic brightness of a source at image observation - # time. Here, we are storing source profile as dictionary of observation time + + # we can use this to get intrinsic brightness of a source at image observation + # time. Here, we are storing source profile as dictionary of observation time # and magnitude but need to decide what format molet needs. I checked with molet # and it says format should be in the form given below. - source_profile = [{"time":list(self.source.lightcurve_time), - "signal":list(self._point_source_magnitude(band=band, - lensed=False, time=self.source.lightcurve_time))}] - #using source profile, kappa, gamma, kappa_star, image_observed_time molet - # should return lightcurve of each images. The lightcurve can be a interpolated - # function or a dictionary of observation time and magnitudes in specified band + source_profile = [ + { + "time": list(self.source.lightcurve_time), + "signal": list( + self._point_source_magnitude( + band=band, lensed=False, time=self.source.lightcurve_time + ) + ), + } + ] + # using source profile, kappa, gamma, kappa_star, image_observed_time molet + # should return lightcurve of each images. The lightcurve can be a interpolated + # function or a dictionary of observation time and magnitudes in specified band # as given below. - #This molet_output is temporary. Once we call molet, this will be actual molet + # This molet_output is temporary. Once we call molet, this will be actual molet # output. - molet_output = [{"time": list(self.source.lightcurve_time), - "magnitude": np.lnspace( - 23, 34, len(self.source.lightcurve_time))}, - {"time": list(self.source.lightcurve_time), - "magnitude": np.lnspace( - 24, 36, len(self.source.lightcurve_time))}] - # molet_output can be molet_output = [interp_lightcurve_image1, + molet_output = [ + { + "time": list(self.source.lightcurve_time), + "magnitude": np.lnspace(23, 34, len(self.source.lightcurve_time)), + }, + { + "time": list(self.source.lightcurve_time), + "magnitude": np.lnspace(24, 36, len(self.source.lightcurve_time)), + }, + ] + # molet_output can be molet_output = [interp_lightcurve_image1, # interp_lightcurve_image2] - - #calls interpolated functions for each images and saves magnitudes at given + + # calls interpolated functions for each images and saves magnitudes at given # observation time. variable_magnitudes = [] for i in range(len(molet_output)): - variable_magnitudes.append(function_or_dictionary(molet_output[i])( - image_observed_times[i])) + variable_magnitudes.append( + function_or_dictionary(molet_output[i])(image_observed_times[i]) + ) return np.array(variable_magnitudes) - def extended_source_magnitude(self, band, lensed=False): """Unlensed apparent magnitude of the extended source for a given band (assumes diff --git a/tests/test_param_util.py b/tests/test_param_util.py index 3cfef644f..aabe4ad46 100644 --- a/tests/test_param_util.py +++ b/tests/test_param_util.py @@ -14,7 +14,7 @@ transformmatrix_to_pixelscale, magnitude_to_amplitude, amplitude_to_magnitude, - function_or_dictionary + function_or_dictionary, ) from slsim.Sources.SourceVariability.variability import Variability import pytest @@ -163,12 +163,14 @@ def test_magnitude_to_amplitude(): assert low_mag == new_low_mag assert high_mag == new_high_mag + def test_function_or_dictionary(): - quantity = {"time": np.linspace(-20, 50, 100), - "magnitude": np.linspace( - 23, 34, 100)} - x=np.linspace(10, 15, 100) - y=np.linspace(30, 40, 100) + quantity = { + "time": np.linspace(-20, 50, 100), + "magnitude": np.linspace(23, 34, 100), + } + x = np.linspace(10, 15, 100) + y = np.linspace(30, 40, 100) interpolation_function = interp1d(x, y) result = function_or_dictionary(quantity) result2 = function_or_dictionary(interpolation_function) From c53e07e6bde82cf3e6d0b1465697e4aa79cb29da Mon Sep 17 00:00:00 2001 From: narayan Date: Thu, 20 Jun 2024 18:44:40 -0400 Subject: [PATCH 13/19] minor change. --- slsim/lens.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 28f06fc46..f3e9f9e97 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -11,8 +11,6 @@ from slsim.ParamDistributions.gaussian_mixture_model import GaussianMixtureModel from lenstronomy.Util import util, data_util from slsim.lensed_system_base import LensedSystemBase -from slsim.Sources.SourceVariability.light_curve_interpolation import \ - LightCurveInterpolation from slsim.Util.param_util import function_or_dictionary import warnings From a8e73d14e2612bd496d2f779a7e0950d78afcc8d Mon Sep 17 00:00:00 2001 From: narayan Date: Fri, 21 Jun 2024 12:03:44 -0400 Subject: [PATCH 14/19] updated test_requirements.txt --- test_requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_requirements.txt b/test_requirements.txt index 64cac1314..8f9ef3043 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1 +1,2 @@ -git+https://github.com/aymgal/coolest@main#egg=coolest \ No newline at end of file +# git+https://github.com/aymgal/coolest@main#egg=coolest +coolest==0.1.8 \ No newline at end of file From 40f483d43e842a18a05fbf7dfabb3c5bdc53aef1 Mon Sep 17 00:00:00 2001 From: narayan Date: Fri, 21 Jun 2024 14:36:09 -0400 Subject: [PATCH 15/19] minor change --- slsim/lens.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 3f130e011..f64b2e9c8 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -545,7 +545,7 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # as given below. # This molet_output is temporary. Once we call molet, this will be actual molet # output. - molet_output = [ + self.molet_output = [ { "time": list(self.source.lightcurve_time), "magnitude": np.lnspace(23, 34, len(self.source.lightcurve_time)), @@ -561,9 +561,11 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # calls interpolated functions for each images and saves magnitudes at given # observation time. variable_magnitudes = [] - for i in range(len(molet_output)): + # This is iteration through all images. Inside this, it checks whether + # molet_output is a interpolated function or a dictionary. + for i in range(len(self.molet_output)): variable_magnitudes.append( - function_or_dictionary(molet_output[i])(image_observed_times[i]) + function_or_dictionary(self.molet_output[i])(image_observed_times[i]) ) return np.array(variable_magnitudes) From 6d8c5346d252a0f8ae17f892a39c2ae1e5508ec2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 18:37:08 +0000 Subject: [PATCH 16/19] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- slsim/lens.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsim/lens.py b/slsim/lens.py index f64b2e9c8..3182e2b06 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -561,7 +561,7 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # calls interpolated functions for each images and saves magnitudes at given # observation time. variable_magnitudes = [] - # This is iteration through all images. Inside this, it checks whether + # This is iteration through all images. Inside this, it checks whether # molet_output is a interpolated function or a dictionary. for i in range(len(self.molet_output)): variable_magnitudes.append( From 31797e91e3c2758af7bb61439d93c8740e541c9f Mon Sep 17 00:00:00 2001 From: narayan Date: Mon, 24 Jun 2024 10:30:08 -0400 Subject: [PATCH 17/19] minor refactoring --- slsim/lens.py | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index f64b2e9c8..9de7631f8 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -494,6 +494,23 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): provides magnitude without variability. :return: point source magnitude (lensed (incl. micro-lensing)) """ + # Get image observed times + image_observed_times = self.image_observer_times(time) + if not hasattr(self, '_molet_output'): + self._molet_output = self._generate_molet_output(band, time, **kwargs_molet) + + # calls interpolated functions for each images and saves magnitudes at given + # observation time. + variable_magnitudes = [] + # This is the iteration through all images. Inside this, it checks whether + # self._molet_output is an interpolated function or a dictionary. + for i in range(len(self._molet_output)): + variable_magnitudes.append( + function_or_dictionary(self._molet_output[i])(image_observed_times[i]) + ) + return np.array(variable_magnitudes) + + def _generate_molet_output(self, band, time, **kwargs_molet): # coolest convention of lens model (or kappa, gamma, kappa_star) lens_model_list, kwargs_lens = self.deflector_mass_model_lenstronomy() lens_model = LensModel(lens_model_list=lens_model_list) @@ -514,16 +531,18 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # kappa: lensing convergence at image position # gamma: shear strength at image position # kappa_star: stellar convergence at image position - # image_observed_times: time of the source at the different images, not correcting for - # redshifts, but for time delays. The time is relative to the first arriving - # image. + # image_observed_times: time of the source at the different images, not + # correcting for redshifts, but for time delays. The time is relative to the + # first arriving image. # band: photometric band, potentially changing to transmission curve - # kwargs_molet: additional (optional) dictionary of settings required by molet that do not depend on - # the Lens() class + # kwargs_molet: additional (optional) dictionary of settings required by molet + # that do not depend on the Lens() class # =============== - # TODO: in what format should be the 2d source profile be stored (as it is time- and wavelength dependent) - # TODO: do we create full light curves (and save it in cache) or call it each time + # TODO: in what format should be the 2d source profile be stored (as it is + # time- and wavelength dependent) + # TODO: do we create full light curves (and save it in cache) or call it each + # time # we can use this to get intrinsic brightness of a source at image observation # time. Here, we are storing source profile as dictionary of observation time @@ -543,9 +562,9 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # should return lightcurve of each images. The lightcurve can be a interpolated # function or a dictionary of observation time and magnitudes in specified band # as given below. - # This molet_output is temporary. Once we call molet, this will be actual molet - # output. - self.molet_output = [ + # This molet_output is temporary. Once we call molet, this will be an actual + # molet output. + image_lightcurve_list = [ { "time": list(self.source.lightcurve_time), "magnitude": np.lnspace(23, 34, len(self.source.lightcurve_time)), @@ -558,16 +577,7 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): # molet_output can be molet_output = [interp_lightcurve_image1, # interp_lightcurve_image2] - # calls interpolated functions for each images and saves magnitudes at given - # observation time. - variable_magnitudes = [] - # This is iteration through all images. Inside this, it checks whether - # molet_output is a interpolated function or a dictionary. - for i in range(len(self.molet_output)): - variable_magnitudes.append( - function_or_dictionary(self.molet_output[i])(image_observed_times[i]) - ) - return np.array(variable_magnitudes) + return image_lightcurve_list def extended_source_magnitude(self, band, lensed=False): """Unlensed apparent magnitude of the extended source for a given band (assumes From 4547cb9eb71bc07ddc93fc92c8be5826dc9cb015 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:32:33 +0000 Subject: [PATCH 18/19] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- slsim/lens.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 9de7631f8..ed00136e7 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -496,20 +496,20 @@ def point_source_magnitude_molet(self, band, time, **kwargs_molet): """ # Get image observed times image_observed_times = self.image_observer_times(time) - if not hasattr(self, '_molet_output'): + if not hasattr(self, "_molet_output"): self._molet_output = self._generate_molet_output(band, time, **kwargs_molet) # calls interpolated functions for each images and saves magnitudes at given # observation time. variable_magnitudes = [] - # This is the iteration through all images. Inside this, it checks whether + # This is the iteration through all images. Inside this, it checks whether # self._molet_output is an interpolated function or a dictionary. for i in range(len(self._molet_output)): variable_magnitudes.append( function_or_dictionary(self._molet_output[i])(image_observed_times[i]) ) return np.array(variable_magnitudes) - + def _generate_molet_output(self, band, time, **kwargs_molet): # coolest convention of lens model (or kappa, gamma, kappa_star) lens_model_list, kwargs_lens = self.deflector_mass_model_lenstronomy() @@ -531,17 +531,17 @@ def _generate_molet_output(self, band, time, **kwargs_molet): # kappa: lensing convergence at image position # gamma: shear strength at image position # kappa_star: stellar convergence at image position - # image_observed_times: time of the source at the different images, not - # correcting for redshifts, but for time delays. The time is relative to the + # image_observed_times: time of the source at the different images, not + # correcting for redshifts, but for time delays. The time is relative to the # first arriving image. # band: photometric band, potentially changing to transmission curve - # kwargs_molet: additional (optional) dictionary of settings required by molet + # kwargs_molet: additional (optional) dictionary of settings required by molet # that do not depend on the Lens() class # =============== - # TODO: in what format should be the 2d source profile be stored (as it is + # TODO: in what format should be the 2d source profile be stored (as it is # time- and wavelength dependent) - # TODO: do we create full light curves (and save it in cache) or call it each + # TODO: do we create full light curves (and save it in cache) or call it each # time # we can use this to get intrinsic brightness of a source at image observation @@ -562,7 +562,7 @@ def _generate_molet_output(self, band, time, **kwargs_molet): # should return lightcurve of each images. The lightcurve can be a interpolated # function or a dictionary of observation time and magnitudes in specified band # as given below. - # This molet_output is temporary. Once we call molet, this will be an actual + # This molet_output is temporary. Once we call molet, this will be an actual # molet output. image_lightcurve_list = [ { From 506473d7850e487e0d3ac9b035808d9e77bbed55 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 19 Feb 2025 21:35:20 +0000 Subject: [PATCH 19/19] Autofix formatting from pre-commit.com hooks --- slsim/lens.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/slsim/lens.py b/slsim/lens.py index 6c635df99..a548bd6a9 100644 --- a/slsim/lens.py +++ b/slsim/lens.py @@ -575,8 +575,8 @@ def _image_observer_times(self, source, t_obs): return observer_times def point_source_magnitude(self, band, lensed=False, time=None, molet=False): - """Point source magnitude, either unlensed (single value) or lensed (array) with - macro-model magnifications. This function provided + """Point source magnitude, either unlensed (single value) or lensed + (array) with macro-model magnifications. This function provided magnitudes of all the sources. # TODO: time-variability with micro-lensing @@ -613,7 +613,6 @@ def _point_source_magnitude(self, band, source, lensed=False, time=None): :param time: time is a image observation time in units of days. If None, provides magnitude without variability. :return: point source magnitude of a single source - """ # TODO: might have to change conventions between extended and point source if lensed: @@ -638,14 +637,13 @@ def _point_source_magnitude(self, band, source, lensed=False, time=None): return np.array(magnified_mag_list) return source.point_source_magnitude(band) - def point_source_magnitude_micro_lensing(self, band, time, **kwargs_micro_lensing): """Return image magnitudes at a given observer time. :param band: imaging band :type band: string - :param time: time is an image observation time in units of days. If None, - provides magnitude without variability. + :param time: time is an image observation time in units of days. + If None, provides magnitude without variability. :return: point source magnitude (lensed (incl. micro-lensing)) """ # Get image observed times