Skip to content

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).

OperationGroupChecksLargest differenceResult
CSV importData6nonePass
Sample rate from the X columnData1nonePass
FormulaFormula798.2 × 10⁻¹⁵Pass
Scale and offsetArithmetic1nonePass
Absolute valueArithmetic1nonePass
Normalize (0-1)Arithmetic1nonePass
Z-scoreArithmetic26.2 × 10⁻¹⁶Pass
Moving averageTime domain42.7 × 10⁻¹⁶Pass
Moving RMSTime domain44.3 × 10⁻¹⁶Pass
Moving standard deviationTime domain31.1 × 10⁻¹⁴Pass
Expanding meanTime domain11.2 × 10⁻¹⁶Pass
Expanding standard deviationTime domain25 × 10⁻¹⁶Pass
Envelope (moving min / max)Time domain4nonePass
Exponential moving averageTime domain42.7 × 10⁻¹⁶Pass
Envelope (Hilbert)Time domain24.9 × 10⁻¹⁶Pass
Cumulative sumTime domain11.7 × 10⁻¹⁵Pass
DifferenceTime domain2nonePass
DerivativeTime domain3nonePass
Integral (cumulative)Time domain31.2 × 10⁻¹⁵Pass
DetrendTime domain41.2 × 10⁻¹⁴Pass
Peak detectionTime domain20nonePass
Zero crossingsTime domain28nonePass
Resample to uniform rateTime domain4nonePass
Median filterFiltering5nonePass
Butterworth filterFiltering115.6 × 10⁻¹⁵Pass
Savitzky-Golay smoothingFiltering41.2 × 10⁻¹¹Pass
Decimate (with anti-alias filter)Filtering62.3 × 10⁻¹⁴Pass
FFT spectrumFrequency domain211.5 × 10⁻¹⁴Pass
PSD (Welch)Frequency domain342.4 × 10⁻¹⁵Pass
FRF (H1 / H2) and coherenceFrequency domain244.5 × 10⁻¹⁴Pass
Band SNRFrequency domain153.5 × 10⁻¹⁴Pass
SpectrogramFrequency domain301.1 × 10⁻¹⁵Pass
HistogramStatistics45nonePass
RMS, crest factor, peak to peakStatistics82.5 × 10⁻¹⁵Pass
Percentiles, skewness, kurtosisStatistics147.9 × 10⁻¹⁴Pass
Correlation (Pearson)Statistics47.2 × 10⁻¹⁵Pass
Polynomial fitStatistics254.8 × 10⁻¹³Pass
Cross-correlationStatistics248.9 × 10⁻¹⁶Pass
Rainflow counting and damageEngineering64nonePass
Shock response spectrumEngineering121.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
OperationOur settingsReferenceDifferenceLimitResult
CSV importtime_sfloat() of each cell of time_s (Python)noneidenticalPASS
CSV importsignal_afloat() of each cell of signal_a (Python)noneidenticalPASS
CSV importsignal_a_gapsfloat() of each cell of signal_a_gaps (Python)noneidenticalPASS
CSV importsignal_bfloat() of each cell of signal_b (Python)noneidenticalPASS
CSV importload_cyclesfloat() of each cell of load_cycles (Python)noneidenticalPASS
CSV importpricefloat() of each cell of price (Python)noneidenticalPASS
Sample rate from the X columnfs1 / numpy.median(numpy.diff(time_s))noneidenticalPASS
Formula79 checks · all passing · largest 8.2 × 10⁻¹⁵
OperationOur settingsReferenceDifferenceLimitResult
Formulaabs(signal_a_gaps)numpy.absnoneidenticalPASS
Formulasqrt(price)numpy.sqrtnoneidenticalPASS
Formulasqrt(signal_a)numpy.sqrt (NaN for negative values)noneidenticalPASS
Formulaexp(signal_a)numpy.exp1.1 × 10⁻¹⁶10⁻¹⁵PASS
Formulalog(price)numpy.log3.7 × 10⁻¹⁵10⁻¹⁴PASS
Formulalog(price, 3)numpy.emath.logn(3, price)8.2 × 10⁻¹⁵10⁻¹⁴PASS
Formulalog10(price)numpy.log104.3 × 10⁻¹⁵10⁻¹⁴PASS
Formulalog2(price)numpy.log22.6 × 10⁻¹⁵10⁻¹⁴PASS
Formulasin(signal_a)numpy.sin5.6 × 10⁻¹⁷10⁻¹⁵PASS
Formulacos(signal_a)numpy.cos5.6 × 10⁻¹⁷10⁻¹⁵PASS
Formulatan(signal_a)numpy.tan1.7 × 10⁻¹⁸10⁻¹⁵PASS
Formulaasin(signal_a / 4)numpy.arcsin(signal_a / 4)6.9 × 10⁻¹⁷10⁻¹⁵PASS
Formulaacos(signal_a / 4)numpy.arccos(signal_a / 4)1.4 × 10⁻¹⁶10⁻¹⁵PASS
Formulaatan(signal_a)numpy.arctan9.2 × 10⁻¹⁷10⁻¹⁵PASS
Formulaatan2(signal_b, signal_a)numpy.arctan2(signal_b, signal_a)7.1 × 10⁻¹⁷10⁻¹⁵PASS
Formulasinh(signal_a)numpy.sinh2.7 × 10⁻¹⁸10⁻¹⁵PASS
Formulacosh(signal_a)numpy.cosh1.1 × 10⁻¹⁶10⁻¹⁵PASS
Formulatanh(signal_a)numpy.tanh1.1 × 10⁻¹⁶10⁻¹⁵PASS
Formuladeg(signal_a)numpy.degrees8.9 × 10⁻¹⁷10⁻¹⁵PASS
Formularad(signal_a)numpy.radians7.2 × 10⁻¹⁷10⁻¹⁵PASS
Formulamin(signal_a)signal_a (one argument)noneidenticalPASS
Formulamin(signal_a_gaps, signal_b)numpy.minimum (NaN propagates)noneidenticalPASS
Formulamin(signal_a, signal_b, 0.5)numpy.minimum.reduce([signal_a, signal_b, 0.5])noneidenticalPASS
Formulamax(signal_a_gaps, signal_b)numpy.maximum (NaN propagates)noneidenticalPASS
Formulamax(signal_a, signal_b, 0.5)numpy.maximum.reduce([signal_a, signal_b, 0.5])noneidenticalPASS
Formulaclamp(signal_a_gaps, -1, 1.5)numpy.clip(signal_a_gaps, -1, 1.5)noneidenticalPASS
Formularound(price)half away from zero: sign(x)·floor(|x| + 1/2) (numpy.round rounds half to even)noneidenticalPASS
Formularound(price, 1)half_away(price · 10) / 10 (numpy.round(price, 1) rounds half to even)noneidenticalPASS
Formularound(signal_a, 3)half_away(signal_a · 1000) / 1000noneidenticalPASS
Formulafloor(signal_a)numpy.floornoneidenticalPASS
Formulaceil(signal_a)numpy.ceilnoneidenticalPASS
Formulatrunc(signal_a)numpy.truncnoneidenticalPASS
Formulapow(price, 1.5)numpy.power(price, 1.5)none10⁻¹⁵PASS
Formulapow(signal_a, signal_b)numpy.power(signal_a, signal_b) (NaN for a negative base)none10⁻¹⁵PASS
Formulahypot(signal_a)numpy.abs (one argument)noneidenticalPASS
Formulahypot(signal_a, signal_b)numpy.hypot2.5 × 10⁻¹⁶10⁻¹⁵PASS
Formulahypot(signal_a, signal_b, price)numpy.hypot(numpy.hypot(signal_a, signal_b), price)1.1 × 10⁻¹⁵10⁻¹⁴PASS
Formulasign(signal_a_gaps)numpy.signnoneidenticalPASS
Formulamod(load_cycles, 7)numpy.mod (floored: sign of the divisor)noneidenticalPASS
Formulamod(signal_a, -0.7)numpy.mod(signal_a, -0.7)noneidenticalPASS
Formulaisnan(signal_a_gaps)numpy.isnannoneidenticalPASS
Formulaisfinite(signal_a_gaps / signal_a_gaps * (signal_a - 0.5) / round(signal_a - 0.5))numpy.isfinite (with ±inf from a division by 0)noneidenticalPASS
Formulacoalesce(signal_a_gaps, signal_b)pandas.DataFrame([signal_a_gaps, signal_b]).bfill(axis=1) first columnnoneidenticalPASS
Formulacoalesce(signal_a_gaps, signal_a_gaps * 2, price)pandas bfill(axis=1) over three columnsnoneidenticalPASS
Formulaif(signal_a_gaps > 1, signal_b, price)numpy.where(isnan(c), nan, numpy.where(c > 1, signal_b, price))noneidenticalPASS
Formulasignal_a + signal_bnumpy.addnoneidenticalPASS
Formulasignal_a_gaps - signal_bnumpy.subtractnoneidenticalPASS
Formulasignal_a * signal_bnumpy.multiplynoneidenticalPASS
Formulasignal_a / signal_bnumpy.dividenoneidenticalPASS
Formulaload_cycles % 7numpy.modnoneidenticalPASS
Formulaprice ^ 2numpy.power(price, 2)noneidenticalPASS
Formulasignal_a ^ 3numpy.power(signal_a, 3)1.4 × 10⁻¹⁶10⁻¹⁵PASS
Formulaprice ^ signal_anumpy.power(price, signal_a)none10⁻¹⁵PASS
Formulaprice ** 0.5numpy.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_gapsnumpy.negativenoneidenticalPASS
Formula+signal_asignal_anoneidenticalPASS
Formula-signal_a ^ 2-(signal_a ** 2) (power binds tighter than unary minus)noneidenticalPASS
Formula2 ^ -1 * signal_a + signal_b * price - 3 / price0.5 * signal_a + signal_b * price - 3 / pricenoneidenticalPASS
Formulasignal_a_gaps < signal_bpandas Float64 array < (missing -> <NA> -> NaN)noneidenticalPASS
Formulasignal_a_gaps <= signal_bpandas Float64 array <=noneidenticalPASS
Formulasignal_a_gaps > signal_bpandas Float64 array >noneidenticalPASS
Formulasignal_a_gaps >= signal_bpandas Float64 array >=noneidenticalPASS
Formularound(signal_a_gaps) == 1pandas Float64 array ==noneidenticalPASS
Formularound(signal_a_gaps) != 1pandas Float64 array !=noneidenticalPASS
Formularound(signal_a_gaps) <> 1pandas Float64 array !=noneidenticalPASS
Formulasignal_a_gaps > 0 && signal_b > 0pandas boolean array & (Kleene logic: False & <NA> = False)noneidenticalPASS
Formulasignal_a_gaps > 0 and signal_b < 0pandas boolean array &noneidenticalPASS
Formulasignal_a_gaps > 0 || signal_b > 0pandas boolean array | (Kleene logic: True | <NA> = True)noneidenticalPASS
Formulasignal_a_gaps > 0 or signal_b < 0pandas boolean array |noneidenticalPASS
Formula!(signal_a_gaps > 0)pandas boolean array ~noneidenticalPASS
Formulanot signal_a_gapspandas boolean array ~ of (signal_a_gaps != 0)noneidenticalPASS
Formulasignal_a × signal_b − price ÷ 100signal_a * signal_b - price / 100noneidenticalPASS
Formulasignal_a · 2signal_a * 2noneidenticalPASS
Formulasignal_a_gaps ≤ signal_bpandas Float64 array <=noneidenticalPASS
Formulasignal_a_gaps ≥ signal_bpandas Float64 array >=noneidenticalPASS
Formularound(signal_a_gaps) ≠ 1pandas Float64 array !=noneidenticalPASS
Formula2 * pi * 50 * t2 * numpy.pi * 50 * time_snoneidenticalPASS
Formulae ^ signal_anumpy.power(numpy.e, signal_a)none10⁻¹⁵PASS
Formulax * 1000 - itime_s * 1000 - numpy.arange(n)noneidenticalPASS
Arithmetic5 checks · all passing · largest 6.2 × 10⁻¹⁶
OperationOur settingsReferenceDifferenceLimitResult
Scale and offsetsignal_a_gaps; scale 9.81, offset -2.5signal_a_gaps * 9.81 + -2.5 (numpy)noneidenticalPASS
Absolute valuesignal_a_gapsnumpy.abs(signal_a_gaps)noneidenticalPASS
Normalize (0-1)signal_a_gaps(y - numpy.nanmin(y)) / (numpy.nanmax(y) - numpy.nanmin(y))noneidenticalPASS
Z-scoresignal_a_gaps; ddof 0scipy.stats.zscore(signal_a_gaps, ddof=0, nan_policy='omit')6.2 × 10⁻¹⁶10⁻¹²PASS
Z-scoresignal_a_gaps; ddof 1scipy.stats.zscore(signal_a_gaps, ddof=1, nan_policy='omit')5.4 × 10⁻¹⁶10⁻¹²PASS
Time domain89 checks · all passing · largest 1.2 × 10⁻¹⁴
OperationOur settingsReferenceDifferenceLimitResult
Moving averagesignal_a; window 101, align centeredpandas.Series(signal_a).rolling(101, center=True, min_periods=1).mean()2.7 × 10⁻¹⁶10⁻¹²PASS
Moving RMSsignal_a; window 101, align centerednumpy.sqrt(pandas.Series(signal_a**2).rolling(101, center=True, min_periods=1).mean())4.2 × 10⁻¹⁶10⁻¹²PASS
Moving averagesignal_a; window 100, align centeredpandas.Series(signal_a).rolling(100, center=True, min_periods=1).mean()2.7 × 10⁻¹⁶10⁻¹²PASS
Moving RMSsignal_a; window 100, align centerednumpy.sqrt(pandas.Series(signal_a**2).rolling(100, center=True, min_periods=1).mean())4.3 × 10⁻¹⁶10⁻¹²PASS
Moving averagesignal_a; window 25, align trailingpandas.Series(signal_a).rolling(25, center=False, min_periods=1).mean()2.1 × 10⁻¹⁶10⁻¹²PASS
Moving RMSsignal_a; window 25, align trailingnumpy.sqrt(pandas.Series(signal_a**2).rolling(25, center=False, min_periods=1).mean())2.7 × 10⁻¹⁶10⁻¹²PASS
Moving averagesignal_a_gaps; window 101, align centeredpandas.Series(signal_a_gaps).rolling(101, center=True, min_periods=1).mean()2.7 × 10⁻¹⁶10⁻¹²PASS
Moving RMSsignal_a_gaps; window 101, align centerednumpy.sqrt(pandas.Series(signal_a_gaps**2).rolling(101, center=True, min_periods=1).mean())4.2 × 10⁻¹⁶10⁻¹²PASS
Moving standard deviationsignal_a; window 101, align centered, ddof 1pandas.Series(signal_a).rolling(101, center=True, min_periods=1).std(ddof=1)9.1 × 10⁻¹⁵10⁻¹²PASS
Moving standard deviationsignal_a; window 100, align trailing, ddof 0pandas.Series(signal_a).rolling(100, center=False, min_periods=1).std(ddof=0)2.5 × 10⁻¹⁵10⁻¹²PASS
Moving standard deviationsignal_a_gaps; window 51, align centered, ddof 1pandas.Series(signal_a_gaps).rolling(51, center=True, min_periods=1).std(ddof=1)1.1 × 10⁻¹⁴10⁻¹²PASS
Expanding meansignal_a_gapspandas.Series(signal_a_gaps).expanding(min_periods=1).mean()1.2 × 10⁻¹⁶10⁻¹²PASS
Expanding standard deviationsignal_a_gaps; ddof 1pandas.Series(signal_a_gaps).expanding(min_periods=1).std(ddof=1)5 × 10⁻¹⁶10⁻¹²PASS
Expanding standard deviationsignal_a_gaps; ddof 0pandas.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 upperpandas.Series(signal_a).rolling(101, center=True, min_periods=1).max()noneidenticalPASS
Envelope (moving min / max)signal_a; window 101, align centered, side lowerpandas.Series(signal_a).rolling(101, center=True, min_periods=1).min()noneidenticalPASS
Envelope (moving min / max)signal_a_gaps; window 20, align trailing, side upperpandas.Series(signal_a_gaps).rolling(20, center=False, min_periods=1).max()noneidenticalPASS
Envelope (moving min / max)signal_a_gaps; window 20, align trailing, side lowerpandas.Series(signal_a_gaps).rolling(20, center=False, min_periods=1).min()noneidenticalPASS
Exponential moving averagesignal_a; mode span, span 20pandas.Series(signal_a).ewm(span=20, adjust=False).mean()1.8 × 10⁻¹⁶10⁻¹²PASS
Exponential moving averagesignal_a_gaps; mode alpha, alpha 0.1pandas.Series(signal_a_gaps).ewm(alpha=0.1, adjust=False, ignore_na=True).mean(), missing rows kept missing2.7 × 10⁻¹⁶10⁻¹²PASS
Exponential moving averagesignal_a; mode tau, tau 0.02explicit 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 averagesignal_a; X: row number; mode tau, tau 5pandas.Series(signal_a).ewm(alpha=1 - exp(-1/5), adjust=False).mean() (X = row number)1.4 × 10⁻¹⁶10⁻¹²PASS
Envelope (Hilbert)signal_anumpy.abs(scipy.signal.hilbert(signal_a))4.9 × 10⁻¹⁶10⁻¹²PASS
Envelope (Hilbert)signal_a_gapsnumpy.abs(scipy.signal.hilbert(gaps filled by numpy.interp over time_s)), gaps restored4.2 × 10⁻¹⁶10⁻¹²PASS
Cumulative sumsignal_a_gapsnumpy.nancumsum(signal_a_gaps), missing rows kept missing1.7 × 10⁻¹⁵10⁻¹²PASS
Differencesignal_a_gaps; lag 1pandas.Series(signal_a_gaps).diff(1)noneidenticalPASS
Differencesignal_a_gaps; lag 5pandas.Series(signal_a_gaps).diff(5)noneidenticalPASS
Derivativesignal_anumpy.gradient(signal_a, time_s)none10⁻¹²PASS
Derivativesignal_a_gapsnumpy.gradient(signal_a_gaps, time_s)none10⁻¹²PASS
Derivativesignal_a; X: row numbernumpy.gradient(signal_a) (X = row number)none10⁻¹²PASS
Integral (cumulative)signal_a; initial 0scipy.integrate.cumulative_trapezoid(signal_a, time_s, initial=0)9.6 × 10⁻¹⁶10⁻¹²PASS
Integral (cumulative)signal_a; initial 1010 + scipy.integrate.cumulative_trapezoid(signal_a, time_s, initial=0)1.2 × 10⁻¹⁵10⁻¹²PASS
Integral (cumulative)signal_a_gaps; initial 0numpy: cumsum of Δt·(y[i] + y[i-1]) / 2 with intervals touching a gap as 0, missing rows kept missing9.6 × 10⁻¹⁶10⁻¹²PASS
Detrendsignal_a; type linearsignal_a - numpy.polyval(numpy.polyfit(time_s, signal_a, 1), time_s)1.2 × 10⁻¹⁴10⁻¹²PASS
Detrendsignal_a_gaps; type constantsignal_a_gaps - numpy.nanmean(signal_a_gaps)4 × 10⁻¹⁶10⁻¹²PASS
Detrendsignal_a_gaps; type linearnumpy.polyfit over the rows with a value, against time_s1.4 × 10⁻¹⁵10⁻¹²PASS
Detrendsignal_a; X: row number; type linearscipy.signal.detrend(signal_a, type='linear') (X = row number)1.4 × 10⁻¹⁶10⁻¹²PASS
Peak detectionRowsignal_ascipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominencesnoneidenticalPASS
Peak detectiontime_ssignal_ascipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominencesnoneidenticalPASS
Peak detectionHeightsignal_ascipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominencesnoneidenticalPASS
Peak detectionProminencesignal_ascipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominencesnoneidenticalPASS
Peak detectioncountsignal_ascipy.signal.find_peaks(signal_a) + scipy.signal.peak_prominencesnoneidenticalPASS
Peak detectionRowsignal_a; height 1.0, distance 20scipy.signal.find_peaks(signal_a, height=1.0, distance=20)noneidenticalPASS
Peak detectiontime_ssignal_a; height 1.0, distance 20scipy.signal.find_peaks(signal_a, height=1.0, distance=20)noneidenticalPASS
Peak detectionHeightsignal_a; height 1.0, distance 20scipy.signal.find_peaks(signal_a, height=1.0, distance=20)noneidenticalPASS
Peak detectionProminencesignal_a; height 1.0, distance 20scipy.signal.find_peaks(signal_a, height=1.0, distance=20)noneidenticalPASS
Peak detectioncountsignal_a; height 1.0, distance 20scipy.signal.find_peaks(signal_a, height=1.0, distance=20)noneidenticalPASS
Peak detectionRowsignal_a; prominence 1.5scipy.signal.find_peaks(signal_a, prominence=1.5)noneidenticalPASS
Peak detectiontime_ssignal_a; prominence 1.5scipy.signal.find_peaks(signal_a, prominence=1.5)noneidenticalPASS
Peak detectionHeightsignal_a; prominence 1.5scipy.signal.find_peaks(signal_a, prominence=1.5)noneidenticalPASS
Peak detectionProminencesignal_a; prominence 1.5scipy.signal.find_peaks(signal_a, prominence=1.5)noneidenticalPASS
Peak detectioncountsignal_a; prominence 1.5scipy.signal.find_peaks(signal_a, prominence=1.5)noneidenticalPASS
Peak detectionRowsignal_a_gaps; height 0.5, prominence 0.3, distance 5scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3)noneidenticalPASS
Peak detectiontime_ssignal_a_gaps; height 0.5, prominence 0.3, distance 5scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3)noneidenticalPASS
Peak detectionHeightsignal_a_gaps; height 0.5, prominence 0.3, distance 5scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3)noneidenticalPASS
Peak detectionProminencesignal_a_gaps; height 0.5, prominence 0.3, distance 5scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3)noneidenticalPASS
Peak detectioncountsignal_a_gaps; height 0.5, prominence 0.3, distance 5scipy.signal.find_peaks on the rows with a value (height=0.5, distance=5, prominence=0.3)noneidenticalPASS
Zero crossingsRowsignal_a; level 0.0, direction bothnumpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingstime_ssignal_a; level 0.0, direction bothnumpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsDirection (+1 rising, −1 falling)signal_a; level 0.0, direction bothnumpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingscountsignal_a; level 0.0, direction bothnumpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsrisingsignal_a; level 0.0, direction bothnumpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsfallingsignal_a; level 0.0, direction bothnumpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsratesignal_a; level 0.0, direction bothnumpy: sign changes of (signal_a >= 0.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsRowsignal_a; level 1.0, direction risingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingstime_ssignal_a; level 1.0, direction risingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsDirection (+1 rising, −1 falling)signal_a; level 1.0, direction risingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingscountsignal_a; level 1.0, direction risingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsrisingsignal_a; level 1.0, direction risingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsfallingsignal_a; level 1.0, direction risingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsratesignal_a; level 1.0, direction risingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsRowsignal_a; level 1.0, direction fallingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingstime_ssignal_a; level 1.0, direction fallingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsDirection (+1 rising, −1 falling)signal_a; level 1.0, direction fallingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingscountsignal_a; level 1.0, direction fallingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsrisingsignal_a; level 1.0, direction fallingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsfallingsignal_a; level 1.0, direction fallingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsratesignal_a; level 1.0, direction fallingnumpy: sign changes of (signal_a >= 1.0), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsRowsignal_a_gaps; level 0.5, direction bothnumpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingstime_ssignal_a_gaps; level 0.5, direction bothnumpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsDirection (+1 rising, −1 falling)signal_a_gaps; level 0.5, direction bothnumpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingscountsignal_a_gaps; level 0.5, direction bothnumpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsrisingsignal_a_gaps; level 0.5, direction bothnumpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsfallingsignal_a_gaps; level 0.5, direction bothnumpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_snoneidenticalPASS
Zero crossingsratesignal_a_gaps; level 0.5, direction bothnumpy: sign changes of (signal_a_gaps >= 0.5), positions by linear interpolation of time_snoneidenticalPASS
Resample to uniform ratexsignal_a_gaps; rate 250numpy.interp(time_s[0] + k / 250, time_s, signal_a_gaps) over the rows with a valuenoneidenticalPASS
Resample to uniform ratesignal_a_gapssignal_a_gaps; rate 250numpy.interp(time_s[0] + k / 250, time_s, signal_a_gaps) over the rows with a valuenoneidenticalPASS
Resample to uniform ratexsignal_a_gaps; rate 1500numpy.interp(time_s[0] + k / 1500, time_s, signal_a_gaps) over the rows with a valuenoneidenticalPASS
Resample to uniform ratesignal_a_gapssignal_a_gaps; rate 1500numpy.interp(time_s[0] + k / 1500, time_s, signal_a_gaps) over the rows with a valuenoneidenticalPASS
Filtering26 checks · all passing · largest 1.2 × 10⁻¹¹
OperationOur settingsReferenceDifferenceLimitResult
Median filtersignal_a; window 5, align centeredpandas.Series(signal_a).rolling(5, center=True, min_periods=1).median()noneidenticalPASS
Median filtersignal_a; window 6, align centeredpandas.Series(signal_a).rolling(6, center=True, min_periods=1).median()noneidenticalPASS
Median filtersignal_a; window 11, align trailingpandas.Series(signal_a).rolling(11, center=False, min_periods=1).median()noneidenticalPASS
Median filtersignal_a; window 101, align centeredpandas.Series(signal_a).rolling(101, center=True, min_periods=1).median()noneidenticalPASS
Median filtersignal_a_gaps; window 5, align centeredpandas.Series(signal_a_gaps).rolling(5, center=True, min_periods=1).median()noneidenticalPASS
Butterworth filtersignal_a; type lowpass, order 4, cutoff 50.0, zeroPhase onscipy.signal.sosfiltfilt(scipy.signal.butter(4, 50.0, 'lowpass', fs=fs, output='sos'), signal_a)9.4 × 10⁻¹⁶10⁻¹⁰PASS
Butterworth filtersignal_a; type lowpass, order 4, cutoff 50.0, zeroPhase offscipy.signal.sosfilt(scipy.signal.butter(4, 50.0, 'lowpass', fs=fs, output='sos'), signal_a)none10⁻¹⁰PASS
Butterworth filtersignal_a; type highpass, order 3, cutoff 20.0, zeroPhase onscipy.signal.sosfiltfilt(scipy.signal.butter(3, 20.0, 'highpass', fs=fs, output='sos'), signal_a)2.4 × 10⁻¹⁵10⁻¹⁰PASS
Butterworth filtersignal_a; type highpass, order 7, cutoff 100.0, zeroPhase offscipy.signal.sosfilt(scipy.signal.butter(7, 100.0, 'highpass', fs=fs, output='sos'), signal_a)none10⁻¹⁰PASS
Butterworth filtersignal_a; type bandpass, order 2, cutoff 30.0–80.0, zeroPhase onscipy.signal.sosfiltfilt(scipy.signal.butter(2, [30.0, 80.0], 'bandpass', fs=fs, output='sos'), signal_a)2.1 × 10⁻¹⁵10⁻¹⁰PASS
Butterworth filtersignal_a; type bandpass, order 5, cutoff 100.0–140.0, zeroPhase offscipy.signal.sosfilt(scipy.signal.butter(5, [100.0, 140.0], 'bandpass', fs=fs, output='sos'), signal_a)1.9 × 10⁻¹⁵10⁻¹⁰PASS
Butterworth filtersignal_a; type bandstop, order 4, cutoff 40.0–60.0, zeroPhase onscipy.signal.sosfiltfilt(scipy.signal.butter(4, [40.0, 60.0], 'bandstop', fs=fs, output='sos'), signal_a)5.6 × 10⁻¹⁵10⁻¹⁰PASS
Butterworth filtersignal_a; type bandstop, order 6, cutoff 110.0–130.0, zeroPhase offscipy.signal.sosfilt(scipy.signal.butter(6, [110.0, 130.0], 'bandstop', fs=fs, output='sos'), signal_a)2.5 × 10⁻¹⁵10⁻¹⁰PASS
Butterworth filtersignal_a; type lowpass, order 1, cutoff 10.0, zeroPhase onscipy.signal.sosfiltfilt(scipy.signal.butter(1, 10.0, 'lowpass', fs=fs, output='sos'), signal_a)4.5 × 10⁻¹⁵10⁻¹⁰PASS
Butterworth filtersignal_a; type lowpass, order 10, cutoff 100.0, zeroPhase onscipy.signal.sosfiltfilt(scipy.signal.butter(10, 100.0, 'lowpass', fs=fs, output='sos'), signal_a)2.8 × 10⁻¹⁵10⁻¹⁰PASS
Butterworth filtersignal_a_gaps; type lowpass, order 4, cutoff 50.0, zeroPhase onscipy.signal.sosfiltfilt(scipy.signal.butter(4, 50.0, 'lowpass', fs=fs, output='sos'), signal_a_gaps) with gaps filled by numpy.interp, gaps restored10⁻¹⁵10⁻¹⁰PASS
Savitzky-Golay smoothingsignal_a; window 11, polyorder 3scipy.signal.savgol_filter(signal_a, 11, 3, mode='interp')2.2 × 10⁻¹⁵10⁻¹²PASS
Savitzky-Golay smoothingsignal_a; window 51, polyorder 4scipy.signal.savgol_filter(signal_a, 51, 4, mode='interp')1.2 × 10⁻¹¹10⁻¹⁰PASS
Savitzky-Golay smoothingsignal_a_gaps; window 11, polyorder 3scipy.signal.savgol_filter(signal_a_gaps, 11, 3, mode='interp')2.2 × 10⁻¹⁵10⁻¹²PASS
Savitzky-Golay smoothingsignal_a; window 51, polyorder 4the same filter in exact rational arithmetic (Python fractions.Fraction), rounded once at the end6.5 × 10⁻¹⁶10⁻¹³PASS
Decimate (with anti-alias filter)xsignal_a; factor 4, zeroPhase onscipy.signal.decimate(signal_a, 4, zero_phase=True)none10⁻¹⁰PASS
Decimate (with anti-alias filter)signal_asignal_a; factor 4, zeroPhase onscipy.signal.decimate(signal_a, 4, zero_phase=True)5.5 × 10⁻¹⁵10⁻¹⁰PASS
Decimate (with anti-alias filter)xsignal_a; factor 10, zeroPhase offscipy.signal.decimate(signal_a, 10, zero_phase=False)none10⁻¹⁰PASS
Decimate (with anti-alias filter)signal_asignal_a; factor 10, zeroPhase offscipy.signal.decimate(signal_a, 10, zero_phase=False)2.3 × 10⁻¹⁴10⁻¹⁰PASS
Decimate (with anti-alias filter)xsignal_a_gaps; factor 4, zeroPhase onscipy.signal.decimate(signal_a_gaps, 4, zero_phase=True)none10⁻¹⁰PASS
Decimate (with anti-alias filter)signal_a_gapssignal_a_gaps; factor 4, zeroPhase onscipy.signal.decimate(signal_a_gaps, 4, zero_phase=True)5.6 × 10⁻¹⁵10⁻¹⁰PASS
Frequency domain124 checks · all passing · largest 4.5 × 10⁻¹⁴
OperationOur settingsReferenceDifferenceLimitResult
FFT spectrumxsignal_a; window rect, scaling amplitude, detrend none, length all, db offscipy.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 spectrumAmplitudesignal_a; window rect, scaling amplitude, detrend none, length all, db offscipy.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 spectrumdfsignal_a; window rect, scaling amplitude, detrend none, length all, db offscipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P))none10⁻¹²PASS
FFT spectrumxsignal_a; window hann, scaling rms, detrend constant, length all, db offscipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='constant', scaling='spectrum') → sqrt(P)1.1 × 10⁻¹⁶10⁻¹²PASS
FFT spectrumRMS amplitudesignal_a; window hann, scaling rms, detrend constant, length all, db offscipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='constant', scaling='spectrum') → sqrt(P)4.8 × 10⁻¹⁶10⁻¹²PASS
FFT spectrumdfsignal_a; window hann, scaling rms, detrend constant, length all, db offscipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='constant', scaling='spectrum') → sqrt(P)none10⁻¹²PASS
FFT spectrumxsignal_a; window hamming, scaling power, detrend linear, length pow2, db offscipy.signal.periodogram(signal_a, fs, window='hamming', nfft=4096, detrend='linear', scaling='spectrum') → Pnone10⁻¹²PASS
FFT spectrumPowersignal_a; window hamming, scaling power, detrend linear, length pow2, db offscipy.signal.periodogram(signal_a, fs, window='hamming', nfft=4096, detrend='linear', scaling='spectrum') → P2.3 × 10⁻¹⁵10⁻¹²PASS
FFT spectrumdfsignal_a; window hamming, scaling power, detrend linear, length pow2, db offscipy.signal.periodogram(signal_a, fs, window='hamming', nfft=4096, detrend='linear', scaling='spectrum') → Pnone10⁻¹²PASS
FFT spectrumxsignal_a; window blackman, scaling amplitude, detrend constant, length pow2, db offscipy.signal.periodogram(signal_a, fs, window='blackman', nfft=4096, detrend='constant', scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P))none10⁻¹²PASS
FFT spectrumAmplitudesignal_a; window blackman, scaling amplitude, detrend constant, length pow2, db offscipy.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 spectrumdfsignal_a; window blackman, scaling amplitude, detrend constant, length pow2, db offscipy.signal.periodogram(signal_a, fs, window='blackman', nfft=4096, detrend='constant', scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P))none10⁻¹²PASS
FFT spectrumxsignal_a; window flattop, scaling amplitude, detrend none, length all, db offscipy.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 spectrumAmplitudesignal_a; window flattop, scaling amplitude, detrend none, length all, db offscipy.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 spectrumdfsignal_a; window flattop, scaling amplitude, detrend none, length all, db offscipy.signal.periodogram(signal_a, fs, window='flattop', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P))none10⁻¹²PASS
FFT spectrumxsignal_a; window rect, scaling amplitude, detrend none, length all, db onscipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) → dB1.1 × 10⁻¹⁶10⁻¹²PASS
FFT spectrumAmplitudesignal_a; window rect, scaling amplitude, detrend none, length all, db onscipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) → dB1.5 × 10⁻¹⁴10⁻¹²PASS
FFT spectrumdfsignal_a; window rect, scaling amplitude, detrend none, length all, db onscipy.signal.periodogram(signal_a, fs, window='boxcar', nfft=n, detrend=False, scaling='spectrum') → sqrt(P)·√2 (DC, Nyquist: sqrt(P)) → dBnone10⁻¹²PASS
FFT spectrumxsignal_a; window hann, scaling power, detrend linear, length all, db onscipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='linear', scaling='spectrum') → P → dB1.1 × 10⁻¹⁶10⁻¹²PASS
FFT spectrumPowersignal_a; window hann, scaling power, detrend linear, length all, db onscipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='linear', scaling='spectrum') → P → dB5.6 × 10⁻¹⁵10⁻¹²PASS
FFT spectrumdfsignal_a; window hann, scaling power, detrend linear, length all, db onscipy.signal.periodogram(signal_a, fs, window='hann', nfft=n, detrend='linear', scaling='spectrum') → P → dBnone10⁻¹²PASS
PSD (Welch)xsignal_a; nperseg 4096, overlap 50, window hann, scaling density, db offscipy.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)PSDsignal_a; nperseg 4096, overlap 50, window hann, scaling density, db offscipy.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)dfsignal_a; nperseg 4096, overlap 50, window hann, scaling density, db offscipy.signal.welch(signal_a, fs, window='hann', nperseg=4096, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f))none10⁻¹²PASS
PSD (Welch)segmentssignal_a; nperseg 4096, overlap 50, window hann, scaling density, db offscipy.signal.welch(signal_a, fs, window='hann', nperseg=4096, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f))none10⁻¹²PASS
PSD (Welch)grmssignal_a; nperseg 4096, overlap 50, window hann, scaling density, db offscipy.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)xsignal_a; nperseg 512, overlap 50, window hann, scaling density, db offscipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f))none10⁻¹²PASS
PSD (Welch)PSDsignal_a; nperseg 512, overlap 50, window hann, scaling density, db offscipy.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)dfsignal_a; nperseg 512, overlap 50, window hann, scaling density, db offscipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f))none10⁻¹²PASS
PSD (Welch)segmentssignal_a; nperseg 512, overlap 50, window hann, scaling density, db offscipy.signal.welch(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f))none10⁻¹²PASS
PSD (Welch)grmssignal_a; nperseg 512, overlap 50, window hann, scaling density, db offscipy.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)xsignal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db offscipy.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)none10⁻¹²PASS
PSD (Welch)PSDsignal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db offscipy.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)dfsignal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db offscipy.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)none10⁻¹²PASS
PSD (Welch)segmentssignal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db offscipy.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)none10⁻¹²PASS
PSD (Welch)grmssignal_a; nperseg 1024, overlap 75, window hamming, scaling density, band 40.0–130.0, db offscipy.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)xsignal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db offscipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum')none10⁻¹²PASS
PSD (Welch)PSDsignal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db offscipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum')8.1 × 10⁻¹⁸10⁻¹²PASS
PSD (Welch)dfsignal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db offscipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum')none10⁻¹²PASS
PSD (Welch)segmentssignal_a; nperseg 256, overlap 0, window rect, scaling spectrum, db offscipy.signal.welch(signal_a, fs, window='boxcar', nperseg=256, noverlap=floor(0% of the segment), scaling='spectrum')none10⁻¹²PASS
PSD (Welch)xsignal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db offscipy.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)none10⁻¹²PASS
PSD (Welch)PSDsignal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db offscipy.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)dfsignal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db offscipy.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)none10⁻¹²PASS
PSD (Welch)segmentssignal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db offscipy.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)none10⁻¹²PASS
PSD (Welch)grmssignal_a; nperseg 512, overlap 50, window blackman, scaling density, band 45.5–54.5, db offscipy.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)xsignal_a; nperseg 512, overlap 30, window flattop, scaling density, db onscipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10none10⁻¹²PASS
PSD (Welch)PSDsignal_a; nperseg 512, overlap 30, window flattop, scaling density, db onscipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log106.6 × 10⁻¹⁶10⁻¹²PASS
PSD (Welch)dfsignal_a; nperseg 512, overlap 30, window flattop, scaling density, db onscipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10none10⁻¹²PASS
PSD (Welch)segmentssignal_a; nperseg 512, overlap 30, window flattop, scaling density, db onscipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log10none10⁻¹²PASS
PSD (Welch)grmssignal_a; nperseg 512, overlap 30, window flattop, scaling density, db onscipy.signal.welch(signal_a, fs, window='flattop', nperseg=512, noverlap=floor(30% of the segment), scaling='density'); Grms = sqrt(numpy.trapezoid(psd, f)) → 10·log103.9 × 10⁻¹⁶10⁻¹²PASS
PSD (Welch)xsignal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db offscipy.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)none10⁻¹²PASS
PSD (Welch)PSDsignal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db offscipy.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)dfsignal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db offscipy.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)none10⁻¹²PASS
PSD (Welch)segmentssignal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db offscipy.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)none10⁻¹²PASS
PSD (Welch)grmssignal_a_gaps; nperseg 512, overlap 50, window hann, scaling density, db offscipy.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 coherencexsignal_a, signal_b; nperseg 512, window hann, estimator H1H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hann', nperseg=512)none10⁻¹²PASS
FRF (H1 / H2) and coherence|H1|signal_a, signal_b; nperseg 512, window hann, estimator H1H1 = 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 H1signal_a, signal_b; nperseg 512, window hann, estimator H1H1 = 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 coherenceCoherencesignal_a, signal_b; nperseg 512, window hann, estimator H1H1 = 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 coherencexsignal_a, signal_b; nperseg 1024, window hamming, estimator H2H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='hamming', nperseg=1024)none10⁻¹²PASS
FRF (H1 / H2) and coherence|H2|signal_a, signal_b; nperseg 1024, window hamming, estimator H2H1 = 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 H2signal_a, signal_b; nperseg 1024, window hamming, estimator H2H1 = 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 coherenceCoherencesignal_a, signal_b; nperseg 1024, window hamming, estimator H2H1 = 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 coherencexsignal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2H1 = csd(signal_a, signal_b) / welch(signal_a), H2 = welch(signal_b) / conj(csd), coherence = |csd|² / (welch·welch) (scipy.signal, window='flattop', nperseg=512)none10⁻¹²PASS
FRF (H1 / H2) and coherence|H1|signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2H1 = 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 H1signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2H1 = 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 H2H1 = 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 H2signal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2H1 = 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 coherenceCoherencesignal_a, signal_b; nperseg 512, window flattop, estimator H1 and H2H1 = 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 coherencexsignal_a, signal_b; nperseg 256, window rect, estimator H1H1 = 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)none10⁻¹²PASS
FRF (H1 / H2) and coherence|H1|signal_a, signal_b; nperseg 256, window rect, estimator H1H1 = 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 H1signal_a, signal_b; nperseg 256, window rect, estimator H1H1 = 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 coherenceCoherencesignal_a, signal_b; nperseg 256, window rect, estimator H1H1 = 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 coherencexsignal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2H1 = 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)none10⁻¹²PASS
FRF (H1 / H2) and coherence|H1|signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2H1 = 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 H1signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2H1 = 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 H2H1 = 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 H2signal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2H1 = 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 coherenceCoherencesignal_a_gaps, signal_b; nperseg 2048, window blackman, estimator H1 and H2H1 = 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 SNRsnrsignal_a; signal 45.0–55.0, noise 200.0–300.0, nperseg 512, window hann10·log10(band power 45.0–55.0 Hz / 200.0–300.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=512, window='hann')none10⁻¹²PASS
Band SNRsignalsignal_a; signal 45.0–55.0, noise 200.0–300.0, nperseg 512, window hann10·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 SNRnoisesignal_a; signal 45.0–55.0, noise 200.0–300.0, nperseg 512, window hann10·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 SNRsnrsignal_a; signal 110.0–130.0, nperseg 1024, window flattop10·log10(band power 110.0–130.0 Hz / rest of the spectrum), numpy.trapezoid of scipy.signal.welch(nperseg=1024, window='flattop')none10⁻¹²PASS
Band SNRsignalsignal_a; signal 110.0–130.0, nperseg 1024, window flattop10·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 SNRnoisesignal_a; signal 110.0–130.0, nperseg 1024, window flattop10·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 SNRsnrsignal_a; signal 45.0–55.0, noise 60.0–110.0, nperseg 4096, window rect10·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 SNRsignalsignal_a; signal 45.0–55.0, noise 60.0–110.0, nperseg 4096, window rect10·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 SNRnoisesignal_a; signal 45.0–55.0, noise 60.0–110.0, nperseg 4096, window rect10·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 SNRsnrsignal_a; signal 115.0–125.0, noise 300.0–450.0, nperseg 256, window hamming10·log10(band power 115.0–125.0 Hz / 300.0–450.0 Hz), numpy.trapezoid of scipy.signal.welch(nperseg=256, window='hamming')none10⁻¹²PASS
Band SNRsignalsignal_a; signal 115.0–125.0, noise 300.0–450.0, nperseg 256, window hamming10·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 SNRnoisesignal_a; signal 115.0–125.0, noise 300.0–450.0, nperseg 256, window hamming10·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 SNRsnrsignal_a; signal 48.0–52.0, nperseg 2048, window blackman10·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 SNRsignalsignal_a; signal 48.0–52.0, nperseg 2048, window blackman10·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 SNRnoisesignal_a; signal 48.0–52.0, nperseg 2048, window blackman10·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
Spectrogramxsignal_a; nperseg 1024, overlap 50scipy.signal.spectrogram(signal_a, fs, nperseg=1024, noverlap=floor(50% of 1024)) (window ('tukey', 0.25), psd)none10⁻¹²PASS
Spectrogramysignal_a; nperseg 1024, overlap 50scipy.signal.spectrogram(signal_a, fs, nperseg=1024, noverlap=floor(50% of 1024)) (window ('tukey', 0.25), psd)none10⁻¹²PASS
Spectrogramsignal_a; nperseg 1024, overlap 50scipy.signal.spectrogram(signal_a, fs, nperseg=1024, noverlap=floor(50% of 1024)) (window ('tukey', 0.25), psd)4.5 × 10⁻¹⁶10⁻¹²PASS
Spectrogramxsignal_a; nperseg 256, overlap 50scipy.signal.spectrogram(signal_a, fs, nperseg=256, noverlap=floor(50% of 256)) (window ('tukey', 0.25), psd)none10⁻¹²PASS
Spectrogramysignal_a; nperseg 256, overlap 50scipy.signal.spectrogram(signal_a, fs, nperseg=256, noverlap=floor(50% of 256)) (window ('tukey', 0.25), psd)none10⁻¹²PASS
Spectrogramsignal_a; nperseg 256, overlap 50scipy.signal.spectrogram(signal_a, fs, nperseg=256, noverlap=floor(50% of 256)) (window ('tukey', 0.25), psd)6.2 × 10⁻¹⁶10⁻¹²PASS
Spectrogramxsignal_a_gaps; nperseg 128, overlap 75scipy.signal.spectrogram(signal_a_gaps, fs, nperseg=128, noverlap=floor(75% of 128)) (window ('tukey', 0.25), psd)none10⁻¹²PASS
Spectrogramysignal_a_gaps; nperseg 128, overlap 75scipy.signal.spectrogram(signal_a_gaps, fs, nperseg=128, noverlap=floor(75% of 128)) (window ('tukey', 0.25), psd)none10⁻¹²PASS
Spectrogramsignal_a_gaps; nperseg 128, overlap 75scipy.signal.spectrogram(signal_a_gaps, fs, nperseg=128, noverlap=floor(75% of 128)) (window ('tukey', 0.25), psd)4.9 × 10⁻¹⁶10⁻¹²PASS
Spectrogramxsignal_a; nperseg 100, overlap 0scipy.signal.spectrogram(signal_a, fs, nperseg=100, noverlap=floor(0% of 100)) (window ('tukey', 0.25), psd)none10⁻¹²PASS
Spectrogramysignal_a; nperseg 100, overlap 0scipy.signal.spectrogram(signal_a, fs, nperseg=100, noverlap=floor(0% of 100)) (window ('tukey', 0.25), psd)1.1 × 10⁻¹⁶10⁻¹²PASS
Spectrogramsignal_a; nperseg 100, overlap 0scipy.signal.spectrogram(signal_a, fs, nperseg=100, noverlap=floor(0% of 100)) (window ('tukey', 0.25), psd)5.4 × 10⁻¹⁶10⁻¹²PASS
Spectrogramxsignal_a; nperseg 512, overlap 50, window hannscipy.signal.spectrogram(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of 512)) (psd)none10⁻¹²PASS
Spectrogramysignal_a; nperseg 512, overlap 50, window hannscipy.signal.spectrogram(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of 512)) (psd)none10⁻¹²PASS
Spectrogramsignal_a; nperseg 512, overlap 50, window hannscipy.signal.spectrogram(signal_a, fs, window='hann', nperseg=512, noverlap=floor(50% of 512)) (psd)9.6 × 10⁻¹⁶10⁻¹²PASS
Spectrogramxsignal_a; nperseg 256, overlap 75, window hamming, range 40.0–130.0scipy.signal.spectrogram(signal_a, fs, window='hamming', nperseg=256, noverlap=floor(75% of 256)) (psd); the rows from 40.0 to 130.0 Hznone10⁻¹²PASS
Spectrogramysignal_a; nperseg 256, overlap 75, window hamming, range 40.0–130.0scipy.signal.spectrogram(signal_a, fs, window='hamming', nperseg=256, noverlap=floor(75% of 256)) (psd); the rows from 40.0 to 130.0 Hznone10⁻¹²PASS
Spectrogramsignal_a; nperseg 256, overlap 75, window hamming, range 40.0–130.0scipy.signal.spectrogram(signal_a, fs, window='hamming', nperseg=256, noverlap=floor(75% of 256)) (psd); the rows from 40.0 to 130.0 Hz7 × 10⁻¹⁶10⁻¹²PASS
Spectrogramxsignal_a_gaps; nperseg 1024, overlap 50, window rectscipy.signal.spectrogram(signal_a_gaps, fs, window='boxcar', nperseg=1024, noverlap=floor(50% of 1024)) (psd)none10⁻¹²PASS
Spectrogramysignal_a_gaps; nperseg 1024, overlap 50, window rectscipy.signal.spectrogram(signal_a_gaps, fs, window='boxcar', nperseg=1024, noverlap=floor(50% of 1024)) (psd)none10⁻¹²PASS
Spectrogramsignal_a_gaps; nperseg 1024, overlap 50, window rectscipy.signal.spectrogram(signal_a_gaps, fs, window='boxcar', nperseg=1024, noverlap=floor(50% of 1024)) (psd)1.2 × 10⁻¹⁶10⁻¹²PASS
Spectrogramxsignal_a; nperseg 512, overlap 25, window blackman, range 0.0–60.0scipy.signal.spectrogram(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(25% of 512)) (psd); the rows from 0.0 to 60.0 Hznone10⁻¹²PASS
Spectrogramysignal_a; nperseg 512, overlap 25, window blackman, range 0.0–60.0scipy.signal.spectrogram(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(25% of 512)) (psd); the rows from 0.0 to 60.0 Hznone10⁻¹²PASS
Spectrogramsignal_a; nperseg 512, overlap 25, window blackman, range 0.0–60.0scipy.signal.spectrogram(signal_a, fs, window='blackman', nperseg=512, noverlap=floor(25% of 512)) (psd); the rows from 0.0 to 60.0 Hz1.1 × 10⁻¹⁵10⁻¹²PASS
Spectrogramxsignal_a; nperseg 256, overlap 50, window flattopscipy.signal.spectrogram(signal_a, fs, window='flattop', nperseg=256, noverlap=floor(50% of 256)) (psd)none10⁻¹²PASS
Spectrogramysignal_a; nperseg 256, overlap 50, window flattopscipy.signal.spectrogram(signal_a, fs, window='flattop', nperseg=256, noverlap=floor(50% of 256)) (psd)none10⁻¹²PASS
Spectrogramsignal_a; nperseg 256, overlap 50, window flattopscipy.signal.spectrogram(signal_a, fs, window='flattop', nperseg=256, noverlap=floor(50% of 256)) (psd)1.1 × 10⁻¹⁵10⁻¹²PASS
Spectrogramxsignal_a; nperseg 1024, overlap 50, window tukey, range 100.0–200.0scipy.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 Hznone10⁻¹²PASS
Spectrogramysignal_a; nperseg 1024, overlap 50, window tukey, range 100.0–200.0scipy.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 Hznone10⁻¹²PASS
Spectrogramsignal_a; nperseg 1024, overlap 50, window tukey, range 100.0–200.0scipy.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 Hz4.7 × 10⁻¹⁶10⁻¹²PASS
Statistics120 checks · all passing · largest 4.8 × 10⁻¹³
OperationOur settingsReferenceDifferenceLimitResult
HistogramFromsignal_a; bins autonumpy.histogram(signal_a, bins='auto')noneidenticalPASS
HistogramTosignal_a; bins autonumpy.histogram(signal_a, bins='auto')noneidenticalPASS
HistogramCountsignal_a; bins autonumpy.histogram(signal_a, bins='auto')noneidenticalPASS
Histogramcountsignal_a; bins autonumpy.histogram(signal_a, bins='auto')noneidenticalPASS
Histogrambinssignal_a; bins autonumpy.histogram(signal_a, bins='auto')noneidenticalPASS
HistogramFromsignal_a; bins fdnumpy.histogram(signal_a, bins='fd')noneidenticalPASS
HistogramTosignal_a; bins fdnumpy.histogram(signal_a, bins='fd')noneidenticalPASS
HistogramCountsignal_a; bins fdnumpy.histogram(signal_a, bins='fd')noneidenticalPASS
Histogramcountsignal_a; bins fdnumpy.histogram(signal_a, bins='fd')noneidenticalPASS
Histogrambinssignal_a; bins fdnumpy.histogram(signal_a, bins='fd')noneidenticalPASS
HistogramFromsignal_a; bins sturgesnumpy.histogram(signal_a, bins='sturges')noneidenticalPASS
HistogramTosignal_a; bins sturgesnumpy.histogram(signal_a, bins='sturges')noneidenticalPASS
HistogramCountsignal_a; bins sturgesnumpy.histogram(signal_a, bins='sturges')noneidenticalPASS
Histogramcountsignal_a; bins sturgesnumpy.histogram(signal_a, bins='sturges')noneidenticalPASS
Histogrambinssignal_a; bins sturgesnumpy.histogram(signal_a, bins='sturges')noneidenticalPASS
HistogramFromsignal_a; bins sqrtnumpy.histogram(signal_a, bins='sqrt')noneidenticalPASS
HistogramTosignal_a; bins sqrtnumpy.histogram(signal_a, bins='sqrt')noneidenticalPASS
HistogramCountsignal_a; bins sqrtnumpy.histogram(signal_a, bins='sqrt')noneidenticalPASS
Histogramcountsignal_a; bins sqrtnumpy.histogram(signal_a, bins='sqrt')noneidenticalPASS
Histogrambinssignal_a; bins sqrtnumpy.histogram(signal_a, bins='sqrt')noneidenticalPASS
HistogramFromsignal_a; bins 10numpy.histogram(signal_a, bins=10)noneidenticalPASS
HistogramTosignal_a; bins 10numpy.histogram(signal_a, bins=10)noneidenticalPASS
HistogramCountsignal_a; bins 10numpy.histogram(signal_a, bins=10)noneidenticalPASS
Histogramcountsignal_a; bins 10numpy.histogram(signal_a, bins=10)noneidenticalPASS
Histogrambinssignal_a; bins 10numpy.histogram(signal_a, bins=10)noneidenticalPASS
HistogramFromsignal_a; bins 20numpy.histogram(signal_a, bins=20)noneidenticalPASS
HistogramTosignal_a; bins 20numpy.histogram(signal_a, bins=20)noneidenticalPASS
HistogramCountsignal_a; bins 20numpy.histogram(signal_a, bins=20)noneidenticalPASS
Histogramcountsignal_a; bins 20numpy.histogram(signal_a, bins=20)noneidenticalPASS
Histogrambinssignal_a; bins 20numpy.histogram(signal_a, bins=20)noneidenticalPASS
HistogramFromsignal_a; bins 50numpy.histogram(signal_a, bins=50)noneidenticalPASS
HistogramTosignal_a; bins 50numpy.histogram(signal_a, bins=50)noneidenticalPASS
HistogramCountsignal_a; bins 50numpy.histogram(signal_a, bins=50)noneidenticalPASS
Histogramcountsignal_a; bins 50numpy.histogram(signal_a, bins=50)noneidenticalPASS
Histogrambinssignal_a; bins 50numpy.histogram(signal_a, bins=50)noneidenticalPASS
HistogramFromsignal_a; bins 100numpy.histogram(signal_a, bins=100)noneidenticalPASS
HistogramTosignal_a; bins 100numpy.histogram(signal_a, bins=100)noneidenticalPASS
HistogramCountsignal_a; bins 100numpy.histogram(signal_a, bins=100)noneidenticalPASS
Histogramcountsignal_a; bins 100numpy.histogram(signal_a, bins=100)noneidenticalPASS
Histogrambinssignal_a; bins 100numpy.histogram(signal_a, bins=100)noneidenticalPASS
HistogramFromsignal_a_gaps; bins autonumpy.histogram(values of signal_a_gaps, bins='auto')noneidenticalPASS
HistogramTosignal_a_gaps; bins autonumpy.histogram(values of signal_a_gaps, bins='auto')noneidenticalPASS
HistogramCountsignal_a_gaps; bins autonumpy.histogram(values of signal_a_gaps, bins='auto')noneidenticalPASS
Histogramcountsignal_a_gaps; bins autonumpy.histogram(values of signal_a_gaps, bins='auto')noneidenticalPASS
Histogrambinssignal_a_gaps; bins autonumpy.histogram(values of signal_a_gaps, bins='auto')noneidenticalPASS
RMS, crest factor, peak to peakminsignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)none10⁻¹³PASS
RMS, crest factor, peak to peakmaxsignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)none10⁻¹³PASS
RMS, crest factor, peak to peakmeansignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)2.5 × 10⁻¹⁵10⁻¹³PASS
RMS, crest factor, peak to peakrmssignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)none10⁻¹³PASS
RMS, crest factor, peak to peakp2psignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)none10⁻¹³PASS
RMS, crest factor, peak to peakcrestsignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)none10⁻¹³PASS
RMS, crest factor, peak to peakstdsignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)4 × 10⁻¹⁶10⁻¹³PASS
RMS, crest factor, peak to peakcountsignal_a_gapsnumpy.nanmin / nanmax / nanmean / sqrt(nanmean(y²)) / nanstd(ddof=1)none10⁻¹³PASS
Percentiles, skewness, kurtosisp1signal_a_gaps; bias offnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp5signal_a_gaps; bias offnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp50signal_a_gaps; bias offnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp95signal_a_gaps; bias offnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp99signal_a_gaps; bias offnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisskewnesssignal_a_gaps; bias offnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit')7.9 × 10⁻¹⁴10⁻¹²PASS
Percentiles, skewness, kurtosiskurtosissignal_a_gaps; bias offnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=True, nan_policy='omit')1.6 × 10⁻¹⁴10⁻¹²PASS
Percentiles, skewness, kurtosisp1signal_a_gaps; bias onnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp5signal_a_gaps; bias onnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp50signal_a_gaps; bias onnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp95signal_a_gaps; bias onnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisp99signal_a_gaps; bias onnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit')none10⁻¹²PASS
Percentiles, skewness, kurtosisskewnesssignal_a_gaps; bias onnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit')7.9 × 10⁻¹⁴10⁻¹²PASS
Percentiles, skewness, kurtosiskurtosissignal_a_gaps; bias onnumpy.nanpercentile(y, [1, 5, 50, 95, 99]); scipy.stats.skew / kurtosis(y, bias=False, nan_policy='omit')1.6 × 10⁻¹⁴10⁻¹²PASS
Correlation (Pearson)rsignal_a, signal_bscipy.stats.pearsonr(signal_a, signal_b)3.6 × 10⁻¹⁵10⁻¹³PASS
Correlation (Pearson)r2signal_a, signal_bscipy.stats.pearsonr(signal_a, signal_b)7.2 × 10⁻¹⁵10⁻¹³PASS
Correlation (Pearson)rsignal_a_gaps, pricescipy.stats.pearsonr on the rows where both have a value3 × 10⁻¹⁵10⁻¹³PASS
Correlation (Pearson)r2signal_a_gaps, pricescipy.stats.pearsonr on the rows where both have a value6 × 10⁻¹⁵10⁻¹³PASS
Polynomial fitsignal_a; degree 1numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot6.3 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitr2signal_a; degree 1numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot1.3 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitcoefficientssignal_a; degree 1numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot7.4 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitmusignal_a; degree 1numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot5.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitsigmasignal_a; degree 1numpy.polyfit((time_s - mean) / std, signal_a, 1); R² = 1 - SS_res / SS_tot3.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitsignal_a; degree 3numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot3.2 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitr2signal_a; degree 3numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot1.7 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitcoefficientssignal_a; degree 3numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot9.5 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitmusignal_a; degree 3numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot5.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitsigmasignal_a; degree 3numpy.polyfit((time_s - mean) / std, signal_a, 3); R² = 1 - SS_res / SS_tot3.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitprice; degree 0numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot1.7 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitr2price; degree 0numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot9.3 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitcoefficientsprice; degree 0numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot1.7 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitmuprice; degree 0numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot5.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitsigmaprice; degree 0numpy.polyfit((time_s - mean) / std, price, 0); R² = 1 - SS_res / SS_tot3.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitprice; degree 10numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot1.3 × 10⁻¹³10⁻¹²PASS
Polynomial fitr2price; degree 10numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot4.3 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitcoefficientsprice; degree 10numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot4.8 × 10⁻¹³10⁻¹²PASS
Polynomial fitmuprice; degree 10numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot5.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitsigmaprice; degree 10numpy.polyfit((time_s - mean) / std, price, 10); R² = 1 - SS_res / SS_tot3.6 × 10⁻¹⁴10⁻¹²PASS
Polynomial fitsignal_a_gaps; degree 2numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot2.8 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitr2signal_a_gaps; degree 2numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot1.4 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitcoefficientssignal_a_gaps; degree 2numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot2.9 × 10⁻¹⁵10⁻¹²PASS
Polynomial fitmusignal_a_gaps; degree 2numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot6.7 × 10⁻¹⁶10⁻¹²PASS
Polynomial fitsigmasignal_a_gaps; degree 2numpy.polyfit((time_s - mean) / std, signal_a_gaps, 2); R² = 1 - SS_res / SS_tot3.8 × 10⁻¹⁶10⁻¹²PASS
Cross-correlationxsignal_a, signal_b; normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²)none10⁻¹²PASS
Cross-correlationCorrelationsignal_a, signal_b; normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²)4.6 × 10⁻¹⁶10⁻¹²PASS
Cross-correlationpeakLagsignal_a, signal_b; normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²)none10⁻¹²PASS
Cross-correlationdelaysignal_a, signal_b; normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²)none10⁻¹²PASS
Cross-correlationxsignal_a, signal_b; maxLag 50, normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 50none10⁻¹²PASS
Cross-correlationCorrelationsignal_a, signal_b; maxLag 50, normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 505.6 × 10⁻¹⁶10⁻¹²PASS
Cross-correlationpeakLagsignal_a, signal_b; maxLag 50, normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 50none10⁻¹²PASS
Cross-correlationdelaysignal_a, signal_b; maxLag 50, normalization coeffscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 50none10⁻¹²PASS
Cross-correlationxsignal_a, signal_b; maxLag 200, normalization biasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 200none10⁻¹²PASS
Cross-correlationCorrelationsignal_a, signal_b; maxLag 200, normalization biasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 2005.6 × 10⁻¹⁶10⁻¹²PASS
Cross-correlationpeakLagsignal_a, signal_b; maxLag 200, normalization biasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 200none10⁻¹²PASS
Cross-correlationdelaysignal_a, signal_b; maxLag 200, normalization biasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / N, |lag| <= 200none10⁻¹²PASS
Cross-correlationxsignal_a, signal_b; maxLag 200, normalization unbiasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 200none10⁻¹²PASS
Cross-correlationCorrelationsignal_a, signal_b; maxLag 200, normalization unbiasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 2006.7 × 10⁻¹⁶10⁻¹²PASS
Cross-correlationpeakLagsignal_a, signal_b; maxLag 200, normalization unbiasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 200none10⁻¹²PASS
Cross-correlationdelaysignal_a, signal_b; maxLag 200, normalization unbiasedscipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / (N - |lag|), |lag| <= 200none10⁻¹²PASS
Cross-correlationxsignal_a, signal_b; maxLag 30, normalization nonescipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 30none10⁻¹²PASS
Cross-correlationCorrelationsignal_a, signal_b; maxLag 30, normalization nonescipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 306 × 10⁻¹⁶10⁻¹²PASS
Cross-correlationpeakLagsignal_a, signal_b; maxLag 30, normalization nonescipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 30none10⁻¹²PASS
Cross-correlationdelaysignal_a, signal_b; maxLag 30, normalization nonescipy.signal.correlate(signal_a - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, raw sums, |lag| <= 30none10⁻¹²PASS
Cross-correlationxsignal_a_gaps, signal_b; maxLag 100, normalization coeffscipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 100none10⁻¹²PASS
Cross-correlationCorrelationsignal_a_gaps, signal_b; maxLag 100, normalization coeffscipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 1008.9 × 10⁻¹⁶10⁻¹²PASS
Cross-correlationpeakLagsignal_a_gaps, signal_b; maxLag 100, normalization coeffscipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 100none10⁻¹²PASS
Cross-correlationdelaysignal_a_gaps, signal_b; maxLag 100, normalization coeffscipy.signal.correlate(signal_a_gaps - mean, signal_b - mean, 'full') with scipy.signal.correlation_lags, / sqrt(Σa²·Σb²), |lag| <= 100none10⁻¹²PASS
Engineering76 checks · all passing · largest 1.1 × 10⁻¹⁴
OperationOur settingsReferenceDifferenceLimitResult
Rainflow counting and damagecyclesload_cycles; output cycles, hysteresis 0rainflow.extract_cycles(load_cycles)noneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output cycles, hysteresis 0rainflow.extract_cycles(load_cycles)noneidenticalPASS
Rainflow counting and damageRangeload_cycles; output cycles, hysteresis 0rainflow.extract_cycles(load_cycles)noneidenticalPASS
Rainflow counting and damageMeanload_cycles; output cycles, hysteresis 0rainflow.extract_cycles(load_cycles)noneidenticalPASS
Rainflow counting and damageCountload_cycles; output cycles, hysteresis 0rainflow.extract_cycles(load_cycles)noneidenticalPASS
Rainflow counting and damageStart rowload_cycles; output cycles, hysteresis 0rainflow.extract_cycles(load_cycles)noneidenticalPASS
Rainflow counting and damageEnd rowload_cycles; output cycles, hysteresis 0rainflow.extract_cycles(load_cycles)noneidenticalPASS
Rainflow counting and damagecyclesload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damageRangeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damageMeanload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damageCountload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damageStart rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damageEnd rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damagedamageload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnone10⁻¹²PASS
Rainflow counting and damagelifeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^mnone10⁻¹²PASS
Rainflow counting and damagecyclesload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnoneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnoneidenticalPASS
Rainflow counting and damageRangeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnoneidenticalPASS
Rainflow counting and damageMeanload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnoneidenticalPASS
Rainflow counting and damageCountload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnoneidenticalPASS
Rainflow counting and damageStart rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnoneidenticalPASS
Rainflow counting and damageEnd rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnoneidenticalPASS
Rainflow counting and damagedamageload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnone10⁻¹²PASS
Rainflow counting and damagelifeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection goodman, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Goodman mean-stress correctionnone10⁻¹²PASS
Rainflow counting and damagecyclesload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnoneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnoneidenticalPASS
Rainflow counting and damageRangeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnoneidenticalPASS
Rainflow counting and damageMeanload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnoneidenticalPASS
Rainflow counting and damageCountload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnoneidenticalPASS
Rainflow counting and damageStart rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnoneidenticalPASS
Rainflow counting and damageEnd rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnoneidenticalPASS
Rainflow counting and damagedamageload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnone10⁻¹²PASS
Rainflow counting and damagelifeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection gerber, ultimate 2000.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Gerber mean-stress correctionnone10⁻¹²PASS
Rainflow counting and damagecyclesload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnoneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnoneidenticalPASS
Rainflow counting and damageRangeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnoneidenticalPASS
Rainflow counting and damageMeanload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnoneidenticalPASS
Rainflow counting and damageCountload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnoneidenticalPASS
Rainflow counting and damageStart rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnoneidenticalPASS
Rainflow counting and damageEnd rowload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnoneidenticalPASS
Rainflow counting and damagedamageload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnone10⁻¹²PASS
Rainflow counting and damagelifeload_cycles; output cycles, hysteresis 0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection soderberg, yieldStrength 1500.0rainflow.extract_cycles(load_cycles); Miner sum n / (C·S^-m), C = nRef·sRef^m, Soderberg mean-stress correctionnone10⁻¹²PASS
Rainflow counting and damagecyclesload_cycles; output histogram, hysteresis 0, rangeBins 32rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts)noneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output histogram, hysteresis 0, rangeBins 32rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts)noneidenticalPASS
Rainflow counting and damageRange fromload_cycles; output histogram, hysteresis 0, rangeBins 32rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts)none10⁻¹⁵PASS
Rainflow counting and damageRange toload_cycles; output histogram, hysteresis 0, rangeBins 32rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts)none10⁻¹⁵PASS
Rainflow counting and damageCyclesload_cycles; output histogram, hysteresis 0, rangeBins 32rainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=32, range=(0, max range), weights=counts)noneidenticalPASS
Rainflow counting and damagecyclesload_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damageRange fromload_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^mnone10⁻¹⁵PASS
Rainflow counting and damageRange toload_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^mnone10⁻¹⁵PASS
Rainflow counting and damageCyclesload_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^mnoneidenticalPASS
Rainflow counting and damagedamageload_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^mnone10⁻¹²PASS
Rainflow counting and damagelifeload_cycles; output histogram, hysteresis 0, rangeBins 10, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.extract_cycles(load_cycles); numpy.histogram(ranges, bins=10, range=(0, max range), weights=counts); Miner sum n / (C·S^-m), C = nRef·sRef^mnone10⁻¹²PASS
Rainflow counting and damagecyclesload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnoneidenticalPASS
Rainflow counting and damagereversalsload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnoneidenticalPASS
Rainflow counting and damageRangeload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnoneidenticalPASS
Rainflow counting and damageMeanload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnoneidenticalPASS
Rainflow counting and damageCountload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnoneidenticalPASS
Rainflow counting and damageStart rowload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnoneidenticalPASS
Rainflow counting and damageEnd rowload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnoneidenticalPASS
Rainflow counting and damagedamageload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnone10⁻¹²PASS
Rainflow counting and damagelifeload_cycles; output cycles, hysteresis 25.0, m 5.0, sRef 100.0, nRef 2000000.0, meanCorrection nonerainflow.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^mnone10⁻¹²PASS
Shock response spectrumxsignal_ascipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)none10⁻¹⁵PASS
Shock response spectrumMaximaxsignal_ascipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)3.5 × 10⁻¹⁵10⁻¹²PASS
Shock response spectrumPositivesignal_ascipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)3.5 × 10⁻¹⁵10⁻¹²PASS
Shock response spectrumNegativesignal_ascipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)5.5 × 10⁻¹⁵10⁻¹²PASS
Shock response spectrumxsignal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)none10⁻¹⁵PASS
Shock response spectrumMaximaxsignal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)2.9 × 10⁻¹⁵10⁻¹²PASS
Shock response spectrumPositivesignal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)2.9 × 10⁻¹⁵10⁻¹²PASS
Shock response spectrumNegativesignal_a; q 25, fmin 5, fmax 100, pointsPerOctave 6scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)1.1 × 10⁻¹⁴10⁻¹²PASS
Shock response spectrumxsignal_a_gaps; q 5, fmin 20, pointsPerOctave 24scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)none10⁻¹⁵PASS
Shock response spectrumMaximaxsignal_a_gaps; q 5, fmin 20, pointsPerOctave 24scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)8.1 × 10⁻¹⁵10⁻¹²PASS
Shock response spectrumPositivesignal_a_gaps; q 5, fmin 20, pointsPerOctave 24scipy.signal.lfilter with Smallwood's coefficients for each natural frequency (plus one period of free response)8.1 × 10⁻¹⁵10⁻¹²PASS
Shock response spectrumNegativesignal_a_gaps; q 5, fmin 20, pointsPerOctave 24scipy.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. pow and ^ follow JavaScript: a NaN exponent gives NaN even for a base of 1, and (±1) ^ (±∞) is NaN (C and numpy give 1); x ^ 0.5 is computed as sqrt(x), so (−∞) ^ 0.5 is NaN where numpy.power gives +∞. The sample has no such values; formula.json covers 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 the rainflow package's own binning. The bins are numpy.histogram(ranges, bins, range=(0, largest range), weights=counts); the package's count_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; with numpy.round the prices ending in a half cent would differ.
  • Standard deviation. The standard deviation is the sample one, divided by n − 1, like MATLAB's std and Excel's STDEV. NumPy's nanstd divides by n unless asked otherwise, so the reference is numpy.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 > 0 is false. and / or follow three-valued logic: false and missing is false, true or missing is 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.detrend fits 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.8786

Open 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, welch and coherence.

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.

Coming soon to MegaRows: CSV to Excel and PDF reports · Compare CSV versions.