73 lines
2.2 KiB
Python
73 lines
2.2 KiB
Python
import numpy as np
|
|
from backend.data_types import LineData, RecordTable
|
|
|
|
|
|
def test_acf_1d():
|
|
from backend.nodes.acf_1d import ACF1D
|
|
|
|
node = ACF1D()
|
|
|
|
# Periodic signal — ACF should show a peak at the period
|
|
n = 256
|
|
period = 32
|
|
t = np.arange(n, dtype=np.float64)
|
|
signal = np.sin(2 * np.pi * t / period)
|
|
profile = LineData(
|
|
data=signal,
|
|
x_axis=t * 1e-9,
|
|
x_unit="m",
|
|
y_unit="V",
|
|
)
|
|
|
|
acf, measurement = node.process(profile, level="mean")
|
|
|
|
assert isinstance(acf, LineData)
|
|
assert isinstance(measurement, RecordTable)
|
|
|
|
# ACF should be symmetric about zero lag
|
|
center = len(acf) // 2
|
|
assert np.allclose(acf.data, acf.data[::-1], atol=1e-10)
|
|
|
|
# Peak period should be close to the input period in metres
|
|
expected_period_m = period * 1e-9
|
|
assert len(measurement) == 1
|
|
assert measurement[0]["quantity"] == "Peak period"
|
|
assert abs(measurement[0]["value"] - expected_period_m) / expected_period_m < 0.1
|
|
assert measurement[0]["unit"] == "m"
|
|
|
|
# x_axis should be centred on zero
|
|
assert acf.x_axis is not None
|
|
assert acf.x_axis[center] == 0.0 or abs(acf.x_axis[center]) < 1e-15
|
|
|
|
# ACF at zero lag should equal variance (signal is mean-subtracted)
|
|
assert acf.data[center] > 0
|
|
|
|
|
|
def test_acf_1d_no_peak():
|
|
from backend.nodes.acf_1d import ACF1D
|
|
|
|
node = ACF1D()
|
|
|
|
# White noise — ACF should have no reliable peak, measurement table may be empty
|
|
rng = np.random.default_rng(0)
|
|
noise = rng.standard_normal(64)
|
|
profile = LineData(data=noise, x_axis=np.arange(64, dtype=np.float64), x_unit="m")
|
|
|
|
acf, measurement = node.process(profile, level="none")
|
|
assert isinstance(acf, LineData)
|
|
# measurement is either empty or has one row — no assertion on content
|
|
|
|
|
|
def test_acf_1d_level_none():
|
|
from backend.nodes.acf_1d import ACF1D
|
|
|
|
node = ACF1D()
|
|
|
|
# With level="none", a DC offset should not be removed
|
|
data = np.ones(32, dtype=np.float64) * 5.0
|
|
profile = LineData(data=data, x_axis=np.arange(32, dtype=np.float64))
|
|
|
|
acf, _ = node.process(profile, level="none")
|
|
# ACF of a constant is a constant
|
|
assert acf.data[len(acf) // 2] > 0
|