diff --git a/Makefile b/Makefile
index 8cc1e14..fe52acf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,6 @@
default:
make -C specdal/gui/pyqt
- pip uninstall -y specdal
- pip install .
+ python setup.py install
clean:
pip uninstall SpecDAL
diff --git a/setup.py b/setup.py
index bb626f3..88c7d4a 100644
--- a/setup.py
+++ b/setup.py
@@ -8,6 +8,7 @@
'bin/specdal_pipeline',
'bin/specdal_info',
'bin/specdal_gui',
+ 'bin/specdalqt',
],
entry_points={
'gui_scripts': ['specdal_gui = specdal.gui.viewer:main'],
diff --git a/specdal/gui/pyqt/collection_plotter.py b/specdal/gui/pyqt/collection_plotter.py
index 988ac25..9c2cd62 100644
--- a/specdal/gui/pyqt/collection_plotter.py
+++ b/specdal/gui/pyqt/collection_plotter.py
@@ -11,6 +11,71 @@
from matplotlib.figure import Figure
from matplotlib.patches import Rectangle
+def set_or_none(iterable):
+ if iterable is not None and not isinstance(iterable,set):
+ iterable = set(iterable)
+ return iterable
+
+class SpectrumArtist():
+ show_flagged = True
+ show_unselected = True
+
+ def __init__(self,artist):
+ self.artist = artist
+ self._flagged = False
+ self._selected = False
+ self._visible = True
+ self.style = '-'
+ self.color = 'k'
+
+ @property
+ def flagged(self):
+ return self._flagged
+
+ @flagged.setter
+ def flagged(self,value):
+ self._flagged = value
+ self.color = 'r' if self._flagged else 'k'
+ self._update_look()
+
+ @property
+ def selected(self):
+ return self._selected
+
+ @selected.setter
+ def selected(self,value):
+ self._selected = value
+ self.style = '--' if self._selected else '-'
+ self._update_look()
+
+ @property
+ def visible(self):
+ return self._visible
+
+ @visible.setter
+ def visible(self,value):
+ self._visible = value
+ if self._visible:
+ self.artist.set_linestyle(self.style)
+ else:
+ self.artist.set_linestyle('None')
+
+ def _calculate_visibility(self):
+ visible = True
+ if not self.selected and not self.show_unselected:
+ visible = False
+ if self.flagged and not self.show_flagged:
+ visible = False
+ self.visible = visible
+
+ def _update_look(self):
+ self._calculate_visibility()
+ if self.visible:
+ self.artist.set_color(self.color)
+ self.artist.set_linestyle(self.style)
+
+
+
class CollectionCanvas(FigureCanvasQTAgg):
"""Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
@@ -32,21 +97,22 @@ def __init__(self, parent=None, width=5, height=4, dpi=100):
QtWidgets.QSizePolicy.Expanding)
FigureCanvasQTAgg.updateGeometry(self)
- @property
- def unselected_style(self):
- return self._unselected_style
- @unselected_style.setter
- def unselected_style(self,value):
- self._unselected_style = value
+ @property
+ def show_unselected(self):
+ pass
+
+ @show_unselected.setter
+ def show_unselected(self,value):
+ SpectrumArtist.show_unselected = value
@property
- def flag_style(self):
- return self._flag_style
+ def show_flagged(self):
+ pass
- @flag_style.setter
- def flag_style(self,value):
- self._flag_style = value
+ @show_flagged.setter
+ def show_flagged(self,value):
+ SpectrumArtist.show_flagged = value
def rectangleStartEvent(self,event):
self._rect = None
@@ -125,75 +191,50 @@ def suspendMouseNavigation(self):
def update_selected(self,selected_keys,only_add=False):
# better lookup time
- if not isinstance(selected_keys,set):
- selected_keys = set(selected_keys)
+ selected_keys = set_or_none(selected_keys)
if only_add:
# if we're only adding, just select
for key in selected_keys:
- self.artist_dict[key].set_linestyle('--')
+ self.artist_dict[key].selected = True
else:
# otherwise, unselect everything that isn't selected
keys = self.artist_dict.keys()
for key in keys:
- if self.artist_dict[key].get_linestyle() == 'None' and \
- self.artist_dict[key].get_color() == 'r':
- continue
- if key in selected_keys:
- self.artist_dict[key].set_linestyle('--')
- else:
- self.artist_dict[key].set_linestyle(self.unselected_style)
+ self.artist_dict[key].selected = key in selected_keys
self.draw()
- def add_flagged(self,flagged_keys,selected_keys=None):
+ def set_flagged(self,flagged_keys,selected_keys=None,flag=True):
# better lookup time
- if not isinstance(flagged_keys,set):
- flagged_keys = set(flagged_keys)
- if selected_keys is not None and not isinstance(selected_keys,set):
- selected_keys = set(selected_keys)
+ flagged_keys = set_or_none(flagged_keys)
+ selected_keys = set_or_none(selected_keys)
for key in flagged_keys:
- if self.flag_style in 'rk':
- self.artist_dict[key].set_color(self.flag_style)
- if selected_keys is not None:
- style = '--' if key in selected_keys else self.unselected_style
- self.artist_dict[key].set_linestyle(style)
- else:
- self.artist_dict[key].set_color('r')
- self.artist_dict[key].set_linestyle(self.flag_style)
+ self.artist_dict[key].flagged = flag
+
self.draw()
+ def add_flagged(self,unflagged_keys,selected_keys=None):
+ self.set_flagged(unflagged_keys,selected_keys,True)
+
def remove_flagged(self,unflagged_keys,selected_keys=None):
- old_style = self.flag_style
- self.flag_style = 'k'
- self.add_flagged(unflagged_keys,selected_keys)
- self.flag_style = old_style
+ self.set_flagged(unflagged_keys,selected_keys,False)
def update_artists(self,collection,new_lim=False):
if collection is None:
return
- #update values being plotted -> redo statistics
- self.mean_line = None
- self.median_line = None
- self.max_line = None
- self.min_line = None
- self.std_line = None
# save limits
if new_lim == False:
xlim = self.ax.get_xlim()
ylim = self.ax.get_ylim()
# plot
self.ax.clear()
- flag_style = self.flag_style
- unselected_style = self.unselected_style
- flags = [s.name in collection.flags for s in collection.spectra]
- collection.plot(ax=self.ax,
- style=list(np.where(flags, flag_style, 'k')),
- picker=1)
+ collection.plot(ax=self.ax, style='k', picker=1)
#self.ax.set_title(collection.name)
-
keys = [s.name for s in collection.spectra]
artists = self.ax.lines
- self.artist_dict = {key:artist for key,artist in zip(keys,artists)}
- self.colors = {key:'k' for key in keys}
+ self.artist_dict = {key:SpectrumArtist(artist)
+ for key,artist in zip(keys,artists)}
+ for key in collection.flags:
+ self.artist_dict[key].flagged = True
self.ax.legend().remove()
self.ax.grid(True)
self.draw()
@@ -271,7 +312,7 @@ def _icon_of(name,fname,description, idx=None):
_icon_of("jump","icons8-jump-correct-32.png","Jump Correct")
_icon_of("interpolate","icons8-interpolate-32.png","Interpolate")
_icon_of("proximal","icons8-proximal-join.png","Proximal Join")
- _icon_of("reset","icons8-restart-32.png","Undo Operations")
+ _icon_of("reset","icons8-restart-32.png","Revert Operators")
self.insertSeparator(self.icons['flag'])
self.insertSeparator(self.icons['operators'])
diff --git a/specdal/gui/pyqt/qt_viewer.ui b/specdal/gui/pyqt/qt_viewer.ui
index 542862c..e9848e7 100644
--- a/specdal/gui/pyqt/qt_viewer.ui
+++ b/specdal/gui/pyqt/qt_viewer.ui
@@ -74,6 +74,22 @@
0
+ -
+
+
+ Select Group:
+
+
+
+ -
+
+
-
+
+ --
+
+
+
+
-
@@ -106,32 +122,32 @@
- -
-
+
-
+
-
+
0
0
-
-
-
- Name for Group
+ Name Group
- -
-
+
-
+
-
+
0
0
- Group Selection
+
+
+
+ Name for Selection
diff --git a/specdal/gui/pyqt/qt_viewer_ui.py b/specdal/gui/pyqt/qt_viewer_ui.py
index 54057b6..a7928d8 100644
--- a/specdal/gui/pyqt/qt_viewer_ui.py
+++ b/specdal/gui/pyqt/qt_viewer_ui.py
@@ -52,6 +52,13 @@ def setupUi(self, MainWindow):
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setContentsMargins(-1, -1, -1, 0)
self.gridLayout.setObjectName("gridLayout")
+ self.label = QtWidgets.QLabel(self.layoutWidget)
+ self.label.setObjectName("label")
+ self.gridLayout.addWidget(self.label, 2, 0, 1, 1)
+ self.comboBox = QtWidgets.QComboBox(self.layoutWidget)
+ self.comboBox.setObjectName("comboBox")
+ self.comboBox.addItem("")
+ self.gridLayout.addWidget(self.comboBox, 2, 1, 1, 1)
self.nameSelection = QtWidgets.QLineEdit(self.layoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@@ -69,6 +76,14 @@ def setupUi(self, MainWindow):
self.selectByName.setSizePolicy(sizePolicy)
self.selectByName.setObjectName("selectByName")
self.gridLayout.addWidget(self.selectByName, 0, 1, 1, 1)
+ self.createGroup = QtWidgets.QPushButton(self.layoutWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.createGroup.sizePolicy().hasHeightForWidth())
+ self.createGroup.setSizePolicy(sizePolicy)
+ self.createGroup.setObjectName("createGroup")
+ self.gridLayout.addWidget(self.createGroup, 1, 1, 1, 1)
self.groupName = QtWidgets.QLineEdit(self.layoutWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@@ -78,14 +93,6 @@ def setupUi(self, MainWindow):
self.groupName.setText("")
self.groupName.setObjectName("groupName")
self.gridLayout.addWidget(self.groupName, 1, 0, 1, 1)
- self.createGroup = QtWidgets.QPushButton(self.layoutWidget)
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.createGroup.sizePolicy().hasHeightForWidth())
- self.createGroup.setSizePolicy(sizePolicy)
- self.createGroup.setObjectName("createGroup")
- self.gridLayout.addWidget(self.createGroup, 1, 1, 1, 1)
self.verticalLayout_2.addLayout(self.gridLayout)
self.onlyShowSelected = QtWidgets.QCheckBox(self.layoutWidget)
self.onlyShowSelected.setObjectName("onlyShowSelected")
@@ -206,11 +213,13 @@ def setupUi(self, MainWindow):
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "SpecDAL GUI"))
+ self.label.setText(_translate("MainWindow", "Select Group:"))
+ self.comboBox.setItemText(0, _translate("MainWindow", "--"))
self.nameSelection.setToolTip(_translate("MainWindow", "Select Spectra by Name"))
self.nameSelection.setPlaceholderText(_translate("MainWindow", "Select by Name"))
self.selectByName.setText(_translate("MainWindow", "Select"))
- self.groupName.setPlaceholderText(_translate("MainWindow", "Name for Group"))
- self.createGroup.setText(_translate("MainWindow", "Group Selection"))
+ self.createGroup.setText(_translate("MainWindow", "Name Group"))
+ self.groupName.setPlaceholderText(_translate("MainWindow", "Name for Selection"))
self.onlyShowSelected.setText(_translate("MainWindow", "Only Show Selected"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
diff --git a/specdal/gui/pyqt/viewer.py b/specdal/gui/pyqt/viewer.py
index 8faf12a..cf62e50 100644
--- a/specdal/gui/pyqt/viewer.py
+++ b/specdal/gui/pyqt/viewer.py
@@ -231,6 +231,7 @@ def __init__(self,parent=None):
self.navbar.triggered('export').connect(self._export_flags)
# Operators
self.navbar.triggered('operators').connect(self.openOperatorConfig)
+ # TODO: Implement statistic plotting
self.navbar.triggered('stats').connect(
lambda:self.openOperatorConfig('stats'))
self.navbar.triggered('jump').connect(
@@ -330,6 +331,8 @@ def _restore_dataset(self):
if self._directory is not None:
self._open_dataset(self._directory)
# restore flags
+ for flag in flags:
+ self._collection.flag(flag)
self.canvas.add_flagged(flags)
# restore groups
@@ -471,15 +474,14 @@ def unflagFromList(self):
self.canvas.remove_flagged(self.selection_text)
def toggleSelectedVisibility(self,state):
- self.show_selected = not state
- self.canvas.unselected_style = '-' if self.show_selected else 'None'
- print(self.canvas.unselected_style)
+ self.show_unselected = not state
+ self.canvas.show_unselected = self.show_unselected
if self._collection:
self.canvas.update_selected(self.selection_text)
def toggleFlagVisibility(self):
self.show_flagged = not self.show_flagged
- self.canvas.flag_style = 'r' if self.show_flagged else 'None'
+ self.canvas.show_flagged = self.show_flagged
if self._collection:
self.canvas.add_flagged(self._collection.flags,self.selection_text)