From 60f4e7ea5ed786bc2ac9fac82b08b33fd0bba7d4 Mon Sep 17 00:00:00 2001 From: nmearl Date: Mon, 29 Oct 2018 12:50:17 -0400 Subject: [PATCH 1/3] Disallow interaction until user has created a model --- specviz/plugins/model_editor/model_editor.py | 14 ++ specviz/plugins/model_editor/model_editor.ui | 175 +++++++++++++------ specviz/plugins/model_editor/models.py | 9 - 3 files changed, 138 insertions(+), 60 deletions(-) diff --git a/specviz/plugins/model_editor/model_editor.py b/specviz/plugins/model_editor/model_editor.py index e5cc63d0..7e35d475 100644 --- a/specviz/plugins/model_editor/model_editor.py +++ b/specviz/plugins/model_editor/model_editor.py @@ -41,8 +41,14 @@ def __init__(self, *args, **kwargs): action.triggered.connect(lambda x, m=v: self._add_fittable_model(m)) models_menu.addAction(action) + # Initially hide the model editor tools until user has selected an + # editable model spectrum object + self.editor_holder_widget.setHidden(True) + self.setup_holder_widget.setHidden(False) + self.equation_edit_button.clicked.connect( self._on_equation_edit_button_clicked) + self.new_model_button.clicked.connect(self._create_new_model) # When a plot data item is select, get its model editor model # representation @@ -51,6 +57,9 @@ def __init__(self, *args, **kwargs): @plugin.tool_bar(name="New Model", icon=QIcon(":/icons/012-file.svg")) def on_new_model_triggered(self): + self._create_new_model() + + def _create_new_model(self): if self.hub.data_item is None: message_box = QMessageBox() message_box.setText("No item selected, cannot create model.") @@ -124,8 +133,13 @@ def _on_equation_edit_button_clicked(self): def _on_plot_item_selected(self, plot_data_item): if not isinstance(plot_data_item.data_item, ModelDataItem): self.model_tree_view.setModel(None) + self.editor_holder_widget.setHidden(True) + self.setup_holder_widget.setHidden(False) return + self.editor_holder_widget.setHidden(False) + self.setup_holder_widget.setHidden(True) + model_data_item = plot_data_item.data_item # Set the model on the tree view and expand all children initially. diff --git a/specviz/plugins/model_editor/model_editor.ui b/specviz/plugins/model_editor/model_editor.ui index 900696cc..5f5ddea7 100644 --- a/specviz/plugins/model_editor/model_editor.ui +++ b/specviz/plugins/model_editor/model_editor.ui @@ -32,18 +32,60 @@ 0 - - - true - + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Create a new model-based spectrum object before addings sub models. + + + Qt::AlignCenter + + + true + + + + + + + Create New Model + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + - - - false - - + + 0 @@ -60,54 +102,85 @@ 0 - - - ... - - - - :/icons/plus.svg - - + + + true + - - - ... - - - - :/icons/minus.svg - + + + false + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ... + + + + :/icons/plus.svg + + + + + + + + ... + + + + :/icons/minus.svg + + + + + + + + ... + + + + :/icons/014-calculator.svg + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - ... - - - - :/icons/014-calculator.svg - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - diff --git a/specviz/plugins/model_editor/models.py b/specviz/plugins/model_editor/models.py index 70e49f0f..9a1cce44 100644 --- a/specviz/plugins/model_editor/models.py +++ b/specviz/plugins/model_editor/models.py @@ -20,15 +20,6 @@ def __init__(self, *args, **kwargs): self.setHorizontalHeaderLabels(["Name", "Value", "Unit", "Fixed"]) - from astropy.modeling.models import Gaussian1D, Linear1D - - a = Gaussian1D() - l = Linear1D() - - self.add_model(a) - self.add_model(l) - self.add_model(Gaussian1D()) - @property def items(self): return [self.item(idx) for idx in range(self.rowCount())] From f8694b8c54546b85783aa0026a6681558762b9b1 Mon Sep 17 00:00:00 2001 From: nmearl Date: Mon, 29 Oct 2018 12:52:23 -0400 Subject: [PATCH 2/3] Fix typo --- specviz/plugins/model_editor/model_editor.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specviz/plugins/model_editor/model_editor.ui b/specviz/plugins/model_editor/model_editor.ui index 5f5ddea7..4812ebbf 100644 --- a/specviz/plugins/model_editor/model_editor.ui +++ b/specviz/plugins/model_editor/model_editor.ui @@ -50,7 +50,7 @@ - Create a new model-based spectrum object before addings sub models. + Create a new model-based spectrum object before adding sub models. Qt::AlignCenter From 1e8982a2fd9536aaab7f4f6901eb9e65f0fc7451 Mon Sep 17 00:00:00 2001 From: nmearl Date: Tue, 30 Oct 2018 10:23:12 -0400 Subject: [PATCH 3/3] Fix crash when no compound model created; allow model removal --- specviz/core/hub.py | 39 +++++++++++++++++++- specviz/plugins/model_editor/items.py | 8 +++- specviz/plugins/model_editor/model_editor.py | 20 +++++++--- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/specviz/core/hub.py b/specviz/core/hub.py index f52a7063..d893da48 100644 --- a/specviz/core/hub.py +++ b/specviz/core/hub.py @@ -1,4 +1,6 @@ -from qtpy.QtWidgets import QApplication +import logging + +from .items import DataItem class Hub: @@ -73,6 +75,41 @@ def data_items(self): """List of all data items held in the data item model.""" return self.model.items + def append_data_item(self, data_item): + """ + Adds a new data item object to appear in the left data list view. + + Parameters + ---------- + data_item : :class:`~specviz.core.items.PlotDataItem` + The data item to be added to the list view. + """ + if isinstance(data_item, DataItem): + self.workspace.model.appendRow(data_item) + else: + logging.error("Data item model only accepts items of class " + "'DataItem', received '{}'.".format(type(data_item))) + + def plot_data_item_from_data_item(self, data_item): + """ + Returns the PlotDataItem associated with the provided DataItem. + + Parameters + ---------- + data_item : :class:`~specviz.core.items.PlotDataItem` + The DataItem from which the associated PlotDataItem will be + returned. + + Returns + ------- + plot_data_item : :class:`~specviz.core.items.PlotDataItem` + The PlotDataItem wrapping the DataItem. + """ + plot_data_item = self.workspace.proxy_model.item_from_id( + data_item.identifier) + + return plot_data_item + def set_active_plugin_bar(self, name=None, index=None): """ Sets the currently displayed widget in the plugin side panel. diff --git a/specviz/plugins/model_editor/items.py b/specviz/plugins/model_editor/items.py index 0fe43dbf..2fbfae87 100644 --- a/specviz/plugins/model_editor/items.py +++ b/specviz/plugins/model_editor/items.py @@ -1,5 +1,6 @@ +import numpy as np + from ...core.items import DataItem -import astropy.units as u class ModelDataItem(DataItem): @@ -15,7 +16,10 @@ def flux(self): result = self.model_editor_model.evaluate() - return result(self.spectral_axis.value) * self.data(self.DataRole).flux.unit + if result is not None: + return result(self.spectral_axis.value) * self.data(self.DataRole).flux.unit + + return np.zeros(self.spectral_axis.size) * self.data(self.DataRole).flux.unit @property def model_editor_model(self): diff --git a/specviz/plugins/model_editor/model_editor.py b/specviz/plugins/model_editor/model_editor.py index 7e35d475..3d70c112 100644 --- a/specviz/plugins/model_editor/model_editor.py +++ b/specviz/plugins/model_editor/model_editor.py @@ -48,7 +48,8 @@ def __init__(self, *args, **kwargs): self.equation_edit_button.clicked.connect( self._on_equation_edit_button_clicked) - self.new_model_button.clicked.connect(self._create_new_model) + self.new_model_button.clicked.connect(self._on_create_new_model) + self.remove_model_button.clicked.connect(self._on_remove_model) # When a plot data item is select, get its model editor model # representation @@ -57,9 +58,9 @@ def __init__(self, *args, **kwargs): @plugin.tool_bar(name="New Model", icon=QIcon(":/icons/012-file.svg")) def on_new_model_triggered(self): - self._create_new_model() + self._on_create_new_model() - def _create_new_model(self): + def _on_create_new_model(self): if self.hub.data_item is None: message_box = QMessageBox() message_box.setText("No item selected, cannot create model.") @@ -83,16 +84,23 @@ def _create_new_model(self): identifier=uuid.uuid4(), data=new_spec) - self.hub.workspace.model.appendRow(model_data_item) + self.hub.append_data_item(model_data_item) - plot_data_item = self.hub.workspace.proxy_model.item_from_id( - model_data_item.identifier) + plot_data_item = self.hub.plot_data_item_from_data_item(model_data_item) # Connect data change signals so that the plot updates when the user # changes a parameter in the model view model model_data_item.model_editor_model.dataChanged.connect( lambda tl, br, r, pi=plot_data_item: self._on_model_data_changed(tl, br, pi)) + def _on_remove_model(self): + """Remove an astropy model from the model editor tree view.""" + indexes = self.model_tree_view.selectionModel().selectedIndexes() + + if len(indexes) > 0: + selected_idx = indexes[0] + self.model_tree_view.model().removeRow(selected_idx.row()) + def _add_fittable_model(self, model): idx = self.model_tree_view.model().add_model(model()) self.model_tree_view.setExpanded(idx, True)