Rename `Flow` -> `Viz`
The type is better described as a "data visualization": https://en.wikipedia.org/wiki/Data_and_information_visualization Add `ChartPlotWidget.get_viz()` to start working towards not accessing the private table directly XD We'll probably end up using the name `Flow` for a type that tracks a collection of composed/cascaded `Flume`s: https://en.wikipedia.org/wiki/Two-port_network#Cascade_connectionepoch_indexing_and_dataviz_layer
parent
9ace053aaf
commit
86d09d9305
|
@ -302,7 +302,7 @@ class DynamicDateAxis(Axis):
|
||||||
# XX: ARGGGGG AG:LKSKDJF:LKJSDFD
|
# XX: ARGGGGG AG:LKSKDJF:LKJSDFD
|
||||||
chart = self.pi.chart_widget
|
chart = self.pi.chart_widget
|
||||||
|
|
||||||
flow = chart._flows[chart.name]
|
flow = chart._vizs[chart.name]
|
||||||
shm = flow.shm
|
shm = flow.shm
|
||||||
bars = shm.array
|
bars = shm.array
|
||||||
first = shm._first.value
|
first = shm._first.value
|
||||||
|
|
|
@ -72,7 +72,7 @@ from ._interaction import ChartView
|
||||||
from ._forms import FieldsForm
|
from ._forms import FieldsForm
|
||||||
from .._profile import pg_profile_enabled, ms_slower_then
|
from .._profile import pg_profile_enabled, ms_slower_then
|
||||||
from ._overlay import PlotItemOverlay
|
from ._overlay import PlotItemOverlay
|
||||||
from ._flows import Flow
|
from ._flows import Viz
|
||||||
from ._search import SearchWidget
|
from ._search import SearchWidget
|
||||||
from . import _pg_overrides as pgo
|
from . import _pg_overrides as pgo
|
||||||
from .._profile import Profiler
|
from .._profile import Profiler
|
||||||
|
@ -711,7 +711,7 @@ class LinkedSplits(QWidget):
|
||||||
if style == 'ohlc_bar':
|
if style == 'ohlc_bar':
|
||||||
|
|
||||||
# graphics, data_key = cpw.draw_ohlc(
|
# graphics, data_key = cpw.draw_ohlc(
|
||||||
flow = cpw.draw_ohlc(
|
viz = cpw.draw_ohlc(
|
||||||
name,
|
name,
|
||||||
shm,
|
shm,
|
||||||
flume=flume,
|
flume=flume,
|
||||||
|
@ -727,7 +727,7 @@ class LinkedSplits(QWidget):
|
||||||
elif style == 'line':
|
elif style == 'line':
|
||||||
add_label = True
|
add_label = True
|
||||||
# graphics, data_key = cpw.draw_curve(
|
# graphics, data_key = cpw.draw_curve(
|
||||||
flow = cpw.draw_curve(
|
viz = cpw.draw_curve(
|
||||||
name,
|
name,
|
||||||
shm,
|
shm,
|
||||||
flume,
|
flume,
|
||||||
|
@ -738,7 +738,7 @@ class LinkedSplits(QWidget):
|
||||||
elif style == 'step':
|
elif style == 'step':
|
||||||
add_label = True
|
add_label = True
|
||||||
# graphics, data_key = cpw.draw_curve(
|
# graphics, data_key = cpw.draw_curve(
|
||||||
flow = cpw.draw_curve(
|
viz = cpw.draw_curve(
|
||||||
name,
|
name,
|
||||||
shm,
|
shm,
|
||||||
flume,
|
flume,
|
||||||
|
@ -751,8 +751,8 @@ class LinkedSplits(QWidget):
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Chart style {style} is currently unsupported")
|
raise ValueError(f"Chart style {style} is currently unsupported")
|
||||||
|
|
||||||
graphics = flow.graphics
|
graphics = viz.graphics
|
||||||
data_key = flow.name
|
data_key = viz.name
|
||||||
|
|
||||||
if _is_main:
|
if _is_main:
|
||||||
assert style == 'ohlc_bar', 'main chart must be OHLC'
|
assert style == 'ohlc_bar', 'main chart must be OHLC'
|
||||||
|
@ -908,7 +908,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
# self.setViewportMargins(0, 0, 0, 0)
|
# self.setViewportMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
# registry of overlay curve names
|
# registry of overlay curve names
|
||||||
self._flows: dict[str, Flow] = {}
|
self._vizs: dict[str, Viz] = {}
|
||||||
|
|
||||||
self.feed: Feed | None = None
|
self.feed: Feed | None = None
|
||||||
|
|
||||||
|
@ -974,7 +974,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
Return a range tuple for the bars present in view.
|
Return a range tuple for the bars present in view.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
main_flow = self._flows[self.name]
|
main_flow = self._vizs[self.name]
|
||||||
ifirst, l, lbar, rbar, r, ilast = main_flow.datums_range()
|
ifirst, l, lbar, rbar, r, ilast = main_flow.datums_range()
|
||||||
return l, lbar, rbar, r
|
return l, lbar, rbar, r
|
||||||
|
|
||||||
|
@ -1038,9 +1038,9 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
Set the view box to the "default" startup view of the scene.
|
Set the view box to the "default" startup view of the scene.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
flow = self._flows.get(self.name)
|
flow = self._vizs.get(self.name)
|
||||||
if not flow:
|
if not flow:
|
||||||
log.warning(f'`Flow` for {self.name} not loaded yet?')
|
log.warning(f'`Viz` for {self.name} not loaded yet?')
|
||||||
return
|
return
|
||||||
|
|
||||||
arr = flow.shm.array
|
arr = flow.shm.array
|
||||||
|
@ -1220,7 +1220,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
|
|
||||||
**graphics_kwargs,
|
**graphics_kwargs,
|
||||||
|
|
||||||
) -> Flow:
|
) -> Viz:
|
||||||
'''
|
'''
|
||||||
Draw a "curve" (line plot graphics) for the provided data in
|
Draw a "curve" (line plot graphics) for the provided data in
|
||||||
the input shm array ``shm``.
|
the input shm array ``shm``.
|
||||||
|
@ -1254,7 +1254,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
**graphics_kwargs,
|
**graphics_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
flow = self._flows[data_key] = Flow(
|
flow = self._vizs[data_key] = Viz(
|
||||||
data_key,
|
data_key,
|
||||||
pi,
|
pi,
|
||||||
shm,
|
shm,
|
||||||
|
@ -1332,7 +1332,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
array_key: Optional[str] = None,
|
array_key: Optional[str] = None,
|
||||||
**draw_curve_kwargs,
|
**draw_curve_kwargs,
|
||||||
|
|
||||||
) -> Flow:
|
) -> Viz:
|
||||||
'''
|
'''
|
||||||
Draw OHLC datums to chart.
|
Draw OHLC datums to chart.
|
||||||
|
|
||||||
|
@ -1358,7 +1358,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
Update the named internal graphics from ``array``.
|
Update the named internal graphics from ``array``.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
flow = self._flows[array_key or graphics_name]
|
flow = self._vizs[array_key or graphics_name]
|
||||||
return flow.update_graphics(
|
return flow.update_graphics(
|
||||||
array_key=array_key,
|
array_key=array_key,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
|
@ -1426,15 +1426,15 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
delayed=True,
|
delayed=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: here we should instead look up the ``Flow.shm.array``
|
# TODO: here we should instead look up the ``Viz.shm.array``
|
||||||
# and read directly from shm to avoid copying to memory first
|
# and read directly from shm to avoid copying to memory first
|
||||||
# and then reading it again here.
|
# and then reading it again here.
|
||||||
flow_key = name or self.name
|
flow_key = name or self.name
|
||||||
flow = self._flows.get(flow_key)
|
viz = self._vizs.get(flow_key)
|
||||||
if (
|
if (
|
||||||
flow is None
|
viz is None
|
||||||
):
|
):
|
||||||
log.error(f"flow {flow_key} doesn't exist in chart {self.name} !?")
|
log.error(f"viz {flow_key} doesn't exist in chart {self.name} !?")
|
||||||
key = res = 0, 0
|
key = res = 0, 0
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -1445,11 +1445,11 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
rbar,
|
rbar,
|
||||||
r,
|
r,
|
||||||
last,
|
last,
|
||||||
) = bars_range or flow.datums_range()
|
) = bars_range or viz.datums_range()
|
||||||
profiler(f'{self.name} got bars range')
|
profiler(f'{self.name} got bars range')
|
||||||
|
|
||||||
key = round(lbar), round(rbar)
|
key = round(lbar), round(rbar)
|
||||||
res = flow.maxmin(*key)
|
res = viz.maxmin(*key)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
res is None
|
res is None
|
||||||
|
@ -1465,3 +1465,9 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
profiler(f'yrange mxmn: {key} -> {res}')
|
profiler(f'yrange mxmn: {key} -> {res}')
|
||||||
# print(f'{flow_key} yrange mxmn: {key} -> {res}')
|
# print(f'{flow_key} yrange mxmn: {key} -> {res}')
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def get_viz(
|
||||||
|
self,
|
||||||
|
key: str,
|
||||||
|
) -> Viz:
|
||||||
|
return self._vizs[key]
|
||||||
|
|
|
@ -274,8 +274,8 @@ class ContentsLabels:
|
||||||
) -> None:
|
) -> None:
|
||||||
for chart, name, label, update in self._labels:
|
for chart, name, label, update in self._labels:
|
||||||
|
|
||||||
flow = chart._flows[name]
|
viz = chart.get_viz(name)
|
||||||
array = flow.shm.array
|
array = viz.shm.array
|
||||||
|
|
||||||
if not (
|
if not (
|
||||||
index >= 0
|
index >= 0
|
||||||
|
@ -482,25 +482,32 @@ class Cursor(pg.GraphicsObject):
|
||||||
|
|
||||||
def add_curve_cursor(
|
def add_curve_cursor(
|
||||||
self,
|
self,
|
||||||
plot: ChartPlotWidget, # noqa
|
chart: ChartPlotWidget, # noqa
|
||||||
curve: 'PlotCurveItem', # noqa
|
curve: 'PlotCurveItem', # noqa
|
||||||
|
|
||||||
) -> LineDot:
|
) -> LineDot:
|
||||||
# if this plot contains curves add line dot "cursors" to denote
|
# if this chart contains curves add line dot "cursors" to denote
|
||||||
# the current sample under the mouse
|
# the current sample under the mouse
|
||||||
main_flow = plot._flows[plot.name]
|
main_viz = chart.get_viz(chart.name)
|
||||||
|
|
||||||
# read out last index
|
# read out last index
|
||||||
i = main_flow.shm.array[-1]['index']
|
i = main_viz.shm.array[-1]['index']
|
||||||
cursor = LineDot(
|
cursor = LineDot(
|
||||||
curve,
|
curve,
|
||||||
index=i,
|
index=i,
|
||||||
plot=plot
|
plot=chart
|
||||||
)
|
)
|
||||||
plot.addItem(cursor)
|
chart.addItem(cursor)
|
||||||
self.graphics[plot].setdefault('cursors', []).append(cursor)
|
self.graphics[chart].setdefault('cursors', []).append(cursor)
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def mouseAction(self, action, plot): # noqa
|
def mouseAction(
|
||||||
|
self,
|
||||||
|
action: str,
|
||||||
|
plot: ChartPlotWidget,
|
||||||
|
|
||||||
|
) -> None: # noqa
|
||||||
|
|
||||||
log.debug(f"{(action, plot.name)}")
|
log.debug(f"{(action, plot.name)}")
|
||||||
if action == 'Enter':
|
if action == 'Enter':
|
||||||
self.active_plot = plot
|
self.active_plot = plot
|
||||||
|
|
|
@ -78,7 +78,7 @@ from .._profile import Profiler
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# TODO: delegate this to each `Flow.maxmin()` which includes
|
# TODO: delegate this to each `Viz.maxmin()` which includes
|
||||||
# caching and further we should implement the following stream based
|
# caching and further we should implement the following stream based
|
||||||
# approach, likely with ``numba``:
|
# approach, likely with ``numba``:
|
||||||
# https://arxiv.org/abs/cs/0610046
|
# https://arxiv.org/abs/cs/0610046
|
||||||
|
@ -113,7 +113,7 @@ def chart_maxmin(
|
||||||
|
|
||||||
# TODO: we need to NOT call this to avoid a manual
|
# TODO: we need to NOT call this to avoid a manual
|
||||||
# np.max/min trigger and especially on the vlm_chart
|
# np.max/min trigger and especially on the vlm_chart
|
||||||
# flows which aren't shown.. like vlm?
|
# vizs which aren't shown.. like vlm?
|
||||||
if vlm_chart:
|
if vlm_chart:
|
||||||
out = vlm_chart.maxmin()
|
out = vlm_chart.maxmin()
|
||||||
if out:
|
if out:
|
||||||
|
@ -220,7 +220,7 @@ class DisplayState(Struct):
|
||||||
_, _, _, r = chart.bars_range()
|
_, _, _, r = chart.bars_range()
|
||||||
liv = r >= shm.index
|
liv = r >= shm.index
|
||||||
|
|
||||||
# update the "last datum" (aka extending the flow graphic with
|
# update the "last datum" (aka extending the vizs graphic with
|
||||||
# new data) only if the number of unit steps is >= the number of
|
# new data) only if the number of unit steps is >= the number of
|
||||||
# such unit steps per pixel (aka uppx). Iow, if the zoom level
|
# such unit steps per pixel (aka uppx). Iow, if the zoom level
|
||||||
# is such that a datum(s) update to graphics wouldn't span
|
# is such that a datum(s) update to graphics wouldn't span
|
||||||
|
@ -301,14 +301,14 @@ async def graphics_update_loop(
|
||||||
fqsn = symbol.fqsn
|
fqsn = symbol.fqsn
|
||||||
|
|
||||||
# update last price sticky
|
# update last price sticky
|
||||||
fast_pi = fast_chart._flows[fqsn].plot
|
fast_pi = fast_chart._vizs[fqsn].plot
|
||||||
last_price_sticky = fast_pi.getAxis('right')._stickies[fqsn]
|
last_price_sticky = fast_pi.getAxis('right')._stickies[fqsn]
|
||||||
last_price_sticky.update_from_data(
|
last_price_sticky.update_from_data(
|
||||||
*ohlcv.array[-1][['index', 'close']]
|
*ohlcv.array[-1][['index', 'close']]
|
||||||
)
|
)
|
||||||
last_price_sticky.show()
|
last_price_sticky.show()
|
||||||
|
|
||||||
slow_pi = hist_chart._flows[fqsn].plot
|
slow_pi = hist_chart._vizs[fqsn].plot
|
||||||
hist_last_price_sticky = slow_pi.getAxis('right')._stickies[fqsn]
|
hist_last_price_sticky = slow_pi.getAxis('right')._stickies[fqsn]
|
||||||
hist_last_price_sticky.update_from_data(
|
hist_last_price_sticky.update_from_data(
|
||||||
*hist_ohlcv.array[-1][['index', 'close']]
|
*hist_ohlcv.array[-1][['index', 'close']]
|
||||||
|
@ -383,7 +383,7 @@ async def graphics_update_loop(
|
||||||
})
|
})
|
||||||
|
|
||||||
if vlm_chart:
|
if vlm_chart:
|
||||||
vlm_pi = vlm_chart._flows['volume'].plot
|
vlm_pi = vlm_chart._vizs['volume'].plot
|
||||||
vlm_sticky = vlm_pi.getAxis('right')._stickies['volume']
|
vlm_sticky = vlm_pi.getAxis('right')._stickies['volume']
|
||||||
ds.vlm_chart = vlm_chart
|
ds.vlm_chart = vlm_chart
|
||||||
ds.vlm_sticky = vlm_sticky
|
ds.vlm_sticky = vlm_sticky
|
||||||
|
@ -441,8 +441,8 @@ async def graphics_update_loop(
|
||||||
and liv
|
and liv
|
||||||
):
|
):
|
||||||
# hist_chart.increment_view(steps=i_diff)
|
# hist_chart.increment_view(steps=i_diff)
|
||||||
flow = hist_chart._flows[fqsn]
|
viz = hist_chart._vizs[fqsn]
|
||||||
flow.plot.vb._set_yrange(
|
viz.plot.vb._set_yrange(
|
||||||
# yrange=hist_chart.maxmin(name=fqsn)
|
# yrange=hist_chart.maxmin(name=fqsn)
|
||||||
)
|
)
|
||||||
# hist_chart.view._set_yrange(yrange=hist_chart.maxmin())
|
# hist_chart.view._set_yrange(yrange=hist_chart.maxmin())
|
||||||
|
@ -518,7 +518,7 @@ def graphics_update_cycle(
|
||||||
flume = ds.flume
|
flume = ds.flume
|
||||||
sym = flume.symbol
|
sym = flume.symbol
|
||||||
fqsn = sym.fqsn
|
fqsn = sym.fqsn
|
||||||
main_flow = chart._flows[fqsn]
|
main_viz = chart._vizs[fqsn]
|
||||||
|
|
||||||
profiler = Profiler(
|
profiler = Profiler(
|
||||||
msg=f'Graphics loop cycle for: `{chart.name}`',
|
msg=f'Graphics loop cycle for: `{chart.name}`',
|
||||||
|
@ -562,7 +562,7 @@ def graphics_update_cycle(
|
||||||
):
|
):
|
||||||
# print(f'INCREMENTING {fqsn}')
|
# print(f'INCREMENTING {fqsn}')
|
||||||
chart.increment_view(steps=i_diff)
|
chart.increment_view(steps=i_diff)
|
||||||
main_flow.plot.vb._set_yrange(
|
main_viz.plot.vb._set_yrange(
|
||||||
# yrange=(mn, mx),
|
# yrange=(mn, mx),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -629,7 +629,7 @@ def graphics_update_cycle(
|
||||||
# chart.name,
|
# chart.name,
|
||||||
# do_append=do_append,
|
# do_append=do_append,
|
||||||
)
|
)
|
||||||
main_flow.draw_last(array_key=fqsn)
|
main_viz.draw_last(array_key=fqsn)
|
||||||
|
|
||||||
hist_chart.update_graphics_from_flow(
|
hist_chart.update_graphics_from_flow(
|
||||||
fqsn,
|
fqsn,
|
||||||
|
@ -748,7 +748,7 @@ def graphics_update_cycle(
|
||||||
and not chart._static_yrange == 'axis'
|
and not chart._static_yrange == 'axis'
|
||||||
):
|
):
|
||||||
# main_vb = chart.view
|
# main_vb = chart.view
|
||||||
main_vb = chart._flows[fqsn].plot.vb
|
main_vb = chart._vizs[fqsn].plot.vb
|
||||||
if (
|
if (
|
||||||
main_vb._ic is None
|
main_vb._ic is None
|
||||||
or not main_vb._ic.is_set()
|
or not main_vb._ic.is_set()
|
||||||
|
@ -779,26 +779,26 @@ def graphics_update_cycle(
|
||||||
is_1m=True,
|
is_1m=True,
|
||||||
)
|
)
|
||||||
if hist_liv:
|
if hist_liv:
|
||||||
flow = hist_chart._flows[fqsn]
|
viz = hist_chart._vizs[fqsn]
|
||||||
flow.plot.vb._set_yrange(
|
viz.plot.vb._set_yrange(
|
||||||
# yrange=hist_chart.maxmin(name=fqsn),
|
# yrange=hist_chart.maxmin(name=fqsn),
|
||||||
)
|
)
|
||||||
|
|
||||||
# XXX: update this every draw cycle to make L1-always-in-view work.
|
# XXX: update this every draw cycle to make L1-always-in-view work.
|
||||||
vars['last_mx'], vars['last_mn'] = mx, mn
|
vars['last_mx'], vars['last_mn'] = mx, mn
|
||||||
|
|
||||||
# run synchronous update on all linked flows
|
# run synchronous update on all linked viz
|
||||||
# TODO: should the "main" (aka source) flow be special?
|
# TODO: should the "main" (aka source) viz be special?
|
||||||
for curve_name, flow in chart._flows.items():
|
for curve_name, viz in chart._vizs.items():
|
||||||
# update any overlayed fsp flows
|
# update any overlayed fsp flows
|
||||||
if (
|
if (
|
||||||
# curve_name != chart.data_key
|
# curve_name != chart.data_key
|
||||||
curve_name != fqsn
|
curve_name != fqsn
|
||||||
and not flow.is_ohlc
|
and not viz.is_ohlc
|
||||||
):
|
):
|
||||||
update_fsp_chart(
|
update_fsp_chart(
|
||||||
chart,
|
chart,
|
||||||
flow,
|
viz,
|
||||||
curve_name,
|
curve_name,
|
||||||
array_key=curve_name,
|
array_key=curve_name,
|
||||||
)
|
)
|
||||||
|
@ -812,7 +812,7 @@ def graphics_update_cycle(
|
||||||
# and not do_append
|
# and not do_append
|
||||||
# and not do_rt_update
|
# and not do_rt_update
|
||||||
):
|
):
|
||||||
flow.draw_last(
|
viz.draw_last(
|
||||||
array_key=curve_name,
|
array_key=curve_name,
|
||||||
only_last_uppx=True,
|
only_last_uppx=True,
|
||||||
)
|
)
|
||||||
|
@ -821,7 +821,7 @@ def graphics_update_cycle(
|
||||||
# TODO: can we unify this with the above loop?
|
# TODO: can we unify this with the above loop?
|
||||||
if vlm_chart:
|
if vlm_chart:
|
||||||
# print(f"DOING VLM {fqsn}")
|
# print(f"DOING VLM {fqsn}")
|
||||||
vlm_flows = vlm_chart._flows
|
vlm_vizs = vlm_chart._vizs
|
||||||
|
|
||||||
# always update y-label
|
# always update y-label
|
||||||
ds.vlm_sticky.update_from_data(
|
ds.vlm_sticky.update_from_data(
|
||||||
|
@ -866,21 +866,21 @@ def graphics_update_cycle(
|
||||||
vars['last_mx_vlm'] = mx_vlm_in_view
|
vars['last_mx_vlm'] = mx_vlm_in_view
|
||||||
|
|
||||||
# update all downstream FSPs
|
# update all downstream FSPs
|
||||||
for curve_name, flow in vlm_flows.items():
|
for curve_name, viz in vlm_vizs.items():
|
||||||
|
|
||||||
if (
|
if (
|
||||||
curve_name not in {'volume', fqsn}
|
curve_name not in {'volume', fqsn}
|
||||||
and flow.render
|
and viz.render
|
||||||
and (
|
and (
|
||||||
liv and do_rt_update
|
liv and do_rt_update
|
||||||
or do_append
|
or do_append
|
||||||
)
|
)
|
||||||
# and not flow.is_ohlc
|
# and not viz.is_ohlc
|
||||||
# and curve_name != fqsn
|
# and curve_name != fqsn
|
||||||
):
|
):
|
||||||
update_fsp_chart(
|
update_fsp_chart(
|
||||||
vlm_chart,
|
vlm_chart,
|
||||||
flow,
|
viz,
|
||||||
curve_name,
|
curve_name,
|
||||||
array_key=curve_name,
|
array_key=curve_name,
|
||||||
# do_append=uppx < update_uppx,
|
# do_append=uppx < update_uppx,
|
||||||
|
@ -889,7 +889,7 @@ def graphics_update_cycle(
|
||||||
# is this even doing anything?
|
# is this even doing anything?
|
||||||
# (pretty sure it's the real-time
|
# (pretty sure it's the real-time
|
||||||
# resizing from last quote?)
|
# resizing from last quote?)
|
||||||
fvb = flow.plot.vb
|
fvb = viz.plot.vb
|
||||||
fvb._set_yrange(
|
fvb._set_yrange(
|
||||||
name=curve_name,
|
name=curve_name,
|
||||||
)
|
)
|
||||||
|
@ -905,9 +905,9 @@ def graphics_update_cycle(
|
||||||
# range of that set.
|
# range of that set.
|
||||||
):
|
):
|
||||||
# always update the last datum-element
|
# always update the last datum-element
|
||||||
# graphic for all flows
|
# graphic for all vizs
|
||||||
# print(f'drawing last {flow.name}')
|
# print(f'drawing last {viz.name}')
|
||||||
flow.draw_last(array_key=curve_name)
|
viz.draw_last(array_key=curve_name)
|
||||||
|
|
||||||
|
|
||||||
async def link_views_with_region(
|
async def link_views_with_region(
|
||||||
|
@ -937,12 +937,12 @@ async def link_views_with_region(
|
||||||
hist_pi.addItem(region, ignoreBounds=True)
|
hist_pi.addItem(region, ignoreBounds=True)
|
||||||
region.setOpacity(6/16)
|
region.setOpacity(6/16)
|
||||||
|
|
||||||
flow = rt_chart._flows[flume.symbol.fqsn]
|
viz = rt_chart._vizs[flume.symbol.fqsn]
|
||||||
assert flow
|
assert viz
|
||||||
|
|
||||||
# XXX: no idea why this doesn't work but it's causing
|
# XXX: no idea why this doesn't work but it's causing
|
||||||
# a weird placement of the region on the way-far-left..
|
# a weird placement of the region on the way-far-left..
|
||||||
# region.setClipItem(flow.graphics)
|
# region.setClipItem(viz.graphics)
|
||||||
|
|
||||||
# poll for datums load and timestep detection
|
# poll for datums load and timestep detection
|
||||||
for _ in range(100):
|
for _ in range(100):
|
||||||
|
@ -1052,11 +1052,11 @@ def multi_maxmin(
|
||||||
|
|
||||||
) -> tuple[float, float]:
|
) -> tuple[float, float]:
|
||||||
'''
|
'''
|
||||||
Flows "group" maxmin loop; assumes all named flows
|
Viz "group" maxmin loop; assumes all named vizs
|
||||||
are in the same co-domain and thus can be sorted
|
are in the same co-domain and thus can be sorted
|
||||||
as one set.
|
as one set.
|
||||||
|
|
||||||
Iterates all the named flows and calls the chart
|
Iterates all the named vizs and calls the chart
|
||||||
api to find their range values and return.
|
api to find their range values and return.
|
||||||
|
|
||||||
TODO: really we should probably have a more built-in API
|
TODO: really we should probably have a more built-in API
|
||||||
|
@ -1279,7 +1279,7 @@ async def display_symbol_data(
|
||||||
hist_pi.hideAxis('left')
|
hist_pi.hideAxis('left')
|
||||||
hist_pi.hideAxis('bottom')
|
hist_pi.hideAxis('bottom')
|
||||||
|
|
||||||
flow = hist_chart.draw_curve(
|
viz = hist_chart.draw_curve(
|
||||||
fqsn,
|
fqsn,
|
||||||
hist_ohlcv,
|
hist_ohlcv,
|
||||||
flume,
|
flume,
|
||||||
|
@ -1300,8 +1300,8 @@ async def display_symbol_data(
|
||||||
# specially store ref to shm for lookup in display loop
|
# specially store ref to shm for lookup in display loop
|
||||||
# since only a placeholder of `None` is entered in
|
# since only a placeholder of `None` is entered in
|
||||||
# ``.draw_curve()``.
|
# ``.draw_curve()``.
|
||||||
flow = hist_chart._flows[fqsn]
|
viz = hist_chart._vizs[fqsn]
|
||||||
assert flow.plot is hist_pi
|
assert viz.plot is hist_pi
|
||||||
pis.setdefault(fqsn, [None, None])[1] = hist_pi
|
pis.setdefault(fqsn, [None, None])[1] = hist_pi
|
||||||
|
|
||||||
rt_pi = rt_chart.overlay_plotitem(
|
rt_pi = rt_chart.overlay_plotitem(
|
||||||
|
@ -1312,7 +1312,7 @@ async def display_symbol_data(
|
||||||
rt_pi.hideAxis('left')
|
rt_pi.hideAxis('left')
|
||||||
rt_pi.hideAxis('bottom')
|
rt_pi.hideAxis('bottom')
|
||||||
|
|
||||||
flow = rt_chart.draw_curve(
|
viz = rt_chart.draw_curve(
|
||||||
fqsn,
|
fqsn,
|
||||||
ohlcv,
|
ohlcv,
|
||||||
flume,
|
flume,
|
||||||
|
@ -1333,8 +1333,8 @@ async def display_symbol_data(
|
||||||
# specially store ref to shm for lookup in display loop
|
# specially store ref to shm for lookup in display loop
|
||||||
# since only a placeholder of `None` is entered in
|
# since only a placeholder of `None` is entered in
|
||||||
# ``.draw_curve()``.
|
# ``.draw_curve()``.
|
||||||
flow = rt_chart._flows[fqsn]
|
viz = rt_chart._vizs[fqsn]
|
||||||
assert flow.plot is rt_pi
|
assert viz.plot is rt_pi
|
||||||
pis.setdefault(fqsn, [None, None])[0] = rt_pi
|
pis.setdefault(fqsn, [None, None])[0] = rt_pi
|
||||||
|
|
||||||
rt_chart.setFocus()
|
rt_chart.setFocus()
|
||||||
|
|
|
@ -377,7 +377,7 @@ class SelectRect(QtWidgets.QGraphicsRectItem):
|
||||||
nbars = ixmx - ixmn + 1
|
nbars = ixmx - ixmn + 1
|
||||||
|
|
||||||
chart = self._chart
|
chart = self._chart
|
||||||
data = chart._flows[chart.name].shm.array[ixmn:ixmx]
|
data = chart.get_viz(chart.name).shm.array[ixmn:ixmx]
|
||||||
|
|
||||||
if len(data):
|
if len(data):
|
||||||
std = data['close'].std()
|
std = data['close'].std()
|
||||||
|
|
|
@ -65,7 +65,7 @@ log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def render_baritems(
|
def render_baritems(
|
||||||
flow: Flow,
|
viz: Viz,
|
||||||
graphics: BarItems,
|
graphics: BarItems,
|
||||||
read: tuple[
|
read: tuple[
|
||||||
int, int, np.ndarray,
|
int, int, np.ndarray,
|
||||||
|
@ -89,7 +89,7 @@ def render_baritems(
|
||||||
bars = graphics
|
bars = graphics
|
||||||
|
|
||||||
# if no source data renderer exists create one.
|
# if no source data renderer exists create one.
|
||||||
self = flow
|
self = viz
|
||||||
show_bars: bool = False
|
show_bars: bool = False
|
||||||
|
|
||||||
r = self._src_r
|
r = self._src_r
|
||||||
|
@ -98,28 +98,28 @@ def render_baritems(
|
||||||
|
|
||||||
# OHLC bars path renderer
|
# OHLC bars path renderer
|
||||||
r = self._src_r = Renderer(
|
r = self._src_r = Renderer(
|
||||||
flow=self,
|
viz=self,
|
||||||
fmtr=OHLCBarsFmtr(
|
fmtr=OHLCBarsFmtr(
|
||||||
shm=flow.shm,
|
shm=viz.shm,
|
||||||
flow=flow,
|
viz=viz,
|
||||||
_last_read=read,
|
_last_read=read,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
ds_curve_r = Renderer(
|
ds_curve_r = Renderer(
|
||||||
flow=self,
|
viz=self,
|
||||||
fmtr=OHLCBarsAsCurveFmtr(
|
fmtr=OHLCBarsAsCurveFmtr(
|
||||||
shm=flow.shm,
|
shm=viz.shm,
|
||||||
flow=flow,
|
viz=viz,
|
||||||
_last_read=read,
|
_last_read=read,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
curve = FlattenedOHLC(
|
curve = FlattenedOHLC(
|
||||||
name=f'{flow.name}_ds_ohlc',
|
name=f'{viz.name}_ds_ohlc',
|
||||||
color=bars._color,
|
color=bars._color,
|
||||||
)
|
)
|
||||||
flow.ds_graphics = curve
|
viz.ds_graphics = curve
|
||||||
curve.hide()
|
curve.hide()
|
||||||
self.plot.addItem(curve)
|
self.plot.addItem(curve)
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ def render_baritems(
|
||||||
):
|
):
|
||||||
# print('FLIPPING TO BARS')
|
# print('FLIPPING TO BARS')
|
||||||
should_line = False
|
should_line = False
|
||||||
flow._in_ds = False
|
viz._in_ds = False
|
||||||
|
|
||||||
elif (
|
elif (
|
||||||
not in_line
|
not in_line
|
||||||
|
@ -150,7 +150,7 @@ def render_baritems(
|
||||||
):
|
):
|
||||||
# print('FLIPPING TO LINE')
|
# print('FLIPPING TO LINE')
|
||||||
should_line = True
|
should_line = True
|
||||||
flow._in_ds = True
|
viz._in_ds = True
|
||||||
|
|
||||||
profiler(f'ds logic complete line={should_line}')
|
profiler(f'ds logic complete line={should_line}')
|
||||||
|
|
||||||
|
@ -196,9 +196,9 @@ def render_baritems(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Flow(msgspec.Struct): # , frozen=True):
|
class Viz(msgspec.Struct): # , frozen=True):
|
||||||
'''
|
'''
|
||||||
(Financial Signal-)Flow compound type which wraps a real-time
|
(Data) "Visualization" compound type which wraps a real-time
|
||||||
shm array stream with displayed graphics (curves, charts)
|
shm array stream with displayed graphics (curves, charts)
|
||||||
for high level access and control as well as efficient incremental
|
for high level access and control as well as efficient incremental
|
||||||
update.
|
update.
|
||||||
|
@ -216,7 +216,7 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
# for tracking y-mn/mx for y-axis auto-ranging
|
# for tracking y-mn/mx for y-axis auto-ranging
|
||||||
yrange: tuple[float, float] = None
|
yrange: tuple[float, float] = None
|
||||||
|
|
||||||
# in some cases a flow may want to change its
|
# in some cases a viz may want to change its
|
||||||
# graphical "type" or, "form" when downsampling, to
|
# graphical "type" or, "form" when downsampling, to
|
||||||
# start this is only ever an interpolation line.
|
# start this is only ever an interpolation line.
|
||||||
ds_graphics: Optional[Curve] = None
|
ds_graphics: Optional[Curve] = None
|
||||||
|
@ -251,12 +251,6 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
def shm(self) -> ShmArray:
|
def shm(self) -> ShmArray:
|
||||||
return self._shm
|
return self._shm
|
||||||
|
|
||||||
# TODO: remove this and only allow setting through
|
|
||||||
# private ``._shm`` attr?
|
|
||||||
# @shm.setter
|
|
||||||
# def shm(self, shm: ShmArray) -> ShmArray:
|
|
||||||
# self._shm = shm
|
|
||||||
|
|
||||||
def maxmin(
|
def maxmin(
|
||||||
self,
|
self,
|
||||||
lbar: int,
|
lbar: int,
|
||||||
|
@ -318,7 +312,7 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
def view_range(self) -> tuple[int, int]:
|
def view_range(self) -> tuple[int, int]:
|
||||||
'''
|
'''
|
||||||
Return the indexes in view for the associated
|
Return the indexes in view for the associated
|
||||||
plot displaying this flow's data.
|
plot displaying this viz's data.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
vr = self.plot.viewRect()
|
vr = self.plot.viewRect()
|
||||||
|
@ -344,7 +338,7 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
# TODO: avoid this and have shm passed
|
# TODO: avoid this and have shm passed
|
||||||
# in earlier.
|
# in earlier.
|
||||||
if self.shm is None:
|
if self.shm is None:
|
||||||
# haven't initialized the flow yet
|
# haven't initialized the viz yet
|
||||||
return (0, l, 0, 0, r, 0)
|
return (0, l, 0, 0, r, 0)
|
||||||
|
|
||||||
array = self.shm.array
|
array = self.shm.array
|
||||||
|
@ -420,7 +414,7 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
profiler = Profiler(
|
profiler = Profiler(
|
||||||
msg=f'Flow.update_graphics() for {self.name}',
|
msg=f'Viz.update_graphics() for {self.name}',
|
||||||
disabled=not pg_profile_enabled(),
|
disabled=not pg_profile_enabled(),
|
||||||
ms_threshold=4,
|
ms_threshold=4,
|
||||||
# ms_threshold=ms_slower_then,
|
# ms_threshold=ms_slower_then,
|
||||||
|
@ -475,10 +469,10 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
if isinstance(graphics, StepCurve):
|
if isinstance(graphics, StepCurve):
|
||||||
|
|
||||||
r = self._src_r = Renderer(
|
r = self._src_r = Renderer(
|
||||||
flow=self,
|
viz=self,
|
||||||
fmtr=StepCurveFmtr(
|
fmtr=StepCurveFmtr(
|
||||||
shm=self.shm,
|
shm=self.shm,
|
||||||
flow=self,
|
viz=self,
|
||||||
_last_read=read,
|
_last_read=read,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -493,10 +487,10 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
if not r:
|
if not r:
|
||||||
# just using for ``.diff()`` atm..
|
# just using for ``.diff()`` atm..
|
||||||
r = self._src_r = Renderer(
|
r = self._src_r = Renderer(
|
||||||
flow=self,
|
viz=self,
|
||||||
fmtr=IncrementalFormatter(
|
fmtr=IncrementalFormatter(
|
||||||
shm=self.shm,
|
shm=self.shm,
|
||||||
flow=self,
|
viz=self,
|
||||||
_last_read=read,
|
_last_read=read,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -581,7 +575,7 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
path, data, reset = out
|
path, data, reset = out
|
||||||
|
|
||||||
# if self.yrange:
|
# if self.yrange:
|
||||||
# print(f'flow {self.name} yrange from m4: {self.yrange}')
|
# print(f'viz {self.name} yrange from m4: {self.yrange}')
|
||||||
|
|
||||||
# XXX: SUPER UGGGHHH... without this we get stale cache
|
# XXX: SUPER UGGGHHH... without this we get stale cache
|
||||||
# graphics that don't update until you downsampler again..
|
# graphics that don't update until you downsampler again..
|
||||||
|
@ -691,7 +685,7 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
|
|
||||||
class Renderer(msgspec.Struct):
|
class Renderer(msgspec.Struct):
|
||||||
|
|
||||||
flow: Flow
|
viz: Viz
|
||||||
fmtr: IncrementalFormatter
|
fmtr: IncrementalFormatter
|
||||||
|
|
||||||
# output graphics rendering, the main object
|
# output graphics rendering, the main object
|
||||||
|
@ -794,7 +788,7 @@ class Renderer(msgspec.Struct):
|
||||||
- blah blah blah (from notes)
|
- blah blah blah (from notes)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
# TODO: can the renderer just call ``Flow.read()`` directly?
|
# TODO: can the renderer just call ``Viz.read()`` directly?
|
||||||
# unpack latest source data read
|
# unpack latest source data read
|
||||||
fmtr = self.fmtr
|
fmtr = self.fmtr
|
||||||
|
|
||||||
|
@ -858,7 +852,7 @@ class Renderer(msgspec.Struct):
|
||||||
path is None
|
path is None
|
||||||
or should_redraw
|
or should_redraw
|
||||||
):
|
):
|
||||||
# print(f"{self.flow.name} -> REDRAWING BRUH")
|
# print(f"{self.viz.name} -> REDRAWING BRUH")
|
||||||
if new_sample_rate and showing_src_data:
|
if new_sample_rate and showing_src_data:
|
||||||
log.info(f'DEDOWN -> {array_key}')
|
log.info(f'DEDOWN -> {array_key}')
|
||||||
self._in_ds = False
|
self._in_ds = False
|
||||||
|
@ -870,8 +864,8 @@ class Renderer(msgspec.Struct):
|
||||||
y_1d,
|
y_1d,
|
||||||
uppx,
|
uppx,
|
||||||
)
|
)
|
||||||
self.flow.yrange = ymn, ymx
|
self.viz.yrange = ymn, ymx
|
||||||
# print(f'{self.flow.name} post ds: ymn, ymx: {ymn},{ymx}')
|
# print(f'{self.viz.name} post ds: ymn, ymx: {ymn},{ymx}')
|
||||||
|
|
||||||
reset = True
|
reset = True
|
||||||
profiler(f'FULL PATH downsample redraw={should_ds}')
|
profiler(f'FULL PATH downsample redraw={should_ds}')
|
||||||
|
@ -942,7 +936,7 @@ class Renderer(msgspec.Struct):
|
||||||
profiler('generated append qpath')
|
profiler('generated append qpath')
|
||||||
|
|
||||||
if use_fpath:
|
if use_fpath:
|
||||||
# print(f'{self.flow.name}: FAST PATH')
|
# print(f'{self.viz.name}: FAST PATH')
|
||||||
# an attempt at trying to make append-updates faster..
|
# an attempt at trying to make append-updates faster..
|
||||||
if fast_path is None:
|
if fast_path is None:
|
||||||
fast_path = append_path
|
fast_path = append_path
|
||||||
|
|
|
@ -289,7 +289,7 @@ async def run_fsp_ui(
|
||||||
# first UI update, usually from shm pushed history
|
# first UI update, usually from shm pushed history
|
||||||
update_fsp_chart(
|
update_fsp_chart(
|
||||||
chart,
|
chart,
|
||||||
chart._flows[array_key],
|
chart.get_viz(array_key),
|
||||||
name,
|
name,
|
||||||
array_key=array_key,
|
array_key=array_key,
|
||||||
)
|
)
|
||||||
|
@ -357,7 +357,7 @@ async def run_fsp_ui(
|
||||||
# last = time.time()
|
# last = time.time()
|
||||||
|
|
||||||
|
|
||||||
# TODO: maybe this should be our ``Flow`` type since it maps
|
# TODO: maybe this should be our ``Viz`` type since it maps
|
||||||
# one flume to the next? The machinery for task/actor mgmt should
|
# one flume to the next? The machinery for task/actor mgmt should
|
||||||
# be part of the instantiation API?
|
# be part of the instantiation API?
|
||||||
class FspAdmin:
|
class FspAdmin:
|
||||||
|
@ -386,7 +386,7 @@ class FspAdmin:
|
||||||
|
|
||||||
# TODO: make this a `.src_flume` and add
|
# TODO: make this a `.src_flume` and add
|
||||||
# a `dst_flume`?
|
# a `dst_flume`?
|
||||||
# (=> but then wouldn't this be the most basic `Flow`?)
|
# (=> but then wouldn't this be the most basic `Viz`?)
|
||||||
self.flume = flume
|
self.flume = flume
|
||||||
|
|
||||||
def rr_next_portal(self) -> tractor.Portal:
|
def rr_next_portal(self) -> tractor.Portal:
|
||||||
|
@ -694,7 +694,7 @@ async def open_vlm_displays(
|
||||||
|
|
||||||
) -> tuple[float, float]:
|
) -> tuple[float, float]:
|
||||||
'''
|
'''
|
||||||
Flows "group" maxmin loop; assumes all named flows
|
Viz "group" maxmin loop; assumes all named flows
|
||||||
are in the same co-domain and thus can be sorted
|
are in the same co-domain and thus can be sorted
|
||||||
as one set.
|
as one set.
|
||||||
|
|
||||||
|
@ -865,7 +865,7 @@ async def open_vlm_displays(
|
||||||
# specially store ref to shm for lookup in display loop
|
# specially store ref to shm for lookup in display loop
|
||||||
# since only a placeholder of `None` is entered in
|
# since only a placeholder of `None` is entered in
|
||||||
# ``.draw_curve()``.
|
# ``.draw_curve()``.
|
||||||
# flow = chart._flows[name]
|
# viz = chart._vizs[name]
|
||||||
assert flow.plot is pi
|
assert flow.plot is pi
|
||||||
|
|
||||||
chart_curves(
|
chart_curves(
|
||||||
|
@ -901,7 +901,7 @@ async def open_vlm_displays(
|
||||||
# liquidity events (well at least on low OHLC periods - 1s).
|
# liquidity events (well at least on low OHLC periods - 1s).
|
||||||
vlm_curve.hide()
|
vlm_curve.hide()
|
||||||
chart.removeItem(vlm_curve)
|
chart.removeItem(vlm_curve)
|
||||||
vflow = chart._flows['volume']
|
vflow = chart._vizs['volume']
|
||||||
vflow.render = False
|
vflow.render = False
|
||||||
|
|
||||||
# avoid range sorting on volume once disabled
|
# avoid range sorting on volume once disabled
|
||||||
|
|
|
@ -504,7 +504,7 @@ class ChartView(ViewBox):
|
||||||
|
|
||||||
# if (
|
# if (
|
||||||
# ev.delta() < 0
|
# ev.delta() < 0
|
||||||
# and vl >= len(chart._flows[chart.name].shm.array) + 666
|
# and vl >= len(chart._vizs[chart.name].shm.array) + 666
|
||||||
# ):
|
# ):
|
||||||
# log.debug("Min zoom bruh...")
|
# log.debug("Min zoom bruh...")
|
||||||
# return
|
# return
|
||||||
|
@ -821,7 +821,7 @@ class ChartView(ViewBox):
|
||||||
# XXX: only compute the mxmn range
|
# XXX: only compute the mxmn range
|
||||||
# if none is provided as input!
|
# if none is provided as input!
|
||||||
if not yrange:
|
if not yrange:
|
||||||
# flow = chart._flows[name]
|
# flow = chart._vizs[name]
|
||||||
yrange = self._maxmin()
|
yrange = self._maxmin()
|
||||||
|
|
||||||
if yrange is None:
|
if yrange is None:
|
||||||
|
@ -912,7 +912,7 @@ class ChartView(ViewBox):
|
||||||
graphics items which are our children.
|
graphics items which are our children.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
graphics = [f.graphics for f in self._chart._flows.values()]
|
graphics = [f.graphics for f in self._chart._vizs.values()]
|
||||||
if not graphics:
|
if not graphics:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ -948,7 +948,7 @@ class ChartView(ViewBox):
|
||||||
plots |= linked.subplots
|
plots |= linked.subplots
|
||||||
|
|
||||||
for chart_name, chart in plots.items():
|
for chart_name, chart in plots.items():
|
||||||
for name, flow in chart._flows.items():
|
for name, flow in chart._vizs.items():
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not flow.render
|
not flow.render
|
||||||
|
|
|
@ -43,7 +43,7 @@ from ._compression import (
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ._flows import (
|
from ._flows import (
|
||||||
Renderer,
|
Renderer,
|
||||||
Flow,
|
Viz,
|
||||||
)
|
)
|
||||||
from .._profile import Profiler
|
from .._profile import Profiler
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ class IncrementalFormatter(msgspec.Struct):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
shm: ShmArray
|
shm: ShmArray
|
||||||
flow: Flow
|
viz: Viz
|
||||||
|
|
||||||
# last read from shm (usually due to an update call)
|
# last read from shm (usually due to an update call)
|
||||||
_last_read: tuple[
|
_last_read: tuple[
|
||||||
|
@ -90,7 +90,7 @@ class IncrementalFormatter(msgspec.Struct):
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
msg = (
|
msg = (
|
||||||
f'{type(self)}: ->\n\n'
|
f'{type(self)}: ->\n\n'
|
||||||
f'fqsn={self.flow.name}\n'
|
f'fqsn={self.viz.name}\n'
|
||||||
f'shm_name={self.shm.token["shm_name"]}\n\n'
|
f'shm_name={self.shm.token["shm_name"]}\n\n'
|
||||||
|
|
||||||
f'last_vr={self._last_vr}\n'
|
f'last_vr={self._last_vr}\n'
|
||||||
|
@ -130,7 +130,7 @@ class IncrementalFormatter(msgspec.Struct):
|
||||||
last_in_view,
|
last_in_view,
|
||||||
) = self.last_read
|
) = self.last_read
|
||||||
|
|
||||||
# TODO: can the renderer just call ``Flow.read()`` directly?
|
# TODO: can the renderer just call ``Viz.read()`` directly?
|
||||||
# unpack latest source data read
|
# unpack latest source data read
|
||||||
(
|
(
|
||||||
xfirst,
|
xfirst,
|
||||||
|
@ -337,7 +337,7 @@ class IncrementalFormatter(msgspec.Struct):
|
||||||
if slice_to_inview:
|
if slice_to_inview:
|
||||||
view_changed = self._track_inview_range(view_range)
|
view_changed = self._track_inview_range(view_range)
|
||||||
array = in_view
|
array = in_view
|
||||||
profiler(f'{self.flow.name} view range slice {view_range}')
|
profiler(f'{self.viz.name} view range slice {view_range}')
|
||||||
|
|
||||||
hist = array[:slice_to_head]
|
hist = array[:slice_to_head]
|
||||||
|
|
||||||
|
@ -370,9 +370,9 @@ class IncrementalFormatter(msgspec.Struct):
|
||||||
# # assert (len(appended) - 1) == append_len
|
# # assert (len(appended) - 1) == append_len
|
||||||
# # assert len(appended) == append_len
|
# # assert len(appended) == append_len
|
||||||
# print(
|
# print(
|
||||||
# f'{self.flow.name} APPEND LEN: {append_len}\n'
|
# f'{self.viz.name} APPEND LEN: {append_len}\n'
|
||||||
# f'{self.flow.name} APPENDED: {appended}\n'
|
# f'{self.viz.name} APPENDED: {appended}\n'
|
||||||
# f'{self.flow.name} app_tres: {app_tres}\n'
|
# f'{self.viz.name} app_tres: {app_tres}\n'
|
||||||
# )
|
# )
|
||||||
|
|
||||||
# update the last "in view data range"
|
# update the last "in view data range"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
"""
|
|
||||||
Super hawt Qt UI components
|
|
||||||
"""
|
|
|
@ -1,67 +0,0 @@
|
||||||
import sys
|
|
||||||
|
|
||||||
from PySide2.QtCharts import QtCharts
|
|
||||||
from PySide2.QtWidgets import QApplication, QMainWindow
|
|
||||||
from PySide2.QtCore import Qt, QPointF
|
|
||||||
from PySide2 import QtGui
|
|
||||||
import qdarkstyle
|
|
||||||
|
|
||||||
data = ((1, 7380, 7520, 7380, 7510, 7324),
|
|
||||||
(2, 7520, 7580, 7410, 7440, 7372),
|
|
||||||
(3, 7440, 7650, 7310, 7520, 7434),
|
|
||||||
(4, 7450, 7640, 7450, 7550, 7480),
|
|
||||||
(5, 7510, 7590, 7460, 7490, 7502),
|
|
||||||
(6, 7500, 7590, 7480, 7560, 7512),
|
|
||||||
(7, 7560, 7830, 7540, 7800, 7584))
|
|
||||||
|
|
||||||
|
|
||||||
app = QApplication([])
|
|
||||||
# set dark stylesheet
|
|
||||||
# import pdb; pdb.set_trace()
|
|
||||||
app.setStyleSheet(qdarkstyle.load_stylesheet_pyside())
|
|
||||||
|
|
||||||
series = QtCharts.QCandlestickSeries()
|
|
||||||
series.setDecreasingColor(Qt.darkRed)
|
|
||||||
series.setIncreasingColor(Qt.darkGreen)
|
|
||||||
|
|
||||||
ma5 = QtCharts.QLineSeries() # 5-days average data line
|
|
||||||
tm = [] # stores str type data
|
|
||||||
|
|
||||||
# in a loop, series and ma5 append corresponding data
|
|
||||||
for num, o, h, l, c, m in data:
|
|
||||||
candle = QtCharts.QCandlestickSet(o, h, l, c)
|
|
||||||
series.append(candle)
|
|
||||||
ma5.append(QPointF(num, m))
|
|
||||||
tm.append(str(num))
|
|
||||||
|
|
||||||
pen = candle.pen()
|
|
||||||
# import pdb; pdb.set_trace()
|
|
||||||
|
|
||||||
chart = QtCharts.QChart()
|
|
||||||
|
|
||||||
# import pdb; pdb.set_trace()
|
|
||||||
series.setBodyOutlineVisible(False)
|
|
||||||
series.setCapsVisible(False)
|
|
||||||
# brush = QtGui.QBrush()
|
|
||||||
# brush.setColor(Qt.green)
|
|
||||||
# series.setBrush(brush)
|
|
||||||
chart.addSeries(series) # candle
|
|
||||||
chart.addSeries(ma5) # ma5 line
|
|
||||||
|
|
||||||
chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations)
|
|
||||||
chart.createDefaultAxes()
|
|
||||||
chart.legend().hide()
|
|
||||||
|
|
||||||
chart.axisX(series).setCategories(tm)
|
|
||||||
chart.axisX(ma5).setVisible(False)
|
|
||||||
|
|
||||||
view = QtCharts.QChartView(chart)
|
|
||||||
view.chart().setTheme(QtCharts.QChart.ChartTheme.ChartThemeDark)
|
|
||||||
view.setRubberBand(QtCharts.QChartView.HorizontalRubberBand)
|
|
||||||
# chartview.chart().setTheme(QtCharts.QChart.ChartTheme.ChartThemeBlueCerulean)
|
|
||||||
|
|
||||||
ui = QMainWindow()
|
|
||||||
# ui.setGeometry(50, 50, 500, 300)
|
|
||||||
ui.setCentralWidget(view)
|
|
||||||
ui.show()
|
|
||||||
sys.exit(app.exec_())
|
|
Loading…
Reference in New Issue