Use `Viz.draw_last()` inside `.update_graphics()`
In an effort to ensure uniform and uppx-optimized last datum graphics updates call this method directly instead of the equivalent graphics object thus ensuring we only update the last pixel column according with the appropriate max/min computed from the last uppx's worth of data. Fixes / improvements to enable `.draw_last()` usage include, - change `Viz._render_table` -> `._alt_r: tuple[Renderer, pg.GraphicsItem] | None` which holds an alternative (usually downsampled) render and graphics obj. - extend the `.draw_last()` signature to include: - `last_read` to allow passing in the already read data from `.update_graphics()`, if it isn't passed then a manual read is done internally. - `reset_cache: bool` which is passed through to the graphics obj. - use the new `Formatter.flat_index_ratio: float` when indexing into xy 1d data to compute the max/min for that px column. Other, - drop `bars_range` input from `maxmin()` since it's unused.multichartz
parent
b762cf0456
commit
65434e2e67
|
@ -132,9 +132,9 @@ def render_baritems(
|
||||||
|
|
||||||
# baseline "line" downsampled OHLC curve that should
|
# baseline "line" downsampled OHLC curve that should
|
||||||
# kick on only when we reach a certain uppx threshold.
|
# kick on only when we reach a certain uppx threshold.
|
||||||
self._render_table = (ds_curve_r, curve)
|
self._alt_r = (ds_curve_r, curve)
|
||||||
|
|
||||||
ds_r, curve = self._render_table
|
ds_r, curve = self._alt_r
|
||||||
|
|
||||||
# print(
|
# print(
|
||||||
# f'r: {r.fmtr.xy_slice}\n'
|
# f'r: {r.fmtr.xy_slice}\n'
|
||||||
|
@ -270,11 +270,11 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
_index_step: float | None = None
|
_index_step: float | None = None
|
||||||
|
|
||||||
# map from uppx -> (downsampled data, incremental graphics)
|
# map from uppx -> (downsampled data, incremental graphics)
|
||||||
_src_r: Optional[Renderer] = None
|
_src_r: Renderer | None = None
|
||||||
_render_table: dict[
|
_alt_r: tuple[
|
||||||
Optional[int],
|
Renderer,
|
||||||
tuple[Renderer, pg.GraphicsItem],
|
pg.GraphicsItem
|
||||||
] = (None, None)
|
] | None = None
|
||||||
|
|
||||||
# cache of y-range values per x-range input.
|
# cache of y-range values per x-range input.
|
||||||
_mxmns: dict[
|
_mxmns: dict[
|
||||||
|
@ -329,11 +329,6 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
def maxmin(
|
def maxmin(
|
||||||
self,
|
self,
|
||||||
|
|
||||||
# TODO: drop this right?
|
|
||||||
bars_range: Optional[tuple[
|
|
||||||
int, int, int, int, int, int
|
|
||||||
]] = None,
|
|
||||||
|
|
||||||
x_range: slice | tuple[int, int] | None = None,
|
x_range: slice | tuple[int, int] | None = None,
|
||||||
use_caching: bool = True,
|
use_caching: bool = True,
|
||||||
|
|
||||||
|
@ -366,11 +361,7 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
rbar,
|
rbar,
|
||||||
_,
|
_,
|
||||||
r,
|
r,
|
||||||
) = (
|
) = self.datums_range()
|
||||||
# TODO: drop this yah?
|
|
||||||
bars_range
|
|
||||||
or self.datums_range()
|
|
||||||
)
|
|
||||||
|
|
||||||
profiler(f'{self.name} got bars range')
|
profiler(f'{self.name} got bars range')
|
||||||
x_range = lbar, rbar
|
x_range = lbar, rbar
|
||||||
|
@ -816,18 +807,29 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
with graphics.reset_cache():
|
with graphics.reset_cache():
|
||||||
graphics.path = r.path
|
graphics.path = r.path
|
||||||
graphics.fast_path = r.fast_path
|
graphics.fast_path = r.fast_path
|
||||||
|
|
||||||
|
self.draw_last(
|
||||||
|
array_key=array_key,
|
||||||
|
last_read=read,
|
||||||
|
reset_cache=reset_cache,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# assign output paths to graphicis obj
|
# assign output paths to graphicis obj
|
||||||
graphics.path = r.path
|
graphics.path = r.path
|
||||||
graphics.fast_path = r.fast_path
|
graphics.fast_path = r.fast_path
|
||||||
|
|
||||||
graphics.draw_last_datum(
|
self.draw_last(
|
||||||
path,
|
array_key=array_key,
|
||||||
src_array,
|
last_read=read,
|
||||||
reset_cache,
|
reset_cache=reset_cache,
|
||||||
array_key,
|
|
||||||
index_field=self.index_field,
|
|
||||||
)
|
)
|
||||||
|
# graphics.draw_last_datum(
|
||||||
|
# path,
|
||||||
|
# src_array,
|
||||||
|
# reset_cache,
|
||||||
|
# array_key,
|
||||||
|
# index_field=self.index_field,
|
||||||
|
# )
|
||||||
graphics.update()
|
graphics.update()
|
||||||
profiler('.update()')
|
profiler('.update()')
|
||||||
|
|
||||||
|
@ -845,7 +847,9 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
|
|
||||||
def draw_last(
|
def draw_last(
|
||||||
self,
|
self,
|
||||||
array_key: Optional[str] = None,
|
array_key: str | None = None,
|
||||||
|
last_read: tuple | None = None,
|
||||||
|
reset_cache: bool = False,
|
||||||
only_last_uppx: bool = False,
|
only_last_uppx: bool = False,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -854,17 +858,11 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
(
|
(
|
||||||
xfirst, xlast, src_array,
|
xfirst, xlast, src_array,
|
||||||
ivl, ivr, in_view,
|
ivl, ivr, in_view,
|
||||||
) = self.read()
|
) = last_read or self.read()
|
||||||
|
|
||||||
g = self.graphics
|
|
||||||
array_key = array_key or self.name
|
array_key = array_key or self.name
|
||||||
x, y = g.draw_last_datum(
|
|
||||||
g.path,
|
gfx = self.graphics
|
||||||
src_array,
|
|
||||||
False, # never reset path
|
|
||||||
array_key,
|
|
||||||
self.index_field,
|
|
||||||
)
|
|
||||||
|
|
||||||
# the renderer is downsampling we choose
|
# the renderer is downsampling we choose
|
||||||
# to always try and update a single (interpolating)
|
# to always try and update a single (interpolating)
|
||||||
|
@ -874,19 +872,28 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
# worth of data since that's all the screen
|
# worth of data since that's all the screen
|
||||||
# can represent on the last column where
|
# can represent on the last column where
|
||||||
# the most recent datum is being drawn.
|
# the most recent datum is being drawn.
|
||||||
|
uppx = ceil(self._last_uppx)
|
||||||
if (
|
if (
|
||||||
self._in_ds
|
(self._in_ds or only_last_uppx)
|
||||||
or only_last_uppx
|
and uppx > 0
|
||||||
):
|
):
|
||||||
dsg = self.ds_graphics or self.graphics
|
alt_renderer = self._alt_r
|
||||||
|
if alt_renderer:
|
||||||
|
renderer, gfx = alt_renderer
|
||||||
|
fmtr = renderer.fmtr
|
||||||
|
x = fmtr.x_1d
|
||||||
|
y = fmtr.y_1d
|
||||||
|
else:
|
||||||
|
renderer = self._src_r
|
||||||
|
fmtr = renderer.fmtr
|
||||||
|
x = fmtr.x_1d
|
||||||
|
y = fmtr.y_1d
|
||||||
|
|
||||||
|
if alt_renderer:
|
||||||
|
uppx *= fmtr.flat_index_ratio
|
||||||
|
|
||||||
# XXX: pretty sure we don't need this?
|
|
||||||
# if isinstance(g, Curve):
|
|
||||||
# with dsg.reset_cache():
|
|
||||||
uppx = round(self._last_uppx)
|
|
||||||
y = y[-uppx:]
|
y = y[-uppx:]
|
||||||
ymn, ymx = y.min(), y.max()
|
ymn, ymx = y.min(), y.max()
|
||||||
# print(f'drawing uppx={uppx} mxmn line: {ymn}, {ymx}')
|
|
||||||
try:
|
try:
|
||||||
iuppx = x[-uppx]
|
iuppx = x[-uppx]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -894,16 +901,32 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
# datum index.
|
# datum index.
|
||||||
iuppx = x[0]
|
iuppx = x[0]
|
||||||
|
|
||||||
dsg._last_line = QLineF(
|
gfx._last_line = QLineF(
|
||||||
iuppx, ymn,
|
iuppx, ymn,
|
||||||
x[-1], ymx,
|
x[-1], ymx,
|
||||||
)
|
)
|
||||||
# print(f'updating DS curve {self.name}')
|
# if self.is_ohlc:
|
||||||
dsg.update()
|
# times = self.shm.array['time']
|
||||||
|
# time_step = times[-1] - times[-2]
|
||||||
|
# # if 'hist' in self.shm.token['shm_name']
|
||||||
|
# # if self.index_step() == 1:
|
||||||
|
# # breakpoint()
|
||||||
|
# print(
|
||||||
|
# f'updating DS curve {self.name}@{time_step}s\n'
|
||||||
|
# f'drawing uppx={uppx} mxmn line: {ymn}, {ymx}'
|
||||||
|
# )
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
x, y = gfx.draw_last_datum(
|
||||||
|
gfx.path,
|
||||||
|
src_array,
|
||||||
|
reset_cache, # never reset path
|
||||||
|
array_key,
|
||||||
|
self.index_field,
|
||||||
|
)
|
||||||
# print(f'updating NOT DS curve {self.name}')
|
# print(f'updating NOT DS curve {self.name}')
|
||||||
g.update()
|
|
||||||
|
gfx.update()
|
||||||
|
|
||||||
def default_view(
|
def default_view(
|
||||||
self,
|
self,
|
||||||
|
@ -1029,7 +1052,7 @@ class Viz(msgspec.Struct): # , frozen=True):
|
||||||
)
|
)
|
||||||
|
|
||||||
if do_ds:
|
if do_ds:
|
||||||
# view.interaction_graphics_update_cycle()
|
# view.interaction_graphics_cycle()
|
||||||
view.maybe_downsample_graphics()
|
view.maybe_downsample_graphics()
|
||||||
view._set_yrange()
|
view._set_yrange()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue