diff --git a/jdaviz/app.py b/jdaviz/app.py index 2a462fc546..a9e16eea2c 100644 --- a/jdaviz/app.py +++ b/jdaviz/app.py @@ -354,11 +354,11 @@ def __init__(self, configuration=None, *args, **kwargs): # Key should be (data_label, statistic) and value the translated object. self._get_object_cache = {} self.hub.subscribe(self, SubsetUpdateMessage, - handler=lambda msg: self._clear_object_cache(msg.subset.label)) + handler=self._on_subset_update_message) # Subscribe to messages that result in changes to the layers self.hub.subscribe(self, AddDataMessage, - handler=self._on_layers_changed) + handler=self._on_add_data_message) self.hub.subscribe(self, RemoveDataMessage, handler=self._on_layers_changed) self.hub.subscribe(self, SubsetCreateMessage, @@ -366,6 +366,38 @@ def __init__(self, configuration=None, *args, **kwargs): self.hub.subscribe(self, SubsetDeleteMessage, handler=self._on_layers_changed) + def _update_live_plugin_results(self, trigger_data=None, trigger_subset=None): + # print("*** _update_live_plugin_results", trigger_data, trigger_subset) + for data in self.data_collection: + plugin_inputs = data.meta.get('_update_live_plugin_results', None) + if plugin_inputs is None: + continue + # print(f"*** {data.label}, {trigger_data}, {trigger_subset}") + # TODO: generalize to any data input (not just dataset) + if trigger_data is not None and plugin_inputs.get('dataset') != trigger_data: + continue + # TODO: generalize to any subset input (not just spectral_subset) + if trigger_subset is not None and plugin_inputs.get('spectral_subset') != trigger_subset: + continue + # update and overwrite data + print("*** UPDATING LIVE PLUGIN RESULTS FOR", data.label) + # make a new instance of the plugin to avoid changing any UI settings + plg = self._jdaviz_helper.plugins.get(data.meta.get('Plugin'))._obj.new() + plg.user_api.from_dict(plugin_inputs) + # still need to know the method to call to add the results... + if data.meta.get('Plugin') != 'Collapse': + raise NotImplementedError("currently hardcocded for collapse case") + plg.collapse(add_data=True) + + def _on_add_data_message(self, msg): + self._on_layers_changed(msg) + self._update_live_plugin_results(trigger_data=msg.data.label) + + def _on_subset_update_message(self, msg): + # NOTE: print statements in here will require the viewer output_widget + self._clear_object_cache(msg.subset.label) + self._update_live_plugin_results(trigger_subset=msg.subset.label) + @property def hub(self): """ diff --git a/jdaviz/components/plugin_add_results.vue b/jdaviz/components/plugin_add_results.vue index bdd7c4715c..a8c940fa00 100644 --- a/jdaviz/components/plugin_add_results.vue +++ b/jdaviz/components/plugin_add_results.vue @@ -52,6 +52,17 @@ + + + + + module.exports = { props: ['label', 'label_default', 'label_auto', 'label_invalid_msg', 'label_overwrite', 'label_label', 'label_hint', - 'add_to_viewer_items', 'add_to_viewer_selected', 'add_to_viewer_hint', + 'add_to_viewer_items', 'add_to_viewer_selected', 'auto_update_result', 'add_to_viewer_hint', 'action_disabled', 'action_spinner', 'action_label', 'action_tooltip'] }; diff --git a/jdaviz/configs/default/plugins/collapse/collapse.vue b/jdaviz/configs/default/plugins/collapse/collapse.vue index 4a29c467b4..20e048dc79 100644 --- a/jdaviz/configs/default/plugins/collapse/collapse.vue +++ b/jdaviz/configs/default/plugins/collapse/collapse.vue @@ -43,6 +43,7 @@ label_hint="Label for the collapsed cube" :add_to_viewer_items="add_to_viewer_items" :add_to_viewer_selected.sync="add_to_viewer_selected" + :auto_update_result.sync="auto_update_result" action_label="Collapse" action_tooltip="Collapse data" :action_spinner="spinner" diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index 1a4626b42c..f4ea62dd38 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -3262,6 +3262,8 @@ class AddResults(BasePluginComponent): * ``add_to_viewer_items`` (list of dicts: see ``ViewerSelect``) * ``add_to_viewer_selected`` (string: name of the viewer to add the results, see ``ViewerSelect``) + * ``auto_update_result`` (bool: whether the resulting data-product should be regenerated when + any input arguments are changed) Methods: @@ -3280,6 +3282,7 @@ class AddResults(BasePluginComponent): label_hint="Label for the smoothed data" :add_to_viewer_items="add_to_viewer_items" :add_to_viewer_selected.sync="add_to_viewer_selected" + :auto_update_result.sync="auto_update_result" action_label="Apply" action_tooltip="Apply the action to the data" @click:action="apply" @@ -3290,12 +3293,14 @@ class AddResults(BasePluginComponent): def __init__(self, plugin, label, label_default, label_auto, label_invalid_msg, label_overwrite, add_to_viewer_items, add_to_viewer_selected, + auto_update_result, label_whitelist_overwrite=[]): super().__init__(plugin, label=label, label_default=label_default, label_auto=label_auto, label_invalid_msg=label_invalid_msg, label_overwrite=label_overwrite, add_to_viewer_items=add_to_viewer_items, - add_to_viewer_selected=add_to_viewer_selected) + add_to_viewer_selected=add_to_viewer_selected, + auto_update_result=auto_update_result) # DataCollectionAdd/Delete are fired even if remain unchecked in all viewers self.hub.subscribe(self, DataCollectionAddMessage, @@ -3319,7 +3324,7 @@ def __repr__(self): @property def user_api(self): - return UserApiWrapper(self, ('label', 'auto', 'viewer')) + return UserApiWrapper(self, ('label', 'auto', 'viewer', 'auto_update_result')) @property def label(self): @@ -3432,6 +3437,10 @@ def add_results_from_plugin(self, data_item, replace=None, label=None): data_item.meta['Plugin'] = self._plugin.__class__.__name__ if self.app.config == 'mosviz': data_item.meta['mosviz_row'] = self.app.state.settings['mosviz_row'] + + if self.auto_update_result: + data_item.meta['_update_live_plugin_results'] = self.plugin.user_api.to_dict() + self.app.add_data(data_item, label) for viewer_ref, visible, preserved in zip(add_to_viewer_refs, add_to_viewer_vis, @@ -3481,6 +3490,7 @@ class AddResultsMixin(VuetifyTemplate, HubListener): label_hint="Label for the smoothed data" :add_to_viewer_items="add_to_viewer_items" :add_to_viewer_selected.sync="add_to_viewer_selected" + :auto_update_result.sync="auto_update_result" action_label="Apply" action_tooltip="Apply the action to the data" @click:action="apply" @@ -3496,12 +3506,15 @@ class AddResultsMixin(VuetifyTemplate, HubListener): add_to_viewer_items = List().tag(sync=True) add_to_viewer_selected = Unicode().tag(sync=True) + auto_update_result = Bool(False).tag(sync=True) + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_results = AddResults(self, 'results_label', 'results_label_default', 'results_label_auto', 'results_label_invalid_msg', 'results_label_overwrite', - 'add_to_viewer_items', 'add_to_viewer_selected') + 'add_to_viewer_items', 'add_to_viewer_selected', + 'auto_update_result') class PlotOptionsSyncState(BasePluginComponent):