spaCR plugin SDK¶
The plugin SDK lets a separately installed Python package add assays,
importers, analysis utilities, settings panels, model-zoo entries and report
sections without editing spaCR. Plugins use Python package entry points, so
spaCR discovers them at startup and keeps them available to both the Qt
application and spacr-run.
The current SDK API is 1.0. Only the major version controls
compatibility: a plugin declaring API 1.x works with spaCR’s 1.x SDK.
A malformed or failing plugin is isolated and reported by
spacr-plugins doctor; it cannot replace a built-in module or prevent spaCR
from starting.
Minimal plugin¶
Declare the entry point in the plugin package’s pyproject.toml:
[project.entry-points."spacr.plugins"]
my_assays = "my_spacr_plugin:plugin"
Then expose a manifest:
from spacr.plugins import AppContribution, SpacrPlugin
plugin = SpacrPlugin(
name="My laboratory assays",
version="0.1.0",
api_version="1.0",
apps=(
AppContribution(
key="organelle_contact",
name="Organelle Contact",
description="Measure contact sites from a processed plate.",
kind="assay",
section="results",
stage="alpha",
entrypoint="my_spacr_plugin.pipeline:run",
defaults="my_spacr_plugin.pipeline:default_settings",
categories={
"Input": ("src", "table"),
"Detection": ("distance_px", "min_area"),
"Output": ("save_figures",),
},
tooltips={
"src": "Processed spaCR plate folder.",
"distance_px": "Maximum membrane-to-membrane distance.",
},
labels={"distance_px": "Contact distance (px)"},
docs_url="https://example.org/my-plugin/api/",
aliases=("contacts",),
validator="my_spacr_plugin.pipeline:validate",
drop_handler="my_spacr_plugin.qt:PlateDropHandler",
requires=("src — a processed spaCR plate",),
writes=("<src>/measurements/contact_sites.csv",),
),
),
)
The pipeline callable receives one settings dictionary. The defaults callable
must accept an optional settings dictionary and return a dictionary. A
validator returns spacr.validate.Problem objects (or equivalent
mappings). All processing still runs through spaCR’s worker, journal,
cancellation and reproducibility paths.
Settings and custom screens¶
The generic settings screen is preferred: declare categories, tooltips
and optional labels on spacr.plugins.AppContribution. The UI then
provides the normal Run/Stop controls, console, progress reporting, API links,
drag-and-drop fallback and remote-submit action.
For a layout the generic screen cannot express, set screen_factory to a
module:callable. The callable is invoked as factory(app_key=...) and
must return a PySide6.QtWidgets.QWidget. A custom drop_handler must be
a subclass of spacr.qt.dnd_handlers.DropHandler. icon may name a
spaCR semantic icon or an absolute image path; otherwise the normal puzzle
piece fallback is used.
Model providers¶
Add a spacr.plugins.ModelProviderContribution. Its zero-argument
callable returns an iterable of spacr.model_zoo.ModelEntry objects or
the mappings accepted by spaCR’s JSON model catalogue.
from spacr.plugins import ModelProviderContribution
ModelProviderContribution(
key="lab_models",
provider="my_spacr_plugin.models:catalogue",
)
Providers must be read-only during catalogue discovery. Downloads remain an
explicit Model Zoo action. A provider exception is shown by
spacr-plugins doctor and built-in models remain available.
Report sections¶
A spacr.plugins.ReportSectionContribution builder receives a
read-only spacr.plugins.ReportContext and returns a
spacr.report.Section:
from spacr.plugins import ReportSectionContribution
from spacr.report import Section
def build_contacts(context):
return Section(
key="organelle_contacts",
title="Organelle contacts",
body_html="<p>Contact-site results.</p>",
text_lines=["Contact-site results."],
)
contact_report = ReportSectionContribution(
key="organelle_contacts",
title="Organelle contacts",
builder="my_spacr_plugin.report:build_contacts",
after="statistics",
)
If the builder raises, the generated report contains a visible problem chapter with the exception instead of silently omitting the section.
Translations¶
SpacrPlugin.translations maps spaCR language codes to English-source /
translated-text mappings. Supported codes are sv, de, es,
zh_CN, pt, hi, ko, is and fr. Missing strings fall
back to English.
Development and diagnostics¶
During local development only, point SPACR_PLUGIN_MODULES at a
comma-separated list of module:attribute references. Set
SPACR_DISABLE_PLUGINS=1 to start spaCR without third-party plugins.
SPACR_PLUGIN_MODULES=my_spacr_plugin:plugin spacr-plugins list
spacr-plugins doctor
spacr-plugins doctor --json
The public SDK lives in spacr.plugins; the diagnostics command lives in
spacr.cli_plugins.
API reference¶
Versioned extension SDK for third-party spaCR plugins.
Plugins are ordinary Python distributions exposing one entry point in the
spacr.plugins group. The entry point may resolve to a
SpacrPlugin, a mapping accepted by plugin_from_mapping(), or a
zero-argument factory returning either. Discovery is lazy, deterministic and
failure-isolated: one malformed plugin is recorded in diagnostics()
without preventing spaCR or the remaining plugins from loading.
For editable/local development, SPACR_PLUGIN_MODULES may contain a
comma-separated list of module or module:attribute references.
Installed plugins should always use package entry points instead.
Plugins and assay recipes can also be installed from a catalogue, a JSON
file listing each entry’s version, author and licence. A catalogue plugin is
installed into its own folder under ~/.spacr/plugins (or
SPACR_PLUGIN_HOME), together with the libraries it asks for, so it never
replaces or upgrades a package spaCR itself uses; it is discovered like any
other plugin until it is uninstalled.
Setting SPACR_DISABLE_PLUGINS to 1, true, yes or on
(case-insensitively) skips discovery entirely, so no plugin loads from either
source.
- class spacr.plugins.AppContribution(key: str, name: str, description: str, entrypoint: str, defaults: str, section: str = 'results', stage: str = 'alpha', kind: str = 'analysis', categories: ~typing.Mapping[str, ~typing.Sequence[str]] = <factory>, tooltips: ~typing.Mapping[str, str] = <factory>, labels: ~typing.Mapping[str, str] = <factory>, docs_url: str = '', aliases: ~typing.Tuple[str, ...] = (), validator: str = '', screen_factory: str = '', drop_handler: str = '', icon: str = '', requires: ~typing.Tuple[str, ...] = (), writes: ~typing.Tuple[str, ...] = (), call_style: str = 'settings')[source]
Bases:
objectOne runnable GUI/headless application contributed by a plugin.
Discovery rejects the contribution with
ValueErrorwhensection,stage,kindorcall_stylefalls outside the fixed vocabulary listed below, whenkeydoes not match^[a-z][a-z0-9_]{1,63}$, or when any non-emptymodule:callablereference is malformed.- Variables:
key – identifier the CLI accepts and the GUI registers under; must match
^[a-z][a-z0-9_]{1,63}$. Reusing another plugin’s key fails that plugin’s load; colliding with a built-in app skips the contribution and records a diagnostic.name – human-readable title shown in the sidebar and screen header; cannot be blank.
description – one-line blurb used as the app intro and the
spacr-run --listsummary; cannot be blank.entrypoint –
"module:callable"reference to the callable that does the work.defaults –
"module:callable"reference to a helper returning the settings dictionary; called with{}and retried with no argument.section – sidebar group; one of
"core","data","models","results"or"toxo".stage – maturity annotation; one of
"alpha","beta"or"stable".kind – what the app is; one of
"assay","importer","analysis"or"utility".categories – settings-screen tabs, mapping a tab name to the setting keys it holds; empty means the generic ungrouped layout.
tooltips – hover text per setting key.
labels – display label per setting key, overriding the generated one.
docs_url – address the settings screen’s API link opens.
aliases – extra names the CLI and
spacr.validateresolve tokey.validator – optional
"module:callable"reference to a callable taking the settings dict and returningspacr.validate.Problemobjects or equivalent mappings.screen_factory – optional
"module:callable"reference to a factory returning aQWidget, replacing the generic settings screen; it is always invoked asfactory(app_key=...)and so must accept that keyword.drop_handler – optional
"module:callable"reference to aspacr.qt.dnd_handlers.DropHandlersubclass.icon – absolute image path, or the name of a spaCR semantic icon; empty falls back to the puzzle-piece icon.
requires – settings the user must supply, phrased for a human.
writes – what the app leaves on disk.
call_style –
"settings"forfn(settings_dict);"folder"for a callable taking a bare path.
- class spacr.plugins.ModelProviderContribution(key: str, provider: str)[source]
Bases:
objectImmutable record naming a plugin’s model-zoo provider.
- Parameters:
key – identifier for the provider; must match
^[a-z][a-z0-9_]{1,63}$and be unique across all loaded plugins.provider –
"module:callable"reference string – not the callable itself – resolved at catalogue time to a zero-argument callable returning model-zoo entries or entry mappings.
- class spacr.plugins.PluginDiagnostic(plugin: str, severity: str, message: str, exception: str = '')[source]
Bases:
objectOne discovery or contribution error visible to users and logs.
- Parameters:
plugin – entry-point or manifest name identifying the plugin that could not be loaded.
severity – diagnostic level, such as
"error"or"warning".message – concise user-facing account of the failed operation.
exception – captured exception text with the technical cause; empty when no exception accompanied the diagnostic.
- class spacr.plugins.ReportContext(src: Any, artifacts: Mapping[str, Any], runs: Tuple[Mapping[str, Any], ...], options: Mapping[str, Any])[source]
Bases:
objectRead-only inputs passed to plugin report-section builders.
- Parameters:
src – source folder or object from which the core report is built.
artifacts – named core report artifacts available for reuse by the plugin section.
runs – immutable sequence of recorded run summaries associated with the report source.
options – report-generation options supplied by the caller.
- class spacr.plugins.ReportSectionContribution(key: str, title: str, builder: str, after: str = 'statistics')[source]
Bases:
objectImmutable record naming a builder that adds one report section.
spacr.report.collect_report()resolves and calls the builder, and substitutes a visible problem section if it fails.- Parameters:
key – stable section identifier; plugin validation requires
^[a-z][a-z0-9_]{1,63}$and discovery rejects duplicate contribution keys.title – fallback section heading used when the builder returns no title and when the builder fails; cannot be blank.
builder –
"module:callable"reference resolved at report collection to a callable takingReportContextand returning aspacr.report.Section.after – existing section key after which this section is inserted; an unmatched key appends it to the report.
- class spacr.plugins.SpacrPlugin(name: str, version: str, api_version: str = '1.0', apps: ~typing.Tuple[~spacr.plugins.AppContribution, ...] = (), model_providers: ~typing.Tuple[~spacr.plugins.ModelProviderContribution, ...] = (), report_sections: ~typing.Tuple[~spacr.plugins.ReportSectionContribution, ...] = (), translations: ~typing.Mapping[str, ~typing.Mapping[str, str]] = <factory>)[source]
Bases:
objectValidated plugin manifest returned by a
spacr.pluginsentry point.- Parameters:
name – human-readable plugin name used in diagnostics and discovery output.
version – version of the plugin distribution, reported to users without being interpreted by spaCR.
api_version – plugin SDK version the manifest targets; its major version must match
PLUGIN_API_VERSION.apps – runnable applications the plugin adds to the GUI and headless registry.
model_providers – providers that extend the model-zoo catalogue.
report_sections – builders that insert plugin-owned sections into generated reports.
translations – locale-to-message mappings that translate the plugin’s own visible strings.
- apps: Tuple[AppContribution, ...] = ()[source]
- model_providers: Tuple[ModelProviderContribution, ...] = ()[source]
- report_sections: Tuple[ReportSectionContribution, ...] = ()[source]
- spacr.plugins.diagnostics() Tuple[PluginDiagnostic, ...][source]
Return discovery and runtime contribution failures.
- spacr.plugins.discover_plugins() Tuple[SpacrPlugin, ...][source]
Return every valid discovered plugin in deterministic order.
Returns an empty tuple, with no diagnostic recorded, when
SPACR_DISABLE_PLUGINSis set to1,true,yesoron(case-insensitively): nothing is imported at all. The result is cached;reload_plugins()discards the cache and discovers again.
- spacr.plugins.get_app(key: str) AppContribution | None[source]
Return a contributed app by key, or
None.- Parameters:
key –
keyof an installed plugin’sAppContribution; converted withstr()before the registry lookup.
- spacr.plugins.load_object(reference: str) Any[source]
Import and return
module:attribute(nested attributes supported).- Parameters:
reference – string of the form
"package.module:attribute"; the attribute part may be dotted to reach nested objects. Anything else raisesValueError.
- spacr.plugins.model_providers() Tuple[Tuple[str, ModelProviderContribution], ...][source]
Return
(plugin_name, provider)model-zoo contributions.
- spacr.plugins.plugin_apps() Tuple[AppContribution, ...][source]
Return all contributed applications.
- spacr.plugins.plugin_from_mapping(value: Mapping[str, Any]) SpacrPlugin[source]
Validate a mapping and return its immutable
SpacrPlugin.- Parameters:
value – manifest mapping whose keys are the
SpacrPluginfields;apps,model_providersandreport_sectionsmay hold mappings or contribution objects, andtranslationsmust map language codes to string mappings. A non-mapping raisesTypeError.
- spacr.plugins.record_diagnostic(plugin: str, message: str, exception: Any = '', severity: str = 'error') None[source]
Record a model/report/runtime plugin failure without aborting spaCR.
- Parameters:
plugin – name of the plugin that failed, stored on the
PluginDiagnosticand written to the log.message – user-facing account of the failed operation.
- spacr.plugins.reload_plugins() Tuple[SpacrPlugin, ...][source]
Clear the discovery cache and discover again (primarily for tests/dev).
- spacr.plugins.report_sections() Tuple[Tuple[str, ReportSectionContribution], ...][source]
Return
(plugin_name, section)report contributions.