Skip to content

Commit 2406222

Browse files
committed
Add demo entrypoint
1 parent e49bf62 commit 2406222

File tree

6 files changed

+164
-17
lines changed

6 files changed

+164
-17
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ data/
44
.snakemake/
55
.ipynb_checkpoints/
66
*.egg-info/
7-
src/cev/_version.py
87
.vite
98
dist/
109
mair/

notebooks/getting-started.ipynb

+13-5
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,12 @@
8080
},
8181
"outputs": [],
8282
"source": [
83-
"tissue_umap_embedding = Embedding.from_ozette(df=pd.read_parquet(\"./data/mair-2022-tissue-138-umap.pq\"))\n",
84-
"tissue_ozette_embedding = Embedding.from_ozette(df=pd.read_parquet(\"./data/mair-2022-tissue-138-ozette.pq\"))"
83+
"tissue_umap_embedding = Embedding.from_ozette(\n",
84+
" df=pd.read_parquet(\"./data/mair-2022-tissue-138-umap.pq\")\n",
85+
")\n",
86+
"tissue_ozette_embedding = Embedding.from_ozette(\n",
87+
" df=pd.read_parquet(\"./data/mair-2022-tissue-138-ozette.pq\")\n",
88+
")"
8589
]
8690
},
8791
{
@@ -126,7 +130,7 @@
126130
},
127131
"outputs": [],
128132
"source": [
129-
"umap_vs_ozette.select(['CD3+', 'CD4+', 'CD8-'])"
133+
"umap_vs_ozette.select([\"CD3+\", \"CD4+\", \"CD8-\"])"
130134
]
131135
},
132136
{
@@ -148,7 +152,9 @@
148152
},
149153
"outputs": [],
150154
"source": [
151-
"tumor_ozette_embedding = Embedding.from_ozette(df=pd.read_parquet(\"./data/mair-2022-tumor-006-ozette.pq\"))"
155+
"tumor_ozette_embedding = Embedding.from_ozette(\n",
156+
" df=pd.read_parquet(\"./data/mair-2022-tumor-006-ozette.pq\")\n",
157+
")"
152158
]
153159
},
154160
{
@@ -192,7 +198,9 @@
192198
},
193199
"outputs": [],
194200
"source": [
195-
"tissue_vs_tumor.select(\"CD4-CD8+CD3+CD45RA+CD27+CD19-CD103-CD28-CD69+PD1+HLADR-GranzymeB-CD25-ICOS-TCRgd-CD38-CD127-Tim3-\")"
201+
"tissue_vs_tumor.select(\n",
202+
" \"CD4-CD8+CD3+CD45RA+CD27+CD19-CD103-CD28-CD69+PD1+HLADR-GranzymeB-CD25-ICOS-TCRgd-CD38-CD127-Tim3-\"\n",
203+
")"
196204
]
197205
},
198206
{

pyproject.toml

+10-5
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,37 @@ classifiers = [
1919
"Programming Language :: Python :: 3.10",
2020
"Programming Language :: Python :: 3.11",
2121
]
22-
requires-python = ">=3.8"
22+
requires-python = ">=3.8,<3.12"
2323
dependencies = [
2424
"anywidget>=0.2.3",
2525
"cev-metrics>=0.1.2",
2626
"ipywidgets>=8.0.0",
2727
"jinja2>=3.0.0",
2828
"jupyter-scatter>=0.14.0",
29-
"pandas>=1.0",
29+
"pandas>=1.0,<2.0",
30+
"numpy>=1.0,<2.0",
31+
"pyarrow",
32+
"pooch>=1.3.0",
3033
]
3134
dynamic = ["version"]
3235

3336
# https://peps.python.org/pep-0621/#dependencies-optional-dependencies
3437
[project.optional-dependencies]
3538
dev = [
36-
"black[jupyter]",
39+
"black[jupyter]==23.1.0",
3740
"jupyterlab",
3841
"pytest",
39-
"rich",
40-
"ruff",
42+
"ruff==0.0.246",
4143
]
4244
notebooks = [
4345
"pyarrow",
4446
"fastparquet",
4547
"matplotlib",
4648
]
4749

50+
[project.scripts]
51+
cev = "cev._cli:main"
52+
4853
[project.urls]
4954
homepage = "https://github.com/OzetteTech/comparative-embedding-visualization"
5055

src/cev/__init__.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
from importlib.metadata import PackageNotFoundError, version
1+
from cev._version import __version__ # noqa
22

33
import cev.metrics as metrics # noqa
44
import cev.widgets as widgets # noqa
5-
6-
try:
7-
__version__ = version("cev")
8-
except PackageNotFoundError:
9-
__version__ = "uninstalled"

src/cev/_cli.py

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import argparse
2+
import json
3+
import os
4+
import shutil
5+
import sys
6+
import textwrap
7+
import zipfile
8+
from pathlib import Path
9+
10+
import pooch
11+
12+
from cev._version import __version__
13+
14+
_DEV = True
15+
16+
17+
def download_data() -> tuple[Path, Path]:
18+
archive = pooch.retrieve(
19+
url="https://figshare.com/ndownloader/articles/23063615/versions/1",
20+
path=pooch.os_cache("cev"),
21+
fname="data.zip",
22+
known_hash=None,
23+
)
24+
archive = Path(archive)
25+
files = [
26+
"mair-2022-tissue-138-umap.pq",
27+
"mair-2022-tissue-138-ozette.pq",
28+
]
29+
with zipfile.ZipFile(archive, "r") as zip_ref:
30+
for file in files:
31+
zip_ref.extract(file, path=archive.parent)
32+
return (
33+
archive.parent / "mair-2022-tissue-138-umap.pq",
34+
archive.parent / "mair-2022-tissue-138-ozette.pq",
35+
)
36+
37+
38+
def write_notebook(output: Path):
39+
umap_path, ozette_path = download_data()
40+
source = textwrap.dedent(
41+
f"""
42+
import pandas as pd
43+
from cev.widgets import Embedding, EmbeddingComparisonWidget
44+
45+
umap_embedding = pd.read_parquet("{umap_path}").pipe(Embedding.from_ozette)
46+
ozette_embedding = pd.read_parquet("{ozette_path}").pipe(Embedding.from_ozette)
47+
48+
EmbeddingComparisonWidget(
49+
umap_embedding,
50+
ozette_embedding,
51+
titles=("Standard UMAP", "Annotation-Transformed UMAP"),
52+
metric="confusion",
53+
selection="synced",
54+
auto_zoom=True,
55+
row_height=320,
56+
)
57+
"""
58+
).strip()
59+
60+
nb = {
61+
"cells": [
62+
{
63+
"cell_type": "code",
64+
"execution_count": None,
65+
"metadata": {},
66+
"outputs": [],
67+
"source": source,
68+
}
69+
],
70+
"metadata": {
71+
"kernelspec": {
72+
"display_name": "Python 3",
73+
"language": "python",
74+
"name": "python3",
75+
}
76+
},
77+
"nbformat": 4,
78+
"nbformat_minor": 5,
79+
}
80+
with output.open("w") as f:
81+
json.dump(nb, f, indent=2)
82+
83+
84+
def check_uv_available():
85+
if shutil.which("uv") is None:
86+
print("Error: 'uv' command not found.", file=sys.stderr)
87+
print("Please install 'uv' to run `cev demo` entrypoint.", file=sys.stderr)
88+
print(
89+
"For more information, visit: https://github.com/astral-sh/uv",
90+
file=sys.stderr,
91+
)
92+
sys.exit(1)
93+
94+
95+
def run_notebook(notebook_path: Path):
96+
check_uv_available()
97+
command = [
98+
"uvx",
99+
"--python",
100+
"3.11",
101+
"--with",
102+
"." if _DEV else f"cev=={__version__}",
103+
"--with",
104+
"jupyterlab",
105+
"jupyter",
106+
"lab",
107+
str(notebook_path),
108+
]
109+
try:
110+
os.execvp(command[0], command)
111+
except OSError as e:
112+
print(f"Error executing {command[0]}: {e}", file=sys.stderr)
113+
sys.exit(1)
114+
115+
116+
def main():
117+
parser = argparse.ArgumentParser(prog="cev")
118+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
119+
subparsers.add_parser("download", help="Download the demo notebook (and data)")
120+
subparsers.add_parser("demo", help="Run the demo notebook in JupyterLab")
121+
args = parser.parse_args()
122+
123+
notebook_path = Path("cev-demo.ipynb")
124+
if args.command == "download":
125+
write_notebook(notebook_path)
126+
elif args.command == "demo":
127+
write_notebook(notebook_path)
128+
run_notebook(notebook_path)
129+
else:
130+
parser.print_help()
131+
132+
133+
if __name__ == "__main__":
134+
main()

src/cev/_version.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from importlib.metadata import PackageNotFoundError, version
2+
3+
try:
4+
__version__ = version("cev")
5+
except PackageNotFoundError:
6+
__version__ = "uninstalled"

0 commit comments

Comments
 (0)