Skip to content

Commit

Permalink
moved logic for artist styling into its own class
Browse files Browse the repository at this point in the history
  • Loading branch information
westphallm1 committed Apr 30, 2019
1 parent ef88bf7 commit 2a48720
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 81 deletions.
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
default:
make -C specdal/gui/pyqt
pip uninstall -y specdal
pip install .
python setup.py install

clean:
pip uninstall SpecDAL
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Expand Down
149 changes: 95 additions & 54 deletions specdal/gui/pyqt/collection_plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.)."""

Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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'])

Expand Down
38 changes: 27 additions & 11 deletions specdal/gui/pyqt/qt_viewer.ui
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Select Group:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBox">
<item>
<property name="text">
<string>--</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLineEdit" name="nameSelection">
<property name="sizePolicy">
Expand Down Expand Up @@ -106,32 +122,32 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="groupName">
<item row="1" column="1">
<widget class="QPushButton" name="createGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Name for Group</string>
<string>Name Group</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="createGroup">
<item row="1" column="0">
<widget class="QLineEdit" name="groupName">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Group Selection</string>
<string/>
</property>
<property name="placeholderText">
<string>Name for Selection</string>
</property>
</widget>
</item>
Expand Down
29 changes: 19 additions & 10 deletions specdal/gui/pyqt/qt_viewer_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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")
Expand Down Expand Up @@ -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"))
Expand Down
10 changes: 6 additions & 4 deletions specdal/gui/pyqt/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)

Expand Down

0 comments on commit 2a48720

Please sign in to comment.