Add a `Flow` compound type for coupling graphics with backing data-streams
parent
860ed99757
commit
e3a3fd2d39
|
@ -33,6 +33,7 @@ from PyQt5.QtWidgets import (
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
import trio
|
import trio
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from ._axes import (
|
from ._axes import (
|
||||||
DynamicDateAxis,
|
DynamicDateAxis,
|
||||||
|
@ -614,17 +615,30 @@ class LinkedSplits(QWidget):
|
||||||
cpw.sidepane.setMinimumWidth(sp_w)
|
cpw.sidepane.setMinimumWidth(sp_w)
|
||||||
cpw.sidepane.setMaximumWidth(sp_w)
|
cpw.sidepane.setMaximumWidth(sp_w)
|
||||||
|
|
||||||
# import pydantic
|
|
||||||
|
|
||||||
# class Graphics(pydantic.BaseModel):
|
# class FlowsTable(pydantic.BaseModel):
|
||||||
# '''
|
# '''
|
||||||
# Data-AGGRegate: high level API onto multiple (categorized)
|
# Data-AGGRegate: high level API onto multiple (categorized)
|
||||||
# ``ShmArray``s with high level processing routines for
|
# ``Flow``s with high level processing routines for
|
||||||
# graphics computations and display.
|
# multi-graphics computations and display.
|
||||||
|
|
||||||
# '''
|
# '''
|
||||||
# arrays: dict[str, np.ndarray] = {}
|
# flows: dict[str, np.ndarray] = {}
|
||||||
# graphics: dict[str, pg.GraphicsObject] = {}
|
|
||||||
|
|
||||||
|
class Flow(BaseModel):
|
||||||
|
'''
|
||||||
|
(FinancialSignal-)Flow compound type which wraps a real-time
|
||||||
|
graphics (curve) and its backing data stream together for high level
|
||||||
|
access and control.
|
||||||
|
|
||||||
|
'''
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
name: str
|
||||||
|
plot: pg.PlotItem
|
||||||
|
shm: Optional[ShmArray] = None # may be filled in "later"
|
||||||
|
|
||||||
|
|
||||||
class ChartPlotWidget(pg.PlotWidget):
|
class ChartPlotWidget(pg.PlotWidget):
|
||||||
|
@ -721,8 +735,9 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
self.data_key: array,
|
self.data_key: array,
|
||||||
}
|
}
|
||||||
self._graphics = {} # registry of underlying graphics
|
self._graphics = {} # registry of underlying graphics
|
||||||
|
|
||||||
# registry of overlay curve names
|
# registry of overlay curve names
|
||||||
self._overlays: dict[str, ShmArray] = {}
|
self._flows: dict[str, Flow] = {}
|
||||||
|
|
||||||
self._feeds: dict[Symbol, Feed] = {}
|
self._feeds: dict[Symbol, Feed] = {}
|
||||||
|
|
||||||
|
@ -981,7 +996,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
# TODO: this probably needs its own method?
|
# TODO: this probably needs its own method?
|
||||||
if overlay:
|
if overlay:
|
||||||
# anchor_at = ('bottom', 'left')
|
# anchor_at = ('bottom', 'left')
|
||||||
self._overlays[name] = None
|
self._flows[name] = Flow(name=name, plot=pi)
|
||||||
|
|
||||||
if isinstance(overlay, pg.PlotItem):
|
if isinstance(overlay, pg.PlotItem):
|
||||||
if overlay not in self.pi_overlay.overlays:
|
if overlay not in self.pi_overlay.overlays:
|
||||||
|
@ -1062,7 +1077,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
assert len(array)
|
assert len(array)
|
||||||
data_key = array_key or graphics_name
|
data_key = array_key or graphics_name
|
||||||
|
|
||||||
if graphics_name not in self._overlays:
|
if graphics_name not in self._flows:
|
||||||
self._arrays[self.name] = array
|
self._arrays[self.name] = array
|
||||||
else:
|
else:
|
||||||
self._arrays[data_key] = array
|
self._arrays[data_key] = array
|
||||||
|
@ -1164,12 +1179,15 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
# f"begin: {begin}, end: {end}, extra: {extra}"
|
# f"begin: {begin}, end: {end}, extra: {extra}"
|
||||||
# )
|
# )
|
||||||
|
|
||||||
|
# TODO: here we should instead look up the ``Flow.shm.array``
|
||||||
|
# and read directly from shm to avoid copying to memory first
|
||||||
|
# and then reading it again here.
|
||||||
a = self._arrays.get(name or self.name)
|
a = self._arrays.get(name or self.name)
|
||||||
if a is None:
|
if a is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ifirst = a[0]['index']
|
ifirst = a[0]['index']
|
||||||
bars = a[lbar - ifirst:rbar - ifirst + 1]
|
bars = a[lbar - ifirst:(rbar - ifirst) + 1]
|
||||||
|
|
||||||
if not len(bars):
|
if not len(bars):
|
||||||
# likely no data loaded yet or extreme scrolling?
|
# likely no data loaded yet or extreme scrolling?
|
||||||
|
|
Loading…
Reference in New Issue