Open source

Open-source tools for large data and time series.

Five projects for interactive visualization and analysis of large data and time series: FlexViz, plotly-resampler, tsflex, tsdownsample, and argminmax. All developed in the open, on GitHub.

Our mission

Interactive exploration of large data, made ordinary.

Two shifts at once: datasets are outgrowing the tools people use to visualize them, and the people doing that work now do it alongside a coding agent. The projects on this page address the first; FlexViz addresses both.

Mission 01

Make visualizing large data ordinary

No sampling, no waiting, no giving up on interactivity. Seeing all of your data, and moving through it freely, should be the ordinary case at 100M+ rows. That runs through every project here, from the SIMD kernel up to the dashboard.

Mission 02

Make that exploration agent-native

The direction the newer work takes. A coding agent builds the dashboard and reads your live view back as state, not a screenshot, then reasons over the rows behind it. FlexViz is where that is built today.

What we believe

  • 01

    Visualize all your data

    A sample hides the outlier you were looking for. The tools aggregate the full dataset for the current view instead, so nothing is dropped before you see it.

  • 02

    Interaction beats an image

    A picture cannot be zoomed or brushed. Exploration is about changing the view and getting an honest answer back, live.

  • 03

    Open by default

    Every tool on this page is open source and stays that way. Permissive licenses, public issue trackers, and peer-reviewed papers behind the algorithms.

How the tools relate.

Solid arrows are code dependencies. The dashed arrow is not: it is what FlexViz carried over from plotly-resampler, which it does not import a line of.

argminmax SIMD argmin / argmax tsdownsample downsampling algorithms Polars polars-ops, polars-utils flexviz-polars FlexViz's Polars plugin plotly-resampler view-aware figures HoloViews downsample1d hvPlot downsample= FlexViz data exploration, agent-native —— compiled or imported into - - - ideas carried over, no code solid border: our projects dashed border: other people’s

  • argminmax is the SIMD kernel used by tsdownsample, Polars its arg_min and arg_max functions, and FlexViz’s own Polars plugin.
  • tsdownsample carries no dependency on any plotting library. That is why besides plotly-resampler, also HoloViews and hvPlot use it as well: their downsample1d operation accelerates LTTB with it, and its minmax, minmax-lttb and m4 algorithms are unavailable without it.
  • tsflex is the sibling project, used for processing and window-based feature extraction rather than for plotting.
flexviz11 on PyPI since 2026-08-25

FlexViz is our open-source engine for interactive data exploration at scale, and the project the consulting work is built on. Zoom, brush and linked hover are answered by lazy Polars aggregations and Rust kernels, so only the aggregate reaches the browser.

The server is stateless and every view is a URL: viewport, selections, cross-filter mode and layout all encode into the link. Ten trace types are supported, from line and histogram to correlation heatmap and geo 2D histogram. Parquet larger than memory streams through the same lazy plan, so a billion rows explore in under 400 MB of resident memory.

It is agent-native. A coding agent writes the dashboard spec, hands over the URL, and reads your zoom and selections back as state, so you both work against the same live view.

dashboard.pypython
import polars as pl
from flexviz import Dashboard

lf = pl.scan_parquet("readings.parquet")  # 100M rows, lazy

dash = Dashboard(lf)
dash.add_figure().add_line(x="timestamp", y="value")
dash.add_figure().add_histogram(x="value", bins=50)
dash.show()  # cross-filtered
A coding agent builds a FlexViz dashboard over 84 million NYC taxi trips, hands over the URL, then reads the human's zoom and brush back as state and answers from the rows behind it
A coding agent builds the dashboard, hands over the URL, then reads the zoom and brush back as state. 84M NYC taxi trips; the closing numbers are Polars queries over the range actually brushed.

plotly-resampler

plotly-resampler1.2k 18M PyPI downloads · 389k last month

plotly-resampler visualizes large time series with plotly.py. Wrapping a figure in FigureResampler keeps the high-frequency series in Python and sends only a view-aware aggregate to the browser.

Every zoom and pan triggers a new aggregation over the visible window, through a Dash callback or through the FigureWidget in a notebook. The default aggregator is MinMaxLTTB from tsdownsample.

The approach was published at IEEE VIS 2022.

resample.pypython
from plotly_resampler import FigureResampler

fig = FigureResampler(go.Figure())
# hf_ data stays in Python, never in the browser
fig.add_trace(go.Scattergl(name="sine"), hf_x=x, hf_y=y)
fig.show_dash(mode="inline")
Zooming into a plotly-resampler figure; the series is re-aggregated for each new view
Demo on 100M+ points
tsflex442 212k PyPI downloads

tsflex processes time series and extracts features from them. A FeatureCollection describes which functions run over which series, in which windows and at which strides, and calculates the whole set in one call.

It makes few assumptions about the sequence data. Input can be multivariate with a different sample rate per series, the time index may be irregular or asynchronous, and one collection can hold several windows and strides at the same time.

Feature functions come from the libraries you already use: numpy, scipy, seglearn, tsfresh and catch22 all plug in. Published in SoftwareX 2022.

features.pypython
import numpy as np, scipy.stats as ss
from tsflex.features import (FeatureCollection,
                             MultipleFeatureDescriptors)

fc = FeatureCollection(MultipleFeatureDescriptors(
    functions=[np.min, np.mean, np.std, ss.skew],
    series_names=["TMP", "ACC_x", "IBI"],
    windows=["15min", "30min"], strides="15min"))

features = fc.calculate(data=[df_tmp, df_acc, df_ibi])
tsdownsample235 16M PyPI downloads · 421k last month

tsdownsample selects the data points that represent a long series in a fixed number of pixels. It is written in Rust and exposed to Python through PyO3, and it returns indices, so the caller keeps its own arrays.

SIMD comes from argminmax with runtime CPU feature detection, and the algorithms are multithreaded with Rayon. They operate on views instead of copies, x is optional, and datatypes from f16 to u64 and datetime64 are supported.

downsample.pypython
from tsdownsample import MinMaxLTTBDownsampler

# returns indices into y, not a copy
idx = MinMaxLTTBDownsampler().downsample(x, y, n_out=1000)
argminmax64 14.1M crates.io downloads

argminmax returns the index of the minimum and the index of the maximum of an array from a single function. The inner loop is SIMD (SSE, AVX2, AVX512, NEON) and branch-free, so the best and the worst case take the same time. Runtime CPU feature detection picks the implementation, so one binary runs on every CPU.

tsdownsample sits on this crate because MinMax downsampling needs both extremes of every bucket. One pass reads each bucket once instead of twice.

main.rsrust
use argminmax::ArgMinMax;

// one pass, both extremes
let (min_i, max_i) = v.argminmax();

Contributing and support.

Issues and pull requests are welcome on the repositories above. A bug report with a small reproducible example is the most useful thing you can send, especially for FlexViz, which is pre-1.0 and still moving.

Paid work is separate from that: running these tools on your data, custom traces and aggregations, and time-series analysis. That is what the services page covers.