Skip to content

Commit

Permalink
Merge pull request #1775 from SasView/504-slider-fixes
Browse files Browse the repository at this point in the history
5.0.4: Fix errors on data deletion and project load
  • Loading branch information
Wojciech Potrzebowski committed Feb 4, 2021
2 parents 8a2e762 + d140858 commit aa50173
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 19 deletions.
29 changes: 27 additions & 2 deletions src/sas/qtgui/MainWindow/DataExplorer.py
Expand Up @@ -398,13 +398,36 @@ def allDataForModel(self, model):
if data is None: continue
# Now, all plots under this item
name = data.name
######################################################
# Reset all slider values in data so save/load does not choke on them
# Remove once slider definition moved out of PlotterData
data.slider_low_q_setter = None
data.slider_high_q_setter = None
data.slider_low_q_input = None
data.slider_high_q_input = None
data.slider_update_on_move = False
data.slider_low_q_getter = None
data.slider_high_q_getter = None
######################################################
is_checked = item.checkState()
properties['checked'] = is_checked
other_datas = []
# save underlying theories
other_datas = GuiUtils.plotsFromDisplayName(name, model)
# skip the main plot
other_datas = list(other_datas.values())[1:]
for datas in other_datas:
######################################################
# Reset all slider values in data so save/load does not choke on them
# Remove once slider definition moved out of PlotterData
datas.slider_low_q_setter = None
datas.slider_high_q_setter = None
datas.slider_low_q_input = None
datas.slider_high_q_input = None
datas.slider_update_on_move = False
datas.slider_low_q_getter = None
datas.slider_high_q_getter = None
######################################################
all_data[data.id] = [data, properties, other_datas]
return all_data

Expand Down Expand Up @@ -1346,7 +1369,7 @@ def readData(self, path):
data_error = True

except Exception as ex:
logging.error(str(ex) + sys.exc_info()[1])
logging.error(str(ex) + str(sys.exc_info()[1]))

any_error = True
if any_error or data_error or error_message != "":
Expand Down Expand Up @@ -1678,7 +1701,7 @@ def showEditDataMask(self, data=None):
msg.exec_()
return
except Exception as ex:
logging.error(str(ex) + sys.exc_info()[1])
logging.error(str(ex) + str(sys.exc_info()[1]))
msg.exec_()
return

Expand Down Expand Up @@ -1750,6 +1773,8 @@ def deleteAllItems(self):
deleted_items += deleted_theory_items
deleted_names = [item.text() for item in deleted_items]
deleted_names += deleted_theory_items
# Close all active plots
self.closeAllPlots()
# Let others know we deleted data
self.communicator.dataDeletedSignal.emit(deleted_items)
# update stored_data
Expand Down
5 changes: 4 additions & 1 deletion src/sas/qtgui/MainWindow/GuiManager.py
Expand Up @@ -196,7 +196,8 @@ def closeAllPerspectives(self):
for name, perspective in self.loadedPerspectives.items():
try:
perspective.setClosable(True)
self._workspace.workspace.removeSubWindow(self.subwindow)
if self.subwindow in self._workspace.workspace.subWindowList():
self._workspace.workspace.removeSubWindow(self.subwindow)
perspective.close()
except Exception as e:
logger.warning(f"Unable to close {name} perspective\n{e}")
Expand Down Expand Up @@ -667,6 +668,8 @@ def actionSave_Project(self):
Menu Save Project
"""
filename = self.filesWidget.saveProject()
if not filename:
return

# datasets
all_data = self.filesWidget.getSerializedData()
Expand Down
30 changes: 20 additions & 10 deletions src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py
Expand Up @@ -204,8 +204,8 @@ def setupLinks(self):
lambda: self._calculator.set_alpha(is_float(self.regularizationConstantInput.text())))
self.maxDistanceInput.textChanged.connect(
lambda: self._calculator.set_dmax(is_float(self.maxDistanceInput.text())))
self.maxQInput.textChanged.connect(self.check_q_high)
self.minQInput.textChanged.connect(self.check_q_low)
self.maxQInput.editingFinished.connect(self.check_q_high)
self.minQInput.editingFinished.connect(self.check_q_low)
self.slitHeightInput.textChanged.connect(
lambda: self._calculator.set_slit_height(is_float(self.slitHeightInput.text())))
self.slitWidthInput.textChanged.connect(
Expand Down Expand Up @@ -454,11 +454,15 @@ def stopCalculation(self):
self.isCalculating = False
self.updateGuiValues()

def check_q_low(self, q_value):
def check_q_low(self, q_value=None):
""" Validate the low q value """
q_min = min(self._calculator.x)
q_max = self._calculator.get_qmax()
q_value = float(q_value)
if not q_value:
q_value = float(self.minQInput.text()) if self.minQInput.text() else ''
if q_value == '':
self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem(q_value))
return
q_min = min(self._calculator.x) if any(self._calculator.x) else -1 * np.inf
q_max = self._calculator.get_qmax() if self._calculator.get_qmax() is not None else np.inf
if q_value > q_max:
# Value too high - coerce to max q
self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem("{:.4g}".format(q_max)))
Expand All @@ -470,11 +474,15 @@ def check_q_low(self, q_value):
self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem("{:.4g}".format(q_value)))
self._calculator.set_qmin(q_value)

def check_q_high(self, q_value):
def check_q_high(self, q_value=None):
""" Validate the value of high q sent by the slider """
q_max = max(self._calculator.x)
q_min = self._calculator.get_qmin()
q_value = float(q_value)
if not q_value:
q_value = float(self.maxQInput.text()) if self.maxQInput.text() else ''
if q_value == '':
self.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem(q_value))
return
q_max = max(self._calculator.x) if any(self._calculator.x) else np.inf
q_min = self._calculator.get_qmin() if self._calculator.get_qmin() is not None else -1 * np.inf
if q_value > q_max:
# Value too high - coerce to max q
self.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem("{:.4g}".format(q_max)))
Expand Down Expand Up @@ -1042,7 +1050,9 @@ def _calculateUpdate(self, output_tuple):

self.dataPlot.show_q_range_sliders = True
self.dataPlot.slider_low_q_input = self.minQInput
self.dataPlot.slider_low_q_setter = self.check_q_low
self.dataPlot.slider_high_q_input = self.maxQInput
self.dataPlot.slider_high_q_setter = self.check_q_high

# Udpate internals and GUI
self.updateDataList(self._data)
Expand Down
5 changes: 5 additions & 0 deletions src/sas/qtgui/Plotting/Plotter.py
Expand Up @@ -11,6 +11,7 @@
from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterBase import PlotterBase
from sas.qtgui.Plotting.AddText import AddText
from sas.qtgui.Plotting.Binder import BindArtist
from sas.qtgui.Plotting.SetGraphRange import SetGraphRange
from sas.qtgui.Plotting.LinearFit import LinearFit
from sas.qtgui.Plotting.QRangeSlider import QRangeSlider
Expand Down Expand Up @@ -529,6 +530,7 @@ def removePlot(self, id):

# Remove the plot from the list of plots
self.plot_dict.pop(id)
self.sliders.pop(id, None)

# Labels might have been changed
xl = self.ax.xaxis.label.get_text()
Expand All @@ -537,6 +539,9 @@ def removePlot(self, id):
mpl.pyplot.cla()
self.ax.cla()

# Recreate Artist bindings after plot clear
self.connect = BindArtist(self.figure)

for ids in self.plot_dict:
if ids != id:
self.plot(data=self.plot_dict[ids], hide_error=self.plot_dict[ids].hide_error)
Expand Down
8 changes: 8 additions & 0 deletions src/sas/qtgui/Plotting/PlotterBase.py
Expand Up @@ -315,6 +315,7 @@ def closeEvent(self, event):
"""
Overwrite the close event adding helper notification
"""
self.clearQRangeSliders()
# Please remove me from your database.
PlotHelper.deletePlot(PlotHelper.idOfPlot(self))

Expand All @@ -323,6 +324,13 @@ def closeEvent(self, event):

event.accept()

def clearQRangeSliders(self):
# Destroy the Q-range sliders in 1D plots
if hasattr(self, 'sliders') and isinstance(self.sliders, dict):
for slider in self.sliders.values():
slider.clear()
self.sliders = {}

def onImageSave(self):
"""
Use the internal MPL method for saving to file
Expand Down
16 changes: 10 additions & 6 deletions src/sas/qtgui/Plotting/QRangeSlider.py
Expand Up @@ -57,8 +57,6 @@ def clear(self):
Clear this slicer and its markers
"""
self.clear_markers()
self.line_max.remove()
self.line_min.remove()

def update(self, x=None, y=None):
"""
Expand Down Expand Up @@ -91,9 +89,10 @@ def move(self, x, y, ev):

def clear_markers(self):
"""
Should be no way to clear the markers
Clear each of the lines individually
"""
pass
self.line_min.clear()
self.line_max.clear()

def draw(self):
"""
Expand Down Expand Up @@ -139,6 +138,7 @@ def validate(self, param_name, param_value):
return True

def clear(self):
self.clear_markers()
self.remove()

def remove(self):
Expand Down Expand Up @@ -230,6 +230,10 @@ def onRelease(self, ev):

def clear_markers(self):
"""
Should be no way to clear the markers
Disconnect the input and clear the callbacks
"""
pass
if self.input:
self.input.textChanged.disconnect(self.inputChanged)
self.setter = None
self.getter = None
self.input = None

0 comments on commit aa50173

Please sign in to comment.