Draft 'step' curve; couldn't get pg builtin to work
							parent
							
								
									69c2dd866e
								
							
						
					
					
						commit
						f4e1362792
					
				| 
						 | 
					@ -20,6 +20,7 @@ Fast, smooth, sexy curves.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
from typing import Tuple
 | 
					from typing import Tuple
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
import pyqtgraph as pg
 | 
					import pyqtgraph as pg
 | 
				
			||||||
from PyQt5 import QtCore, QtGui, QtWidgets
 | 
					from PyQt5 import QtCore, QtGui, QtWidgets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +30,12 @@ from .._profile import pg_profile_enabled
 | 
				
			||||||
# TODO: got a feeling that dropping this inheritance gets us even more speedups
 | 
					# TODO: got a feeling that dropping this inheritance gets us even more speedups
 | 
				
			||||||
class FastAppendCurve(pg.PlotCurveItem):
 | 
					class FastAppendCurve(pg.PlotCurveItem):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        *args,
 | 
				
			||||||
 | 
					        step_mode: bool = False,
 | 
				
			||||||
 | 
					        **kwargs
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO: we can probably just dispense with the parent since
 | 
					        # TODO: we can probably just dispense with the parent since
 | 
				
			||||||
        # we're basically only using the pen setting now...
 | 
					        # we're basically only using the pen setting now...
 | 
				
			||||||
| 
						 | 
					@ -37,6 +43,7 @@ class FastAppendCurve(pg.PlotCurveItem):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._last_line: QtCore.QLineF = None
 | 
					        self._last_line: QtCore.QLineF = None
 | 
				
			||||||
        self._xrange: Tuple[int, int] = self.dataBounds(ax=0)
 | 
					        self._xrange: Tuple[int, int] = self.dataBounds(ax=0)
 | 
				
			||||||
 | 
					        self._step_mode: bool = step_mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO: one question still remaining is if this makes trasform
 | 
					        # TODO: one question still remaining is if this makes trasform
 | 
				
			||||||
        # interactions slower (such as zooming) and if so maybe if/when
 | 
					        # interactions slower (such as zooming) and if so maybe if/when
 | 
				
			||||||
| 
						 | 
					@ -59,23 +66,53 @@ class FastAppendCurve(pg.PlotCurveItem):
 | 
				
			||||||
        prepend_length = istart - x[0]
 | 
					        prepend_length = istart - x[0]
 | 
				
			||||||
        append_length = x[-1] - istop
 | 
					        append_length = x[-1] - istop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO: step mode support
 | 
					        # step mode: draw flat top discrete "step"
 | 
				
			||||||
        # if self.stepMode in ("center", True):  ## support True for back-compat
 | 
					        # over the index space for each datum.
 | 
				
			||||||
        #     x2 = np.empty((len(x),2), dtype=x.dtype)
 | 
					        if self._step_mode:
 | 
				
			||||||
        #     x2[:] = x[:, np.newaxis]
 | 
					            y_out = y.copy()
 | 
				
			||||||
 | 
					            x_out = x.copy()
 | 
				
			||||||
 | 
					            x2 = np.empty(
 | 
				
			||||||
 | 
					                # the data + 2 endpoints on either end for
 | 
				
			||||||
 | 
					                # "termination of the path".
 | 
				
			||||||
 | 
					                (len(x) + 1, 2),
 | 
				
			||||||
 | 
					                # we want to align with OHLC or other sampling style
 | 
				
			||||||
 | 
					                # bars likely so we need fractinal values
 | 
				
			||||||
 | 
					                dtype=float,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            x2[0] = x[0] - 0.5
 | 
				
			||||||
 | 
					            x2[1] = x[0] + 0.5
 | 
				
			||||||
 | 
					            x2[1:] = x[:, np.newaxis] + 0.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # flatten to 1-d
 | 
				
			||||||
 | 
					            x_out = x2.reshape(x2.size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # we create a 1d with 2 extra indexes to
 | 
				
			||||||
 | 
					            # hold the start and (current) end value for the steps
 | 
				
			||||||
 | 
					            # on either end
 | 
				
			||||||
 | 
					            y_out = np.empty(
 | 
				
			||||||
 | 
					                2*len(y) + 2,
 | 
				
			||||||
 | 
					                dtype=y.dtype
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            y2 = np.empty((len(y), 2), dtype=y.dtype)
 | 
				
			||||||
 | 
					            y2[:] = y[:,np.newaxis]
 | 
				
			||||||
 | 
					            # flatten 
 | 
				
			||||||
 | 
					            y_out[1:-1] = y2.reshape(y2.size)
 | 
				
			||||||
 | 
					            y_out[0] = 0
 | 
				
			||||||
 | 
					            y_out[-1] = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # TODO: see ``painter.fillPath()`` call
 | 
				
			||||||
 | 
					            # inside parent's ``.paint()`` to get
 | 
				
			||||||
 | 
					            # a solid brush under the curve.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            # by default we only pull data up to the last (current) index
 | 
				
			||||||
 | 
					            x_out, y_out = x[:-1], y[:-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #     ## If we have a fill level, add two extra points at either end
 | 
					 | 
				
			||||||
        #     x = x2.reshape(x2.size)
 | 
					 | 
				
			||||||
        #     y2 = np.empty((len(y)+2,2), dtype=y.dtype)
 | 
					 | 
				
			||||||
        #     y2[1:-1] = y[:,np.newaxis]
 | 
					 | 
				
			||||||
        #     y = y2.reshape(y2.size)[1:-1]
 | 
					 | 
				
			||||||
        #     y[0] = self.opts['fillLevel']
 | 
					 | 
				
			||||||
        #     y[-1] = self.opts['fillLevel']
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.path is None or prepend_length:
 | 
					        if self.path is None or prepend_length:
 | 
				
			||||||
            self.path = pg.functions.arrayToQPath(
 | 
					            self.path = pg.functions.arrayToQPath(
 | 
				
			||||||
                x[:-1],
 | 
					                x_out,
 | 
				
			||||||
                y[:-1],
 | 
					                y_out,
 | 
				
			||||||
                connect='all'
 | 
					                connect='all'
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            profiler('generate fresh path')
 | 
					            profiler('generate fresh path')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue