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
parent
4099b53ea2
commit
3074773662
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue