## -*- texinfo -*-
## @deftypefn  {Function File} dsp_pad_flat_ylim (@var{ax}, @var{y})
## @deftypefnx {Function File} dsp_pad_flat_ylim (@var{ax}, @var{y}, @var{pad})
## Give @var{ax} a readable y-range when the data @var{y} is constant or very
## nearly so.
##
## A linear-phase FIR filter has exactly constant group delay, which leaves
## the automatic y-limits degenerate: the curve is pinned to an edge of the
## box and every tick label rounds to the same number, so the axis reads
## @code{24  24  24  24}.  This centres such a series in its box with a
## sensible margin (@var{pad}, default 1 unit, or 5%% of the level when that
## is larger).
##
## Data with a real spread is left untouched.
## @end deftypefn

function dsp_pad_flat_ylim(ax, y, pad)
    y = y(isfinite(y));
    if isempty(y)
        return;
    end

    lo = min(y);
    hi = max(y);
    mid = (lo + hi) / 2;

    if nargin < 3 || isempty(pad)
        pad = max(1, 0.02 * abs(mid));
    end

    % "Flat" means the spread is negligible next to the level itself.  The
    % tolerance is 1e-3 relative rather than something near eps because
    % grpdelay does not return a mathematically exact constant even for a
    % linear-phase FIR: an order-48 design comes back spread over ~6e-5
    % around 24.  Anything varying by more than this is real structure and is
    % left alone to auto-scale.
    if (hi - lo) > 1e-3 * max(1, abs(mid))
        return;
    end

    ylim(ax, [mid - pad, mid + pad]);
end
