initial commit
This commit is contained in:
0
tests/test_channel/__init__.py
Normal file
0
tests/test_channel/__init__.py
Normal file
BIN
tests/test_channel/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
tests/test_channel/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
tests/test_channel/__pycache__/__init__.cpython-314.pyc
Normal file
BIN
tests/test_channel/__pycache__/__init__.cpython-314.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
98
tests/test_channel/test_code.py
Normal file
98
tests/test_channel/test_code.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""Tests for ISO channel code parsing."""
|
||||
|
||||
import pytest
|
||||
|
||||
from impakt.channel.code import ChannelCode, parse_channel_code
|
||||
|
||||
|
||||
class TestChannelCodeParsing:
|
||||
"""Test the 16-character ISO channel code parser."""
|
||||
|
||||
def test_parse_full_code(self):
|
||||
code = ChannelCode.parse("11HEAD0000ACXA")
|
||||
assert code.is_valid
|
||||
assert code.test_object == "11"
|
||||
assert code.main_location == "HEAD"
|
||||
assert code.fine_location == "0000"
|
||||
assert code.measurement == "AC"
|
||||
assert code.direction == "X"
|
||||
assert code.sense == "A"
|
||||
|
||||
def test_parse_with_filter_class(self):
|
||||
code = ChannelCode.parse("11HEAD0000ACXA60")
|
||||
assert code.is_valid
|
||||
assert code.filter_class == "60"
|
||||
|
||||
def test_parse_neck_channel(self):
|
||||
code = ChannelCode.parse("11NECKUP00FOZA")
|
||||
assert code.test_object == "11"
|
||||
assert code.main_location == "NECK"
|
||||
assert code.fine_location == "UP00"
|
||||
assert code.measurement == "FO"
|
||||
assert code.direction == "Z"
|
||||
|
||||
def test_parse_femur_channel(self):
|
||||
code = ChannelCode.parse("11FEMRLE00FOZA")
|
||||
assert code.main_location == "FEMR"
|
||||
assert code.fine_location == "LE00"
|
||||
assert code.measurement == "FO"
|
||||
|
||||
def test_invalid_short_code(self):
|
||||
code = ChannelCode.parse("SHORT")
|
||||
assert not code.is_valid
|
||||
|
||||
def test_group_key(self):
|
||||
cx = ChannelCode.parse("11HEAD0000ACXA")
|
||||
cy = ChannelCode.parse("11HEAD0000ACYA")
|
||||
cz = ChannelCode.parse("11HEAD0000ACZA")
|
||||
assert cx.group_key() == cy.group_key() == cz.group_key()
|
||||
|
||||
def test_group_key_differs_for_different_locations(self):
|
||||
head = ChannelCode.parse("11HEAD0000ACXA")
|
||||
chest = ChannelCode.parse("11CHST0000ACXA")
|
||||
assert head.group_key() != chest.group_key()
|
||||
|
||||
def test_is_component(self):
|
||||
assert ChannelCode.parse("11HEAD0000ACXA").is_component()
|
||||
assert ChannelCode.parse("11HEAD0000ACYA").is_component()
|
||||
assert ChannelCode.parse("11HEAD0000ACZA").is_component()
|
||||
assert not ChannelCode.parse("11HEAD0000ACRA").is_resultant() is False
|
||||
|
||||
def test_is_resultant(self):
|
||||
assert ChannelCode.parse("11HEAD0000ACRA").is_resultant()
|
||||
|
||||
def test_description(self):
|
||||
code = ChannelCode.parse("11HEAD0000ACXA")
|
||||
desc = code.description
|
||||
assert "Head" in desc
|
||||
assert "Acceleration" in desc
|
||||
assert "X" in desc
|
||||
|
||||
def test_short_label(self):
|
||||
code = ChannelCode.parse("11HEAD0000ACXA")
|
||||
label = code.short_label
|
||||
assert "Head" in label
|
||||
assert "Accel" in label
|
||||
assert "X" in label
|
||||
|
||||
def test_measurement_unit(self):
|
||||
code = ChannelCode.parse("11HEAD0000ACXA")
|
||||
assert code.measurement_unit == "m/s²"
|
||||
|
||||
def test_matches_wildcard(self):
|
||||
code = ChannelCode.parse("11HEAD0000ACXA")
|
||||
assert code.matches("11HEAD0000AC*")
|
||||
assert code.matches("11HEAD*")
|
||||
assert code.matches("*ACXA")
|
||||
assert not code.matches("12HEAD*")
|
||||
|
||||
def test_matches_set_notation(self):
|
||||
code = ChannelCode.parse("11HEAD0000ACXA")
|
||||
assert code.matches("11HEAD0000AC{X,Y,Z}A")
|
||||
code_y = ChannelCode.parse("11HEAD0000ACYA")
|
||||
assert code_y.matches("11HEAD0000AC{X,Y,Z}A")
|
||||
|
||||
def test_convenience_function(self):
|
||||
code = parse_channel_code("11HEAD0000ACXA")
|
||||
assert code.is_valid
|
||||
assert code.test_object == "11"
|
||||
109
tests/test_channel/test_model.py
Normal file
109
tests/test_channel/test_model.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""Tests for channel and test data models."""
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from impakt.channel.model import Channel, ChannelGroup, TestData
|
||||
|
||||
|
||||
class TestChannel:
|
||||
def test_channel_properties(self, head_accel_x):
|
||||
ch = head_accel_x
|
||||
assert ch.name == "11HEAD0000ACXA"
|
||||
assert ch.unit == "g"
|
||||
assert ch.sample_rate == 20000.0
|
||||
assert ch.n_samples == len(ch.data)
|
||||
assert ch.duration > 0
|
||||
|
||||
def test_channel_peak(self, head_accel_x):
|
||||
ch = head_accel_x
|
||||
assert ch.peak > 35.0 # ~40g peak
|
||||
assert 0.0 <= ch.peak_time <= 0.1
|
||||
|
||||
def test_value_at_interpolation(self, head_accel_x):
|
||||
ch = head_accel_x
|
||||
# At t=0 (pre-trigger boundary), value should be near zero
|
||||
v = ch.value_at(-0.005)
|
||||
assert abs(v) < 2.0 # Small noise
|
||||
|
||||
# At peak (~0.05s), should be near 40g
|
||||
v_peak = ch.value_at(0.05)
|
||||
assert v_peak > 30.0
|
||||
|
||||
def test_with_data_creates_new_channel(self, head_accel_x):
|
||||
ch = head_accel_x
|
||||
new_data = ch.data * 2.0
|
||||
ch2 = ch.with_data(data=new_data, transform_note="doubled")
|
||||
assert ch2 is not ch
|
||||
assert np.allclose(ch2.data, new_data)
|
||||
assert ch2.name == ch.name
|
||||
assert len(ch2.transform_history) == 1
|
||||
assert "doubled" in ch2.transform_history[0]
|
||||
|
||||
def test_data_time_length_mismatch_raises(self):
|
||||
with pytest.raises(ValueError, match="data length"):
|
||||
Channel(
|
||||
name="test",
|
||||
code=__import__("impakt.channel.code", fromlist=["ChannelCode"]).ChannelCode.parse(
|
||||
"test"
|
||||
),
|
||||
data=np.zeros(100),
|
||||
time=np.zeros(50),
|
||||
)
|
||||
|
||||
|
||||
class TestChannelGroup:
|
||||
def test_group_components(self, head_group):
|
||||
comps = head_group.components()
|
||||
assert len(comps) == 3
|
||||
|
||||
def test_group_resultant(self, head_group):
|
||||
resultant = head_group.resultant()
|
||||
assert resultant.code.direction == "R"
|
||||
assert resultant.n_samples == head_group.x.n_samples
|
||||
# Resultant should be >= any single component
|
||||
assert resultant.peak >= head_group.x.peak
|
||||
|
||||
def test_group_description(self, head_group):
|
||||
desc = head_group.description
|
||||
assert "Head" in desc
|
||||
|
||||
|
||||
class TestTestDataContainer:
|
||||
def test_get_channel(self, sample_test_data):
|
||||
ch = sample_test_data.get("11HEAD0000ACXA")
|
||||
assert ch.name == "11HEAD0000ACXA"
|
||||
|
||||
def test_get_channel_case_insensitive(self, sample_test_data):
|
||||
ch = sample_test_data.get("11head0000acxa")
|
||||
assert ch.name == "11HEAD0000ACXA"
|
||||
|
||||
def test_find_channels(self, sample_test_data):
|
||||
channels = sample_test_data.find("11HEAD0000AC*")
|
||||
assert len(channels) == 3 # X, Y, Z
|
||||
|
||||
def test_groups(self, sample_test_data):
|
||||
groups = sample_test_data.groups()
|
||||
assert len(groups) > 0
|
||||
# Head acceleration group should exist
|
||||
head_keys = [k for k in groups if "HEAD" in k and "AC" in k]
|
||||
assert len(head_keys) == 1
|
||||
|
||||
def test_group_lookup(self, sample_test_data):
|
||||
group = sample_test_data.group("HEAD0000AC")
|
||||
assert group.x is not None
|
||||
assert group.y is not None
|
||||
assert group.z is not None
|
||||
|
||||
def test_channel_tree(self, sample_test_data):
|
||||
tree = sample_test_data.channel_tree()
|
||||
assert len(tree) > 0
|
||||
# Should have a "Driver" entry
|
||||
assert any("Driver" in key for key in tree)
|
||||
|
||||
def test_len(self, sample_test_data):
|
||||
assert len(sample_test_data) == 7
|
||||
|
||||
def test_contains(self, sample_test_data):
|
||||
assert "11HEAD0000ACXA" in sample_test_data
|
||||
assert "NONEXISTENT" not in sample_test_data
|
||||
Reference in New Issue
Block a user