Functional Weave
Code in Python

charts.sparkline@1.0.0

impl/python.py

1,791 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import math
from typing import Optional, Sequence

from .charts_extent import extent  ← from charts.extent ^1.0.0 · built alongside by fune
from .charts_scale_linear_scale import linear_scale
from .charts_shape_line_path import line_path
from .charts_shape_types import Point
from .charts_sparkline_types import SparkPoint, Sparkline
from .math_round_float import round_float  ← from math.round-float ^1.0.0 · built alongside by fune


def _check_size(value: float, what: str) -> None:
    if isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(value) or value < 0:
        raise ValueError("%s must be a finite number of zero or more, received %r" % (what, value))


def sparkline(values: Sequence[Optional[float]], width: float, height: float, padding: float) -> Sparkline:
    """A sparkline in a box; see the README for flat and single-value series."""
    _check_size(width, "width")
    _check_size(height, "height")
    _check_size(padding, "padding")
    if width - 2 * padding <= 0 or height - 2 * padding <= 0:
        raise ValueError(
            "the box is too small for its padding: %r by %r with %r on each side" % (width, height, padding)
        )
    rng = extent(values)
    if rng is None:
        return Sparkline(path="", end=None)
    lo, hi = rng
    n = len(values)
    points = []
    for i, v in enumerate(values):
        x = width - padding if n == 1 else linear_scale([0, n - 1], [padding, width - padding], i, False)
        if v is None:
            points.append(Point(x=x, y=None))
            continue
        y = height / 2 if lo == hi else linear_scale([lo, hi], [height - padding, padding], v, False)
        points.append(Point(x=x, y=y))
    end = None
    for p in points:
        if p.y is not None:
            end = SparkPoint(x=round_float(p.x, 2), y=round_float(p.y, 2))
    return Sparkline(path=line_path(points), end=end)