Skip to content

Commit d93cad3

Browse files
committed
Add comparative analysis notebook and fix configuration bug
1 parent a700de0 commit d93cad3

File tree

2 files changed

+399
-1
lines changed

2 files changed

+399
-1
lines changed
Lines changed: 398 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,398 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {
6+
"nbsphinx": "hidden"
7+
},
8+
"source": [
9+
"# Vitessce Widget Tutorial"
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {},
15+
"source": [
16+
"# Visualization of ComparativeData object"
17+
]
18+
},
19+
{
20+
"cell_type": "markdown",
21+
"metadata": {},
22+
"source": [
23+
"## Configure Vitessce"
24+
]
25+
},
26+
{
27+
"cell_type": "code",
28+
"execution_count": 1,
29+
"metadata": {},
30+
"outputs": [],
31+
"source": [
32+
"from oxc_py import transform\n",
33+
"from vitessce import VitessceConfig, hconcat, vconcat"
34+
]
35+
},
36+
{
37+
"cell_type": "markdown",
38+
"metadata": {},
39+
"source": [
40+
"## Configure the data and views"
41+
]
42+
},
43+
{
44+
"cell_type": "code",
45+
"execution_count": 2,
46+
"metadata": {},
47+
"outputs": [],
48+
"source": [
49+
"# Reference: https://github.com/vitessce/vitessce/blob/main/examples/configs/src/view-configs/kpmp-premiere.js"
50+
]
51+
},
52+
{
53+
"cell_type": "code",
54+
"execution_count": 3,
55+
"metadata": {},
56+
"outputs": [],
57+
"source": [
58+
"base_url = 'https://storage.googleapis.com/vitessce-demo-data/kpmp-jan-2025/kpmp_premiere_20250330.adata.zarr'"
59+
]
60+
},
61+
{
62+
"cell_type": "code",
63+
"execution_count": 4,
64+
"metadata": {},
65+
"outputs": [],
66+
"source": [
67+
"vc = VitessceConfig(schema_version=\"1.0.17\", name='Lake et al.')\n",
68+
"\n",
69+
"dataset = vc.add_dataset('lake_et_al').add_file(\n",
70+
" file_type='comparisonMetadata.anndata.zarr',\n",
71+
" url=base_url,\n",
72+
" options={\n",
73+
" \"path\": 'uns/comparison_metadata',\n",
74+
" },\n",
75+
" coordination_values={\n",
76+
" \"obsType\": 'cell',\n",
77+
" \"sampleType\": 'sample',\n",
78+
" },\n",
79+
").add_file(\n",
80+
" file_type='comparativeFeatureStats.anndata.zarr',\n",
81+
" url=base_url,\n",
82+
" options= {\n",
83+
" \"metadataPath\": 'uns/comparison_metadata',\n",
84+
" \"indexColumn\": 'names',\n",
85+
" \"pValueColumn\": 'pvals_adj',\n",
86+
" \"foldChangeColumn\": 'logfoldchanges',\n",
87+
" \"pValueAdjusted\": True,\n",
88+
" \"foldChangeTransformation\": 'log2',\n",
89+
" },\n",
90+
" coordination_values={\n",
91+
" \"obsType\": 'cell',\n",
92+
" \"sampleType\": 'sample',\n",
93+
" \"featureType\": 'gene',\n",
94+
" },\n",
95+
").add_file(\n",
96+
" file_type= 'comparativeObsSetStats.anndata.zarr',\n",
97+
" url= base_url,\n",
98+
" options= {\n",
99+
" \"metadataPath\": 'uns/comparison_metadata',\n",
100+
" \"indexColumn\": 'Cell Type',\n",
101+
" \"interceptExpectedSampleColumn\": 'Expected Sample_intercept',\n",
102+
" \"effectExpectedSampleColumn\": 'Expected Sample_effect',\n",
103+
" \"foldChangeColumn\": 'log2-fold change',\n",
104+
" \"foldChangeTransformation\": 'log2',\n",
105+
" \"isCredibleEffectColumn\": 'is_credible_effect',\n",
106+
" },\n",
107+
" coordination_values= {\n",
108+
" \"obsType\": 'cell',\n",
109+
" \"sampleType\": 'sample',\n",
110+
" },\n",
111+
").add_file(\n",
112+
" file_type='comparativeFeatureSetStats.anndata.zarr',\n",
113+
" url=base_url,\n",
114+
" options= {\n",
115+
" \"metadataPath\": 'uns/comparison_metadata',\n",
116+
" \"indexColumn\": 'pathway_name',\n",
117+
" \"termColumn\": 'pathway_term',\n",
118+
" \"pValueColumn\": 'pvals_adj',\n",
119+
" \"pValueAdjusted\": True,\n",
120+
" \"analysisType\": 'pertpy_hypergeometric',\n",
121+
" \"featureSetLibrary\": 'Reactome_2022',\n",
122+
" },\n",
123+
" coordination_values= {\n",
124+
" \"obsType\": 'cell',\n",
125+
" \"featureType\": 'gene',\n",
126+
" \"sampleType\": 'sample',\n",
127+
" },\n",
128+
").add_file(\n",
129+
" file_type='anndata.zarr',\n",
130+
" url=base_url,\n",
131+
" coordination_values={\n",
132+
" \"obsType\": 'cell',\n",
133+
" \"featureType\": 'gene',\n",
134+
" \"featureValueType\": 'expression',\n",
135+
" \"sampleType\": 'sample',\n",
136+
" },\n",
137+
" options={\n",
138+
" \"obsFeatureMatrix\": {\n",
139+
" \"path\": 'layers/pearson_residuals',\n",
140+
" },\n",
141+
" \"obsEmbedding\": [\n",
142+
" {\n",
143+
" \"path\": 'obsm/X_densmap',\n",
144+
" \"embeddingType\": 'densMAP',\n",
145+
" },\n",
146+
" ],\n",
147+
" \"obsSets\": [\n",
148+
" {\n",
149+
" \"name\": 'Cell Type',\n",
150+
" \"path\": 'obs/cell_type',\n",
151+
" },\n",
152+
" {\n",
153+
" \"name\": 'Subclass L1',\n",
154+
" \"path\": 'obs/subclass_l1',\n",
155+
" },\n",
156+
" {\n",
157+
" \"name\": 'Subclass L2',\n",
158+
" \"path\": 'obs/subclass_l2',\n",
159+
" },\n",
160+
" {\n",
161+
" \"name\": 'Donor ID',\n",
162+
" \"path\": 'obs/donor_id',\n",
163+
" },\n",
164+
" ],\n",
165+
" \"sampleEdges\": {\n",
166+
" \"path\": 'obs/SampleID',\n",
167+
" },\n",
168+
" },\n",
169+
").add_file(\n",
170+
" file_type='sampleSets.anndata.zarr',\n",
171+
" url=f\"{base_url}/uns/__all__.samples\",\n",
172+
" options={\n",
173+
" \"sampleSets\": [\n",
174+
" {\n",
175+
" \"name\": 'Disease Type',\n",
176+
" \"path\": 'diseasetype',\n",
177+
" },\n",
178+
" {\n",
179+
" \"name\": 'Adjudicated Category',\n",
180+
" \"path\": 'AdjudicatedCategory',\n",
181+
" },\n",
182+
" {\n",
183+
" \"name\": 'Enrollment Category',\n",
184+
" \"path\": 'EnrollmentCategory',\n",
185+
" },\n",
186+
" ],\n",
187+
" },\n",
188+
" coordination_values= {\n",
189+
" \"sampleType\": 'sample',\n",
190+
" },\n",
191+
")\n",
192+
"\n",
193+
"biomarkerSelect = vc.add_view('biomarkerSelect', dataset=dataset, uid='biomarker-select')\n",
194+
"comparativeHeading = vc.add_view('comparativeHeading', dataset=dataset, uid='comparative-heading')\n",
195+
"dualScatterplot = vc.add_view('dualScatterplot', dataset=dataset, uid='scatterplot')\n",
196+
"obsSets = vc.add_view('obsSets', dataset=dataset, uid='cell-sets')\n",
197+
"sampleSets = vc.add_view('sampleSetPairManager', dataset=dataset, uid='sample-sets')\n",
198+
"obsSetSizes = vc.add_view('obsSetSizes', dataset=dataset)\n",
199+
"featureList = vc.add_view('featureList', dataset=dataset)\n",
200+
"violinPlots = vc.add_view('obsSetFeatureValueDistribution', dataset=dataset, uid='violin-plot')\n",
201+
"dotPlot = vc.add_view('dotPlot', dataset=dataset, uid='dot-plot')\n",
202+
"treemap = vc.add_view('treemap', dataset=dataset, uid='treemap')\n",
203+
"volcanoPlot = vc.add_view('volcanoPlot', dataset=dataset, uid='volcano-plot')\n",
204+
"volcanoPlotTable = vc.add_view('featureStatsTable', dataset=dataset, uid='volcano-plot-table')\n",
205+
"obsSetCompositionBarPlot = vc.add_view('obsSetCompositionBarPlot', dataset=dataset, uid='sccoda-plot')\n",
206+
"featureSetEnrichmentBarPlot = vc.add_view('featureSetEnrichmentBarPlot', dataset=dataset, uid='pathways-plot')\n",
207+
"\n",
208+
"[sampleSetScope_caseControl] = vc.add_coordination('sampleSetSelection')\n",
209+
"sampleSetScope_caseControl.set_value([['Disease Type', 'CKD'], ['Disease Type', 'Reference']])\n",
210+
"\n",
211+
"[featureSelectionScope] = vc.add_coordination('featureSelection')\n",
212+
"featureSelectionScope.set_value(['UMOD', 'NPHS2'])\n",
213+
"\n",
214+
"vc.link_views_by_dict([dualScatterplot], {\n",
215+
" \"embeddingType\": 'densMAP',\n",
216+
" \"embeddingContoursVisible\": True,\n",
217+
" \"embeddingPointsVisible\": False,\n",
218+
" \"embeddingObsSetLabelsVisible\": True,\n",
219+
"}, meta=False);\n",
220+
"\n",
221+
"\n",
222+
"vc.link_views([biomarkerSelect, dualScatterplot, obsSets, obsSetSizes, featureList, violinPlots, dotPlot, treemap, volcanoPlot, volcanoPlotTable, comparativeHeading, obsSetCompositionBarPlot, featureSetEnrichmentBarPlot, sampleSets], ['sampleType'], ['sample'])\n",
223+
"\n",
224+
"vc.link_views_by_dict([biomarkerSelect, dualScatterplot, obsSets, obsSetSizes, featureList, violinPlots, dotPlot, treemap, volcanoPlot, volcanoPlotTable, comparativeHeading, obsSetCompositionBarPlot, featureSetEnrichmentBarPlot, sampleSets], {\n",
225+
" \"sampleSetSelection\": sampleSetScope_caseControl,\n",
226+
" \"featureSelection\": featureSelectionScope,\n",
227+
"}, meta=False)\n",
228+
"\n",
229+
"vc.link_views_by_dict([dualScatterplot, violinPlots, featureList, dotPlot], {\n",
230+
" # \"featureSelection\": ['UMOD', 'NPHS2'], // , 'ENSG00000074803', 'ENSG00000164825'],\n",
231+
" \"obsColorEncoding\": 'geneSelection',\n",
232+
" \"featureValueColormap\": 'jet',\n",
233+
" \"featureValueColormapRange\": [0, 0.25],\n",
234+
" \"featureAggregationStrategy\": None,\n",
235+
"}, meta=False)\n",
236+
"\n",
237+
"vc.layout(hconcat(\n",
238+
" vconcat(dualScatterplot, biomarkerSelect, comparativeHeading, obsSets, obsSetSizes, featureList),\n",
239+
" vconcat(treemap, featureSetEnrichmentBarPlot, violinPlots, dotPlot, obsSetCompositionBarPlot, sampleSets),\n",
240+
" volcanoPlotTable,\n",
241+
"));"
242+
]
243+
},
244+
{
245+
"cell_type": "code",
246+
"execution_count": 5,
247+
"metadata": {},
248+
"outputs": [],
249+
"source": [
250+
"# vc.to_dict(base_url=\"\")"
251+
]
252+
},
253+
{
254+
"cell_type": "markdown",
255+
"metadata": {
256+
"tags": []
257+
},
258+
"source": [
259+
"## Define the page layout"
260+
]
261+
},
262+
{
263+
"cell_type": "code",
264+
"execution_count": 6,
265+
"metadata": {},
266+
"outputs": [],
267+
"source": [
268+
"# Reference: https://github.com/vitessce/vitessce/blob/main/examples/configs/src/view-configs/lake-2023.js\n",
269+
"PAGE_ESM = transform(\"\"\"\n",
270+
"function createPage(utilsForPages) {\n",
271+
" const {\n",
272+
" React,\n",
273+
" usePageModeView,\n",
274+
" } = utilsForPages;\n",
275+
" function PageComponent(props) {\n",
276+
" const BiomarkerSelect = usePageModeView('biomarker-select');\n",
277+
" const DualScatterplot = usePageModeView('scatterplot');\n",
278+
" const CellSets = usePageModeView('cell-sets');\n",
279+
" const ViolinPlot = usePageModeView('violin-plot');\n",
280+
" const DotPlot = usePageModeView('dot-plot');\n",
281+
" \n",
282+
" return (\n",
283+
" <>\n",
284+
" <style>{`\n",
285+
" h1, h2, h3, h4, h5, h6 {\n",
286+
" font-family: sans-serif;\n",
287+
" }\n",
288+
" h1 {\n",
289+
" font-weight: normal;\n",
290+
" }\n",
291+
" h2 {\n",
292+
" font-size: 36px;\n",
293+
" }\n",
294+
" h3 {\n",
295+
" font-size: 28px;\n",
296+
" }\n",
297+
" `}\n",
298+
" </style>\n",
299+
" <div style={{ width: '100%' }}>\n",
300+
" <h1>Comparative visualization of single-cell atlas data</h1>\n",
301+
" <BiomarkerSelect />\n",
302+
" </div>\n",
303+
"\n",
304+
" <div style={{ width: '100%', display: 'flex', flexDirection: 'row' }}>\n",
305+
" <div style={{ width: '100%'}}>\n",
306+
" <div style={{ width: '100%', display: 'flex', flexDirection: 'row' }}>\n",
307+
" <div style={{ width: '45%' }}><h2>Chronic Kidney Disease</h2></div>\n",
308+
" <div style={{ width: '5%' }}><h2 style={{ textAlign: 'right' }}>vs.&nbsp;</h2></div>\n",
309+
" <div style={{ width: '50%' }}><h2>Healthy Reference</h2></div>\n",
310+
" </div>\n",
311+
" <h3>Cell type-level representations</h3>\n",
312+
" <div style={{ width: '100%', height: '500px' }}>\n",
313+
" <DualScatterplot />\n",
314+
" </div>\n",
315+
" <div style={{ width: '100%', height: '500px' }}>\n",
316+
" <ViolinPlot />\n",
317+
" </div>\n",
318+
" <div style={{ width: '100%', height: '500px' }}>\n",
319+
" <DotPlot />\n",
320+
" </div>\n",
321+
" </div>\n",
322+
" <div style={{ width: '14%', height: '500px', marginTop: '213px' }}>\n",
323+
" <CellSets />\n",
324+
" </div>\n",
325+
" </div>\n",
326+
"\n",
327+
" </>\n",
328+
" );\n",
329+
" }\n",
330+
" return PageComponent;\n",
331+
"}\n",
332+
"export default { createPage };\n",
333+
"\"\"\")"
334+
]
335+
},
336+
{
337+
"cell_type": "markdown",
338+
"metadata": {},
339+
"source": [
340+
"## Render page as widget"
341+
]
342+
},
343+
{
344+
"cell_type": "code",
345+
"execution_count": 7,
346+
"metadata": {},
347+
"outputs": [
348+
{
349+
"data": {
350+
"application/vnd.jupyter.widget-view+json": {
351+
"model_id": "408477a5c11747ba8e531f0d9c5cd596",
352+
"version_major": 2,
353+
"version_minor": 1
354+
},
355+
"text/plain": [
356+
"VitessceWidget(config={'version': '1.0.17', 'name': 'Lake et al.', 'description': '', 'datasets': [{'uid': 'A'…"
357+
]
358+
},
359+
"execution_count": 7,
360+
"metadata": {},
361+
"output_type": "execute_result"
362+
}
363+
],
364+
"source": [
365+
"vw = vc.widget(page_esm=PAGE_ESM, page_mode=True, height=3000)\n",
366+
"vw"
367+
]
368+
},
369+
{
370+
"cell_type": "code",
371+
"execution_count": null,
372+
"metadata": {},
373+
"outputs": [],
374+
"source": []
375+
}
376+
],
377+
"metadata": {
378+
"kernelspec": {
379+
"display_name": "Python 3 (ipykernel)",
380+
"language": "python",
381+
"name": "python3"
382+
},
383+
"language_info": {
384+
"codemirror_mode": {
385+
"name": "ipython",
386+
"version": 3
387+
},
388+
"file_extension": ".py",
389+
"mimetype": "text/x-python",
390+
"name": "python",
391+
"nbconvert_exporter": "python",
392+
"pygments_lexer": "ipython3",
393+
"version": "3.10.14"
394+
}
395+
},
396+
"nbformat": 4,
397+
"nbformat_minor": 4
398+
}

0 commit comments

Comments
 (0)