Skip to content

Commit

Permalink
model fitting residuals
Browse files Browse the repository at this point in the history
  • Loading branch information
kecnry committed Nov 22, 2022
1 parent 0b9d469 commit c4061e2
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 10 deletions.
2 changes: 2 additions & 0 deletions jdaviz/components/plugin_add_results.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
</v-switch>
</v-row>

<slot></slot>

<v-row justify="end">
<j-tooltip :tooltipcontent="label_overwrite ? action_tooltip+' and replace existing entry' : action_tooltip">
<v-btn :disabled="label_invalid_msg.length > 0 || action_disabled"
Expand Down
24 changes: 23 additions & 1 deletion jdaviz/configs/default/plugins/model_fitting/model_fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ class ModelFitting(PluginTemplateMixin, DatasetSelectMixin,

cube_fit = Bool(False).tag(sync=True)

# residuals (non-cube fit only)
residuals_expose = Bool(False).tag(sync=True)
residuals_label = Unicode().tag(sync=True)
residuals_label_default = Unicode().tag(sync=True)
residuals_label_auto = Bool(True).tag(sync=True)
residuals_label_invalid_msg = Unicode('').tag(sync=True)

def __init__(self, *args, **kwargs):
self._spectrum1d = None
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -136,6 +143,9 @@ def __init__(self, *args, **kwargs):
self.equation = AutoTextField(self, 'model_equation', 'model_equation_default',
'model_equation_auto', 'model_equation_invalid_msg')

self.residuals = AutoTextField(self, 'residuals_label', 'residuals_label_default',
'residuals_label_auto', 'residuals_label_invalid_msg')

# set the filter on the viewer options
self._update_viewer_filters()

Expand All @@ -147,7 +157,7 @@ def user_api(self):
expose += ['spectral_subset', 'model_component', 'poly_order', 'model_component_label',
'model_components', 'create_model_component', 'remove_model_component',
'get_model_component', 'set_model_component',
'equation', 'add_results']
'equation', 'add_results', 'residuals_expose', 'residuals']
if self.config == "cubeviz":
expose += ['cube_fit']
expose += ['calculate_fit']
Expand Down Expand Up @@ -618,6 +628,10 @@ def _set_default_results_label(self, event={}):
label_comps += ["model"]
self.results_label_default = " ".join(label_comps)

@observe("results_label")
def _set_residuals_label_default(self, event={}):
self.residuals_label_default = self.results_label+" residuals"

@observe("cube_fit")
def _update_viewer_filters(self, event={}):
if event.get('new', self.cube_fit):
Expand Down Expand Up @@ -800,4 +814,12 @@ def _register_spectrum(self, event):
window=self._window)

self.add_results.add_results_from_plugin(spectrum)

if self.residuals_expose:
# NOTE: this will NOT load into the viewer since we have already called
# add_results_from_plugin above.
self.add_results.add_results_from_plugin(self._spectrum1d-spectrum,
label=self.residuals.value,
replace=False)

self._set_default_results_label()
24 changes: 23 additions & 1 deletion jdaviz/configs/default/plugins/model_fitting/model_fitting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,29 @@
action_tooltip="Fit the model to the data"
:action_disabled="model_equation_invalid_msg.length > 0"
@click:action="apply"
></plugin-add-results>
>
<div v-if="config!=='cubeviz' || !cube_fit">
<v-row>
<v-switch
v-model="residuals_expose"
label="Expose residiuals"
hint="Whether to compute and export residuals (data-model)."
persistent-hint
></v-switch>
</v-row>

<plugin-auto-label
v-if="residuals_expose"
:value.sync="residuals_label"
:default="residuals_label_default"
:auto.sync="residuals_label_auto"
:invalid_msg="residuals_label_invalid_msg"
label="Residuals Data Label"
hint="Label for the residuals. Data entry will not be loaded into the viewer automatically."
></plugin-auto-label>

</div>
</plugin-add-results>

<v-row>
<span class="v-messages v-messages__message text--secondary">
Expand Down
19 changes: 11 additions & 8 deletions jdaviz/core/template_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1669,14 +1669,17 @@ def _on_label_changed(self, msg={}):
self.label_invalid_msg = ''
self.label_overwrite = False

def add_results_from_plugin(self, data_item, replace=None):
def add_results_from_plugin(self, data_item, replace=None, label=None):
"""
Add ``data_item`` to the app's data_collection according to the default or user-provided
label and adds to any requested viewers.
"""
if self.label_invalid_msg:
raise ValueError(self.label_invalid_msg)

if label is None:
label = self.label

if replace is None:
replace = self.viewer.selected_reference != 'spectrum-viewer'

Expand All @@ -1687,29 +1690,29 @@ def add_results_from_plugin(self, data_item, replace=None):
viewer_item = self.app._viewer_item_by_reference(viewer_reference)
viewer = self.app.get_viewer(viewer_reference)
viewer_loaded_labels = [layer.layer.label for layer in viewer.layers]
add_to_viewer_selected = viewer_reference if self.label in viewer_loaded_labels else 'None' # noqa
visible = self.label in viewer_item['visible_layers']
add_to_viewer_selected = viewer_reference if label in viewer_loaded_labels else 'None' # noqa
visible = label in viewer_item['visible_layers']
else:
add_to_viewer_selected = self.add_to_viewer_selected
visible = True

if self.label in self.app.data_collection:
if label in self.app.data_collection:
if add_to_viewer_selected != 'None':
self.app.remove_data_from_viewer(self.viewer.selected_reference, self.label)
self.app.data_collection.remove(self.app.data_collection[self.label])
self.app.remove_data_from_viewer(self.viewer.selected_reference, label)
self.app.data_collection.remove(self.app.data_collection[label])

if not hasattr(data_item, 'meta'):
data_item.meta = {}
data_item.meta['Plugin'] = self._plugin.__class__.__name__
if self.app.config == 'mosviz':
data_item.meta['mosviz_row'] = self.app.state.settings['mosviz_row']
self.app.add_data(data_item, self.label)
self.app.add_data(data_item, label)

if add_to_viewer_selected != 'None':
# replace the contents in the selected viewer with the results from this plugin
# TODO: switch to an instance/classname check?
self.app.add_data_to_viewer(self.viewer.selected_id,
self.label,
label,
visible=visible, clear_other_data=replace)

# update overwrite warnings, etc
Expand Down

0 comments on commit c4061e2

Please sign in to comment.