visualdynamics.core.kurtosis¶
kurtosis
¶
How Gaussian a record is, channel by channel.
A random vibration test is specified as a spectrum, and a spectrum says nothing about the shape of the distribution that produced it. Two records with identical PSDs can be a smooth Gaussian hiss and a train of rare hard peaks, and the second fatigues an article in a way the first never will. Kurtosis is the number that tells them apart, and reading it per channel is how a rattling fixture or a clipping amplifier is caught while the spectrum still looks right.
Pearson, not Fisher (Brandon, 2026-08-24). The Pearson kurtosis of
a Gaussian is 3; Fisher's "excess" form subtracts that 3 so a Gaussian
reads 0. Both are in use and they differ by exactly three, which is
the sort of ambiguity that ends in a report claiming a value it did
not compute — so the nominal is written down here as NOMINAL and
every reading of it says which one it is.
The band: within TOLERANCE of nominal is unremarkable, and beyond it
in either direction is worth looking at. High is the interesting
direction — peaks the spectrum did not predict — but low matters too,
because a record that reads much under three has usually been
clipped or is not random at all.
Functions:
| Name | Description |
|---|---|
kurtosis |
The Pearson kurtosis of one record: 3 for a Gaussian. |
analysed_span |
Which stretch of a record the analysis reads, and its name. |
channel_kurtosis |
[(channel label, Pearson kurtosis)] for a time history. |
Functions:¶
kurtosis
¶
The Pearson kurtosis of one record: 3 for a Gaussian.
The population (biased) estimator, m4 / m2**2, which is what
every vibration-test convention quotes and what
scipy.stats.kurtosis(fisher=False, bias=True) returns — the
tests hold this against scipy rather than restating the algebra.
A record with no variance has no shape to describe, so it answers NaN rather than dividing by zero: a dead channel is not a Gaussian one.
Source code in src/visualdynamics/core/kurtosis.py
analysed_span
¶
Which stretch of a record the analysis reads, and its name.
The same stretch the spectra beside it are computed from, and for a reason found the hard way (Brandon, 2026-08-24): a system-ID excitation read whole came out at 4.23 where every steady frame of it read 2.92. Nothing was wrong with the arithmetic — the record is only a quarter analysed, and the silent lead-in and tail make the whole record a mixture of a loud distribution and a quiet one, which genuinely is not Gaussian. A number that disagrees with the PSD printed beside it is worse than no number, so the reading covers what the PSD covers.
Returns ([(first, last), ...], phrase) — sample ranges and
what to call them in a caption. A record with frames set answers
with its analysis span, one with shocks found answers with those
windows (order does not matter to a distribution, so separate
windows read together), and one with neither is read whole.
Source code in src/visualdynamics/core/kurtosis.py
channel_kurtosis
¶
[(channel label, Pearson kurtosis)] for a time history.
Read over analysed_span — the stretch the spectra beside it are
computed from — so the two readings describe one thing.
Every channel on one chart whatever it measures (Brandon, 2026-08-24): kurtosis is dimensionless, so accelerations, forces and volts share an axis honestly — which is the one reading in this package where mixing quantities is not a lie. Channels whose record is dead answer NaN and draw as a gap rather than as zero, which would read as an impossibly flat distribution.