Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1ea2599
add multi-agg and pca path to anndata_utils
gav-sturm Mar 16, 2026
5a2deb5
add pca optimization step to ops_model
gav-sturm Mar 16, 2026
9a2fcfa
refactor helpers in pca optimization
gav-sturm Mar 16, 2026
742cdc8
major refactor of pca optimization main method
gav-sturm Mar 16, 2026
b7cca9d
further refactor of helper functions in pca optimization
gav-sturm Mar 16, 2026
e4c460a
add hconcat helper to anndata utils
gav-sturm Mar 16, 2026
1dd15b3
use pca ssweep plots helper
gav-sturm Mar 16, 2026
941b90c
further smaller refactor of pca optimization
gav-sturm Mar 16, 2026
0264199
fix up refactored pca optimization
gav-sturm Mar 17, 2026
e4f7924
add git ignore
gav-sturm Mar 17, 2026
634999f
add DINO vs CellProfiler mAP comparison script
gav-sturm Mar 17, 2026
d8991be
add all 4 metrics to CP vs DINO comaprison
gav-sturm Mar 17, 2026
4e315e1
more compact graphs for CP vs Dino comparison
gav-sturm Mar 17, 2026
28de4ad
add phase-only and no-phase options for pca optimization
gav-sturm Mar 18, 2026
af8fb87
reanme to compare map scores for multtiuple usage
gav-sturm Mar 18, 2026
eff718d
save pca components for compeoentn to feature analysis and fix chad c…
gav-sturm Mar 18, 2026
47568fb
udpate docstring in pca component to feature
gav-sturm Mar 18, 2026
6f8890a
Robust evaluation module
Mar 17, 2026
e84f8de
update memory requirement for embedding jobs, 48 --> 72 GB
Mar 17, 2026
9dce4aa
Save features as float32 rather than float64
Mar 18, 2026
6c807ec
inference script for cell_dino model
Mar 17, 2026
500be11
update dataloader
Mar 17, 2026
1768987
fix how feature names are inferred from file_names
Mar 17, 2026
9b80e45
many small updates
Mar 17, 2026
7261d51
simplify path finding and comparisons for compare map scores
gav-sturm Mar 19, 2026
e13f7f5
faster PCA with subsampling method for >5Mcells per reporter and pass…
gav-sturm Mar 19, 2026
ac452c9
remove dead code of per exp-channel pca reduction
gav-sturm Mar 19, 2026
7d42ccb
move peak plot after all metrics are measured
gav-sturm Mar 19, 2026
026826f
change leiden custering function
Mar 19, 2026
59189a2
Add pca_optimization into combination cli
Mar 19, 2026
0f98489
Move plotting functions to eval, and port high cell pca calc into com…
Mar 20, 2026
2138b76
upgrade iohub version
gav-sturm Mar 23, 2026
ed58dd9
fix feature mismatch on cellprofiler
gav-sturm Mar 23, 2026
b3e2474
new titration script for cell count curves
gav-sturm Mar 23, 2026
af80327
update git ignore
gav-sturm Mar 23, 2026
ca6357d
more precise mAP scores for single reporter metrics
gav-sturm Mar 24, 2026
efe41ec
do reporter pairs titration analysis for combined learning curves
gav-sturm Mar 24, 2026
91234bb
add all pairs mode for paired titration analysis
gav-sturm Mar 24, 2026
4c6ff42
add euclidean distanceo mAP scoring and fixed threshold for PCA features
gav-sturm Mar 25, 2026
5971816
bettter sweep evalution for all 3 mAP metrics
gav-sturm Mar 25, 2026
1ce34f7
outdir for pca sweep mode
gav-sturm Mar 25, 2026
1e44520
add minibinder titration option to titration script
gav-sturm Mar 26, 2026
dfa6e9a
remove depreciated keyword from plotting function
Mar 27, 2026
7154eb1
Add option to run distinctivness on all cells
Mar 27, 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: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,6 @@ ENV/
.vscode/


configs/
configs/
scratch/
scripts/compare_dino_cp_map.py
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ classifiers = [
dynamic = ["version"]
dependencies = [
"ops_utils",
"scikit-learn",
"torch==2.7.1",
"lightning",
"byol-pytorch",
Expand All @@ -35,7 +36,7 @@ dependencies = [
"cytoself @ git+https://github.com/royerlab/cytoself.git@version_1.5",
"pytorch-metric-learning",
"cp-measure",
"iohub==0.3.0a6",
"iohub>=0.3.0a7",
"viscy",
"monai",
"diffusers[torch]",
Expand Down Expand Up @@ -64,9 +65,8 @@ dev = [
homepage = "https://github.com/ahillsley/ops_model"
repository = "https://github.com/ahillsley/ops_model"

# same as console_scripts entry point
# [project.scripts]
# spam-cli = "spam:main_cli"
[project.scripts]
run_eval = "ops_model.eval.run_eval:main"

# Entry points
# https://peps.python.org/pep-0621/#entry-points
Expand Down
14 changes: 14 additions & 0 deletions src/ops_model/data/data_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@

warnings.filterwarnings("ignore", category=zarr.errors.ZarrUserWarning)

# Maps experiment-specific column names → canonical internal names.
# Add new entries here to support additional experiment types.
COLUMN_ALIASES: dict[str, str] = {
"minibinder_perturbation": "gene_name", # minibinder experiments
"AA_sequence": "sgRNA", # minibinder experiments
}


def normalize_link_csv(df: pd.DataFrame) -> pd.DataFrame:
"""Rename experiment-specific column variants to canonical names."""
rename = {src: dst for src, dst in COLUMN_ALIASES.items() if src in df.columns}
return df.rename(columns=rename)


class BaseDataset(Dataset):

Expand Down Expand Up @@ -509,6 +522,7 @@ def get_labels(self):
if self.verbose:
print("reading labels for", exp_name, f"links_{w[0]}{w[2]}")
labels_tmp = pd.read_csv(OpsPaths(exp_name, well=w).links["training"])
labels_tmp = normalize_link_csv(labels_tmp)

# remove rows with NaN segmentation_id
labels_tmp = labels_tmp.dropna(subset=["segmentation_id"])
Expand Down
2 changes: 1 addition & 1 deletion src/ops_model/data/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self, experiment: str, well: str = None):
else:
self.well_prefix = None

self.base = Path("/hpc/projects/intracellular_dashboard/ops")
self.base = Path("/hpc/projects/icd.fast.ops")

self.stores = {
"phenotyping": self.base / self.experiment / "3-assembly/phenotyping.zarr",
Expand Down
1 change: 1 addition & 0 deletions src/ops_model/eval/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Evaluation suite for OPS embedding models."""
99 changes: 0 additions & 99 deletions src/ops_model/eval/eval_classification.py

This file was deleted.

123 changes: 0 additions & 123 deletions src/ops_model/eval/eval_cytoself.py

This file was deleted.

91 changes: 91 additions & 0 deletions src/ops_model/eval/eval_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"""Save evaluation outputs (CSVs and plots) to disk."""

from __future__ import annotations

from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import pandas as pd

from ops_utils.analysis.map_scores import plot_map_scatter


def save_guide_eval(
activity_map: pd.DataFrame,
distinctiveness_map: pd.DataFrame,
metrics: dict,
output_dir: str | Path,
) -> None:
"""Save guide-level evaluation outputs to output_dir.

Writes:
- ``phenotypic_activity.csv``
- ``phenotypic_distinctiveness.csv``
- ``map_activity_distinctiveness.png``

Parameters
----------
activity_map : DataFrame
Per-perturbation mAP results from ``phenotypic_activity_assesment``.
distinctiveness_map : DataFrame
Per-perturbation mAP results from ``phenotypic_distinctivness``.
metrics : dict
Scalar metrics returned by ``evaluate_guide_level`` (used for plot titles).
output_dir : str or Path
Directory to write outputs into (created if it does not exist).
"""
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)

activity_map.to_csv(output_dir / "phenotypic_activity.csv", index=False)
distinctiveness_map.to_csv(output_dir / "phenotypic_distinctiveness.csv", index=False)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 7))
plot_map_scatter(ax1, activity_map, "Activity", metrics["pct_perturbations_active"])
plot_map_scatter(ax2, distinctiveness_map, "Distinctiveness", metrics["pct_perturbations_distinct"])
fig.tight_layout()
fig.savefig(output_dir / "map_activity_distinctiveness.png", dpi=150, bbox_inches="tight")
plt.close(fig)


def save_gene_eval(
consistency_corum_map: pd.DataFrame,
consistency_manual_map: pd.DataFrame,
metrics: dict,
output_dir: str | Path,
) -> None:
"""Save gene-level evaluation outputs to output_dir.

Writes:
- ``phenotypic_consistency_corum.csv``
- ``phenotypic_consistency_manual.csv``
- ``map_consistency.png``

Parameters
----------
consistency_corum_map : DataFrame
Per-complex mAP results from ``phenotypic_consistency_corum``.
consistency_manual_map : DataFrame
Per-complex mAP results from ``phenotypic_consistency_manual_annotation``.
metrics : dict
Scalar metrics returned by ``evaluate_gene_level`` (used for plot titles).
output_dir : str or Path
Directory to write outputs into (created if it does not exist).
"""
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)

consistency_corum_map.to_csv(output_dir / "phenotypic_consistency_corum.csv", index=False)
consistency_manual_map.to_csv(output_dir / "phenotypic_consistency_manual.csv", index=False)

corum_entity_col = "complex_id" if "complex_id" in consistency_corum_map.columns else consistency_corum_map.columns[0]
chad_entity_col = "complex_num" if "complex_num" in consistency_manual_map.columns else consistency_manual_map.columns[0]

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 7))
plot_map_scatter(ax1, consistency_corum_map, "Consistency (CORUM)", metrics["pct_complexes_significant_corum"])
plot_map_scatter(ax2, consistency_manual_map, "Consistency (CHAD)", metrics["pct_complexes_significant_manual"])
fig.tight_layout()
fig.savefig(output_dir / "map_consistency.png", dpi=150, bbox_inches="tight")
plt.close(fig)
Loading
Loading