Models#

The modular nature of Prospector allows it to be applied to a variety of data types and different scientific questions. However, this flexibility requires the user to take care in defining the model, including prior distributions, which may be specific to a particular scientific question or to the data to be fit. Different models and prior beliefs may be more or less appropriate for different kinds of galaxies. Certain kinds of data may require particular model components in order to be described well. Prospector strives to make this model building process as straightforward as possible, but it is a step that cannot be skipped.

The choice of which parameters to include, which to let vary, and what prior distributions to use will depend on the data being fit (including the types of objects) and the goal of the inference. As examples, if no infrared data is available then it is not necessary to fit – or even include in the model at all – the dust emission parameters controlling the shape of the infrared SED. For globular clusters or completely quenched galaxies it may not be necessary to include nebular emission in the model, and one may wish to adjust the priors on population age or star formation history to be more appropriate for such objects. If spectroscopic data is being fit then it may be necessary to include velocity dispersion as a free parameter. Generating and fitting mock data can be an extremely useful tool for exploring the sensitivity of a given type of data to various parameters.

Parameter Specification#

A model is defined by a dictionary of parameter specifications, keyed by parameter name, that is used to instantiate and configure the model objects (instances of models.ProspectorParams or its subclasses.) This dictionary is usually constructed or given in a parameter file.

For a single parameter the specification is a dictionary that should at minimum include several keys:

"N"

An integer specifying the length of the parameter. If not supplied this defaults to 1, the common case of a scalar parameter.

"isfree"

Boolean specifying whether a parameter is free to vary during optimization and sampling (True) or not (False). This defaults to False if not supplied.

"init"

The initial value of the parameter. If the parameter is not free, then this is the value that will be used throughout optimization and sampling. If the parameter is free to vary, this is where optimization will start from or – if no optimization happens – this will be the center of the initial ball of emcee walkers. Note that if using nested sampling then the value of "init" is not important (though a value must still be given).

For parameters with isfree=True the following additional key is required:

"prior"

An instance of a prior object, including parameters for the prior (e.g. priors.TopHat(mini=10, maxi=12)).

If using emcee, the following key can be useful to have:

"init_disp"

The dispersion in this parameter to use when generating an emcee sampler ball. This is not technically required, as it defaults to 10% of the initial value. It is ignored if nested sampling is used.

It’s also a good idea to have a "units" key, a string describing the units of the the parameter. So, in the end, this looks something like:

mass = dict(N=1, init=1e9, isfree=True,
            prior= priors.LogUniform(mini=1e7, maxi=1e12),
            units="M$_\odot$ of stars formed.", init_disp=1e8)
model_params = dict(mass=mass)

Nearly all parameters used by FSPS can become a model parameter. When fitting galaxies the default python-FSPS parameter values will be used unless specified in a fixed parameter, e.g. imf_type can be changed by including it as a fixed parameter with value given by "init".

Parameters can also be used to control the Prospector-specific parts of the modeling code. These include things like spectral smoothing, wavelength calibration, spectrophotometric calibration, and any parameters of the noise model. Be warned though, if you include a parameter that does not affect the model the code will not complain, and if that parameter is free it will simply result in a posterior PDF that is the same as the prior (though optimization algorithms may fail).

Priors#

All parameters that are free to vary must have an associated prior distribution. Prior objects can be found in the prospect.models.priors module. When specifying a prior using an object, you can and should specify the parameters of that prior on initialization, e.g.

model_params["dust2"]["prior"] = priors.ClippedNormal(mean=0.3, sigma=0.5, mini=0.0, maxi=3.0)

Transformations#

Sometimes the native parameterization of stellar population models is not the most useful. In these cases parameter transformations can prove useful.

Transformations are useful to impose parameter limits that are a function of other parameters; for example, when fitting for redshift it can be useful to reparameterize the age of a population (say, in Gyr) into its age as a fraction of the age of the universe at that redshift. This avoids the problem of populations that are older than the age of the universe, or complicated joint priors on the population age and the redshift. A number of useful transformation functions are provided in Prospector and these may be easily supplemented with user defined functions.

This parameter transformation and dependency mechanism can be used to tie any number of parameters to any number of other parameters in the model, as long as the latter parameters are not also dependent on some parameter transformation. This mechanism may also be used to avoid joint priors. For example, if one wishes to place a prior on the ratio of two parameters (say, that it be less than one) then the ratio itself can be introduced as a new parameter, and one of the original parameters can be “fixed” but have its value at each parameter location depend on the other original parameter and the new ratio parameter.

As a simple example, we consider sampling in the log of the SF timescale instead of the timescale itself. The follwing code

def delogify(logtau=0, **extras):
    return 10**logtau

model_params["tau"]["isfree"] = False
model_params["tau"]["depends_on"] = delogify
model_params["logtau"] = dict(N=1, init=0, isfree=True, prior=priors.TopHat(mini=-1, maxi=1))

could be used to set the value of tau using the free parameter logtau (i.e., sample in the log of a parameter, though setting a prospect.models.priors.LogUniform prior is equivalent in terms of the posterior).

This dependency function must take optional extra keywords (**extras) because the entire parameter dictionary will be passed to it. Then add the new parameter specification to the model_params dictionary for the parameter that can vary (and upon which the fixed parameter depends). In this example that new free parameter would be logtau.

This pattern can also be used to tie arbitrary parameters together (e.g. gas-phase and stellar metallicity) while still allowing them to vary. A parameter may depend on multiple other (free or fixed) parameters, and multiple parameters may depend on a single other (free or fixed) parameter. This mechanism is used extensively for the non-parametric SFHs, and is recommended for complex dust attenuation models.

Note

It is important that any parameter with the "depends_on" key present is a fixed parameter. For portability and easy reconstruction of the model it is important that the depends_on function either be importable (e.g. one of the functions supplied in prospect.models.transforms) or defined within the parameter file.

Parameter Set Templates#

A number of predefined sets of parameters (with priors) are available as dictionaries of model specifications from prospect.models.templates.TemplateLibrary, these can be a good starting place for building your model. To see the available parameter sets to inspect the free and fixed parameters in a given set, you can do something like

        from prospect.models.templates import TemplateLibrary
        # Show all pre-defined parameter sets
        TemplateLibrary.show_contents()
        # Show details on the "parameteric" set of parameters
        TemplateLibrary.describe("parametric_sfh")
        # Simply print all parameter specifications in "parametric_sfh"
        print(TemplateLibrary["parametric_sfh"])
        # Actually get a copy of one of the predefined sets
        model_params = TemplateLibrary["parametric_sfh"]
# This dictionary can be updated or modified, to expand the model.
model_params.update(TemplateLibrary["nebular"])
        # Instantiate a model object
        from prospect.models import SedModel
        model = SedModel(model_params)

The build_model() Method#

This method in the parameter file should take the run_params dictionary as keyword arguments, and return an instance of a subclass of prospect.models.ProspectorParams.

The model object, a subclass of prospect.models.ProspectorParams, is initialized with a list or dictionary (keyed by parameter name) of each of the model parameter specifications described above. If using a list, the order of the list sets the order of the free parameters in the parameter vector. The free parameters will be varied by the code during the optimization and sampling phases. The initial value from which optimization is begun is set by the "init" values of each parameter. For fixed parameters the "init" value gives the value of that parameter to use throughout the optimization and sampling phases (unless the "depends_on" key is present, see Advanced Usage.)

The run_params dictionary of arguments (including command line modifications) can be used to change how the model parameters are specified within this method before the prospect.models.ProspectorParams model object is instantiated. For example, the value of a fixed parameter like zred can be set based on values in run_params or additional parameters related to dust or nebular emission can be optionally added based on switches in run_params.

Useful model objects include prospect.models.SpecModel and prospect.models.PolySpecModel. The latter includes tools for optimization of spectrophotometric calibration.