Functional Weave
Code in TypeScript

charts.ticks@1.0.0

impl/python/nice_ticks.py

1,480 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.

from typing import List, Tuple

from .charts_ticks_tick_step import tick_spec  ← tickStep, another function of this group · built into the same file, even by a slim install
from .math_round_float import round_float  ← from math.round-float ^1.0.0 · built alongside by fune


def nice_ticks(start: float, stop: float, count: int) -> List[float]:
    """Ticks at round values between start and stop, as d3.ticks, each one
    exact operation on a whole number (i * step or i / divisor), so 0.1 steps
    give 0.3 and not 0.30000000000000004."""
    mul, div = tick_spec(start, stop, count)
    if start == stop:
        return [float(start) + 0.0]
    reverse = stop < start
    lo = float(stop if reverse else start)
    hi = float(start if reverse else stop)
    i1, i2 = _indexes(lo, hi, mul, div)
    if i2 < i1 and count == 1:
        # No multiple of the step for one tick falls inside; d3 retries with two.
        mul, div = tick_spec(start, stop, 2)
        i1, i2 = _indexes(lo, hi, mul, div)
    ticks = []
    i = i1
    while i <= i2:
        ticks.append((i / div if div > 1 else i * mul) + 0.0)
        i += 1
    if reverse:
        ticks.reverse()
    return ticks


def _indexes(lo: float, hi: float, mul: float, div: float) -> Tuple[float, float]:
    if div > 1:
        i1 = round_float(lo * div, 0)
        i2 = round_float(hi * div, 0)
        if i1 / div < lo:
            i1 += 1
        if i2 / div > hi:
            i2 -= 1
        return i1, i2
    i1 = round_float(lo / mul, 0)
    i2 = round_float(hi / mul, 0)
    if i1 * mul < lo:
        i1 += 1
    if i2 * mul > hi:
        i2 -= 1
    return i1, i2