Move `Flume.slice_from_time()` to `.data._pathops` mod func
							parent
							
								
									a4eb2d0feb
								
							
						
					
					
						commit
						0dbfa2f721
					
				| 
						 | 
				
			
			@ -30,6 +30,10 @@ from numba import (
 | 
			
		|||
# TODO: for ``numba`` typing..
 | 
			
		||||
# from ._source import numba_ohlc_dtype
 | 
			
		||||
from ._m4 import ds_m4
 | 
			
		||||
from .._profile import (
 | 
			
		||||
    Profiler,
 | 
			
		||||
    pg_profile_enabled,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def xy_downsample(
 | 
			
		||||
| 
						 | 
				
			
			@ -121,7 +125,7 @@ def path_arrays_from_ohlc(
 | 
			
		|||
        high = q['high']
 | 
			
		||||
        low = q['low']
 | 
			
		||||
        close = q['close']
 | 
			
		||||
        index = float64(q['index'])
 | 
			
		||||
        index = float64(q['time'])
 | 
			
		||||
 | 
			
		||||
        # XXX: ``numba`` issue: https://github.com/numba/numba/issues/8622
 | 
			
		||||
        # index = float64(q[index_field])
 | 
			
		||||
| 
						 | 
				
			
			@ -263,3 +267,105 @@ def ohlc_flatten(
 | 
			
		|||
            num=len(flat),
 | 
			
		||||
        )
 | 
			
		||||
    return x, flat
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def slice_from_time(
 | 
			
		||||
    arr: np.ndarray,
 | 
			
		||||
    start_t: float,
 | 
			
		||||
    stop_t: float,
 | 
			
		||||
 | 
			
		||||
) -> tuple[
 | 
			
		||||
    slice,
 | 
			
		||||
    slice,
 | 
			
		||||
    np.ndarray | None,
 | 
			
		||||
]:
 | 
			
		||||
    '''
 | 
			
		||||
    Slice an input struct array to a time range and return the absolute
 | 
			
		||||
    and "readable" slices for that array as well as the indexing mask
 | 
			
		||||
    for the caller to use to slice the input array if needed.
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    profiler = Profiler(
 | 
			
		||||
        msg='slice_from_time()',
 | 
			
		||||
        disabled=not pg_profile_enabled(),
 | 
			
		||||
        ms_threshold=4,
 | 
			
		||||
        # ms_threshold=ms_slower_then,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    times = arr['time']
 | 
			
		||||
    index = arr['index']
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
        start_t < 0
 | 
			
		||||
        or start_t >= stop_t
 | 
			
		||||
    ):
 | 
			
		||||
        return (
 | 
			
		||||
            slice(
 | 
			
		||||
                index[0],
 | 
			
		||||
                index[-1],
 | 
			
		||||
            ),
 | 
			
		||||
            slice(
 | 
			
		||||
                0,
 | 
			
		||||
                len(arr),
 | 
			
		||||
            ),
 | 
			
		||||
            None,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    # use advanced indexing to map the
 | 
			
		||||
    # time range to the index range.
 | 
			
		||||
    mask: np.ndarray = np.where(
 | 
			
		||||
        (times >= start_t)
 | 
			
		||||
        &
 | 
			
		||||
        (times < stop_t)
 | 
			
		||||
    )
 | 
			
		||||
    profiler('advanced indexing slice')
 | 
			
		||||
    # TODO: if we can ensure each time field has a uniform
 | 
			
		||||
    # step we can instead do some arithmetic to determine
 | 
			
		||||
    # the equivalent index like we used to?
 | 
			
		||||
    # return array[
 | 
			
		||||
    #     lbar - ifirst:
 | 
			
		||||
    #     (rbar - ifirst) + 1
 | 
			
		||||
    # ]
 | 
			
		||||
 | 
			
		||||
    i_by_t = index[mask]
 | 
			
		||||
    try:
 | 
			
		||||
        i_0 = i_by_t[0]
 | 
			
		||||
        i_last = i_by_t[-1]
 | 
			
		||||
        i_first_read = index[0]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        if (
 | 
			
		||||
            start_t < times[0]
 | 
			
		||||
            or stop_t >= times[-1]
 | 
			
		||||
        ):
 | 
			
		||||
            return (
 | 
			
		||||
                slice(
 | 
			
		||||
                    index[0],
 | 
			
		||||
                    index[-1],
 | 
			
		||||
                ),
 | 
			
		||||
                slice(
 | 
			
		||||
                    0,
 | 
			
		||||
                    len(arr),
 | 
			
		||||
                ),
 | 
			
		||||
                None,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    abs_slc = slice(i_0, i_last)
 | 
			
		||||
 | 
			
		||||
    # slice data by offset from the first index
 | 
			
		||||
    # available in the passed datum set.
 | 
			
		||||
    read_slc = slice(
 | 
			
		||||
        i_0 - i_first_read,
 | 
			
		||||
        i_last - i_first_read + 1,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    profiler(
 | 
			
		||||
        'slicing complete'
 | 
			
		||||
        f'{start_t} -> {abs_slc.start} | {read_slc.start}\n'
 | 
			
		||||
        f'{stop_t} -> {abs_slc.stop} | {read_slc.stop}\n'
 | 
			
		||||
    )
 | 
			
		||||
    # also return the readable data from the timerange
 | 
			
		||||
    return (
 | 
			
		||||
        abs_slc,
 | 
			
		||||
        read_slc,
 | 
			
		||||
        mask,
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,7 @@ from ._sharedmem import (
 | 
			
		|||
from ._sampling import (
 | 
			
		||||
    open_sample_stream,
 | 
			
		||||
)
 | 
			
		||||
from ._pathops import slice_from_time
 | 
			
		||||
from .._profile import (
 | 
			
		||||
    Profiler,
 | 
			
		||||
    pg_profile_enabled,
 | 
			
		||||
| 
						 | 
				
			
			@ -238,108 +239,6 @@ class Flume(Struct):
 | 
			
		|||
        # just the latest index
 | 
			
		||||
        return array['index'][-1]
 | 
			
		||||
 | 
			
		||||
    def slice_from_time(
 | 
			
		||||
        self,
 | 
			
		||||
        arr: np.ndarray,
 | 
			
		||||
        start_t: float,
 | 
			
		||||
        stop_t: float,
 | 
			
		||||
 | 
			
		||||
    ) -> tuple[
 | 
			
		||||
        slice,
 | 
			
		||||
        slice,
 | 
			
		||||
        np.ndarray | None,
 | 
			
		||||
    ]:
 | 
			
		||||
        '''
 | 
			
		||||
        Slice an input struct array to a time range and return the absolute
 | 
			
		||||
        and "readable" slices for that array as well as the indexing mask
 | 
			
		||||
        for the caller to use to slice the input array if needed.
 | 
			
		||||
 | 
			
		||||
        '''
 | 
			
		||||
        profiler = Profiler(
 | 
			
		||||
            msg='Flume.slice_from_time()',
 | 
			
		||||
            disabled=not pg_profile_enabled(),
 | 
			
		||||
            ms_threshold=4,
 | 
			
		||||
            # ms_threshold=ms_slower_then,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        times = arr['time']
 | 
			
		||||
        index = arr['index']
 | 
			
		||||
 | 
			
		||||
        if (
 | 
			
		||||
            start_t < 0
 | 
			
		||||
            or start_t >= stop_t
 | 
			
		||||
        ):
 | 
			
		||||
            return (
 | 
			
		||||
                slice(
 | 
			
		||||
                    index[0],
 | 
			
		||||
                    index[-1],
 | 
			
		||||
                ),
 | 
			
		||||
                slice(
 | 
			
		||||
                    0,
 | 
			
		||||
                    len(arr),
 | 
			
		||||
                ),
 | 
			
		||||
                None,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        # use advanced indexing to map the
 | 
			
		||||
        # time range to the index range.
 | 
			
		||||
        mask: np.ndarray = np.where(
 | 
			
		||||
            (times >= start_t)
 | 
			
		||||
            &
 | 
			
		||||
            (times < stop_t)
 | 
			
		||||
        )
 | 
			
		||||
        profiler('advanced indexing slice')
 | 
			
		||||
        # TODO: if we can ensure each time field has a uniform
 | 
			
		||||
        # step we can instead do some arithmetic to determine
 | 
			
		||||
        # the equivalent index like we used to?
 | 
			
		||||
        # return array[
 | 
			
		||||
        #     lbar - ifirst:
 | 
			
		||||
        #     (rbar - ifirst) + 1
 | 
			
		||||
        # ]
 | 
			
		||||
 | 
			
		||||
        i_by_t = index[mask]
 | 
			
		||||
        try:
 | 
			
		||||
            i_0 = i_by_t[0]
 | 
			
		||||
            i_last = i_by_t[-1]
 | 
			
		||||
            i_first_read = index[0]
 | 
			
		||||
        except IndexError:
 | 
			
		||||
            if (
 | 
			
		||||
                start_t < times[0]
 | 
			
		||||
                or stop_t >= times[-1]
 | 
			
		||||
            ):
 | 
			
		||||
                return (
 | 
			
		||||
                    slice(
 | 
			
		||||
                        index[0],
 | 
			
		||||
                        index[-1],
 | 
			
		||||
                    ),
 | 
			
		||||
                    slice(
 | 
			
		||||
                        0,
 | 
			
		||||
                        len(arr),
 | 
			
		||||
                    ),
 | 
			
		||||
                    None,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
        abs_slc = slice(i_0, i_last)
 | 
			
		||||
 | 
			
		||||
        # slice data by offset from the first index
 | 
			
		||||
        # available in the passed datum set.
 | 
			
		||||
        read_slc = slice(
 | 
			
		||||
            i_0 - i_first_read,
 | 
			
		||||
            i_last - i_first_read + 1,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        profiler(
 | 
			
		||||
            'slicing complete'
 | 
			
		||||
            f'{start_t} -> {abs_slc.start} | {read_slc.start}\n'
 | 
			
		||||
            f'{stop_t} -> {abs_slc.stop} | {read_slc.stop}\n'
 | 
			
		||||
        )
 | 
			
		||||
        # also return the readable data from the timerange
 | 
			
		||||
        return (
 | 
			
		||||
            abs_slc,
 | 
			
		||||
            read_slc,
 | 
			
		||||
            mask,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    # TODO: maybe move this our ``Viz`` type to avoid
 | 
			
		||||
    # the shm lookup discrepancy?
 | 
			
		||||
    def view_data(
 | 
			
		||||
| 
						 | 
				
			
			@ -366,7 +265,7 @@ class Flume(Struct):
 | 
			
		|||
            abs_slc,
 | 
			
		||||
            read_slc,
 | 
			
		||||
            mask,
 | 
			
		||||
        ) = self.slice_from_time(
 | 
			
		||||
        ) = slice_from_time(
 | 
			
		||||
            arr,
 | 
			
		||||
            start_t=vr.left(),
 | 
			
		||||
            stop_t=vr.right(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,6 +66,7 @@ from ..data.feed import (
 | 
			
		|||
    Feed,
 | 
			
		||||
    Flume,
 | 
			
		||||
)
 | 
			
		||||
from ..data._pathops import slice_from_time
 | 
			
		||||
from ..data._source import Symbol
 | 
			
		||||
from ..log import get_logger
 | 
			
		||||
from ._interaction import ChartView
 | 
			
		||||
| 
						 | 
				
			
			@ -1037,7 +1038,7 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
			
		|||
                read_slc,
 | 
			
		||||
                mask,
 | 
			
		||||
 | 
			
		||||
            ) = viz.flume.slice_from_time(
 | 
			
		||||
            ) = slice_from_time(
 | 
			
		||||
                array,
 | 
			
		||||
                start_t=vtl,
 | 
			
		||||
                stop_t=vtr,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,10 @@ from ..data._formatters import (
 | 
			
		|||
    OHLCBarsAsCurveFmtr,  # OHLC converted to line
 | 
			
		||||
    StepCurveFmtr,  # "step" curve (like for vlm)
 | 
			
		||||
)
 | 
			
		||||
from ..data._pathops import xy_downsample
 | 
			
		||||
from ..data._pathops import (
 | 
			
		||||
    xy_downsample,
 | 
			
		||||
    slice_from_time,
 | 
			
		||||
)
 | 
			
		||||
from ._ohlc import (
 | 
			
		||||
    BarItems,
 | 
			
		||||
    # bar_from_ohlc_row,
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +104,6 @@ def render_baritems(
 | 
			
		|||
            fmtr=OHLCBarsFmtr(
 | 
			
		||||
                shm=viz.shm,
 | 
			
		||||
                viz=viz,
 | 
			
		||||
                # index_field=viz.index_field,
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +112,6 @@ def render_baritems(
 | 
			
		|||
            fmtr=OHLCBarsAsCurveFmtr(
 | 
			
		||||
                shm=viz.shm,
 | 
			
		||||
                viz=viz,
 | 
			
		||||
                # index_field=viz.index_field,
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +292,7 @@ class Viz(msgspec.Struct):  # , frozen=True):
 | 
			
		|||
                abs_slc,
 | 
			
		||||
                read_slc,
 | 
			
		||||
                mask,
 | 
			
		||||
            ) = self.flume.slice_from_time(
 | 
			
		||||
            ) = slice_from_time(
 | 
			
		||||
                arr,
 | 
			
		||||
                start_t=lbar,
 | 
			
		||||
                stop_t=rbar,
 | 
			
		||||
| 
						 | 
				
			
			@ -444,7 +445,7 @@ class Viz(msgspec.Struct):  # , frozen=True):
 | 
			
		|||
                abs_slc,
 | 
			
		||||
                read_slc,
 | 
			
		||||
                mask,
 | 
			
		||||
            ) = self.flume.slice_from_time(
 | 
			
		||||
            ) = slice_from_time(
 | 
			
		||||
                array,
 | 
			
		||||
                start_t=lbar,
 | 
			
		||||
                stop_t=rbar,
 | 
			
		||||
| 
						 | 
				
			
			@ -463,7 +464,7 @@ class Viz(msgspec.Struct):  # , frozen=True):
 | 
			
		|||
            #     )
 | 
			
		||||
            if profiler:
 | 
			
		||||
                profiler(
 | 
			
		||||
                    '`Flume.slice_from_time('
 | 
			
		||||
                    '`slice_from_time('
 | 
			
		||||
                    f'start_t={lbar}'
 | 
			
		||||
                    f'stop_t={rbar})'
 | 
			
		||||
                )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue