Metadata-Version: 2.4
Name: biwt
Version: 0.4.0
Summary: BioInformatics WalkThrough: import single-cell data and generate agent-based model initial conditions
Author-email: Daniel Bergman <dbergman1@som.umaryland.edu>, Daphnee Jobert <djobert@som.umaryland.edu>, Marwa Naji <mnaji2@jh.edu>, Jeanette Johnson <jjohn450@jhmi.edu>, Randy Heiland <heiland@iu.edu>, Paul Macklin <macklinp@iu.edu>
License: BSD-3-Clause
Project-URL: Homepage, https://github.com/drbergman-lab/biwt
Project-URL: Repository, https://github.com/drbergman-lab/biwt
Project-URL: Documentation, https://drbergman-lab.github.io/biwt/
Project-URL: Issues, https://github.com/drbergman-lab/biwt/issues
Keywords: PhysiCell,bioinformatics,single-cell,initial conditions,agent-based modeling
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.22
Requires-Dist: pandas>=1.4
Requires-Dist: tomli>=1.2; python_version < "3.11"
Provides-Extra: anndata
Requires-Dist: anndata>=0.9; extra == "anndata"
Provides-Extra: seurat
Requires-Dist: anndata>=0.9; extra == "seurat"
Requires-Dist: anndata2ri<2,>=1.1; extra == "seurat"
Requires-Dist: rpy2>=3.5; extra == "seurat"
Provides-Extra: gui
Requires-Dist: PyQt5>=5.15; extra == "gui"
Requires-Dist: matplotlib>=3.5; extra == "gui"
Provides-Extra: all
Requires-Dist: biwt[anndata,gui,seurat]; extra == "all"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.5; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
Requires-Dist: black>=24; extra == "docs"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-qt; extra == "dev"
Requires-Dist: biwt[anndata,gui]; extra == "dev"

# BIWT — BioInformatics WalkThrough

A guided wizard for importing single-cell bioinformatics data and generating initial conditions for agent-based models (ABMs). Designed as a standalone pip-installable package that can be embedded in any host application. Currently integrated with PhysiCell Studio.

## Installation

```bash
pip install biwt                    # core (CSV support only)
pip install "biwt[anndata]"         # + .h5ad support
pip install "biwt[seurat]"          # + .rds/.rda support (also needs R — see below)
pip install "biwt[gui]"             # + PyQt5 walkthrough UI
pip install "biwt[all]"             # everything
```

Development install (from a clone):

```bash
pip install -e ".[dev]"             # editable + test dependencies
```

`.rds` / `.rda` import needs a working R with `Seurat` and `SingleCellExperiment` in addition
to the pip extra. See the
**[installation guide](https://drbergman-lab.github.io/biwt/getting-started/installation/)**
for the conda recipe and a
[troubleshooting guide](https://drbergman-lab.github.io/biwt/getting-started/troubleshooting/)
for the R stack.

## Documentation

Full docs: **[drbergman-lab.github.io/biwt](https://drbergman-lab.github.io/biwt/)** — user
guide for every wizard step, worked recipes for Visium / scRNA-seq / spot-deconvolution data,
the host-integration contract, and a generated API reference.

Build them locally with:

```bash
pip install -e ".[docs]"
mkdocs serve
```

## Quick Start

```python
import sys
from PyQt5.QtWidgets import QApplication

from biwt.gui.theme import apply_light_palette
from biwt.gui.walkthrough import create_biwt_widget
from biwt.types import BiwtInput, DomainSpec

domain = DomainSpec(xmin=-500, xmax=500, ymin=-500, ymax=500, units="micron")
biwt_input = BiwtInput(preferred_domain=domain)

def on_complete(result):
    # result.coordinates is a DataFrame with columns: x, y, z, type
    result.to_csv("config/cells.csv")

app = QApplication(sys.argv)
apply_light_palette(app) 

widget = create_biwt_widget(biwt_input, on_complete=on_complete)
widget.show()

sys.exit(app.exec_())
```

## Running Tests

```bash
PYTHONPATH=src python -m pytest tests/ -v
```

## Package Structure

```
src/biwt/
  types.py              — Public API: DomainSpec, BiwtInput, BiwtResult
  core/
    data_loader.py      — Unified loader (.h5ad, .rds, .csv) → BiwtData
    domain.py           — Domain inference + coordinate column detection
    positioning.py      — Coordinate scaling + build_ic_dataframe
    cell_types.py       — Name-matching heuristics
    parameters/
      cell_templates.py — 29 PhysiCell cell-type XML templates
      xml_defaults.py   — Default PhysiCell XML scaffold
  gui/
    walkthrough.py      — Session state machine + Qt widget + step logic
    widgets.py          — Shared Qt widgets
    windows/            — One file per walkthrough step
tests/
  test_session.py       — 78 tests covering session logic end-to-end
  test_gui_smoke.py     — Headless Qt import-path and error-dialog tests
  test_positions_plot.py — Spatial placement / plot scaling tests
  fixtures/             — CSV test fixtures
scripts/
  make_screenshot_data.py — Synthetic Visium-like .h5ad for doc screenshots
docs/                   — MkDocs Material site (published to GitHub Pages)
  index.md
  getting-started/      — Install matrix, first walkthrough, R/Seurat troubleshooting
  guide/                — One page per wizard step, plus the domain editor
  recipes/              — Visium, non-spatial scRNA-seq, spot deconvolution
  integration/          — Host embedding: API contract + Studio bridge
  reference/            — mkdocstrings API reference
mkdocs.yml
```

## Key Design Decisions

- **No file I/O in BIWT.** The package returns `BiwtResult` in-memory; the host decides how to write.
- **Pure-Python session.** `WalkthroughSession` has no Qt dependencies. All Qt logic is in window classes.
- **Single source of truth for steps.** `_step_predicates(session)` defines step ordering. Tests import it directly.
- **CSV uses `type` header** (not `cell_type`) to match PhysiCell convention.
- **Domain units.** `DomainSpec.units` defaults to `"micron"` but supports other ABM frameworks.

## Implementation Status

### Completed

- [x] Data import: .h5ad, .rds/.rda/.rdata, .csv
- [x] Spatial coordinate detection (obsm, obs columns)
- [x] Pixel-coordinate fallback: recognize `imagecol`→x / `imagerow`→y (row-flipped) as a last-resort spatial source; domain reported in a generic `data unit` (no inferred unit name)
- [x] Spatial synthesis from obs columns (x/y/z or imagerow/imagecol → obsm["spatial"]) for CSV and AnnData/R, so the dim-reduction plot offers a Spatial view
- [x] Domain inference with priority chain (preferred > data_range > default)
- [x] Domain mismatch: two-tier detection (classify_domain_mismatch: "outside" / "small" / None)
- [x] DomainEditorDialog auto-triggered at positions window open (not import time)
- [x] Context-sensitive mismatch header; no header for manual "Domain Settings…" open
- [x] domain_accepted flag prevents re-trigger on back/forward navigation
- [x] Domain editor OK is gated on a usable domain: all six bounds must parse and `min < max` on every axis (a zero-width axis divides by zero in placement scaling); offending fields are highlighted and Cancel is never gated
- [x] Domain editor shows the live extents of the domain being edited
- [x] BiwtInput.domain_accepted + "Skip domain validation" checkbox bypass auto-check
- [x] Z-fields default to ±10 for 2D data in domain editor
- [x] Data-unit→host-unit scale factor in the domain editor: auto-detected Visium µm/pixel (`_extract_visium_microns_per_pixel`), editable, with each value shown in host units beside its parenthesized data-units mirror, synced by the factor, plus a reset-to-file button
- [x] Domain editor is an axis-major ruled grid — one row per axis (`X (width)`, `Y (height)`, `Z (depth)`) against min / max / size columns — so an axis' extent sits beside the bounds that span it instead of in a separate block six rows below. `_DOMAIN_AXES` is the single source of truth for the layout, the extent derivation, and the validation
- [x] Placement scales cells by the factor and centers them in the domain (`compute_spatial_placement`; `session.effective_scale()`) — uniform, aspect-preserving; the domain is an independent host-units container
- [x] "Domain Settings…" button in positions plot window for manual domain editing
- [x] Spot deconvolution query and cell expansion; per-spot apportionment lives in `core.positioning.apportion_spot_cells` (shifted-divisor equal proportions), with ties broken at random so the surplus cell no longer lands on the first-listed `obs` column in every spot
- [x] Cluster column selection
- [x] Spatial data query (use spatial coords or random placement)
- [x] Edit cell types (keep / merge / delete) with scatter plot and legend
- [x] Rename cell types with Studio name suggestions and duplicate blocking
- [x] Cell counts (data counts, confluence, total count modes); a count of zero defines the cell type without placing any of it
- [x] Coordinate placement (spatial scaling, random placement)
- [x] 29 cell parameter templates with XML assembly
- [x] BiwtResult assembly (coordinates, cell_type_map, domain, XML)
- [x] `BiwtResult` carries no output path — the host owns *where* results go; `to_csv(path)` writes and records nothing
- [x] 3-D spatial plot ⇧-drag writes the correct extent slots (the 3-D layout is `(x0, y0, z0, width, height, depth)`, not the 2-D `(x0, y0, width, height)`)
- [x] Studio bridge (BiwtInput/BiwtResult, _biwt_complete callback)
- [x] Overwrite/Append/Browse/Cancel dialog for CSV output
- [x] Append handles extra columns in existing CSV
- [x] Session reset on reimport
- [x] `tomli` in core dependencies (fixes import crash on Python 3.9/3.10)
- [x] Step predicate extraction for testability
- [x] `[project.urls]` metadata so the PyPI page links to the repo, docs, and issues
- [x] MkDocs Material documentation site published to GitHub Pages by `.github/workflows/docs.yml`
- [x] Docs: user guide (all wizard steps), recipes (Visium / non-spatial / spot deconvolution), host-integration guide, mkdocstrings API reference
- [x] `LoadError.docs_url`: environment-related import failures link to the setup docs from the "Import failed" dialog; file-related failures stay plain text. Missing dependencies point at the install page, broken R stacks at troubleshooting
- [x] pyproject.toml extras for anndata/seurat/dev dependencies
- [x] CI pipeline (GitHub Actions, Python 3.9–3.12)
- [x] CI: R-dependent `.rds` tests run in a dedicated `seurat` job that provisions R, Seurat, and SingleCellExperiment from conda across Python 3.9–3.12; `tests/fixtures/make_fixtures.R` regenerates the fixture each run so it cannot drift against the resolved R version
- [x] 155 passing tests (one `.rds` test skips locally without the R stack; the `seurat` CI job runs it)

### In Progress

- [ ] End-to-end manual testing with Studio

### Remaining

- [ ] User documentation / help text within wizard steps
- [ ] Substrate/gene expression pass-through (reserved fields in BiwtResult)
- [ ] Multi-library Visium support
- [ ] 3D spatial data support beyond z=0 padding

## Related Documents

- [Documentation site](https://drbergman-lab.github.io/biwt/) — user guide, recipes, integration guide, API reference (source in [docs/](docs/))
- [PRD.md](PRD.md) — Product requirements (behavioral specs, acceptance criteria)
- [progress.md](progress.md) — Session decisions and reasoning
- [CLAUDE.md](CLAUDE.md) — Claude agent guide for this repo
