Skip to content

Python Utilities API

The doppler.util module holds small numeric helpers shared across the library. Today it exposes one function, square_clip — the per-component hard limiter used by the AGC and other saturating paths.

Source: src/doppler/util/__init__.py


square_clip

Clips the real and imaginary parts of a complex sample independently to [-lin, lin] — a square region in the IQ plane (each axis limited on its own), as opposed to a circular magnitude clip. This is the cheap, branch-light limiter a feedback loop applies after gain to bound excursions without rotating the sample's phase quadrant.

from doppler.util import square_clip

square_clip(3 + 4j, 1.0)    # (1+1j)   -> re and im each clamped to [-1, 1]
square_clip(0.5 - 0.2j, 1.0)  # (0.5-0.2j) -> inside the square, unchanged

Contrast with a circular clip, which would scale 3 + 4j (magnitude 5) down to magnitude lin while preserving its phase; square_clip instead clamps each axis, which is what a fixed-point I/Q datapath does at its rails.


square_clip

square_clip(y: complex, lin: float) -> complex

Square-clip a complex sample: clip the real and imaginary parts independently to [-lin, lin] (a square region in the IQ plane).

Parameters:

Name Type Description Default
y complex

Complex CF32 input sample.

required
lin float

Per-component clip threshold (linear amplitude, >= 0). Values outside [-lin, lin] are clamped; values on the boundary are preserved exactly.

required

Returns:

Type Description
complex

Sample with each component limited to [-lin, lin].

Examples:

>>> from doppler.util import square_clip
>>> square_clip(0.5+0.25j, 1.0)   # within bounds, passed through
(0.5+0.25j)
>>> square_clip(2.0+0.5j, 1.0)    # real clipped, imag unchanged
(1+0.5j)
>>> square_clip(3.0-4.0j, 1.0)    # both components clipped
(1-1j)
>>> square_clip(0.5+0.5j, 0.25)   # smaller threshold clips both
(0.25+0.25j)
>>> square_clip(-2.0+0.0j, 1.0)   # negative real clipped
(-1+0j)