The sherpa.models.model module

Allow models to be defined and combined.

A single model is defined by the parameters of the model - stored as sherpa.models.parameter.Parameter instances - and the function that takes the parameter values along with an array of grid values. The main classes are:

  • Model which is the base class and defines most of the interfaces.

  • ArithmeticConstantModel and ArithmeticFunctionModel for representing a constant value or a function.

  • ArithmeticModel is the main base class for deriving user models since it supports combining models (e.g. by addition or multiplication) and a cache to reduce evaluation time at the expense of memory use.

  • RegriddableModel builds on ArithmeticModel to allow a model to be evaluated on a different grid to that requested: most model classes are derived from the 1D (RegriddableModel1D) and 2D (RegriddableModel2D) variants of RegriddableModel.

  • CompositeModel which is used to represent a model expression, that is combined models, such as m1 * (m2 + m3)

  • SimulFitModel for fitting multiple models and datasets.

Creating a model

Models can be created with an optional name, which is useful for identifying a component in an expression:

>>> from sherpa.models.basic import Gauss1D
>>> m1 = Gauss1D()
>>> m2 = Gauss1D('gmdl')
>>> print(m1)
gauss1d
   Param        Type          Value          Min          Max      Units
   -----        ----          -----          ---          ---      -----
   gauss1d.fwhm thawed           10  1.17549e-38  3.40282e+38
   gauss1d.pos  thawed            0 -3.40282e+38  3.40282e+38
   gauss1d.ampl thawed            1 -3.40282e+38  3.40282e+38
>>> print(m2)
gmdl
   Param        Type          Value          Min          Max      Units
   -----        ----          -----          ---          ---      -----
   gmdl.fwhm    thawed           10  1.17549e-38  3.40282e+38
   gmdl.pos     thawed            0 -3.40282e+38  3.40282e+38
   gmdl.ampl    thawed            1 -3.40282e+38  3.40282e+38

Changing parameters

The parameters are the model values that control the output of the model. A particular model has a fixed set of parameters that can be inspected with print or the pars attribute:

>>> print(m2)
gmdl
   Param        Type          Value          Min          Max      Units
   -----        ----          -----          ---          ---      -----
   gmdl.fwhm    thawed           10  1.17549e-38  3.40282e+38
   gmdl.pos     thawed            0 -3.40282e+38  3.40282e+38
   gmdl.ampl    thawed            1 -3.40282e+38  3.40282e+38
>>> print(m2.pars)
(<Parameter 'fwhm' of model 'gmdl'>, <Parameter 'pos' of model 'gmdl'>, <Parameter 'ampl' of model 'gmdl'>)

The parameters are instances of the sherpa.models.parameter.Parameter class:

>>> print(m2.fwhm)
val         = 10.0
min         = 1.1754943508222875e-38
max         = 3.4028234663852886e+38
units       =
frozen      = False
link        = None
default_val = 10.0
default_min = 1.1754943508222875e-38
default_max = 3.4028234663852886e+38
>>> print(m2.fwhm.val)
10.0

Setting the model parameter does not require going through the val attribute as you can say:

>>> m2.fwhm = 20

Accessing parameter values

The model class is set up so that any attribute access is case insensitive, so the following are all ways to change the fwhm parameter:

>>> m2.fwhm = 10
>>> m2.FWHM = 10
>>> m2.FwHm = 10

Linking parameters

One parameter can be made to reference one or more other parameters, a process called “linking”. The linked parameter is no-longer considered a free parameter in a fit since its value is derived from the other parameters. This link can be a simple one-to-one case, such as ensuring the fwhm parameter of one model is the same as the other:

>>> m2.fwhm = m1.fwhm

It can be more complex, such as ensuring the position of one line is a fixed distance from another:

>>> m2.pos = m1.pos + 23.4

It can even include multiple parameters:

>>> m3 = Gauss1D("m3")
>>> m3.ampl = (m1.ampl + m2.ampl) / 2

Requesting the parameter value will return the evaluated expression, and the expression is stored in the link attribute:

>>> m1.ampl = 10
>>> m2.ampl = 12
>>> m3.ampl.val
11.0
>>> m3.ampl.link
<BinaryOpParameter '((gauss1d.ampl + gmdl.ampl) / 2)'>

The string representation of the model changes for linked parameters to indicate the expression:

>>> print(m3)
m3
   Param        Type          Value          Min          Max      Units
   -----        ----          -----          ---          ---      -----
   m3.fwhm      thawed           10  1.17549e-38  3.40282e+38
   m3.pos       thawed            0 -3.40282e+38  3.40282e+38
   m3.ampl      linked           11 expr: ((gauss1d.ampl + gmdl.ampl) / 2)

Model evaluation

With a sherpa.data.Data instance a model can be evaluated with the eval_model method of the object. For example:

>>> import numpy as np
>>> from sherpa.data import Data1D
>>> from sherpa.models.basic import Gauss1D
>>> x = np.asarray([4000, 4100, 4250, 4300, 4400])
>>> y = np.asarray([10, 20, 50, 40, 30])
>>> d = Data1D('example', x, y)
>>> mdl = Gauss1D()
>>> mdl.pos = 4200
>>> mdl.fwhm = 200
>>> mdl.ampl = 50
>>> ymdl1 = d.eval_model(mdl)
>>> print(ymdl1)
[ 3.125      25.         42.04482076 25.          3.125     ]

The model can also be evaluated directly with the independent axis values:

>>> ymdl2 = mdl(x)
>>> print(ymdl2)
[ 3.125      25.         42.04482076 25.          3.125     ]

Integrated bins

If given the low and high edges of the bins then the model will - if supported - evaluate the integral of the model across the bins:

>>> xlo = np.asarray([4180, 4190, 4195, 4200, 4210])
>>> xhi = np.asarray([4190, 4194, 4200, 4210, 4220])
>>> y = mdl(xlo, xhi)
>>> print(y)
[491.98725233 199.0964993  249.85566938 498.847153   491.98725233]

Note that the bins are expected to be in ascending order and do not overlap, but they do not need to be consecutive.

The behavior of a model when given low and high edges depends on whether the model is written to support this mode - that is, integrating the model across the bin - and the setting of the integrate flag of the model. For example, the sherpa.models.basic.Gauss1D model will, by default, integrate the model across each bin when given the bin edges, but if the flag is set to False then just the first array (here xlo) is used:

>>> print(mdl.integrate)
True
>>> mdl.integrate = False
>>> y2 = mdl(xlo, xhi)
>>> print(y2)
[48.63274737 49.65462477 49.91343163 50.         49.65462477]
>>> y3 = mdl(xlo)
>>> y2 == y3
array([ True,  True,  True,  True,  True])

Direct access

The calc method of a model can also be used to evaluate the model, and this requires a list of the parameters and the independent axes:

>>> pars = [200, 4200, 50]
>>> y4 = mdl.calc(pars, x)
>>> y5 = mdl.calc(pars, xlo, xhi)

The parameter order matches the pars attribute of the model:

>>> print([p.fullname for p in mdl.pars])
['gauss1d.fwhm', 'gauss1d.pos', 'gauss1d.ampl']

Model expressions

The CompositeModel class is the base class for creating model expressions - that is the overall model that is combined of one or more model objects along with possible numeric terms, such as a model containing two gaussians and a polynomial:

>>> from sherpa.models.basic import Gauss1D, Polynom1D
>>> l1 = Gauss1D('l1')
>>> l2 = Gauss1D('l2')
>>> l1.pos = 5
>>> l2.pos = 20
>>> l2.ampl = l1.ampl
>>> c = Polynom1D('c')
>>> mdl = l1 + (0.5 * l2) + c

The resulting model can be evaluated just like an individual component:

>>> x = np.arange(-10, 40, 2)
>>> y = mdl(x)

This model is written so that the amplitude of the l2 component is half the l1 component by linking the two ampl parameters and then including a scaling factor in the model expression for l2. An alternative would have been to include this scaling factor in the link expression:

>>> l2.ampl = l1.ampl / 2

Model cache

The ArithmeticModel class and modelCacher1d decorator provide basic support for caching one-dimensional model evaluations - that is, to avoid re-calculating the model. The idea is to save the results of the latest calls to a model and return the values from the cache, hopefully saving time at the expense of using more memory. This is most effective when the same model is used with multiple datasets which all have the same grid.

The _use_caching attribute of the model is used to determine whether the cache is used, but this setting can be over-ridden by the startup method, which is automatically called by the fit and est_errors methods of a sherpa.fit.Fit object.

The cache_clear and cache_status methods of the ArithmeticModel and CompositeModel classes allow you to clear the cache and display to the standard output the cache status of each model component.

Example

The following class implements a simple scale model which has a single parameter (scale) which defaults to 1. It can be used for both non-integrated and integrated datasets of any dimensionality (see sherpa.models.basic.Scale1D and sherpa.models.basic.Scale2D):

class ScaleND(ArithmeticModel):
    '''A constant value per element.'''

    def __init__(self, name='scalend'):
        self.scale = Parameter(name, 'scale', 1)
        self.integrate = False
        pars = (self.scale, )
        ArithmeticModel.__init__(self, name, pars)

    def calc(self, p, *args, **kwargs):
        return p[0] * np.ones_like(args[0])

Classes

Model(name[, pars])

The base class for Sherpa models.

ArithmeticConstantModel(val[, name])

Represent a constant value, or values.

ArithmeticFunctionModel(func)

Represent a callable function.

ArithmeticModel(name[, pars])

Support combining model expressions and caching results.

CompositeModel(name, parts)

Represent a model with composite parts.

BinaryOpModel(lhs, rhs, op, opstr)

Combine two model expressions.

FilterModel(model, filter)

MultigridSumModel(models)

NestedModel(outer, inner, *otherargs, ...)

Apply a model to the results of a model.

RegriddableModel(name[, pars])

Support models that can be evaluated on a different grid.

RegriddableModel1D(name[, pars])

Allow 1D models to be regridded.

RegriddableModel2D(name[, pars])

Allow 2D models to be regridded.

SimulFitModel(name, parts)

Store multiple models.

UnaryOpModel(arg, op, opstr)

Apply an operator to a model expression.

Functions

modelCacher1d(func)

A decorater to cache 1D ArithmeticModel evalutions.

Class Inheritance Diagram

Inheritance diagram of Model, ArithmeticConstantModel, ArithmeticFunctionModel, ArithmeticModel, CompositeModel, BinaryOpModel, FilterModel, MultigridSumModel, NestedModel, RegriddableModel, RegriddableModel1D, RegriddableModel2D, SimulFitModel, UnaryOpModel