diff --git a/pyproject.toml b/pyproject.toml index ed3724ac..778862a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,10 @@ dependencies = [ # https://peps.python.org/pep-0621/#dependencies-optional-dependencies [project.optional-dependencies] models = ["transformers<4.40"] +# Multiscale UMAP montages for the diffae interpretability figures. A git +# dependency, so it is kept out of the default install; only +# models/interpretability/diffae/viewer/ imports it. +diffae = ["latent-lens @ git+https://github.com/czi-ai/latent-lens"] test = ["pytest>=6.0", "pytest-cov"] dev = [ "ipykernel", diff --git a/src/ops_model/models/interpretability/diffae/viewer/build_umap_montage.py b/src/ops_model/models/interpretability/diffae/viewer/build_umap_montage.py index 87bd16cf..6d16a3ee 100644 --- a/src/ops_model/models/interpretability/diffae/viewer/build_umap_montage.py +++ b/src/ops_model/models/interpretability/diffae/viewer/build_umap_montage.py @@ -15,7 +15,6 @@ import anndata as ad from PIL import Image -from latent_lens import MontageConfig, build_montage from ..classifier.config import slugify from .precompute import VIEWER_ALPHAS @@ -79,6 +78,10 @@ def montage_from_cache(h5ad, out_zarr, cell=0, alpha=2.0, modality="phase", grai placed at the gene's position in `embedding` (obsm X_, e.g. umap or phate). Crops kept GRAYSCALE (white category tint). crop_size=256 sharp; px_per_umap≈22×crop fills canvas. `border_field` (an obs column, e.g. 'leiden_r4') draws a per-cell colored border keyed on that group.""" + # Lazy: latent-lens is the `diffae` extra, not a default install + # (`uv sync --extra diffae`, or `pip install ops_model[diffae]`). + from latent_lens import MontageConfig, build_montage + al = list(VIEWER_ALPHAS) ai = int(np.argmin([abs(a - alpha) for a in al])) # frame index for the requested α a0 = int(np.argmin([abs(a) for a in al])) # α=0 frame index (shared anchor recon)