Custom Models and Effects

Introduction

Users can create their own custom models and effects within the LightCurveLynx framework, allowing them to expand the range of phenomena that can be simulated. This page provides a high-level overview of how to create custom models and effects. For more details and examples, see the Adding New Model Types and Adding New Effect Types notebooks.

Custom Models

All models are subclasses of the BasePhysicalModel class, which provides the recipe for computing the noise-free light curves given values for a set of parameters. This base class is subclassed into:

  • SEDModel: for models that simulate the full spectral energy distributions (SEDs).

  • BandfluxModel: for models that simulate band fluxes directly.

Users creating their own models will start by subclassing one of these two classes, depending on the type of model they want to create.

For both types of models, users need to implement an __init__() function that defines the model’s parameters. This function should call the super().__init__() function to initialize the base class and then define the model’s parameters using the add_parameter() function.

For new SED-type models, the class needs to implement a compute_sed() function that generates the noise-free flux densities (in nJy) in the object’s rest-frame given information about the times (in days relative to t0), wavelengths (in Angstroms), and model parameters (called graph_state). Both the times and wavelengths are converted to account for redshift before being passed to the compute_sed() function, so the function takes rest-frame times and wavelengths.

For example simple code to output a constant 1 nJy for all times and wavelengths would look like:

def compute_sed(self, times, wavelengths, graph_state, **kwargs):
    return np.ones((len(times), len(wavelengths)))

For new Bandflux-type models, the class needs to implement a corresponding compute_bandflux() function that generates the band fluxes in the observer-frame given the times (in days relative to t0), bands, and model parameters (called graph_state). These models do not account for redshift, since simulation is done in the observer frame.

A user of a particular physical model only needs to understand what parameters the model has and how they are set. A user creating a new physical model additionally needs to know how the noise-free, rest-frame flux density values are generated from those parameters.

For examples see the Adding New Model Types notebook.

Custom Effects

Effects are transformations made to the flux densities generated by the physical model. Users can create a new effect by subclassing the BaseEffect class and implementing the apply() function, which takes in the flux densities, applies the transformation to them, and outputs the transformed flux densities.

For examples see the Adding New Effect Types notebook.

Handling Randomness

A key property in LightCurveLynx is that a simulation should be deterministically replay-able given a GraphState. What does this mean when a model uses randomness, such as a AGN computed with a damped random walk? LightCurveLynx supports a combination of random models and reproducibility by allowing users to store random seeds within the GraphState.

For example the basic AGN model includes a parameter agn_seed. When generating fluxes for observations, the simulation starts by creating a random number generator with the given seed and using it to sample. The seed saved into the agn_seed can thus be used to reproduce the samples for the AGN. If no seed is specified, this value will itself be random:

if seed is not None:
    self.add_parameter(
        "agn_seed",
        seed,
        description="The seed for the AGN random number generator.",
    )
else:
    seed_generator = NumpyRandomFunc("integers", low=0, high=2**32 - 1)
    self.add_parameter(
        "agn_seed",
        seed_generator,
        description="The seed for the AGN random number generator.",
    )

This ensures that different (non-fixed) the simulations are indeed different.

A similar approach can be used for effects that depend on randomness, such as the WhiteNoise effect. This effect uses the white_noise_seed parameter when to create a random number generator that is deterministic given the seed. Unless a seed is manually specified, that parameter is random chosen.