piker/piker/ui/_render.py

343 lines
10 KiB
Python
Raw Normal View History

Add new `ui._flows` module This begins the removal of data processing / analysis methods from the chart widget and instead moving them to our new `Flow` API (in the new module introduce here) and delegating the old chart methods to the respective internal flow. Most importantly is no longer storing the "last read" of an array from shm in an internal chart table (was `._arrays`) and instead the `ShmArray` instance is passed as input and stored in the `Flow` instance. This greatly simplifies lookup logic such that the display loop now doesn't have to worry about reading shm, it can be done by internal graphics logic as desired. Generally speaking, all previous `._arrays`/`._graphics` lookups are now delegated to the entries in the chart's `._flows` table. The new `Flow` methods are generally better factored and provide more detailed output regarding data-stream <-> graphics inter-relations for the future purpose of allowing much more efficient update calls in the display loop as well as supporting low latency interaction UX. The concept here is that we're introducing an intermediary layer that ties together graphics and real-time data flows such that widget code is oriented around plot layout and the flow apis are oriented around real-time low latency updates and providing an efficient high level metric layer for the UX. The summary api transition is something like: - `update_graphics_from_array()` -> `.update_graphics_from_flow()` - `.bars_range()` -> `Flow.datums_range()` - `.bars_range()` -> `Flow.datums_range()`
2022-04-14 13:38:25 +00:00
# piker: trading gear for hackers
# Copyright (C) Tyler Goodlet (in stewardship for pikers)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
High level streaming graphics primitives.
This is an intermediate layer which associates real-time low latency
2022-12-14 17:05:35 +00:00
graphics primitives with underlying stream/flow related data structures
for fast incremental update.
Add new `ui._flows` module This begins the removal of data processing / analysis methods from the chart widget and instead moving them to our new `Flow` API (in the new module introduce here) and delegating the old chart methods to the respective internal flow. Most importantly is no longer storing the "last read" of an array from shm in an internal chart table (was `._arrays`) and instead the `ShmArray` instance is passed as input and stored in the `Flow` instance. This greatly simplifies lookup logic such that the display loop now doesn't have to worry about reading shm, it can be done by internal graphics logic as desired. Generally speaking, all previous `._arrays`/`._graphics` lookups are now delegated to the entries in the chart's `._flows` table. The new `Flow` methods are generally better factored and provide more detailed output regarding data-stream <-> graphics inter-relations for the future purpose of allowing much more efficient update calls in the display loop as well as supporting low latency interaction UX. The concept here is that we're introducing an intermediary layer that ties together graphics and real-time data flows such that widget code is oriented around plot layout and the flow apis are oriented around real-time low latency updates and providing an efficient high level metric layer for the UX. The summary api transition is something like: - `update_graphics_from_array()` -> `.update_graphics_from_flow()` - `.bars_range()` -> `Flow.datums_range()` - `.bars_range()` -> `Flow.datums_range()`
2022-04-14 13:38:25 +00:00
'''
2022-04-16 19:22:11 +00:00
from __future__ import annotations
Add new `ui._flows` module This begins the removal of data processing / analysis methods from the chart widget and instead moving them to our new `Flow` API (in the new module introduce here) and delegating the old chart methods to the respective internal flow. Most importantly is no longer storing the "last read" of an array from shm in an internal chart table (was `._arrays`) and instead the `ShmArray` instance is passed as input and stored in the `Flow` instance. This greatly simplifies lookup logic such that the display loop now doesn't have to worry about reading shm, it can be done by internal graphics logic as desired. Generally speaking, all previous `._arrays`/`._graphics` lookups are now delegated to the entries in the chart's `._flows` table. The new `Flow` methods are generally better factored and provide more detailed output regarding data-stream <-> graphics inter-relations for the future purpose of allowing much more efficient update calls in the display loop as well as supporting low latency interaction UX. The concept here is that we're introducing an intermediary layer that ties together graphics and real-time data flows such that widget code is oriented around plot layout and the flow apis are oriented around real-time low latency updates and providing an efficient high level metric layer for the UX. The summary api transition is something like: - `update_graphics_from_array()` -> `.update_graphics_from_flow()` - `.bars_range()` -> `Flow.datums_range()` - `.bars_range()` -> `Flow.datums_range()`
2022-04-14 13:38:25 +00:00
from typing import (
TYPE_CHECKING,
Add new `ui._flows` module This begins the removal of data processing / analysis methods from the chart widget and instead moving them to our new `Flow` API (in the new module introduce here) and delegating the old chart methods to the respective internal flow. Most importantly is no longer storing the "last read" of an array from shm in an internal chart table (was `._arrays`) and instead the `ShmArray` instance is passed as input and stored in the `Flow` instance. This greatly simplifies lookup logic such that the display loop now doesn't have to worry about reading shm, it can be done by internal graphics logic as desired. Generally speaking, all previous `._arrays`/`._graphics` lookups are now delegated to the entries in the chart's `._flows` table. The new `Flow` methods are generally better factored and provide more detailed output regarding data-stream <-> graphics inter-relations for the future purpose of allowing much more efficient update calls in the display loop as well as supporting low latency interaction UX. The concept here is that we're introducing an intermediary layer that ties together graphics and real-time data flows such that widget code is oriented around plot layout and the flow apis are oriented around real-time low latency updates and providing an efficient high level metric layer for the UX. The summary api transition is something like: - `update_graphics_from_array()` -> `.update_graphics_from_flow()` - `.bars_range()` -> `Flow.datums_range()` - `.bars_range()` -> `Flow.datums_range()`
2022-04-14 13:38:25 +00:00
)
import msgspec
import numpy as np
import pyqtgraph as pg
from PyQt5.QtGui import QPainterPath
from ..data._formatters import (
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
IncrementalFormatter,
)
from ..data._pathops import (
xy_downsample,
2022-04-16 19:22:11 +00:00
)
from ..log import get_logger
from ..toolz import (
Profiler,
)
if TYPE_CHECKING:
2022-12-14 17:05:35 +00:00
from ._dataviz import Viz
log = get_logger(__name__)
Add new `ui._flows` module This begins the removal of data processing / analysis methods from the chart widget and instead moving them to our new `Flow` API (in the new module introduce here) and delegating the old chart methods to the respective internal flow. Most importantly is no longer storing the "last read" of an array from shm in an internal chart table (was `._arrays`) and instead the `ShmArray` instance is passed as input and stored in the `Flow` instance. This greatly simplifies lookup logic such that the display loop now doesn't have to worry about reading shm, it can be done by internal graphics logic as desired. Generally speaking, all previous `._arrays`/`._graphics` lookups are now delegated to the entries in the chart's `._flows` table. The new `Flow` methods are generally better factored and provide more detailed output regarding data-stream <-> graphics inter-relations for the future purpose of allowing much more efficient update calls in the display loop as well as supporting low latency interaction UX. The concept here is that we're introducing an intermediary layer that ties together graphics and real-time data flows such that widget code is oriented around plot layout and the flow apis are oriented around real-time low latency updates and providing an efficient high level metric layer for the UX. The summary api transition is something like: - `update_graphics_from_array()` -> `.update_graphics_from_flow()` - `.bars_range()` -> `Flow.datums_range()` - `.bars_range()` -> `Flow.datums_range()`
2022-04-14 13:38:25 +00:00
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
class Renderer(msgspec.Struct):
'''
Low(er) level interface for converting a source, real-time updated,
data buffer (usually held in a ``ShmArray``) to a graphics data
format usable by `Qt`.
A renderer reads in context-specific source data using a ``Viz``,
formats that data to a 2D-xy pre-graphics format using
a ``IncrementalFormatter``, then renders that data to a set of
output graphics objects normally a ``.ui._curve.FlowGraphics``
sub-type to which the ``Renderer.path`` is applied and further "last
datum" graphics are updated from the source buffer's latest
sample(s).
'''
viz: Viz
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
fmtr: IncrementalFormatter
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
# output graphics rendering, the main object
# processed in ``QGraphicsObject.paint()``
path: QPainterPath | None = None
fast_path: QPainterPath | None = None
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
# downsampling state
_last_uppx: float = 0
_in_ds: bool = False
def draw_path(
self,
x: np.ndarray,
y: np.ndarray,
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
connect: str | np.ndarray = 'all',
path: QPainterPath | None = None,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
redraw: bool = False,
) -> QPainterPath:
path_was_none = path is None
if redraw and path:
path.clear()
# TODO: avoid this?
if self.fast_path:
self.fast_path.clear()
path = pg.functions.arrayToQPath(
x,
y,
connect=connect,
finiteCheck=False,
# reserve mem allocs see:
# - https://doc.qt.io/qt-5/qpainterpath.html#reserve
# - https://doc.qt.io/qt-5/qpainterpath.html#capacity
# - https://doc.qt.io/qt-5/qpainterpath.html#clear
# XXX: right now this is based on ad-hoc checks on a
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
# hidpi 3840x2160 4k monitor but we should optimize for
# the target display(s) on the sys.
# if no_path_yet:
# graphics.path.reserve(int(500e3))
# path=path, # path re-use / reserving
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
)
# avoid mem allocs if possible
if path_was_none:
path.reserve(path.capacity())
return path
def render(
self,
new_read,
array_key: str,
profiler: Profiler,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
uppx: float = 1,
# redraw and ds flags
should_redraw: bool = False,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
new_sample_rate: bool = False,
should_ds: bool = False,
showing_src_data: bool = True,
do_append: bool = True,
use_fpath: bool = True,
force_reformat: bool = False,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
# only render datums "in view" of the ``ChartView``
use_vr: bool = True,
) -> tuple[QPainterPath, bool]:
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
'''
Render the current graphics path(s)
There are (at least) 3 stages from source data to graphics data:
- a data transform (which can be stored in additional shm)
- a graphics transform which converts discrete basis data to
a `float`-basis view-coords graphics basis. (eg. ``ohlc_flatten()``,
``step_path_arrays_from_1d()``, etc.)
- blah blah blah (from notes)
'''
# TODO: can the renderer just call ``Viz.read()`` directly?
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
# unpack latest source data read
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
fmtr = self.fmtr
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
(
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
_,
_,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
array,
ivl,
ivr,
in_view,
) = new_read
# xy-path data transform: convert source data to a format
# able to be passed to a `QPainterPath` rendering routine.
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
fmt_out = fmtr.format_to_1d(
new_read,
array_key,
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
profiler,
slice_to_inview=use_vr,
force_full_realloc=force_reformat,
)
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
# no history in view case
if not fmt_out:
# XXX: this might be why the profiler only has exits?
return
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
(
x_1d,
y_1d,
connect,
prepend_length,
append_length,
view_changed,
# append_tres,
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
) = fmt_out
WIP get incremental step curve updates working This took longer then i care to admit XD but it definitely adds a huge speedup and with only a few outstanding correctness bugs: - panning from left to right causes strange trailing artifacts in the flows fsp (vlm) sub-plot but only when some data is off-screen on the left but doesn't appear to be an issue if we keep the `._set_yrange()` handler hooked up to the `.sigXRangeChanged` signal (but we aren't going to because this makes panning way slower). i've got a feeling this is a bug todo with the device coordinate cache stuff and we may need to report to Qt core? - factoring out the step curve logic from `FastAppendCurve.update_from_array()` (un)fortunately required some logic branch uncoupling but also meant we needed special input controls to avoid things like redraws and curve appends for special cases, this will hopefully all be better rectified in code when the core of this method is moved into a renderer type/implementation. - the `tina_vwap` fsp curve now somehow causes hangs when doing erratic scrolling on downsampled graphics data. i have no idea why or how but disabling it makes the issue go away (ui will literally just freeze and gobble CPU on a `.paint()` call until you ctrl-c the hell out of it). my guess is that something in the logic for standard line curves and appends on large data sets is the issue? Code related changes/hacks: - drop use of `step_path_arrays_from_1d()`, it was always a bit hacky (being based on `pyqtgraph` internals) and was generally hard to understand since it returns 1d data instead of the more expected (N,2) array of "step levels"; instead this is now implemented (uglily) in the `Flow.update_graphics()` block for step curves (which will obviously get cleaned up and factored elsewhere). - add a bunch of new flags to the update method on the fast append curve: `draw_last: bool`, `slice_to_head: int`, `do_append: bool`, `should_redraw: bool` which are all controls to aid with previously mentioned issues specific to getting step curve updates working correctly. - add a ton of commented tinkering related code (that we may end up using) to both the flow and append curve methods that was written as part of the effort to get this all working. - implement all step curve updating inline in `Flow.update_graphics()` including prepend and append logic for pre-graphics incremental step data maintenance and in-view slicing as well as "last step" graphics updating. Obviously clean up commits coming stat B)
2022-04-26 12:34:53 +00:00
if not x_1d.size:
log.warning(f'{array_key} has no `.size`?')
return
# redraw conditions
if (
prepend_length > 0
or new_sample_rate
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
or view_changed
# NOTE: comment this to try and make "append paths"
# work below..
or append_length > 0
):
should_redraw = True
WIP get incremental step curve updates working This took longer then i care to admit XD but it definitely adds a huge speedup and with only a few outstanding correctness bugs: - panning from left to right causes strange trailing artifacts in the flows fsp (vlm) sub-plot but only when some data is off-screen on the left but doesn't appear to be an issue if we keep the `._set_yrange()` handler hooked up to the `.sigXRangeChanged` signal (but we aren't going to because this makes panning way slower). i've got a feeling this is a bug todo with the device coordinate cache stuff and we may need to report to Qt core? - factoring out the step curve logic from `FastAppendCurve.update_from_array()` (un)fortunately required some logic branch uncoupling but also meant we needed special input controls to avoid things like redraws and curve appends for special cases, this will hopefully all be better rectified in code when the core of this method is moved into a renderer type/implementation. - the `tina_vwap` fsp curve now somehow causes hangs when doing erratic scrolling on downsampled graphics data. i have no idea why or how but disabling it makes the issue go away (ui will literally just freeze and gobble CPU on a `.paint()` call until you ctrl-c the hell out of it). my guess is that something in the logic for standard line curves and appends on large data sets is the issue? Code related changes/hacks: - drop use of `step_path_arrays_from_1d()`, it was always a bit hacky (being based on `pyqtgraph` internals) and was generally hard to understand since it returns 1d data instead of the more expected (N,2) array of "step levels"; instead this is now implemented (uglily) in the `Flow.update_graphics()` block for step curves (which will obviously get cleaned up and factored elsewhere). - add a bunch of new flags to the update method on the fast append curve: `draw_last: bool`, `slice_to_head: int`, `do_append: bool`, `should_redraw: bool` which are all controls to aid with previously mentioned issues specific to getting step curve updates working correctly. - add a ton of commented tinkering related code (that we may end up using) to both the flow and append curve methods that was written as part of the effort to get this all working. - implement all step curve updating inline in `Flow.update_graphics()` including prepend and append logic for pre-graphics incremental step data maintenance and in-view slicing as well as "last step" graphics updating. Obviously clean up commits coming stat B)
2022-04-26 12:34:53 +00:00
path: QPainterPath = self.path
fast_path: QPainterPath = self.fast_path
reset: bool = False
self.viz.ds_yrange = None
# redraw the entire source data if we have either of:
# - no prior path graphic rendered or,
# - we always intend to re-render the data only in view
if (
2022-05-18 12:53:35 +00:00
path is None
or should_redraw
):
# print(f"{self.viz.name} -> REDRAWING BRUH")
if (
new_sample_rate
and showing_src_data
):
2023-01-05 23:04:40 +00:00
log.info(f'DE-downsampling -> {array_key}')
self._in_ds = False
elif should_ds and uppx > 1:
ds_out = xy_downsample(
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
x_1d,
y_1d,
uppx,
WIP get incremental step curve updates working This took longer then i care to admit XD but it definitely adds a huge speedup and with only a few outstanding correctness bugs: - panning from left to right causes strange trailing artifacts in the flows fsp (vlm) sub-plot but only when some data is off-screen on the left but doesn't appear to be an issue if we keep the `._set_yrange()` handler hooked up to the `.sigXRangeChanged` signal (but we aren't going to because this makes panning way slower). i've got a feeling this is a bug todo with the device coordinate cache stuff and we may need to report to Qt core? - factoring out the step curve logic from `FastAppendCurve.update_from_array()` (un)fortunately required some logic branch uncoupling but also meant we needed special input controls to avoid things like redraws and curve appends for special cases, this will hopefully all be better rectified in code when the core of this method is moved into a renderer type/implementation. - the `tina_vwap` fsp curve now somehow causes hangs when doing erratic scrolling on downsampled graphics data. i have no idea why or how but disabling it makes the issue go away (ui will literally just freeze and gobble CPU on a `.paint()` call until you ctrl-c the hell out of it). my guess is that something in the logic for standard line curves and appends on large data sets is the issue? Code related changes/hacks: - drop use of `step_path_arrays_from_1d()`, it was always a bit hacky (being based on `pyqtgraph` internals) and was generally hard to understand since it returns 1d data instead of the more expected (N,2) array of "step levels"; instead this is now implemented (uglily) in the `Flow.update_graphics()` block for step curves (which will obviously get cleaned up and factored elsewhere). - add a bunch of new flags to the update method on the fast append curve: `draw_last: bool`, `slice_to_head: int`, `do_append: bool`, `should_redraw: bool` which are all controls to aid with previously mentioned issues specific to getting step curve updates working correctly. - add a ton of commented tinkering related code (that we may end up using) to both the flow and append curve methods that was written as part of the effort to get this all working. - implement all step curve updating inline in `Flow.update_graphics()` including prepend and append logic for pre-graphics incremental step data maintenance and in-view slicing as well as "last step" graphics updating. Obviously clean up commits coming stat B)
2022-04-26 12:34:53 +00:00
)
if ds_out is not None:
x_1d, y_1d, ymn, ymx = ds_out
self.viz.ds_yrange = ymn, ymx
# print(f'{self.viz.name} post ds: ymn, ymx: {ymn},{ymx}')
reset = True
profiler(f'FULL PATH downsample redraw={should_ds}')
self._in_ds = True
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
path = self.draw_path(
Add graphics incr-updated "formatter" subsys After trying to hack epoch indexed time series and failing miserably, decided to properly factor out all formatting routines into a common subsystem API: ``IncrementalFormatter`` which provides the interface for incrementally updating and tracking pre-path-graphics formatted data. Previously this functionality was mangled into our `Renderer` (which also does the work of `QPath` generation and update) but splitting it out also preps for being able to do graphics-buffer downsampling and caching on a remote host B) The ``IncrementalFormatter`` (parent type) has the default behaviour of tracking a single field-array on some source `ShmArray`, updating a flattened `numpy.ndarray` in-mem allocation, and providing a default 1d conversion for pre-downsampling and path generation. Changed out of `Renderer`, - `.allocate_xy()`, `update_xy()` and `format_xy()` all are moved to more explicitly named formatter methods. - all `.x/y_data` nd array management and update - "last view range" tracking - `.last_read`, `.diff()` - now calls `IncrementalFormatter.format_to_1d()` inside `.render()` The new API gets, - `.diff()`, `.last_read` - all view range diff tracking through `.track_inview_range()`. - better nd format array names: `.x/y_nd`, `xy_nd_start/stop`. - `.format_to_1d()` which renders pre-path formatted arrays ready for both m4 sampling and path gen. - better explicit overloadable formatting method names: * `.allocate_xy()` -> `.allocate_xy_nd()` * `.update_xy()` -> `.incr_update_xy_nd()` * `.format_xy()` -> `.format_xy_nd_to_1d()` Finally this implements per-graphics-type formatters which define each set up related formatting routines: - `OHLCBarsFmtr`: std multi-line style bars - `OHLCBarsAsCurveFmtr`: draws an interpolated line for ohlc sampled data - `StepCurveFmtr`: handles vlm style curves
2022-11-22 22:28:58 +00:00
x=x_1d,
y=y_1d,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
connect=connect,
2022-05-18 12:53:35 +00:00
path=path,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
redraw=True,
)
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
profiler(
'generated fresh path. '
f'(should_redraw: {should_redraw} '
f'should_ds: {should_ds} new_sample_rate: {new_sample_rate})'
)
# TODO: get this piecewise prepend working - right now it's
# giving heck on vwap...
# elif prepend_length:
# prepend_path = pg.functions.arrayToQPath(
# x[0:prepend_length],
# y[0:prepend_length],
# connect='all'
# )
# # swap prepend path in "front"
# old_path = graphics.path
# graphics.path = prepend_path
# # graphics.path.moveTo(new_x[0], new_y[0])
# graphics.path.connectPath(old_path)
elif (
append_length > 0
and do_append
):
2023-01-05 23:04:40 +00:00
profiler(f'sliced append path {append_length}')
# (
# x_1d,
# y_1d,
# connect,
# ) = append_tres
profiler(
f'diffed array input, append_length={append_length}'
)
WIP get incremental step curve updates working This took longer then i care to admit XD but it definitely adds a huge speedup and with only a few outstanding correctness bugs: - panning from left to right causes strange trailing artifacts in the flows fsp (vlm) sub-plot but only when some data is off-screen on the left but doesn't appear to be an issue if we keep the `._set_yrange()` handler hooked up to the `.sigXRangeChanged` signal (but we aren't going to because this makes panning way slower). i've got a feeling this is a bug todo with the device coordinate cache stuff and we may need to report to Qt core? - factoring out the step curve logic from `FastAppendCurve.update_from_array()` (un)fortunately required some logic branch uncoupling but also meant we needed special input controls to avoid things like redraws and curve appends for special cases, this will hopefully all be better rectified in code when the core of this method is moved into a renderer type/implementation. - the `tina_vwap` fsp curve now somehow causes hangs when doing erratic scrolling on downsampled graphics data. i have no idea why or how but disabling it makes the issue go away (ui will literally just freeze and gobble CPU on a `.paint()` call until you ctrl-c the hell out of it). my guess is that something in the logic for standard line curves and appends on large data sets is the issue? Code related changes/hacks: - drop use of `step_path_arrays_from_1d()`, it was always a bit hacky (being based on `pyqtgraph` internals) and was generally hard to understand since it returns 1d data instead of the more expected (N,2) array of "step levels"; instead this is now implemented (uglily) in the `Flow.update_graphics()` block for step curves (which will obviously get cleaned up and factored elsewhere). - add a bunch of new flags to the update method on the fast append curve: `draw_last: bool`, `slice_to_head: int`, `do_append: bool`, `should_redraw: bool` which are all controls to aid with previously mentioned issues specific to getting step curve updates working correctly. - add a ton of commented tinkering related code (that we may end up using) to both the flow and append curve methods that was written as part of the effort to get this all working. - implement all step curve updating inline in `Flow.update_graphics()` including prepend and append logic for pre-graphics incremental step data maintenance and in-view slicing as well as "last step" graphics updating. Obviously clean up commits coming stat B)
2022-04-26 12:34:53 +00:00
# if should_ds and uppx > 1:
# new_x, new_y = xy_downsample(
# new_x,
# new_y,
# uppx,
# )
# profiler(f'fast path downsample redraw={should_ds}')
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
append_path = self.draw_path(
x=x_1d,
y=y_1d,
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
connect=connect,
path=fast_path,
)
profiler('generated append qpath')
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
if use_fpath:
# an attempt at trying to make append-updates faster..
if fast_path is None:
2022-05-18 12:53:35 +00:00
fast_path = append_path
# fast_path.reserve(int(6e3))
else:
2023-01-05 23:04:40 +00:00
# print(
# f'{self.viz.name}: FAST PATH\n'
# f"append_path br: {append_path.boundingRect()}\n"
# f"path size: {size}\n"
# f"append_path len: {append_path.length()}\n"
# f"fast_path len: {fast_path.length()}\n"
# )
fast_path.connectPath(append_path)
size = fast_path.capacity()
profiler(f'connected fast path w size: {size}')
# graphics.path.moveTo(new_x[0], new_y[0])
# path.connectPath(append_path)
# XXX: lol this causes a hang..
# graphics.path = graphics.path.simplified()
else:
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
size = path.capacity()
profiler(f'connected history path w size: {size}')
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
path.connectPath(append_path)
Move graphics update logic into `Renderer.render()` Finally this gets us much closer to a generic incremental update system for graphics wherein the input array diffing, pre-graphical format data processing, downsampler activation and incremental update and storage of any of these data flow stages can be managed in one modular sub-system :surfer_boi:. Dirty deatz: - reorg and move all path logic into `Renderer.render()` and have it take in pretty much the same flags as the old `FastAppendCurve.update_from_array()` and instead storing all update state vars (even copies of the downsampler related ones) on the renderer instance: - new state vars: `._last_uppx, ._in_ds, ._vr, ._avr` - `.render()` input bools: `new_sample_rate, should_redraw, should_ds, showing_src_data` - add a hack-around for passing in incremental update data (for now) via a `input_data: tuple` of numpy arrays - a default `uppx: float = 1` - add new render interface attrs: - `.format_xy()` which takes in the source data array and produces out x, y arrays (and maybe a `connect` array) that can be passed to `.draw_path()` (the default for this is just to slice out the index and `array_key: str` columns from the input struct array), - `.draw_path()` which takes in the x, y, connect arrays and generates a `QPainterPath` - `.fast_path`, for "appendable" updates like there was on the fast append curve - move redraw (aka `.clear()` calls) into `.draw_path()` and trigger via `redraw: bool` flag. - our graphics objects no longer set their own `.path` state, it's done by the `Flow.update_graphics()` method using output from `Renderer.render()` (and it's state if necessary)
2022-05-18 19:23:14 +00:00
self.path = path
self.fast_path = fast_path
return self.path, reset