Skip to content

Commit 1ed2b2f

Browse files
committed
Add visium HD nb
1 parent 8792ef9 commit 1ed2b2f

File tree

2 files changed

+33
-52
lines changed

2 files changed

+33
-52
lines changed

docs/notebooks/spatial_data_visium_hd.ipynb

Lines changed: 10 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -137,33 +137,6 @@
137137
"sdata"
138138
]
139139
},
140-
{
141-
"cell_type": "code",
142-
"execution_count": null,
143-
"metadata": {},
144-
"outputs": [],
145-
"source": [
146-
"# Test with spatialdata-plot"
147-
]
148-
},
149-
{
150-
"cell_type": "code",
151-
"execution_count": null,
152-
"metadata": {},
153-
"outputs": [],
154-
"source": [
155-
"import spatialdata_plot"
156-
]
157-
},
158-
{
159-
"cell_type": "code",
160-
"execution_count": null,
161-
"metadata": {},
162-
"outputs": [],
163-
"source": [
164-
"sdata.pl.render_images(\"Visium_HD_Mouse_Small_Intestine_full_image\").pl.render_labels(\"rasterized_016um\").pl.show(\"Visium_HD_Mouse_Small_Intestine\")"
165-
]
166-
},
167140
{
168141
"cell_type": "markdown",
169142
"metadata": {},
@@ -209,8 +182,17 @@
209182
" 'photometricInterpretation': 'RGB',\n",
210183
" }]),\n",
211184
"}, scope_prefix=get_initial_coordination_scope_prefix(\"A\", \"image\"))\n",
185+
"vc.link_views_by_dict([spatial, layer_controller], {\n",
186+
" 'segmentationLayer': CL([{\n",
187+
" 'segmentationChannel': CL([{\n",
188+
" 'spatialChannelOpacity': 0.5,\n",
189+
" 'obsColorEncoding': 'geneSelection',\n",
190+
" 'featureValueColormapRange': [0, 0.5],\n",
191+
" }])\n",
192+
" }]),\n",
193+
"}, scope_prefix=get_initial_coordination_scope_prefix(\"A\", \"obsSegmentations\"))\n",
212194
"obs_sets = vc.add_view(vt.OBS_SETS, dataset=dataset)\n",
213-
"vc.link_views([spatial, layer_controller, feature_list, obs_sets], ['obsType'], [wrapper.obs_type_label])\n",
195+
"vc.link_views([spatial, layer_controller, feature_list, obs_sets], ['obsType', 'featureSelection'], [wrapper.obs_type_label, ['AA986860']])\n",
214196
"\n",
215197
"# Layout the views\n",
216198
"vc.layout(spatial | (feature_list / layer_controller / obs_sets));"
@@ -233,16 +215,6 @@
233215
"vw"
234216
]
235217
},
236-
{
237-
"cell_type": "code",
238-
"execution_count": null,
239-
"metadata": {},
240-
"outputs": [],
241-
"source": [
242-
"import json\n",
243-
"print(json.dumps(vc.to_dict(base_url=f\"http://localhost:{vw.port}\")))"
244-
]
245-
},
246218
{
247219
"cell_type": "code",
248220
"execution_count": null,

src/vitessce/widget.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ def get_uid_str(uid):
445445
function VitessceWidget(props) {
446446
const { model, styleContainer } = props;
447447
448-
const [config, setConfig] = React.useState(prependBaseUrl(model.get('config'), model.get('proxy'), model.get('has_host_name')));
448+
const [config, setConfig] = React.useState(prependBaseUrl(model.get('_config'), model.get('proxy'), model.get('has_host_name')));
449449
const [validateConfig, setValidateConfig] = React.useState(true);
450450
const height = model.get('height');
451451
const theme = model.get('theme') === 'auto' ? (prefersDark ? 'dark' : 'light') : model.get('theme');
@@ -484,16 +484,16 @@ def get_uid_str(uid):
484484
// Config changed on JS side (from within <Vitessce/>),
485485
// send updated config to Python side.
486486
const onConfigChange = React.useCallback((config) => {
487-
model.set('config', config);
487+
model.set('_config', config);
488488
setValidateConfig(false);
489489
model.save_changes();
490490
}, [model]);
491491
492492
// Config changed on Python side,
493493
// pass to <Vitessce/> component to it is updated on JS side.
494494
React.useEffect(() => {
495-
model.on('change:config', () => {
496-
const newConfig = prependBaseUrl(model.get('config'), model.get('proxy'), model.get('has_host_name'));
495+
model.on('change:_config', () => {
496+
const newConfig = prependBaseUrl(model.get('_config'), model.get('proxy'), model.get('has_host_name'));
497497
498498
// Force a re-render and re-validation by setting a new config.uid value.
499499
// TODO: make this conditional on a parameter from Python.
@@ -622,7 +622,12 @@ class VitessceWidget(anywidget.AnyWidget):
622622
# Widget properties are defined as traitlets. Any property tagged with `sync=True`
623623
# is automatically synced to the frontend *any* time it changes in Python.
624624
# It is synced back to Python from the frontend *any* time the model is touched.
625-
config = Dict({}).tag(sync=True)
625+
_config = Dict({}).tag(sync=True)
626+
"""dict: Dictionary representation of the Vitessce JSON configuration. Synced via traitlets upon interactions."""
627+
628+
config = None
629+
"""VitessceConfig: The VitessceConfig instance used to create this widget. Not synced upon interactions."""
630+
626631
height = Int(600).tag(sync=True)
627632
theme = Unicode('auto').tag(sync=True)
628633
proxy = Bool(False).tag(sync=True)
@@ -631,7 +636,7 @@ class VitessceWidget(anywidget.AnyWidget):
631636

632637
next_port = DEFAULT_PORT
633638

634-
js_package_version = Unicode('3.6.11').tag(sync=True)
639+
js_package_version = Unicode('3.6.12').tag(sync=True)
635640
js_dev_mode = Bool(False).tag(sync=True)
636641
custom_js_url = Unicode('').tag(sync=True)
637642
plugin_esm = List(trait=Unicode(''), default_value=[]).tag(sync=True)
@@ -644,7 +649,7 @@ class VitessceWidget(anywidget.AnyWidget):
644649

645650
store_urls = List(trait=Unicode(''), default_value=[]).tag(sync=True)
646651

647-
def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=False, js_package_version='3.6.11', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, prefer_local=True, invoke_timeout=300000, invoke_batched=True, page_mode=False, page_esm=None, prevent_scroll=True):
652+
def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=False, js_package_version='3.6.12', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, prefer_local=True, invoke_timeout=300000, invoke_batched=True, page_mode=False, page_esm=None, prevent_scroll=True):
648653
"""
649654
Construct a new Vitessce widget.
650655
@@ -678,7 +683,11 @@ def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=
678683

679684
base_url, use_port, VitessceWidget.next_port = get_base_url_and_port(
680685
port, VitessceWidget.next_port, proxy=proxy)
681-
self.config_obj = config
686+
# Note:
687+
# - self.config is the VitessceConfig instance.
688+
# - self._config is the JSON configuration, synced via traitlets
689+
690+
self.config = config
682691
self.port = use_port
683692
config_dict = config.to_dict(base_url=base_url)
684693
routes = config.get_routes()
@@ -694,7 +703,7 @@ def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=
694703
uid_str = get_uid_str(uid)
695704

696705
super(VitessceWidget, self).__init__(
697-
config=config_dict, height=height, theme=theme, proxy=proxy,
706+
_config=config_dict, height=height, theme=theme, proxy=proxy,
698707
js_package_version=js_package_version, js_dev_mode=js_dev_mode, custom_js_url=custom_js_url,
699708
plugin_esm=plugin_esm, remount_on_uid_change=remount_on_uid_change,
700709
page_mode=page_mode, page_esm=('' if page_esm is None else page_esm),
@@ -712,14 +721,14 @@ def handle_config_change(change):
712721
# It is optional for plugins to implement on_config_change.
713722
pass
714723
if new_config is not None:
715-
self.config = new_config
724+
self._config = new_config
716725

717-
self.observe(handle_config_change, names=['config'])
726+
self.observe(handle_config_change, names=['_config'])
718727

719728
serve_routes(config, routes, use_port)
720729

721730
def _get_coordination_value(self, coordination_type, coordination_scope):
722-
obj = self.config['coordinationSpace'][coordination_type]
731+
obj = self._config['coordinationSpace'][coordination_type]
723732
obj_scopes = list(obj.keys())
724733
if coordination_scope is not None:
725734
if coordination_scope in obj_scopes:
@@ -742,7 +751,7 @@ def get_cell_selection(self, scope=None):
742751
return self._get_coordination_value('cellSelection', scope)
743752

744753
def close(self):
745-
self.config_obj.stop_server(self.port)
754+
self.config.stop_server(self.port)
746755
super().close()
747756

748757
@anywidget.experimental.command
@@ -780,7 +789,7 @@ def _plugin_command(self, params, buffers):
780789
# Launch Vitessce using plain HTML representation (no ipywidgets)
781790

782791

783-
def ipython_display(config, height=600, theme='auto', base_url=None, host_name=None, uid=None, port=None, proxy=False, js_package_version='3.6.11', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, page_mode=False, page_esm=None):
792+
def ipython_display(config, height=600, theme='auto', base_url=None, host_name=None, uid=None, port=None, proxy=False, js_package_version='3.6.12', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, page_mode=False, page_esm=None):
784793
from IPython.display import display, HTML
785794
uid_str = "vitessce" + get_uid_str(uid)
786795

0 commit comments

Comments
 (0)