Skip to content

Commit

Permalink
Merge pull request #2448 from SasView/2447-plot-roles
Browse files Browse the repository at this point in the history
2447 plot roles
  • Loading branch information
butlerpd authored Mar 14, 2023
2 parents 951b732 + 0de5691 commit b956b61
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 48 deletions.
19 changes: 10 additions & 9 deletions src/sas/qtgui/MainWindow/DataExplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data2D
from sas.qtgui.Plotting.PlotterData import DataRole
from sas.qtgui.Plotting.Plotter import Plotter
from sas.qtgui.Plotting.Plotter2D import Plotter2D
from sas.qtgui.Plotting.MaskEditor import MaskEditor
Expand Down Expand Up @@ -1043,7 +1044,7 @@ def displayDataByName(self, name=None, is_data=True, id=None):
or name in plot.name
or name == plot.filename):
# Residuals get their own plot
if plot.plot_role == Data1D.ROLE_RESIDUAL:
if plot.plot_role in [DataRole.ROLE_RESIDUAL, DataRole.ROLE_STAND_ALONE]:
plot.yscale = 'linear'
self.plotData([(item, plot)])
else:
Expand Down Expand Up @@ -1090,13 +1091,13 @@ def displayData(self, data_list, id=None):

plot_name = plot_to_show.name
role = plot_to_show.plot_role
stand_alone_types = [DataRole.ROLE_RESIDUAL, DataRole.ROLE_STAND_ALONE]

if (role == Data1D.ROLE_RESIDUAL and shown) or role == Data1D.ROLE_DELETABLE:
# Nothing to do if separate plot already shown or to be deleted
if (role in stand_alone_types and shown) or role == DataRole.ROLE_DELETABLE:
# Nothing to do if stand-alone plot already shown or plot to be deleted
continue
elif role == Data1D.ROLE_RESIDUAL:
# Residual plots should always be separate
plot_to_show.yscale='linear'
elif role in stand_alone_types:
# Stand-alone plots should always be separate
self.plotData([(plot_item, plot_to_show)])
elif append:
# Assume all other plots sent together should be on the same chart if a previous plot exists
Expand Down Expand Up @@ -1128,7 +1129,7 @@ def isPlotShown(self, plot):
if not hasattr(plot, 'name'):
return False
ids_vals = [val.data[0].name for val in self.active_plots.values()]
#if val.data[0].plot_role != Data1D.ROLE_DATA]
#if val.data[0].plot_role != DataRole.ROLE_DATA]

return plot.name in ids_vals

Expand Down Expand Up @@ -1271,13 +1272,13 @@ def updatePlot(self, data):
data_id = data.name
if data_id in ids_keys:
# We have data, let's replace data that needs replacing
if data.plot_role != Data1D.ROLE_DATA:
if data.plot_role != DataRole.ROLE_DATA:
self.active_plots[data_id].replacePlot(data_id, data)
# restore minimized window, if applicable
self.active_plots[data_id].showNormal()
return True
#elif data_id in ids_vals:
# if data.plot_role != Data1D.ROLE_DATA:
# if data.plot_role != DataRole.ROLE_DATA:
# list(self.active_plots.values())[ids_vals.index(data_id)].replacePlot(data_id, data)
# self.active_plots[data_id].showNormal()
# return True
Expand Down
4 changes: 2 additions & 2 deletions src/sas/qtgui/MainWindow/DataManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from io import BytesIO
import numpy as np

from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data1D, DataRole
from sas.qtgui.Plotting.PlotterData import Data2D
from sas.qtgui.Plotting.Plottables import PlottableTheory1D
from sas.qtgui.Plotting.Plottables import PlottableFit1D
Expand Down Expand Up @@ -128,7 +128,7 @@ def create_gui_data(self, data, path=None):
new_plot.path = path
new_plot.list_group_id = []
# Assign the plot role to data
new_plot.plot_role = Data1D.ROLE_DATA
new_plot.plot_role = DataRole.ROLE_DATA
##post data to plot
# plot data
return new_plot
Expand Down
19 changes: 9 additions & 10 deletions src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from mpl_toolkits.mplot3d import Axes3D

# Local
from sas.qtgui.Plotting.PlotterData import Data1D, Data2D
from sas.qtgui.Plotting.PlotterData import Data1D, Data2D, DataRole
from sasdata.dataloader.loader import Loader
from sas.qtgui.MainWindow.DataManager import DataManager

Expand Down Expand Up @@ -1132,7 +1132,6 @@ def testClosePlotsForItem(self, form):
assert len(PlotHelper.currentPlotIds()) == 0
assert len(form.plot_widgets) == 0

@pytest.mark.xfail(reason="2022-09 already broken")
def testPlotsFromMultipleData1D(self, form):
"""
Tests interplay between plotting 1D datasets and plotting
Expand All @@ -1143,19 +1142,19 @@ def testPlotsFromMultipleData1D(self, form):
plot1 = Plotter(parent=form)
data1 = Data1D()
data1.name = 'p1'
data1.plot_role = Data1D.ROLE_DATA
data1.plot_role = DataRole.ROLE_DATA
plot1.data = data1

plot2 = Plotter(parent=form)
data2 = Data1D()
data2.name = 'M2 [p1]'
data2.plot_role = Data1D.ROLE_DEFAULT
data2.plot_role = DataRole.ROLE_DEFAULT
plot2.data = data2

plot3 = Plotter(parent=form)
data3 = Data1D()
data3.name = 'Residuals for M2[p1]'
data3.plot_role = Data1D.ROLE_RESIDUAL
data3.plot_role = DataRole.ROLE_RESIDUAL
plot3.data = data3

# pretend we're displaying three plots
Expand All @@ -1165,7 +1164,7 @@ def testPlotsFromMultipleData1D(self, form):

# redoing plots from the same tab
# data -> must be shown
assert not form.isPlotShown(data1)
assert form.isPlotShown(data1)

# model and residuals are already shown
assert form.isPlotShown(data2)
Expand All @@ -1175,7 +1174,7 @@ def testPlotsFromMultipleData1D(self, form):
plot4 = Plotter(parent=form)
data4 = Data1D()
data4.name = 'M1 [p1]'
data4.plot_role = Data1D.ROLE_DEFAULT
data4.plot_role = DataRole.ROLE_DEFAULT
plot4.data = data1
# same data but must show, since different model
assert not form.isPlotShown(data4)
Expand All @@ -1190,19 +1189,19 @@ def testPlotsFromMultipleData2D(self, form):
plot1 = Plotter(parent=form)
data1 = Data2D()
data1.name = 'p1'
data1.plot_role = Data1D.ROLE_DATA
data1.plot_role = DataRole.ROLE_DATA
plot1.data = data1

plot2 = Plotter(parent=form)
data2 = Data2D()
data2.name = 'M2 [p1]'
data2.plot_role = Data1D.ROLE_DEFAULT
data2.plot_role = DataRole.ROLE_DEFAULT
plot2.data = data2

plot3 = Plotter(parent=form)
data3 = Data2D()
data3.name = 'Residuals for M2[p1]'
data3.plot_role = Data1D.ROLE_RESIDUAL
data3.plot_role = DataRole.ROLE_RESIDUAL
plot3.data = data3

# pretend we're displaying three plots
Expand Down
5 changes: 2 additions & 3 deletions src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import numpy as np

from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data2D
from sas.qtgui.Plotting.PlotterData import Data1D, Data2D, DataRole

from sasdata.dataloader.data_info import Detector
from sasdata.dataloader.data_info import Source
Expand Down Expand Up @@ -155,7 +154,7 @@ def _create1DPlot(self, tab_id, x, y, model, data, component=None):
new_plot.yaxis(_yaxis, _yunit)

if component is not None:
new_plot.plot_role = Data1D.ROLE_DELETABLE #deletable
new_plot.plot_role = DataRole.ROLE_DELETABLE #deletable

return new_plot

Expand Down
5 changes: 2 additions & 3 deletions src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

import numpy

from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data2D
from sas.qtgui.Plotting.PlotterData import Data1D, DataRole, Data2D

from sas.qtgui.Perspectives.Fitting.AssociatedComboBox import AssociatedComboBox

Expand Down Expand Up @@ -644,7 +643,7 @@ def plotPolydispersities(model):
data1d.symbol = 'Line'
data1d.name = "{} polydispersity".format(name)
data1d.id = data1d.name # placeholder, has to be completed later
data1d.plot_role = Data1D.ROLE_RESIDUAL
data1d.plot_role = DataRole.ROLE_STAND_ALONE
plots.append(data1d)
return plots

Expand Down
7 changes: 3 additions & 4 deletions src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@

import sas.qtgui.Utilities.GuiUtils as GuiUtils
from sas.qtgui.Utilities.CategoryInstaller import CategoryInstaller
from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data2D
from sas.qtgui.Plotting.PlotterData import Data1D, Data2D, DataRole
from sas.qtgui.Plotting.Plotter import PlotterWidget

from sas.qtgui.Perspectives.Fitting.UI.FittingWidgetUI import Ui_FittingWidgetUI
Expand Down Expand Up @@ -2451,7 +2450,7 @@ def _requestPlots(self, item_name, item_model):
data_shown = False
item = None
for item, plot in plots.items():
if plot.plot_role != Data1D.ROLE_DATA and fitpage_name in plot.name:
if plot.plot_role != DataRole.ROLE_DATA and fitpage_name in plot.name:
data_shown = True
self.communicate.plotRequestedSignal.emit([item, plot], self.tab_id)
# return the last data item seen, if nothing was plotted; supposed to be just data)
Expand Down Expand Up @@ -3333,7 +3332,7 @@ def calculateResiduals(self, fitted_data):
if residuals_plot is None:
return
residuals_plot.id = "Residual " + residuals_plot.id
residuals_plot.plot_role = Data1D.ROLE_RESIDUAL
residuals_plot.plot_role = DataRole.ROLE_RESIDUAL
self.createNewIndex(residuals_plot)
return residuals_plot

Expand Down
6 changes: 3 additions & 3 deletions src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

# sas-global
from sas.sascalc.invariant import invariant
from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data1D, DataRole
import sas.qtgui.Utilities.GuiUtils as GuiUtils

# local
Expand Down Expand Up @@ -266,7 +266,7 @@ def plotResult(self, model): # TODO: Pythonic name, typing
# Send the modified model item to DE for keeping in the model
plots = [self._model_item]
if self.high_extrapolation_plot:
self.high_extrapolation_plot.plot_role = Data1D.ROLE_DEFAULT
self.high_extrapolation_plot.plot_role = DataRole.ROLE_DEFAULT
self.high_extrapolation_plot.symbol = "Line"
self.high_extrapolation_plot.show_errors = False
self.high_extrapolation_plot.show_q_range_sliders = True
Expand All @@ -280,7 +280,7 @@ def plotResult(self, model): # TODO: Pythonic name, typing
self.high_extrapolation_plot.title)
plots.append(self.high_extrapolation_plot)
if self.low_extrapolation_plot:
self.low_extrapolation_plot.plot_role = Data1D.ROLE_DEFAULT
self.low_extrapolation_plot.plot_role = DataRole.ROLE_DEFAULT
self.low_extrapolation_plot.symbol = "Line"
self.low_extrapolation_plot.show_errors = False
self.low_extrapolation_plot.show_q_range_sliders = True
Expand Down
6 changes: 3 additions & 3 deletions src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

# pr inversion calculation elements
from sas.sascalc.pr.invertor import Invertor
from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data1D, DataRole
# Batch calculation display
from sas.qtgui.Utilities.GridPanel import BatchInversionOutputPanel
from sas.qtgui.Perspectives.perspective import Perspective
Expand Down Expand Up @@ -654,12 +654,12 @@ def updateGuiValues(self):
pr.get_pos_err(out, cov))))
if self.prPlot is not None:
title = self.prPlot.name
self.prPlot.plot_role = Data1D.ROLE_RESIDUAL
self.prPlot.plot_role = DataRole.ROLE_STAND_ALONE
GuiUtils.updateModelItemWithPlot(self._data, self.prPlot, title)
self.communicate.plotRequestedSignal.emit([self._data,self.prPlot], None)
if self.dataPlot is not None:
title = self.dataPlot.name
self.dataPlot.plot_role = Data1D.ROLE_DEFAULT
self.dataPlot.plot_role = DataRole.ROLE_DEFAULT
self.dataPlot.symbol = "Line"
self.dataPlot.show_errors = False
GuiUtils.updateModelItemWithPlot(self._data, self.dataPlot, title)
Expand Down
4 changes: 2 additions & 2 deletions src/sas/qtgui/Plotting/Plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from matplotlib.font_manager import FontProperties
from packaging import version

from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data1D, DataRole
from sas.qtgui.Plotting.PlotterBase import PlotterBase
from sas.qtgui.Plotting.AddText import AddText
from sas.qtgui.Plotting.Binder import BindArtist
Expand Down Expand Up @@ -228,7 +228,7 @@ def plot(self, data=None, color=None, marker=None, hide_error=False, transform=T
ax.axhline(color='black', linewidth=1)

# Display +/- 3 sigma and +/- 1 sigma lines for residual plots
if data.plot_role == data.ROLE_RESIDUAL:
if data.plot_role == DataRole.ROLE_RESIDUAL:
ax.axhline(y=3, color='red', linestyle='-')
ax.axhline(y=-3, color='red', linestyle='-')
ax.axhline(y=1, color='gray', linestyle='--')
Expand Down
24 changes: 18 additions & 6 deletions src/sas/qtgui/Plotting/PlotterData.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import copy
import numpy
import math
from enum import Enum

from sasdata.data_util.uncertainty import Uncertainty

from sas.qtgui.Plotting.Plottables import PlottableData1D
Expand All @@ -13,13 +15,23 @@
from sasdata.dataloader.data_info import Data2D as LoadData2D


class DataRole(Enum):
"""Labels to apply to different plot types."""
# Data is for imported data
ROLE_DATA = 0
# Default is for fits of the imported data
ROLE_DEFAULT = 1
# Deletable is for orphaned plots
ROLE_DELETABLE = 2
# Residual is for stand-alone residual plots
ROLE_RESIDUAL = 3
# Stand alone is for plots that should be plotted separately
ROLE_STAND_ALONE = 4


class Data1D(PlottableData1D, LoadData1D):
"""
"""
ROLE_DATA=0
ROLE_DEFAULT=1
ROLE_DELETABLE=2
ROLE_RESIDUAL=3
def __init__(self, x=None, y=None, dx=None, dy=None):
"""
"""
Expand All @@ -43,7 +55,7 @@ def __init__(self, x=None, y=None, dx=None, dy=None):
# 1: normal lifecycle (fit)
# 2: deletable on model change (Q(I), S(I)...)
# 3: separate chart on Show Plot (residuals)
self.plot_role = Data1D.ROLE_DEFAULT
self.plot_role = DataRole.ROLE_DEFAULT
# Q-range slider definitions
self.show_q_range_sliders = False # Should sliders be shown?
self.slider_update_on_move = True # Should the gui update during the move?
Expand Down Expand Up @@ -209,7 +221,7 @@ def __init__(self, image=None, err_image=None,
self.title = ""
self.scale = None
# Always default
self.plot_role = Data1D.ROLE_DEFAULT
self.plot_role = DataRole.ROLE_DEFAULT

def copy_from_datainfo(self, data2d):
"""
Expand Down
5 changes: 2 additions & 3 deletions src/sas/qtgui/Utilities/GuiUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
from periodictable import formula as Formula
from sas.qtgui.Plotting import DataTransform
from sas.qtgui.Plotting.ConvertUnits import convertUnit
from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data2D
from sas.qtgui.Plotting.PlotterData import Data1D, Data2D, DataRole
from sas.qtgui.Plotting.Plottables import Plottable
from sasdata.dataloader.data_info import Sample, Source, Vector
from sasdata.dataloader.data_info import Detector, Process, TransmissionSpectrum
Expand Down Expand Up @@ -240,7 +239,7 @@ def deleteRedundantPlots(item, new_plots):
if (plot_data.id is not None) and \
(plot_data.id not in ids) and \
(plot_data.name not in names) and \
(plot_data.plot_role == Data1D.ROLE_DELETABLE):
(plot_data.plot_role == DataRole.ROLE_DELETABLE):
items_to_delete.append(plot_item)

for plot_item in items_to_delete:
Expand Down

0 comments on commit b956b61

Please sign in to comment.