Skip to content

Commit 25ff13e

Browse files
authored
Loosen tolerance for our rotation calc in viz (#14033)
1 parent d828df4 commit 25ff13e

3 files changed

Lines changed: 23 additions & 5 deletions

File tree

mne/transforms.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,12 +1296,12 @@ def quat_to_rot(quat):
12961296

12971297

12981298
@jit()
1299-
def _one_rot_to_quat(rot):
1299+
def _one_rot_to_quat(rot, *, tol=1e-3):
13001300
"""Convert a rotation matrix to quaternions."""
13011301
# see e.g. http://www.euclideanspace.com/maths/geometry/rotations/
13021302
# conversions/matrixToQuaternion/
13031303
det = np.linalg.det(np.reshape(rot, (3, 3)))
1304-
if np.abs(det - 1.0) > 1e-3:
1304+
if np.abs(det - 1.0) > tol:
13051305
raise ValueError("Matrix is not a pure rotation, got determinant != 1")
13061306
t = 1.0 + rot[0] + rot[4] + rot[8]
13071307
if t > np.finfo(rot.dtype).eps:
@@ -1331,13 +1331,16 @@ def _one_rot_to_quat(rot):
13311331
return np.array((qx, qy, qz))
13321332

13331333

1334-
def rot_to_quat(rot):
1334+
def rot_to_quat(rot, *, tol=1e-3):
13351335
"""Convert a set of rotations to quaternions.
13361336
13371337
Parameters
13381338
----------
13391339
rot : array, shape (..., 3, 3)
13401340
The rotation matrices to convert.
1341+
tol : float
1342+
Tolerance for the determinant checking that the rotation matrices are valid.
1343+
The default (1e-3) should be suitable for most cases.
13411344
13421345
Returns
13431346
-------
@@ -1350,7 +1353,7 @@ def rot_to_quat(rot):
13501353
quat_to_rot
13511354
"""
13521355
rot = rot.reshape(rot.shape[:-2] + (9,))
1353-
return np.apply_along_axis(_one_rot_to_quat, -1, rot)
1356+
return np.apply_along_axis(_one_rot_to_quat, -1, rot, tol=tol)
13541357

13551358

13561359
def _quat_to_affine(quat):

mne/viz/_3d.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,9 @@ def _ch_pos_in_coord_frame(info, to_cf_t, warn_meg=True, verbose=None):
11491149
frame_trans = to_cf_t[_frame_to_str[ch_coord_frame]]["trans"]
11501150
transform = frame_trans @ coil_trans
11511151
position = transform[:3, 3]
1152-
quat = rot_to_quat(transform[:3, :3])
1152+
# Some MEG systems have rotation matrices that are not exactly
1153+
# orthonormal, so be a bit more tolerant than usual here
1154+
quat = rot_to_quat(transform[:3, :3], tol=2e-3)
11531155
shape_key = (local_rr.round(10).tobytes(), triangles.tobytes())
11541156
chs[type_name][info.ch_names[idx]] = (
11551157
local_rr,

mne/viz/tests/test_3d.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,19 @@ def test_plot_alignment_meg(renderer, system):
457457
pytest.importorskip("nibabel")
458458
if system == "Neuromag":
459459
this_info = read_info(evoked_fname)
460+
# Test regression for somato dataset, which has less than ideal rot encoded
461+
idx = this_info["ch_names"].index("MEG 0322")
462+
this_info["chs"][idx]["loc"][3:] = [
463+
-0.351594,
464+
0.118898,
465+
-0.92858398,
466+
-0.370994,
467+
-0.92838401,
468+
0.0216,
469+
-0.85886598,
470+
0.37848499,
471+
0.34239799,
472+
]
460473
elif system == "CTF":
461474
this_info = read_raw_ctf(ctf_fname).info
462475
elif system == "BTi":

0 commit comments

Comments
 (0)