Functional Weave
Code in TypeScript

charts.downsample@1.0.0

README.md

1,756 bytes · view raw

# charts.downsample

A line chart of 100,000 points drawn into 800 pixels is mostly wasted work,
and the browser or PDF renderer pays for every point. `downsample(points,
threshold)` keeps `threshold` of them, chosen so the line still looks the
same: peaks, dips and spikes survive.

The method is Largest-Triangle-Three-Buckets (LTTB) from Sveinn Steinarsson's
2013 thesis. The first and last points are always kept. The points between are
split into `threshold - 2` buckets of about equal size, and from each bucket
the point kept is the one forming the largest triangle with the point kept
from the previous bucket and the average of the next bucket. Unlike keeping
every nth point, a one-sample spike is not lost; unlike averaging a bucket,
the result is made of real data points, so a tooltip over it shows a value
that was actually measured.

- The result is a subset of the input, in input order, never new points.
- Bucket bounds are `floor(i x every) + 1` with `every = (n - 2) / (threshold - 2)`
  in floating point, as in the reference implementation, so the same points are
  chosen as there. The triangle areas use real x values, so uneven spacing
  matters.
- When two candidates make triangles of the same area, the earlier one is kept.
- A series of `threshold` points or fewer is returned unchanged (as a copy).
- `threshold` must be at least 3. The reference implementation treats 0 as
  "do not downsample"; here a threshold that cannot work is an error.
- Points should be in drawing order (ascending x for a time series); they are
  not sorted here.

Source: S. Steinarsson, "Downsampling Time Series for Visual Representation",
MSc thesis, University of Iceland, 2013; reference code at
github.com/sveinn-steinarsson/flot-downsample.