Only `.maybe_downsample_graphics()` on manual changes

We don't need update graphics on every x-range change since that's what
the display loop does. Instead, only on manual changes do we make manual
calls into `.update_graphics_from_array()` and be sure to iterate all
linked subplots and all their embedded graphics.
big_data_lines
Tyler Goodlet 2022-04-06 11:11:28 -04:00
parent 1a95712680
commit b5f2558cec
1 changed files with 55 additions and 41 deletions

View File

@ -360,6 +360,7 @@ class ChartView(ViewBox):
): ):
super().__init__( super().__init__(
parent=parent, parent=parent,
name=name,
# TODO: look into the default view padding # TODO: look into the default view padding
# support that might replace somem of our # support that might replace somem of our
# ``ChartPlotWidget._set_yrange()` # ``ChartPlotWidget._set_yrange()`
@ -742,6 +743,11 @@ class ChartView(ViewBox):
data set. data set.
''' '''
profiler = pg.debug.Profiler(
disabled=not pg_profile_enabled(),
gt=ms_slower_then,
delayed=True,
)
set_range = True set_range = True
chart = self._chart chart = self._chart
@ -769,9 +775,11 @@ class ChartView(ViewBox):
# Make sure min bars/datums on screen is adhered. # Make sure min bars/datums on screen is adhered.
else: else:
br = bars_range or chart.bars_range() br = bars_range or chart.bars_range()
profiler(f'got bars range: {br}')
# TODO: maybe should be a method on the # TODO: maybe should be a method on the
# chart widget/item? # chart widget/item?
# if False:
if autoscale_linked_plots: if autoscale_linked_plots:
# avoid recursion by sibling plots # avoid recursion by sibling plots
linked = self.linkedsplits linked = self.linkedsplits
@ -786,6 +794,7 @@ class ChartView(ViewBox):
bars_range=br, bars_range=br,
autoscale_linked_plots=False, autoscale_linked_plots=False,
) )
profiler('autoscaled linked plots')
if set_range: if set_range:
@ -795,6 +804,8 @@ class ChartView(ViewBox):
ylow, yhigh = yrange ylow, yhigh = yrange
profiler(f'maxmin(): {yrange}')
# view margins: stay within a % of the "true range" # view margins: stay within a % of the "true range"
diff = yhigh - ylow diff = yhigh - ylow
ylow = ylow - (diff * range_margin) ylow = ylow - (diff * range_margin)
@ -808,6 +819,7 @@ class ChartView(ViewBox):
yMax=yhigh, yMax=yhigh,
) )
self.setYRange(ylow, yhigh) self.setYRange(ylow, yhigh)
profiler(f'set limits: {(ylow, yhigh)}')
def enable_auto_yrange( def enable_auto_yrange(
self, self,
@ -830,7 +842,9 @@ class ChartView(ViewBox):
# iterate those. # iterate those.
# - only register this when certain downsampleable graphics are # - only register this when certain downsampleable graphics are
# "added to scene". # "added to scene".
src_vb.sigXRangeChanged.connect(self.maybe_downsample_graphics) src_vb.sigRangeChangedManually.connect(
self.maybe_downsample_graphics
)
# mouse wheel doesn't emit XRangeChanged # mouse wheel doesn't emit XRangeChanged
src_vb.sigRangeChangedManually.connect(self._set_yrange) src_vb.sigRangeChangedManually.connect(self._set_yrange)
@ -844,25 +858,39 @@ class ChartView(ViewBox):
self._chart._static_yrange = 'axis' self._chart._static_yrange = 'axis'
def xs_in_px(self) -> float: def x_uppx(self) -> float:
''' '''
Return the "number of x units" within a single Return the "number of x units" within a single
pixel currently being displayed for relevant pixel currently being displayed for relevant
graphics items which are our children. graphics items which are our children.
''' '''
for graphic in self._chart._graphics.values(): graphics = list(self._chart._graphics.values())
xvec = graphic.pixelVectors()[0] if not graphics:
if xvec: return 0
xpx = xvec.x()
if xpx: graphic = graphics[0]
return xpx xvec = graphic.pixelVectors()[0]
else: if xvec:
continue return xvec.x()
return 1.0 else:
return 0
def maybe_downsample_graphics(self): def maybe_downsample_graphics(self):
uppx = self.x_uppx()
if (
# we probably want to drop this once we are "drawing in
# view" for downsampled flows..
uppx and uppx > 16
and self._ic is not None
):
# don't bother updating since we're zoomed out bigly and
# in a pan-interaction, in which case we shouldn't be
# doing view-range based rendering (at least not yet).
# print(f'{uppx} exiting early!')
return
profiler = pg.debug.Profiler( profiler = pg.debug.Profiler(
disabled=not pg_profile_enabled(), disabled=not pg_profile_enabled(),
gt=3, gt=3,
@ -871,37 +899,23 @@ class ChartView(ViewBox):
# TODO: a faster single-loop-iterator way of doing this XD # TODO: a faster single-loop-iterator way of doing this XD
chart = self._chart chart = self._chart
linked = self.linkedsplits
plots = linked.subplots | {chart.name: chart}
for chart_name, chart in plots.items():
for name, graphics in chart._graphics.items():
# print(f'maybe ds chart:{name} graphic:{name}')
for name, graphics in chart._graphics.items(): use_vr = False
if isinstance(graphics, BarItems):
use_vr = True
# TODO: make it so we don't have to do this XD # pass in no array which will read and render from the last
# if name == 'volume': # passed array (normally provided by the display loop.)
# continue chart.update_graphics_from_array(
uppx = graphics.x_uppx() name,
if ( use_vr=use_vr,
uppx and uppx > 16 profiler=profiler,
and self._ic is not None )
): profiler(f'range change updated {chart_name}:{name}')
# don't bother updating since we're zoomed out bigly and
# in a pan-interaction, in which case we shouldn't be
# doing view-range based rendering (at least not yet).
# print(f'{uppx} exiting early!')
return
use_vr = False
if isinstance(graphics, BarItems):
use_vr = True
# pass in no array which will read and render from the last
# passed array (normally provided by the display loop.)
chart.update_graphics_from_array(
name,
use_vr=use_vr,
)
profiler(f'updated {name}')
profiler.finish() profiler.finish()
# for graphic in graphics:
# ds_meth = getattr(graphic, 'maybe_downsample', None)
# if ds_meth:
# ds_meth()