Add first-draft `PlotItemOverlay.group_maxmin()`
Computes the maxmin values for each underlying plot's in-view range as well as the max up/down swing (in percentage terms) from the plot with most dispersion and returns a all these values plus a `dict` of plots to their ranges as part of output.log_linearized_curve_overlays
parent
eb51033b18
commit
223e9d999c
|
@ -22,7 +22,6 @@ from collections import defaultdict
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import (
|
from typing import (
|
||||||
Callable,
|
Callable,
|
||||||
Optional,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from pyqtgraph.graphicsItems.AxisItem import AxisItem
|
from pyqtgraph.graphicsItems.AxisItem import AxisItem
|
||||||
|
@ -246,7 +245,7 @@ class ComposedGridLayout:
|
||||||
plot: PlotItem,
|
plot: PlotItem,
|
||||||
name: str,
|
name: str,
|
||||||
|
|
||||||
) -> Optional[AxisItem]:
|
) -> AxisItem | None:
|
||||||
'''
|
'''
|
||||||
Retrieve the named axis for overlayed ``plot`` or ``None``
|
Retrieve the named axis for overlayed ``plot`` or ``None``
|
||||||
if axis for that name is not shown.
|
if axis for that name is not shown.
|
||||||
|
@ -321,7 +320,7 @@ class PlotItemOverlay:
|
||||||
def add_plotitem(
|
def add_plotitem(
|
||||||
self,
|
self,
|
||||||
plotitem: PlotItem,
|
plotitem: PlotItem,
|
||||||
index: Optional[int] = None,
|
index: int | None = None,
|
||||||
|
|
||||||
# event/signal names which will be broadcasted to all added
|
# event/signal names which will be broadcasted to all added
|
||||||
# (relayee) ``PlotItem``s (eg. ``ViewBox.mouseDragEvent``).
|
# (relayee) ``PlotItem``s (eg. ``ViewBox.mouseDragEvent``).
|
||||||
|
@ -376,7 +375,7 @@ class PlotItemOverlay:
|
||||||
|
|
||||||
# TODO: drop this viewbox specific input and
|
# TODO: drop this viewbox specific input and
|
||||||
# allow a predicate to be passed in by user.
|
# allow a predicate to be passed in by user.
|
||||||
axis: 'Optional[int]' = None,
|
axis: int | None = None,
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
|
||||||
|
@ -578,3 +577,93 @@ class PlotItemOverlay:
|
||||||
|
|
||||||
# '''
|
# '''
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
|
def group_maxmin(
|
||||||
|
self,
|
||||||
|
focus_around: str | None = None,
|
||||||
|
force_min: float | None = None,
|
||||||
|
|
||||||
|
) -> tuple[
|
||||||
|
float, # mn
|
||||||
|
float, # mx
|
||||||
|
float, # max range in % terms of highest sigma plot's y-range
|
||||||
|
PlotItem, # front/selected plot
|
||||||
|
]:
|
||||||
|
'''
|
||||||
|
Overlay "group" maxmin sorting.
|
||||||
|
|
||||||
|
Assumes all named flows are in the same co-domain and thus can
|
||||||
|
be sorted as one set.
|
||||||
|
|
||||||
|
Iterates all the named flows and calls the chart api to find
|
||||||
|
their range values and return.
|
||||||
|
|
||||||
|
TODO: really we should probably have a more built-in API for
|
||||||
|
this?
|
||||||
|
|
||||||
|
'''
|
||||||
|
# TODO:
|
||||||
|
# - use this in the ``.ui._fsp`` mutli-maxmin stuff
|
||||||
|
# -
|
||||||
|
|
||||||
|
# force 0 to always be in view
|
||||||
|
group_mx: float = 0
|
||||||
|
group_mn: float = 0
|
||||||
|
mx_up_rng: float = 0
|
||||||
|
mn_down_rng: float = 0
|
||||||
|
pis2ranges: dict[
|
||||||
|
PlotItem,
|
||||||
|
tuple[float, float],
|
||||||
|
] = {}
|
||||||
|
|
||||||
|
for pi in self.overlays:
|
||||||
|
|
||||||
|
# TODO: can we remove this from the widget
|
||||||
|
# and place somewhere more related to UX/Viz?
|
||||||
|
# name = pi.name
|
||||||
|
# chartw = pi.chart_widget
|
||||||
|
viz = pi.viz
|
||||||
|
# viz = chartw._vizs[name]
|
||||||
|
|
||||||
|
out = viz.maxmin()
|
||||||
|
if out is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
(
|
||||||
|
(x_start, x_stop),
|
||||||
|
read_slc,
|
||||||
|
(ymn, ymx),
|
||||||
|
) = out
|
||||||
|
|
||||||
|
arr = viz.shm.array
|
||||||
|
|
||||||
|
y_start = arr[read_slc.start - 1]
|
||||||
|
y_stop = arr[read_slc.stop - 1]
|
||||||
|
if viz.is_ohlc:
|
||||||
|
y_start = y_start['open']
|
||||||
|
y_stop = y_stop['close']
|
||||||
|
else:
|
||||||
|
y_start = y_start[viz.name]
|
||||||
|
y_stop = y_stop[viz.name]
|
||||||
|
|
||||||
|
# update max for group
|
||||||
|
up_rng = (ymx - y_start) / y_start
|
||||||
|
down_rng = (y_stop - ymn) / y_stop
|
||||||
|
|
||||||
|
# compute directional (up/down) y-range % swing/dispersion
|
||||||
|
mx_up_rng = max(mx_up_rng, up_rng)
|
||||||
|
mn_down_rng = min(mn_down_rng, down_rng)
|
||||||
|
|
||||||
|
pis2ranges[pi] = (ymn, ymx)
|
||||||
|
|
||||||
|
group_mx = max(group_mx, ymx)
|
||||||
|
if force_min is None:
|
||||||
|
group_mn = min(group_mn, ymn)
|
||||||
|
|
||||||
|
return (
|
||||||
|
group_mn if force_min is None else force_min,
|
||||||
|
group_mx,
|
||||||
|
mn_down_rng,
|
||||||
|
mx_up_rng,
|
||||||
|
pis2ranges,
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue