@@ -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