Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0418ace
Dataset prep documentation
LRabuzin Mar 5, 2026
2df5753
Wire up per-cluster enrichment plugin and multi-attribute scatters
LRabuzin Aug 12, 2026
bc58f8c
Repackage src/ as an installable grass_mil package
LRabuzin Aug 12, 2026
5f9cd67
Stop dropping node-level tensors when sampling, rename categorical codes
LRabuzin Aug 12, 2026
8452262
Add cell-type embedding and GINE-on-edge-length to the encoder
LRabuzin Aug 12, 2026
95b50dc
Make MIL attention per-class and assert the attribution identity
LRabuzin Aug 13, 2026
a8d10ed
Add hull-interior seed sampling and ego-graph radius cutoff
LRabuzin Aug 13, 2026
ad9e49b
Port degree-importance BGRL augmentations, fix asymmetric edge dropping
LRabuzin Aug 13, 2026
4c6b22b
Add a survival task preset and vectorise the concordance index
LRabuzin Aug 13, 2026
201eb51
Add exact additive attribution with bootstrap intervals
LRabuzin Aug 13, 2026
46c0587
Add Moran's I, Ripley cross-L, and cross-space cluster agreement
LRabuzin Aug 13, 2026
2880f71
Wire the new analyses into plugins and expose the attention head space
LRabuzin Aug 13, 2026
4492a3a
Remove the auxiliary objectives and learned graph pooling
LRabuzin Aug 13, 2026
9506acb
Document method fidelity and correct the gap audit
LRabuzin Aug 13, 2026
5e70cc7
Generalise margin attribution to multi-class with a one-vs-rest contrast
LRabuzin Aug 13, 2026
c5dbe21
Use niche vocabulary, name Background, order niches by composition
LRabuzin Aug 13, 2026
a026f3d
Finish the niche rename in transfer helpers and output artifacts
LRabuzin Aug 13, 2026
24781d7
Require per-class attention and merge the contracts modules
LRabuzin Aug 13, 2026
4c1a322
Make the augmentation generator functional and drop the duplicate path
LRabuzin Aug 13, 2026
57d787a
Read the head bias from the checkpoint instead of asking for it by hand
LRabuzin Aug 13, 2026
77cf896
Renumber niches by dendrogram order once, after clustering
LRabuzin Aug 13, 2026
d45fe40
Interpret through weighted logit margins only
LRabuzin Aug 13, 2026
2d4d08a
Cleanups: one config resolver, honest loss names, no slow marker
LRabuzin Aug 13, 2026
b5eb829
Update docs to the current code and delete requirements.txt
LRabuzin Aug 13, 2026
85f2136
Fix macOS CI: install torch-sparse from conda, not pip
LRabuzin Aug 13, 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
4 changes: 2 additions & 2 deletions .github/workflows/code-quality-main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.12"

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/code-quality-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.12"

Expand Down
45 changes: 39 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up conda env (spatial-pinned)
uses: conda-incubator/setup-miniconda@v3
with:
activate-environment: spatial
environment-file: environment.ci-spatial.yaml
auto-activate-base: false
auto-activate: false
mamba-version: "*"
channels: pyg,pytorch,conda-forge,defaults
channel-priority: flexible
Expand Down Expand Up @@ -61,14 +61,14 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up conda env (spatial-pinned)
uses: conda-incubator/setup-miniconda@v3
with:
activate-environment: spatial
environment-file: environment.ci-spatial.yaml
auto-activate-base: false
auto-activate: false
mamba-version: "*"
channels: pyg,pytorch,conda-forge,defaults
channel-priority: flexible
Expand All @@ -77,7 +77,40 @@ jobs:
shell: bash -el {0}
run: |
pip install pytest-cov[toml]
pytest --cov src
pytest --cov grass_mil

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5

packaging:
name: Install from source and run the CLI
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

# A plain pip install, deliberately outside conda: this is the path a
# downstream user takes, and it is the one that silently rots when the
# package layout or the config tree moves.
- name: Install the package
run: pip install .

- name: Entrypoints resolve packaged configs from an unrelated directory
run: |
mkdir -p "${RUNNER_TEMP}/elsewhere"
cd "${RUNNER_TEMP}/elsewhere"
grass-mil-train --help
grass-mil-report --help
python -c "import grass_mil, grass_mil.configs; print(grass_mil.__file__)"

- name: Packaging contract tests
run: |
pip install pytest
pytest -v tests/test_packaging.py
7 changes: 2 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ sync: ## Merge changes from main branch to your current branch
git pull
git pull origin main

test: ## Run not slow tests
pytest -k "not slow"

test-full: ## Run all tests
test: ## Run the test suite
pytest

train: ## Train the model
python src/train.py
grass-mil-train
81 changes: 56 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ Geometric deep learning framework for spatial omics data, built around a Hydra-c

Core architecture:

- Data pipeline: `src/data/` + `configs/data/`
- Model/runtime pipeline: `src/models/` + `configs/model/` + `configs/task/`
- Interpretability pipeline: `src/interpretability/` + `configs/interpretability/`
- Entrypoints: `src/train.py`, `src/eval.py`
- Data pipeline: `src/grass_mil/data/` + `configs/data/`
- Model/runtime pipeline: `src/grass_mil/models/` + `configs/model/` + `configs/task/`
- Interpretability pipeline: `src/grass_mil/interpretability/` + `configs/interpretability/`
- Entrypoints: `src/grass_mil/train.py`, `src/grass_mil/eval.py`
- Configuration system: `configs/` (Hydra groups)

## Interpretability
Expand All @@ -32,7 +32,7 @@ Core architecture:
Quick run:

```bash
python src/interpretability/report_cli.py \
grass-mil-report \
data.instance_table=/absolute/path/to/instance_table.csv \
data.spatial_table=/absolute/path/to/spatial_table.csv
```
Expand All @@ -42,16 +42,30 @@ python src/interpretability/report_cli.py \
### 1) Install

```bash
cd /Users/lovrorabuzin/Projects/grass-mil_unification/grass-mil
git clone git@github.com:BoevaLab/grass-mil.git
cd grass-mil
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

# Editable install for development; drop -e for a plain install.
pip install -e .

# Optional extras: interpretability plots, report rendering, spatial statistics,
# and the h5ad/SingleCellExperiment readers.
pip install -e ".[interpretability,report,spatial-stats,io]"
```

Set project root for Hydra path resolution:
Installing exposes the CLI entrypoints (`grass-mil-train`, `grass-mil-eval`,
`grass-mil-loocv`, `grass-mil-predict`, `grass-mil-report`). The Hydra config
tree ships inside the package, so it resolves from any working directory.

Hydra's `paths.root_dir` defaults to the `PROJECT_ROOT` environment variable
when set (`rootutils` exports it automatically from the `.project-root` marker
in a source checkout) and otherwise falls back to the current working
directory. Set it explicitly to place `data/` and `logs/` elsewhere:

```bash
export PROJECT_ROOT=/Users/lovrorabuzin/Projects/grass-mil_unification/grass-mil
export PROJECT_ROOT=/path/to/your/workspace
```

### 2) Prepare New Data
Expand All @@ -67,16 +81,19 @@ Optional:
- `region_id`
- `polygons_path`

For the full onboarding checklist and dataset schema details, see
[`docs/dataset_preparation.md`](docs/dataset_preparation.md).

### 3) Run Default Supervised Pipeline

```bash
python src/train.py task=finetune_mean model=supervised_module data=spatial_omics
grass-mil-train task=finetune_mean model=supervised_module data=spatial_omics
```

### 4) Evaluate A Checkpoint

```bash
python src/eval.py \
grass-mil-eval \
ckpt_path=/absolute/path/to/checkpoint.ckpt \
task=finetune_mean \
model=supervised_module \
Expand All @@ -86,23 +103,26 @@ python src/eval.py \
## Documentation Index

- Full tracked-file map: [`docs/repository_map.md`](docs/repository_map.md)
- Dataset onboarding and preparation checklist: [`docs/dataset_preparation.md`](docs/dataset_preparation.md)
- End-to-end workflows (new data, SSL pretrain->finetune, model adjustments, inference): [`docs/workflows_train_infer.md`](docs/workflows_train_infer.md)
- Inference utility suite (prediction artifacts, metrics, embeddings): [`docs/inference_utility_suite.md`](docs/inference_utility_suite.md)
- Interpretability suite architecture and usage: [`docs/interpretability_suite.md`](docs/interpretability_suite.md)
- Interpretability extension guide (plugins/new analyses): [`docs/interpretability_extension_guide.md`](docs/interpretability_extension_guide.md)
- Exhaustive hyperparameter reference for repo configs: [`docs/hyperparameter_reference.md`](docs/hyperparameter_reference.md)
- Capability modes and operational options: [`docs/capabilities_and_modes.md`](docs/capabilities_and_modes.md)
- Existing model contracts: [`docs/model_component_contracts.md`](docs/model_component_contracts.md)
- Existing legacy gap audit: [`docs/legacy_gap_audit.md`](docs/legacy_gap_audit.md)
- Method fidelity map (method -> code -> test): [`docs/method_fidelity.md`](docs/method_fidelity.md)
- Fidelity status and bugs found while closing gaps: [`docs/legacy_gap_audit.md`](docs/legacy_gap_audit.md)

## Supported Training/Inference Modes

| Mode | Task Config | Model Config | Entrypoint | Primary Output |
|---|---|---|---|---|
| Supervised mean aggregation | `task=finetune_mean` | `model=supervised_module` | `src/train.py` | Region/sample-level logits via mean bag aggregation |
| Supervised MIL attention | `task=finetune_mil` | `model=supervised_module` | `src/train.py` | Attention-weighted bag logits (+ optional MIL auxiliary terms) |
| SSL pretraining (BGRL) | `task=pretrain_bgrl` | `model=bgrl_module` | `src/train.py` | BGRL-pretrained encoder checkpoint |
| Checkpoint evaluation | any compatible task/model | matching training stack | `src/eval.py` | Test metrics from selected checkpoint |
| Supervised mean aggregation | `task=finetune_mean` | `model=supervised_module` | `src/grass_mil/train.py` | Region/sample-level logits via mean bag aggregation |
| Supervised MIL attention | `task=finetune_mil` | `model=supervised_module` | `src/grass_mil/train.py` | Per-class attention-weighted bag logits |
| Cox survival with MIL | `task=finetune_survival` | `model=supervised_module` | `src/grass_mil/train.py` | Scalar log-hazard per bag, scored by c-index |
| SSL pretraining (BGRL) | `task=pretrain_bgrl` | `model=bgrl_module` | `src/grass_mil/train.py` | BGRL-pretrained encoder checkpoint |
| Checkpoint evaluation | any compatible task/model | matching training stack | `src/grass_mil/eval.py` | Test metrics from selected checkpoint |
| Advanced prediction (Python API) | compatible with `SupervisedModule.predict_step` | `model=supervised_module` | `Trainer.predict(...)` | `bag_ids`, `bag_logits`, `row_region_ids`, `row_sample_ids`, optional `bag_targets`, optional `bag_attention`, optional `instance_*`, optional `embedding_*` |

## Required Inputs (Manifest Summary)
Expand All @@ -129,20 +149,20 @@ See full input contracts and file examples in [`docs/workflows_train_infer.md`](
### Switch aggregation regime

```bash
python src/train.py task=finetune_mean model=supervised_module
python src/train.py task=finetune_mil model=supervised_module
grass-mil-train task=finetune_mean model=supervised_module
grass-mil-train task=finetune_mil model=supervised_module
```

### Run SSL pretraining

```bash
python src/train.py task=pretrain_bgrl model=bgrl_module
grass-mil-train task=pretrain_bgrl model=bgrl_module
```

### Change backbone

```bash
python src/train.py task=finetune_mil model=supervised_module \
grass-mil-train task=finetune_mil model=supervised_module \
model.encoder.conv_type=gine \
model.encoder.use_edge_attr=true \
model.encoder.edge_attr_dim=2
Expand All @@ -151,13 +171,13 @@ python src/train.py task=finetune_mil model=supervised_module \
### Force data re-precompute

```bash
python src/train.py data.force_precompute=true
grass-mil-train data.force_precompute=true
```

### Resume training

```bash
python src/train.py ckpt_path=/absolute/path/to/last.ckpt
grass-mil-train ckpt_path=/absolute/path/to/last.ckpt
```

## Where Outputs Go
Expand All @@ -176,9 +196,20 @@ Data precompute outputs:

## Known Gaps / Non-Goals

Current repository behavior intentionally excludes:
`grass-mil` implements the method, and only the method. It is deliberately not
a reproduction harness for any particular study, so the following live outside
this repository:

1. Cohort-specific experiment configs and dataset preprocessing.
2. Non-GNN baselines (cell-type composition models, frozen-encoder probes) and
the benchmark tables that compare against them.
3. Cross-validation campaign harnesses, hyperparameter sweep recipes, and
experiment-tracking orchestration.

The one deliberate exception is the interpretability suite, which is
first-class here because the method's attribution claim is part of the method.

1. Curated first-class hyperparameter sweep recipes in `configs/hparams_search/`.
2. Turnkey dataset-specific benchmark packs beyond the generic Hydra/config contracts.
For what is implemented and the tests that hold it in place, see
[`docs/method_fidelity.md`](docs/method_fidelity.md).

All currently supported capabilities are documented in [`docs/workflows_train_infer.md`](docs/workflows_train_infer.md), [`docs/hyperparameter_reference.md`](docs/hyperparameter_reference.md), and [`docs/capabilities_and_modes.md`](docs/capabilities_and_modes.md).
13 changes: 0 additions & 13 deletions configs/data/sampler/shadow_custom.yaml

This file was deleted.

13 changes: 0 additions & 13 deletions configs/data/sampler/shadow_native.yaml

This file was deleted.

41 changes: 0 additions & 41 deletions configs/interpretability/plugins/default.yaml

This file was deleted.

5 changes: 0 additions & 5 deletions configs/model/attention/gated.yaml

This file was deleted.

6 changes: 0 additions & 6 deletions configs/model/attention/gated_projected.yaml

This file was deleted.

Loading
Loading