Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Point source refactoring #338

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 30 additions & 0 deletions CITATION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Citation Guidelines
===================

|JOSS| |Birrer&Amara|

If you use lenstronomy for work or research presented in a publication (whether
directly, or as a dependency of another package) we recommend and encourage
the following acknowledgment:

This research made use of lenstronomy, a multi-purpose gravitational lens
modeling software package (Birrer et. al., 2021, Birrer & Amara, 2018).

where the citations are to our publication in the `Journal of Open Source
Software`_ and the `Original Publication`_. We also encourage citations within the main text wherever
appropriate. DOIs and BibTeX keys are available through the links above.

Please also cite `Birrer et al 2015 <http://adsabs.harvard.edu/abs/2015ApJ...813..102B>`_
when you make use of the lenstronomy work-flow or the Shapelet source reconstruction and make sure to cite also
the relevant work that was implemented in lenstronomy, as described in the release paper and the documentation.
Don't hesitate to reach out to the developers if you have questions!


.. _Journal of Open Source Software: https://joss.theoj.org/papers/10.21105/joss.03283
.. _Original Publication: https://ui.adsabs.harvard.edu/abs/2018PDU....22..189B/abstract

.. |JOSS| image:: https://joss.theoj.org/papers/10.21105/joss.03283/status.svg
:target: https://joss.theoj.org/papers/10.21105/joss.03283

.. |Birrer&Amara| image:: https://img.shields.io/badge/arXiv-1803.09746%20-yellowgreen.svg
:target: https://ui.adsabs.harvard.edu/abs/2018PDU....22..189B/abstract
16 changes: 12 additions & 4 deletions MAILINGLIST.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
============
Mailing list
============
==============================
Mailing list and Slack channel
==============================

You can join the **lenstronomy** mailing list by signing up on the
`google groups page <https://groups.google.com/forum/#!forum/lenstronomy>`_.

The email list is meant to provide a communication platform between users and developers. You can ask questions,
and suggest new features. New releases will be announced via this mailing list.

If you encounter errors or problems with **lenstronomy**, please let us know!
We also have a `Slack channel <https://lenstronomers.slack.com>`_ for the community.
Please send us an `email <lenstronomy-dev@googlegroups.com>`_ such that we can add you to the channel.

If you encounter errors or problems with **lenstronomy**, please let us know!
You can open an `issue <https://github.com/lenstronomy/lenstronomy/issues>`_,
make a post on the `Slack channel <https://lenstronomers.slack.com>`_ or
write an `email <lenstronomy-dev@googlegroups.com>`_ to the lenstronomy developers.

We are also encouraging you to reach out with feature requests, general or specific feedback and questions about use cases.
4 changes: 3 additions & 1 deletion lenstronomy/PointSource/Types/base_ps.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ def __init__(self, lens_model=None, fixed_magnification=False, additional_image=

:param lens_model: instance of the LensModel() class
:param fixed_magnification: bool. If True, magnification
ratio of point sources is fixed to the one given by the lens model
ratio of point sources is fixed to the one given by the lens model.
If True, amplitude parameters are passed as 'source_amp'.
If False, amplitudes are passed as in the image plane as 'image_amp'.
:param additional_image: bool. If True, search for additional images of the same source is conducted.
"""
self._lens_model = lens_model
Expand Down
8 changes: 4 additions & 4 deletions lenstronomy/PointSource/Types/lensed_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class LensedPositions(PSBase):
"""
class of a a lensed point source parameterized as the (multiple) observed image positions
Name within the PointSource module: 'LENSED_POSITION'
parameters: ra_image, dec_image, point_amp
If fixed_magnification=True, than 'source_amp' is a parameter instead of 'point_amp'
parameters: ra_image, dec_image, source_amp/source_amp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to image_amp/source_amp

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explicitly write "source_amp is the amplitude of the point source in the source plane. image_amp are the amplitudes of the point source images in the image plane. When fixed_magnification=True, use source_amp. Otherwise, use image_amp" (in source_position as well)

If fixed_magnification=True, than 'source_amp' is a parameter instead of 'image_amp'

"""
# def __init__(self, lens_model=None, fixed_magnification=False, additional_image=False):
Expand Down Expand Up @@ -82,7 +82,7 @@ def image_amplitude(self, kwargs_ps, kwargs_lens=None, x_pos=None, y_pos=None, m
mag = self._lens_model.magnification(ra_image, dec_image, kwargs_lens)
point_amp = kwargs_ps['source_amp'] * np.abs(mag)
else:
point_amp = kwargs_ps['point_amp']
point_amp = kwargs_ps['image_amp']
if x_pos is not None:
point_amp = _expand_to_array(point_amp, len(x_pos))
return np.array(point_amp)
Expand All @@ -103,6 +103,6 @@ def source_amplitude(self, kwargs_ps, kwargs_lens=None):
else:
ra_image, dec_image = kwargs_ps['ra_image'], kwargs_ps['dec_image']
mag = self._lens_model.magnification(ra_image, dec_image, kwargs_lens)
point_amp = kwargs_ps['point_amp']
point_amp = kwargs_ps['image_amp']
source_amp = np.mean(np.array(point_amp) / np.array(np.abs(mag)))
return np.array(source_amp)
6 changes: 3 additions & 3 deletions lenstronomy/PointSource/Types/source_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class of a single point source defined in the original source coordinate positio

Name within the PointSource module: 'SOURCE_POSITION'
parameters: ra_source, dec_source, source_amp, mag_pert (optional)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to " parameters: ... image_amp/source_amp" to match lensed_position.py

If fixed_magnification=True, than 'source_amp' is a parameter instead of 'point_amp'
If fixed_magnification=True, than 'source_amp' is a parameter instead of 'image_amp'
mag_pert is a list of fractional magnification pertubations applied to point source images

"""
Expand Down Expand Up @@ -76,7 +76,7 @@ def image_amplitude(self, kwargs_ps, kwargs_lens=None, x_pos=None, y_pos=None, m
mag = self._lens_model.magnification(ra_image, dec_image, kwargs_lens)
point_amp = kwargs_ps['source_amp'] * np.abs(mag)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some way to throw an informative error before trying to access kwargs_ps['source_amp']? i.e. check for both self.fixed_magnification = True and the existence of the 'source_amp' key before trying to access it? And also check the opposite for self.fixed_magnification = False and 'image_amp'. This might be difficult because you would have to put this in every function that uses kwargs_ps...

else:
point_amp = kwargs_ps['point_amp']
point_amp = kwargs_ps['image_amp']
if x_pos is not None:
point_amp = _expand_to_array(point_amp, len(x_pos))
mag_pert = kwargs_ps.get('mag_pert', 1)
Expand All @@ -100,6 +100,6 @@ def source_amplitude(self, kwargs_ps, kwargs_lens=None):
else:
ra_image, dec_image = self.image_position(kwargs_ps, kwargs_lens)
mag = self._lens_model.magnification(ra_image, dec_image, kwargs_lens)
point_amp = kwargs_ps['point_amp']
point_amp = kwargs_ps['image_amp']
source_amp = np.mean(np.array(point_amp) / np.array(mag))
return np.array(source_amp)
6 changes: 3 additions & 3 deletions lenstronomy/PointSource/Types/unlensed.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Unlensed(PSBase):
class of a single point source in the image plane, aka star
Name within the PointSource module: 'UNLENSED'
This model can deal with arrays of point sources.
parameters: ra_image, dec_image, point_amp
parameters: ra_image, dec_image, image_amp

"""

Expand Down Expand Up @@ -43,7 +43,7 @@ def image_amplitude(self, kwargs_ps, **kwargs):
:param kwargs: keyword arguments of function call (which are not used for this object
:return: numpy array of amplitudes
"""
point_amp = kwargs_ps['point_amp']
point_amp = kwargs_ps['image_amp']
return np.array(point_amp)

def source_amplitude(self, kwargs_ps, **kwargs):
Expand All @@ -54,5 +54,5 @@ def source_amplitude(self, kwargs_ps, **kwargs):
:param kwargs: keyword arguments of function call (which are not used for this object
:return: numpy array of amplitudes
"""
point_amp = kwargs_ps['point_amp']
point_amp = kwargs_ps['image_amp']
return np.array(point_amp)
14 changes: 7 additions & 7 deletions lenstronomy/PointSource/point_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, point_source_type_list, lensModel=None, fixed_magnification_l
:param fixed_magnification_list: list of booleans (same length as point_source_type_list).
If True, magnification ratio of point sources is fixed to the one given by the lens model.
This option then requires to provide a 'source_amp' amplitude of the source brightness instead of
'point_amp' the list of image brightnesses.
'image_amp' the list of image brightnesses.
:param additional_images_list: list of booleans (same length as point_source_type_list). If True, search for
additional images of the same source is conducted.
:param flux_from_point_source_list: list of booleans (optional), if set, will only return image positions
Expand Down Expand Up @@ -322,7 +322,7 @@ def update_linear(self, param, i, kwargs_ps, kwargs_lens):
i += 1
else:
n_points = len(ra_pos_list[k])
kwargs['point_amp'] = np.array(param[i:i + n_points])
kwargs['image_amp'] = np.array(param[i:i + n_points])
i += n_points
return kwargs_ps, i

Expand Down Expand Up @@ -361,12 +361,12 @@ def set_amplitudes(self, amp_list, kwargs_ps):
if self._flux_from_point_source_list[i]:
amp = amp_list[i]
if model == 'UNLENSED':
kwargs_list[i]['point_amp'] = amp
kwargs_list[i]['image_amp'] = amp
elif model in ['LENSED_POSITION', 'SOURCE_POSITION']:
if self._fixed_magnification_list[i] is True:
kwargs_list[i]['source_amp'] = amp
else:
kwargs_list[i]['point_amp'] = amp
kwargs_list[i]['image_amp'] = amp
return kwargs_list

@classmethod
Expand All @@ -375,12 +375,12 @@ def check_positive_flux(cls, kwargs_ps):
check whether inferred linear parameters are positive

:param kwargs_ps: point source keyword argument list
:return: bool, True, if all 'point_amp' parameters are positive semi-definite
:return: bool, True, if all 'image_amp' or 'source_amp' parameters are positive semi-definite
"""
pos_bool = True
for kwargs in kwargs_ps:
if 'point_amp' in kwargs:
point_amp = kwargs['point_amp']
if 'image_amp' in kwargs:
point_amp = kwargs['image_amp']
if not np.all(point_amp >= 0):
pos_bool = False
break
Expand Down
20 changes: 10 additions & 10 deletions lenstronomy/PointSource/point_source_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __init__(self, model_list, kwargs_fixed, num_point_source_list=None, linear_
if self._fixed_magnification_list[k] is True and model in ['LENSED_POSITION', 'SOURCE_POSITION']:
fixed_low['source_amp'] = 0
else:
fixed_low['point_amp'] = np.zeros(num)
fixed_low['image_amp'] = np.zeros(num)
kwargs_lower.append(fixed_low)
if kwargs_upper is None:
kwargs_upper = []
Expand All @@ -60,7 +60,7 @@ def __init__(self, model_list, kwargs_fixed, num_point_source_list=None, linear_
if self._fixed_magnification_list[k] is True and model in ['LENSED_POSITION', 'SOURCE_POSITION']:
fixed_high['source_amp'] = 100
else:
fixed_high['point_amp'] = np.ones(num)*100
fixed_high['image_amp'] = np.ones(num)*100
kwargs_upper.append(fixed_high)
self.lower_limit = kwargs_lower
self.upper_limit = kwargs_upper
Expand Down Expand Up @@ -106,11 +106,11 @@ def get_params(self, args, i):
else:
kwargs['source_amp'] = kwargs_fixed['source_amp']
else:
if 'point_amp' not in kwargs_fixed:
kwargs['point_amp'] = np.array(args[i:i + self._num_point_sources_list[k]])
if 'image_amp' not in kwargs_fixed:
kwargs['image_amp'] = np.array(args[i:i + self._num_point_sources_list[k]])
i += self._num_point_sources_list[k]
else:
kwargs['point_amp'] = kwargs_fixed['point_amp']
kwargs['image_amp'] = kwargs_fixed['image_amp']

kwargs_list.append(kwargs)
return kwargs_list, i
Expand Down Expand Up @@ -144,8 +144,8 @@ def set_params(self, kwargs_list):
if 'source_amp' not in kwargs_fixed:
args.append(kwargs['source_amp'])
else:
if 'point_amp' not in kwargs_fixed:
amp = kwargs['point_amp'][0:self._num_point_sources_list[k]]
if 'image_amp' not in kwargs_fixed:
amp = kwargs['image_amp'][0:self._num_point_sources_list[k]]
for a in amp:
args.append(a)
return args
Expand Down Expand Up @@ -182,10 +182,10 @@ def num_param(self):
num += 1
name_list.append('source_amp')
else:
if 'point_amp' not in kwargs_fixed:
if 'image_amp' not in kwargs_fixed:
num += self._num_point_sources_list[k]
for i in range(self._num_point_sources_list[k]):
name_list.append('point_amp')
name_list.append('image_amp')
return num, name_list

def add_fix_linear(self, kwargs_fixed):
Expand All @@ -199,7 +199,7 @@ def add_fix_linear(self, kwargs_fixed):
if self._fixed_magnification_list[k] is True and model in ['LENSED_POSITION', 'SOURCE_POSITION']:
kwargs_fixed[k]['source_amp'] = 1
else:
kwargs_fixed[k]['point_amp'] = np.ones(self._num_point_sources_list[k])
kwargs_fixed[k]['image_amp'] = np.ones(self._num_point_sources_list[k])
return kwargs_fixed

def num_param_linear(self):
Expand Down
2 changes: 1 addition & 1 deletion lenstronomy/SimulationAPI/point_source_variability.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,5 @@ def point_source_time(self, t):
for i, dt in enumerate(self._dt_days):
t_i = -dt + t
mag[i] = self._variability_func(t_i)
kwargs_ps[0]['point_amp'] = self.sim_api_ps.magnitude2cps(mag) * np.abs(self._mag)
kwargs_ps[0]['image_amp'] = self.sim_api_ps.magnitude2cps(mag) * np.abs(self._mag)
return kwargs_ps
2 changes: 1 addition & 1 deletion test/test_Analysis/test_light_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def test_point_source(self):
kwargs_model = {'lens_model_list': ['SPEMD', 'SHEAR_GAMMA_PSI'], 'point_source_model_list': ['SOURCE_POSITION']}
lensAnalysis = ProfileAnalysis(kwargs_model=kwargs_model)
source_x, source_y = 0.02, 0.1
kwargs_ps = [{'dec_source': source_y, 'ra_source': source_x, 'point_amp': 75.155}]
kwargs_ps = [{'dec_source': source_y, 'ra_source': source_x, 'image_amp': 75.155}]
kwargs_lens = [{'e2': 0.1, 'center_x': 0, 'theta_E': 1.133, 'e1': 0.1, 'gamma': 2.063, 'center_y': 0}, {'gamma_ext': 0.026, 'psi_ext': 1.793}]
x_image, y_image = lensAnalysis.PointSource.image_position(kwargs_ps=kwargs_ps, kwargs_lens=kwargs_lens)
from lenstronomy.LensModel.Solver.lens_equation_solver import LensEquationSolver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def setup(self):

# Point Source
point_source_model_list = ['UNLENSED']
kwargs_ps = [{'ra_image': [0.4], 'dec_image': [-0.2], 'point_amp': [2]}]
kwargs_ps = [{'ra_image': [0.4], 'dec_image': [-0.2], 'image_amp': [2]}]
point_source_class = PointSource(point_source_type_list=point_source_model_list)

kwargs_numerics = {'supersampling_factor': 1, 'supersampling_convolution': False, 'compute_mode': 'regular'}
Expand Down
4 changes: 2 additions & 2 deletions test/test_ImSim/test_image_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def test_point_source_rendering(self):
ra_pos, dec_pos = makeImage.Data.map_pix2coord(x_pix, y_pix)
e1, e2 = param_util.phi_q2_ellipticity(0, 0.8)
kwargs_lens_init = [{'theta_E': 1, 'gamma': 2, 'e1': e1, 'e2': e2, 'center_x': 0, 'center_y': 0}]
kwargs_else = [{'ra_image': ra_pos, 'dec_image': dec_pos, 'point_amp': np.ones_like(ra_pos)}]
kwargs_else = [{'ra_image': ra_pos, 'dec_image': dec_pos, 'image_amp': np.ones_like(ra_pos)}]
image = makeImage.image(kwargs_lens_init, kwargs_source={}, kwargs_lens_light={}, kwargs_ps=kwargs_else)
#print(np.shape(model), 'test')
#image = makeImage.ImageNumerics.array2image(model)
Expand All @@ -186,7 +186,7 @@ def test_point_source_rendering(self):
phi, q = 0., 0.8
e1, e2 = param_util.phi_q2_ellipticity(phi, q)
kwargs_lens_init = [{'theta_E': 1, 'gamma': 2, 'e1': e1, 'e2': e2, 'center_x': 0, 'center_y': 0}]
kwargs_else = [{'ra_image': ra_pos, 'dec_image': dec_pos, 'point_amp': np.ones_like(ra_pos)}]
kwargs_else = [{'ra_image': ra_pos, 'dec_image': dec_pos, 'image_amp': np.ones_like(ra_pos)}]
image = makeImage.image(kwargs_lens_init, kwargs_source={}, kwargs_lens_light={}, kwargs_ps=kwargs_else)
#image = makeImage.ImageNumerics.array2image(model)
for i in range(len(x_pix)):
Expand Down
6 changes: 3 additions & 3 deletions test/test_Plots/test_plot_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ def test_source_position_plot(self):
lensModel = LensModel(lens_model_list=['SIS'])
ps = PointSource(point_source_type_list=['UNLENSED', 'LENSED_POSITION', 'SOURCE_POSITION'], lensModel=lensModel)
kwargs_lens = [{'theta_E': 1., 'center_x': 0, 'center_y': 0}]
kwargs_ps = [{'ra_image': [1., 1.], 'dec_image': [0, 1], 'point_amp': [1, 1]},
{'ra_image': [1.], 'dec_image': [1.], 'point_amp': [10]},
{'ra_source': 0.1, 'dec_source': 0, 'point_amp': 1.}]
kwargs_ps = [{'ra_image': [1., 1.], 'dec_image': [0, 1], 'image_amp': [1, 1]},
{'ra_image': [1.], 'dec_image': [1.], 'image_amp': [10]},
{'ra_source': 0.1, 'dec_source': 0, 'image_amp': 1.}]
ra_source, dec_source = ps.source_position(kwargs_ps, kwargs_lens)
from lenstronomy.Data.coord_transforms import Coordinates
coords_source = Coordinates(transform_pix2angle=np.array([[1, 0], [0, 1]])* 0.1,
Expand Down
4 changes: 2 additions & 2 deletions test/test_PointSource/test_Types/test_lensed_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def setup(self):
self.ps_mag = LensedPositions(lens_model=lens_model, fixed_magnification=True)
self.ps = LensedPositions(lens_model=lens_model, fixed_magnification=False)
self.ps_add = LensedPositions(lens_model=lens_model, fixed_magnification=[False], additional_image=True)
self.kwargs = {'point_amp': [2, 1], 'ra_image': [0, 1.2], 'dec_image': [0, 0]}
self.kwargs = {'image_amp': [2, 1], 'ra_image': [0, 1.2], 'dec_image': [0, 0]}
self.kwargs_mag = {'source_amp': 2, 'ra_image': [0, 1.2], 'dec_image': [0, 0]}

def test_image_source_position(self):
Expand All @@ -37,7 +37,7 @@ def test_image_amplitude(self):
amp = self.ps.image_amplitude(self.kwargs, kwargs_lens=self.kwargs_lens, x_pos=self.kwargs['ra_image'],
y_pos=self.kwargs['dec_image'], magnification_limit=None,
kwargs_lens_eqn_solver=None)
npt.assert_almost_equal(self.kwargs['point_amp'], amp)
npt.assert_almost_equal(self.kwargs['image_amp'], amp)

amp = self.ps_mag.image_amplitude(self.kwargs_mag, kwargs_lens=self.kwargs_lens, x_pos=None,
y_pos=None, magnification_limit=None, kwargs_lens_eqn_solver=None)
Expand Down
4 changes: 2 additions & 2 deletions test/test_PointSource/test_Types/test_source_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def setup(self):
self.kwargs_lens = [{'theta_E': 1, 'center_x': 0, 'center_y': 0}]
self.ps_mag = SourcePositions(lens_model=lens_model, fixed_magnification=True)
self.ps = SourcePositions(lens_model=lens_model, fixed_magnification=False)
self.kwargs = {'point_amp': [2, 1], 'ra_source': 0.1, 'dec_source': 0}
self.kwargs = {'image_amp': [2, 1], 'ra_source': 0.1, 'dec_source': 0}
self.kwargs_mag = {'source_amp': 1, 'ra_source': 0.1, 'dec_source': 0}

def test_image_position(self):
Expand All @@ -38,7 +38,7 @@ def test_image_amplitude(self):
amp = self.ps.image_amplitude(self.kwargs, kwargs_lens=self.kwargs_lens, x_pos=x_img,
y_pos=y_img, magnification_limit=None,
kwargs_lens_eqn_solver=None)
npt.assert_almost_equal(amp, self.kwargs['point_amp'])
npt.assert_almost_equal(amp, self.kwargs['image_amp'])

#see if works with mag_pert defined
self.kwargs['mag_pert'] = [0.1,0.1]
Expand Down