Fix 'last datum line is uppx's worth of data' rendering

This was introduced in #302 but after thorough testing was clear to be
not working XD. Adjust the display loop to update the last graphics
segment on both the OHLC and vlm charts (as well as all deriving fsp
flows) whenever the uppx >= 1 and there is no current path append
taking place (since more datums are needed to span an x-pixel in view).

Summary of tweaks:
- move vlm chart update code to be at the end of the cycle routine and
  have that block include the tests for a "interpolated last datum in
  view" line.
- make `do_append: bool` compare with a floor of the uppx value (i.e.
  appends should happen when we're just fractionally over a pixel of
  x units).
- never update the "volume" chart.
update_last_datums_in_view
Tyler Goodlet 2022-06-09 17:46:55 -04:00
parent 4099b53ea2
commit 3074773662
1 changed files with 109 additions and 87 deletions

View File

@ -24,6 +24,7 @@ graphics update methods via our custom ``pyqtgraph`` charting api.
from dataclasses import dataclass from dataclasses import dataclass
from functools import partial from functools import partial
import time import time
from math import floor
from typing import Optional, Any, Callable from typing import Optional, Any, Callable
import numpy as np import numpy as np
@ -367,7 +368,7 @@ def graphics_update_cycle(
# such unit steps per pixel (aka uppx). Iow, if the zoom level # such unit steps per pixel (aka uppx). Iow, if the zoom level
# is such that a datum(s) update to graphics wouldn't span # is such that a datum(s) update to graphics wouldn't span
# to a new pixel, we don't update yet. # to a new pixel, we don't update yet.
do_append = (append_diff >= uppx) do_append = (append_diff >= floor(uppx))
if do_append: if do_append:
vars['i_last_append'] = i_step vars['i_last_append'] = i_step
@ -426,71 +427,6 @@ def graphics_update_cycle(
profiler('view incremented') profiler('view incremented')
if vlm_chart:
# always update y-label
ds.vlm_sticky.update_from_data(
*array[-1][['index', 'volume']]
)
if (
(
do_rt_update
or do_append
and liv
)
or trigger_all
):
# TODO: make it so this doesn't have to be called
# once the $vlm is up?
vlm_chart.update_graphics_from_flow(
'volume',
# UGGGh, see ``maxmin()`` impl in `._fsp` for
# the overlayed plotitems... we need a better
# bay to invoke a maxmin per overlay..
render=False,
# XXX: ^^^^ THIS IS SUPER IMPORTANT! ^^^^
# without this, since we disable the
# 'volume' (units) chart after the $vlm starts
# up we need to be sure to enable this
# auto-ranging otherwise there will be no handler
# connected to update accompanying overlay
# graphics..
)
profiler('`vlm_chart.update_graphics_from_flow()`')
if (
mx_vlm_in_view != vars['last_mx_vlm']
):
yrange = (0, mx_vlm_in_view * 1.375)
vlm_chart.view._set_yrange(
yrange=yrange,
)
profiler('`vlm_chart.view._set_yrange()`')
# print(f'mx vlm: {last_mx_vlm} -> {mx_vlm_in_view}')
vars['last_mx_vlm'] = mx_vlm_in_view
for curve_name, flow in vlm_chart._flows.items():
if not flow.render:
continue
update_fsp_chart(
vlm_chart,
flow,
curve_name,
array_key=curve_name,
# do_append=uppx < update_uppx,
do_append=do_append,
)
# is this even doing anything?
# (pretty sure it's the real-time
# resizing from last quote?)
fvb = flow.plot.vb
fvb._set_yrange(
# autoscale_linked_plots=False,
name=curve_name,
)
ticks_frame = quote.get('ticks', ()) ticks_frame = quote.get('ticks', ())
frames_by_type: dict[str, dict] = {} frames_by_type: dict[str, dict] = {}
@ -540,15 +476,16 @@ def graphics_update_cycle(
or do_append or do_append
or trigger_all or trigger_all
): ):
# TODO: we should always update the "last" datum
# since the current range should at least be updated
# to it's max/min on the last pixel.
chart.update_graphics_from_flow( chart.update_graphics_from_flow(
chart.name, chart.name,
# do_append=uppx < update_uppx, # do_append=uppx < update_uppx,
do_append=do_append, do_append=do_append,
) )
# NOTE: we always update the "last" datum
# since the current range should at least be updated
# to it's max/min on the last pixel.
# iterate in FIFO order per tick-frame # iterate in FIFO order per tick-frame
for typ, tick in lasts.items(): for typ, tick in lasts.items():
@ -653,30 +590,115 @@ def graphics_update_cycle(
vars['last_mx'], vars['last_mn'] = mx, mn vars['last_mx'], vars['last_mn'] = mx, mn
# run synchronous update on all linked flows # run synchronous update on all linked flows
# TODO: should the "main" (aka source) flow be special?
for curve_name, flow in chart._flows.items(): for curve_name, flow in chart._flows.items():
# update any overlayed fsp flows
if curve_name != chart.data_key:
update_fsp_chart(
chart,
flow,
curve_name,
array_key=curve_name,
)
# even if we're downsampled bigly
# draw the last datum in the final
# px column to give the user the mx/mn
# range of that set.
if (
not do_append
# and not do_rt_update
and liv
):
flow.draw_last(
array_key=curve_name,
only_last_uppx=True,
)
# volume chart logic..
# TODO: can we unify this with the above loop?
if vlm_chart:
# always update y-label
ds.vlm_sticky.update_from_data(
*array[-1][['index', 'volume']]
)
if ( if (
not (do_rt_update or do_append) (
and liv do_rt_update
# even if we're downsampled bigly or do_append
# draw the last datum in the final and liv
# px column to give the user the mx/mn )
# range of that set. or trigger_all
): ):
# always update the last datum-element # TODO: make it so this doesn't have to be called
# graphic for all flows # once the $vlm is up?
flow.draw_last(array_key=curve_name) vlm_chart.update_graphics_from_flow(
'volume',
# UGGGh, see ``maxmin()`` impl in `._fsp` for
# the overlayed plotitems... we need a better
# bay to invoke a maxmin per overlay..
render=False,
# XXX: ^^^^ THIS IS SUPER IMPORTANT! ^^^^
# without this, since we disable the
# 'volume' (units) chart after the $vlm starts
# up we need to be sure to enable this
# auto-ranging otherwise there will be no handler
# connected to update accompanying overlay
# graphics..
)
profiler('`vlm_chart.update_graphics_from_flow()`')
# TODO: should the "main" (aka source) flow be special? if (
if curve_name == chart.data_key: mx_vlm_in_view != vars['last_mx_vlm']
continue ):
yrange = (0, mx_vlm_in_view * 1.375)
vlm_chart.view._set_yrange(
yrange=yrange,
)
profiler('`vlm_chart.view._set_yrange()`')
# print(f'mx vlm: {last_mx_vlm} -> {mx_vlm_in_view}')
vars['last_mx_vlm'] = mx_vlm_in_view
update_fsp_chart( for curve_name, flow in vlm_chart._flows.items():
chart,
flow, if (
curve_name, curve_name != 'volume' and
array_key=curve_name, flow.render and (
) liv and
do_rt_update or do_append
)
):
update_fsp_chart(
vlm_chart,
flow,
curve_name,
array_key=curve_name,
# do_append=uppx < update_uppx,
do_append=do_append,
)
# is this even doing anything?
# (pretty sure it's the real-time
# resizing from last quote?)
fvb = flow.plot.vb
fvb._set_yrange(
name=curve_name,
)
elif (
curve_name != 'volume'
and not do_append
and liv
and uppx >= 1
# even if we're downsampled bigly
# draw the last datum in the final
# px column to give the user the mx/mn
# range of that set.
):
# always update the last datum-element
# graphic for all flows
# print(f'drawing last {flow.name}')
flow.draw_last(array_key=curve_name)
async def display_symbol_data( async def display_symbol_data(