Making changes to models and plotting using dependency injections

Several models and classes in redback use dependency injections. This enables users to easily swap some functionality with their own preferred method while keeping the rest of the infrastructure intact.

Modifying a model physics/Creating a new model

In models we discussed how to make changes to models with functions/classes already implemented in redback.

Here we show how to create your own modification to the physics and pass that into a redback model. We demonstrate this functionality with creating a new ejecta relation class, that provides a link from the intrinsic binary neutron star parameters to the properties of the ejecta.

from redback.ejecta_relations import calc_compactness_from_lambda

class I_made_this_relation_up(object):
    """
    Relations to connect intrinsic GW parameters to extrinsic kilonova parameters
    """
    def __init__(self, mass_1, mass_2, lambda_1, lambda_2):
        self.mass_1 = mass_1
        self.mass_2 = mass_2
        self.lambda_1 = lambda_1
        self.lambda_2 = lambda_2
        self.reference = 'No, I really just made this up'
        self.ejecta_mass = self.calculate_ejecta_mass
        self.ejecta_velocity = self.calculate_ejecta_velocity

    @property
    def calculate_ejecta_velocity(self):
        c1 = calc_compactness_from_lambda(self.lambda_1)
        c2 = calc_compactness_from_lambda(self.lambda_2)

        vej = 1000 * (self.mass_1 / self.mass_2) * (1 + 0.5) + 0.99 * (self.mass_2 / self.mass_1)
        return vej

    @property
    def calculate_ejecta_mass(self):
        c1 = calc_compactness_from_lambda(self.lambda_1)
        c2 = calc_compactness_from_lambda(self.lambda_2)

        log10_mej = self.mass_1 * (self.mass_2 / self.mass_1)**c1

        mej = 10 ** log10_mej
        return mej

We can now use the class above in the redback one_component_ejecta_relation_model kilonova model

from redback.model_library import all_models_dict
import numpy as np

model = 'one_component_ejecta_relation_model'

function = all_models_dict(model)
time = np.logspace(2, 8, 100)/day_to_s

# create a kwargs dictionary for additional model parameters/ejecta relationship
kwargs = {}

# Pass in our class name, the class will be instantiated within the function.
kwargs['ejecta_relation'] = I_made_this_relation_up

kwargs['frequency'] = 2e14   # frequency to evaluate on

kwargs['temperature_floor'] = 4000 # minimum photosphere temperature

kwargs['output_format'] = flux_density # output format

flux_density = function(time, redshift=0.05, mass_1=1.4, mass_2=1.4,
                                    lambda_1=400, lambda_2=400, kappa=3, **kwargs)

The above is just an example to create a new model by changing the relating the ejecta properties in a kilonova to the binary parameters. We can similarly create other functions/classes to change what cosmology is used, model engine, type of interaction process, photosphere, or SED.

Modifying plot_lightcurve

Similarly to how a user can modify a model, a user can also modify the plot_lightcurve and plot_multiband_lightcurve routines. We don’t really recommend this for aesthetic things as they can be simply passed to the existing function, but a user can do this if they want to.

Using your own cosmology

If a user works with a transient outside of the Hubble flow, redshift is not a useful measure of the distance. In such a case, the user could provide a known physical distance.

from astropy import units as u
from redback.util import user_cosmology

your_cosmology = user_cosmology()
your_cosmology.set_luminosity_distance(40*u.kpc)

# To use your cosmology in the fitting

model_kwargs = dict(cosmology = your_cosmology)