From 99965e7601a2e5a7522e7a7086128ed29d1c122f Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Fri, 3 Jun 2022 16:45:53 -0400 Subject: [PATCH] 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". --- piker/ui/_display.py | 13 ++++++++++++ piker/ui/_flows.py | 47 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/piker/ui/_display.py b/piker/ui/_display.py index e33c2c74..415827fb 100644 --- a/piker/ui/_display.py +++ b/piker/ui/_display.py @@ -654,6 +654,19 @@ def graphics_update_cycle( # run synchronous update on all linked flows 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? if curve_name == chart.data_key: continue diff --git a/piker/ui/_flows.py b/piker/ui/_flows.py index 7960d649..01bbbece 100644 --- a/piker/ui/_flows.py +++ b/piker/ui/_flows.py @@ -34,6 +34,7 @@ import numpy as np from numpy.lib import recfunctions as rfn import pyqtgraph as pg from PyQt5.QtGui import QPainterPath +from PyQt5.QtCore import QLineF from ..data._sharedmem import ( ShmArray, @@ -335,12 +336,6 @@ class Flow(msgspec.Struct): # , frozen=True): graphics: Curve _shm: ShmArray - draw_last: Optional[ - Callable[ - [np.ndarray, str], - tuple[np.ndarray] - ] - ] = None is_ohlc: bool = False render: bool = True # toggle for display loop @@ -594,7 +589,6 @@ class Flow(msgspec.Struct): # , frozen=True): # TODO: append logic inside ``.render()`` isn't # correct yet for step curves.. remove this to see it. should_redraw = True - # draw_last = True slice_to_head = -2 # downsampling incremental state checking @@ -690,8 +684,47 @@ class Flow(msgspec.Struct): # , frozen=True): graphics.update() profiler('.update()') + # track downsampled state + self._in_ds = r._in_ds + 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( renderer: Renderer,