Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/mouse_tracking/matching/vectorized_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def __init__(self, detections: list[Detection]):

def _extract_poses(self, detections: list[Detection]) -> np.ndarray:
"""Extract pose data into a vectorized array."""
if len(detections) == 0:
# Return properly shaped empty array
return np.zeros((0, 12, 2), dtype=np.float64)

poses = []
for det in detections:
if det.pose is not None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,9 @@ def test_init_empty_detections(self):

assert features.n_detections == 0
assert features.detections == []
assert features.poses.shape == (0,) # Empty array has shape (0,)
assert features.poses.shape == (0, 12, 2) # Properly shaped empty array
assert features.embeddings.shape == (0, 0) # Empty embeddings
assert (
features.valid_pose_masks.shape == ()
) # Empty array results in scalar shape
assert features.valid_pose_masks.shape == (0, 12) # Properly shaped empty mask
assert features.valid_embed_masks.shape == (0,)

def test_init_mixed_valid_invalid(self, detection_factory):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,25 @@ def test_pose_distances_different_sizes(self, features_factory):
assert distances.shape == (3, 2)
assert not np.any(np.isnan(distances)) # All should be valid

def test_pose_distances_empty_features(self):
@pytest.mark.parametrize("n_features1, n_features2", [(0, 0), (0, 1), (1, 0)])
def test_pose_distances_empty_features(
self, n_features1, n_features2, features_factory
):
"""Test pose distance computation with empty features."""
features1 = VectorizedDetectionFeatures([])
features2 = VectorizedDetectionFeatures([])
example_pose_config = [{"has_pose": True, "center": (0, 0)}]
features1 = features_factory(
n_detections=n_features1, pose_configs=example_pose_config
)
features2 = features_factory(
n_detections=n_features2, pose_configs=example_pose_config
)

# This will likely crash due to empty array indexing - mark as expected behavior
# TODO: This reveals a bug in the function with empty features
with pytest.raises(IndexError):
compute_vectorized_pose_distances(features1, features2)
# Should handle empty features gracefully
distances = compute_vectorized_pose_distances(features1, features2)
Comment thread
bergsalex marked this conversation as resolved.

# Should return empty distance matrix with correct shape
assert distances.shape == (n_features1, n_features2)
assert distances.dtype == np.float64

def test_pose_distances_single_detection(self, features_factory):
"""Test pose distance computation with single detection."""
Expand Down
4 changes: 2 additions & 2 deletions tests/matching/vectorized_features/test_get_rotated_poses.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ def test_get_rotated_poses_empty_detections(self):
# Should not call rotate_pose
assert mock_rotate.call_count == 0

# Should return empty array matching poses shape
assert rotated_poses.shape == (0,)
# Should return properly shaped empty array
assert rotated_poses.shape == (0, 12, 2)
assert np.array_equal(rotated_poses, features.poses)

def test_get_rotated_poses_uses_detection_rotate_pose(self, detection_factory):
Expand Down