Only set the major curve's range once (per render cycle)
Turns out this is a limitation of the `ViewBox.setYRange()` api: you can't call it more then once and expect anything but the first call to be applied without letting a render cycle run. As such, we wait until the end of the log-linear scaling loop to finally apply the major curves y-mx/mn after all minor curves have been evaluated. This also drops all the debug prints (for now) to get a feel for latency in production mode.multichartz
parent
7f49792a29
commit
5da2f10ff0
|
@ -827,11 +827,11 @@ class ChartView(ViewBox):
|
||||||
# to get different view modes to operate
|
# to get different view modes to operate
|
||||||
# correctly!
|
# correctly!
|
||||||
|
|
||||||
profiler(
|
# print(
|
||||||
f'set limits {self.name}:\n'
|
# f'set limits {self.name}:\n'
|
||||||
f'ylow: {ylow}\n'
|
# f'ylow: {ylow}\n'
|
||||||
f'yhigh: {yhigh}\n'
|
# f'yhigh: {yhigh}\n'
|
||||||
)
|
# )
|
||||||
self.setYRange(
|
self.setYRange(
|
||||||
ylow,
|
ylow,
|
||||||
yhigh,
|
yhigh,
|
||||||
|
@ -841,6 +841,7 @@ class ChartView(ViewBox):
|
||||||
yMin=ylow,
|
yMin=ylow,
|
||||||
yMax=yhigh,
|
yMax=yhigh,
|
||||||
)
|
)
|
||||||
|
self.update()
|
||||||
|
|
||||||
# LOL: yet anothercucking pg buggg..
|
# LOL: yet anothercucking pg buggg..
|
||||||
# can't use `msg=f'setYRange({ylow}, {yhigh}')`
|
# can't use `msg=f'setYRange({ylow}, {yhigh}')`
|
||||||
|
@ -993,7 +994,9 @@ class ChartView(ViewBox):
|
||||||
profiler(f'<{chart_name}>.interact_graphics_cycle({name})')
|
profiler(f'<{chart_name}>.interact_graphics_cycle({name})')
|
||||||
|
|
||||||
# if no overlays, set lone chart's yrange and short circuit
|
# if no overlays, set lone chart's yrange and short circuit
|
||||||
if len(mxmn_groups) < 2:
|
if (
|
||||||
|
len(mxmn_groups) < 2
|
||||||
|
):
|
||||||
viz.plot.vb._set_yrange(
|
viz.plot.vb._set_yrange(
|
||||||
yrange=yrange,
|
yrange=yrange,
|
||||||
)
|
)
|
||||||
|
@ -1024,6 +1027,7 @@ class ChartView(ViewBox):
|
||||||
] = {}
|
] = {}
|
||||||
max_istart: float = 0
|
max_istart: float = 0
|
||||||
major_viz: Viz = None
|
major_viz: Viz = None
|
||||||
|
# major_in_view: np.ndarray = None
|
||||||
|
|
||||||
for viz_name, out in mxmn_groups.items():
|
for viz_name, out in mxmn_groups.items():
|
||||||
(
|
(
|
||||||
|
@ -1072,6 +1076,7 @@ class ChartView(ViewBox):
|
||||||
mx_disp = disp
|
mx_disp = disp
|
||||||
major_mn = ymn
|
major_mn = ymn
|
||||||
major_mx = ymx
|
major_mx = ymx
|
||||||
|
# major_in_view = in_view
|
||||||
|
|
||||||
# compute directional (up/down) y-range % swing/dispersion
|
# compute directional (up/down) y-range % swing/dispersion
|
||||||
y_ref = y_med
|
y_ref = y_med
|
||||||
|
@ -1081,18 +1086,18 @@ class ChartView(ViewBox):
|
||||||
mx_up_rng = max(mx_up_rng, up_rng)
|
mx_up_rng = max(mx_up_rng, up_rng)
|
||||||
mn_down_rng = min(mn_down_rng, down_rng)
|
mn_down_rng = min(mn_down_rng, down_rng)
|
||||||
|
|
||||||
print(
|
# print(
|
||||||
f'{viz.name}@{chart_name} group mxmn calc\n'
|
# f'{viz.name}@{chart_name} group mxmn calc\n'
|
||||||
'--------------------\n'
|
# '--------------------\n'
|
||||||
f'y_start: {y_start}\n'
|
# f'y_start: {y_start}\n'
|
||||||
f'ymn: {ymn}\n'
|
# f'ymn: {ymn}\n'
|
||||||
f'ymx: {ymx}\n'
|
# f'ymx: {ymx}\n'
|
||||||
f'mx_disp: {mx_disp}\n'
|
# f'mx_disp: {mx_disp}\n'
|
||||||
f'up %: {up_rng * 100}\n'
|
# f'up %: {up_rng * 100}\n'
|
||||||
f'down %: {down_rng * 100}\n'
|
# f'down %: {down_rng * 100}\n'
|
||||||
f'mx up %: {mx_up_rng * 100}\n'
|
# f'mx up %: {mx_up_rng * 100}\n'
|
||||||
f'mn down %: {mn_down_rng * 100}\n'
|
# f'mn down %: {mn_down_rng * 100}\n'
|
||||||
)
|
# )
|
||||||
|
|
||||||
for (
|
for (
|
||||||
view,
|
view,
|
||||||
|
@ -1113,6 +1118,14 @@ class ChartView(ViewBox):
|
||||||
if viz is major_viz:
|
if viz is major_viz:
|
||||||
ymn = y_min
|
ymn = y_min
|
||||||
ymx = y_max
|
ymx = y_max
|
||||||
|
# print(
|
||||||
|
# f'{view.name} MAJOR mxmn\n'
|
||||||
|
# '--------------------\n'
|
||||||
|
# f'scaled ymn: {ymn}\n'
|
||||||
|
# f'scaled ymx: {ymx}\n'
|
||||||
|
# f'scaled mx_disp: {mx_disp}\n'
|
||||||
|
# )
|
||||||
|
continue
|
||||||
|
|
||||||
else:
|
else:
|
||||||
key = 'open' if viz.is_ohlc else viz.name
|
key = 'open' if viz.is_ohlc else viz.name
|
||||||
|
@ -1129,11 +1142,11 @@ class ChartView(ViewBox):
|
||||||
# y-range based on the major curves y-range.
|
# y-range based on the major curves y-range.
|
||||||
|
|
||||||
# get intersection point y-values for both curves
|
# get intersection point y-values for both curves
|
||||||
# abs_i_start = max_istart
|
|
||||||
|
|
||||||
mshm = major_viz.shm
|
mshm = major_viz.shm
|
||||||
|
|
||||||
minor_i_start = minor_in_view[0]['index']
|
minor_i_start = minor_in_view[0]['index']
|
||||||
major_i_start = mshm.array['index'][0],
|
major_i_start = mshm.array['index'][0]
|
||||||
|
|
||||||
abs_i_start = max(
|
abs_i_start = max(
|
||||||
minor_i_start,
|
minor_i_start,
|
||||||
major_i_start,
|
major_i_start,
|
||||||
|
@ -1169,53 +1182,75 @@ class ChartView(ViewBox):
|
||||||
# is side (up/down) specific.
|
# is side (up/down) specific.
|
||||||
new_maj_mxmn: None | tuple[float, float] = None
|
new_maj_mxmn: None | tuple[float, float] = None
|
||||||
if y_max > ymx:
|
if y_max > ymx:
|
||||||
|
|
||||||
y_ref = y_minor_intersect
|
y_ref = y_minor_intersect
|
||||||
r_up_minor = (y_max - y_ref) / y_ref
|
r_up_minor = (y_max - y_ref) / y_ref
|
||||||
new_maj_ymx = y_maj_intersect * (1 + r_up_minor)
|
|
||||||
|
# y_maj_ref = max(
|
||||||
|
# major_in_view[0][key],
|
||||||
|
# y_maj_intersect,
|
||||||
|
# )
|
||||||
|
y_maj_ref = y_maj_intersect
|
||||||
|
new_maj_ymx = y_maj_ref * (1 + r_up_minor)
|
||||||
new_maj_mxmn = (major_mn, new_maj_ymx)
|
new_maj_mxmn = (major_mn, new_maj_ymx)
|
||||||
print(
|
# print(
|
||||||
f'{view.name} OUT OF RANGE:\n'
|
# f'{view.name} OUT OF RANGE:\n'
|
||||||
'--------------------\n'
|
# '--------------------\n'
|
||||||
f'y_max:{y_max} > ymx:{ymx}\n'
|
# f'y_max:{y_max} > ymx:{ymx}\n'
|
||||||
f'RESCALE MAJOR {major_viz.name}:\n'
|
# )
|
||||||
f'{new_maj_mxmn}\n'
|
|
||||||
)
|
|
||||||
ymx = y_max
|
ymx = y_max
|
||||||
|
|
||||||
if y_min < ymn:
|
if y_min < ymn:
|
||||||
|
|
||||||
y_ref = y_minor_intersect
|
y_ref = y_minor_intersect
|
||||||
r_down_minor = (y_min - y_ref) / y_ref
|
r_down_minor = (y_min - y_ref) / y_ref
|
||||||
new_maj_ymn = y_maj_intersect * (1 + r_down_minor)
|
|
||||||
|
# y_maj_ref = min(
|
||||||
|
# major_in_view[0][key],
|
||||||
|
# y_maj_intersect,
|
||||||
|
# )
|
||||||
|
y_maj_ref = y_maj_intersect
|
||||||
|
new_maj_ymn = y_maj_ref * (1 + r_down_minor)
|
||||||
new_maj_mxmn = (
|
new_maj_mxmn = (
|
||||||
new_maj_ymn,
|
new_maj_ymn,
|
||||||
new_maj_mxmn[1] if new_maj_mxmn else major_mx
|
new_maj_mxmn[1] if new_maj_mxmn else major_mx
|
||||||
)
|
)
|
||||||
print(
|
# print(
|
||||||
f'{view.name} OUT OF RANGE:\n'
|
# f'{view.name} OUT OF RANGE:\n'
|
||||||
'--------------------\n'
|
# '--------------------\n'
|
||||||
f'y_min:{y_min} < ymn:{ymn}\n'
|
# f'y_min:{y_min} < ymn:{ymn}\n'
|
||||||
f'RESCALE MAJOR {major_viz.name}:\n'
|
# )
|
||||||
f'{new_maj_mxmn}\n'
|
|
||||||
)
|
|
||||||
ymn = y_min
|
ymn = y_min
|
||||||
|
|
||||||
if new_maj_mxmn:
|
# now scale opposite side to compensate
|
||||||
major_mx, major_mn = new_maj_mxmn
|
# y_ref = y_major_intersect
|
||||||
major_viz.plot.vb._set_yrange(
|
# r_down_minor = (major_ - y_ref) / y_ref
|
||||||
yrange=new_maj_mxmn,
|
|
||||||
# range_margin=None,
|
|
||||||
)
|
|
||||||
|
|
||||||
print(
|
if new_maj_mxmn:
|
||||||
f'{view.name} APPLY group mxmn\n'
|
# print(
|
||||||
'--------------------\n'
|
# f'RESCALE MAJOR {major_viz.name}:\n'
|
||||||
f'minor_y_start: {minor_y_start}\n'
|
# f'previous: {(major_mn, major_mx)}\n'
|
||||||
f'mn_down_rng: {mn_down_rng * 100}\n'
|
# f'new: {new_maj_mxmn}\n'
|
||||||
f'mx_up_rng: {mx_up_rng * 100}\n'
|
# )
|
||||||
f'scaled ymn: {ymn}\n'
|
# major_viz.plot.vb._set_yrange(
|
||||||
f'scaled ymx: {ymx}\n'
|
# yrange=new_maj_mxmn,
|
||||||
f'scaled mx_disp: {mx_disp}\n'
|
# # range_margin=None,
|
||||||
)
|
# )
|
||||||
|
major_mn, major_mx = new_maj_mxmn
|
||||||
|
# vrs = major_viz.plot.vb.viewRange()
|
||||||
|
# if vrs[1][0] > new_maj_mxmn[0]:
|
||||||
|
# breakpoint()
|
||||||
|
|
||||||
|
# print(
|
||||||
|
# f'{view.name} APPLY group mxmn\n'
|
||||||
|
# '--------------------\n'
|
||||||
|
# f'minor_y_start: {minor_y_start}\n'
|
||||||
|
# f'mn_down_rng: {mn_down_rng * 100}\n'
|
||||||
|
# f'mx_up_rng: {mx_up_rng * 100}\n'
|
||||||
|
# f'scaled ymn: {ymn}\n'
|
||||||
|
# f'scaled ymx: {ymx}\n'
|
||||||
|
# f'scaled mx_disp: {mx_disp}\n'
|
||||||
|
# )
|
||||||
|
|
||||||
if (
|
if (
|
||||||
math.isinf(ymx)
|
math.isinf(ymx)
|
||||||
|
@ -1227,4 +1262,22 @@ class ChartView(ViewBox):
|
||||||
yrange=(ymn, ymx),
|
yrange=(ymn, ymx),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# NOTE XXX: we have to set the major curve's range once (and
|
||||||
|
# only once) here since we're doing this entire routine
|
||||||
|
# inside of a single render cycle (and apparently calling
|
||||||
|
# `ViewBox.setYRange()` multiple times within one only takes
|
||||||
|
# the first call as serious...) XD
|
||||||
|
# print(
|
||||||
|
# f'Scale MAJOR {major_viz.name}:\n'
|
||||||
|
# f'previous: {(major_mn, major_mx)}\n'
|
||||||
|
# f'new: {new_maj_mxmn}\n'
|
||||||
|
# )
|
||||||
|
major_viz.plot.vb._set_yrange(
|
||||||
|
yrange=(major_mn, major_mx),
|
||||||
|
)
|
||||||
|
# major_mx, major_mn = new_maj_mxmn
|
||||||
|
# vrs = major_viz.plot.vb.viewRange()
|
||||||
|
# if vrs[1][0] > major_mn:
|
||||||
|
# breakpoint()
|
||||||
|
|
||||||
profiler.finish()
|
profiler.finish()
|
||||||
|
|
Loading…
Reference in New Issue