Make `LinearRegion` link using epoch-time index

Turned out to be super simple to get the first draft to work since the
fast and slow chart now use the same domain, however, it seems like
maybe there's an offset issue still where the fast may be a couple
minutes ahead of the slow?

Need to dig in a bit..
multichartz
Tyler Goodlet 2022-12-15 14:26:50 -05:00
parent eb0216feaf
commit e95152272f
1 changed files with 100 additions and 80 deletions

View File

@ -847,92 +847,113 @@ async def link_views_with_region(
hist_pi.addItem(region, ignoreBounds=True) hist_pi.addItem(region, ignoreBounds=True)
region.setOpacity(6/16) region.setOpacity(6/16)
viz = rt_chart._vizs[flume.symbol.fqsn] viz = rt_chart.get_viz(flume.symbol.fqsn)
assert viz assert viz
index_field = viz.index_field
# XXX: no idea why this doesn't work but it's causing # XXX: no idea why this doesn't work but it's causing
# a weird placement of the region on the way-far-left.. # a weird placement of the region on the way-far-left..
# region.setClipItem(viz.graphics) # region.setClipItem(viz.graphics)
# poll for datums load and timestep detection if index_field == 'time':
for _ in range(100):
try: # in the (epoch) index case we can map directly
_, _, ratio = flume.get_ds_info() # from the fast chart's x-domain values since they are
break # on the same index as the slow chart.
except IndexError:
await trio.sleep(0.01) def update_region_from_pi(
continue window,
viewRange: tuple[tuple, tuple],
is_manual: bool = True,
) -> None:
# put linear region "in front" in layer terms
region.setZValue(10)
# set the region on the history chart
# to the range currently viewed in the
# HFT/real-time chart.
region.setRegion(viewRange[0])
else: else:
raise RuntimeError( # poll for datums load and timestep detection
'Failed to detect sampling periods from shm!?') for _ in range(100):
try:
_, _, ratio = flume.get_ds_info()
break
except IndexError:
await trio.sleep(0.01)
continue
else:
raise RuntimeError(
'Failed to detect sampling periods from shm!?')
# sampling rate transform math: # sampling rate transform math:
# ----------------------------- # -----------------------------
# define the fast chart to slow chart as a linear mapping # define the fast chart to slow chart as a linear mapping
# over the fast index domain `i` to the slow index domain # over the fast index domain `i` to the slow index domain
# `j` as: # `j` as:
# #
# j = i - i_offset # j = i - i_offset
# ------------ + j_offset # ------------ + j_offset
# j/i # j/i
# #
# conversely the inverse function is: # conversely the inverse function is:
# #
# i = j/i * (j - j_offset) + i_offset # i = j/i * (j - j_offset) + i_offset
# #
# Where `j_offset` is our ``izero_hist`` and `i_offset` is our # Where `j_offset` is our ``izero_hist`` and `i_offset` is our
# `izero_rt`, the ``ShmArray`` offsets which correspond to the # `izero_rt`, the ``ShmArray`` offsets which correspond to the
# indexes in each array where the "current" time is indexed at init. # indexes in each array where the "current" time is indexed at init.
# AKA the index where new data is "appended to" and historical data # AKA the index where new data is "appended to" and historical data
# if "prepended from". # if "prepended from".
# #
# more practically (and by default) `i` is normally an index # more practically (and by default) `i` is normally an index
# into 1s samples and `j` is an index into 60s samples (aka 1m). # into 1s samples and `j` is an index into 60s samples (aka 1m).
# in the below handlers ``ratio`` is the `j/i` and ``mn``/``mx`` # in the below handlers ``ratio`` is the `j/i` and ``mn``/``mx``
# are the low and high index input from the source index domain. # are the low and high index input from the source index domain.
def update_region_from_pi( def update_region_from_pi(
window, window,
viewRange: tuple[tuple, tuple], viewRange: tuple[tuple, tuple],
is_manual: bool = True, is_manual: bool = True,
) -> None: ) -> None:
# put linear region "in front" in layer terms # put linear region "in front" in layer terms
region.setZValue(10) region.setZValue(10)
# set the region on the history chart # set the region on the history chart
# to the range currently viewed in the # to the range currently viewed in the
# HFT/real-time chart. # HFT/real-time chart.
mn, mx = viewRange[0] mn, mx = viewRange[0]
ds_mn = (mn - izero_rt)/ratio ds_mn = (mn - izero_rt)/ratio
ds_mx = (mx - izero_rt)/ratio ds_mx = (mx - izero_rt)/ratio
lhmn = ds_mn + izero_hist lhmn = ds_mn + izero_hist
lhmx = ds_mx + izero_hist lhmx = ds_mx + izero_hist
# print( # print(
# f'rt_view_range: {(mn, mx)}\n' # f'rt_view_range: {(mn, mx)}\n'
# f'ds_mn, ds_mx: {(ds_mn, ds_mx)}\n' # f'ds_mn, ds_mx: {(ds_mn, ds_mx)}\n'
# f'lhmn, lhmx: {(lhmn, lhmx)}\n' # f'lhmn, lhmx: {(lhmn, lhmx)}\n'
# ) # )
region.setRegion(( region.setRegion((
lhmn, lhmn,
lhmx, lhmx,
)) ))
# TODO: if we want to have the slow chart adjust range to # TODO: if we want to have the slow chart adjust range to
# match the fast chart's selection -> results in the # match the fast chart's selection -> results in the
# linear region expansion never can go "outside of view". # linear region expansion never can go "outside of view".
# hmn, hmx = hvr = hist_chart.view.state['viewRange'][0] # hmn, hmx = hvr = hist_chart.view.state['viewRange'][0]
# print((hmn, hmx)) # print((hmn, hmx))
# if ( # if (
# hvr # hvr
# and (lhmn < hmn or lhmx > hmx) # and (lhmn < hmn or lhmx > hmx)
# ): # ):
# hist_pi.setXRange( # hist_pi.setXRange(
# lhmn, # lhmn,
# lhmx, # lhmx,
# padding=0, # padding=0,
# ) # )
# hist_linked.graphics_cycle() # hist_linked.graphics_cycle()
# connect region to be updated on plotitem interaction. # connect region to be updated on plotitem interaction.
rt_pi.sigRangeChanged.connect(update_region_from_pi) rt_pi.sigRangeChanged.connect(update_region_from_pi)
@ -1327,12 +1348,11 @@ async def display_symbol_data(
) )
godwidget.resize_all() godwidget.resize_all()
# hist_chart.hide() await link_views_with_region(
# await link_views_with_region( rt_chart,
# rt_chart, hist_chart,
# hist_chart, flume,
# flume, )
# )
# start graphics update loop after receiving first live quote # start graphics update loop after receiving first live quote
ln.start_soon( ln.start_soon(