Skip to content

Embedding BIWT

BIWT is designed to be embedded. It ships a Qt widget and a two-type data contract, and deliberately knows nothing about the application hosting it.

The whole interface

from biwt.gui.walkthrough import create_biwt_widget
from biwt.types import BiwtInput, BiwtResult, DomainSpec

widget = create_biwt_widget(
    BiwtInput(preferred_domain=DomainSpec(xmin=-500, xmax=500, ymin=-500, ymax=500)),
    on_complete=my_handler,      # called with a BiwtResult
)

That is the entire surface. Everything else in biwt is internal and free to change.

biwt.__version__ is also public. The widget shows it on its own home screen, which is the only place a user can see it when BIWT is embedded as a tab.

Two rules

1. The host owns all file I/O

BIWT never writes to disk. It hands you a BiwtResult in memory and your on_complete does whatever your application does with output — write it, show a save dialog, keep it in memory, push it to a server.

2. The widget does not close itself

When the workflow finishes, BIWT calls on_complete and stops. It does not hide, close, or reset. If your application should dismiss the tab, do it in your handler.

Importing a new file resets the session, so the same widget instance can be reused for another dataset.

3. The application icon stays yours

BIWT marks its own widget and step windows, and never calls QApplication.setWindowIcon — that is one icon per process and taking it would replace yours. On macOS, where the Dock shows only that process-level icon, BIWT's per-window icons are invisible and yours is what a user sees.

Optional inputs worth wiring up

BiwtInput has one field beyond the domain: host_cell_type_names, the cell types your app already defines, so imported types can line up with them instead of duplicating them. At the rename step BIWT offers a match as placeholder text — a case-insensitive exact match first, else the first host name the matcher accepts. It is a hint, not a ranking. Two caveats: the placeholder only renders in an empty field, so it sits hidden behind the pre-filled original name; and pass nothing and there are no suggestions at all. The names are also offered at the cell-templates step, where assigning one comes back marked HOST_SOURCE.

Everything else goes to create_biwt_widget, because none of it is state that changes between runs:

Argument Effect
host_name Your application's name, used in the domain editor UI ("Use Studio Domain"). Defaults to "Host", which looks unfinished.
name_matches Your own (str, str) -> bool for "do these name the same cell type?", replacing BIWT's default (and name_match_cutoff) for both rename suggestions and template pre-selection. See templates and name matching.
cell_template_paths TOML files of cell templates. BIWT ships none, so these seed the library offered at the cell-templates step — listed on the landing screen, where the user can add more or drop yours. See templates and name matching.

If your host outlives one walkthrough, pass a callable returning a BiwtInput rather than an instance: BIWT calls it at each import, so these fields do not freeze at build time. See when BIWT reads its input.

Degrading gracefully when BIWT is absent

BIWT is an optional dependency for most hosts. The conventional pattern:

try:
    from biwt.gui.walkthrough import create_biwt_widget
    from biwt.types import BiwtInput, DomainSpec
    HAVE_BIWT = True
except ImportError:
    HAVE_BIWT = False

...then branch on HAVE_BIWT when building the UI, and tell the user how to install it if they reach for the feature.

  • The API contractBiwtInput and BiwtResult field by field, including what is reserved for future use.
  • Templates and name matching — the two jobs BIWT hands back to you: supplying a template library and deciding when two names mean the same cell type.
  • PhysiCell Studio — a complete worked bridge, and the conventions it established.
  • API reference — generated signatures and docstrings.