Feature/biwt package#3
Closed
drbergman wants to merge 1 commit into
Closed
Conversation
There was a problem hiding this comment.
Pull request overview
Introduces a new standalone biwt Python package (core + PyQt5 GUI walkthrough) and wires PhysiCell Studio to prefer the packaged BIWT implementation (with legacy fallback), along with unit tests, fixtures, and CI.
Changes:
- Add a pure-Python BIWT core (data loading, domain logic, positioning utilities) plus a PyQt5 walkthrough UI and step windows.
- Add session-level unit tests and CSV fixtures for spatial, non-spatial, and spot-deconvolution flows.
- Add Studio integration bridge + a GitHub Actions workflow to run BIWT tests.
Reviewed changes
Copilot reviewed 35 out of 39 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| biwt/tests/test_session.py | New end-to-end session/unit tests for loader, domain logic, step predicates, and pipeline outputs |
| biwt/tests/fixtures/spot_deconv.csv | Spot-deconvolution CSV fixture with probability columns |
| biwt/tests/fixtures/spatial.csv | Spatial CSV fixture with x/y/type |
| biwt/tests/fixtures/nonspatial.csv | Non-spatial CSV fixture with type only |
| biwt/tests/init.py | Marks BIWT tests package |
| biwt/src/biwt/types.py | Defines public API dataclasses: DomainSpec, BiwtInput, BiwtResult |
| biwt/src/biwt/gui/windows/write_positions.py | Adds (deprecated-style) output writer window for CSV/XML |
| biwt/src/biwt/gui/windows/spot_deconvolution.py | Adds spot-deconvolution query step window |
| biwt/src/biwt/gui/windows/spatial_query.py | Adds spatial-data usage query step window |
| biwt/src/biwt/gui/windows/rename_cell_types.py | Adds rename step window with duplicate blocking and suggestions |
| biwt/src/biwt/gui/windows/load_cell_parameters.py | Adds cell-parameter template assignment step window |
| biwt/src/biwt/gui/windows/edit_cell_types.py | Adds keep/merge/delete UI with optional scatter plot + legend |
| biwt/src/biwt/gui/windows/cluster_column.py | Adds cluster/label column selection step window |
| biwt/src/biwt/gui/windows/cell_counts.py | Adds non-spatial cell-counts configuration step window |
| biwt/src/biwt/gui/windows/base.py | Adds common walkthrough window base class + navigation helpers |
| biwt/src/biwt/gui/windows/init.py | Exports step windows in a single module |
| biwt/src/biwt/gui/widgets.py | Adds shared Qt widgets (buttons, line edits, filtered combo, legend dialog, etc.) |
| biwt/src/biwt/gui/walkthrough.py | Implements session dataclass, step predicate table, walkthrough controller, and result assembly |
| biwt/src/biwt/gui/init.py | Guards GUI import on PyQt5 availability and exports create_biwt_widget |
| biwt/src/biwt/core/positioning.py | Adds coordinate scaling, IC dataframe creation, and spot-expansion helper |
| biwt/src/biwt/core/parameters/xml_defaults.py | Adds default PhysiCell XML section snippets |
| biwt/src/biwt/core/parameters/init.py | Documents the parameters subpackage purpose |
| biwt/src/biwt/core/domain.py | Adds domain inference and mismatch classification logic |
| biwt/src/biwt/core/data_loader.py | Adds unified loader for .h5ad, R formats, and .csv into BiwtData |
| biwt/src/biwt/core/cell_types.py | Adds cell-type action/config model and name suggestion heuristics |
| biwt/src/biwt/core/init.py | Core package marker/docstring |
| biwt/src/biwt/init.py | Package exports and version |
| biwt/pyproject.toml | Packaging metadata + optional dependency extras + pytest config |
| biwt/progress.md | Development decisions log for BIWT |
| biwt/README.md | BIWT package documentation, usage, and status |
| biwt/PRD.md | BIWT requirements/specification document |
| biwt/.gitignore | BIWT-specific ignore rules |
| bin/ics_tab.py | Studio integration: prefer biwt package widget when installed; host writes output via callback |
| README.md | Top-level repo README now references BIWT package and usage |
| CLAUDE.md | Repo architecture guide updated to include BIWT package and integration |
| .gitignore | Adds venv/editor ignores at repo root |
| .github/workflows/ci.yml | Adds CI job to install BIWT and run tests |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+26
to
+32
| - name: Install BIWT with dev dependencies | ||
| # TODO (standalone repo): change to: pip install -e ".[dev]" | ||
| run: pip install -e "biwt/[dev]" | ||
|
|
||
| - name: Run tests | ||
| # TODO (standalone repo): remove "cd biwt &&" | ||
| run: cd biwt && PYTHONPATH=src python -m pytest tests/ -v |
Comment on lines
+55
to
+58
| all = ["biwt[anndata,seurat,gui]"] | ||
|
|
||
| # pip install biwt[dev] — development / testing extras | ||
| dev = ["pytest>=7", "pytest-qt", "biwt[all]"] |
Comment on lines
+27
to
+40
| def __init__(self, walkthrough): | ||
| super().__init__(walkthrough) | ||
| s = walkthrough.session | ||
|
|
||
| csv_path = s.biwt_input.output_csv_path or "./config/cells.csv" | ||
| self._full_fname: str | None = None | ||
|
|
||
| vbox = QVBoxLayout() | ||
| vbox.addWidget(QLabel( | ||
| "Confirm output file, then choose to overwrite or append." | ||
| )) | ||
|
|
||
| self._csv_path_edit = QLineEdit(csv_path) | ||
| browse_btn = QPushButton("Browse…") |
Comment on lines
+128
to
+137
| def test_data_at_exactly_50pct_each_axis_returns_none(self): | ||
| # width=500 (50%), height=500 (50%), area=25% → small (area check) | ||
| data = DomainSpec(xmin=-250, xmax=250, ymin=-250, ymax=250) | ||
| assert classify_domain_mismatch(data, self.PREFERRED) == "small" | ||
|
|
||
| def test_data_covers_more_than_50pct_returns_none(self): | ||
| # width=700 (70%), height=700 (70%), area=49% — below 50% area threshold | ||
| data = DomainSpec(xmin=-350, xmax=350, ymin=-350, ymax=350) | ||
| assert classify_domain_mismatch(data, self.PREFERRED) == "small" | ||
|
|
Comment on lines
+831
to
+853
| coords_df = build_ic_dataframe(self.session.coords_by_type) | ||
| mapping = self.session.cell_type_config.resolve() | ||
| s = self.session | ||
|
|
||
| # Build cell-definitions XML if the parameters step populated the registry. | ||
| if s.cell_definitions_registry: | ||
| root = ET.Element("PhysiCell_settings", version="devel-version") | ||
| for key, xml_str in xml_defaults.items(): | ||
| wrapped = f"<{key}>{xml_str.strip()}</{key}>" | ||
| root.append(ET.fromstring(wrapped)) | ||
| cell_defs = ET.SubElement(root, "cell_definitions") | ||
| for template_elem in s.cell_definitions_registry.values(): | ||
| cell_defs.append(copy.deepcopy(template_elem)) | ||
| s.cell_definitions_xml = ET.tostring( | ||
| root, encoding="unicode", xml_declaration=False | ||
| ) | ||
|
|
||
| result = BiwtResult( | ||
| coordinates=coords_df, | ||
| cell_type_map=mapping, | ||
| domain_used=s.effective_domain, | ||
| cell_definitions_xml=s.cell_definitions_xml, | ||
| ) |
Comment on lines
+58
to
+75
| # Normalize to [0, 1] | ||
| normalized = (coords - src_min) / src_range | ||
|
|
||
| domain_widths = np.array([domain.width, domain.height, domain.depth]) | ||
| domain_origins = np.array([domain.xmin, domain.ymin, domain.zmin]) | ||
|
|
||
| out = np.zeros((len(coords), 3)) | ||
|
|
||
| if preserve_aspect: | ||
| # Scale by the smallest ratio so data fits within domain without distortion, | ||
| # then center the result. | ||
| n_spatial = min(n_dims, 2) # only x/y for 2-D data | ||
| scale = min(domain_widths[i] for i in range(n_spatial)) | ||
| for i in range(n_dims): | ||
| center = domain_origins[i] + 0.5 * domain_widths[i] | ||
| data_width = scale if i < 2 else domain_widths[2] | ||
| out[:, i] = (normalized[:, i] - 0.5) * data_width + center | ||
| else: |
617884f to
6c0dd1b
Compare
- add the new src-layout biwt package with pyproject metadata, public host/package contracts, core loaders/domain/cell-type/positioning modules, parameter templates, icons, and a modular PyQt walkthrough under gui/windows/ - refactor the walkthrough around explicit session state and step predicates, with better navigation, plotting/layout cleanup, domain mismatch editing, cell count and rename validation, template loading from TOML, and improved out-of-bounds handling - make Studio consume the package behind --biwt via bin/ics_tab.py while keeping the legacy fallback tab; BIWT now returns an in-memory BiwtResult and Studio owns CSV/XML save, append, browse, and reload flows - document the package split and install path in the repo README and BIWT docs, add PRD/progress/CLAUDE guidance, and add package CI plus session tests and CSV fixtures
6c0dd1b to
fbef040
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.