`compute_average_dev_head_t` averages head rotation with squared time weights (translation uses linear weights)

Đang mở Phù hợp với người mới
#14,478 2 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
66/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
numpy, python
Lĩnh vực
data

Hướng nghiên cứu

Lỗi nằm ở _average_quats trong mne/transforms.py, được gọi bởi compute_average_dev_head_t trong mne/preprocessing. Bắt đầu từ các dòng nhân quaternion với trọng số trước einsum tạo A, rồi kiểm tra chỗ các trọng số bị bình phương. Chạy script tái hiện từ issue: góc quay phải xấp xỉ 0,1501 rad, không phải 0,1801. Hoàn thành khi góc quay khớp với trung bình có trọng số và các test transform hiện có vẫn chạy đạt.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

BUG
Description of the problem

_average_quats (used by mne.preprocessing.compute_average_dev_head_t) is documented in a comment as the weighted quaternion average of Markley et al., which maximizes q^T A q with A = sum_i w_i q_i q_i^T. The implementation multiplies each quaternion by its weight and then forms the outer products, so it actually builds A = sum_i w_i^2 q_i q_i^T. The rotation is therefore averaged with squared weights, while the translation in the same function is averaged with the plain time weights, so the two parts of the returned transform are inconsistent.

Steps to reproduce
import numpy as np, mne
from mne.transforms import rot_to_quat

def rz(t):
    return np.array([[np.cos(t), -np.sin(t), 0], [np.sin(t), np.cos(t), 0], [0, 0, 1]])

sfreq = 100.0
raw = mne.io.RawArray(np.zeros((1, 1000)), mne.create_info(1, sfreq, "eeg"))
q = rot_to_quat(np.array([rz(0.0), rz(0.2)]))
# columns: time, q1, q2, q3, x, y, z, g, error, velocity
pos = np.array([[0.0, *q[0], 0.00, 0, 0, 1, 0, 0],
                [2.5, *q[1], 0.01, 0, 0, 1, 0, 0]])
trans = mne.preprocessing.compute_average_dev_head_t(raw, pos)["trans"]
print(np.arctan2(trans[1, 0], trans[0, 0]))  # 0.1801
print(trans[0, 3])                           # 0.0075
Link to data

No response

Expected results

The translation is the time-weighted mean (0.75 * 0.01 = 0.0075). The rotation should be the matching weighted quaternion mean: with A = sum_i w_i q_i q_i^T the dominant eigenvector corresponds to a rotation angle of 0.1501 rad (close to the weighted mean angle 0.75 * 0.2 = 0.15).

Actual results

The rotation angle is 0.1801 rad, which matches what squared weights give (0.5625 / (0.0625 + 0.5625) * 0.2 = 0.18). The head-position average is biased towards the longest segment.

Additional information

I suspect the problem is in mne/transforms.py, _average_quats:

quats = np.concatenate((_quat_real(quats)[..., np.newaxis], quats), -1)
quats *= weights[:, np.newaxis]
A = np.einsum("ij,ik->jk", quats, quats)  # sum of outer product of each q
Ngôn ngữ chính
Python
Star
3.6k
Fork
1.6k
Merge trung bình
1 ngày 20 giờ
Pull request đã merge (30 ngày)
73

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của mne-tools/mne-python

Tất cả issue của mne-tools/mne-python

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.