Add `Viz.bars_range()` (moved from chart API)

Call it from view kb loop.
epoch_indexing_and_dataviz_layer
Tyler Goodlet 2022-11-28 09:47:41 -05:00
parent 6cacd7d18b
commit 5a0673d66f
2 changed files with 119 additions and 33 deletions

View File

@ -76,7 +76,6 @@ async def handle_viewmode_kb_inputs(
pressed: set[str] = set() pressed: set[str] = set()
last = time.time() last = time.time()
trigger_mode: str
action: str action: str
on_next_release: Optional[Callable] = None on_next_release: Optional[Callable] = None
@ -495,7 +494,7 @@ class ChartView(ViewBox):
chart = self.linked.chart chart = self.linked.chart
# don't zoom more then the min points setting # don't zoom more then the min points setting
l, lbar, rbar, r = chart.bars_range() l, lbar, rbar, r = chart.get_viz(chart.name).bars_range()
# vl = r - l # vl = r - l
# if ev.delta() > 0 and vl <= _min_points_to_show: # if ev.delta() > 0 and vl <= _min_points_to_show:

View File

@ -129,12 +129,18 @@ def render_baritems(
ds_r, curve = self._render_table ds_r, curve = self._render_table
# print(
# f'r: {r.fmtr.xy_slice}\n'
# f'ds_r: {ds_r.fmtr.xy_slice}\n'
# )
# do checks for whether or not we require downsampling: # do checks for whether or not we require downsampling:
# - if we're **not** downsampling then we simply want to # - if we're **not** downsampling then we simply want to
# render the bars graphics curve and update.. # render the bars graphics curve and update..
# - if instead we are in a downsamplig state then we to # - if instead we are in a downsamplig state then we to
x_gt = 6 x_gt = 6
uppx = curve.x_uppx() uppx = curve.x_uppx()
print(f'BARS UPPX: {uppx}')
in_line = should_line = curve.isVisible() in_line = should_line = curve.isVisible()
if ( if (
in_line in_line
@ -241,9 +247,6 @@ class Viz(msgspec.Struct): # , frozen=True):
# to the underlying shm ref after startup? # to the underlying shm ref after startup?
# _shm: Optional[ShmArray] = None # currently, may be filled in "later" # _shm: Optional[ShmArray] = None # currently, may be filled in "later"
# last read from shm (usually due to an update call)
_last_read: Optional[np.ndarray] = None
# cache of y-range values per x-range input. # cache of y-range values per x-range input.
_mxmns: dict[tuple[int, int], tuple[float, float]] = {} _mxmns: dict[tuple[int, int], tuple[float, float]] = {}
@ -263,6 +266,8 @@ class Viz(msgspec.Struct): # , frozen=True):
if no range can be determined (yet). if no range can be determined (yet).
''' '''
# TODO: hash the slice instead maybe?
# https://stackoverflow.com/a/29980872
rkey = (lbar, rbar) rkey = (lbar, rbar)
cached_result = self._mxmns.get(rkey) cached_result = self._mxmns.get(rkey)
if cached_result: if cached_result:
@ -274,14 +279,27 @@ class Viz(msgspec.Struct): # , frozen=True):
arr = shm.array arr = shm.array
# build relative indexes into shm array # get relative slice indexes into array
(
abs_slc,
read_slc,
mask,
) = self.flume.slice_from_time(
arr,
start_t=lbar,
stop_t=rbar,
)
# TODO: should we just add/use a method # TODO: should we just add/use a method
# on the shm to do this? # on the shm to do this?
ifirst = arr[0]['index']
slice_view = arr[ # ifirst = arr[0]['index']
lbar - ifirst: # slice_view = arr[
(rbar - ifirst) + 1 # lbar - ifirst:
] # (rbar - ifirst) + 1
# ]
slice_view = arr[mask]
if not slice_view.size: if not slice_view.size:
return None return None
@ -321,9 +339,18 @@ class Viz(msgspec.Struct): # , frozen=True):
vr.right(), vr.right(),
) )
def bars_range(self) -> tuple[int, int, int, int]:
'''
Return a range tuple for the bars present in view.
'''
start, l, datum_start, datum_stop, r, stop = self.datums_range()
return l, datum_start, datum_stop, r
def datums_range( def datums_range(
self, self,
index_field: str = 'index', index_field: str = 'time',
) -> tuple[ ) -> tuple[
int, int, int, int, int, int int, int, int, int, int, int
]: ]:
@ -335,26 +362,39 @@ class Viz(msgspec.Struct): # , frozen=True):
l = round(l) l = round(l)
r = round(r) r = round(r)
# TODO: avoid this and have shm passed # # TODO: avoid this and have shm passed
# in earlier. # # in earlier.
if self.shm is None: # if self.shm is None:
# haven't initialized the viz yet # # haven't initialized the viz yet
return (0, l, 0, 0, r, 0) # return (0, l, 0, 0, r, 0)
array = self.shm.array array = self.shm.array
index = array['index'] index = array[index_field]
start = index[0] start = index[0]
end = index[-1] stop = index[-1]
lbar = max(l, start) datum_start = max(l, start)
rbar = min(r, end) datum_stop = min(r, stop)
return ( return (
start, l, lbar, rbar, r, end, start,
l, # left x-in-view
datum_start,
datum_stop,
r, # right-x-in-view
stop,
) )
def bars_range(self) -> tuple[int, int, int, int]:
'''
Return a range tuple for the bars present in view.
'''
start, l, datum_start, datum_stop, r, stop = self.datums_range()
return l, datum_start, datum_stop, r
def read( def read(
self, self,
array_field: Optional[str] = None, array_field: Optional[str] = None,
index_field: str = 'index', index_field: str = 'time',
) -> tuple[ ) -> tuple[
int, int, np.ndarray, int, int, np.ndarray,
@ -370,30 +410,59 @@ class Viz(msgspec.Struct): # , frozen=True):
# readable data # readable data
array = self.shm.array array = self.shm.array
indexes = array[index_field] # indexes = array[index_field]
ifirst = indexes[0] # ifirst = indexes[0]
ilast = indexes[-1] # ilast = indexes[-1]
ifirst, l, lbar, rbar, r, ilast = self.datums_range() (
ifirst,
l,
lbar,
rbar,
r,
ilast,
) = self.datums_range(index_field=index_field)
(
abs_slc,
read_slc,
mask,
) = self.flume.slice_from_time(
array,
start_t=lbar,
stop_t=rbar,
)
# (
# abs_slc,
# read_slc,
# in_view,
# ) = self.flume.view_data(
# self.plot,
# )
# get read-relative indices adjusting # get read-relative indices adjusting
# for master shm index. # for master shm index.
lbar_i = max(l, ifirst) - ifirst # lbar_i = max(l, ifirst) - ifirst
rbar_i = min(r, ilast) - ifirst # rbar_i = min(r, ilast) - ifirst
in_view = array[read_slc]
if array_field: if array_field:
array = array[array_field] array = array[array_field]
# TODO: we could do it this way as well no? # TODO: we could do it this way as well no?
# to_draw = array[lbar - ifirst:(rbar - ifirst) + 1] # to_draw = array[lbar - ifirst:(rbar - ifirst) + 1]
in_view = array[lbar_i: rbar_i + 1] # in_view = array[lbar_i: rbar_i + 1]
return ( return (
# abs indices + full data set # abs indices + full data set
ifirst, ilast, array, abs_slc.start,
abs_slc.stop,
array,
# relative indices + in view datums # relative (read) indices + in view data
lbar_i, rbar_i, in_view, read_slc.start,
read_slc.stop,
in_view,
) )
def update_graphics( def update_graphics(
@ -495,6 +564,9 @@ class Viz(msgspec.Struct): # , frozen=True):
), ),
) )
if isinstance(graphics, StepCurve):
slice_to_head = -2
# ``Curve`` derivative case(s): # ``Curve`` derivative case(s):
array_key = array_key or self.name array_key = array_key or self.name
# print(array_key) # print(array_key)
@ -682,6 +754,21 @@ class Viz(msgspec.Struct): # , frozen=True):
# print(f'updating NOT DS curve {self.name}') # print(f'updating NOT DS curve {self.name}')
g.update() g.update()
def curve_width_pxs(
self,
) -> float:
'''
Return the width of the current datums in view in pixel units.
'''
_, lbar, rbar, _ = self.bars_range()
return self.view.mapViewToDevice(
QLineF(
lbar, 0,
rbar, 0
)
).length()
class Renderer(msgspec.Struct): class Renderer(msgspec.Struct):