spacr.qt.model_install

Install a model from inside spaCR, without freezing the window.

Two kinds of thing are installed from a click: a segmentation backend, which is a Python package added to the running environment with pip (DINOCell and SAMCell, spacr.model_zoo.INSTALLABLE_BACKENDS), and a Cellpose checkpoint from the model zoo, which is a file downloaded and verified by spacr.model_zoo.install(). Both can take minutes, so both run off the GUI thread: PackageInstall runs pip as a child process watched from the event loop, and CheckpointDownload runs the zoo’s download on a worker thread. Each reports progress while it runs and a single result when it ends, and a failure is a message rather than an exception, so a failed install leaves the screen that started it working.

SegmentationBackendCombo is the Mask module’s choice of segmentation backend: every backend is listed, one that is not installed is greyed, and choosing it offers to install it and selects it once installed. Make Masks offers the same backends, in the same way, in its Live magnifier Mode box.

Classes

CheckpointDownload

Download and verify one model-zoo checkpoint off the GUI thread.

PackageInstall

One pip install in a child process, watched from the event loop.

SegmentationBackendCombo

The Mask module's segmentation_backend: every backend, always.

SpotDetectorCombo

The OPS module's ops_spot_detector: spaCR's own, SpotNet or

Functions

backend_row(→ Optional[Tuple[str, str, str, str]])

The backend_rows() row for one backend.

backend_rows(→ List[Tuple[str, str, str, str]])

Every installable segmentation backend, as the model zoo lists it.

can_install_packages(→ bool)

Whether this build of spaCR can add a package to itself.

confirm_backend_install(→ bool)

Ask before installing a backend, and say what the install risks.

human_bytes(→ str)

A byte count a person can read, such as '1.2 GB'.

is_importable(→ bool)

Whether module can be imported here, without importing it.

pip_command(→ List[str])

The command that installs requirement into this environment.

Module Contents

class spacr.qt.model_install.CheckpointDownload(entry: Any, folder: str, parent: PySide6.QtCore.QObject | None = None, *, unverified: bool = False)[source]

Bases: PySide6.QtCore.QObject

Download and verify one model-zoo checkpoint off the GUI thread.

Goes through spacr.model_zoo.install(), so the file is checked against its published digest before it is put where it belongs, and a failure leaves the destination as it was. Like PackageInstall it keeps itself alive until its thread has ended, so the widget that started it can be deleted without taking a running thread with it.

Parameters:
  • entry – the zoo’s spacr.model_zoo.ModelEntry.

  • folder – where the checkpoint goes.

  • parent – owner; give it none, for the reason above.

  • unverified – accept an entry that publishes no checksum. Only for an entry that has none, and only after the user has said so.

Prepare the download without starting it.

Parameters:
  • entry – the zoo entry.

  • folder – destination folder.

  • parent – owner.

  • unverified – skip the checksum requirement.

cancel() → None[source]

Stop the download at its next chunk, and report it as cancelled.

Returns at once: the thread ends on its own, and the partial file is removed by spacr.model_zoo.fetch().

is_running() → bool[source]

Whether the download thread is still running.

start() → bool[source]

Start the download on its own thread.

Returns:

True once the thread is running.

wait(timeout_ms: int = 10000) → bool[source]

Block until the download thread has ended.

Parameters:

timeout_ms – how long to wait.

Returns:

True when it has ended.

class spacr.qt.model_install.PackageInstall(requirement: str, parent: PySide6.QtCore.QObject | None = None, *, command: List[str] | None = None)[source]

Bases: PySide6.QtCore.QObject

One pip install in a child process, watched from the event loop.

Nothing waits on the process: its output arrives through progressed as it is written, and finished fires once, with whether it worked and what to tell the user. A process that cannot start finishes at once, unsuccessfully.

Give it no parent. It keeps itself alive while pip runs, because a child process deleted with its owner is killed, and pip killed half way through an install can leave the environment broken.

Parameters:
  • requirement – what to install, for example 'spacr[samcell]'.

  • parent – owner, if the caller insists on one.

  • command – the program and arguments to run instead of pip_command(), for a caller that needs a different installer.

Prepare the install without starting it.

Parameters:
  • requirement – what to install.

  • parent – owner.

  • command – a replacement for pip_command().

cancel() → None[source]

Stop the installer, and report it as not having worked.

is_running() → bool[source]

Whether the installer is still running.

output() → str[source]

Everything the installer has written so far.

start() → bool[source]

Start the installer.

Returns:

False when it could not be started, in which case finished has already said so.

class spacr.qt.model_install.SegmentationBackendCombo(default: Any = 'cellpose', parent: PySide6.QtWidgets.QWidget | None = None)[source]

Bases: PySide6.QtWidgets.QComboBox

The Mask module’s segmentation_backend: every backend, always.

Cellpose is always first and always installed. DINOCell and SAMCell are listed whether or not their packages are here; one that is missing is greyed, with a tooltip saying so, and choosing it asks before running pip in the background. The box goes back to the backend it was on while the install runs, so the setting never names a backend that cannot load, and selects the new backend once it is installed.

The stored value of each row is the setting’s own value ('cellpose', 'dinocell', 'samcell'), so the settings form reads and writes it as it reads and writes any other dropdown.

Parameters:
  • default – the value to start on.

  • parent – parent widget.

List the backends and select default.

Parameters:
  • default – the value to start on.

  • parent – parent widget.

missing() → List[str][source]

The backends listed but not installed, by name.

Installed means “can segment now”, which is either an environment of its own under ~/.spacr/backends or – the older arrangement, still honoured – the package importable in spaCR’s own environment. spacr._segmentation_backends._backend_state() answers both with file checks and no import, so this stays cheap enough to ask while the box is being built.

offer_install(name: str) → bool[source]

Install backend name into an environment of its own.

THE DESTINATION CHANGED, NOT THE GESTURE. A greyed row installs itself when it is chosen. It used to run pip install "spacr[<backend>]" against the environment spaCR is running in; each backend now gets an isolated environment, so the install goes through the Model Zoo’s own dialog instead: off the GUI thread, with progress and Cancel, into ~/.spacr/backends/<name>, and spaCR’s own environment is never changed.

Parameters:

name – a backend name.

Returns:

True when the backend can segment afterwards.

refresh_installed() → None[source]

Grey the backends that are not installed, and only those.

setCurrentText(text: Any) → None[source]

Select the row whose caption, or stored value, is text.

Parameters:

text – a caption such as 'SAMCell' or a value such as 'samcell'; anything else leaves the selection alone.

class spacr.qt.model_install.SpotDetectorCombo(default: Any = 'native', parent: PySide6.QtWidgets.QWidget | None = None, readiness: Callable[[], Tuple[bool, str]] | None = None, spotiflow_readiness: Callable[[], Tuple[bool, str]] | None = None)[source]

Bases: PySide6.QtWidgets.QComboBox

The OPS module’s ops_spot_detector: spaCR’s own, SpotNet or Spotiflow.

spaCR’s own detector is first, the default and always usable. SpotNet and Spotiflow are listed whether or not they can run; when one’s environment (or SpotNet’s DeepCell token) is missing its row is disabled and its tooltip says which. SpotNet’s tooltip states its non-commercial licence either way, because this box is where a person chooses it. A saved Spotiflow choice is kept even while its row is disabled or hidden, so the run receives it and says why it cannot run rather than detecting with another detector.

Parameters:
  • default – the value to start on, 'native', 'spotnet' or 'spotiflow'.

  • parent – parent widget.

  • readiness – () -> (ready, reason); SpotNet’s own check when None, a stand-in in tests.

  • spotiflow_readiness – the same for Spotiflow.

List the detectors, disable those that cannot run, select.

refresh() → Tuple[bool, str][source]

Enable SpotNet’s and Spotiflow’s rows only when each can run, and say why not.

Returns:

SpotNet’s (ready, reason).

setCurrentText(text: Any) → None[source]

Select the row whose caption or value is text, if usable.

Parameters:

text – a caption or stored value; a row that is not installed (disabled), or no match, leaves the selection alone, except Spotiflow’s, which is selected whatever its state.

spacr.qt.model_install.backend_row(name: str) → Tuple[str, str, str, str] | None[source]

The backend_rows() row for one backend.

Parameters:

name – a backend name such as 'samcell'.

Returns:

the row, or None for a name the zoo does not list.

spacr.qt.model_install.backend_rows() → List[Tuple[str, str, str, str]][source]

Every installable segmentation backend, as the model zoo lists it.

Returns:

(name, label, pip requirement, import name) per backend, in the zoo’s order.

spacr.qt.model_install.can_install_packages() → bool[source]

Whether this build of spaCR can add a package to itself.

A frozen application has no pip to run: its interpreter is the application binary.

Returns:

False inside a frozen build.

spacr.qt.model_install.confirm_backend_install(parent: PySide6.QtWidgets.QWidget | None, label: str, requirement: str) → bool[source]

Ask before installing a backend, and say what the install risks.

Parameters:
  • parent – the widget the question belongs to.

  • label – the backend’s name, for example 'SAMCell'.

  • requirement – what is passed to pip install.

Returns:

True when the user agreed.

spacr.qt.model_install.human_bytes(size: Any) → str[source]

A byte count a person can read, such as '1.2 GB'.

Parameters:

size – bytes.

Returns:

the text, or '' for an unknown (zero) size.

spacr.qt.model_install.is_importable(module: str) → bool[source]

Whether module can be imported here, without importing it.

Parameters:

module – the top-level import name.

Returns:

True when Python can find it.

spacr.qt.model_install.pip_command(requirement: str) → List[str][source]

The command that installs requirement into this environment.

python -m pip with the interpreter spaCR is running on, so the package lands where this process imports from.

Parameters:

requirement – a pip requirement, for example 'spacr[samcell]'.

Returns:

the program followed by its arguments.