Configs#
Configuration files are used to control the behaviour model components in PyAutoFit, which perform the following tasks:
Specify the default priors of model components, so that a user does not have to manually specify priors every time they create a model.
Specify labels of every parameter, which are used for plotting and visualizing results.
This cookbook illustrates how to create configuration files for your own model components, so that they can be used with PyAutoFit.
Contents:
No Config Behaviour: An example of what happens when a model component does not have a config file.
Template: A template config file for specifying default model component priors.
Modules: Writing prior config files based on the Python module the model component Python class is contained in.
Labels: Config files which specify the labels of model component parameters for visualization.
No Config Behaviour#
The examples seen so far have used Gaussian
and Exponential
model components, which have configuration files in
the autofit_workspace/config/priors
folder which define their priors and labels.
If a model component does not have a configuration file and we try to use it in a fit, PyAutoFit will raise an error.
Lets illustrate this by setting up the usual Gaussian object, but naming it GaussianNoConfig
so that it does
not have a config file.
class GaussianNoConfig:
def __init__(
self,
centre=0.0, # <- PyAutoFit recognises these constructor arguments
normalization=0.1, # <- are the Gaussian`s model parameters.
sigma=0.01,
):
"""
Represents a 1D `Gaussian` profile, which does not have a config file set up.
"""
self.centre = centre
self.normalization = normalization
self.sigma = sigma
def model_data_1d_via_xvalues_from(self, xvalues: np.ndarray) -> np.ndarray:
"""
The usual method that returns the 1D data of the `Gaussian` profile.
"""
transformed_xvalues = xvalues - self.centre
return np.multiply(
np.divide(self.normalization, self.sigma * np.sqrt(2.0 * np.pi)),
np.exp(-0.5 * np.square(np.divide(transformed_xvalues, self.sigma))),
)
When we try make this a Model
and fit it, PyAutoFit raises an error, as it does not know where the priors
of the GaussianNoConfig
are located.
model = af.Model(GaussianNoConfig)
dataset_path = path.join("dataset", "example_1d", "gaussian_x1")
data = af.util.numpy_array_from_json(file_path=path.join(dataset_path, "data.json"))
noise_map = af.util.numpy_array_from_json(
file_path=path.join(dataset_path, "noise_map.json")
)
analysis = af.ex.Analysis(data=data, noise_map=noise_map)
search = af.DynestyStatic()
result = search.fit(model=model, analysis=analysis)
In all other examples, the fits runs because the priors have been defined in one of two ways:
They were manually input in the example script.
They were loaded via config files “behind the scenes”.
Checkout the folder autofit_workspace/config/priors
, where .yaml files defining the priors of the Gaussian
and
Exponential
model components are located. These are the config files that PyAutoFit loads in the background
in order to setup the default priors of these model components.
If we do not manually override priors, these are the priors that will be used by default when a model-fit is performed.
Templates#
For your model-fitting task, you therefore should set up a config file for every model component you defining its default priors.
Next, inspect the TemplateObject.yaml
priors configuration file in autofit_workspace/config/priors
.
You should see the following text:
parameter0:
type: Uniform
lower_limit: 0.0
upper_limit: 1.0
parameter1:
type: Gaussian
mean: 0.0
sigma: 0.1
lower_limit: 0.0
upper_limit: inf
parameter2:
type: Uniform
lower_limit: 0.0
upper_limit: 10.0
This specifies the default priors on two parameters, named parameter0
and parameter1
.
The type
is the type of prior assumed by PyAutoFit by default for its corresponding parameter, where in this
example:
parameter0
is given aUniformPrior
with limits between 0.0 and 1.0.parameter1
aGaussianPrior
with mean 0.0 and sigma 1.0.parameter2
is given aUniformPrior
with limits between 0.0 and 10.0.
The lower_limit
and upper_limit
of a GaussianPrior
define the boundaries of what parameter values are
physically allowed. If a model-component is given a value outside these limits during model-fitting the model is
instantly resampled and discarded.
We can easily adapt this template for any model component, for example the GaussianNoConfig
.
First, copy and paste the TemplateObject.yaml
file to create a new file called GaussianNoConfig.yaml
.
The name of the class is matched to the name of the configuration file, therefore it is a requirement that the
configuration file is named GaussianNoConfig.yaml
so that PyAutoFit can associate it with the GaussianNoConfig
Python class.
Now perform the follow changes to the .yaml
file:
Rename
parameter0
tocentre
and updates its uniform prior to be from alower_limit
of 0.0 and anupper_limit
of 100.0.Rename
parameter1
tonormalization
.Rename
parameter2
tosigma
.
The .yaml
file should read as follows:
centre:
type: Uniform
lower_limit: 0.0
upper_limit: 100.0
normalization:
type: Gaussian
mean: 0.0
sigma: 0.1
lower_limit: 0.0
upper_limit: inf
sigma:
type: Uniform
lower_limit: 0.0
upper_limit: 10.0
We should now be able to make a Model
of the GaussianNoConfig
class and fit it, without manually specifying
the priors.
You may need to reset your Jupyter notebook’s kernel for the changes to the .yaml
file to take effect.
model = af.Model(GaussianNoConfig)
dataset_path = path.join("dataset", "example_1d", "gaussian_x1")
data = af.util.numpy_array_from_json(file_path=path.join(dataset_path, "data.json"))
noise_map = af.util.numpy_array_from_json(
file_path=path.join(dataset_path, "noise_map.json")
)
analysis = af.ex.Analysis(data=data, noise_map=noise_map)
search = af.DynestyStatic()
result = search.fit(model=model, analysis=analysis)
Modules#
For larger projects, it may not be ideal to have to write a .yaml file for every Python class which acts as a model component.
We instead would prefer them to be in their own dedicated Python module.
Suppose the Gaussian
and Exponential
model components were contained in a module named profiles.py
in your
project’s source code.
You could then write a priors .yaml config file following the format given in the example config file
autofit_workspace/config/priors/profiles.yaml
, noting that there is a paring between the module name
(profiles.py
) and the name of the .yaml
file (profiles.yaml
).
The file autofit_workspace/config/priors/template_module.yaml
provides the tempolate for module based prior
configs and reads as follows:
ModelComponent0:
parameter0:
type: Uniform
lower_limit: 0.0
upper_limit: 1.0
parameter1:
type: LogUniform
lower_limit: 1.0e-06
upper_limit: 1000000.0
parameter2:
type: Uniform
lower_limit: 0.0
upper_limit: 25.0
ModelComponent1:
parameter0:
type: Uniform
lower_limit: 0.0
upper_limit: 1.0
parameter1:
type: LogUniform
lower_limit: 1.0e-06
upper_limit: 1000000.0
parameter2:
type: Uniform
lower_limit: 0.0
upper_limit: 1.0
This looks very similar to TemplateObject
, the only differences are:
It now contains the model-component class name in the configuration file, e.g.
ModelComponent0
,ModelComponent1
.It includes multiple model-components, whereas
TemplateObject.yaml
corresponded to only one model component.
Labels#
There is an optional configs which associate model parameters with labels:
autofit_workspace/config/notation.yaml
It includes a label
section which pairs every parameter with a label, which is used when visualizing results
(e.g. these labels are used when creating a corner plot).
label:
label:
sigma: \sigma
centre: x
normalization: norm
parameter0: a
parameter1: b
parameter2: c
rate: \lambda
It also contains a superscript
section which pairs every model-component label with a superscript, so that
models with the same parameter names (e.g. centre
can be distinguished).
label:
superscript:
Exponential: e
Gaussian: g
ModelComponent0: M0
ModelComponent1: M1
The label_format
section sets Python formatting options for every parameter, controlling how they display in
the model.results
file.
label_format:
format:
sigma: '{:.2f}'
centre: '{:.2f}'
normalization: '{:.2f}'
parameter0: '{:.2f}'
parameter1: '{:.2f}'
parameter2: '{:.2f}'
rate: '{:.2f}'