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 e5cc63d0..3d70c112 100644
--- a/specviz/plugins/model_editor/model_editor.py
+++ b/specviz/plugins/model_editor/model_editor.py
@@ -41,8 +41,15 @@ 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._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
@@ -51,6 +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._on_create_new_model()
+
+ 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.")
@@ -74,16 +84,23 @@ def on_new_model_triggered(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)
@@ -124,8 +141,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..4812ebbf 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 adding 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())]