Quickstart

This section illustrates lensingGW’s core functionalities through worked-out examples. They demonstrate the solver usage and the simulation of the lensed and unlensed gravitational signals.

The lens model is specified through a list of lens profile names and a list of related parameters. It is handled through a forked version of Lenstronomy (original version here): any lens profile implemented therein can be used.

Ready-to-use python scripts implementing the following examples are provided along with each subsection and at the end of the section.

Solve the lens model

Radians

We first define the lens configuration: we use radians, which is lensingGW’s default. As an illustration, we consider two point lenses with Einstein radii \(\theta_{E_1}\) and \(\theta_{E_2}\), whose parameters we have defined in kwargs_lens_list

# lens model
lens_model_list  = ['POINT_MASS', 'POINT_MASS']
kwargs_lens_list = [{'center_x': 6.9e-11,'center_y': 0.0, 'theta_E': thetaE1} , {'center_x': -6.9e-11,'center_y': 0.0, 'theta_E': thetaE2}]

We then specify the solver settings

# solver setup
solver_settings = {'SearchWindowMacro': 4*thetaE1,
                   'SearchWindow'     : 4*thetaE2}
The solver implements the two-step-procedure presented in Pagano et al. 2020. The minimal setup to specify consists in the extension of the search region for the macromodel, SearchWindowMacro and for the complete model, SearchWindow.
Finally, we import the solver routine and solve for the image positions
from lensinggw.solver.images import microimages

# solve for the image positions with the two-step procedure
Img_ra, Img_dec, MacroImg_ra, MacroImg_dec, pixel_width  = microimages(source_pos_x    = 1.39e-11,
                                                                       source_pos_y    = 1.20e-10,
                                                                       lens_model_list = lens_model_list,
                                                                       kwargs_lens     = kwargs_lens_list,
                                                                       **solver_settings)
We obtain the right ascensions and the declinations of the images of the complete model, of the macromodel and the pixel width of the last iteration, in the same units as the input.
The description of the each iteration step can be enabled through the Verbose option in the solver settings.
solver_settings.update({'Verbose' : True})

The verbosity is a useful diagnostic in non-converging cases, as it allows to identify the problematic part of the iteration.

Image properties

Magnifications, time delays and Morse indices can be accessed through the related modules

from lensinggw.utils.utils import TimeDelay, magnifications, getMinMaxSaddle

# time delays, magnifications, Morse indices
tds = TimeDelay(Img_ra, Img_dec,
                source_pos_x = 1.39e-11, source_pos_y = 1.20e-10,
                zL = 0.5 , zS = 2.0,
                lens_model_list, kwargs_lens_list)

mus = magnifications(Img_ra, Img_dec, lens_model_list, kwargs_lens_list)
ns  = getMinMaxSaddle(Img_ra, Img_dec, lens_model_list, kwargs_lens_list)

By default, the solver considers the first profile in lens_model_list as macromodel and applies the two-step procedure to all the macroimages. It sets the same precision requirement on both types of images, as well as the same number of pixels and the same grid sizes for the iterations. These items can be customized through the solver settings. A detailed description of the available options can be found in the solver technical notes.

Arbitrary units

lensingGW supports arbitrary coordinate units, defined as \(x_{\mathrm{a.u.}} = x_{\mathrm{radians}}/ \alpha\), where \(\alpha\) is a constant. To use arbitrary units, all input must be given in the scaled coordinate system and the scaled flag must be enabled in the routines involving coordinates or conversions to physical units.
The previous example can be modified to use \(\alpha = \theta_{E}\), where \(\theta_{E}\) is the Einstein radius of the total mass: replace each quantity in radians with its scaled equivalent and modify the solver settings and the TimeDelay input as follows
# solver setup
solver_settings = {'Scaled'           : True,             # indicate that the input is in scaled units
                   'ScaleFactor'      : thetaE,           # and the scale factor
                   'SearchWindowMacro': 4*thetaE1/thetaE, # scaled input
                   'SearchWindow'     : 4*thetaE2/thetaE} # scaled input
# time delays, magnifications, Morse indices
tds = TimeDelay(Img_ra, Img_dec,                                                # already in scaled units
                source_pos_x = 1.39e-11/thetaE, source_pos_y = 1.20e-10/thetaE, # scaled input
                zL = 0.5 , zS = 2.0,
                lens_model_list, kwargs_lens_list,
                scaled       = solver_settings['Scaled'],      # indicate that the input is in scaled units
                scale_factor = solver_settings['ScaleFactor']) # and the scale factor

The magnification and Morse indices computation doesn’t need modifications, provided that all radians input has been scaled. This includes the lens parameters and the source position.

Multi-component macromodel

By default, lensingGW considers the first profile in lens_model_list as macromodel. However, users can indicate the profiles that form the macromodel by specifying the matching indices in the lens list. This allows to indicate a different profile or multi-component macromodels.
For example, we can define a 2-component macromodel constituted by both the point lenses of the previous examples by adding the following specification in the solver settings
solver_settings.update({'MacroIndex' : [0,1]})

If the number of specified indices corresponds to the number of lens profiles, all the deflectors are considered as part of the macromodel and only the macroimages are investigated.

Only macromodel

If the lens model is composed of a macromodel and a micromodel (such as multiple microlenses), users can require the study of the macromodel only by enabling an appropriate flag in the solver settings

solver_settings.update({'OnlyMacro': True})
This functionality, combined with the multi-component choice, allows to define the lens model once and for all and then investigate the impact of each component on the resulting images by acting on the solver settings.
For example, one can
  • enable OnlyMacro and change the lens profile/profile group indicated as macromodel - assesses the impact of the macromodel components on the images of the macromodel

  • disable OnlyMacro and change the lens profile/profile group indicated as macromodel - assesses the impact of the macromodel components on the images of the complete model

Simulate gravitational waves

Configuration files

If gravitational-wave (GW) signals are requested, a configuration file specifying the binary parameters and the waveform settings has to be provided to lensingGW. A template configuration file with explanations of each entry and a ready-to-use configuration file are provided in examples/ini_files on GitLab.

Note on angles

GWs from compact binaries depend on a set of angles. In addition to the binary right ascension and declination, the waveform depends on the inclination of the system, the polarization angle and on the phase of coalescence.
The standard choice in gravitational-wave astronomy is to indicate such angles in radians. To avoid confusion, the same choice has been adopted within lensingGW. This only affects the angles specified in the waveform configuration file: although any routine of lensingGW supports the definition of arbitrary units for the source coordinates, the source right ascension and declination in the configuration file must by expressed in radians.

Interferometers’ noise curves

Power spectral densities (PSDs) have to be provided for each interferometer in which the waveform is requested. Advanced LIGO and Advanced Virgo design PSDs released by the LIGO/Virgo Collaborations are provided in examples/psds on GitLab.

Get the unlensed gravitational waves

To generate unlensed waveforms, lensingGW’s signal model has to be initialized through the configuration file

from lensinggw.waveform.waveform import gw_signal

# read the waveform parameters
config_file = 'ini_files/waveform_config.ini'

# instantiate the waveform model
waveform_model = gw_signal(config_file)

Polarizations, strains and their frequencies can be accessed through lensingGW’s unlensed routines

# compute the unlensed waveform polarizations, strains in the requested detectors and their frequencies
freqs, hp_tilde, hc_tilde, strain_dict = waveform_model.unlensed_gw()

# and their signal-to-noise-ratios
SNR_dict = waveform_model.unlensed_snr()

The strain and SNR dictionaries allow to access information of each detector individually

# access an unlensed strain
sH1 = strain_dict['H1']

Get the lensed gravitational waves

In addition to the waveform configuration file and to the noise curves, the simulation of lensed signals requires to specify a lens model and a set of images, from which the amplification factor is computed.
Images can be found as described in the solver section, where the lens model initialization is also shown.
Assuming that a lens_model_list and a kwargs_lens_list have been defined and that the Img_ra and Img_dec arrays store the images’ right ascensions and declinations, one can modify the previous example as follows to get the lensed quantities
# compute the lensed waveform polarizations, strains in the requested detectors and their frequencies
waveform_model.lensed_gw(Img_ra, Img_dec,
                         source_pos_x = 1.39e-11, source_pos_y = 1.20e-10,
                         zL = 0.5 , zS = 2.0,
                         lens_model_list,
                         kwargs_lens_list)
# and their signal-to-noise-ratios
waveform_model.lensed_snr(Img_ra, Img_dec,
                          source_pos_x = 1.39e-11, source_pos_y = 1.20e-10,
                          zL = 0.5 , zS = 2.0,
                          lens_model_list,
                          kwargs_lens_list)

Arbitrary units

If the input is in arbitrary units, the scaling has to be notified to the lensed waveform routines by enabling the scaled flag and indicating the scale factor. The previous lines can be modified to use \(\alpha = \theta_{E_1}\) as follows

# compute the lensed waveform polarizations, strains in the requested detectors and their frequencies
waveform_model.lensed_gw(Img_ra, Img_dec,
                          .
                          .
                         scaled = True,
                         scale_factor = thetaE1)
# and their signal-to-noise-ratios
waveform_model.lensed_snr(Img_ra, Img_dec,
                           .
                           .
                          scaled = True,
                          scale_factor = thetaE1)

where omitted lines are unchanged.

User-defined cosmology

By default, a flat cosmology with \(H_0=69.7, \Omega_0=0.306, T_{cmb0}=2.725\) is considered to convert the lens and source redshifts \(z_L\) and \(z_S\) to angular diameter distances. However, users can indicate a different one by specifying an instance of the astropy cosmology class to TimeDelay, lensed_gw and to lensed_snr through the cosmo keyword argument
# time delays, magnifications, Morse indices
TimeDelay(Img_ra, Img_dec,
             .
             .
            cosmo = asropy_cosmo_instance)
# compute the lensed waveform polarizations, strains in the requested detectors and their frequencies
waveform_model.lensed_gw(Img_ra, Img_dec,
                          .
                          .
                         cosmo = asropy_cosmo_instance)
# and their signal-to-noise-ratios
lensed_SNR_dict = waveform_model.lensed_snr(Img_ra, Img_dec,
                                             .
                                             .
                                            cosmo = asropy_cosmo_instance)

where omitted lines are unchanged.