Only clear/redraw curve on uppx diffs > 2
Only if the uppx increases by more then 2 we redraw the entire line otherwise just ds with previous params and update the current curve. This *should* avoid strange lower sample rate artefacts from showing on updates. Summary: - stash both uppx and px width in `._dsi` (downsample info) - use the new `ohlc_to_m4_line()` flags - add notes about using `.reserve()` and friends - always delete last `._array` ref prior to line updatesmkts_backup
							parent
							
								
									fac1f86891
								
							
						
					
					
						commit
						d2b42a46e6
					
				| 
						 | 
					@ -36,10 +36,7 @@ from ._style import hcolor
 | 
				
			||||||
from ..log import get_logger
 | 
					from ..log import get_logger
 | 
				
			||||||
from ._curve import FastAppendCurve
 | 
					from ._curve import FastAppendCurve
 | 
				
			||||||
from ._compression import (
 | 
					from ._compression import (
 | 
				
			||||||
    # hl2mxmn,
 | 
					 | 
				
			||||||
    # ohlc_flatten,
 | 
					 | 
				
			||||||
    ohlc_to_m4_line,
 | 
					    ohlc_to_m4_line,
 | 
				
			||||||
    # ds_m4,
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
| 
						 | 
					@ -234,9 +231,6 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._pi = plotitem
 | 
					        self._pi = plotitem
 | 
				
			||||||
        self.path = QtGui.QPainterPath()
 | 
					        self.path = QtGui.QPainterPath()
 | 
				
			||||||
        # not sure if this is actually impoving anything but figured it
 | 
					 | 
				
			||||||
        # was worth a shot:
 | 
					 | 
				
			||||||
        self.path.reserve(int(100e3 * 6))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._xrange: tuple[int, int]
 | 
					        self._xrange: tuple[int, int]
 | 
				
			||||||
        self._yrange: tuple[float, float]
 | 
					        self._yrange: tuple[float, float]
 | 
				
			||||||
| 
						 | 
					@ -253,7 +247,7 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
        self._in_ds: bool = False
 | 
					        self._in_ds: bool = False
 | 
				
			||||||
        self._ds_lines: dict[int, FastAppendCurve] = {}
 | 
					        self._ds_lines: dict[int, FastAppendCurve] = {}
 | 
				
			||||||
        self._ds_line: Optional[FastAppendCurve] = None
 | 
					        self._ds_line: Optional[FastAppendCurve] = None
 | 
				
			||||||
        self._ds: int = 0
 | 
					        self._dsi: tuple[int, int] = 0, 0
 | 
				
			||||||
        self._xs_in_px: float = 0
 | 
					        self._xs_in_px: float = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def draw_from_data(
 | 
					    def draw_from_data(
 | 
				
			||||||
| 
						 | 
					@ -319,18 +313,12 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
    def update_ds_line(
 | 
					    def update_ds_line(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        ohlc: np.ndarray,
 | 
					        ohlc: np.ndarray,
 | 
				
			||||||
        use_ds: bool = False,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ) -> int:
 | 
					    ) -> int:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not use_ds:
 | 
					 | 
				
			||||||
            ds = 0
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            ds = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # determine current potential downsampling value (based on pixel
 | 
					        # determine current potential downsampling value (based on pixel
 | 
				
			||||||
        # scaling) and return any existing curve for it.
 | 
					        # scaling) and return any existing curve for it.
 | 
				
			||||||
        curve, ds = self.get_ds_line()
 | 
					        curve, uppx = self.get_ds_line()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        chart = self.linked.chart
 | 
					        chart = self.linked.chart
 | 
				
			||||||
        if not chart:
 | 
					        if not chart:
 | 
				
			||||||
| 
						 | 
					@ -341,12 +329,46 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
        # if self._ds_line:
 | 
					        # if self._ds_line:
 | 
				
			||||||
        #     self._pi.removeItem(self._ds_line)
 | 
					        #     self._pi.removeItem(self._ds_line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # old tracer with no downsampling
 | 
					        # log.info(f'current dsi: {self._dsi}')
 | 
				
			||||||
        # y, x = hl2mxmn(ohlc)
 | 
					        ds_uppx, ds_px_width = self._dsi
 | 
				
			||||||
        x, y = ohlc_to_m4_line(ohlc, px_width)
 | 
					
 | 
				
			||||||
 | 
					        if (
 | 
				
			||||||
 | 
					            abs(uppx - ds_uppx) >= 2
 | 
				
			||||||
 | 
					            or ds_px_width == 0
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            ds_uppx, ds_px_width = dsi = (uppx, px_width)
 | 
				
			||||||
 | 
					            log.info(f'sampler change: {self._dsi} -> {dsi}')
 | 
				
			||||||
 | 
					            self._dsi = dsi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if curve:
 | 
				
			||||||
 | 
					                # trigger a full redraw of the curve path since
 | 
				
			||||||
 | 
					                # we have downsampled another "level" using m4.
 | 
				
			||||||
 | 
					                curve.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # always refresh data bounds until we get diffing
 | 
				
			||||||
 | 
					        # working properly, see above..
 | 
				
			||||||
 | 
					        x, y = ohlc_to_m4_line(
 | 
				
			||||||
 | 
					            ohlc,
 | 
				
			||||||
 | 
					            ds_px_width,
 | 
				
			||||||
 | 
					            uppx=ds_uppx,
 | 
				
			||||||
 | 
					            # pretrace=True,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # activate m4 ds?
 | 
				
			||||||
 | 
					            downsample=True,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not curve:
 | 
					        if not curve:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # TODO: figuring out the most optimial size for the ideal
 | 
				
			||||||
 | 
					            # curve-path by,
 | 
				
			||||||
 | 
					            # - calcing the display's max px width `.screen()`
 | 
				
			||||||
 | 
					            # - drawing a curve and figuring out it's capacity:
 | 
				
			||||||
 | 
					            #   https://doc.qt.io/qt-5/qpainterpath.html#capacity
 | 
				
			||||||
 | 
					            # - reserving that cap for each curve-mapped-to-shm with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # - leveraging clearing when needed to redraw the entire
 | 
				
			||||||
 | 
					            #   curve that does not release mem allocs:
 | 
				
			||||||
 | 
					            #   https://doc.qt.io/qt-5/qpainterpath.html#clear
 | 
				
			||||||
            curve = FastAppendCurve(
 | 
					            curve = FastAppendCurve(
 | 
				
			||||||
                y=y,
 | 
					                y=y,
 | 
				
			||||||
                x=x,
 | 
					                x=x,
 | 
				
			||||||
| 
						 | 
					@ -357,12 +379,9 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            curve.hide()
 | 
					            curve.hide()
 | 
				
			||||||
            self._pi.addItem(curve)
 | 
					            self._pi.addItem(curve)
 | 
				
			||||||
            self._ds_lines[ds] = curve
 | 
					            self._ds_lines[ds_uppx] = curve
 | 
				
			||||||
            self._ds_line = curve
 | 
					            self._ds_line = curve
 | 
				
			||||||
            return curve, ds
 | 
					            return curve, ds_uppx
 | 
				
			||||||
 | 
					 | 
				
			||||||
        # elif ds != self._ds:
 | 
					 | 
				
			||||||
            # print(f'ds changed {self._ds} -> {ds}')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO: we should be diffing the amount of new data which
 | 
					        # TODO: we should be diffing the amount of new data which
 | 
				
			||||||
        # needs to be downsampled. Ideally we actually are just
 | 
					        # needs to be downsampled. Ideally we actually are just
 | 
				
			||||||
| 
						 | 
					@ -371,19 +390,11 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
        # choice.
 | 
					        # choice.
 | 
				
			||||||
        # diff = do_diff(ohlc, new_bit)
 | 
					        # diff = do_diff(ohlc, new_bit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # always refresh data bounds until we get diffing
 | 
					 | 
				
			||||||
        # working properly, see above..
 | 
					 | 
				
			||||||
        if abs(ds - self._ds) > 2:
 | 
					 | 
				
			||||||
            log.info(f'sampler change: {self._ds} -> {ds}')
 | 
					 | 
				
			||||||
            curve.path = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        curve.update_from_array(
 | 
					        curve.update_from_array(
 | 
				
			||||||
            y=y,
 | 
					            y=y,
 | 
				
			||||||
            x=x,
 | 
					            x=x,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        self._ds = ds
 | 
					        return curve, ds_uppx
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return curve, ds
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_from_array(
 | 
					    def update_from_array(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
| 
						 | 
					@ -406,6 +417,8 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        # XXX: always do this?
 | 
					        # XXX: always do this?
 | 
				
			||||||
        # if self._ds_line:
 | 
					        # if self._ds_line:
 | 
				
			||||||
 | 
					        del self._array
 | 
				
			||||||
 | 
					        self._array = ohlc
 | 
				
			||||||
        curve, ds = self.update_ds_line(ohlc)
 | 
					        curve, ds = self.update_ds_line(ohlc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # index = self.start_index
 | 
					        # index = self.start_index
 | 
				
			||||||
| 
						 | 
					@ -497,8 +510,6 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
        if flip_cache:
 | 
					        if flip_cache:
 | 
				
			||||||
            self.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache)
 | 
					            self.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._array = ohlc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def boundingRect(self):
 | 
					    def boundingRect(self):
 | 
				
			||||||
        # Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect
 | 
					        # Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -568,7 +579,10 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            xs_in_px = self._ds_line.pixelVectors()[0].x()
 | 
					            xs_in_px = self._ds_line.pixelVectors()[0].x()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if xs_in_px != self._xs_in_px and self._array is not None:
 | 
					        if (
 | 
				
			||||||
 | 
					            # xs_in_px != self._xs_in_px
 | 
				
			||||||
 | 
					            self._array is not None
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
            self.update_ds_line(self._array)
 | 
					            self.update_ds_line(self._array)
 | 
				
			||||||
            self._xs_in_px = xs_in_px
 | 
					            self._xs_in_px = xs_in_px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -619,7 +633,7 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # elif (
 | 
					        # elif (
 | 
				
			||||||
        #     self._in_ds
 | 
					        #     self._in_ds
 | 
				
			||||||
        #     and self._ds != ds
 | 
					        #     and self._dsi != ds
 | 
				
			||||||
        # ):
 | 
					        # ):
 | 
				
			||||||
        #     # curve = self._ds_lines.get(ds)
 | 
					        #     # curve = self._ds_lines.get(ds)
 | 
				
			||||||
        #     # assert self._ds_line is not curve
 | 
					        #     # assert self._ds_line is not curve
 | 
				
			||||||
| 
						 | 
					@ -632,7 +646,7 @@ class BarItems(pg.GraphicsObject):
 | 
				
			||||||
        #         curve.update()
 | 
					        #         curve.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #     self._ds_line = curve
 | 
					        #     self._ds_line = curve
 | 
				
			||||||
        #     self._ds = ds
 | 
					        #     self._dsi = ds
 | 
				
			||||||
        #     linked.graphics_cycle()
 | 
					        #     linked.graphics_cycle()
 | 
				
			||||||
        #     return True
 | 
					        #     return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue