aboutsummaryrefslogtreecommitdiff

scopekit

scopekit is a Python library for creating high-performance, interactive oscilloscope-style plots for large time-series datasets using matplotlib.

It is designed to handle millions of data points smoothly by automatically decimating data for the current view. When zoomed out, it displays a performance-optimized "envelope" view, and when zoomed in, it seamlessly transitions to show detailed raw data.

Installation

To install the package from your local repository, run:

pip install .

Quickstart Example

Here is a simple example of how to create a plot with scopekit.

import numpy as np
from scopekit import OscilloscopePlot

# 1. Generate some sample data
fs = 1e7  # 10 MHz sampling rate
duration = 0.1  # 0.1 seconds of data
t = np.arange(0, duration, 1/fs)
# A 50 Hz signal with some high-frequency noise
x = np.sin(2 * np.pi * 50 * t) + np.sin(2 * np.pi * 1e3 * t) * 0.2

# 2. Create an OscilloscopePlot instance
# The plot automatically handles decimation and display modes.
plot = OscilloscopePlot(t, x, name="Sample Waveform")

# 3. Render the plot
# This creates the matplotlib figure and axes.
plot.render()

# 4. Show the plot
# The plot is now interactive: zoom with the mouse and use the toolbar.
plot.show()

API Reference

The primary interface for the library is the OscilloscopePlot class.

OscilloscopePlot

__init__

def __init__(
    self,
    t: Union[np.ndarray, List[np.ndarray]],
    x: Union[np.ndarray, List[np.ndarray]],
    name: Union[str, List[str]] = "Waveform",
    trace_colors: Optional[List[str]] = None,
    max_plot_points: int = 10000,
    mode_switch_threshold: float = 10e-3,
    min_y_range: Optional[float] = None,
    y_margin_fraction: float = 0.15,
    signal_line_width: float = 1.0,
    signal_alpha: float = 0.75,
    envelope_alpha: float = 0.75,
    region_alpha: float = 0.4,
    region_zorder: int = -5,
    envelope_window_samples: Optional[int] = None,
):

Methods

def add_line(
    self,
    t: Union[np.ndarray, List[np.ndarray]],
    data: Union[np.ndarray, List[np.ndarray]],
    label: str = "Line",
    color: Optional[str] = None,
    alpha: float = 0.75,
    linestyle: str = "-",
    linewidth: float = 1.0,
    display_mode: int = MODE_BOTH,
    trace_idx: int = 0,
    zorder: int = 5,
) -> None:
def add_ribbon(
    self,
    t: Union[np.ndarray, List[np.ndarray]],
    center_data: Union[np.ndarray, List[np.ndarray]],
    width: Union[float, np.ndarray],
    label: str = "Ribbon",
    color: str = "gray",
    alpha: float = 0.6,
    display_mode: int = MODE_DETAIL,
    trace_idx: int = 0,
    zorder: int = 2,
) -> None:
def add_envelope(
    self,
    min_data: Union[np.ndarray, List[np.ndarray]],
    max_data: Union[np.ndarray, List[np.ndarray]],
    label: str = "Envelope",
    color: Optional[str] = None,
    alpha: float = 0.4,
    display_mode: int = MODE_ENVELOPE,
    trace_idx: int = 0,
    zorder: int = 1,
) -> None:
def add_regions(
    self,
    regions: np.ndarray,
    label: str = "Regions",
    color: str = "crimson",
    alpha: float = 0.4,
    display_mode: int = MODE_BOTH,
    trace_idx: int = 0,
    zorder: int = -5,
) -> None:
def render(self) -> None:
def show(self) -> None:
def save(self, filepath: str) -> None:
def home(self) -> None:
def refresh(self) -> None: