Signal¶
signal
¶
Array-pure signal utilities.
Numeric helpers that operate on plain NumPy arrays sampled along an axis — no :class:~pybvh.bvh.Bvh involved. The centerpiece is :func:finite_difference, the single derivative convention shared by the kinematics ladder (:mod:pybvh.analysis) and the geometry derivative kernels (:mod:pybvh.geometry); the rest are self-contained statistics, smoothing, spectrum, and simplification tools (no scipy).
finite_difference(arr: npt.NDArray[np.float64], dt: float, *, stencil: str = 'central', pad: str = 'edge', axis: int = 0) -> npt.NDArray[np.float64]
¶
Differentiate a sampled array along one axis.
The single finite-difference convention shared across pybvh — the
kinematics ladder (node_velocities → …accelerations → jerk)
and the geometry derivative kernels (curvature, torsion,
movement_phase) all route through this, so derivatives composed
across the two stay consistent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arr
|
ndarray
|
Samples taken at a uniform step |
required |
dt
|
float
|
Sample spacing (e.g. |
required |
stencil
|
('central', 'forward')
|
|
"central"
|
pad
|
('edge', 'none')
|
|
"edge"
|
axis
|
int
|
Axis to differentiate along (default 0, the frame axis). |
0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The derivative. Same shape as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
temporal_stats(signal: npt.NDArray[np.float64], axis: int = 0) -> TemporalStats
¶
Summary statistics of a signal along an axis.
Returns mean, std, min, max, and the third/fourth standardized moments
(skewness and excess kurtosis), all reduced over axis. Skew and
kurtosis are computed by hand (no scipy). Where the std is ~0 (a
constant signal) skewness and kurtosis are nan.
All estimators are the population (biased) forms: std uses
ddof=0, and the moments are plain 1/N sums, giving
g₁ = m₃/s³ and g₂ = m₄/s⁴ − 3. The bias-corrected sample
forms — what pandas.Series.skew() / .kurt() / .std()
return, and what scipy gives with bias=False — carry extra
N-dependent factors and differ materially on short signals
(converging as N grows). Kurtosis is excess (normal ⇒ 0), not
raw (normal ⇒ 3). The population convention matches cov3dj and
the rest of pybvh's descriptors, which treat a clip as the whole
population rather than a sample of one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
ndarray
|
Input signal. |
required |
axis
|
int
|
Axis to reduce over (default 0). |
0
|
Returns:
| Type | Description |
|---|---|
TemporalStats
|
Named tuple |
box_filter_smooth(signal: npt.NDArray[np.float64], window: int, axis: int = 0) -> npt.NDArray[np.float64]
¶
Moving-average smoothing with a box kernel of width window.
Edge samples are handled by edge-padding (the alternatives — reflect, zero-pad, or a shrinking window at the ends — bias the first and last samples differently) so the output keeps the input length. Fully vectorized via a cumulative-sum sliding window (no Python loop over the signal).
An even window cannot be centered on a sample; this takes the
extra sample from the future ((window-1)//2 back,
window//2 forward), so the output leads the input by half a
sample. The mirror choice lags by the same amount. Use an odd window
when that half-sample matters, or when matching another
implementation's even-window output.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
ndarray
|
Input signal. |
required |
window
|
int
|
Box width in samples ( |
required |
axis
|
int
|
Axis to smooth along (default 0). |
0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The smoothed signal, same shape as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
fft_magnitude(signal: npt.NDArray[np.float64], fs: float = 1.0, axis: int = 0, *, norm: str = 'backward') -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]
¶
One-sided FFT magnitude spectrum of a real signal.
The default is unnormalized — the raw |rfft(signal)|, with
no rectangular window correction and no scaling. Raw magnitude
scales with signal length, so values are comparable across bins and
across signals of the same length only; select a normalization
via norm before comparing spectra of different lengths or
against published amplitudes. :func:sparc normalizes by its own
peak, so this choice does not affect it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
ndarray
|
Real input signal. |
required |
fs
|
float
|
Sampling rate in Hz (default 1.0). |
1.0
|
axis
|
int
|
Axis to transform along (default 0). |
0
|
norm
|
('backward', 'ortho', 'forward', 'amplitude')
|
Normalization of the returned magnitude. The first three follow
numpy's |
"backward"
|
Returns:
| Name | Type | Description |
|---|---|---|
freqs |
(ndarray, shape(T // 2 + 1))
|
Non-negative frequency bins in Hz. |
magnitude |
ndarray
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
dominant_frequency(signal: npt.NDArray[np.float64], fs: float, axis: int = 0) -> npt.NDArray[np.float64]
¶
Frequency (Hz) of the largest non-DC spectral component.
The DC bin is excluded so a non-zero mean doesn't dominate.
The peak is the argmax of the raw spectrum at native bin resolution
fs / T: no zero-padding, no window, no sub-bin interpolation.
Resolution is therefore fs / T, and rectangular-window leakage
can move the winning bin for a tone falling between bins — pad the
signal or use quadratic peak interpolation if you need better than
bin precision. Exact ties go to the lowest frequency
(np.argmax).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
ndarray
|
Real input signal. |
required |
fs
|
float
|
Sampling rate in Hz. |
required |
axis
|
int
|
Axis to analyze along (default 0). |
0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Dominant frequency with |
ramer_douglas_peucker(curve: npt.NDArray[np.float64], eps: float) -> npt.NDArray[np.float64]
¶
Simplify a polyline with the Ramer–Douglas–Peucker algorithm.
Drops points that lie within eps of the simplified path, keeping the
overall shape. Operates on a single curve (recursion over the curve's
own points, not over a batch); each split's perpendicular distances are
computed vectorized.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
curve
|
(ndarray, shape(P, D))
|
Ordered points of one curve (any dimension |
required |
eps
|
float
|
Maximum allowed perpendicular deviation. |
required |
Returns:
| Type | Description |
|---|---|
(ndarray, shape(K, D))
|
The retained points (endpoints always kept), in order. |