prfmodel.models.base.BaseCanonical

class prfmodel.models.base.BaseCanonical(**models: prfmodel.protocols.ModelProtocol | None)

Generic abstract base class for creating canonical models.

A canonical model combines multiple submodels and defines how they interact to make a combined prediction.

Parameters:

**models – Submodels to be combined into the canonical model. All submodel classes must inherit from ModelProtocol.

Raises:

TypeError – If submodel classes do not inherit from ModelProtocol.

Notes

Cannot be instantiated on its own. Can only be used as a parent class to create custom canonical models. Subclasses must override the abstract call() method and must be defined with a specific stimulus type and its matching tensor-holding type. Do not override __call__(); it returns a numpy.ndarray, while call() returns a backend tensor.

Inside call(), invoke submodels through their call() as well, not through the user-facing __call__().

Examples

Create a canonical model that combines a Gaussian2DPRFTuning and a PRFStimulusEncoder. The parameter_names property automatically aggregates the unique parameter names from all submodels.

>>> import pandas as pd
>>> from prfmodel.examples import load_2d_prf_bar_stimulus
>>> from prfmodel.stimuli import PRFStimulus, PRFStimulusTensors
>>> from prfmodel.models.prf import Gaussian2DPRFTuning, PRFStimulusEncoder
>>> class CanonicalPRFModel(BaseCanonical[PRFStimulus, PRFStimulusTensors]):
...     def call(self, stimulus, parameters, regressors=None):
...         response = self.models["prf_model"].call(stimulus, parameters)
...         return self.models["encoding_model"].call(stimulus, response, parameters)
>>> model = CanonicalPRFModel(
...     prf_model=Gaussian2DPRFTuning(),
...     encoding_model=PRFStimulusEncoder(),
... )
>>> model.parameter_names
['mu_y', 'mu_x', 'sigma']
>>> stimulus = load_2d_prf_bar_stimulus()
>>> params = pd.DataFrame({"mu_y": [0.0, 1.0], "mu_x": [1.0, 0.0], "sigma": [1.0, 1.5]})
>>> resp = model(stimulus, params)
>>> print(resp.shape)  # (num_units, num_frames)
(2, 170)
__call__(stimulus: S, parameters: pandas.DataFrame, regressors: pandas.DataFrame | None = None, dtype: str | None = None) → numpy.ndarray

Predict a canonical model response to a stimulus.

This is the public entry point; subclasses implement call() instead. Use call() when a backend tensor is required, for example inside a fitter or another model’s call().

Parameters:
  • stimulus (Stimulus) – Stimulus object.

  • parameters (pandas.DataFrame) – Dataframe with columns containing different model parameters and rows containing parameter values for different units.

  • regressors (pandas.DataFrame, optional) – Regressor design data. Required when the canonical model has a regressors model configured. A single data frame with shape (num_frames, num_regressors) whose columns cover the names required by every configured regressor model. Extra columns are ignored.

  • dtype (str, optional) – The dtype of the prediction result. If None (the default), uses the dtype from prfmodel.utils.get_dtype().

Returns:

The predicted model response with shape (num_units, num_frames) and dtype dtype.

Return type:

numpy.ndarray

Raises:

ValueError – If parameters is missing one or more of parameter_names.

abstractmethod call(stimulus: T, parameters: prfmodel.utils.TensorFrame, regressors: prfmodel.utils.TensorFrame | None = None) → prfmodel.typing.Tensor

Predict a canonical model response from tensors.

Parameters:
Returns:

The predicted model response with shape (num_units, num_frames) and dtype dtype.

Return type:

Tensor

Notes

Implementations must be traceable by a backend compiler, and must reach submodels through their call() rather than through __call__(). See BaseTuning.call().

check_parameter_names(parameters: pandas.DataFrame) → None

Check that required parameter names are supplied.

Parameters:

parameters (pandas.DataFrame) – Dataframe with columns containing different model parameters and rows containing parameter values for different units.

Raises:

ValueError – When a parameter name in the parameter_names attribute is not a column in parameters.

check_parameter_values(parameters: pandas.DataFrame) → None

Check that the parameter values lie inside the domain the model is defined on.

Parameters:

parameters (pandas.DataFrame) – Dataframe with columns containing different model parameters and rows containing parameter values for different units.

Raises:

ValueError – When a parameter that must be > 0 is zero or negative.

get_consumed_parameter_names(parameters: pandas.DataFrame) → list[str]

Return the parameter names this model and its submodels read from parameters.

Parameters:

parameters (pandas.DataFrame) – Dataframe with columns containing different model parameters and rows containing parameter values for different units.

Returns:

Names of the parameters this model and its submodels read from parameters.

Return type:

list of str

property models: dict[str, ModelProtocol | None]

A dictionary with the named submodels.

Parameters:

models (dict of ModelProtocol) – Named submodels.

Raises:

TypeError – When a submodel does not inherit from ModelProtocol.

property parameter_names: list[str]

A list with names of unique parameters that are used by the submodels.