PySide6Plot 0.0.1__tar.gz → 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PKG-INFO +1 -1
  2. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/libs/data_handler.py +3 -0
  3. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/libs/plot_item.py +84 -9
  4. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/libs/style.py +36 -2
  5. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/q_plot_widget.py +1 -1
  6. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot.egg-info/PKG-INFO +1 -1
  7. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot.egg-info/SOURCES.txt +1 -0
  8. pyside6plot-0.0.2/examples/qplotwidget_line_plot.py +43 -0
  9. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/.gitignore +0 -0
  10. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/__init__.py +0 -0
  11. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/compoents/__init__.py +0 -0
  12. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/compoents/average_line.py +0 -0
  13. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/compoents/draw_line.py +0 -0
  14. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/compoents/frame_recorder.py +0 -0
  15. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/compoents/zoom_move.py +0 -0
  16. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/libs/__init__.py +0 -0
  17. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/libs/constant.py +0 -0
  18. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/libs/helpers.py +0 -0
  19. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/resources/icons/ChevronLeft_black.svg +0 -0
  20. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/resources/icons/ChevronLeft_white.svg +0 -0
  21. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/resources/qss/dark/navigation_view_interface.qss +0 -0
  22. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/resources/qss/light/navigation_view_interface.qss +0 -0
  23. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/__init__.py +0 -0
  24. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/colorful_toggle_button.py +0 -0
  25. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/fluent_scroller.py +0 -0
  26. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/line_card.py +0 -0
  27. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/navigation_widget.py +0 -0
  28. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/removable_table.py +0 -0
  29. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/transparent_Line_edit.py +0 -0
  30. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/transparent_selector.py +0 -0
  31. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/value_select_box.py +0 -0
  32. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot/widgets/zoom_bar.py +0 -0
  33. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot.egg-info/dependency_links.txt +0 -0
  34. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot.egg-info/requires.txt +0 -0
  35. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/PySide6Plot.egg-info/top_level.txt +0 -0
  36. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/README.md +0 -0
  37. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/examples/price_volume_plotter.py +0 -0
  38. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/examples/sample_stock_data.h5 +0 -0
  39. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/examples/single_plotter.py +0 -0
  40. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/pyproject.toml +0 -0
  41. {pyside6plot-0.0.1 → pyside6plot-0.0.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PySide6Plot
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: Scientific/Financial plot utilities with PySide6+pyqtgraph.
5
5
  Author-email: YQ Cui <qianyun210603@hotmail.com>
6
6
  License-Expression: MIT
@@ -38,6 +38,9 @@ class ChildDataFrame:
38
38
  min_y_key (str, optional): The key to access the minimum y-value data. Defaults to None.
39
39
  x_label_key (str, optional): The key to access the x-label data. Defaults to None.
40
40
  """
41
+ if "date" not in data_frame.columns:
42
+ if isinstance(data_frame.index, pd.DatetimeIndex):
43
+ data_frame.reset_index(inplace=True, drop=False)
41
44
  data_keys = data_keys if isinstance(data_keys, list) else [data_keys]
42
45
  self.data_keys = deepcopy(data_keys)
43
46
  if max_y_key is not None:
@@ -1,8 +1,8 @@
1
1
  from pyqtgraph import QtGui, QtCore
2
2
  import pyqtgraph as pg
3
- from abc import abstractclassmethod
3
+ from abc import abstractmethod
4
4
  import numpy as np
5
- from .style import DEFAULT_STYLE
5
+ from .style import DEFAULT_STYLE, LINE_DEFAULT_STYLE
6
6
  from .data_handler import ChildDataFrame, PricesDataFrame, VolumeDataFrame
7
7
 
8
8
 
@@ -37,8 +37,8 @@ class AdaptiveGraphObject(pg.GraphicsObject):
37
37
  super().__init__()
38
38
  self.style = None
39
39
 
40
- @abstractclassmethod
41
- def get_local_plot_range(x_start, x_end):
40
+ @abstractmethod
41
+ def get_local_plot_range(self, x_start, x_end):
42
42
  """
43
43
  Abstract method to get the local plot range for the graph object.
44
44
 
@@ -51,8 +51,8 @@ class AdaptiveGraphObject(pg.GraphicsObject):
51
51
  """
52
52
  raise NotImplementedError
53
53
 
54
- @abstractclassmethod
55
- def get_x_ticks():
54
+ @abstractmethod
55
+ def get_x_ticks(self):
56
56
  """
57
57
  Abstract method to get the x-axis ticks for the graph object.
58
58
 
@@ -61,8 +61,8 @@ class AdaptiveGraphObject(pg.GraphicsObject):
61
61
  """
62
62
  raise NotImplementedError
63
63
 
64
- @abstractclassmethod
65
- def get_feature_value(key):
64
+ @abstractmethod
65
+ def get_feature_value(self, key):
66
66
  """
67
67
  Abstract method to get the value of a specific feature for the graph object.
68
68
 
@@ -223,7 +223,7 @@ class CandlestickVolumeItem(AdaptiveGraphObject):
223
223
  """
224
224
  return self.data.get_x_ticks()
225
225
 
226
- def get_feature_value(self):
226
+ def get_feature_value(self, key=None):
227
227
  """
228
228
  Get the feature values for the volume item.
229
229
 
@@ -231,3 +231,78 @@ class CandlestickVolumeItem(AdaptiveGraphObject):
231
231
  numpy.ndarray: An array of feature values.
232
232
  """
233
233
  return np.asarray([data[1] / 1e8 for data in self.data])
234
+
235
+
236
+ def draw_circle_marker(p, canvas_pt, marker_size):
237
+ """
238
+ Draws a circle marker at the specified canvas point.
239
+
240
+ Args:
241
+ p (QPainter): The painter object used for drawing.
242
+ canvas_pt (QPointF): The point where the marker should be drawn.
243
+ marker_size (float): The size of the marker.
244
+ """
245
+ p.drawEllipse(canvas_pt, marker_size, marker_size)
246
+
247
+
248
+ class LinePlotItem(AdaptiveGraphObject):
249
+ """
250
+ A class representing a line plot item for displaying data.
251
+
252
+ Attributes:
253
+ data (ChildDataFrame): The data containing the values to be plotted.
254
+ style (Style, optional): The style of the line plot item. Defaults to DEFAULT_STYLE.
255
+ """
256
+
257
+ MARKER_DRAWER = {"circle": draw_circle_marker, "o": draw_circle_marker}
258
+
259
+ def __init__(self, data: ChildDataFrame, style=LINE_DEFAULT_STYLE, marker=None):
260
+ super().__init__()
261
+ self.data = data
262
+ self.style = style
263
+ self.marker_drawer = self.MARKER_DRAWER.get(marker, None)
264
+ self.picture = QtGui.QPicture()
265
+ p = QtGui.QPainter(self.picture)
266
+ p.setPen(pg.mkPen(self.style.line_color, width=self.style.line_width))
267
+ x = data.data_frame.index.to_numpy()
268
+ for data_key in data.data_keys:
269
+ if data_key not in data.data_frame.columns:
270
+ raise ValueError(f"Data key '{data_key}' not found in data frame.")
271
+ y = data.data_frame[data_key].to_numpy()
272
+ p.drawPolyline(QtGui.QPolygonF([QtCore.QPointF(x[i], y[i]) for i in range(len(x))]))
273
+ p.end()
274
+
275
+ def paint(self, p, *args):
276
+ p.drawPicture(0, 0, self.picture)
277
+ if self.marker_drawer is not None:
278
+ transform = p.transform()
279
+ # Set marker color
280
+ p.setPen(pg.mkPen(self.style.marker_color, width=self.style.line_width))
281
+ p.setBrush(pg.mkBrush(self.style.marker_color))
282
+ marker_size = self.style.marker_size / 2
283
+ x = self.data.data_frame.index.to_numpy()
284
+ # Reset transformation to canvas transform, so marker is unaffected by data scaling.
285
+ p.resetTransform()
286
+ for data_key in self.data.data_keys:
287
+ if data_key not in self.data.data_frame.columns:
288
+ continue
289
+ y = self.data.data_frame[data_key].to_numpy()
290
+ for i in range(len(x)):
291
+ # Map data point to canvas coordinate.
292
+ data_pt = QtCore.QPointF(x[i], y[i])
293
+ canvas_pt = transform.map(data_pt)
294
+ self.marker_drawer(p, canvas_pt, marker_size)
295
+ # Restore the original transformation
296
+ p.setTransform(transform)
297
+
298
+ def boundingRect(self):
299
+ return QtCore.QRectF(self.picture.boundingRect())
300
+
301
+ def get_local_plot_range(self, x_start, x_end):
302
+ return self.data.get_local_range(x_start, x_end)
303
+
304
+ def get_x_ticks(self):
305
+ return self.data.get_x_ticks()
306
+
307
+ def get_feature_value(self, key=None):
308
+ return self.data.get_feature_value(key)
@@ -72,8 +72,41 @@ def default_style_configs() -> ConfigurationsHandler:
72
72
  return configs_handler
73
73
 
74
74
 
75
- def make_style(style_yaml_file="", **kwargs):
76
- configs_handler = default_style_configs()
75
+ def line_style_configs() -> ConfigurationsHandler:
76
+ configs_handler = ConfigurationsHandler()
77
+ configs_handler.add_config_item(
78
+ "line_color",
79
+ default_value=(255, 0, 0),
80
+ value_type=tuple,
81
+ in_func=lambda x, other_config: tuple_to_color(x),
82
+ out_func=lambda x, other_config: color_to_rbg_tuple(x),
83
+ description="color of the line",
84
+ )
85
+ configs_handler.add_config_item(
86
+ "line_width",
87
+ default_value=2.0,
88
+ value_type=float,
89
+ description="width of the line, the unit is pixel",
90
+ )
91
+ configs_handler.add_config_item(
92
+ "marker_color",
93
+ default_value=(255, 0, 0),
94
+ value_type=tuple,
95
+ in_func=lambda x, other_config: tuple_to_color(x),
96
+ out_func=lambda x, other_config: color_to_rbg_tuple(x),
97
+ description="color of the marker",
98
+ )
99
+ configs_handler.add_config_item(
100
+ "marker_size",
101
+ default_value=5.0,
102
+ value_type=float,
103
+ description="size of the marker",
104
+ )
105
+ return configs_handler
106
+
107
+
108
+ def make_style(configs_handler=None, style_yaml_file="", **kwargs):
109
+ configs_handler = configs_handler or default_style_configs()
77
110
  if style_yaml_file != "":
78
111
  configs_handler.set_config_items_from_yaml(style_yaml_file)
79
112
  configs_handler.set_config_items(**kwargs)
@@ -117,3 +150,4 @@ def set_background_with_theme(widget: QWidget, theme=None):
117
150
 
118
151
 
119
152
  DEFAULT_STYLE = make_style()
153
+ LINE_DEFAULT_STYLE = make_style(configs_handler=line_style_configs(), line_color=(255, 0, 0))
@@ -98,7 +98,7 @@ class CustomizedAxis(AxisItem):
98
98
  if self.plot_strs is None:
99
99
  return f"{value:.1f}"
100
100
  else:
101
- if value >= self.min_index and value <= self.max_index:
101
+ if self.min_index <= value <= self.max_index:
102
102
  return self.plot_strs[round(value)]
103
103
  else:
104
104
  return " "
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PySide6Plot
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: Scientific/Financial plot utilities with PySide6+pyqtgraph.
5
5
  Author-email: YQ Cui <qianyun210603@hotmail.com>
6
6
  License-Expression: MIT
@@ -34,5 +34,6 @@ PySide6Plot/widgets/transparent_selector.py
34
34
  PySide6Plot/widgets/value_select_box.py
35
35
  PySide6Plot/widgets/zoom_bar.py
36
36
  examples/price_volume_plotter.py
37
+ examples/qplotwidget_line_plot.py
37
38
  examples/sample_stock_data.h5
38
39
  examples/single_plotter.py
@@ -0,0 +1,43 @@
1
+ # @Time : 2025/7/16 21:43
2
+ # @Author : YQ Tsui
3
+ # @File : qplotwidget_line_plot.py
4
+ # @Purpose :
5
+ from PySide6Plot import QStockPlotter
6
+ from PySide6Plot.libs.data_handler import ChildDataFrame
7
+ from PySide6Plot.libs.plot_item import LinePlotItem
8
+ import numpy as np
9
+ import pandas as pd
10
+
11
+ if __name__ == "__main__":
12
+ from PySide6.QtWidgets import QApplication, QVBoxLayout, QWidget
13
+ import sys
14
+
15
+ app = QApplication(sys.argv)
16
+
17
+ # Create a main window
18
+ main_window = QWidget()
19
+ main_window.setWindowTitle("Line Plot Example")
20
+ main_window.setGeometry(100, 100, 800, 600)
21
+
22
+ # Create a QPlotWidget instance
23
+ plot_widget = QStockPlotter()
24
+
25
+ # Add some sample data to the plot
26
+ test_df = pd.DataFrame(
27
+ np.random.rand(100), index=pd.date_range(end="2025-07-15", periods=100).rename("date"), columns=["data"]
28
+ )
29
+ # plot_widget.plot(x=list(range(len(test_df["data"]))), y=test_df["data"], pen="b", name="Sample Data")
30
+ line_data = ChildDataFrame(test_df, "data", x_label_key="date")
31
+ line_data_item = LinePlotItem(line_data, marker="circle")
32
+
33
+ plot_widget.add_main_item(line_data_item, x_ticks=line_data_item.get_x_ticks())
34
+
35
+ # Set up the layout
36
+ layout = QVBoxLayout(main_window)
37
+ layout.addWidget(plot_widget)
38
+
39
+ main_window.setLayout(layout)
40
+
41
+ main_window.show()
42
+
43
+ sys.exit(app.exec())
File without changes
File without changes
File without changes
File without changes