Skip to content

Commit

Permalink
ENH: enable rerunning tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
leloup314 committed Nov 8, 2017
1 parent 8f77a49 commit b46c4f6
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 15 deletions.
41 changes: 36 additions & 5 deletions testbeam_analysis/gui/analysis_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class AnalysisWidget(QtWidgets.QWidget):
# Signal emitted when plotting is finished
plottingFinished = QtCore.pyqtSignal(str)

rerunSignal = QtCore.pyqtSignal(str)

def __init__(self, parent, setup, options, name, tab_list=None):
super(AnalysisWidget, self).__init__(parent)
self.setup = setup
Expand Down Expand Up @@ -115,12 +117,25 @@ def _setup(self):
self.layout_options.addLayout(self.opt_fixed)
self.layout_options.addStretch(0)

# Proceed button and progressbar
# Layout for proceed and rerun button
self.layout_buttons = QtWidgets.QHBoxLayout()
# Rerun, proceed button and progressbar
self.btn_rerun = QtWidgets.QPushButton(' Re-run')
self.btn_rerun.clicked.connect(lambda: self.rerunSignal.emit(self.name))
self.btn_rerun.setToolTip('Re-runs current tab and resets all following, dependent tabs')
self.btn_rerun.setVisible(False)
icon_rerun = QtWidgets.qApp.style().standardIcon(QtWidgets.qApp.style().SP_BrowserReload)
self.btn_rerun.setIcon(icon_rerun)
self.analysisDone.connect(lambda: self.btn_rerun.setVisible(True))
self.btn_ok = QtWidgets.QPushButton('Ok')
self.btn_ok.clicked.connect(lambda: self._call_funcs())
self.p_bar = AnalysisBar()
self.p_bar.setVisible(False)

# Add buttons to layout
self.layout_buttons.addWidget(self.btn_rerun)
self.layout_buttons.addWidget(self.btn_ok)

# Container widget to disable all but ok button after perfoming analysis
self.container = QtWidgets.QWidget()
self.container.setLayout(self.layout_options)
Expand All @@ -131,7 +146,7 @@ def _setup(self):

# Add container and ok button to right widget
self.scroll_widget.layout().addWidget(self.container)
self.scroll_widget.layout().addWidget(self.btn_ok)
self.scroll_widget.layout().addLayout(self.layout_buttons)

# Make right widget scroll able
self.scroll_area = QtWidgets.QScrollArea()
Expand Down Expand Up @@ -544,6 +559,7 @@ class ParallelAnalysisWidget(QtWidgets.QWidget):
parallelAnalysisDone = QtCore.pyqtSignal(list)
exceptionSignal = QtCore.pyqtSignal(Exception, str, str, str)
plottingFinished = QtCore.pyqtSignal(str)
rerunSignal = QtCore.pyqtSignal(str)

def __init__(self, parent, setup, options, name, tab_list=None):

Expand All @@ -553,17 +569,27 @@ def __init__(self, parent, setup, options, name, tab_list=None):
self.main_layout = QtWidgets.QVBoxLayout()
self.setLayout(self.main_layout)

# Add sub-layout and ok button and progressbar
# Add sub-layout and rerun / ok button and progressbar
self.sub_layout = QtWidgets.QHBoxLayout()
self.btn_rerun = QtWidgets.QPushButton(' Re-run')
self.btn_rerun.clicked.connect(lambda: self.rerunSignal.emit(self.name))
self.btn_rerun.setToolTip('Re-runs current tab and resets all following, dependent tabs')
self.btn_rerun.setVisible(False)
icon_rerun = QtWidgets.qApp.style().standardIcon(QtWidgets.qApp.style().SP_BrowserReload)
self.btn_rerun.setIcon(icon_rerun)
self.parallelAnalysisDone.connect(lambda: self.btn_rerun.setVisible(True))
self.parallelAnalysisDone.connect(lambda: self.handle_sub_layout(tab=self.tabs.currentIndex()))
self.btn_ok = QtWidgets.QPushButton('Ok')
self.btn_ok.clicked.connect(lambda: self._call_parallel_funcs())
self.p_bar = AnalysisBar()
self.p_bar.setVisible(False)

# Set alignment in sub-layout
self.sub_layout.addWidget(self.p_bar)
self.sub_layout.addWidget(self.btn_rerun)
self.sub_layout.addWidget(self.btn_ok)
self.sub_layout.setAlignment(self.p_bar, QtCore.Qt.AlignLeading)
self.sub_layout.setAlignment(self.btn_rerun, QtCore.Qt.AlignLeading)
self.sub_layout.setAlignment(self.btn_ok, QtCore.Qt.AlignTrailing)

# Tab related widgets
Expand Down Expand Up @@ -659,11 +685,16 @@ def showEvent(self, QShowEvent):

def handle_sub_layout(self, tab):

offset = 10
offset = 10 if not self.btn_rerun.isVisible() else 5
sub_widths = self.tw[self.tabs.tabText(tab)].widget_splitter.sizes()

self.btn_rerun.setFixedWidth(sub_widths[1] / 2 + offset)
self.p_bar.setFixedWidth(sub_widths[0] + offset)
self.btn_ok.setFixedWidth(sub_widths[1] + offset)

if not self.btn_rerun.isVisible():
self.btn_ok.setFixedWidth(sub_widths[1] + offset)
else:
self.btn_ok.setFixedWidth(sub_widths[1] / 2 + offset)

def add_parallel_function(self, func):

Expand Down
57 changes: 47 additions & 10 deletions testbeam_analysis/gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def handle_tabs(self, tabs=None, enable=True):
self.tabs.setTabEnabled(i, enable)

# Dis/enable specific tab
elif type(tabs) is unicode:
elif type(tabs) is unicode or type(tabs) is str:
if tabs in self.tab_order:
self.tabs.setTabEnabled(self.tab_order.index(tabs), enable)

Expand Down Expand Up @@ -311,6 +311,7 @@ def connect_tabs(self, tabs=None):

self.tw[name].proceedAnalysis.connect(lambda tab_names: self.handle_tabs(tabs=tab_names))
self.tw[name].proceedAnalysis.connect(lambda tab_names: self.tab_completed(tab_names))
self.tw[name].rerunSignal.connect(lambda tab: self.rerun_tab(tab=tab))
self.tw[name].exceptionSignal.connect(lambda e, trc_bck, tab, cause: self.handle_exceptions(exception=e,
trace_back=trc_bck,
tab=tab,
Expand All @@ -322,14 +323,15 @@ def connect_tabs(self, tabs=None):
else:
pass

def update_tabs(self, data=None, tabs=None, skip=None, exception=False):
def update_tabs(self, data=None, tabs=None, skip=None, exception=False, force=False):
"""
Updates the setup and options with data from the SetupTab and then updates the tabs
:param tabs: list of strings with tab names that should be updated, if None update all
:param data: dict with all information necessary to perform analysis, if None only update tabs
:param skip: str or list of tab names which should be skipped when updating tabs
:param exception: bool determine whether to update a running analysis tab; if exception is thrown, update
:param force: bool whether or not to update previously finished tabs
"""

# Save users current tab position
Expand Down Expand Up @@ -362,13 +364,14 @@ def update_tabs(self, data=None, tabs=None, skip=None, exception=False):
update_tabs.remove(skip)

# Remove tabs from being updated if they are already finished
for t in self.tab_order:
try:
if self.tw[t].isFinished:
if t in update_tabs:
update_tabs.remove(t)
except AttributeError:
pass
if not force:
for t in self.tab_order:
try:
if self.tw[t].isFinished:
if t in update_tabs:
update_tabs.remove(t)
except AttributeError:
pass

# Make temporary dict for updated tabs
tmp_tw = {}
Expand Down Expand Up @@ -439,7 +442,7 @@ def update_tabs(self, data=None, tabs=None, skip=None, exception=False):
try:
if self.tw[tab].analysis_thread.isRunning() and not exception:
continue
except AttributeError:
except (AttributeError, RuntimeError):
pass

# Replace tabs in self.tw with updated tabs
Expand Down Expand Up @@ -537,6 +540,40 @@ def load_session(self):
logging.info(message)
pass

def rerun_tab(self, tab):
"""
Reruns tab and resets/disables all subsequent tabs
:param tab:
"""

if self.tw[self.current_analysis_tab()].analysis_thread.isRunning() or\
self.tw[self.current_analysis_tab()].plotting_thread.isRunning():
msg = 'Can not re-run %s while %s analysis is running.' % (tab, self.current_analysis_tab())
logging.warning(msg=msg)
return

subsequent_tabs = []
for t in self.tab_order:
if self.tab_order.index(t) > self.tab_order.index(tab) and self.tw[t].isFinished:
subsequent_tabs.append(t)

if subsequent_tabs:
msg = 'Do you want to re-run %s analysis? All subsequent and previously run tabs (%s)' \
' will be reset and need to be run again.' % (tab, ', '.join(subsequent_tabs))
else:
msg = 'Do you want to re-run %s analysis? All subsequent tabs will be reset.' % tab
reply = QtWidgets.QMessageBox.question(self, 'Re-run %s tab?' % tab, msg, QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.Cancel)

if reply == QtWidgets.QMessageBox.Yes:
for tab_ in self.tab_order:
if self.tab_order.index(tab_) >= self.tab_order.index(tab):
if tab_ != tab:
self.tabs.setTabEnabled(self.tab_order.index(tab_), False)
self.update_tabs(tabs=tab_, force=True)
else:
pass

def new_analysis(self):
"""
Restores the initial state of the AnalysisWindow to re-start analysis
Expand Down

0 comments on commit b46c4f6

Please sign in to comment.