spacr.regression_backends

Report which regression backends are available in this environment.

spacr.regression_spec says what the backends are – pure data, no imports. This module is the only place that asks the environment about them: is the package installed, is there a CUDA device, and can this backend fit the selected regression_type? Each disabled entry includes its reason; an inapplicable control is never hidden or silently substituted.

The availability probe does not import torch while a settings panel is being built. It inspects driver device nodes unless torch is already loaded, then spacr.mixed_gpu.resolve_device() performs the definitive fit-time check.

Installing optional backends

Three optional backends cannot be enabled by pressing Install, so this section explains why and what to do instead. It is written here rather than only in INSTALL_RECIPES because docs/source/api is built by sphinx-autoapi from this source, and autoapi publishes a module docstring verbatim while it renders a dict as a truncated repr. The two copies cannot drift: test_the_module_docstring_carries_every_command_the_gui_shows asserts that every command in INSTALL_RECIPES appears below.

pymer4 / lme4 needs R. It is an interface to R’s lme4, not a reimplementation. The pymer4 0.9.2 wheel does not declare its runtime dependencies, although its modules import polars and rpy2. Install the Python dependencies and R packages explicitly:

conda install -c conda-forge r-base
R -e 'install.packages(c("lme4","lmerTest"), repos="https://cloud.r-project.org")'
pip install rpy2 polars
pip install pymer4

This is a heavier ask than the other backends: a second language runtime, its own package library and a compiled bridge between them.

cuML needs a different environment. cuml-cu12 26.8.0 declares requires_python >= 3.11 and its recent wheels are cp311 only (25.10, 25.12 and 26.2 shipped cp310-cp313; 26.4, 26.6 and 26.8 ship cp311 alone – the window is narrowing):

conda create -n spacr-gpu python=3.11
conda activate spacr-gpu
pip install spacr
pip install cuml-cu12

Use a separate environment because cuML has narrower Python and CUDA wheel compatibility than spaCR’s core installation. Its coordinate-descent results may also differ from another implementation at the same alpha; treat it as a backend choice, not only a speed switch.

numpyro and gpytorch install cleanly but produce different outputs. numpyro samples a posterior with NUTS and gpytorch fits a Gaussian process; neither produces the point estimates and standard errors statsmodels does, so they are not faster replacements for it:

pip install numpyro
pip install --upgrade 'jax[cuda12]'
pip install gpytorch

Functions

availability_entries(→ list)

Every backend as a panel entry, in panel order.

availability_entry(→ dict)

One backend as the shared hover panel wants it.

backend_choices(→ list)

The combo's option strings -- the labels, in panel order.

backend_install_offer(name[, regression_type])

What pressing Install on a greyed-out backend entry should do.

backend_label(→ str)

The combo entry for a backend -- always suffixed (CPU)/(GPU).

backend_menu(→ list)

Every backend in panel order, each with its status.

backend_status(→ dict)

Whether a backend is choosable right now, and the reason if not.

backend_supports(→ bool)

Return whether name can fit regression_type.

cuda_present_without_importing_torch(→ bool)

Return whether a CUDA device is present, without importing torch.

describe_backends(→ str)

The text the model box shows: every backend, briefly, with its link.

describe_install_recipes(→ str)

Every recipe in INSTALL_RECIPES, in panel order.

install_recipe(→ str)

The written recipe for making name available, or ''.

package_installed(→ bool)

Return whether a backend's package is importable, without importing it.

resolve_backend_name(→ str)

The canonical backend name for whatever a panel or a CSV posted.

Module Contents

spacr.regression_backends.availability_entries(regression_type=None) → list[source]

Every backend as a panel entry, in panel order.

spacr.regression_backends.availability_entry(name, regression_type=None) → dict[source]

One backend as the shared hover panel wants it.

The panel (spacr.qt.widgets.availability_panel) takes a mapping so that neither of its two callers has to import Qt to build one, and so that this module does not import torch or PySide6.

Parameters:

name – backend key, label, or alias represented by the entry.

Returns:

{key, title, reason, url, offer, enabled}.

spacr.regression_backends.backend_choices() → list[source]

The combo’s option strings – the labels, in panel order.

spacr.regression_backends.backend_install_offer(name, regression_type=None)[source]

What pressing Install on a greyed-out backend entry should do.

The environment is checked before spaCR’s own wiring, so the message first names what the user can change on their machine (“cuML needs Python 3.11 and this is 3.10”) rather than what only spaCR can change (“spaCR routes no fit through it yet”).

Parameters:
  • name – a backend name or label.

  • regression_type – what the panel currently asks to fit. Used only for the message, never to decide installability – a family mismatch is fixed by choosing another family, not by installing anything.

Returns:

a spacr.updater.InstallOffer.

spacr.regression_backends.backend_label(name) → str[source]

The combo entry for a backend – always suffixed (CPU)/(GPU).

Parameters:

name – backend key, label, or alias to resolve.

spacr.regression_backends.backend_menu(regression_type=None) → list[source]

Every backend in panel order, each with its status.

This is what a combo box is built from: the entries are all present, in one order, and the disabled ones carry their own reason.

spacr.regression_backends.backend_status(name, regression_type=None) → dict[source]

Whether a backend is choosable right now, and the reason if not.

Parameters:
  • name – backend name or label.

  • regression_type – what the user is asking it to fit. None skips the compatibility half of the question.

Returns:

{name, label, device, enabled, reason, short_reason, url, summary, cost, differs, pip}. reason is '' when enabled – a disabled entry always carries the sentence that says why, and it is written to be shown on the control, not logged.

short_reason is the same refusal at combo-entry length. Qt shows an item tooltip lazily and only while the popup is open, so the short form is placed in the entry’s own text and in the box under it.

spacr.regression_backends.backend_supports(name, regression_type) → bool[source]

Return whether name can fit regression_type.

regression_type=None means “auto-selected from the response”, which only the default backend can answer, since the choice is made after the data is read.

Parameters:
  • name – backend key, label, or alias to inspect.

  • regression_type – requested model family, or None for automatic family selection.

spacr.regression_backends.cuda_present_without_importing_torch() → bool[source]

Return whether a CUDA device is present, without importing torch.

See the module docstring for why this is a driver probe rather than torch.cuda.is_available().

spacr.regression_backends.describe_backends(regression_type=None, html: bool = True, selected=None, compact: bool = False) → str[source]

The text the model box shows: every backend, briefly, with its link.

The text describes every available package briefly with a link to its API and, where a backend cannot agree with statsmodels by construction, says what differs.

Parameters:
  • regression_type – greys the entries that cannot fit it, and their reason is included.

  • html – emit <a href=...> links (the Qt backend box renders rich text). False gives plain text with the URL inline, for a log.

  • selected – the backend the panel currently holds. In compact mode it is the one written out in full.

  • compact –

    one line per backend instead of one paragraph.

    The full text is too long for the one-page settings panel. Compact keeps every backend and every API link and drops, for the backends not selected, the measured cost and the second and later sentences of each summary. The selected backend is written out in full, cost and caveat included.

Returns:

one paragraph per backend, or one line per backend under compact with the selected one expanded above them.

spacr.regression_backends.describe_install_recipes(html: bool = False) → str[source]

Every recipe in INSTALL_RECIPES, in panel order.

Packages that cannot be installed directly need recipes on the API page. This renders them in one block so a caller – the documentation build, a log, or the box under the backend combo – can show all of them without knowing which backends have one.

spacr.regression_backends.install_recipe(name) → str[source]

The written recipe for making name available, or ''.

Parameters:

name – a backend name or label.

Returns:

the entry in INSTALL_RECIPES, or an empty string for a backend that needs no recipe because pip install is the whole story.

spacr.regression_backends.package_installed(name) → bool[source]

Return whether a backend’s package is importable, without importing it.

find_spec on a package that is not there raises ModuleNotFoundError for a missing parent, which is a different question from the one being asked, so it is caught.

Parameters:

name – import package name, or an empty value for a core backend.

spacr.regression_backends.resolve_backend_name(value) → str[source]

The canonical backend name for whatever a panel or a CSV posted.

Accepts the canonical name ('torch'), the label the combo shows ('torch (GPU)'), any casing, and None/'' for “not chosen”.

The label is accepted as a spelling: the design requires every entry to read (CPU) or (GPU), and both GUIs render a combo’s options verbatim – so the option strings are the labels and the value posted back is a label. Normalising here is what keeps the settings CSV written with the short canonical name.

Parameters:

value – what was posted.

Returns:

a key of REGRESSION_BACKENDS.

Raises:

ValueError – on a name no backend answers to. The message names the valid ones.

Nested helpers

backend_status.refuse(reason, short)

Disable and explain the captured backend status.

Parameters:
  • reason – full user-facing explanation of the refusal.

  • short – combo-entry-length form of the same explanation.

Returns:

the captured status mapping after setting enabled false and storing both explanations.

spacr/regression_backends.py:220