First draft, group y-minmax transform algo
On overlaid ohlc vizs we compute the largest max/min spread and apply that maxmimum "up and down swing" proportion to each `Viz`'s viewbox in the group. We obviously still need to clip to the shortest x-range so that it doesn't look exactly the same as before XDmultichartz_backup
parent
c20982f6e1
commit
dc8823570a
|
@ -46,6 +46,7 @@ from . import _event
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ._chart import ChartPlotWidget
|
from ._chart import ChartPlotWidget
|
||||||
from ._dataviz import Viz
|
from ._dataviz import Viz
|
||||||
|
# from ._overlay import PlotItemOverlay
|
||||||
|
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
@ -931,11 +932,18 @@ class ChartView(ViewBox):
|
||||||
# graphics (and thus their backing data sets)
|
# graphics (and thus their backing data sets)
|
||||||
# are in the same co-domain and thus can be sorted
|
# are in the same co-domain and thus can be sorted
|
||||||
# as one set per plot.
|
# as one set per plot.
|
||||||
mxmns: dict[
|
mxmns_by_pi: dict[
|
||||||
pg.PlotItem,
|
pg.PlotItem,
|
||||||
tuple[float, float],
|
tuple[float, float],
|
||||||
] = {}
|
] = {}
|
||||||
|
|
||||||
|
# collect certain flows into groups and do a common calc to
|
||||||
|
# determine auto-ranging input for `._set_yrange()`.
|
||||||
|
mxmn_groups: dict[
|
||||||
|
set[Viz],
|
||||||
|
set[Viz, tuple[float, float]],
|
||||||
|
] = {}
|
||||||
|
|
||||||
for name, viz in chart._vizs.items():
|
for name, viz in chart._vizs.items():
|
||||||
if not viz.render:
|
if not viz.render:
|
||||||
# print(f'skipping {flow.name}')
|
# print(f'skipping {flow.name}')
|
||||||
|
@ -957,15 +965,19 @@ class ChartView(ViewBox):
|
||||||
) = out
|
) = out
|
||||||
|
|
||||||
pi = viz.plot
|
pi = viz.plot
|
||||||
mxmn = mxmns.get(pi)
|
mxmn = mxmns_by_pi.get(pi)
|
||||||
if mxmn:
|
if mxmn:
|
||||||
yrange = mxmns[pi] = (
|
yrange = mxmns_by_pi[pi] = (
|
||||||
min(yrange[0], mxmn[0]),
|
min(yrange[0], mxmn[0]),
|
||||||
max(yrange[1], mxmn[1]),
|
max(yrange[1], mxmn[1]),
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
mxmns[viz.plot] = yrange
|
mxmns_by_pi[pi] = yrange
|
||||||
|
|
||||||
|
if viz.is_ohlc:
|
||||||
|
# print(f'adding {viz.name} to overlay')
|
||||||
|
mxmn_groups[viz.name] = out
|
||||||
|
|
||||||
pi.vb._set_yrange(yrange=yrange)
|
pi.vb._set_yrange(yrange=yrange)
|
||||||
profiler(
|
profiler(
|
||||||
|
@ -991,5 +1003,68 @@ class ChartView(ViewBox):
|
||||||
|
|
||||||
profiler(f'autoscaled overlays {chart_name}')
|
profiler(f'autoscaled overlays {chart_name}')
|
||||||
|
|
||||||
profiler(f'<{chart_name}>.update_graphics_from_flow({name})')
|
profiler(f'<{chart_name}>.interact_graphics_cycle({name})')
|
||||||
|
|
||||||
|
# proportional group auto-scaling per overlay set.
|
||||||
|
# -> loop through overlays on each multi-chart widget
|
||||||
|
# and scale all y-ranges based on autoscale config.
|
||||||
|
group_mx: float = 0
|
||||||
|
group_mn: float = 0
|
||||||
|
mx_up_rng: float = 0
|
||||||
|
mn_down_rng: float = 0
|
||||||
|
start_datums: dict[ViewBox, float] = {}
|
||||||
|
|
||||||
|
for viz_name, out in mxmn_groups.items():
|
||||||
|
(
|
||||||
|
ixrng,
|
||||||
|
read_slc,
|
||||||
|
(ymn, ymx),
|
||||||
|
) = out
|
||||||
|
|
||||||
|
# determine start datum in view
|
||||||
|
viz = chart._vizs[viz_name]
|
||||||
|
arr = viz.shm.array
|
||||||
|
row_start = arr[read_slc.start - 1]
|
||||||
|
# row_stop = arr[read_slc.stop - 1]
|
||||||
|
if viz.is_ohlc:
|
||||||
|
y_start = row_start['open']
|
||||||
|
# y_stop = row_stop['close']
|
||||||
|
else:
|
||||||
|
y_start = row_start[viz.name]
|
||||||
|
# y_stop = row_stop[viz.name]
|
||||||
|
|
||||||
|
start_datums[viz.plot.vb] = (viz, y_start)
|
||||||
|
|
||||||
|
# update max for group
|
||||||
|
up_rng = (ymx - y_start) / y_start
|
||||||
|
down_rng = (ymn - y_start) / y_start
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
group_mn = min(group_mn, ymn)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f'{viz.name}@{chart_name} group mxmn calc\n'
|
||||||
|
f'ymn: {ymn}\n'
|
||||||
|
f'ymx: {ymx}\n'
|
||||||
|
f'down %: {mx_up_rng * 100}\n'
|
||||||
|
f'up %: {mn_down_rng * 100}\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
for view, (viz, ystart) in start_datums.items():
|
||||||
|
ymn = ystart * (1 + mn_down_rng)
|
||||||
|
ymx = ystart * (1 + mx_up_rng)
|
||||||
|
print(
|
||||||
|
f'{view.name} APPLY group mxmn\n'
|
||||||
|
f'ystart: {ystart}\n'
|
||||||
|
f'ymn: {ymn}\n'
|
||||||
|
f'ymx: {ymx}\n'
|
||||||
|
)
|
||||||
|
view._set_yrange(yrange=(ymn, ymx))
|
||||||
|
|
||||||
profiler.finish()
|
profiler.finish()
|
||||||
|
|
Loading…
Reference in New Issue