Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6ad7bf5
Strip a trailing blank line that failed end-of-file-fixer
LRabuzin Aug 17, 2026
86636b6
Untrack the 20 MB mibitof demo file; vignettes download it at runtime
LRabuzin Oct 13, 2026
e7ed3aa
Phase 1: preprint fidelity for graph, encoder and attention; composab…
LRabuzin Oct 13, 2026
b16e4bc
Phase 2: one region per bag, regimes with scaled learning rates, regi…
LRabuzin Oct 13, 2026
7902572
Phase 3: explicit splits, probe pre-fit and nested cross-validation
LRabuzin Oct 13, 2026
a6a365b
Phase 4: BGRL A3 pretraining preset and fidelity
LRabuzin Oct 13, 2026
8eb9d60
Phase 5: cell cache extraction, patient-level aggregation, evaluation…
LRabuzin Oct 13, 2026
fc152aa
Phase 6: niche discovery on the cell cache
LRabuzin Oct 13, 2026
4b63f2c
Phase 7: cross-fold metaclusters, whole-dataset transfer, shared basis
LRabuzin Oct 13, 2026
42f4b42
Phase 8: classical spatial statistics
LRabuzin Oct 13, 2026
c291def
Phase 9: cleanup, documentation, README, citation, vignettes
LRabuzin Oct 13, 2026
2d04415
Phase 10 (part): end-to-end synthetic test, bf16-safe exports, balanc…
LRabuzin Oct 13, 2026
a10e785
Phase 10 (part): per-unit eval metrics for patch/sample bags, resume …
LRabuzin Oct 13, 2026
37f7df4
nested CV: unit ids of patch and sample bags from the namespaced bag id
LRabuzin Oct 13, 2026
acff9bf
Vignette 03 executed (nested CV, niches, metaclusters, scores, spatia…
LRabuzin Oct 13, 2026
8648b84
method correspondence: probehead and spatial-statistics fidelity results
LRabuzin Oct 13, 2026
f31d500
method correspondence: ftALL-reg fold-2 fidelity result
LRabuzin Oct 13, 2026
e009a4d
model loading ignores probe pre-fit and init checkpoints (the trained…
LRabuzin Oct 13, 2026
9d64073
method correspondence: niche fidelity result
LRabuzin Oct 13, 2026
16e5650
Lint: names and unused variables flagged by the pinned pre-commit ruf…
LRabuzin Oct 13, 2026
676156d
Docs: getting-started walkthrough, configuration guide, cohort config…
LRabuzin Oct 13, 2026
c4d4ff5
Repository map regenerated; generator kept in tools/
LRabuzin Oct 13, 2026
2cdc594
e2e test: structural checks instead of a seed-dependent ranking asser…
LRabuzin Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 0 additions & 62 deletions .cursor/rules/model_component_contracts.mdc

This file was deleted.

6 changes: 0 additions & 6 deletions .env.example

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
-f "https://data.pyg.org/whl/torch-${TORCH_VERSION}+cpu.html"

- name: Install the package
run: pip install ".[interpretability,io]" pytest
run: pip install ".[interpretability,io,stats,plots]" pytest

- name: Show key package versions
run: |
Expand Down Expand Up @@ -113,7 +113,7 @@ jobs:

- name: Run tests and collect coverage
run: |
pip install ".[interpretability,io]" pytest "pytest-cov[toml]"
pip install ".[interpretability,io,stats,plots]" pytest "pytest-cov[toml]"
pytest --cov grass_mil

- name: Upload coverage to Codecov
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ dmypy.json

# Lightning-Hydra-Template
configs/local/default.yaml
src/grass_mil/configs/local/*.yaml
!src/grass_mil/configs/local/.gitkeep
/data/
/logs/
.env
Expand All @@ -154,3 +156,6 @@ configs/local/default.yaml

# Vignette scratch space (downloaded data, graphs, runs)
vignettes/vignette_work/

# vignette datasets are downloaded at runtime (squidpy.datasets.mibitof)
vignettes/data/
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Changelog

## 1.0.0 (2026-10)

Public release accompanying the preprint
[GRASS-MIL: graph-based representation and discovery of phenotype-associated spatial structures with multiple instance learning](https://www.biorxiv.org/content/10.64898/2026.10.08.757722v1).

### Method (defaults match the preprint; every setting stays configurable)

- Delaunay cell graph with the bounded log edge length `clip((ln d - 2)/3, 0, 1)` as the edge feature (`log_distance`).
- GINE ego-graph encoder (4 x 256, learnable epsilon, layer norm, max pooling, xavier-initialised cell-type embedding) as `model=grass_mil`.
- Projected gated attention with one channel per class (32 / 8, kaiming) and logit-space pooling, so every bag logit is an exact sum of per-cell contributions.
- One region = one bag: all sampled ego-graphs of a region in one batch, one attention softmax, one loss; region-level validation metrics and selection.
- Training regimes as presets (`regime=mil|mil_frozen|linear_probehead|linear_ftall|linear_ftall_reg`) with per-component learning-rate scales, head pre-fit by a logistic probe, class weights from the training split, per-step cosine schedule, gradient accumulation over regions, AMP-safe scheduler stepping, elementwise feature drop with an unassigned token.
- BGRL "A3" pretraining preset (`regime=pretrain_a3`): roots drawn from the union of all regions, momentum 0.99 -> 1.0, DropImportance + feature noise, checkpoint every 5000 steps.
- Import of legacy SPACE-GM style BGRL checkpoints (`model.encoder_init_map=spacegm_bgrl`).

### Analyses

- `grass-mil-probe`, `grass-mil-nested-cv`: nested patient-grouped cross-validation with explicit fold files, inner-fold epoch selection, refit and out-of-fold predictions (region and patient level).
- `grass-mil-extract`: per-cell cache (embeddings, instance logits, attention) of trained models over every cell.
- `grass-mil-niches`: niche discovery on a model's cells (cosine HDBSCAN by default, any registry backend), attention-weighted margins, per-niche tables, co-localisation, figures.
- `grass-mil-metaclusters`: cross-fold niche replication (constrained matching on composition), whole-dataset transfer, shared label-free basis.
- `grass-mil-scores`: bootstrap AUROC intervals, DeLong tests, within-fold standardisation, operating points (sensitivity, specificity, PPV, NPV, likelihood ratios).
- `grass-mil-spatial-stats`: neighbourhood enrichment, cellular neighbourhoods, contact fractions and cross-K per region with patient-level group tests.
- Patient-level aggregation in `grass-mil-predict` (mean of region probabilities or one merged bag).

### Housekeeping

- Removed stale component configs, the dummy dataset, the embeddings shim and internal audit notes; added `CITATION.cff`; `hydra-core` 1.3.5+.
33 changes: 33 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
cff-version: 1.2.0
message: "If you use GRASS-MIL, please cite the preprint."
title: "GRASS-MIL: graph-based representation and discovery of phenotype-associated spatial structures with multiple instance learning"
type: software
version: 1.0.0
date-released: 2026-10-13
license: MIT
repository-code: https://github.com/BoevaLab/grass-mil
authors:
- family-names: Rabuzin
given-names: Lovro
- family-names: Yates
given-names: Josephine
- family-names: Xu
given-names: Mina
- family-names: Boeva
given-names: Valentina
preferred-citation:
type: article
title: "GRASS-MIL: graph-based representation and discovery of phenotype-associated spatial structures with multiple instance learning"
authors:
- family-names: Rabuzin
given-names: Lovro
- family-names: Yates
given-names: Josephine
- family-names: Xu
given-names: Mina
- family-names: Boeva
given-names: Valentina
journal: bioRxiv
year: 2026
doi: 10.64898/2026.10.08.757722
url: https://www.biorxiv.org/content/10.64898/2026.10.08.757722v1
14 changes: 3 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@

help: ## Show help
@grep -E '^[.a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

clean: ## Clean autogenerated files
clean: ## Remove caches and build artefacts
rm -rf dist
find . -type f -name "*.DS_Store" -ls -delete
find . | grep -E "(__pycache__|\.pyc|\.pyo)" | xargs rm -rf
find . | grep -E ".pytest_cache" | xargs rm -rf
find . | grep -E ".ipynb_checkpoints" | xargs rm -rf
rm -f .coverage

clean-logs: ## Clean logs
clean-logs: ## Remove run outputs under logs/
rm -rf logs/**

format: ## Run pre-commit hooks
format: ## Run pre-commit hooks (ruff lint + format)
pre-commit run -a

sync: ## Merge changes from main branch to your current branch
git pull
git pull origin main

test: ## Run the test suite
pytest

train: ## Train the model
grass-mil-train
Loading
Loading