Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
51 changes: 51 additions & 0 deletions virtual-staining/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Virtual staining evaluation

Reproduce paper metrics for five models on IMC virtual-staining task.

## Quick start (paper reproduction)

```bash
python3 evaluate_all.py --config configs/paper.yaml --table
python3 evaluate_all.py plot --results results/per_point_results.csv
```

## Input data format

### `immuvis_npz` — used by ImmuVis models

Each file is named `recn-{image_id}.npz` and contains:

| Key | Shape | Content |
|---|---|---|
| `recon` | `(C, H, W)` | Model predictions, one channel per marker |
| `target` | `(C, H, W)` | Ground truth, same channel ordering |
| `marker_names` | `(C,)` | Array of marker name strings |
| `metadata` | scalar (JSON string) | `{"image_path": "...", "dataset_name": "hn"}` |

Image ID is extracted from `metadata["image_path"]` by taking the filename stem (last `/`-separated component, minus extension).

Predictions/ground truth are indexed by `[channel, :, :]` — the `marker_names` array is searched for the target marker name to find the channel index.

### `virtues_npy` — used by Virtues and Eva models

Directory of single-channel `.npy` files named `{image_id}_{marker}_recon.npy`, each shape `(H, W)`.

Marker names in filenames use underscores and short forms; they are normalised on load:

| Filename marker | Canonical name |
|---|---|
| `Carbonic` | `Carbonic Anhydrase` |
| `PARP` | `cl.PARP` |
| `H3` or `Histone` | `Histone H3` |
| `Carbonic_Anhydrase` | `Carbonic Anhydrase` (underscores → spaces) |

No ground truth is stored in these files. Ground truth is always sourced from a separate `immuvis_npz` model (configured via `ground_truth.source_model`).

## Output

All CSVs in `output_dir/` (default `results/`):

- `per_point_results.csv` — per (model, image, marker) MSE + Pearson
- `per_marker_pearson.csv` — per-marker aggregated Pearson (sufficient statistics)
- `summary.csv` — per-(model, marker) mean ± std
- `boxplot.pdf` — grouped box plot via `plot` subcommand
58 changes: 58 additions & 0 deletions virtual-staining/configs/paper.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
marker_stats_csv: "data/marker_ds_stats.csv"
crop_size: [128, 128]
output_dir: "results"

models:

- name: "virtues_our_norm"
path: "/raid_encrypted/immucan/recons/virtues_our_norm/"
format: "virtues_npy"
display_name: "Virtues_{IMC17M}_{OP}"
prediction_transform:
type: "immu_offset"
params: { scale: 3.4 }
ground_truth:
source_model: "immuvis_612"
transform:
type: "immu_offset"
params: { scale: 3.4 }

- name: "eva_hn_recon_crop"
path: "/raid_encrypted/immucan/recons/eva_hn_recon_crop/"
format: "virtues_npy"
display_name: "EVA_{OP}"
prediction_transform:
type: "immu_offset"
params: { scale: 3.4 }
ground_truth:
source_model: "immuvis_612"
transform:
type: "immu_offset"
params: { scale: 3.4 }

- name: "immuvis_609"
path: "/raid_encrypted/immucan/results/with_reconstructs/recons/immuvis_609_loo/"
format: "immuvis_npz"
display_name: "ImmuVis_{ViT}"
filter_pairs_to: "virtues_our_norm"
prediction_transform:
type: "immu_offset"
params: { scale: 3.4 }

- name: "immuvis_612"
path: "/raid_encrypted/immucan/results/with_reconstructs/recons/immuvis_612_loo/"
format: "immuvis_npz"
display_name: "ImmuVis_{Conv}"
filter_pairs_to: "virtues_our_norm"
prediction_transform:
type: "immu_offset"
params: { scale: 3.4 }

- name: "immuvis_622"
path: "/raid_encrypted/immucan/results/with_reconstructs/recons/immuvis_622_loo/"
format: "immuvis_npz"
display_name: "ImmuVis_{Swin}"
filter_pairs_to: "virtues_our_norm"
prediction_transform:
type: "immu_offset"
params: { scale: 3.4 }
31 changes: 31 additions & 0 deletions virtual-staining/configs/swin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
marker_stats_csv: "data/marker_ds_stats.csv"
crop_size: [128, 128]
output_dir: "results_swin"

models:
- name: "virtues_our_norm"
path: "/raid_encrypted/immucan/recons/virtues_our_norm/"
format: "virtues_npy"
display_name: "Virtues_{IMC17M}_{OP}"
prediction_transform:
type: "immu_offset"
params: { scale: 3.4 }
ground_truth:
source_model: "immuvis_612"
transform:
type: "immu_offset"
params: { scale: 3.4 }

- name: "immuvis_612"
path: "/raid_encrypted/immucan/results/with_reconstructs/recons/immuvis_612_loo/"
format: "immuvis_npz"
evaluate: false

- name: "immuvis_622"
path: "/raid_encrypted/immucan/results/with_reconstructs/recons/immuvis_622_loo/"
format: "immuvis_npz"
display_name: "ImmuVis_{Swin}"
filter_pairs_to: "virtues_our_norm"
prediction_transform:
type: "immu_offset"
params: { scale: 3.4 }
Loading