Handle "target-is-shorter-then-pinned" case
When the target pinning curve (by default, the dispersion major) is shorter then the pinned curve, we need to make sure we find still find the x-intersect for computing returns scalars! Use `Viz.i_from_t()` to accomplish this as well and, augment that method with a `return_y: bool` to allow the caller to also retrieve the equivalent y-value at the requested input time `t: float` for convenience. Also tweak a few more internals around the 'loglin_ref_to_curve' method: - only solve / adjust for the above case when the major's xref is detected as being "earlier" in time the current minor's. - pop the major viz entry from the overlay table ahead of time to avoid a needless iteration and simplify the transform calc phase loop to avoid handling that needless cycle B) - add much better "organized" debug printing with more clear headers around which "phase"/loop the message pertains and well as more explicit details in terms of x and y-range values on each cycle of each loop.log_linearized_curve_overlays
parent
4bb580ae60
commit
51f3733487
|
@ -26,6 +26,7 @@ from typing import (
|
||||||
)
|
)
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import pendulum
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
|
||||||
from ..data.types import Struct
|
from ..data.types import Struct
|
||||||
|
@ -247,10 +248,11 @@ def overlay_viewlists(
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if debug_print:
|
if debug_print:
|
||||||
|
divstr = '#'*46
|
||||||
print(
|
print(
|
||||||
f'BEGIN UX GRAPHICS CYCLE: @{chart_name}\n'
|
f'BEGIN UX GRAPHICS CYCLE: @{chart_name}\n'
|
||||||
+
|
+
|
||||||
'#'*66
|
divstr
|
||||||
+
|
+
|
||||||
'\n'
|
'\n'
|
||||||
)
|
)
|
||||||
|
@ -353,11 +355,16 @@ def overlay_viewlists(
|
||||||
disp = r_up - r_down
|
disp = r_up - r_down
|
||||||
|
|
||||||
msg = (
|
msg = (
|
||||||
f'=> {viz.name}@{chart_name}\n'
|
f'Viz[{viz.name}][{key}]: @{chart_name}\n'
|
||||||
|
f' .yrange = {viz.vs.yrange}\n'
|
||||||
|
f' .xrange = {viz.vs.xrange}\n\n'
|
||||||
|
f'start_t: {start_t}\n'
|
||||||
f'y_ref: {y_ref}\n'
|
f'y_ref: {y_ref}\n'
|
||||||
f'down disp: {r_down}\n'
|
f'ymn: {ymn}\n'
|
||||||
f'up disp: {r_up}\n'
|
f'ymx: {ymx}\n'
|
||||||
f'full disp: {disp}\n'
|
f'r_up disp: {r_up}\n'
|
||||||
|
f'r_down: {r_down}\n'
|
||||||
|
f'(full) disp: {disp}\n'
|
||||||
)
|
)
|
||||||
profiler(msg)
|
profiler(msg)
|
||||||
if debug_print:
|
if debug_print:
|
||||||
|
@ -378,10 +385,7 @@ def overlay_viewlists(
|
||||||
dnt.start_t = in_view[0]['time']
|
dnt.start_t = in_view[0]['time']
|
||||||
dnt.y_val = ymn
|
dnt.y_val = ymn
|
||||||
|
|
||||||
msg = f'NEW DOWN: {viz.name}@{chart_name} r: {r_down}'
|
profiler(f'NEW DOWN: {viz.name}@{chart_name} r: {r_down}')
|
||||||
profiler(msg)
|
|
||||||
if debug_print:
|
|
||||||
print(msg)
|
|
||||||
else:
|
else:
|
||||||
# minor in the down swing range so check that if
|
# minor in the down swing range so check that if
|
||||||
# we apply the current rng to the minor that it
|
# we apply the current rng to the minor that it
|
||||||
|
@ -439,10 +443,7 @@ def overlay_viewlists(
|
||||||
upt.in_view = in_view
|
upt.in_view = in_view
|
||||||
upt.start_t = in_view[0]['time']
|
upt.start_t = in_view[0]['time']
|
||||||
upt.y_val = ymx
|
upt.y_val = ymx
|
||||||
msg = f'NEW UP: {viz.name}@{chart_name} r: {r_up}'
|
profiler(f'NEW UP: {viz.name}@{chart_name} r: {r_up}')
|
||||||
profiler(msg)
|
|
||||||
if debug_print:
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
intersect = intersect_from_longer(
|
intersect = intersect_from_longer(
|
||||||
|
@ -535,21 +536,32 @@ def overlay_viewlists(
|
||||||
# no overlay transforming is needed.
|
# no overlay transforming is needed.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
profiler('`Viz` curve first pass complete\n')
|
profiler('`Viz` curve (first) scan phase complete\n')
|
||||||
|
|
||||||
if debug_print:
|
|
||||||
# print overlay table in descending dispersion order
|
|
||||||
msg = 'overlays by disp:\n'
|
|
||||||
for disp in reversed(overlay_table):
|
|
||||||
entry = overlay_table[disp]
|
|
||||||
msg += f'{entry[1].name}: {disp}\n'
|
|
||||||
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
r_up_mx: float
|
r_up_mx: float
|
||||||
r_dn_mn: float
|
r_dn_mn: float
|
||||||
mx_disp = max(overlay_table)
|
mx_disp = max(overlay_table)
|
||||||
|
|
||||||
|
if debug_print:
|
||||||
|
# print overlay table in descending dispersion order
|
||||||
|
msg = 'overlays in dispersion order:\n'
|
||||||
|
for i, disp in enumerate(reversed(overlay_table)):
|
||||||
|
entry = overlay_table[disp]
|
||||||
|
msg += f' [{i}] {disp}: {entry[1].name}\n'
|
||||||
|
|
||||||
|
print(
|
||||||
|
'TRANSFORM PHASE' + '-'*100 + '\n\n'
|
||||||
|
+
|
||||||
|
msg
|
||||||
|
)
|
||||||
|
|
||||||
|
if method == 'loglin_ref_to_curve':
|
||||||
|
mx_entry = overlay_table.pop(mx_disp)
|
||||||
|
else:
|
||||||
|
# TODO: for pin to first-in-view we need to no pop this from the
|
||||||
|
# table, but can we simplify below code even more?
|
||||||
mx_entry = overlay_table[mx_disp]
|
mx_entry = overlay_table[mx_disp]
|
||||||
|
|
||||||
(
|
(
|
||||||
mx_view, # viewbox
|
mx_view, # viewbox
|
||||||
mx_viz, # viz
|
mx_viz, # viz
|
||||||
|
@ -557,19 +569,28 @@ def overlay_viewlists(
|
||||||
mx_ymn,
|
mx_ymn,
|
||||||
mx_ymx,
|
mx_ymx,
|
||||||
_, # read_slc
|
_, # read_slc
|
||||||
_, # in_view array
|
mx_in_view, # in_view array
|
||||||
r_up_mx,
|
r_up_mx,
|
||||||
r_dn_mn,
|
r_dn_mn,
|
||||||
) = mx_entry
|
) = mx_entry
|
||||||
|
mx_time = mx_in_view['time']
|
||||||
|
mx_xref = mx_time[0]
|
||||||
|
|
||||||
|
# conduct "log-linearized multi-plot" range transform
|
||||||
|
# calculations for curves detected as overlays in the previous
|
||||||
|
# loop:
|
||||||
|
# -> iterate all curves Ci in dispersion-measure sorted order
|
||||||
|
# going from smallest swing to largest via the
|
||||||
|
# ``overlay_table: dict``,
|
||||||
|
# -> match on overlay ``method: str`` provided by caller,
|
||||||
|
# -> calc y-ranges from each curve's time series and store in
|
||||||
|
# a final table ``scaled: dict`` for final application in the
|
||||||
|
# scaling loop; the final phase.
|
||||||
scaled: dict[
|
scaled: dict[
|
||||||
float,
|
float,
|
||||||
tuple[Viz, float, float, float, float]
|
tuple[Viz, float, float, float, float]
|
||||||
] = {}
|
] = {}
|
||||||
|
|
||||||
# conduct "log-linearized multi-plot" scalings for all groups
|
|
||||||
# -> iterate all curves Ci in dispersion-measure sorted order
|
|
||||||
# going from smallest swing to largest.
|
|
||||||
for full_disp in reversed(overlay_table):
|
for full_disp in reversed(overlay_table):
|
||||||
(
|
(
|
||||||
view,
|
view,
|
||||||
|
@ -601,21 +622,55 @@ def overlay_viewlists(
|
||||||
# scaling to all curves, including the major-target,
|
# scaling to all curves, including the major-target,
|
||||||
# which were previously scaled before.
|
# which were previously scaled before.
|
||||||
case 'loglin_ref_to_curve':
|
case 'loglin_ref_to_curve':
|
||||||
if viz is not mx_viz:
|
|
||||||
|
|
||||||
# calculate y-range scalars from the earliest
|
# calculate y-range scalars from the earliest
|
||||||
# "intersect" datum with the target-major
|
# "intersect" datum with the target-major
|
||||||
# (dispersion) curve so as to "pin" the curves
|
# (dispersion) curve so as to "pin" the curves
|
||||||
# in the y-domain at that spot.
|
# in the y-domain at that spot.
|
||||||
|
# NOTE: there are 2 cases for un-matched support
|
||||||
|
# in x-domain (where one series is shorter then the
|
||||||
|
# other):
|
||||||
|
# => major is longer then minor:
|
||||||
|
# - need to scale the minor *from* the first
|
||||||
|
# supported datum in both series.
|
||||||
|
#
|
||||||
|
# => major is shorter then minor:
|
||||||
|
# - need to scale the minor *from* the first
|
||||||
|
# supported datum in both series (the
|
||||||
|
# intersect x-value) but using the
|
||||||
|
# intersecting point from the minor **not**
|
||||||
|
# its first value in view!
|
||||||
|
yref = y_start
|
||||||
|
|
||||||
|
if mx_xref > xref:
|
||||||
|
(
|
||||||
|
xref_pin,
|
||||||
|
yref,
|
||||||
|
) = viz.i_from_t(
|
||||||
|
mx_xref,
|
||||||
|
return_y=True,
|
||||||
|
)
|
||||||
|
xref_pin_dt = pendulum.from_timestamp(xref_pin)
|
||||||
|
xref = mx_xref
|
||||||
|
|
||||||
|
if debug_print:
|
||||||
|
print(
|
||||||
|
'MAJOR SHORTER!!!\n'
|
||||||
|
f'xref: {xref}\n'
|
||||||
|
f'xref_pin: {xref_pin}\n'
|
||||||
|
f'xref_pin-dt: {xref_pin_dt}\n'
|
||||||
|
f'yref@xref_pin: {yref}\n'
|
||||||
|
)
|
||||||
|
|
||||||
(
|
(
|
||||||
i_start,
|
i_start,
|
||||||
y_ref_major,
|
y_ref_major,
|
||||||
r_major_up_here,
|
r_up_from_major_at_xref,
|
||||||
r_major_down_here,
|
r_down_from_major_at_xref,
|
||||||
) = mx_viz.scalars_from_index(xref)
|
) = mx_viz.scalars_from_index(xref)
|
||||||
|
|
||||||
ymn = y_start * (1 + r_major_down_here)
|
ymn = yref * (1 + r_down_from_major_at_xref)
|
||||||
ymx = y_start * (1 + r_major_up_here)
|
ymx = yref * (1 + r_up_from_major_at_xref)
|
||||||
|
|
||||||
# if this curve's y-range is detected as **not
|
# if this curve's y-range is detected as **not
|
||||||
# being in view** after applying the
|
# being in view** after applying the
|
||||||
|
@ -629,13 +684,18 @@ def overlay_viewlists(
|
||||||
# curves).
|
# curves).
|
||||||
if ymn >= y_min:
|
if ymn >= y_min:
|
||||||
ymn = y_min
|
ymn = y_min
|
||||||
r_dn_minor = (ymn - y_start) / y_start
|
r_dn_minor = (ymn - yref) / yref
|
||||||
|
|
||||||
# rescale major curve's y-max to include new
|
# rescale major curve's y-max to include new
|
||||||
# range increase required by **this minor**.
|
# range increase required by **this minor**.
|
||||||
mx_ymn = y_ref_major * (1 + r_dn_minor)
|
mx_ymn = y_ref_major * (1 + r_dn_minor)
|
||||||
mx_viz.vs.yrange = mx_ymn, mx_viz.vs.yrange[1]
|
mx_viz.vs.yrange = mx_ymn, mx_viz.vs.yrange[1]
|
||||||
|
|
||||||
|
if debug_print:
|
||||||
|
print(
|
||||||
|
f'RESCALE {viz.name} ymn -> {y_min}'
|
||||||
|
f'RESCALE MAJ ymn -> {mx_ymn}'
|
||||||
|
)
|
||||||
# rescale all already scaled curves to new
|
# rescale all already scaled curves to new
|
||||||
# increased range for this side as
|
# increased range for this side as
|
||||||
# determined by ``y_min`` staying in view;
|
# determined by ``y_min`` staying in view;
|
||||||
|
@ -651,10 +711,10 @@ def overlay_viewlists(
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
r_major_down_here,
|
r_down_from_out_of_range,
|
||||||
) = mx_viz.scalars_from_index(_xref)
|
) = mx_viz.scalars_from_index(_xref)
|
||||||
|
|
||||||
new_ymn = _yref * (1 + r_major_down_here)
|
new_ymn = _yref * (1 + r_down_from_out_of_range)
|
||||||
|
|
||||||
scaled[_view] = (
|
scaled[_view] = (
|
||||||
_viz, _yref, new_ymn, _ymx, _xref)
|
_viz, _yref, new_ymn, _ymx, _xref)
|
||||||
|
@ -669,20 +729,26 @@ def overlay_viewlists(
|
||||||
# on the upside.
|
# on the upside.
|
||||||
if ymx <= y_max:
|
if ymx <= y_max:
|
||||||
ymx = y_max
|
ymx = y_max
|
||||||
r_up_minor = (ymx - y_start) / y_start
|
r_up_minor = (ymx - yref) / yref
|
||||||
mx_ymx = y_ref_major * (1 + r_up_minor)
|
mx_ymx = y_ref_major * (1 + r_up_minor)
|
||||||
mx_viz.vs.yrange = mx_viz.vs.yrange[0], mx_ymx
|
mx_viz.vs.yrange = mx_viz.vs.yrange[0], mx_ymx
|
||||||
|
|
||||||
|
if debug_print:
|
||||||
|
print(
|
||||||
|
f'RESCALE {viz.name} ymn -> {y_max}'
|
||||||
|
f'RESCALE MAJ ymx -> {mx_ymx}'
|
||||||
|
)
|
||||||
|
|
||||||
for _view in scaled:
|
for _view in scaled:
|
||||||
_viz, _yref, _ymn, _ymx, _xref = scaled[_view]
|
_viz, _yref, _ymn, _ymx, _xref = scaled[_view]
|
||||||
(
|
(
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
r_major_up_here,
|
r_up_from_out_of_range,
|
||||||
_,
|
_,
|
||||||
) = mx_viz.scalars_from_index(_xref)
|
) = mx_viz.scalars_from_index(_xref)
|
||||||
|
|
||||||
new_ymx = _yref * (1 + r_major_up_here)
|
new_ymx = _yref * (1 + r_up_from_out_of_range)
|
||||||
scaled[_view] = (
|
scaled[_view] = (
|
||||||
_viz, _yref, _ymn, new_ymx, _xref)
|
_viz, _yref, _ymn, new_ymx, _xref)
|
||||||
|
|
||||||
|
@ -693,34 +759,24 @@ def overlay_viewlists(
|
||||||
|
|
||||||
# register all overlays for a final pass where we
|
# register all overlays for a final pass where we
|
||||||
# apply all pinned-curve y-range transform scalings.
|
# apply all pinned-curve y-range transform scalings.
|
||||||
scaled[view] = (viz, y_start, ymn, ymx, xref)
|
scaled[view] = (viz, yref, ymn, ymx, xref)
|
||||||
|
|
||||||
if debug_print:
|
if debug_print:
|
||||||
print(
|
print(
|
||||||
f'Minor SCALARS {viz.name}:\n'
|
f'Viz[{viz.name}]: @ {chart_name}\n'
|
||||||
|
f' .yrange = {viz.vs.yrange}\n'
|
||||||
|
f' .xrange = {viz.vs.xrange}\n\n'
|
||||||
f'xref: {xref}\n'
|
f'xref: {xref}\n'
|
||||||
f'dn: {r_major_down_here}\n'
|
f'xref-dt: {pendulum.from_timestamp(xref)}\n'
|
||||||
f'up: {r_major_up_here}\n'
|
f'y_min: {y_min}\n'
|
||||||
|
f'y_max: {y_max}\n'
|
||||||
|
f'RESCALING\n'
|
||||||
|
f'r dn: {r_down_from_major_at_xref}\n'
|
||||||
|
f'r up: {r_up_from_major_at_xref}\n'
|
||||||
f'ymn: {ymn}\n'
|
f'ymn: {ymn}\n'
|
||||||
f'ymx: {ymx}\n'
|
f'ymx: {ymx}\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
# target/dispersion MAJOR case
|
|
||||||
else:
|
|
||||||
if debug_print:
|
|
||||||
print(
|
|
||||||
f'MAJOR SCALARS {viz.name}:\n'
|
|
||||||
f'dn: {r_dn_mn}\n'
|
|
||||||
f'up: {r_up_mx}\n'
|
|
||||||
f'mx_ymn: {mx_ymn}\n'
|
|
||||||
f'mx_ymx: {mx_ymx}\n'
|
|
||||||
)
|
|
||||||
|
|
||||||
# target/major curve's mxmn may have been
|
|
||||||
# reset by minor overlay steps above.
|
|
||||||
ymn = mx_ymn
|
|
||||||
ymx = mx_ymx
|
|
||||||
|
|
||||||
# Pin all curves by their first datum in view to all
|
# Pin all curves by their first datum in view to all
|
||||||
# others such that each curve's earliest datum provides the
|
# others such that each curve's earliest datum provides the
|
||||||
# reference point for returns vs. every other curve in
|
# reference point for returns vs. every other curve in
|
||||||
|
@ -742,6 +798,22 @@ def overlay_viewlists(
|
||||||
)
|
)
|
||||||
|
|
||||||
if scaled:
|
if scaled:
|
||||||
|
if debug_print:
|
||||||
|
print(
|
||||||
|
'SCALING PHASE' + '-'*100 + '\n\n'
|
||||||
|
'_________MAJOR INFO___________\n'
|
||||||
|
f'SIGMA MAJOR C: {mx_viz.name} -> {mx_disp}\n'
|
||||||
|
f'UP MAJOR C: {upt.viz.name} with disp: {upt.rng}\n'
|
||||||
|
f'DOWN MAJOR C: {dnt.viz.name} with disp: {dnt.rng}\n'
|
||||||
|
f'xref: {mx_xref}\n'
|
||||||
|
f'xref-dt: {pendulum.from_timestamp(mx_xref)}\n'
|
||||||
|
f'dn: {r_dn_mn}\n'
|
||||||
|
f'up: {r_up_mx}\n'
|
||||||
|
f'mx_ymn: {mx_ymn}\n'
|
||||||
|
f'mx_ymx: {mx_ymx}\n'
|
||||||
|
'------------------------------'
|
||||||
|
)
|
||||||
|
|
||||||
for (
|
for (
|
||||||
view,
|
view,
|
||||||
(viz, yref, ymn, ymx, xref)
|
(viz, yref, ymn, ymx, xref)
|
||||||
|
@ -757,32 +829,30 @@ def overlay_viewlists(
|
||||||
|
|
||||||
if debug_print:
|
if debug_print:
|
||||||
print(
|
print(
|
||||||
'------------------------------\n'
|
'_________MINOR INFO___________\n'
|
||||||
f'LOGLIN SCALE CYCLE: {viz.name}@{chart_name}\n'
|
f'Viz[{viz.name}]: @ {chart_name}\n'
|
||||||
f'UP MAJOR C: {upt.viz.name} with disp: {upt.rng}\n'
|
f' .yrange = {viz.vs.yrange}\n'
|
||||||
f'DOWN MAJOR C: {dnt.viz.name} with disp: {dnt.rng}\n'
|
f' .xrange = {viz.vs.xrange}\n\n'
|
||||||
f'SIGMA MAJOR C: {mx_viz.name} -> {mx_disp}\n'
|
f'xref: {xref}\n'
|
||||||
f'xref for MINOR: {xref}\n'
|
f'xref-dt: {pendulum.from_timestamp(xref)}\n'
|
||||||
f'y_start: {y_start}\n'
|
f'y_start: {y_start}\n'
|
||||||
f'y min: {y_min}\n'
|
f'y min: {y_min}\n'
|
||||||
f'y max: {y_max}\n'
|
f'y max: {y_max}\n'
|
||||||
f'T scaled ymn: {ymn}\n'
|
f'T scaled ymn: {ymn}\n'
|
||||||
f'T scaled ymx: {ymx}\n'
|
f'T scaled ymx: {ymx}\n\n'
|
||||||
'------------------------------\n'
|
'--------------------------------\n'
|
||||||
f'Viz[{viz.name}]:\n'
|
|
||||||
f' .yrange = {viz.vs.yrange}\n'
|
|
||||||
f' .xrange = {viz.vs.xrange}\n'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# finally, scale major curve to possibly re-scaled/modified
|
# finally, scale the major target/dispersion curve to
|
||||||
# values
|
# the (possibly re-scaled/modified) values were set in
|
||||||
|
# transform phase loop.
|
||||||
mx_view._set_yrange(yrange=(mx_ymn, mx_ymx))
|
mx_view._set_yrange(yrange=(mx_ymn, mx_ymx))
|
||||||
|
|
||||||
if debug_print:
|
if debug_print:
|
||||||
print(
|
print(
|
||||||
f'END UX GRAPHICS CYCLE: @{chart_name}\n'
|
f'END UX GRAPHICS CYCLE: @{chart_name}\n'
|
||||||
+
|
+
|
||||||
'#'*66
|
divstr
|
||||||
+
|
+
|
||||||
'\n'
|
'\n'
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue