Only draw mx/mn line for last uppx's worth of datums

When using m4, we downsample to the max and min of each
pixel-column's-worth of data thus preserving range / dispersion details
whilst not drawing more graphics then can be displayed by the available
amount of horizontal pixels.

Take and apply this exact same concept to the "last datum" graphics
elements for any `Flow` that is reported as being in a downsampled
state:

- take the xy output from the `Curve.draw_last_datum()`,
- slice out all data that fits in the last pixel's worth of x-range
  by using the uppx,
- compute the highest and lowest value from that data,
- draw a singe line segment which spans this yrange thus creating
  a simple vertical set of pixels which are "filled in" and show the
  entire y-range for the most recent data "contained with that pixel".
incremental_update_paths
Tyler Goodlet 2022-06-03 16:45:53 -04:00
parent e5f96391e3
commit 99965e7601
2 changed files with 53 additions and 7 deletions

View File

@ -654,6 +654,19 @@ def graphics_update_cycle(
# run synchronous update on all linked flows # run synchronous update on all linked flows
for curve_name, flow in chart._flows.items(): for curve_name, flow in chart._flows.items():
if (
not (do_rt_update or do_append)
and liv
# even if we're downsampled bigly
# draw the last datum in the final
# px column to give the user the mx/mn
# range of that set.
):
# always update the last datum-element
# graphic for all flows
flow.draw_last(array_key=curve_name)
# TODO: should the "main" (aka source) flow be special? # TODO: should the "main" (aka source) flow be special?
if curve_name == chart.data_key: if curve_name == chart.data_key:
continue continue

View File

@ -34,6 +34,7 @@ import numpy as np
from numpy.lib import recfunctions as rfn from numpy.lib import recfunctions as rfn
import pyqtgraph as pg import pyqtgraph as pg
from PyQt5.QtGui import QPainterPath from PyQt5.QtGui import QPainterPath
from PyQt5.QtCore import QLineF
from ..data._sharedmem import ( from ..data._sharedmem import (
ShmArray, ShmArray,
@ -335,12 +336,6 @@ class Flow(msgspec.Struct): # , frozen=True):
graphics: Curve graphics: Curve
_shm: ShmArray _shm: ShmArray
draw_last: 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
@ -594,7 +589,6 @@ class Flow(msgspec.Struct): # , frozen=True):
# TODO: append logic inside ``.render()`` isn't # TODO: append logic inside ``.render()`` isn't
# correct yet for step curves.. remove this to see it. # correct yet for step curves.. remove this to see it.
should_redraw = True should_redraw = True
# draw_last = True
slice_to_head = -2 slice_to_head = -2
# downsampling incremental state checking # downsampling incremental state checking
@ -690,8 +684,47 @@ class Flow(msgspec.Struct): # , frozen=True):
graphics.update() graphics.update()
profiler('.update()') profiler('.update()')
# track downsampled state
self._in_ds = r._in_ds
return graphics return graphics
def draw_last(
self,
array_key: Optional[str] = None,
) -> None:
# shm read and slice to view
(
xfirst, xlast, src_array,
ivl, ivr, in_view,
) = self.read()
g = self.graphics
array_key = array_key or self.name
x, y = g.draw_last_datum(
g.path,
src_array,
src_array,
False, # never reset path
array_key,
)
if self._in_ds:
# we only care about the last pixel's
# worth of data since that's all the screen
# can represent on the last column where
# the most recent datum is being drawn.
uppx = self._last_uppx
y = y[-uppx:]
ymn, ymx = y.min(), y.max()
# print(f'drawing uppx={uppx} mxmn line: {ymn}, {ymx}')
g._last_line = QLineF(
x[-2], ymn,
x[-1], ymx,
)
def by_index_and_key( def by_index_and_key(
renderer: Renderer, renderer: Renderer,