spey.base.backend_base.BackendBase

spey.base.backend_base.BackendBase#

class spey.base.backend_base.BackendBase[source]#

Abstract base class that every spey statistical-model backend must inherit.

spey relies on a plugin system to support multiple likelihood prescriptions. Any new prescription is expressed as a Python class that inherits BackendBase and implements, at minimum, config() and get_logpdf_func(). The framework then automatically enables hypothesis testing, upper-limit computation, and Asimov-data generation for the new prescription through StatisticalModel.

Required class-level metadata

Each backend class must expose the following attributes so that spey’s plugin registry can identify, version-check, and cite it:

class MyBackend(spey.BackendBase):
    name          = "my_package.my_model"   # unique entry-point name
    version       = "1.0.0"                 # backend version string
    author        = "Jane Doe <jane@example.com>"
    spey_requires = ">=0.1.0"               # minimum compatible spey version
    doi           = []                       # optional list of citable DOIs
    arXiv         = []                       # optional list of arXiv IDs

Required methods

Subclasses must implement:

  • config() — returns a ModelConfig describing the parameter structure (number of parameters, POI index, suggested initial values, and parameter bounds).

  • get_logpdf_func() — returns a callable f(pars: np.ndarray) -> float that evaluates \(\log\mathcal{L}(\mu, \theta)\) for a given parameter vector.

Optional methods

Each optional method unlocks additional capabilities in the spey interface:

Method

Capability unlocked

is_alive()

Quick validity check; defaults to True.

expected_data()

Required for the asymptotic calculator and Asimov-data generation.

get_objective_function()

Override to supply analytical gradients for the optimiser.

get_hessian_logpdf_func()

Enables sigma_mu_from_hessian().

get_sampler()

Required for the toy (pseudo-experiment) calculator.

combine()

Enables model combination via combine() and the @ operator.

negative_loglikelihood() and variants

Optional fast-path overrides that bypass the generic spey optimiser.

Minimal working example

The example below implements a simple Poisson counting model, \(\mathcal{L}(\mu) = \prod_i \mathrm{Poiss}(n^i \mid \mu s^i + b^i)\), and registers it directly without a setup.py:

import numpy as np
import spey
from spey.base.model_config import ModelConfig

@spey.register_backend
class PoissonModel(spey.BackendBase):
    name          = "my_package.poisson"
    version       = "1.0.0"
    author        = "Jane Doe"
    spey_requires = ">=0.1.0"

    def __init__(self, signal, background, data):
        self._signal     = np.array(signal,     dtype=float)
        self._background = np.array(background, dtype=float)
        self._data       = np.array(data,       dtype=float)

    @property
    def is_alive(self):
        return bool(np.any(self._signal > 0.0))

    def config(self, allow_negative_signal=True, poi_upper_bound=10.0):
        minimum_poi = -10.0 if allow_negative_signal else 0.0
        return ModelConfig(
            poi_index=0,
            minimum_poi=minimum_poi,
            suggested_init=[1.0],
            suggested_bounds=[(minimum_poi, poi_upper_bound)],
        )

    def get_logpdf_func(
        self, expected=spey.ExpectationType.observed, data=None
    ):
        obs = self._data if data is None else np.array(data)
        if expected is spey.ExpectationType.apriori:
            obs = self._background

        def logpdf(pars):
            mu   = pars[0]
            rate = mu * self._signal + self._background
            return float(np.sum(obs * np.log(rate) - rate))

        return logpdf

    def expected_data(self, pars):
        mu = pars[0]
        return list(mu * self._signal + self._background)

# Use the model
model = spey.get_backend("my_package.poisson")(
    signal=[5.0, 3.0],
    background=[10.0, 8.0],
    data=[12, 9],
    analysis="example",
    xsection=0.05,
)
print(model.exclusion_confidence_level())

See also

Building a plugin — full tutorial on writing, registering, and packaging a spey plugin, including entry-point installation via setup.py / pyproject.toml and citation metadata.

__init__()#

Methods

__init__()

asimov_negative_loglikelihood([poi_test, ...])

Compute the profiled negative log-likelihood at fixed \(\mu\) on Asimov data.

combine(other, **kwargs)

Combine this statistical model with another backend instance.

config([allow_negative_signal, poi_upper_bound])

Return the model configuration used by the optimiser.

expected_data(pars)

Return the expected bin counts for a given parameter vector.

get_hessian_logpdf_func([expected, data])

Return a callable that evaluates the Hessian of \(\log\mathcal{L}(\mu, \theta)\).

get_logpdf_func([expected, data])

Return a callable that evaluates \(\log\mathcal{L}(\mu, \theta)\).

get_objective_function([expected, data, do_grad])

Return the objective function (and optionally its gradient) for the optimiser.

get_sampler(pars)

Return a callable that draws pseudo-data from the model at fixed parameters.

minimize_asimov_negative_loglikelihood([...])

Find the global minimum of the negative log-likelihood on Asimov data (free fit).

minimize_negative_loglikelihood([expected, ...])

Find the global minimum of the negative log-likelihood (free fit).

negative_loglikelihood([poi_test, expected])

Compute the profiled negative log-likelihood at a fixed \(\mu\).

Attributes

is_alive

Whether the model has at least one bin with a non-zero signal yield.