Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set proper plot scales for ancillary plots #3148

Draft
wants to merge 12 commits into
base: release_6.0.1
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions src/sas/qtgui/MainWindow/DataExplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1123,18 +1123,17 @@ 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, DataRole.ROLE_POLYDISPERSITY]

if (role in stand_alone_types and shown) or role == DataRole.ROLE_DELETABLE:
if (role.stand_alone and shown) or role == DataRole.ROLE_DELETABLE:
# Nothing to do if stand-alone plot already shown or plot to be deleted
continue
elif role == DataRole.ROLE_RESIDUAL and config.DISABLE_RESIDUAL_PLOT:
elif role in [DataRole.ROLE_RESIDUAL, DataRole.ROLE_RESIDUAL_SESANS] and config.DISABLE_RESIDUAL_PLOT:
# Nothing to do if residuals are not plotted
continue
elif role == DataRole.ROLE_POLYDISPERSITY and config.DISABLE_POLYDISPERSITY_PLOT:
elif role in [DataRole.ROLE_POLYDISPERSITY] and config.DISABLE_POLYDISPERSITY_PLOT:
# Nothing to do if polydispersity plot is not plotted
continue
elif role in stand_alone_types:
elif role.stand_alone:
# Stand-alone plots should always be separate
self.plotData([(plot_item, plot_to_show)])
elif append:
Expand Down Expand Up @@ -1200,15 +1199,13 @@ def plotData(self, plots, transform=True):
"""
# Call show on requested plots
# All same-type charts in one plot
new_plot = PlotterWidget(manager=self, parent=self)
new_plot.item = None
for item, plot_set in plots:
if isinstance(plot_set, Data1D):
if 'new_plot' not in locals():
new_plot = PlotterWidget(manager=self, parent=self)
if not new_plot.item:
new_plot.item = item
# Ensure new plots use the default transform, not the transform of any previous plots the data were in
# TODO: The transform should be part of the PLOT, NOT the data
plot_set.xtransform = None
plot_set.ytransform = None
# Ensure new plots use the default transform, not the transform of any previous plots
new_plot.plot(plot_set, transform=transform)
# active_plots may contain multiple charts
self.active_plots[plot_set.name] = new_plot
Expand All @@ -1218,9 +1215,7 @@ def plotData(self, plots, transform=True):
msg = "Incorrect data type passed to Plotting"
raise AttributeError(msg)

if 'new_plot' in locals() and \
hasattr(new_plot, 'data') and \
isinstance(new_plot.data[0], Data1D):
if hasattr(new_plot, 'data') and isinstance(new_plot.data[0], Data1D):
self.addPlot(new_plot)

def newPlot(self):
Expand Down
6 changes: 2 additions & 4 deletions src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,12 +547,12 @@ def residualsData1D(reference_data, current_data, weights):
residuals.dx = None
residuals.dxl = None
residuals.dxw = None
residuals.ytransform = 'y'
if reference_data.isSesans:
residuals.xtransform = 'x'
residuals.plot_role = DataRole.ROLE_RESIDUAL_SESANS
residuals.xaxis('\\delta ', 'A')
# For latter scale changes
else:
residuals.plot_role = DataRole.ROLE_RESIDUAL
residuals.xaxis('\\rm{Q} ', 'A^{-1}')
residuals.yaxis('\\rm{Residuals} ', 'normalized')

Expand Down Expand Up @@ -636,8 +636,6 @@ def plotPolydispersities(model):
# similar to FittingLogic._create1DPlot() but different data/axes
data1d = Data1D(x=xarr, y=yarr)
xunit = model.details[name][0]
data1d.xtransform = 'x'
data1d.ytransform = 'y'
data1d.xaxis(r'\rm{{{}}}'.format(name.replace('_', '\_')), xunit)
data1d.yaxis(r'\rm{probability}', 'normalized')
data1d.scale = 'linear'
Expand Down
6 changes: 2 additions & 4 deletions src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -3267,8 +3267,7 @@ def complete1D(self, return_data):

# Fits of Sesans data are in real space
if return_data["data"].isSesans:
fitted_data.xtransform="x"
fitted_data.ytransform="y"
fitted_data.plot_role = DataRole.ROLE_LIN_LIN

# assure the current index is set properly for batch
if len(self._logic) > 1:
Expand Down Expand Up @@ -3922,8 +3921,7 @@ def onShowSLDProfile(self):
profile_data._xunit = "\AA"
profile_data._yaxis = "SLD"
profile_data._yunit = "10^{-6}\AA^{-2}"
profile_data.ytransform='y'
profile_data.xtransform='x'
profile_data.data_role = DataRole.ROLE_LIN_LIN

profile_data.id = "sld"

Expand Down
5 changes: 2 additions & 3 deletions src/sas/qtgui/Perspectives/Inversion/InversionLogic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
import numpy as np

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

PR_FIT_LABEL = r"$P_{fit}(r)$"
PR_LOADED_LABEL = r"$P_{loaded}(r)$"
Expand Down Expand Up @@ -129,8 +129,7 @@ def newPRPlot(self, out, pr, cov=None):
new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")
new_plot.title = "P(r) fit"
new_plot.id = PR_FIT_LABEL
new_plot.xtransform = "x"
new_plot.ytransform = "y"
new_plot.data_role = DataRole.ROLE_LIN_LIN
new_plot.group_id = GROUP_ID_PR_FIT

return new_plot
Expand Down
37 changes: 16 additions & 21 deletions src/sas/qtgui/Plotting/Plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,32 +112,32 @@ def plot(self, data=None, color=None, marker=None, hide_error=False, transform=T

if not is_fit:
# make sure we have some function to operate on
if data.xtransform is None:
if self.xLogLabel is None:
if data.isSesans:
data.xtransform='x'
self.xLogLabel = 'x'
else:
data.xtransform = 'log10(x)'
if data.ytransform is None:
self.xLogLabel = 'log10(x)'
if self.yLogLabel is None:
if data.isSesans:
data.ytransform='y'
self.yLogLabel = 'y'
else:
data.ytransform = 'log10(y)'
self.yLogLabel = 'log10(y)'
#Added condition to Dmax explorer from P(r) perspective
if data._xaxis == 'D_{max}':
self.xscale = 'linear'
# Transform data if required.
if transform and (data.xtransform is not None or data.ytransform is not None):
if transform:
self.xLabel, self.yLabel, xscale, yscale = \
GuiUtils.xyTransform(data, data.xtransform, data.ytransform)
GuiUtils.xyTransform(data, self.xLogLabel, self.yLogLabel)
if xscale != 'log' and xscale != self.xscale:
self.xscale = xscale
if yscale != 'log' and yscale != self.yscale:
self.yscale = yscale

# Redefine the Scale properties dialog
self.properties = ScaleProperties(self,
init_scale_x=data.xtransform,
init_scale_y=data.ytransform)
init_scale_x=self.xLogLabel,
init_scale_y=self.yLogLabel)

# Shortcuts
ax = self.ax
Expand Down Expand Up @@ -178,13 +178,13 @@ def plot(self, data=None, color=None, marker=None, hide_error=False, transform=T

markersize = data.markersize

# Use the plot role to define the x and y scales
self.xscale = data.plot_role.x_scale
self.yscale = data.plot_role.y_scale

# Include scaling (log vs. linear)
if version.parse(mpl.__version__) < version.parse("3.3"):
ax.set_xscale(self.xscale, nonposx='clip') if self.xscale != 'linear' else self.ax.set_xscale(self.xscale)
ax.set_yscale(self.yscale, nonposy='clip') if self.yscale != 'linear' else self.ax.set_yscale(self.yscale)
else:
ax.set_xscale(self.xscale, nonpositive='clip') if self.xscale != 'linear' else self.ax.set_xscale(self.xscale)
ax.set_yscale(self.yscale, nonpositive='clip') if self.yscale != 'linear' else self.ax.set_yscale(self.yscale)
ax.set_xscale(self.xscale, nonpositive='clip') if self.xscale != 'linear' else self.ax.set_xscale(self.xscale)
ax.set_yscale(self.yscale, nonpositive='clip') if self.yscale != 'linear' else self.ax.set_yscale(self.yscale)

# Draw non-standard markers
l_width = markersize * 0.4
Expand Down Expand Up @@ -502,9 +502,6 @@ def onScaleChange(self):
"""
if self.properties.exec_() == QtWidgets.QDialog.Accepted:
self.xLogLabel, self.yLogLabel = self.properties.getValues()
for d in self.data:
d.xtransform = self.xLogLabel
d.ytransform = self.yLogLabel
self.xyTransform(self.xLogLabel, self.yLogLabel)

def onAddText(self):
Expand Down Expand Up @@ -682,8 +679,6 @@ def replacePlot(self, id, new_plot, retain_dimensions=True):

# Pull the current transform settings from the old plot
selected_plot = self.plot_dict[id]
new_plot.xtransform = selected_plot.xtransform
new_plot.ytransform = selected_plot.ytransform
#Adding few properties ftom ModifyPlot to preserve them in future changes
new_plot.title = selected_plot.title
new_plot.custom_color = selected_plot.custom_color
Expand Down
1 change: 0 additions & 1 deletion src/sas/qtgui/Plotting/Plotter2D.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,6 @@ def circularAverage(self):
new_plot.xaxis("\\rm{Q}", "A^{-1}")
if hasattr(self.data0, "scale") and \
self.data0.scale == 'linear':
new_plot.ytransform = 'y'
new_plot.yaxis("\\rm{Residuals} ", "normalized")
else:
new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
Expand Down
28 changes: 16 additions & 12 deletions src/sas/qtgui/Plotting/PlotterData.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import copy
import numpy
import math
from enum import Enum
from enum import Enum, auto

from sasdata.data_util.uncertainty import Uncertainty

Expand All @@ -18,17 +18,25 @@
class DataRole(Enum):
"""Labels to apply to different plot types."""
# Data is for imported data
ROLE_DATA = 0
ROLE_DATA = ("log", "log")
# Default is for fits of the imported data
ROLE_DEFAULT = 1
ROLE_DEFAULT = ("log", "log")
# Deletable is for orphaned plots
ROLE_DELETABLE = 2
ROLE_DELETABLE = (None, None)
# Residual is for stand-alone residual plots
ROLE_RESIDUAL = 3
ROLE_RESIDUAL = ("log", "linear")
# Residual sesans is for stand-alone sesans residual plots
ROLE_RESIDUAL_SESANS = ("linear", "linear")
# Stand alone is for plots that should be plotted separately
ROLE_STAND_ALONE = 4
# Polydispersity is for stand-alone polydispersity plot
ROLE_POLYDISPERSITY = 5
ROLE_STAND_ALONE = ("linear", "linear")
# LIN_LIN is for stand-alone plots on a linear-linear scale
ROLE_LIN_LIN = ("linear", "linear")
# POLYDISPERSITY role is to tag polydispersity plots to be able to suppress auto displaying them
ROLE_POLYDISPERSITY = ("linear", "linear")

def __init__(self, x_scale, y_scale):
self.x_scale = x_scale
self.y_scale = y_scale


class Data1D(PlottableData1D, LoadData1D):
Expand All @@ -48,8 +56,6 @@ def __init__(self, x=None, y=None, dx=None, dy=None):
self.group_id = None
self.is_data = True
self.path = None
self.xtransform = None
self.ytransform = None
self.title = ""
self.scale = None
# plot_role:
Expand Down Expand Up @@ -218,8 +224,6 @@ def __init__(self, image=None, err_image=None,
self.group_id = None
self.is_data = True
self.path = None
self.xtransform = None
self.ytransform = None
self.title = ""
self.scale = None
# Always default
Expand Down
9 changes: 3 additions & 6 deletions src/sas/qtgui/Plotting/Slicers/AnnulusSlicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import sas.qtgui.Utilities.GuiUtils as GuiUtils
from .BaseInteractor import BaseInteractor
from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data1D, DataRole
from sas.qtgui.Utilities.GuiUtils import formatNumber
from sas.qtgui.Plotting.SlicerModel import SlicerModel

Expand Down Expand Up @@ -133,16 +133,13 @@ def _post_data(self, nbins=None):
# If the data file does not tell us what the axes are, just assume...
new_plot.xaxis("\\rm{\phi}", 'degrees')
new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
if hasattr(data, "scale") and data.scale == 'linear' and \
self.data.name.count("Residuals") > 0:
new_plot.ytransform = 'y'
if hasattr(data, "scale") and data.scale == 'linear' and self.data.name.count("Residuals") > 0:
new_plot.yaxis("\\rm{Residuals} ", "/")

new_plot.id = "AnnulusPhi" + self.data.name
new_plot.type_id = "Slicer" + self.data.name # Used to remove plots after changing slicer so they don't keep showing up after closed
new_plot.is_data = True
new_plot.xtransform = "x"
new_plot.ytransform = "y"
new_plot.plot_role = DataRole.ROLE_LIN_LIN
item = self._item
if self._item.parent() is not None:
item = self._item.parent()
Expand Down
5 changes: 2 additions & 3 deletions src/sas/qtgui/Plotting/Slicers/WedgeSlicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from sas.qtgui.Plotting.Slicers.BaseInteractor import BaseInteractor
from sas.qtgui.Plotting.SlicerModel import SlicerModel
from sas.qtgui.Plotting.PlotterData import Data1D
from sas.qtgui.Plotting.PlotterData import Data1D, DataRole
import sas.qtgui.Utilities.GuiUtils as GuiUtils

from sas.qtgui.Plotting.Slicers.ArcInteractor import ArcInteractor
Expand Down Expand Up @@ -205,8 +205,7 @@ def _post_data(self, new_sector=None, nbins=None):
# angular plots usually require a linear x scale and better with
# a linear y scale as well.
new_plot.xaxis("\\rm{\phi}", "degrees")
new_plot.xtransform = 'x'
new_plot.ytransform = 'y'
new_plot.plot_role = DataRole.ROLE_LIN_LIN
else:
new_plot.xaxis("\\rm{Q}", 'A^{-1}')
new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
Expand Down
Loading