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