1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2026-05-06 06:44:23 +02:00

fix: add is_log checks and functionality to plot_indicator_items

This commit is contained in:
2024-09-11 22:55:59 +02:00
parent 63c24f97a3
commit 0f9953e8fd
2 changed files with 80 additions and 37 deletions
+47 -9
View File
@@ -1,5 +1,6 @@
"""Module to create an arrow item for a pyqtgraph plot"""
import numpy as np
import pyqtgraph as pg
from qtpy.QtCore import QObject, Qt, Signal, Slot
@@ -12,6 +13,9 @@ class BECIndicatorItem(QObject):
super().__init__(parent=parent)
self.accent_colors = get_accent_colors()
self.plot_item = plot_item
self._pos = None
self.is_log_x = False
self.is_log_y = False
def add_to_plot(self) -> None:
"""Add the item to the plot"""
@@ -25,6 +29,12 @@ class BECIndicatorItem(QObject):
"""Set the position of the item"""
raise NotImplementedError("Method set_position not implemented")
def check_log(self):
"""Checks if the x or y axis is in log scale and updates the internal state accordingly."""
self.is_log_x = self.plot_item.ctrl.logXCheck.isChecked()
self.is_log_y = self.plot_item.ctrl.logYCheck.isChecked()
self.set_position(self._pos)
def cleanup(self) -> None:
"""Cleanup the item"""
self.remove_from_plot()
@@ -43,7 +53,8 @@ class BECTickItem(BECIndicatorItem):
super().__init__(plot_item=plot_item, parent=parent)
self.tick_item = pg.TickSliderItem(allowAdd=False, allowRemove=False)
self.tick = None
self._tick_pos = 0
# Set _pos to float
self._pos = 0
self._range = [0, 1]
@Slot(float)
@@ -53,8 +64,15 @@ class BECTickItem(BECIndicatorItem):
Args:
pos (float): The position of the tick item.
"""
self._tick_pos = pos
self.update_range(self.plot_item.vb, self._range)
if self.is_log_x is True:
pos = pos if pos > 0 else 1e-10
pos = np.log10(pos)
self._pos = pos
view_box = self.plot_item.getViewBox() # Ensure you're accessing the correct view box
view_range = view_box.viewRange()[0]
self.update_range(self.plot_item.vb, view_range)
self.position_changed.emit(pos)
self.position_changed_str.emit(str(pos))
def update_range(self, vb, viewRange) -> None:
"""Update the range of the tick item
@@ -69,12 +87,9 @@ class BECTickItem(BECIndicatorItem):
lengthIncludingPadding = length + self.tick_item.tickSize + 2
self._range = viewRange
tickValueIncludingPadding = (self._tick_pos - viewRange[0]) / (viewRange[1] - viewRange[0])
tickValueIncludingPadding = (self._pos - viewRange[0]) / (viewRange[1] - viewRange[0])
tickValue = (tickValueIncludingPadding * lengthIncludingPadding - origin) / length
self.tick_item.setTickValue(self.tick, tickValue)
self.position_changed.emit(self._tick_pos)
self.position_changed_str.emit(str(self._tick_pos))
def add_to_plot(self):
"""Add the tick item to the view box or plot item."""
@@ -82,6 +97,8 @@ class BECTickItem(BECIndicatorItem):
self.plot_item.layout.addItem(self.tick_item, 4, 1)
self.tick = self.tick_item.addTick(0, movable=False, color=self.accent_colors.highlight)
self.plot_item.vb.sigXRangeChanged.connect(self.update_range)
self.plot_item.ctrl.logXCheck.checkStateChanged.connect(self.check_log)
self.plot_item.ctrl.logYCheck.checkStateChanged.connect(self.check_log)
def remove_from_plot(self):
"""Remove the tick item from the view box or plot item."""
@@ -110,6 +127,7 @@ class BECArrowItem(BECIndicatorItem):
def __init__(self, plot_item: pg.PlotItem = None, parent=None):
super().__init__(plot_item=plot_item, parent=parent)
self.arrow_item = pg.ArrowItem()
self._pos = (0, 0)
@Slot(dict)
def set_style(self, style: dict) -> None:
@@ -128,11 +146,23 @@ class BECArrowItem(BECIndicatorItem):
Args:
pos (tuple): The position of the arrow item as a tuple (x, y).
"""
self._pos = pos
pos_x = pos[0]
pos_y = pos[1]
if self.is_log_x is True:
pos_x = np.log10(pos_x) if pos_x > 0 else 1e-10
view_box = self.plot_item.getViewBox() # Ensure you're accessing the correct view box
view_range = view_box.viewRange()[0]
# Avoid values outside the view range in the negative direction. Otherwise, there is
# a buggy behaviour of the arrow item and it appears at the wrong position.
if pos_x < view_range[0]:
pos_x = view_range[0]
if self.is_log_y is True:
pos_y = np.log10(pos_y) if pos_y > 0 else 1e-10
self.arrow_item.setPos(pos_x, pos_y)
self.position_changed.emit((pos_x, pos_y))
self.position_changed_str.emit((str(pos_x), str(pos_y)))
self.position_changed.emit(self._pos)
self.position_changed_str.emit((str(self._pos[0]), str(self._pos[1])))
def add_to_plot(self):
"""Add the arrow item to the view box or plot item."""
@@ -144,8 +174,16 @@ class BECArrowItem(BECIndicatorItem):
)
if self.plot_item is not None:
self.plot_item.addItem(self.arrow_item)
self.plot_item.ctrl.logXCheck.checkStateChanged.connect(self.check_log)
self.plot_item.ctrl.logYCheck.checkStateChanged.connect(self.check_log)
def remove_from_plot(self):
"""Remove the arrow item from the view box or plot item."""
if self.plot_item is not None:
self.plot_item.removeItem(self.arrow_item)
def check_log(self):
"""Checks if the x or y axis is in log scale and updates the internal state accordingly."""
self.is_log_x = self.plot_item.ctrl.logXCheck.isChecked()
self.is_log_y = self.plot_item.ctrl.logYCheck.isChecked()
self.set_position(self._pos)