Factor all per graphic `.draw_last()` methods into closures
parent
8f1faf97ee
commit
57acc3bd29
|
@ -160,23 +160,6 @@ class FastAppendCurve(pg.GraphicsObject):
|
||||||
QLineF(lbar, 0, rbar, 0)
|
QLineF(lbar, 0, rbar, 0)
|
||||||
).length()
|
).length()
|
||||||
|
|
||||||
def draw_last(
|
|
||||||
self,
|
|
||||||
x: np.ndarray,
|
|
||||||
y: np.ndarray,
|
|
||||||
|
|
||||||
) -> None:
|
|
||||||
x_last = x[-1]
|
|
||||||
y_last = y[-1]
|
|
||||||
|
|
||||||
# draw the "current" step graphic segment so it lines up with
|
|
||||||
# the "middle" of the current (OHLC) sample.
|
|
||||||
self._last_line = QLineF(
|
|
||||||
x[-2], y[-2],
|
|
||||||
x_last, y_last
|
|
||||||
)
|
|
||||||
# self._last_w = x_last - x[-2]
|
|
||||||
|
|
||||||
# XXX: lol brutal, the internals of `CurvePoint` (inherited by
|
# XXX: lol brutal, the internals of `CurvePoint` (inherited by
|
||||||
# our `LineDot`) required ``.getData()`` to work..
|
# our `LineDot`) required ``.getData()`` to work..
|
||||||
def getData(self):
|
def getData(self):
|
||||||
|
|
|
@ -23,7 +23,6 @@ incremental update.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from functools import partial
|
|
||||||
from typing import (
|
from typing import (
|
||||||
Optional,
|
Optional,
|
||||||
Callable,
|
Callable,
|
||||||
|
@ -58,6 +57,7 @@ from ._pathops import (
|
||||||
)
|
)
|
||||||
from ._ohlc import (
|
from ._ohlc import (
|
||||||
BarItems,
|
BarItems,
|
||||||
|
bar_from_ohlc_row,
|
||||||
)
|
)
|
||||||
from ._curve import (
|
from ._curve import (
|
||||||
FastAppendCurve,
|
FastAppendCurve,
|
||||||
|
@ -245,18 +245,73 @@ def render_baritems(
|
||||||
bars.update()
|
bars.update()
|
||||||
|
|
||||||
draw_last = False
|
draw_last = False
|
||||||
lasts = self.shm.array[-2:]
|
|
||||||
last = lasts[-1]
|
|
||||||
|
|
||||||
if should_line:
|
if should_line:
|
||||||
def draw_last():
|
|
||||||
|
def draw_last_flattened_ohlc_line(
|
||||||
|
graphics: pg.GraphicsObject,
|
||||||
|
path: QPainterPath,
|
||||||
|
src_data: np.ndarray,
|
||||||
|
render_data: np.ndarray,
|
||||||
|
reset: bool,
|
||||||
|
) -> None:
|
||||||
|
lasts = src_data[-2:]
|
||||||
x, y = lasts['index'], lasts['close']
|
x, y = lasts['index'], lasts['close']
|
||||||
curve.draw_last(x, y)
|
|
||||||
|
# draw the "current" step graphic segment so it
|
||||||
|
# lines up with the "middle" of the current
|
||||||
|
# (OHLC) sample.
|
||||||
|
graphics._last_line = QLineF(
|
||||||
|
x[-2], y[-2],
|
||||||
|
x[-1], y[-1]
|
||||||
|
)
|
||||||
|
|
||||||
|
draw_last = draw_last_flattened_ohlc_line
|
||||||
|
|
||||||
else:
|
else:
|
||||||
draw_last = partial(
|
def draw_last_ohlc_bar(
|
||||||
bars.draw_last,
|
graphics: pg.GraphicsObject,
|
||||||
last,
|
path: QPainterPath,
|
||||||
)
|
src_data: np.ndarray,
|
||||||
|
render_data: np.ndarray,
|
||||||
|
reset: bool,
|
||||||
|
) -> None:
|
||||||
|
last = src_data[-1]
|
||||||
|
# generate new lines objects for updatable "current bar"
|
||||||
|
graphics._last_bar_lines = bar_from_ohlc_row(last, graphics.w)
|
||||||
|
|
||||||
|
# last bar update
|
||||||
|
i, o, h, l, last, v = last[
|
||||||
|
['index', 'open', 'high', 'low', 'close', 'volume']
|
||||||
|
]
|
||||||
|
# assert i == graphics.start_index - 1
|
||||||
|
# assert i == last_index
|
||||||
|
body, larm, rarm = graphics._last_bar_lines
|
||||||
|
|
||||||
|
# XXX: is there a faster way to modify this?
|
||||||
|
rarm.setLine(rarm.x1(), last, rarm.x2(), last)
|
||||||
|
|
||||||
|
# writer is responsible for changing open on "first" volume of bar
|
||||||
|
larm.setLine(larm.x1(), o, larm.x2(), o)
|
||||||
|
|
||||||
|
if l != h: # noqa
|
||||||
|
|
||||||
|
if body is None:
|
||||||
|
body = graphics._last_bar_lines[0] = QLineF(i, l, i, h)
|
||||||
|
else:
|
||||||
|
# update body
|
||||||
|
body.setLine(i, l, i, h)
|
||||||
|
|
||||||
|
# XXX: pretty sure this is causing an issue where the
|
||||||
|
# bar has a large upward move right before the next
|
||||||
|
# sample and the body is getting set to None since the
|
||||||
|
# next bar is flat but the shm array index update wasn't
|
||||||
|
# read by the time this code runs. Iow we're doing this
|
||||||
|
# removal of the body for a bar index that is now out of
|
||||||
|
# date / from some previous sample. It's weird though
|
||||||
|
# because i've seen it do this to bars i - 3 back?
|
||||||
|
|
||||||
|
draw_last = draw_last_ohlc_bar
|
||||||
|
|
||||||
return (
|
return (
|
||||||
graphics,
|
graphics,
|
||||||
|
@ -355,6 +410,12 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
graphics: pg.GraphicsObject
|
graphics: pg.GraphicsObject
|
||||||
_shm: ShmArray
|
_shm: ShmArray
|
||||||
|
|
||||||
|
draw_last_datum: Optional[
|
||||||
|
Callable[
|
||||||
|
[np.ndarray, str],
|
||||||
|
tuple[np.ndarray]
|
||||||
|
]
|
||||||
|
] = None
|
||||||
is_ohlc: bool = False
|
is_ohlc: bool = False
|
||||||
render: bool = True # toggle for display loop
|
render: bool = True # toggle for display loop
|
||||||
|
|
||||||
|
@ -543,7 +604,7 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
)
|
)
|
||||||
# shm read and slice to view
|
# shm read and slice to view
|
||||||
read = (
|
read = (
|
||||||
xfirst, xlast, array,
|
xfirst, xlast, src_array,
|
||||||
ivl, ivr, in_view,
|
ivl, ivr, in_view,
|
||||||
) = self.read()
|
) = self.read()
|
||||||
|
|
||||||
|
@ -618,14 +679,6 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
# corrent yet for step curves.. remove this to see it.
|
# corrent yet for step curves.. remove this to see it.
|
||||||
should_redraw = True
|
should_redraw = True
|
||||||
|
|
||||||
# TODO: remove this and instead place all step curve
|
|
||||||
# updating into pre-path data render callbacks.
|
|
||||||
# full input data
|
|
||||||
x = array['index']
|
|
||||||
y = array[array_key]
|
|
||||||
x_last = x[-1]
|
|
||||||
y_last = y[-1]
|
|
||||||
|
|
||||||
draw_last = True
|
draw_last = True
|
||||||
|
|
||||||
# downsampling incremental state checking
|
# downsampling incremental state checking
|
||||||
|
@ -698,34 +751,74 @@ class Flow(msgspec.Struct): # , frozen=True):
|
||||||
graphics.fast_path = r.fast_path
|
graphics.fast_path = r.fast_path
|
||||||
|
|
||||||
if draw_last and not bars:
|
if draw_last and not bars:
|
||||||
# default line draw last call
|
|
||||||
if not step_mode:
|
if not step_mode:
|
||||||
with graphics.reset_cache():
|
|
||||||
x = data['index']
|
def draw_last_line(
|
||||||
y = data[array_key]
|
graphics: pg.GraphicsObject,
|
||||||
graphics.draw_last(x, y)
|
path: QPainterPath,
|
||||||
|
src_data: np.ndarray,
|
||||||
|
render_data: np.ndarray,
|
||||||
|
reset: bool,
|
||||||
|
|
||||||
|
) -> None:
|
||||||
|
# default line draw last call
|
||||||
|
with graphics.reset_cache():
|
||||||
|
x = render_data['index']
|
||||||
|
y = render_data[array_key]
|
||||||
|
x_last = x[-1]
|
||||||
|
y_last = y[-1]
|
||||||
|
|
||||||
|
# draw the "current" step graphic segment so it
|
||||||
|
# lines up with the "middle" of the current
|
||||||
|
# (OHLC) sample.
|
||||||
|
graphics._last_line = QLineF(
|
||||||
|
x[-2], y[-2],
|
||||||
|
x_last, y_last
|
||||||
|
)
|
||||||
|
|
||||||
|
draw_last_line(graphics, path, src_array, data, reset)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
w = 0.5
|
|
||||||
# lol, commenting this makes step curves
|
|
||||||
# all "black" for me :eyeroll:..
|
|
||||||
graphics._last_line = QLineF(
|
|
||||||
x_last - w, 0,
|
|
||||||
x_last + w, 0,
|
|
||||||
)
|
|
||||||
graphics._last_step_rect = QRectF(
|
|
||||||
x_last - w, 0,
|
|
||||||
x_last + w, y_last,
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: does this actuallly help us in any way (prolly should
|
def draw_last_step(
|
||||||
# look at the source / ask ogi). I think it avoid artifacts on
|
graphics: pg.GraphicsObject,
|
||||||
# wheel-scroll downsampling curve updates?
|
path: QPainterPath,
|
||||||
graphics.update()
|
src_data: np.ndarray,
|
||||||
profiler('.prepareGeometryChange()')
|
render_data: np.ndarray,
|
||||||
|
reset: bool,
|
||||||
|
|
||||||
|
) -> None:
|
||||||
|
w = 0.5
|
||||||
|
# TODO: remove this and instead place all step curve
|
||||||
|
# updating into pre-path data render callbacks.
|
||||||
|
# full input data
|
||||||
|
x = src_array['index']
|
||||||
|
y = src_array[array_key]
|
||||||
|
x_last = x[-1]
|
||||||
|
y_last = y[-1]
|
||||||
|
|
||||||
|
# lol, commenting this makes step curves
|
||||||
|
# all "black" for me :eyeroll:..
|
||||||
|
graphics._last_line = QLineF(
|
||||||
|
x_last - w, 0,
|
||||||
|
x_last + w, 0,
|
||||||
|
)
|
||||||
|
graphics._last_step_rect = QRectF(
|
||||||
|
x_last - w, 0,
|
||||||
|
x_last + w, y_last,
|
||||||
|
)
|
||||||
|
|
||||||
|
draw_last_step(graphics, path, src_array, data, reset)
|
||||||
|
|
||||||
|
# TODO: does this actuallly help us in any way (prolly should
|
||||||
|
# look at the source / ask ogi). I think it avoid artifacts on
|
||||||
|
# wheel-scroll downsampling curve updates?
|
||||||
|
graphics.update()
|
||||||
|
profiler('.prepareGeometryChange()')
|
||||||
|
|
||||||
elif bars and draw_last:
|
elif bars and draw_last:
|
||||||
draw_last()
|
draw_last(graphics, path, src_array, data, reset)
|
||||||
graphics.update()
|
graphics.update()
|
||||||
profiler('.update()')
|
profiler('.update()')
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,6 @@ from .._profile import pg_profile_enabled, ms_slower_then
|
||||||
from ._style import hcolor
|
from ._style import hcolor
|
||||||
from ..log import get_logger
|
from ..log import get_logger
|
||||||
from ._curve import FastAppendCurve
|
from ._curve import FastAppendCurve
|
||||||
from ._compression import ohlc_flatten
|
|
||||||
from ._pathops import gen_ohlc_qpath
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ._chart import LinkedSplits
|
from ._chart import LinkedSplits
|
||||||
|
@ -148,44 +146,6 @@ class BarItems(pg.GraphicsObject):
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def draw_last(
|
|
||||||
self,
|
|
||||||
last: np.ndarray,
|
|
||||||
|
|
||||||
) -> None:
|
|
||||||
# generate new lines objects for updatable "current bar"
|
|
||||||
self._last_bar_lines = bar_from_ohlc_row(last, self.w)
|
|
||||||
|
|
||||||
# last bar update
|
|
||||||
i, o, h, l, last, v = last[
|
|
||||||
['index', 'open', 'high', 'low', 'close', 'volume']
|
|
||||||
]
|
|
||||||
# assert i == self.start_index - 1
|
|
||||||
# assert i == last_index
|
|
||||||
body, larm, rarm = self._last_bar_lines
|
|
||||||
|
|
||||||
# XXX: is there a faster way to modify this?
|
|
||||||
rarm.setLine(rarm.x1(), last, rarm.x2(), last)
|
|
||||||
|
|
||||||
# writer is responsible for changing open on "first" volume of bar
|
|
||||||
larm.setLine(larm.x1(), o, larm.x2(), o)
|
|
||||||
|
|
||||||
if l != h: # noqa
|
|
||||||
|
|
||||||
if body is None:
|
|
||||||
body = self._last_bar_lines[0] = QLineF(i, l, i, h)
|
|
||||||
else:
|
|
||||||
# update body
|
|
||||||
body.setLine(i, l, i, h)
|
|
||||||
|
|
||||||
# XXX: pretty sure this is causing an issue where the bar has
|
|
||||||
# a large upward move right before the next sample and the body
|
|
||||||
# is getting set to None since the next bar is flat but the shm
|
|
||||||
# array index update wasn't read by the time this code runs. Iow
|
|
||||||
# we're doing this removal of the body for a bar index that is
|
|
||||||
# now out of date / from some previous sample. It's weird
|
|
||||||
# though because i've seen it do this to bars i - 3 back?
|
|
||||||
|
|
||||||
def boundingRect(self):
|
def boundingRect(self):
|
||||||
# Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect
|
# Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue