Clean up cross-curve intersect point indexing
When there are `N`-curves we need to consider the smallest x-data-support subset when figuring out for each major-minor pair such that the "shorter" series is always returns aligned to the longer one. This makes the var naming more explicit with `major/minor_i_start` as well as clarifies more stringently a bunch of other variables and explicitly uses the `minor_y_intersect` y value in the scaling transform calcs. Also fixes some debug prints.multichartz
parent
0cdb065222
commit
b9f3546d2f
|
@ -930,17 +930,20 @@ class ChartView(ViewBox):
|
|||
|
||||
for chart_name, chart in plots.items():
|
||||
|
||||
# Viz "group" maxmins table; presumes that some path
|
||||
# graphics (and thus their backing data sets)
|
||||
# are in the same co-domain and thus can be sorted
|
||||
# as one set per plot.
|
||||
mxmns_by_pi: dict[
|
||||
# Common `PlotItem` maxmin table; presumes that some path
|
||||
# graphics (and thus their backing data sets) are in the
|
||||
# same co-domain and view box (since the were added
|
||||
# a separate graphics objects to a common plot) and thus can
|
||||
# be sorted as one set per plot.
|
||||
mxmns_by_common_pi: dict[
|
||||
pg.PlotItem,
|
||||
tuple[float, float],
|
||||
] = {}
|
||||
|
||||
# collect certain flows into groups and do a common calc to
|
||||
# collect certain flows have grapics objects **in seperate
|
||||
# plots/viewboxes** into groups and do a common calc to
|
||||
# determine auto-ranging input for `._set_yrange()`.
|
||||
# this is primarly used for our so called "log-linearized
|
||||
mxmn_groups: dict[
|
||||
set[Viz],
|
||||
set[Viz, tuple[float, float]],
|
||||
|
@ -967,15 +970,15 @@ class ChartView(ViewBox):
|
|||
) = out
|
||||
|
||||
pi = viz.plot
|
||||
mxmn = mxmns_by_pi.get(pi)
|
||||
mxmn = mxmns_by_common_pi.get(pi)
|
||||
if mxmn:
|
||||
yrange = mxmns_by_pi[pi] = (
|
||||
yrange = mxmns_by_common_pi[pi] = (
|
||||
min(yrange[0], mxmn[0]),
|
||||
max(yrange[1], mxmn[1]),
|
||||
)
|
||||
|
||||
else:
|
||||
mxmns_by_pi[pi] = yrange
|
||||
mxmns_by_common_pi[pi] = yrange
|
||||
|
||||
if viz.is_ohlc:
|
||||
# print(f'adding {viz.name} to overlay')
|
||||
|
@ -1019,7 +1022,7 @@ class ChartView(ViewBox):
|
|||
np.ndarray, # in-view array
|
||||
],
|
||||
] = {}
|
||||
max_start: float = 0
|
||||
max_istart: float = 0
|
||||
major_viz: Viz = None
|
||||
|
||||
for viz_name, out in mxmn_groups.items():
|
||||
|
@ -1029,15 +1032,13 @@ class ChartView(ViewBox):
|
|||
(ymn, ymx),
|
||||
) = out
|
||||
|
||||
x_start = ixrng[0]
|
||||
max_start = max(x_start, max_start)
|
||||
|
||||
# determine start datum in view
|
||||
viz = chart._vizs[viz_name]
|
||||
arr = viz.shm.array
|
||||
in_view = arr[read_slc]
|
||||
row_start = arr[read_slc.start - 1]
|
||||
# row_stop = arr[read_slc.stop - 1]
|
||||
|
||||
max_istart = max(in_view[0]['index'], max_istart)
|
||||
|
||||
if viz.is_ohlc:
|
||||
y_med = np.median(in_view['close'])
|
||||
|
@ -1045,11 +1046,12 @@ class ChartView(ViewBox):
|
|||
else:
|
||||
y_med = np.median(in_view[viz.name])
|
||||
y_start = row_start[viz.name]
|
||||
# y_stop = row_stop[viz.name]
|
||||
|
||||
print(
|
||||
f'{viz.name} -> (x_start: {x_start}, y_start: {y_start}\n'
|
||||
)
|
||||
# x_start = ixrng[0]
|
||||
# print(
|
||||
# f'{viz.name} ->\n'
|
||||
# f'(x_start: {x_start}, y_start: {y_start}\n'
|
||||
# )
|
||||
start_datums[viz.plot.vb] = (
|
||||
viz,
|
||||
y_start,
|
||||
|
@ -1080,17 +1082,14 @@ class ChartView(ViewBox):
|
|||
mn_down_rng = min(mn_down_rng, down_rng)
|
||||
|
||||
print(
|
||||
'####################\n'
|
||||
f'{viz.name}@{chart_name} group mxmn calc\n'
|
||||
'--------------------\nn'
|
||||
'--------------------\n'
|
||||
f'y_start: {y_start}\n'
|
||||
f'ymn: {ymn}\n'
|
||||
f'ymx: {ymx}\n'
|
||||
f'mx_disp: {mx_disp}\n'
|
||||
'####################\n'
|
||||
f'up %: {up_rng * 100}\n'
|
||||
f'down %: {down_rng * 100}\n'
|
||||
'####################\n'
|
||||
f'mx up %: {mx_up_rng * 100}\n'
|
||||
f'mn down %: {mn_down_rng * 100}\n'
|
||||
)
|
||||
|
@ -1128,28 +1127,39 @@ class ChartView(ViewBox):
|
|||
# that the intersecting y-value is used as the
|
||||
# reference point for scaling minor curve's
|
||||
# y-range based on the major curves y-range.
|
||||
abs_ifirst = minor_in_view[0]['index']
|
||||
mshm = major_viz.shm
|
||||
abs_i_start = max(
|
||||
abs_ifirst,
|
||||
mshm.array['index'][0],
|
||||
)
|
||||
|
||||
# get intersection point y-values for both curves
|
||||
# abs_i_start = max_istart
|
||||
|
||||
mshm = major_viz.shm
|
||||
minor_i_start = minor_in_view[0]['index']
|
||||
major_i_start = mshm.array['index'][0],
|
||||
abs_i_start = max(
|
||||
minor_i_start,
|
||||
major_i_start,
|
||||
)
|
||||
|
||||
y_maj_intersect = mshm._array[abs_i_start][key]
|
||||
y_min_intersect = minor_in_view[abs_i_start - abs_ifirst]
|
||||
y_minor_intersect = viz.shm._array[abs_i_start][key]
|
||||
|
||||
# TODO: probably write this as a compile cpython or
|
||||
# numba func.
|
||||
|
||||
# if abs_i_start > major_i_start:
|
||||
|
||||
# compute directional (up/down) y-range
|
||||
# % swing/dispersion starting at the reference index
|
||||
# determined by the above indexing arithmetic.
|
||||
y_ref = y_maj_intersect
|
||||
assert y_ref
|
||||
if not y_ref:
|
||||
breakpoint()
|
||||
|
||||
r_up = (major_mx - y_ref) / y_ref
|
||||
r_down = (major_mn - y_ref) / y_ref
|
||||
ymn = y_start * (1 + r_down)
|
||||
ymx = y_start * (1 + r_up)
|
||||
|
||||
minor_y_start = y_minor_intersect
|
||||
ymn = minor_y_start * (1 + r_down)
|
||||
ymx = minor_y_start * (1 + r_up)
|
||||
|
||||
# XXX: handle out of view cases where minor curve
|
||||
# now is outside the range of the major curve. in
|
||||
|
@ -1159,42 +1169,47 @@ class ChartView(ViewBox):
|
|||
# is side (up/down) specific.
|
||||
new_maj_mxmn: None | tuple[float, float] = None
|
||||
if y_max > ymx:
|
||||
y_ref = y_min_intersect[key]
|
||||
y_ref = y_minor_intersect
|
||||
r_up_minor = (y_max - y_ref) / y_ref
|
||||
new_maj_ymx = y_maj_intersect * (1 + r_up_minor)
|
||||
new_maj_mxmn = (major_mn, new_maj_ymx)
|
||||
ymx = y_max
|
||||
|
||||
print(
|
||||
f'{view.name} OUT OF RANGE:\n'
|
||||
f'MAJOR is {major_viz.name}\n'
|
||||
'--------------------\n'
|
||||
f'y_max:{y_max} > ymx:{ymx}\n'
|
||||
f'RESCALE MAJOR {major_viz.name}:\n'
|
||||
f'{new_maj_mxmn}\n'
|
||||
)
|
||||
ymx = y_max
|
||||
|
||||
if y_min < ymn:
|
||||
y_ref = y_min_intersect[key]
|
||||
y_ref = y_minor_intersect
|
||||
r_down_minor = (y_min - y_ref) / y_ref
|
||||
new_maj_ymn = y_maj_intersect * (1 + r_down_minor)
|
||||
new_maj_mxmn = (
|
||||
new_maj_ymn,
|
||||
new_maj_ymx[1] if new_maj_mxmn else major_mx
|
||||
new_maj_mxmn[1] if new_maj_mxmn else major_mx
|
||||
)
|
||||
print(
|
||||
f'{view.name} OUT OF RANGE:\n'
|
||||
'--------------------\n'
|
||||
f'y_min:{y_min} < ymn:{ymn}\n'
|
||||
f'RESCALE MAJOR {major_viz.name}:\n'
|
||||
f'{new_maj_mxmn}\n'
|
||||
)
|
||||
ymn = y_min
|
||||
|
||||
print(
|
||||
f'{view.name} OUT OF RANGE:\n'
|
||||
f'MAJOR is {major_viz.name}\n'
|
||||
f'y_min:{y_min} < ymn:{ymn}\n'
|
||||
)
|
||||
|
||||
if new_maj_mxmn:
|
||||
major_mx, major_mn = new_maj_mxmn
|
||||
major_viz.plot.vb._set_yrange(
|
||||
yrange=new_maj_mxmn,
|
||||
# range_margin=None,
|
||||
)
|
||||
|
||||
print(
|
||||
f'{view.name} APPLY group mxmn\n'
|
||||
f'y_start: {y_start}\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'
|
||||
|
|
Loading…
Reference in New Issue