Drop diff state tracking in formatter
This was a major cause of error (particularly trying to get epoch indexing working) and really isn't necessary; instead just have `.diff()` always read from the underlying source array for current index-step diffing and append/prepend slice construction. Allows us to, - drop `._last_read` state management and thus usage. - better handle startup indexing by setting `.xy_nd_start/stop` to `None` initially so that the first update can be done in one large prepend. - better understand and document the step curve "slice back to previous level" logic which is now heavily commented B) - drop all the `slice_to_head` stuff from and instead allow each formatter to choose it's 1d segmenting.epoch_indexing_and_dataviz_layer
parent
3d5695f40a
commit
6ea04f850d
|
@ -64,18 +64,6 @@ class IncrementalFormatter(msgspec.Struct):
|
|||
viz: Viz
|
||||
index_field: str = 'index'
|
||||
|
||||
# last read from shm (usually due to an update call)
|
||||
_last_read: tuple[
|
||||
int,
|
||||
int,
|
||||
np.ndarray
|
||||
|
||||
]
|
||||
|
||||
@property
|
||||
def last_read(self) -> tuple | None:
|
||||
return self._last_read
|
||||
|
||||
# Incrementally updated xy ndarray formatted data, a pre-1d
|
||||
# format which is updated and cached independently of the final
|
||||
# pre-graphics-path 1d format.
|
||||
|
@ -99,8 +87,8 @@ class IncrementalFormatter(msgspec.Struct):
|
|||
# indexes which slice into the above arrays (which are allocated
|
||||
# based on source data shm input size) and allow retrieving
|
||||
# incrementally updated data.
|
||||
xy_nd_start: int = 0
|
||||
xy_nd_stop: int = 0
|
||||
xy_nd_start: int | None = None
|
||||
xy_nd_stop: int | None = None
|
||||
|
||||
# TODO: eventually incrementally update 1d-pre-graphics path data?
|
||||
# x_1d: Optional[np.ndarray] = None
|
||||
|
@ -144,17 +132,14 @@ class IncrementalFormatter(msgspec.Struct):
|
|||
np.ndarray,
|
||||
np.ndarray,
|
||||
]:
|
||||
(
|
||||
last_xfirst,
|
||||
last_xlast,
|
||||
last_array,
|
||||
last_ivl,
|
||||
last_ivr,
|
||||
last_in_view,
|
||||
) = self.last_read
|
||||
|
||||
# TODO: can the renderer just call ``Viz.read()`` directly?
|
||||
# unpack latest source data read
|
||||
# TODO:
|
||||
# - can the renderer just call ``Viz.read()`` directly? unpack
|
||||
# latest source data read
|
||||
# - eventually maybe we can implement some kind of
|
||||
# transform on the ``QPainterPath`` that will more or less
|
||||
# detect the diff in "elements" terms? update diff state since
|
||||
# we've now rendered paths.
|
||||
(
|
||||
xfirst,
|
||||
xlast,
|
||||
|
@ -164,25 +149,42 @@ class IncrementalFormatter(msgspec.Struct):
|
|||
in_view,
|
||||
) = new_read
|
||||
|
||||
index = array['index']
|
||||
|
||||
# if the first index in the read array is 0 then
|
||||
# it means the source buffer has bee completely backfilled to
|
||||
# available space.
|
||||
src_start = index[0]
|
||||
src_stop = index[-1] + 1
|
||||
|
||||
# these are the "formatted output data" indices
|
||||
# for the pre-graphics arrays.
|
||||
nd_start = self.xy_nd_start
|
||||
nd_stop = self.xy_nd_stop
|
||||
|
||||
if (
|
||||
nd_start is None
|
||||
):
|
||||
assert nd_stop is None
|
||||
|
||||
# setup to do a prepend of all existing src history
|
||||
nd_start = self.xy_nd_start = src_stop
|
||||
# set us in a zero-to-append state
|
||||
nd_stop = self.xy_nd_stop = src_stop
|
||||
|
||||
# compute the length diffs between the first/last index entry in
|
||||
# the input data and the last indexes we have on record from the
|
||||
# last time we updated the curve index.
|
||||
prepend_length = int(last_xfirst - xfirst)
|
||||
append_length = int(xlast - last_xlast)
|
||||
|
||||
# if (
|
||||
# prepend_length < 0
|
||||
# or append_length < 0
|
||||
# ):
|
||||
# breakpoint()
|
||||
prepend_length = int(nd_start - src_start)
|
||||
append_length = int(src_stop - nd_stop)
|
||||
|
||||
# blah blah blah
|
||||
# do diffing for prepend, append and last entry
|
||||
return (
|
||||
slice(xfirst, last_xfirst),
|
||||
slice(src_start, nd_start),
|
||||
prepend_length,
|
||||
append_length,
|
||||
slice(last_xlast, xlast),
|
||||
slice(nd_stop, src_stop),
|
||||
)
|
||||
|
||||
def _track_inview_range(
|
||||
|
@ -233,7 +235,6 @@ class IncrementalFormatter(msgspec.Struct):
|
|||
array_key: str,
|
||||
profiler: Profiler,
|
||||
|
||||
slice_to_head: int = -1,
|
||||
read_src_from_key: bool = True,
|
||||
slice_to_inview: bool = True,
|
||||
|
||||
|
@ -311,12 +312,6 @@ class IncrementalFormatter(msgspec.Struct):
|
|||
self.xy_nd_stop = shm._last.value
|
||||
profiler('appened xy history: {append_length}')
|
||||
|
||||
# TODO: eventually maybe we can implement some kind of
|
||||
# transform on the ``QPainterPath`` that will more or less
|
||||
# detect the diff in "elements" terms?
|
||||
# update diff state since we've now rendered paths.
|
||||
self._last_read = new_read
|
||||
|
||||
view_changed: bool = False
|
||||
view_range: tuple[int, int] = (ivl, ivr)
|
||||
if slice_to_inview:
|
||||
|
@ -365,7 +360,7 @@ class IncrementalFormatter(msgspec.Struct):
|
|||
|
||||
# update the last "in view data range"
|
||||
if len(x_1d):
|
||||
self._last_ivdr = x_1d[0], x_1d[slice_to_head]
|
||||
self._last_ivdr = x_1d[0], x_1d[-1]
|
||||
if (x_1d[-1] == 0.5).any():
|
||||
breakpoint()
|
||||
|
||||
|
@ -760,41 +755,62 @@ class StepCurveFmtr(IncrementalFormatter):
|
|||
np.ndarray,
|
||||
slice,
|
||||
]:
|
||||
# for a step curve we slice from one datum prior
|
||||
# NOTE: for a step curve we slice from one datum prior
|
||||
# to the current "update slice" to get the previous
|
||||
# "level".
|
||||
last_2 = slice(
|
||||
read_slc.start,
|
||||
read_slc.stop+1,
|
||||
#
|
||||
# why this is needed,
|
||||
# - the current new append slice will often have a zero
|
||||
# value in the latest datum-step (at least for zero-on-new
|
||||
# cases like vlm in the) as per configuration of the FSP
|
||||
# engine.
|
||||
# - we need to look back a datum to get the last level which
|
||||
# will be used to terminate/complete the last step x-width
|
||||
# which will be set to pair with the last x-index THIS MEANS
|
||||
#
|
||||
# XXX: this means WE CAN'T USE the append slice since we need to
|
||||
# "look backward" one step to get the needed back-to-zero level
|
||||
# and the update data in ``new_from_src`` will only contain the
|
||||
# latest new data.
|
||||
back_1 = slice(
|
||||
read_slc.start - 1,
|
||||
read_slc.stop,
|
||||
)
|
||||
y_nd_new = self.y_nd[last_2]
|
||||
y_nd_new[:] = src_shm._array[last_2][array_key][:, None]
|
||||
|
||||
# NOTE: we can't use the append slice since we need to "look
|
||||
# forward" one step to get the current level and copy it as
|
||||
# well? (though i still don't really grok why..)
|
||||
# y_nd_new[:] = new_from_src[array_key][:, None]
|
||||
to_write = src_shm._array[back_1]
|
||||
y_nd_new = self.y_nd[back_1]
|
||||
y_nd_new[:] = to_write[array_key][:, None]
|
||||
|
||||
# XXX: old approach now duplicated above (we can probably drop
|
||||
# this since the key part was the ``nd_stop + 1``
|
||||
# if is_append:
|
||||
# start = max(nd_stop - 1, 0)
|
||||
# end = src_shm._last.value
|
||||
# y_nd_new = src_shm._array[start:end][array_key]#[:, np.newaxis]
|
||||
# slc = slice(start, end)
|
||||
# self.y_nd[slc] = np.broadcast_to(
|
||||
# y_nd_new[:, None],
|
||||
# (y_nd_new.size, 2),
|
||||
x_nd_new = self.x_nd[read_slc]
|
||||
x_nd_new[:] = (
|
||||
new_from_src[self.index_field][:, None]
|
||||
+
|
||||
np.array([-0.5, 0.5])
|
||||
)
|
||||
|
||||
# XXX: uncomment for debugging
|
||||
# x_nd = self.x_nd[self.xy_slice]
|
||||
# y_nd = self.y_nd[self.xy_slice]
|
||||
# name = self.viz.name
|
||||
# if 'dolla_vlm' in name:
|
||||
# s = 4
|
||||
# print(
|
||||
# f'{name}:\n'
|
||||
# 'NEW_FROM_SRC:\n'
|
||||
# f'new_from_src: {new_from_src}\n\n'
|
||||
|
||||
# f'PRE self.x_nd:'
|
||||
# f'\n{x_nd[-s:]}\n'
|
||||
# f'PRE self.y_nd:\n'
|
||||
# f'{y_nd[-s:]}\n\n'
|
||||
|
||||
# f'TO WRITE:\n'
|
||||
# f'x_nd_new:\n'
|
||||
# f'{x_nd_new}\n'
|
||||
# f'y_nd_new:\n'
|
||||
# f'{y_nd_new}\n'
|
||||
# )
|
||||
|
||||
index_field = self.index_field
|
||||
if index_field != 'index':
|
||||
x_nd_new = self.x_nd[read_slc]
|
||||
x_nd_new[:] = new_from_src[index_field][:, np.newaxis]
|
||||
|
||||
# if (self.x_nd[self.xy_slice][-1] == 0.5).any():
|
||||
# breakpoint()
|
||||
|
||||
def format_xy_nd_to_1d(
|
||||
self,
|
||||
|
||||
|
@ -815,15 +831,10 @@ class StepCurveFmtr(IncrementalFormatter):
|
|||
x_step = self.x_nd[start:stop]
|
||||
y_step = self.y_nd[start:stop]
|
||||
|
||||
# if (x_step[-1] == 0.5).any():
|
||||
# breakpoint()
|
||||
|
||||
# pack in duplicate final value to complete last step level
|
||||
# x_step[-1] = last_t
|
||||
# y_step[-1] = last
|
||||
# x_step[-1, 1] = last_t
|
||||
y_step[-1, 1] = last
|
||||
|
||||
# debugging
|
||||
# if y_step.any():
|
||||
# s = 3
|
||||
# print(
|
||||
|
@ -833,7 +844,9 @@ class StepCurveFmtr(IncrementalFormatter):
|
|||
|
||||
# slice out in-view data
|
||||
ivl, ivr = vr
|
||||
# TODO: WHY do we need the extra +1 index?
|
||||
|
||||
# NOTE: add an extra step to get the vertical-line-down-to-zero
|
||||
# adjacent to the last-datum graphic (filled rect).
|
||||
x_step_iv = x_step[ivl:ivr+1]
|
||||
y_step_iv = y_step[ivl:ivr+1]
|
||||
|
||||
|
@ -847,6 +860,7 @@ class StepCurveFmtr(IncrementalFormatter):
|
|||
if x_1d.any() and (x_1d[-1] == 0.5).any():
|
||||
breakpoint()
|
||||
|
||||
# debugging
|
||||
# if y_1d.any():
|
||||
# s = 6
|
||||
# print(
|
||||
|
|
|
@ -102,7 +102,6 @@ def render_baritems(
|
|||
fmtr=OHLCBarsFmtr(
|
||||
shm=viz.shm,
|
||||
viz=viz,
|
||||
_last_read=read,
|
||||
index_field=viz.index_field,
|
||||
),
|
||||
)
|
||||
|
@ -112,7 +111,6 @@ def render_baritems(
|
|||
fmtr=OHLCBarsAsCurveFmtr(
|
||||
shm=viz.shm,
|
||||
viz=viz,
|
||||
_last_read=read,
|
||||
index_field=viz.index_field,
|
||||
),
|
||||
)
|
||||
|
@ -528,7 +526,6 @@ class Viz(msgspec.Struct): # , frozen=True):
|
|||
# print('exiting early')
|
||||
return graphics
|
||||
|
||||
slice_to_head: int = -1
|
||||
should_redraw: bool = False
|
||||
should_line: bool = False
|
||||
rkwargs = {}
|
||||
|
@ -565,7 +562,6 @@ class Viz(msgspec.Struct): # , frozen=True):
|
|||
fmtr=StepCurveFmtr(
|
||||
shm=self.shm,
|
||||
viz=self,
|
||||
_last_read=read,
|
||||
index_field=self.index_field,
|
||||
),
|
||||
)
|
||||
|
@ -573,7 +569,6 @@ class Viz(msgspec.Struct): # , frozen=True):
|
|||
# TODO: append logic inside ``.render()`` isn't
|
||||
# correct yet for step curves.. remove this to see it.
|
||||
should_redraw = True
|
||||
slice_to_head = -2
|
||||
|
||||
else:
|
||||
r = self._src_r
|
||||
|
@ -584,13 +579,9 @@ class Viz(msgspec.Struct): # , frozen=True):
|
|||
fmtr=IncrementalFormatter(
|
||||
shm=self.shm,
|
||||
viz=self,
|
||||
_last_read=read,
|
||||
),
|
||||
)
|
||||
|
||||
if isinstance(graphics, StepCurve):
|
||||
slice_to_head = -2
|
||||
|
||||
# ``Curve`` derivative case(s):
|
||||
array_key = array_key or self.name
|
||||
# print(array_key)
|
||||
|
@ -654,7 +645,6 @@ class Viz(msgspec.Struct): # , frozen=True):
|
|||
should_ds=should_ds,
|
||||
showing_src_data=showing_src_data,
|
||||
|
||||
slice_to_head=slice_to_head,
|
||||
do_append=do_append,
|
||||
|
||||
**rkwargs,
|
||||
|
@ -881,7 +871,6 @@ class Renderer(msgspec.Struct):
|
|||
showing_src_data: bool = True,
|
||||
|
||||
do_append: bool = True,
|
||||
slice_to_head: int = -1,
|
||||
use_fpath: bool = True,
|
||||
|
||||
# only render datums "in view" of the ``ChartView``
|
||||
|
@ -921,7 +910,6 @@ class Renderer(msgspec.Struct):
|
|||
array_key,
|
||||
profiler,
|
||||
|
||||
slice_to_head=slice_to_head,
|
||||
read_src_from_key=read_from_key,
|
||||
slice_to_inview=use_vr,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue