From baf0c745829de9d22d4d7ea0b5d7df2f58d3dc99 Mon Sep 17 00:00:00 2001 From: YektaY Date: Mon, 15 Aug 2022 15:12:08 -0700 Subject: [PATCH 1/4] establish channals for the x_values and update the accelerator diagram --- pydm/widgets/z_plot.py | 208 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 pydm/widgets/z_plot.py diff --git a/pydm/widgets/z_plot.py b/pydm/widgets/z_plot.py new file mode 100644 index 000000000..44ca0bea8 --- /dev/null +++ b/pydm/widgets/z_plot.py @@ -0,0 +1,208 @@ +import typing +import pyqtgraph as pg +from functools import partial +from qtpy.QtWidgets import QWidget, QLabel, QVBoxLayout +from pydm.widgets import PyDMScatterPlot +from .channel import PyDMChannel + + +class PyDMZPlot(QWidget): + """ + + """ + + def __init__(self, parent=None, y_axis_channels=None, x_axis_channels=None, symbol_list=[], y_axis_symbol='o'): + super().__init__() + if y_axis_channels is not None: + self._y_axis_channels = y_axis_channels + else: + self._y_axis_channels = list() + + if x_axis_channels is not None: + self._x_axis_channels = x_axis_channels + else: + self._x_axis_channels = list() + + self._symbol_list = symbol_list + self._y_axis_symbol = y_axis_symbol + self.z_values = [] + self.x_points_table = {} + self.x_points = [] + self.y_points = [] + + # ui elements + self.text = None + self.label = None + self.z_plot = None + self.accelerator_diagram = None + + # build ui + self.ui_components() + self.show() + + def ui_components(self): + """ + + """ + self.setGeometry(100, 100, 800, 500) + self.text = 'z-plot' + self.label = QLabel(self.text) + self.label.setMinimumWidth(130) + self.label.setWordWrap(True) + + pg.setConfigOptions(antialias=True) + + self.z_plot = PyDMScatterPlot() + + for i in range(0, len(self.y_axis_channels)): + self.z_plot.addChannel(y_channel=self._y_axis_channels[i], + x_channel=self._x_axis_channels[i], symbol=self._y_axis_symbol) + + self.accelerator_diagram = pg.PlotWidget() + self.accelerator_diagram.setMouseEnabled(x=True, y=False) + self.accelerator_diagram.getPlotItem().hideAxis('left') + self.accelerator_diagram.getPlotItem().hideAxis('bottom') + + for view in self.z_plot.plotItem.stackedViews: + view.setXLink(self.accelerator_diagram) + + # Get values from the x channels and populate the data into the accelerator diagram + self.establish_channel_connections() + + z_plot_layout = QVBoxLayout() + z_plot_layout.setContentsMargins(0, 0, 0, 0) + z_plot_layout.setSpacing(0) + + z_plot_layout.addWidget(self.z_plot, stretch=3) + z_plot_layout.addWidget(self.accelerator_diagram, stretch=1) + #z_plot_layout.addWidget(self.label) + + self.setLayout(z_plot_layout) + + def establish_channel_connections(self): + """ + + """ + channels = [] + for address in self._x_axis_channels: + new_channel = PyDMChannel(address=address, value_slot=partial(self.update_x_values, address)) + new_channel.connect() + channels.append(new_channel) + + return channels + + def update_x_values(self, new_value, address): + """ + + """ + self.x_points_table.update({address: new_value}) + self.x_points.clear() + + for value in self.x_points_table: + self.x_points.append(value) + + self.y_points = [1] * len(self.x_points) + + if len(self._symbol_list) == len(self.x_points): + symbols = self._symbol_list + else: + # should throw a warning here + symbols = 's' + + self.accelerator_diagram.clear() + self.accelerator_diagram.plot(y=self.y_points, x=self.x_points, symbol=symbols, symbolSizes=14) + + @property + def y_axis_channels(self): + """ + list of channels to be plotted. + + Returns + ------- + list of strings + """ + + return self._y_axis_channels + + @y_axis_channels.setter + def y_axis_channels(self, channels): + """ + list of channels to be plotted. + + Parameters + ------- + channels : list of strings + """ + + if self._y_axis_channels != channels: + self._y_axis_channels = channels + + if len(self._y_axis_channels) == len(self.x_axis_channels): + self.z_plot.clearCurves() + for i in range(0, len(self.y_axis_channels)): + self.z_plot.addChannel(y_channel=self._y_axis_channels[i], + x_channel=self._x_axis_channels[i], symbol=self._y_axis_symbol) + + for view in self.z_plot.plotItem.stackedViews: + view.setXLink(self.accelerator_diagram) + + @property + def x_axis_channels(self): + """ + list of channels to be plotted. + + Returns + ------- + list of strings + """ + + return self._x_axis_channels + + @x_axis_channels.setter + def x_axis_channels(self, channels): + """ + list of channels to be plotted. + + Parameters + ------- + channels : list of strings + """ + + if self._x_axis_channels != channels: + self._x_axis_channels = channels + + # update the accelerator diagram + self.establish_channel_connections() + + # update the z plot graph if both the x and y list are the same size. + if len(self._y_axis_channels) == len(self.x_axis_channels): + self.z_plot.clearCurves() + for i in range(0, len(self.y_axis_channels)): + self.z_plot.addChannel(y_channel=self._y_axis_channels[i], + x_channel=self._x_axis_channels[i], symbol=self._y_axis_symbol) + + for view in self.z_plot.plotItem.stackedViews: + view.setXLink(self.accelerator_diagram) + + @property + def symbol_list(self): + """ + + Returns + ------- + list of strings + """ + + return self._symbol_list + + @symbol_list.setter + def symbol_list(self, symbols): + """ + + Parameters + ------- + symbols : list of strings + """ + + if self._symbol_list != symbols: + self._symbol_list = symbols From eead753888900b0ef0e3b1b755565c3880b19112 Mon Sep 17 00:00:00 2001 From: YektaY Date: Mon, 22 Aug 2022 14:24:35 -0700 Subject: [PATCH 2/4] started to add comments --- pydm/widgets/z_plot.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/pydm/widgets/z_plot.py b/pydm/widgets/z_plot.py index 44ca0bea8..a46a142c4 100644 --- a/pydm/widgets/z_plot.py +++ b/pydm/widgets/z_plot.py @@ -8,8 +8,25 @@ class PyDMZPlot(QWidget): """ - - """ + The PyDMZPlot, is a plotting widget that couples a PyDMScatterPlot and a pyqtgraph PlotWidget to create a plot + widget that has a corresponding dynamic diagram that can represent a positional direction of a machine + or facility. + + Note: + + Parameters + ---------- + parent : QWidget + The parent widget for the plot + y_axis_channels : str, optional + The channels to be used by the widget. + x_axis_channels : str, optional + The channels to be used by the widget. + symbol_list : list, optional + The symbols to be used by the data points in the diagram. + y_axis_symbol : str, optional + The symbol to be used by the y-axis data points. + """ def __init__(self, parent=None, y_axis_channels=None, x_axis_channels=None, symbol_list=[], y_axis_symbol='o'): super().__init__() @@ -42,7 +59,7 @@ def __init__(self, parent=None, y_axis_channels=None, x_axis_channels=None, symb def ui_components(self): """ - + creates the layout and widgets for the z-plot """ self.setGeometry(100, 100, 800, 500) self.text = 'z-plot' @@ -81,7 +98,7 @@ def ui_components(self): def establish_channel_connections(self): """ - + Sets up the pydm channels for the given x_axis addresses. """ channels = [] for address in self._x_axis_channels: From 1e19e13905a4f31f9563f500a29092241b314963 Mon Sep 17 00:00:00 2001 From: YektaY Date: Fri, 26 Aug 2022 09:04:42 -0700 Subject: [PATCH 3/4] added z-plot to the __init__ file --- pydm/widgets/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pydm/widgets/__init__.py b/pydm/widgets/__init__.py index 1f6721017..81c5c090e 100644 --- a/pydm/widgets/__init__.py +++ b/pydm/widgets/__init__.py @@ -25,4 +25,5 @@ from .waveformplot import PyDMWaveformPlot from .scatterplot import PyDMScatterPlot from .tab_bar import PyDMTabWidget -from .template_repeater import PyDMTemplateRepeater \ No newline at end of file +from .template_repeater import PyDMTemplateRepeater +from .z_plot import PyDMZPlot From cfd855cdb72abbbf4f90673195bcc4994ed2aa6c Mon Sep 17 00:00:00 2001 From: YektaY Date: Fri, 26 Aug 2022 09:19:22 -0700 Subject: [PATCH 4/4] added some comments --- pydm/widgets/z_plot.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pydm/widgets/z_plot.py b/pydm/widgets/z_plot.py index a46a142c4..6759422f7 100644 --- a/pydm/widgets/z_plot.py +++ b/pydm/widgets/z_plot.py @@ -1,10 +1,13 @@ import typing +import logging import pyqtgraph as pg from functools import partial from qtpy.QtWidgets import QWidget, QLabel, QVBoxLayout from pydm.widgets import PyDMScatterPlot from .channel import PyDMChannel +logger = logging.getLogger(__name__) + class PyDMZPlot(QWidget): """ @@ -12,8 +15,6 @@ class PyDMZPlot(QWidget): widget that has a corresponding dynamic diagram that can represent a positional direction of a machine or facility. - Note: - Parameters ---------- parent : QWidget @@ -110,7 +111,7 @@ def establish_channel_connections(self): def update_x_values(self, new_value, address): """ - + Update the x values of the self.accelerator_diagram (pyqtgraph PlotWidget) plot. """ self.x_points_table.update({address: new_value}) self.x_points.clear() @@ -123,7 +124,8 @@ def update_x_values(self, new_value, address): if len(self._symbol_list) == len(self.x_points): symbols = self._symbol_list else: - # should throw a warning here + logger.debug("The length of the list of symbols did not match the " + "number of x points so the default symbol was set.") symbols = 's' self.accelerator_diagram.clear() @@ -204,6 +206,7 @@ def x_axis_channels(self, channels): @property def symbol_list(self): """ + list of symbols to be passed to the self.accelerator_diagram (pyqtgraph PlotWidget) plot. Returns ------- @@ -215,6 +218,7 @@ def symbol_list(self): @symbol_list.setter def symbol_list(self, symbols): """ + list of symbols to be passed to the self.accelerator_diagram (pyqtgraph PlotWidget) plot. Parameters -------