How we check our maths
By MegaRows · Full comparison last run
Every result of the Math tools (formulas, filters, spectra, statistics and fatigue counts) is checked against the software scientists and engineers trust most for this work. We gave both the same file and the same settings and compared the answers number by number.
Summary
526 checks, all passing. Every operation, option and formula function of the Math dialog, last compared on 8 October 2026.
- Checks
- 526
- Passed
- 526
- Identical to the last digit
- 341
- Largest difference
- 1.2 × 10⁻¹¹
How the checks work
We made one sample file of invented signals: 4,000 readings taken 1,000 times a second, with two tones, random noise, a sudden step, a column with empty cells and a few columns for fatigue counts and prices. Then we ran every calculation in the Math dialog on it twice: once in MegaRows, exactly as the dialog does it, and once with NumPy and SciPy, the free scientific libraries for Python that most engineers and researchers use, with the same settings. Every output value was compared.
The sample file is public: download it and you can repeat any check yourself. It is also the sample signal behind FFT from CSV.
How we check
These are our own checks, not an independent audit: MegaRows writes and runs them, and the recipe below lets you repeat three of them yourself. The full comparison runs every calculation of the Math dialog, with every option it offers, through MegaRows and through NumPy and SciPy, and compares every output value; it was last run on 8 October 2026. Between full runs, our automated tests check the same operations and options against SciPy’s stored answers on every change to the site, so a change that moved a result would be caught.
What the differences mean
Computers store numbers with about 16 significant digits, and two programs that add up the same numbers in a different order can disagree in the last one or two. So a check does not ask for identical answers. It measures the largest difference between the two results, divided by the size of the result, and passes when that is tiny:
- none: identical to the last digit (341 of the 526 checks);
- 10⁻¹⁵ means one part in a million billion: the last digit a computer keeps. Single functions such as a sine or a logarithm are held to this;
- 10⁻¹² is the limit for sums, statistics, fits and spectra: still a thousand times finer than anything a plot or a table can show;
- 10⁻¹⁰ is the limit for the filters, which work out their own coefficients and carry the last digits through every sample.
The largest difference of all is 1.2 × 10⁻¹¹ of the result, in Savitzky-Golay smoothing, and there SciPy is the less precise of the two: against the exact answer, MegaRows agrees to the last digit.
Results by operation
Each operation, how many outputs and options were checked, and the largest difference found (relative to the size of the result).
| Operation | Group | Checks | Largest difference | Result |
|---|---|---|---|---|
| CSV import | Data | 6 | none | Pass |
| Sample rate from the X column | Data | 1 | none | Pass |
| Formula | Formula | 79 | 8.2 × 10⁻¹⁵ | Pass |
| Scale and offset | Arithmetic | 1 | none | Pass |
| Absolute value | Arithmetic | 1 | none | Pass |
| Normalize (0-1) | Arithmetic | 1 | none | Pass |
| Z-score | Arithmetic | 2 | 6.2 × 10⁻¹⁶ | Pass |
| Moving average | Time domain | 4 | 2.7 × 10⁻¹⁶ | Pass |
| Moving RMS | Time domain | 4 | 4.3 × 10⁻¹⁶ | Pass |
| Moving standard deviation | Time domain | 3 | 1.1 × 10⁻¹⁴ | Pass |
| Expanding mean | Time domain | 1 | 1.2 × 10⁻¹⁶ | Pass |
| Expanding standard deviation | Time domain | 2 | 5 × 10⁻¹⁶ | Pass |
| Envelope (moving min / max) | Time domain | 4 | none | Pass |
| Exponential moving average | Time domain | 4 | 2.7 × 10⁻¹⁶ | Pass |
| Envelope (Hilbert) | Time domain | 2 | 4.9 × 10⁻¹⁶ | Pass |
| Cumulative sum | Time domain | 1 | 1.7 × 10⁻¹⁵ | Pass |
| Difference | Time domain | 2 | none | Pass |
| Derivative | Time domain | 3 | none | Pass |
| Integral (cumulative) | Time domain | 3 | 1.2 × 10⁻¹⁵ | Pass |
| Detrend | Time domain | 4 | 1.2 × 10⁻¹⁴ | Pass |
| Peak detection | Time domain | 20 | none | Pass |
| Zero crossings | Time domain | 28 | none | Pass |
| Resample to uniform rate | Time domain | 4 | none | Pass |
| Median filter | Filtering | 5 | none | Pass |
| Butterworth filter | Filtering | 11 | 5.6 × 10⁻¹⁵ | Pass |
| Savitzky-Golay smoothing | Filtering | 4 | 1.2 × 10⁻¹¹ | Pass |
| Decimate (with anti-alias filter) | Filtering | 6 | 2.3 × 10⁻¹⁴ | Pass |
| FFT spectrum | Frequency domain | 21 | 1.5 × 10⁻¹⁴ | Pass |
| PSD (Welch) | Frequency domain | 34 | 2.4 × 10⁻¹⁵ | Pass |
| FRF (H1 / H2) and coherence | Frequency domain | 24 | 4.5 × 10⁻¹⁴ | Pass |
| Band SNR | Frequency domain | 15 | 3.5 × 10⁻¹⁴ | Pass |
| Spectrogram | Frequency domain | 30 | 1.1 × 10⁻¹⁵ | Pass |
| Histogram | Statistics | 45 | none | Pass |
| RMS, crest factor, peak to peak | Statistics | 8 | 2.5 × 10⁻¹⁵ | Pass |
| Percentiles, skewness, kurtosis | Statistics | 14 | 7.9 × 10⁻¹⁴ | Pass |
| Correlation (Pearson) | Statistics | 4 | 7.2 × 10⁻¹⁵ | Pass |
| Polynomial fit | Statistics | 25 | 4.8 × 10⁻¹³ | Pass |
| Cross-correlation | Statistics | 24 | 8.9 × 10⁻¹⁶ | Pass |
| Rainflow counting and damage | Engineering | 64 | none | Pass |
| Shock response spectrum | Engineering | 12 | 1.1 × 10⁻¹⁴ | Pass |
Every check
Grouped as in the Math dialog. Open a group to see each check: our settings, the reference calculation in Python and the largest difference.
Data7 checks · all passing · largest none
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| CSV import | time_s | float() of each cell of time_s (Python) | none | identical | PASS |
| CSV import | signal_a | float() of each cell of signal_a (Python) | none | identical | PASS |
| CSV import | signal_a_gaps | float() of each cell of signal_a_gaps (Python) | none | identical | PASS |
| CSV import | signal_b | float() of each cell of signal_b (Python) | none | identical | PASS |
| CSV import | load_cycles | float() of each cell of load_cycles (Python) | none | identical | PASS |
| CSV import | price | float() of each cell of price (Python) | none | identical | PASS |
| Sample rate from the X columnfs | 1 / numpy.median(numpy.diff(time_s)) | none | identical | PASS |
Formula79 checks · all passing · largest 8.2 × 10⁻¹⁵
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| Formula | abs(signal_a_gaps) | numpy.abs | none | identical | PASS |
| Formula | sqrt(price) | numpy.sqrt | none | identical | PASS |
| Formula | sqrt(signal_a) | numpy.sqrt (NaN for negative values) | none | identical | PASS |
| Formula | exp(signal_a) | numpy.exp | 1.1 × 10⁻¹⁶ | 10⁻¹⁵ | PASS |
| Formula | log(price) | numpy.log | 3.7 × 10⁻¹⁵ | 10⁻¹⁴ | PASS |
| Formula | log(price, 3) | numpy.emath.logn(3, price) | 8.2 × 10⁻¹⁵ | 10⁻¹⁴ | PASS |
| Formula | log10(price) | numpy.log10 | 4.3 × 10⁻¹⁵ | 10⁻¹⁴ | PASS |
| Formula | log2(price) | numpy.log2 | 2.6 × 10⁻¹⁵ | 10⁻¹⁴ | PASS |
| Formula | sin(signal_a) | numpy.sin | 5.6 × 10⁻¹⁷ | 10⁻¹⁵ | PASS |
| Formula | cos(signal_a) | numpy.cos | 5.6 × 10⁻¹⁷ | 10⁻¹⁵ | PASS |
| Formula | tan(signal_a) | numpy.tan | 1.7 × 10⁻¹⁸ | 10⁻¹⁵ | PASS |
| Formula | asin(signal_a / 4) | numpy.arcsin(signal_a / 4) | 6.9 × 10⁻¹⁷ | 10⁻¹⁵ | PASS |
| Formula | acos(signal_a / 4) | numpy.arccos(signal_a / 4) | 1.4 × 10⁻¹⁶ | 10⁻¹⁵ | PASS |
| Formula | atan(signal_a) | numpy.arctan | 9.2 × 10⁻¹⁷ | 10⁻¹⁵ | PASS |
| Formula | atan2(signal_b, signal_a) | numpy.arctan2(signal_b, signal_a) | 7.1 × 10⁻¹⁷ | 10⁻¹⁵ | PASS |
| Formula | sinh(signal_a) | numpy.sinh | 2.7 × 10⁻¹⁸ | 10⁻¹⁵ | PASS |
| Formula | cosh(signal_a) | numpy.cosh | 1.1 × 10⁻¹⁶ | 10⁻¹⁵ | PASS |
| Formula | tanh(signal_a) | numpy.tanh | 1.1 × 10⁻¹⁶ | 10⁻¹⁵ | PASS |
| Formula | deg(signal_a) | numpy.degrees | 8.9 × 10⁻¹⁷ | 10⁻¹⁵ | PASS |
| Formula | rad(signal_a) | numpy.radians | 7.2 × 10⁻¹⁷ | 10⁻¹⁵ | PASS |
| Formula | min(signal_a) | signal_a (one argument) | none | identical | PASS |
| Formula | min(signal_a_gaps, signal_b) | numpy.minimum (NaN propagates) | none | identical | PASS |
| Formula | min(signal_a, signal_b, 0.5) | numpy.minimum.reduce([signal_a, signal_b, 0.5]) | none | identical | PASS |
| Formula | max(signal_a_gaps, signal_b) | numpy.maximum (NaN propagates) | none | identical | PASS |
| Formula | max(signal_a, signal_b, 0.5) | numpy.maximum.reduce([signal_a, signal_b, 0.5]) | none | identical | PASS |
| Formula | clamp(signal_a_gaps, -1, 1.5) | numpy.clip(signal_a_gaps, -1, 1.5) | none | identical | PASS |
| Formula | round(price) | half away from zero: sign(x)·floor(|x| + 1/2) (numpy.round rounds half to even) | none | identical | PASS |
| Formula | round(price, 1) | half_away(price · 10) / 10 (numpy.round(price, 1) rounds half to even) | none | identical | PASS |
| Formula | round(signal_a, 3) | half_away(signal_a · 1000) / 1000 | none | identical | PASS |
| Formula | floor(signal_a) | numpy.floor | none | identical | PASS |
| Formula | ceil(signal_a) | numpy.ceil | none | identical | PASS |
| Formula | trunc(signal_a) | numpy.trunc | none | identical | PASS |
| Formula | pow(price, 1.5) | numpy.power(price, 1.5) | none | 10⁻¹⁵ | PASS |
| Formula | pow(signal_a, signal_b) | numpy.power(signal_a, signal_b) (NaN for a negative base) | none | 10⁻¹⁵ | PASS |
| Formula | hypot(signal_a) | numpy.abs (one argument) | none | identical | PASS |
| Formula | hypot(signal_a, signal_b) | numpy.hypot | 2.5 × 10⁻¹⁶ | 10⁻¹⁵ | PASS |
| Formula | hypot(signal_a, signal_b, price) | numpy.hypot(numpy.hypot(signal_a, signal_b), price) | 1.1 × 10⁻¹⁵ | 10⁻¹⁴ | PASS |
| Formula | sign(signal_a_gaps) | numpy.sign | none | identical | PASS |
| Formula | mod(load_cycles, 7) | numpy.mod (floored: sign of the divisor) | none | identical | PASS |
| Formula | mod(signal_a, -0.7) | numpy.mod(signal_a, -0.7) | none | identical | PASS |
| Formula | isnan(signal_a_gaps) | numpy.isnan | none | identical | PASS |
| Formula | isfinite(signal_a_gaps / signal_a_gaps * (signal_a - 0.5) / round(signal_a - 0.5)) | numpy.isfinite (with ±inf from a division by 0) | none | identical | PASS |
| Formula | coalesce(signal_a_gaps, signal_b) | pandas.DataFrame([signal_a_gaps, signal_b]).bfill(axis=1) first column | none | identical | PASS |
| Formula | coalesce(signal_a_gaps, signal_a_gaps * 2, price) | pandas bfill(axis=1) over three columns | none | identical | PASS |
| Formula | if(signal_a_gaps > 1, signal_b, price) | numpy.where(isnan(c), nan, numpy.where(c > 1, signal_b, price)) | none | identical | PASS |
| Formula | signal_a + signal_b | numpy.add | none | identical | PASS |
| Formula | signal_a_gaps - signal_b | numpy.subtract | none | identical | PASS |
| Formula | signal_a * signal_b | numpy.multiply | none | identical | PASS |
| Formula | signal_a / signal_b | numpy.divide | none | identical | PASS |
| Formula | load_cycles % 7 | numpy.mod | none | identical | PASS |
| Formula | price ^ 2 | numpy.power(price, 2) | none | identical | PASS |
| Formula | signal_a ^ 3 | numpy.power(signal_a, 3) | 1.4 × 10⁻¹⁶ | 10⁻¹⁵ | PASS |
| Formula | price ^ signal_a | numpy.power(price, signal_a) | none | 10⁻¹⁵ | PASS |
| Formula | price ** 0.5 | numpy.power(price, 0.5) (MegaRows takes the square root, which is correctly rounded; C pow may differ by one unit in the last place) | 1.4 × 10⁻¹⁵ | 10⁻¹⁴ | PASS |
| Formula | -signal_a_gaps | numpy.negative | none | identical | PASS |
| Formula | +signal_a | signal_a | none | identical | PASS |
| Formula | -signal_a ^ 2 | -(signal_a ** 2) (power binds tighter than unary minus) | none | identical | PASS |
| Formula | 2 ^ -1 * signal_a + signal_b * price - 3 / price | 0.5 * signal_a + signal_b * price - 3 / price | none | identical | PASS |
| Formula | signal_a_gaps < signal_b | pandas Float64 array < (missing -> <NA> -> NaN) | none | identical | PASS |
| Formula | signal_a_gaps <= signal_b | pandas Float64 array <= | none | identical | PASS |
| Formula | signal_a_gaps > signal_b | pandas Float64 array > | none | identical | PASS |
| Formula | signal_a_gaps >= signal_b | pandas Float64 array >= | none | identical | PASS |
| Formula | round(signal_a_gaps) == 1 | pandas Float64 array == | none | identical | PASS |
| Formula | round(signal_a_gaps) != 1 | pandas Float64 array != | none | identical | PASS |
| Formula | round(signal_a_gaps) <> 1 | pandas Float64 array != | none | identical | PASS |
| Formula | signal_a_gaps > 0 && signal_b > 0 | pandas boolean array & (Kleene logic: False & <NA> = False) | none | identical | PASS |
| Formula | signal_a_gaps > 0 and signal_b < 0 | pandas boolean array & | none | identical | PASS |
| Formula | signal_a_gaps > 0 || signal_b > 0 | pandas boolean array | (Kleene logic: True | <NA> = True) | none | identical | PASS |
| Formula | signal_a_gaps > 0 or signal_b < 0 | pandas boolean array | | none | identical | PASS |
| Formula | !(signal_a_gaps > 0) | pandas boolean array ~ | none | identical | PASS |
| Formula | not signal_a_gaps | pandas boolean array ~ of (signal_a_gaps != 0) | none | identical | PASS |
| Formula | signal_a × signal_b − price ÷ 100 | signal_a * signal_b - price / 100 | none | identical | PASS |
| Formula | signal_a · 2 | signal_a * 2 | none | identical | PASS |
| Formula | signal_a_gaps ≤ signal_b | pandas Float64 array <= | none | identical | PASS |
| Formula | signal_a_gaps ≥ signal_b | pandas Float64 array >= | none | identical | PASS |
| Formula | round(signal_a_gaps) ≠ 1 | pandas Float64 array != | none | identical | PASS |
| Formula | 2 * pi * 50 * t | 2 * numpy.pi * 50 * time_s | none | identical | PASS |
| Formula | e ^ signal_a | numpy.power(numpy.e, signal_a) | none | 10⁻¹⁵ | PASS |
| Formula | x * 1000 - i | time_s * 1000 - numpy.arange(n) | none | identical | PASS |
Arithmetic5 checks · all passing · largest 6.2 × 10⁻¹⁶
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| Scale and offset | signal_a_gaps; scale 9.81, offset -2.5 | signal_a_gaps * 9.81 + -2.5 (numpy) | none | identical | PASS |
| Absolute value | signal_a_gaps | numpy.abs(signal_a_gaps) | none | identical | PASS |
| Normalize (0-1) | signal_a_gaps | (y - numpy.nanmin(y)) / (numpy.nanmax(y) - numpy.nanmin(y)) | none | identical | PASS |
| Z-score | signal_a_gaps; ddof 0 | scipy.stats.zscore(signal_a_gaps, ddof=0, nan_policy='omit') | 6.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Z-score | signal_a_gaps; ddof 1 | scipy.stats.zscore(signal_a_gaps, ddof=1, nan_policy='omit') | 5.4 × 10⁻¹⁶ | 10⁻¹² | PASS |
Time domain89 checks · all passing · largest 1.2 × 10⁻¹⁴
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| Moving average | signal_a; window 101, align centered | pandas.Series(signal_a).rolling(101, center=True, min_periods=1).mean() | 2.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving RMS | signal_a; window 101, align centered | numpy.sqrt(pandas.Series(signal_a**2).rolling(101, center=True, min_periods=1).mean()) | 4.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving average | signal_a; window 100, align centered | pandas.Series(signal_a).rolling(100, center=True, min_periods=1).mean() | 2.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving RMS | signal_a; window 100, align centered | numpy.sqrt(pandas.Series(signal_a**2).rolling(100, center=True, min_periods=1).mean()) | 4.3 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving average | signal_a; window 25, align trailing | pandas.Series(signal_a).rolling(25, center=False, min_periods=1).mean() | 2.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving RMS | signal_a; window 25, align trailing | numpy.sqrt(pandas.Series(signal_a**2).rolling(25, center=False, min_periods=1).mean()) | 2.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving average | signal_a_gaps; window 101, align centered | pandas.Series(signal_a_gaps).rolling(101, center=True, min_periods=1).mean() | 2.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving RMS | signal_a_gaps; window 101, align centered | numpy.sqrt(pandas.Series(signal_a_gaps**2).rolling(101, center=True, min_periods=1).mean()) | 4.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Moving standard deviation | signal_a; window 101, align centered, ddof 1 | pandas.Series(signal_a).rolling(101, center=True, min_periods=1).std(ddof=1) | 9.1 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Moving standard deviation | signal_a; window 100, align trailing, ddof 0 | pandas.Series(signal_a).rolling(100, center=False, min_periods=1).std(ddof=0) | 2.5 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Moving standard deviation | signal_a_gaps; window 51, align centered, ddof 1 | pandas.Series(signal_a_gaps).rolling(51, center=True, min_periods=1).std(ddof=1) | 1.1 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Expanding mean | signal_a_gaps | pandas.Series(signal_a_gaps).expanding(min_periods=1).mean() | 1.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Expanding standard deviation | signal_a_gaps; ddof 1 | pandas.Series(signal_a_gaps).expanding(min_periods=1).std(ddof=1) | 5 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Expanding standard deviation | signal_a_gaps; ddof 0 | pandas.Series(signal_a_gaps).expanding(min_periods=1).std(ddof=0) | 4 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Envelope (moving min / max) | signal_a; window 101, align centered, side upper | pandas.Series(signal_a).rolling(101, center=True, min_periods=1).max() | none | identical | PASS |
| Envelope (moving min / max) | signal_a; window 101, align centered, side lower | pandas.Series(signal_a).rolling(101, center=True, min_periods=1).min() | none | identical | PASS |
| Envelope (moving min / max) | signal_a_gaps; window 20, align trailing, side upper | pandas.Series(signal_a_gaps).rolling(20, center=False, min_periods=1).max() | none | identical | PASS |
| Envelope (moving min / max) | signal_a_gaps; window 20, align trailing, side lower | pandas.Series(signal_a_gaps).rolling(20, center=False, min_periods=1).min() | none | identical | PASS |
| Exponential moving average | signal_a; mode span, span 20 | pandas.Series(signal_a).ewm(span=20, adjust=False).mean() | 1.8 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Exponential moving average | signal_a_gaps; mode alpha, alpha 0.1 | pandas.Series(signal_a_gaps).ewm(alpha=0.1, adjust=False, ignore_na=True).mean(), missing rows kept missing | 2.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Exponential moving average | signal_a; mode tau, tau 0.02 | explicit recurrence s += (1 - exp(-Δt / 0.02)) · (y - s) over time_s (numpy; pandas has no adjust=False form with times) | 5.4 × 10⁻¹⁷ | 10⁻¹² | PASS |
| Exponential moving average | signal_a; X: row number; mode tau, tau 5 | pandas.Series(signal_a).ewm(alpha=1 - exp(-1/5), adjust=False).mean() (X = row number) | 1.4 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Envelope (Hilbert) | signal_a | numpy.abs(scipy.signal.hilbert(signal_a)) | 4.9 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Envelope (Hilbert) | signal_a_gaps | numpy.abs(scipy.signal.hilbert(gaps filled by numpy.interp over time_s)), gaps restored | 4.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cumulative sum | signal_a_gaps | numpy.nancumsum(signal_a_gaps), missing rows kept missing | 1.7 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Difference | signal_a_gaps; lag 1 | pandas.Series(signal_a_gaps).diff(1) | none | identical | PASS |
| Difference | signal_a_gaps; lag 5 | pandas.Series(signal_a_gaps).diff(5) | none | identical | PASS |
| Derivative | signal_a | numpy.gradient(signal_a, time_s) | none | 10⁻¹² | PASS |
| Derivative | signal_a_gaps | numpy.gradient(signal_a_gaps, time_s) | none | 10⁻¹² | PASS |
| Derivative | signal_a; X: row number | numpy.gradient(signal_a) (X = row number) | none | 10⁻¹² | PASS |
| Integral (cumulative) | signal_a; initial 0 | scipy.integrate.cumulative_trapezoid(signal_a, time_s, initial=0) | 9.6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Integral (cumulative) | signal_a; initial 10 | 10 + scipy.integrate.cumulative_trapezoid(signal_a, time_s, initial=0) | 1.2 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Integral (cumulative) | signal_a_gaps; initial 0 | numpy: cumsum of Δt·(y[i] + y[i-1]) / 2 with intervals touching a gap as 0, missing rows kept missing | 9.6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Detrend | signal_a; type linear | signal_a - numpy.polyval(numpy.polyfit(time_s, signal_a, 1), time_s) | 1.2 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Detrend | signal_a_gaps; type constant | signal_a_gaps - numpy.nanmean(signal_a_gaps) | 4 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Detrend | signal_a_gaps; type linear | numpy.polyfit over the rows with a value, against time_s | 1.4 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Detrend | signal_a; X: row number; type linear | scipy.signal.detrend(signal_a, type='linear') (X = row number) | 1.4 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Peak detectionRow | signal_a | scipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominences | none | identical | PASS |
| Peak detectiontime_s | signal_a | scipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominences | none | identical | PASS |
| Peak detectionHeight | signal_a | scipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominences | none | identical | PASS |
| Peak detectionProminence | signal_a | scipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominences | none | identical | PASS |
| Peak detectioncount | signal_a | scipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominences | none | identical | PASS |
| Peak detectionRow | signal_a; height 1.0, distance 20 | scipy.signal.find_peaks(signal_a, height=1.0, distance=20) | none | identical | PASS |
| Peak detectiontime_s | signal_a; height 1.0, distance 20 | scipy.signal.find_peaks(signal_a, height=1.0, distance=20) | none | identical | PASS |
| Peak detectionHeight | signal_a; height 1.0, distance 20 | scipy.signal.find_peaks(signal_a, height=1.0, distance=20) | none | identical | PASS |
| Peak detectionProminence | signal_a; height 1.0, distance 20 | scipy.signal.find_peaks(signal_a, height=1.0, distance=20) | none | identical | PASS |
| Peak detectioncount | signal_a; height 1.0, distance 20 | scipy.signal.find_peaks(signal_a, height=1.0, distance=20) | none | identical | PASS |
| Peak detectionRow | signal_a; prominence 1.5 | scipy.signal.find_peaks(signal_a, prominence=1.5) | none | identical | PASS |
| Peak detectiontime_s | signal_a; prominence 1.5 | scipy.signal.find_peaks(signal_a, prominence=1.5) | none | identical | PASS |
| Peak detectionHeight | signal_a; prominence 1.5 | scipy.signal.find_peaks(signal_a, prominence=1.5) | none | identical | PASS |
| Peak detectionProminence | signal_a; prominence 1.5 | scipy.signal.find_peaks(signal_a, prominence=1.5) | none | identical | PASS |
| Peak detectioncount | signal_a; prominence 1.5 | scipy.signal.find_peaks(signal_a, prominence=1.5) | none | identical | PASS |
| Peak detectionRow | signal_a_gaps; height 0.5, prominence 0.3, distance 5 | scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3) | none | identical | PASS |
| Peak detectiontime_s | signal_a_gaps; height 0.5, prominence 0.3, distance 5 | scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3) | none | identical | PASS |
| Peak detectionHeight | signal_a_gaps; height 0.5, prominence 0.3, distance 5 | scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3) | none | identical | PASS |
| Peak detectionProminence | signal_a_gaps; height 0.5, prominence 0.3, distance 5 | scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3) | none | identical | PASS |
| Peak detectioncount | signal_a_gaps; height 0.5, prominence 0.3, distance 5 | scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3) | none | identical | PASS |
| Zero crossingsRow | signal_a; level 0.0, direction both | numpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingstime_s | signal_a; level 0.0, direction both | numpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsDirection (+1 rising, −1 falling) | signal_a; level 0.0, direction both | numpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingscount | signal_a; level 0.0, direction both | numpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrising | signal_a; level 0.0, direction both | numpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsfalling | signal_a; level 0.0, direction both | numpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrate | signal_a; level 0.0, direction both | numpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsRow | signal_a; level 1.0, direction rising | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingstime_s | signal_a; level 1.0, direction rising | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsDirection (+1 rising, −1 falling) | signal_a; level 1.0, direction rising | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingscount | signal_a; level 1.0, direction rising | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrising | signal_a; level 1.0, direction rising | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsfalling | signal_a; level 1.0, direction rising | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrate | signal_a; level 1.0, direction rising | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsRow | signal_a; level 1.0, direction falling | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingstime_s | signal_a; level 1.0, direction falling | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsDirection (+1 rising, −1 falling) | signal_a; level 1.0, direction falling | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingscount | signal_a; level 1.0, direction falling | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrising | signal_a; level 1.0, direction falling | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsfalling | signal_a; level 1.0, direction falling | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrate | signal_a; level 1.0, direction falling | numpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsRow | signal_a_gaps; level 0.5, direction both | numpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingstime_s | signal_a_gaps; level 0.5, direction both | numpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsDirection (+1 rising, −1 falling) | signal_a_gaps; level 0.5, direction both | numpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingscount | signal_a_gaps; level 0.5, direction both | numpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrising | signal_a_gaps; level 0.5, direction both | numpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsfalling | signal_a_gaps; level 0.5, direction both | numpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_s | none | identical | PASS |
| Zero crossingsrate | signal_a_gaps; level 0.5, direction both | numpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_s | none | identical | PASS |
| Resample to uniform ratex | signal_a_gaps; rate 250 | numpy.interp(time_s[0] + k / 250, time_s, signal_a_gaps) over the rows with a value | none | identical | PASS |
| Resample to uniform ratesignal_a_gaps | signal_a_gaps; rate 250 | numpy.interp(time_s[0] + k / 250, time_s, signal_a_gaps) over the rows with a value | none | identical | PASS |
| Resample to uniform ratex | signal_a_gaps; rate 1500 | numpy.interp(time_s[0] + k / 1500, time_s, signal_a_gaps) over the rows with a value | none | identical | PASS |
| Resample to uniform ratesignal_a_gaps | signal_a_gaps; rate 1500 | numpy.interp(time_s[0] + k / 1500, time_s, signal_a_gaps) over the rows with a value | none | identical | PASS |
Filtering26 checks · all passing · largest 1.2 × 10⁻¹¹
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| Median filter | signal_a; window 5, align centered | pandas.Series(signal_a).rolling(5, center=True, min_periods=1).median() | none | identical | PASS |
| Median filter | signal_a; window 6, align centered | pandas.Series(signal_a).rolling(6, center=True, min_periods=1).median() | none | identical | PASS |
| Median filter | signal_a; window 11, align trailing | pandas.Series(signal_a).rolling(11, center=False, min_periods=1).median() | none | identical | PASS |
| Median filter | signal_a; window 101, align centered | pandas.Series(signal_a).rolling(101, center=True, min_periods=1).median() | none | identical | PASS |
| Median filter | signal_a_gaps; window 5, align centered | pandas.Series(signal_a_gaps).rolling(5, center=True, min_periods=1).median() | none | identical | PASS |
| Butterworth filter | signal_a; type lowpass, order 4, cutoff 50.0, zeroPhase on | scipy.signal.sosfiltfilt(scipy.signal.butter(4, 50.0, 'lowpass', fs=fs, output='sos'), signal_a) | 9.4 × 10⁻¹⁶ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type lowpass, order 4, cutoff 50.0, zeroPhase off | scipy.signal.sosfilt(scipy.signal.butter(4, 50.0, 'lowpass', fs=fs, output='sos'), signal_a) | none | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type highpass, order 3, cutoff 20.0, zeroPhase on | scipy.signal.sosfiltfilt(scipy.signal.butter(3, 20.0, 'highpass', fs=fs, output='sos'), signal_a) | 2.4 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type highpass, order 7, cutoff 100.0, zeroPhase off | scipy.signal.sosfilt(scipy.signal.butter(7, 100.0, 'highpass', fs=fs, output='sos'), signal_a) | none | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type bandpass, order 2, cutoff 30.0–80.0, zeroPhase on | scipy.signal.sosfiltfilt(scipy.signal.butter(2, [30.0, 80.0], 'bandpass', fs=fs, output='sos'), signal_a) | 2.1 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type bandpass, order 5, cutoff 100.0–140.0, zeroPhase off | scipy.signal.sosfilt(scipy.signal.butter(5, [100.0, 140.0], 'bandpass', fs=fs, output='sos'), signal_a) | 1.9 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type bandstop, order 4, cutoff 40.0–60.0, zeroPhase on | scipy.signal.sosfiltfilt(scipy.signal.butter(4, [40.0, 60.0], 'bandstop', fs=fs, output='sos'), signal_a) | 5.6 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type bandstop, order 6, cutoff 110.0–130.0, zeroPhase off | scipy.signal.sosfilt(scipy.signal.butter(6, [110.0, 130.0], 'bandstop', fs=fs, output='sos'), signal_a) | 2.5 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type lowpass, order 1, cutoff 10.0, zeroPhase on | scipy.signal.sosfiltfilt(scipy.signal.butter(1, 10.0, 'lowpass', fs=fs, output='sos'), signal_a) | 4.5 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a; type lowpass, order 10, cutoff 100.0, zeroPhase on | scipy.signal.sosfiltfilt(scipy.signal.butter(10, 100.0, 'lowpass', fs=fs, output='sos'), signal_a) | 2.8 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Butterworth filter | signal_a_gaps; type lowpass, order 4, cutoff 50.0, zeroPhase on | scipy.signal.sosfiltfilt(scipy.signal.butter(4, 50.0, 'lowpass', fs=fs, output='sos'), signal_a_gaps) with gaps filled by numpy.interp, gaps restored | 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Savitzky-Golay smoothing | signal_a; window 11, polyorder 3 | scipy.signal.savgol_filter(signal_a, 11, 3, mode='interp') | 2.2 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Savitzky-Golay smoothing | signal_a; window 51, polyorder 4 | scipy.signal.savgol_filter(signal_a, 51, 4, mode='interp') | 1.2 × 10⁻¹¹ | 10⁻¹⁰ | PASS |
| Savitzky-Golay smoothing | signal_a_gaps; window 11, polyorder 3 | scipy.signal.savgol_filter(signal_a_gaps, 11, 3, mode='interp') | 2.2 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Savitzky-Golay smoothing | signal_a; window 51, polyorder 4 | the same filter in exact rational arithmetic (Python fractions.Fraction), rounded once at the end | 6.5 × 10⁻¹⁶ | 10⁻¹³ | PASS |
| Decimate (with anti-alias filter)x | signal_a; factor 4, zeroPhase on | scipy.signal.decimate(signal_a, 4, zero_phase=True) | none | 10⁻¹⁰ | PASS |
| Decimate (with anti-alias filter)signal_a | signal_a; factor 4, zeroPhase on | scipy.signal.decimate(signal_a, 4, zero_phase=True) | 5.5 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
| Decimate (with anti-alias filter)x | signal_a; factor 10, zeroPhase off | scipy.signal.decimate(signal_a, 10, zero_phase=False) | none | 10⁻¹⁰ | PASS |
| Decimate (with anti-alias filter)signal_a | signal_a; factor 10, zeroPhase off | scipy.signal.decimate(signal_a, 10, zero_phase=False) | 2.3 × 10⁻¹⁴ | 10⁻¹⁰ | PASS |
| Decimate (with anti-alias filter)x | signal_a_gaps; factor 4, zeroPhase on | scipy.signal.decimate(signal_a_gaps, 4, zero_phase=True) | none | 10⁻¹⁰ | PASS |
| Decimate (with anti-alias filter)signal_a_gaps | signal_a_gaps; factor 4, zeroPhase on | scipy.signal.decimate(signal_a_gaps, 4, zero_phase=True) | 5.6 × 10⁻¹⁵ | 10⁻¹⁰ | PASS |
Frequency domain124 checks · all passing · largest 4.5 × 10⁻¹⁴
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| FFT spectrumx | signal_a; window rect, scaling amplitude, detrend none, length all, db off | scipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FFT spectrumAmplitude | signal_a; window rect, scaling amplitude, detrend none, length all, db off | scipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | 2.3 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FFT spectrumdf | signal_a; window rect, scaling amplitude, detrend none, length all, db off | scipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | none | 10⁻¹² | PASS |
| FFT spectrumx | signal_a; window hann, scaling rms, detrend constant, length all, db off | scipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='constant', scaling='spectrum') → sqrt(P) | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FFT spectrumRMS amplitude | signal_a; window hann, scaling rms, detrend constant, length all, db off | scipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='constant', scaling='spectrum') → sqrt(P) | 4.8 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FFT spectrumdf | signal_a; window hann, scaling rms, detrend constant, length all, db off | scipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='constant', scaling='spectrum') → sqrt(P) | none | 10⁻¹² | PASS |
| FFT spectrumx | signal_a; window hamming, scaling power, detrend linear, length pow2, db off | scipy.signal.periodogram(signal_a, fs, window='hamming', nfft=4096, detrend='linear', scaling='spectrum') → P | none | 10⁻¹² | PASS |
| FFT spectrumPower | signal_a; window hamming, scaling power, detrend linear, length pow2, db off | scipy.signal.periodogram(signal_a, fs, window='hamming', nfft=4096, detrend='linear', scaling='spectrum') → P | 2.3 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FFT spectrumdf | signal_a; window hamming, scaling power, detrend linear, length pow2, db off | scipy.signal.periodogram(signal_a, fs, window='hamming', nfft=4096, detrend='linear', scaling='spectrum') → P | none | 10⁻¹² | PASS |
| FFT spectrumx | signal_a; window blackman, scaling amplitude, detrend constant, length pow2, db off | scipy.signal.periodogram(signal_a, fs, window='blackman', nfft=4096, detrend='constant', scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | none | 10⁻¹² | PASS |
| FFT spectrumAmplitude | signal_a; window blackman, scaling amplitude, detrend constant, length pow2, db off | scipy.signal.periodogram(signal_a, fs, window='blackman', nfft=4096, detrend='constant', scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | 1.4 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FFT spectrumdf | signal_a; window blackman, scaling amplitude, detrend constant, length pow2, db off | scipy.signal.periodogram(signal_a, fs, window='blackman', nfft=4096, detrend='constant', scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | none | 10⁻¹² | PASS |
| FFT spectrumx | signal_a; window flattop, scaling amplitude, detrend none, length all, db off | scipy.signal.periodogram(signal_a, fs, window='flattop', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FFT spectrumAmplitude | signal_a; window flattop, scaling amplitude, detrend none, length all, db off | scipy.signal.periodogram(signal_a, fs, window='flattop', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | 1.9 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FFT spectrumdf | signal_a; window flattop, scaling amplitude, detrend none, length all, db off | scipy.signal.periodogram(signal_a, fs, window='flattop', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) | none | 10⁻¹² | PASS |
| FFT spectrumx | signal_a; window rect, scaling amplitude, detrend none, length all, db on | scipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) → dB | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FFT spectrumAmplitude | signal_a; window rect, scaling amplitude, detrend none, length all, db on | scipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) → dB | 1.5 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FFT spectrumdf | signal_a; window rect, scaling amplitude, detrend none, length all, db on | scipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) → dB | none | 10⁻¹² | PASS |
| FFT spectrumx | signal_a; window hann, scaling power, detrend linear, length all, db on | scipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='linear', scaling='spectrum') → P → dB | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FFT spectrumPower | signal_a; window hann, scaling power, detrend linear, length all, db on | scipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='linear', scaling='spectrum') → P → dB | 5.6 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FFT spectrumdf | signal_a; window hann, scaling power, detrend linear, length all, db on | scipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='linear', scaling='spectrum') → P → dB | none | 10⁻¹² | PASS |
| PSD (Welch)x | signal_a; nperseg 4096, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=4096, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)PSD | signal_a; nperseg 4096, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=4096, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | 5 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)df | signal_a; nperseg 4096, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=4096, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | none | 10⁻¹² | PASS |
| PSD (Welch)segments | signal_a; nperseg 4096, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=4096, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | none | 10⁻¹² | PASS |
| PSD (Welch)grms | signal_a; nperseg 4096, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=4096, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | 2.4 × 10⁻¹⁵ | 10⁻¹² | PASS |
| PSD (Welch)x | signal_a; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | none | 10⁻¹² | PASS |
| PSD (Welch)PSD | signal_a; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | 8.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)df | signal_a; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | none | 10⁻¹² | PASS |
| PSD (Welch)segments | signal_a; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | none | 10⁻¹² | PASS |
| PSD (Welch)grms | signal_a; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) | 3.9 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)x | signal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db off | scipy.signal.welch(signal_a, fs, window='hamming', nperseg=1024, noverlap=floor(75% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 40.0–130.0 Hz, edges by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)PSD | signal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db off | scipy.signal.welch(signal_a, fs, window='hamming', nperseg=1024, noverlap=floor(75% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 40.0–130.0 Hz, edges by numpy.interp) | 2.4 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)df | signal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db off | scipy.signal.welch(signal_a, fs, window='hamming', nperseg=1024, noverlap=floor(75% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 40.0–130.0 Hz, edges by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)segments | signal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db off | scipy.signal.welch(signal_a, fs, window='hamming', nperseg=1024, noverlap=floor(75% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 40.0–130.0 Hz, edges by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)grms | signal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db off | scipy.signal.welch(signal_a, fs, window='hamming', nperseg=1024, noverlap=floor(75% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 40.0–130.0 Hz, edges by numpy.interp) | 4.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)x | signal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db off | scipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum') | none | 10⁻¹² | PASS |
| PSD (Welch)PSD | signal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db off | scipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum') | 8.1 × 10⁻¹⁸ | 10⁻¹² | PASS |
| PSD (Welch)df | signal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db off | scipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum') | none | 10⁻¹² | PASS |
| PSD (Welch)segments | signal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db off | scipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum') | none | 10⁻¹² | PASS |
| PSD (Welch)x | signal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db off | scipy.signal.welch(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 45.5–54.5 Hz, edges by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)PSD | signal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db off | scipy.signal.welch(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 45.5–54.5 Hz, edges by numpy.interp) | 7.8 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)df | signal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db off | scipy.signal.welch(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 45.5–54.5 Hz, edges by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)segments | signal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db off | scipy.signal.welch(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 45.5–54.5 Hz, edges by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)grms | signal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db off | scipy.signal.welch(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid over 45.5–54.5 Hz, edges by numpy.interp) | 3.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)x | signal_a; nperseg 512, overlap 30, window flattop, scaling density, db on | scipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10 | none | 10⁻¹² | PASS |
| PSD (Welch)PSD | signal_a; nperseg 512, overlap 30, window flattop, scaling density, db on | scipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10 | 6.6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)df | signal_a; nperseg 512, overlap 30, window flattop, scaling density, db on | scipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10 | none | 10⁻¹² | PASS |
| PSD (Welch)segments | signal_a; nperseg 512, overlap 30, window flattop, scaling density, db on | scipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10 | none | 10⁻¹² | PASS |
| PSD (Welch)grms | signal_a; nperseg 512, overlap 30, window flattop, scaling density, db on | scipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10 | 3.9 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)x | signal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a_gaps, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) (gaps filled by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)PSD | signal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a_gaps, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) (gaps filled by numpy.interp) | 8.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| PSD (Welch)df | signal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a_gaps, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) (gaps filled by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)segments | signal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a_gaps, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) (gaps filled by numpy.interp) | none | 10⁻¹² | PASS |
| PSD (Welch)grms | signal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db off | scipy.signal.welch(signal_a_gaps, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) (gaps filled by numpy.interp) | 5.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencex | signal_a, signal_b; nperseg 512, window hann, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hann', nperseg=512) | none | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherence|H1| | signal_a, signal_b; nperseg 512, window hann, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hann', nperseg=512) | 4.3 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencePhase H1 | signal_a, signal_b; nperseg 512, window hann, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hann', nperseg=512) | 2 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherenceCoherence | signal_a, signal_b; nperseg 512, window hann, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hann', nperseg=512) | 8.4 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencex | signal_a, signal_b; nperseg 1024, window hamming, estimator H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hamming', nperseg=1024) | none | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherence|H2| | signal_a, signal_b; nperseg 1024, window hamming, estimator H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hamming', nperseg=1024) | 3.7 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencePhase H2 | signal_a, signal_b; nperseg 1024, window hamming, estimator H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hamming', nperseg=1024) | 1.3 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherenceCoherence | signal_a, signal_b; nperseg 1024, window hamming, estimator H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hamming', nperseg=1024) | 5.8 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencex | signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='flattop', nperseg=512) | none | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherence|H1| | signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='flattop', nperseg=512) | 1.4 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencePhase H1 | signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='flattop', nperseg=512) | 1.8 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherence|H2| | signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='flattop', nperseg=512) | 4.5 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencePhase H2 | signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='flattop', nperseg=512) | 1.8 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherenceCoherence | signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='flattop', nperseg=512) | 2.1 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencex | signal_a, signal_b; nperseg 256, window rect, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='boxcar', nperseg=256); 0 Hz row left out (0/0, see Known convention differences) | none | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherence|H1| | signal_a, signal_b; nperseg 256, window rect, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='boxcar', nperseg=256); 0 Hz row left out (0/0, see Known convention differences) | 1.6 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencePhase H1 | signal_a, signal_b; nperseg 256, window rect, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='boxcar', nperseg=256); 0 Hz row left out (0/0, see Known convention differences) | 9 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherenceCoherence | signal_a, signal_b; nperseg 256, window rect, estimator H1 | H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='boxcar', nperseg=256); 0 Hz row left out (0/0, see Known convention differences) | 2.5 × 10⁻¹⁵ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencex | signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2 | H1 = csd(signal_a_gaps, signal_b) / welch(signal_a_gaps), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='blackman', nperseg=2048) | none | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherence|H1| | signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2 | H1 = csd(signal_a_gaps, signal_b) / welch(signal_a_gaps), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='blackman', nperseg=2048) | 1.2 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencePhase H1 | signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2 | H1 = csd(signal_a_gaps, signal_b) / welch(signal_a_gaps), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='blackman', nperseg=2048) | 1.9 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherence|H2| | signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2 | H1 = csd(signal_a_gaps, signal_b) / welch(signal_a_gaps), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='blackman', nperseg=2048) | 3 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherencePhase H2 | signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2 | H1 = csd(signal_a_gaps, signal_b) / welch(signal_a_gaps), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='blackman', nperseg=2048) | 1.8 × 10⁻¹⁴ | 10⁻¹² | PASS |
| FRF (H1 / H2) and coherenceCoherence | signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2 | H1 = csd(signal_a_gaps, signal_b) / welch(signal_a_gaps), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='blackman', nperseg=2048) | 3.5 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Band SNRsnr | signal_a; signal 45.0–55.0, noise 200.0–300.0, nperseg 512, window hann | 10·log10(band power 45.0–55.0 Hz / 200.0–300.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=512, window='hann') | none | 10⁻¹² | PASS |
| Band SNRsignal | signal_a; signal 45.0–55.0, noise 200.0–300.0, nperseg 512, window hann | 10·log10(band power 45.0–55.0 Hz / 200.0–300.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=512, window='hann') | 6.8 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRnoise | signal_a; signal 45.0–55.0, noise 200.0–300.0, nperseg 512, window hann | 10·log10(band power 45.0–55.0 Hz / 200.0–300.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=512, window='hann') | 6.8 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRsnr | signal_a; signal 110.0–130.0, nperseg 1024, window flattop | 10·log10(band power 110.0–130.0 Hz / rest of the spectrum), numpy.trapezoid of scipy.signal.welch(nperseg=1024, window='flattop') | none | 10⁻¹² | PASS |
| Band SNRsignal | signal_a; signal 110.0–130.0, nperseg 1024, window flattop | 10·log10(band power 110.0–130.0 Hz / rest of the spectrum), numpy.trapezoid of scipy.signal.welch(nperseg=1024, window='flattop') | 4.4 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRnoise | signal_a; signal 110.0–130.0, nperseg 1024, window flattop | 10·log10(band power 110.0–130.0 Hz / rest of the spectrum), numpy.trapezoid of scipy.signal.welch(nperseg=1024, window='flattop') | 3.5 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRsnr | signal_a; signal 45.0–55.0, noise 60.0–110.0, nperseg 4096, window rect | 10·log10(band power 45.0–55.0 Hz / 60.0–110.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=4096, window='boxcar') | 7.5 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRsignal | signal_a; signal 45.0–55.0, noise 60.0–110.0, nperseg 4096, window rect | 10·log10(band power 45.0–55.0 Hz / 60.0–110.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=4096, window='boxcar') | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRnoise | signal_a; signal 45.0–55.0, noise 60.0–110.0, nperseg 4096, window rect | 10·log10(band power 45.0–55.0 Hz / 60.0–110.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=4096, window='boxcar') | 3 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Band SNRsnr | signal_a; signal 115.0–125.0, noise 300.0–450.0, nperseg 256, window hamming | 10·log10(band power 115.0–125.0 Hz / 300.0–450.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=256, window='hamming') | none | 10⁻¹² | PASS |
| Band SNRsignal | signal_a; signal 115.0–125.0, noise 300.0–450.0, nperseg 256, window hamming | 10·log10(band power 115.0–125.0 Hz / 300.0–450.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=256, window='hamming') | 3.5 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRnoise | signal_a; signal 115.0–125.0, noise 300.0–450.0, nperseg 256, window hamming | 10·log10(band power 115.0–125.0 Hz / 300.0–450.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=256, window='hamming') | 5.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Band SNRsnr | signal_a; signal 48.0–52.0, nperseg 2048, window blackman | 10·log10(band power 48.0–52.0 Hz / rest of the spectrum), numpy.trapezoid of scipy.signal.welch(nperseg=2048, window='blackman') | 3.5 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Band SNRsignal | signal_a; signal 48.0–52.0, nperseg 2048, window blackman | 10·log10(band power 48.0–52.0 Hz / rest of the spectrum), numpy.trapezoid of scipy.signal.welch(nperseg=2048, window='blackman') | 2 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Band SNRnoise | signal_a; signal 48.0–52.0, nperseg 2048, window blackman | 10·log10(band power 48.0–52.0 Hz / rest of the spectrum), numpy.trapezoid of scipy.signal.welch(nperseg=2048, window='blackman') | 3.5 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 1024, overlap 50 | scipy.signal.spectrogram(signal_a, fs, nperseg=1024, noverlap=floor(50% of 1024)) (window ('tukey', 0.25), psd) | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 1024, overlap 50 | scipy.signal.spectrogram(signal_a, fs, nperseg=1024, noverlap=floor(50% of 1024)) (window ('tukey', 0.25), psd) | none | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 1024, overlap 50 | scipy.signal.spectrogram(signal_a, fs, nperseg=1024, noverlap=floor(50% of 1024)) (window ('tukey', 0.25), psd) | 4.5 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 256, overlap 50 | scipy.signal.spectrogram(signal_a, fs, nperseg=256, noverlap=floor(50% of 256)) (window ('tukey', 0.25), psd) | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 256, overlap 50 | scipy.signal.spectrogram(signal_a, fs, nperseg=256, noverlap=floor(50% of 256)) (window ('tukey', 0.25), psd) | none | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 256, overlap 50 | scipy.signal.spectrogram(signal_a, fs, nperseg=256, noverlap=floor(50% of 256)) (window ('tukey', 0.25), psd) | 6.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogramx | signal_a_gaps; nperseg 128, overlap 75 | scipy.signal.spectrogram(signal_a_gaps, fs, nperseg=128, noverlap=floor(75% of 128)) (window ('tukey', 0.25), psd) | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a_gaps; nperseg 128, overlap 75 | scipy.signal.spectrogram(signal_a_gaps, fs, nperseg=128, noverlap=floor(75% of 128)) (window ('tukey', 0.25), psd) | none | 10⁻¹² | PASS |
| Spectrogram | signal_a_gaps; nperseg 128, overlap 75 | scipy.signal.spectrogram(signal_a_gaps, fs, nperseg=128, noverlap=floor(75% of 128)) (window ('tukey', 0.25), psd) | 4.9 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 100, overlap 0 | scipy.signal.spectrogram(signal_a, fs, nperseg=100, noverlap=floor(0% of 100)) (window ('tukey', 0.25), psd) | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 100, overlap 0 | scipy.signal.spectrogram(signal_a, fs, nperseg=100, noverlap=floor(0% of 100)) (window ('tukey', 0.25), psd) | 1.1 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 100, overlap 0 | scipy.signal.spectrogram(signal_a, fs, nperseg=100, noverlap=floor(0% of 100)) (window ('tukey', 0.25), psd) | 5.4 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 512, overlap 50, window hann | scipy.signal.spectrogram(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of 512)) (psd) | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 512, overlap 50, window hann | scipy.signal.spectrogram(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of 512)) (psd) | none | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 512, overlap 50, window hann | scipy.signal.spectrogram(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of 512)) (psd) | 9.6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 256, overlap 75, window hamming, range 40.0–130.0 | scipy.signal.spectrogram(signal_a, fs, window='hamming', nperseg=256, noverlap=floor(75% of 256)) (psd); the rows from 40.0 to 130.0 Hz | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 256, overlap 75, window hamming, range 40.0–130.0 | scipy.signal.spectrogram(signal_a, fs, window='hamming', nperseg=256, noverlap=floor(75% of 256)) (psd); the rows from 40.0 to 130.0 Hz | none | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 256, overlap 75, window hamming, range 40.0–130.0 | scipy.signal.spectrogram(signal_a, fs, window='hamming', nperseg=256, noverlap=floor(75% of 256)) (psd); the rows from 40.0 to 130.0 Hz | 7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogramx | signal_a_gaps; nperseg 1024, overlap 50, window rect | scipy.signal.spectrogram(signal_a_gaps, fs, window='boxcar', nperseg=1024, noverlap=floor(50% of 1024)) (psd) | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a_gaps; nperseg 1024, overlap 50, window rect | scipy.signal.spectrogram(signal_a_gaps, fs, window='boxcar', nperseg=1024, noverlap=floor(50% of 1024)) (psd) | none | 10⁻¹² | PASS |
| Spectrogram | signal_a_gaps; nperseg 1024, overlap 50, window rect | scipy.signal.spectrogram(signal_a_gaps, fs, window='boxcar', nperseg=1024, noverlap=floor(50% of 1024)) (psd) | 1.2 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 512, overlap 25, window blackman, range 0.0–60.0 | scipy.signal.spectrogram(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(25% of 512)) (psd); the rows from 0.0 to 60.0 Hz | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 512, overlap 25, window blackman, range 0.0–60.0 | scipy.signal.spectrogram(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(25% of 512)) (psd); the rows from 0.0 to 60.0 Hz | none | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 512, overlap 25, window blackman, range 0.0–60.0 | scipy.signal.spectrogram(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(25% of 512)) (psd); the rows from 0.0 to 60.0 Hz | 1.1 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 256, overlap 50, window flattop | scipy.signal.spectrogram(signal_a, fs, window='flattop', nperseg=256, noverlap=floor(50% of 256)) (psd) | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 256, overlap 50, window flattop | scipy.signal.spectrogram(signal_a, fs, window='flattop', nperseg=256, noverlap=floor(50% of 256)) (psd) | none | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 256, overlap 50, window flattop | scipy.signal.spectrogram(signal_a, fs, window='flattop', nperseg=256, noverlap=floor(50% of 256)) (psd) | 1.1 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Spectrogramx | signal_a; nperseg 1024, overlap 50, window tukey, range 100.0–200.0 | scipy.signal.spectrogram(signal_a, fs, window=('tukey', 0.25), nperseg=1024, noverlap=floor(50% of 1024)) (psd); the rows from 100.0 to 200.0 Hz | none | 10⁻¹² | PASS |
| Spectrogramy | signal_a; nperseg 1024, overlap 50, window tukey, range 100.0–200.0 | scipy.signal.spectrogram(signal_a, fs, window=('tukey', 0.25), nperseg=1024, noverlap=floor(50% of 1024)) (psd); the rows from 100.0 to 200.0 Hz | none | 10⁻¹² | PASS |
| Spectrogram | signal_a; nperseg 1024, overlap 50, window tukey, range 100.0–200.0 | scipy.signal.spectrogram(signal_a, fs, window=('tukey', 0.25), nperseg=1024, noverlap=floor(50% of 1024)) (psd); the rows from 100.0 to 200.0 Hz | 4.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
Statistics120 checks · all passing · largest 4.8 × 10⁻¹³
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| HistogramFrom | signal_a; bins auto | numpy.histogram(signal_a, bins='auto') | none | identical | PASS |
| HistogramTo | signal_a; bins auto | numpy.histogram(signal_a, bins='auto') | none | identical | PASS |
| HistogramCount | signal_a; bins auto | numpy.histogram(signal_a, bins='auto') | none | identical | PASS |
| Histogramcount | signal_a; bins auto | numpy.histogram(signal_a, bins='auto') | none | identical | PASS |
| Histogrambins | signal_a; bins auto | numpy.histogram(signal_a, bins='auto') | none | identical | PASS |
| HistogramFrom | signal_a; bins fd | numpy.histogram(signal_a, bins='fd') | none | identical | PASS |
| HistogramTo | signal_a; bins fd | numpy.histogram(signal_a, bins='fd') | none | identical | PASS |
| HistogramCount | signal_a; bins fd | numpy.histogram(signal_a, bins='fd') | none | identical | PASS |
| Histogramcount | signal_a; bins fd | numpy.histogram(signal_a, bins='fd') | none | identical | PASS |
| Histogrambins | signal_a; bins fd | numpy.histogram(signal_a, bins='fd') | none | identical | PASS |
| HistogramFrom | signal_a; bins sturges | numpy.histogram(signal_a, bins='sturges') | none | identical | PASS |
| HistogramTo | signal_a; bins sturges | numpy.histogram(signal_a, bins='sturges') | none | identical | PASS |
| HistogramCount | signal_a; bins sturges | numpy.histogram(signal_a, bins='sturges') | none | identical | PASS |
| Histogramcount | signal_a; bins sturges | numpy.histogram(signal_a, bins='sturges') | none | identical | PASS |
| Histogrambins | signal_a; bins sturges | numpy.histogram(signal_a, bins='sturges') | none | identical | PASS |
| HistogramFrom | signal_a; bins sqrt | numpy.histogram(signal_a, bins='sqrt') | none | identical | PASS |
| HistogramTo | signal_a; bins sqrt | numpy.histogram(signal_a, bins='sqrt') | none | identical | PASS |
| HistogramCount | signal_a; bins sqrt | numpy.histogram(signal_a, bins='sqrt') | none | identical | PASS |
| Histogramcount | signal_a; bins sqrt | numpy.histogram(signal_a, bins='sqrt') | none | identical | PASS |
| Histogrambins | signal_a; bins sqrt | numpy.histogram(signal_a, bins='sqrt') | none | identical | PASS |
| HistogramFrom | signal_a; bins 10 | numpy.histogram(signal_a, bins=10) | none | identical | PASS |
| HistogramTo | signal_a; bins 10 | numpy.histogram(signal_a, bins=10) | none | identical | PASS |
| HistogramCount | signal_a; bins 10 | numpy.histogram(signal_a, bins=10) | none | identical | PASS |
| Histogramcount | signal_a; bins 10 | numpy.histogram(signal_a, bins=10) | none | identical | PASS |
| Histogrambins | signal_a; bins 10 | numpy.histogram(signal_a, bins=10) | none | identical | PASS |
| HistogramFrom | signal_a; bins 20 | numpy.histogram(signal_a, bins=20) | none | identical | PASS |
| HistogramTo | signal_a; bins 20 | numpy.histogram(signal_a, bins=20) | none | identical | PASS |
| HistogramCount | signal_a; bins 20 | numpy.histogram(signal_a, bins=20) | none | identical | PASS |
| Histogramcount | signal_a; bins 20 | numpy.histogram(signal_a, bins=20) | none | identical | PASS |
| Histogrambins | signal_a; bins 20 | numpy.histogram(signal_a, bins=20) | none | identical | PASS |
| HistogramFrom | signal_a; bins 50 | numpy.histogram(signal_a, bins=50) | none | identical | PASS |
| HistogramTo | signal_a; bins 50 | numpy.histogram(signal_a, bins=50) | none | identical | PASS |
| HistogramCount | signal_a; bins 50 | numpy.histogram(signal_a, bins=50) | none | identical | PASS |
| Histogramcount | signal_a; bins 50 | numpy.histogram(signal_a, bins=50) | none | identical | PASS |
| Histogrambins | signal_a; bins 50 | numpy.histogram(signal_a, bins=50) | none | identical | PASS |
| HistogramFrom | signal_a; bins 100 | numpy.histogram(signal_a, bins=100) | none | identical | PASS |
| HistogramTo | signal_a; bins 100 | numpy.histogram(signal_a, bins=100) | none | identical | PASS |
| HistogramCount | signal_a; bins 100 | numpy.histogram(signal_a, bins=100) | none | identical | PASS |
| Histogramcount | signal_a; bins 100 | numpy.histogram(signal_a, bins=100) | none | identical | PASS |
| Histogrambins | signal_a; bins 100 | numpy.histogram(signal_a, bins=100) | none | identical | PASS |
| HistogramFrom | signal_a_gaps; bins auto | numpy.histogram(values of signal_a_gaps, bins='auto') | none | identical | PASS |
| HistogramTo | signal_a_gaps; bins auto | numpy.histogram(values of signal_a_gaps, bins='auto') | none | identical | PASS |
| HistogramCount | signal_a_gaps; bins auto | numpy.histogram(values of signal_a_gaps, bins='auto') | none | identical | PASS |
| Histogramcount | signal_a_gaps; bins auto | numpy.histogram(values of signal_a_gaps, bins='auto') | none | identical | PASS |
| Histogrambins | signal_a_gaps; bins auto | numpy.histogram(values of signal_a_gaps, bins='auto') | none | identical | PASS |
| RMS, crest factor, peak to peakmin | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | none | 10⁻¹³ | PASS |
| RMS, crest factor, peak to peakmax | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | none | 10⁻¹³ | PASS |
| RMS, crest factor, peak to peakmean | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | 2.5 × 10⁻¹⁵ | 10⁻¹³ | PASS |
| RMS, crest factor, peak to peakrms | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | none | 10⁻¹³ | PASS |
| RMS, crest factor, peak to peakp2p | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | none | 10⁻¹³ | PASS |
| RMS, crest factor, peak to peakcrest | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | none | 10⁻¹³ | PASS |
| RMS, crest factor, peak to peakstd | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | 4 × 10⁻¹⁶ | 10⁻¹³ | PASS |
| RMS, crest factor, peak to peakcount | signal_a_gaps | numpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1) | none | 10⁻¹³ | PASS |
| Percentiles, skewness, kurtosisp1 | signal_a_gaps; bias off | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp5 | signal_a_gaps; bias off | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp50 | signal_a_gaps; bias off | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp95 | signal_a_gaps; bias off | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp99 | signal_a_gaps; bias off | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisskewness | signal_a_gaps; bias off | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit') | 7.9 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosiskurtosis | signal_a_gaps; bias off | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit') | 1.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp1 | signal_a_gaps; bias on | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp5 | signal_a_gaps; bias on | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp50 | signal_a_gaps; bias on | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp95 | signal_a_gaps; bias on | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisp99 | signal_a_gaps; bias on | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit') | none | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosisskewness | signal_a_gaps; bias on | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit') | 7.9 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Percentiles, skewness, kurtosiskurtosis | signal_a_gaps; bias on | numpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit') | 1.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Correlation (Pearson)r | signal_a, signal_b | scipy.stats.pearsonr(signal_a, signal_b) | 3.6 × 10⁻¹⁵ | 10⁻¹³ | PASS |
| Correlation (Pearson)r2 | signal_a, signal_b | scipy.stats.pearsonr(signal_a, signal_b) | 7.2 × 10⁻¹⁵ | 10⁻¹³ | PASS |
| Correlation (Pearson)r | signal_a_gaps, price | scipy.stats.pearsonr on the rows where both have a value | 3 × 10⁻¹⁵ | 10⁻¹³ | PASS |
| Correlation (Pearson)r2 | signal_a_gaps, price | scipy.stats.pearsonr on the rows where both have a value | 6 × 10⁻¹⁵ | 10⁻¹³ | PASS |
| Polynomial fit | signal_a; degree 1 | numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot | 6.3 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitr2 | signal_a; degree 1 | numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot | 1.3 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitcoefficients | signal_a; degree 1 | numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot | 7.4 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fitmu | signal_a; degree 1 | numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot | 5.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fitsigma | signal_a; degree 1 | numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot | 3.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fit | signal_a; degree 3 | numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot | 3.2 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitr2 | signal_a; degree 3 | numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot | 1.7 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitcoefficients | signal_a; degree 3 | numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot | 9.5 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fitmu | signal_a; degree 3 | numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot | 5.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fitsigma | signal_a; degree 3 | numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot | 3.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fit | price; degree 0 | numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot | 1.7 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitr2 | price; degree 0 | numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot | 9.3 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitcoefficients | price; degree 0 | numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot | 1.7 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitmu | price; degree 0 | numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot | 5.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fitsigma | price; degree 0 | numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot | 3.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fit | price; degree 10 | numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot | 1.3 × 10⁻¹³ | 10⁻¹² | PASS |
| Polynomial fitr2 | price; degree 10 | numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot | 4.3 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitcoefficients | price; degree 10 | numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot | 4.8 × 10⁻¹³ | 10⁻¹² | PASS |
| Polynomial fitmu | price; degree 10 | numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot | 5.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fitsigma | price; degree 10 | numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot | 3.6 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Polynomial fit | signal_a_gaps; degree 2 | numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot | 2.8 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitr2 | signal_a_gaps; degree 2 | numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot | 1.4 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitcoefficients | signal_a_gaps; degree 2 | numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot | 2.9 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Polynomial fitmu | signal_a_gaps; degree 2 | numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot | 6.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Polynomial fitsigma | signal_a_gaps; degree 2 | numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot | 3.8 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cross-correlationx | signal_a, signal_b; normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²) | none | 10⁻¹² | PASS |
| Cross-correlationCorrelation | signal_a, signal_b; normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²) | 4.6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cross-correlationpeakLag | signal_a, signal_b; normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²) | none | 10⁻¹² | PASS |
| Cross-correlationdelay | signal_a, signal_b; normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²) | none | 10⁻¹² | PASS |
| Cross-correlationx | signal_a, signal_b; maxLag 50, normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 50 | none | 10⁻¹² | PASS |
| Cross-correlationCorrelation | signal_a, signal_b; maxLag 50, normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 50 | 5.6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cross-correlationpeakLag | signal_a, signal_b; maxLag 50, normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 50 | none | 10⁻¹² | PASS |
| Cross-correlationdelay | signal_a, signal_b; maxLag 50, normalization coeff | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 50 | none | 10⁻¹² | PASS |
| Cross-correlationx | signal_a, signal_b; maxLag 200, normalization biased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 200 | none | 10⁻¹² | PASS |
| Cross-correlationCorrelation | signal_a, signal_b; maxLag 200, normalization biased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 200 | 5.6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cross-correlationpeakLag | signal_a, signal_b; maxLag 200, normalization biased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 200 | none | 10⁻¹² | PASS |
| Cross-correlationdelay | signal_a, signal_b; maxLag 200, normalization biased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 200 | none | 10⁻¹² | PASS |
| Cross-correlationx | signal_a, signal_b; maxLag 200, normalization unbiased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 200 | none | 10⁻¹² | PASS |
| Cross-correlationCorrelation | signal_a, signal_b; maxLag 200, normalization unbiased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 200 | 6.7 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cross-correlationpeakLag | signal_a, signal_b; maxLag 200, normalization unbiased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 200 | none | 10⁻¹² | PASS |
| Cross-correlationdelay | signal_a, signal_b; maxLag 200, normalization unbiased | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 200 | none | 10⁻¹² | PASS |
| Cross-correlationx | signal_a, signal_b; maxLag 30, normalization none | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 30 | none | 10⁻¹² | PASS |
| Cross-correlationCorrelation | signal_a, signal_b; maxLag 30, normalization none | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 30 | 6 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cross-correlationpeakLag | signal_a, signal_b; maxLag 30, normalization none | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 30 | none | 10⁻¹² | PASS |
| Cross-correlationdelay | signal_a, signal_b; maxLag 30, normalization none | scipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 30 | none | 10⁻¹² | PASS |
| Cross-correlationx | signal_a_gaps, signal_b; maxLag 100, normalization coeff | scipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 100 | none | 10⁻¹² | PASS |
| Cross-correlationCorrelation | signal_a_gaps, signal_b; maxLag 100, normalization coeff | scipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 100 | 8.9 × 10⁻¹⁶ | 10⁻¹² | PASS |
| Cross-correlationpeakLag | signal_a_gaps, signal_b; maxLag 100, normalization coeff | scipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 100 | none | 10⁻¹² | PASS |
| Cross-correlationdelay | signal_a_gaps, signal_b; maxLag 100, normalization coeff | scipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 100 | none | 10⁻¹² | PASS |
Engineering76 checks · all passing · largest 1.1 × 10⁻¹⁴
| Operation | Our settings | Reference | Difference | Limit | Result |
|---|---|---|---|---|---|
| Rainflow counting and damagecycles | load_cycles; output cycles, hysteresis 0 | rainflow.extract_cycles(load_cycles) | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output cycles, hysteresis 0 | rainflow.extract_cycles(load_cycles) | none | identical | PASS |
| Rainflow counting and damageRange | load_cycles; output cycles, hysteresis 0 | rainflow.extract_cycles(load_cycles) | none | identical | PASS |
| Rainflow counting and damageMean | load_cycles; output cycles, hysteresis 0 | rainflow.extract_cycles(load_cycles) | none | identical | PASS |
| Rainflow counting and damageCount | load_cycles; output cycles, hysteresis 0 | rainflow.extract_cycles(load_cycles) | none | identical | PASS |
| Rainflow counting and damageStart row | load_cycles; output cycles, hysteresis 0 | rainflow.extract_cycles(load_cycles) | none | identical | PASS |
| Rainflow counting and damageEnd row | load_cycles; output cycles, hysteresis 0 | rainflow.extract_cycles(load_cycles) | none | identical | PASS |
| Rainflow counting and damagecycles | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageRange | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageMean | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageCount | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageStart row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageEnd row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damagedamage | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹² | PASS |
| Rainflow counting and damagelife | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹² | PASS |
| Rainflow counting and damagecycles | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | identical | PASS |
| Rainflow counting and damageRange | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | identical | PASS |
| Rainflow counting and damageMean | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | identical | PASS |
| Rainflow counting and damageCount | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | identical | PASS |
| Rainflow counting and damageStart row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | identical | PASS |
| Rainflow counting and damageEnd row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | identical | PASS |
| Rainflow counting and damagedamage | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | 10⁻¹² | PASS |
| Rainflow counting and damagelife | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correction | none | 10⁻¹² | PASS |
| Rainflow counting and damagecycles | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | identical | PASS |
| Rainflow counting and damageRange | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | identical | PASS |
| Rainflow counting and damageMean | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | identical | PASS |
| Rainflow counting and damageCount | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | identical | PASS |
| Rainflow counting and damageStart row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | identical | PASS |
| Rainflow counting and damageEnd row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | identical | PASS |
| Rainflow counting and damagedamage | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | 10⁻¹² | PASS |
| Rainflow counting and damagelife | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correction | none | 10⁻¹² | PASS |
| Rainflow counting and damagecycles | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | identical | PASS |
| Rainflow counting and damageRange | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | identical | PASS |
| Rainflow counting and damageMean | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | identical | PASS |
| Rainflow counting and damageCount | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | identical | PASS |
| Rainflow counting and damageStart row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | identical | PASS |
| Rainflow counting and damageEnd row | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | identical | PASS |
| Rainflow counting and damagedamage | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | 10⁻¹² | PASS |
| Rainflow counting and damagelife | load_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0 | rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correction | none | 10⁻¹² | PASS |
| Rainflow counting and damagecycles | load_cycles; output histogram, hysteresis 0, rangeBins 32 | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts) | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output histogram, hysteresis 0, rangeBins 32 | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts) | none | identical | PASS |
| Rainflow counting and damageRange from | load_cycles; output histogram, hysteresis 0, rangeBins 32 | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts) | none | 10⁻¹⁵ | PASS |
| Rainflow counting and damageRange to | load_cycles; output histogram, hysteresis 0, rangeBins 32 | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts) | none | 10⁻¹⁵ | PASS |
| Rainflow counting and damageCycles | load_cycles; output histogram, hysteresis 0, rangeBins 32 | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts) | none | identical | PASS |
| Rainflow counting and damagecycles | load_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageRange from | load_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹⁵ | PASS |
| Rainflow counting and damageRange to | load_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹⁵ | PASS |
| Rainflow counting and damageCycles | load_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damagedamage | load_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹² | PASS |
| Rainflow counting and damagelife | load_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹² | PASS |
| Rainflow counting and damagecycles | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damagereversals | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageRange | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageMean | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageCount | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageStart row | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damageEnd row | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | identical | PASS |
| Rainflow counting and damagedamage | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹² | PASS |
| Rainflow counting and damagelife | load_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection none | rainflow.extract_cycles on the turning points kept by a 25.0 hysteresis gate (independent Python gate); Miner sum n / (C·S^-m), C = nRef·sRef^m | none | 10⁻¹² | PASS |
| Shock response spectrumx | signal_a | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | none | 10⁻¹⁵ | PASS |
| Shock response spectrumMaximax | signal_a | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 3.5 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Shock response spectrumPositive | signal_a | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 3.5 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Shock response spectrumNegative | signal_a | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 5.5 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Shock response spectrumx | signal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | none | 10⁻¹⁵ | PASS |
| Shock response spectrumMaximax | signal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 2.9 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Shock response spectrumPositive | signal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 2.9 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Shock response spectrumNegative | signal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 1.1 × 10⁻¹⁴ | 10⁻¹² | PASS |
| Shock response spectrumx | signal_a_gaps; q 5, fmin 20, pointsPerOctave 24 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | none | 10⁻¹⁵ | PASS |
| Shock response spectrumMaximax | signal_a_gaps; q 5, fmin 20, pointsPerOctave 24 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 8.1 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Shock response spectrumPositive | signal_a_gaps; q 5, fmin 20, pointsPerOctave 24 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 8.1 × 10⁻¹⁵ | 10⁻¹² | PASS |
| Shock response spectrumNegative | signal_a_gaps; q 5, fmin 20, pointsPerOctave 24 | scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response) | 6.1 × 10⁻¹⁵ | 10⁻¹² | PASS |
Where we follow a different convention on purpose
In a few places MegaRows deliberately does something other than the library’s default, usually to match what spreadsheet users expect. There the reference was set to the same convention, so the numbers could still be compared, and the difference is explained here.
- FRF and coherence at 0 Hz with a rectangular window. The 0 Hz row means nothing here, in MegaRows and in SciPy alike, so it is left out of the comparison. Each segment's mean is removed before the FFT (scipy's default, and the only choice in the dialog). With a rectangular window that makes the 0 Hz input and output spectra zero up to rounding, so H1, H2 and the coherence at 0 Hz are 0/0 in both tools: MegaRows shows |H1| 0.099 there and scipy 0.269, both rounding noise. Every other row agrees to 1e-12 or better, and with any other window the 0 Hz row is a real value and is compared.
- Powers with a missing or infinite exponent.
pow(1, missing)stays missing in MegaRows, where NumPy says 1.powand^follow JavaScript: a NaN exponent gives NaN even for a base of 1, and (±1) ^ (±∞) is NaN (C and numpy give 1);x ^ 0.5is computed assqrt(x), so (−∞) ^ 0.5 is NaN wherenumpy.powergives +∞. The sample has no such values;formula.jsoncovers them with a reference that follows this rule. - Exponential moving average with gaps. A missing row stays missing in MegaRows; pandas repeats the previous value there. The smoothing state is held across the gap in both, so every other row is the same; the reference sets the missing rows back to NaN. With a time constant and an X column the smoothing factor follows each X step, which pandas cannot do with
adjust=False, so that case uses the recurrence written out in numpy. - Rainflow range histogram. Cycle ranges are binned like
numpy.histogram, not like therainflowpackage's own binning. The bins arenumpy.histogram(ranges, bins, range=(0, largest range), weights=counts); the package'scount_cycles(nbins=...)uses right-closed bins sized from the signal's span, so its table would differ while the cycles themselves are identical. - Rounding.
round(2.5)is 3, like Excel; NumPy rounds halves to even (2).round()rounds halves away from zero (−2.5 → −3), like Excel and MATLAB. The reference is numpy written out for half-away rounding,sign(x)·floor(|x| + ½), computed exactly; withnumpy.roundthe prices ending in a half cent would differ. - Standard deviation. The standard deviation is the sample one, divided by n − 1, like MATLAB's
stdand Excel'sSTDEV. NumPy'snanstddivides by n unless asked otherwise, so the reference isnumpy.nanstd(y, ddof=1). The same holds for the statistics panel and the Compare view. The z-score keeps SciPy's default (n) and the moving and expanding standard deviations pandas' (n − 1); both have a choice in the dialog. - Missing values in comparisons and logic. A comparison with a missing value is missing, not false, so a gap stays a gap. numpy would say
NaN > 0is false.and/orfollow three-valued logic:false and missingis false,true or missingis true. pandas' nullable arrays behave exactly like this, so they are the reference. - Gaps in filters and spectra. Gaps are bridged by a straight line before filtering, then shown as gaps again. Operations that skip missing samples leave them out (pandas
rolling(min_periods=1),nanpercentile). Filters, spectra, Hilbert, Savitzky-Golay, decimation and SRS first fill gaps by linear interpolation and, for results on the same rows, set the filled rows back to missing; the references do the same. - Detrend against X. With an X column the trend line is fitted against X, not against the row number. The reference is
numpy.polyfit(time_s, y, 1);scipy.signal.detrendfits against the row number and is the reference when X is the row number. - Rainflow hysteresis. No standard library has a hysteresis gate, so the reference gate is a short independent Python function. A turning point is kept once the signal has come back from it by the gate; the kept points then go through
rainflow.extract_cycles. - Savitzky-Golay with long windows. Here SciPy is the less precise one; MegaRows matches exact arithmetic. SciPy solves each window's least-squares fit on raw powers of the sample offsets, which leaves about 1e-11 of its own rounding for a 51-sample window (polynomial order 4). MegaRows uses an orthonormal basis; against the same filter computed in exact rational arithmetic it agrees to 1e-15, so that case has a second row with the exact reference and a 1e-13 tolerance.
Check it yourself in Python
Three checks you can run in a minute: download the sample file, then run these lines with NumPy, SciPy and pandas installed. They read the signal_a column and work out what the statistics panel, the FFT spectrum and the PSD show for it in MegaRows.
import numpy as np, pandas as pd
from scipy import signal
x = pd.read_csv("megarows-sample-signals.csv")["signal_a"].to_numpy()
# 1. Statistics panel, whole file: Mean and Std dev (sample, n - 1)
print(f"mean {x.mean():.6f} std {x.std(ddof=1):.6f}")
# 2. Math > FFT spectrum: rectangular window, peak amplitude
a = 2 * np.abs(np.fft.rfft(x)) / len(x) # bins 0.25 Hz apart
print(f"50 Hz {a[200]:.4f} 120 Hz {a[480]:.4f}")
# 3. Math > PSD (Welch): Hann, 1024-sample segments, 50 % overlap
f, p = signal.welch(x, fs=1000, window="hann", nperseg=1024)
print(f"Grms {np.sqrt(np.trapezoid(p, f)):.4f}")They print:
mean 0.751169 std 1.116526
50 Hz 0.9848 120 Hz 0.4984
Grms 0.8786Open the same file in the CSV plotter and you get the same numbers: the statistics panel for the whole file (Mean and Std dev, the sample standard deviation), Math › FFT spectrum with a rectangular window (the amplitude at 50 Hz and 120 Hz), and Math › PSD (Welch) with a Hann window, segments of 1,024 samples and 50 % overlap (the Grms readout). We ran these lines on 8 October 2026 with NumPy 2.1.3, SciPy 1.14.1, pandas 2.2.3 and Python 3.12; a test checks on every change that MegaRows still gives these numbers. The worked example on FFT from CSV goes through the PSD step by step.
The worked examples of the signal pages
Each signal page has a worked example on a made-up sample file of its own. A test checks on every change that MegaRows gives the numbers the page prints and that they match SciPy’s to about 12 significant digits:
- FFT from CSV: the PSD of the sample signal against
scipy.signal.welch, and the FFT spectrum against NumPy’s FFT. - PSD calculator: the Grms, the band’s level, the tone and the dB view of the vibration sample against
scipy.signal.welch. - Spectrogram from CSV: every slice’s loudest frequency and the values of the middle one against
scipy.signal.spectrogram, with the Tukey and Hann windows and a frequency range. - FRF and coherence: H1, H2, the phase and the coherence of the mast sample against
scipy.signal.csd,welchandcoherence.
Repeat the checks
The full comparison was last run on 8 October 2026, with numpy 2.1.3, scipy 1.14.1, pandas 2.2.3, rainflow 3.2.0, Python 3.12.15, Node.js 24.20.0. Between full runs, our automated tests check the same operations against SciPy’s stored answers on every change to the site.
Download the sample file (CSV, 185 KB), open it in FFT from CSV or the plotter, and compare any result with your own tools.
Related tools and guides
- CSV plotterOpen a CSV, Excel, TXT, JSON, MATLAB, Parquet, HDF5 or LabVIEW TDMS file with millions of rows and plot it in several linked charts, with zoom and statistics. Works today.
- Large CSV viewerOpen a CSV with millions of rows in your browser: scroll every row, see each column’s type and statistics, chart any column. Works today.
- MATLAB .mat file viewerOpen v4 to v7.3 .mat files without MATLAB and plot any signal. Works today.
- Parquet viewerOpen large .parquet files, see the schema at once and plot millions of rows, without Python. Works today.
- TDMS viewerOpen .tdms files from LabVIEW, DIAdem and DAQmx loggers: every group, channel and property, each channel plotted against its time. Works today.
- HDF5 viewerOpen .h5, .hdf5 and NetCDF-4 .nc files: every group, dataset and attribute, each group’s datasets plotted against their time. Works today.
- MAT to CSVConvert the signals of a .mat file, v4 to v7.3, to a CSV for Excel or Python, without MATLAB. Works today.
- Parquet to CSVConvert a .parquet file to CSV in your browser, with the columns you pick. Works today.
- TDMS to CSVConvert the channels of a .tdms file to CSV, a group at a time, with its time column, without LabVIEW or Excel add-ins. Works today.
- HDF5 to CSVConvert the datasets of an .h5 or NetCDF-4 file to CSV, a table at a time, with its time column, without Python. Works today.
- Excel to CSVConvert any sheet of an .xlsx or .xlsm workbook to CSV, with the saved results of formulas, real dates and 15 significant digits. Works today.
- JSON to CSVConvert JSON and JSON Lines files to CSV: nested fields become columns named by their path, arrays stay as JSON text. Works today.
- CSV to MATConvert a CSV, Excel, JSON or Parquet file to a MATLAB .mat file: a field per column, with names and units, every row. Works today.
- Merge CSV filesAppend many CSV files into one, even with different columns or separators. Works today.
- Split CSV filesSplit a CSV too big for Excel into parts of 1,000,000 rows, parts of a size you choose, or one file per value of a column. Works today.
- CSV row counterCount the lines in a CSV, TSV or TXT file of any size. Works today.
- CSV statisticsCount, missing values, min, max, mean, standard deviation, RMS and peak to peak of each number column, for the whole file or the rows you zoom into. Works today.
- CSV histogramA histogram of any number column, with automatic bins or 10 to 200 of them, and each bin’s count as a table. Works today.
- CSV too large for Excel?Open every row of a CSV beyond Excel’s 1,048,576-row limit, or work around the limit in six other ways.
- FFT and PSD from a CSVTurn a signal column into an FFT spectrum or a PSD with Grms, with results checked against SciPy. Works today.
- PSD calculatorTurn a vibration column into a power spectral density (Welch) in g²/Hz, with the Grms of any band and a dB view. Works today.
- Spectrogram from CSVSee how the frequencies of a measured signal change over time, as a heat map in dB, with the window and range you choose. Works today.
- FRF and coherencePick an input and an output column and get the frequency response (H1, H2, magnitude and phase) and their coherence. Works today.
- The MegaRows toolboxWhat works today and what is coming next, and why nothing is ever uploaded.
Coming soon to MegaRows: CSV to Excel and PDF reports · Compare CSV versions.