|
2 | 2 | # vi: set ft=python sts=4 ts=4 sw=4 et:
|
3 | 3 | """ Utility routines for working with points and affine transforms
|
4 | 4 | """
|
5 |
| - |
6 |
| -from math import acos, pi as PI |
7 | 5 | import numpy as np
|
8 | 6 |
|
9 | 7 | from functools import reduce
|
@@ -299,17 +297,37 @@ def voxel_sizes(affine):
|
299 | 297 | return np.sqrt(np.sum(top_left ** 2, axis=0))
|
300 | 298 |
|
301 | 299 |
|
302 |
| -def obliquity(affine, degrees=False): |
| 300 | +def obliquity(affine, all_angles=True): |
303 | 301 | r"""
|
304 |
| - Estimate the obliquity an affine's axes represent, in degrees from plumb. |
| 302 | + Estimate the *obliquity* an affine's axes represent. |
305 | 303 |
|
| 304 | + The term *obliquity* is defined here as the rotation of those axes with |
| 305 | + respect to the cardinal axes. |
306 | 306 | This implementation is inspired by `AFNI's implementation
|
307 | 307 | <https://github.com/afni/afni/blob/b6a9f7a21c1f3231ff09efbd861f8975ad48e525/src/thd_coords.c#L660-L698>`_
|
308 | 308 |
|
| 309 | + Parameters |
| 310 | + ---------- |
| 311 | + affine : 2D array-like |
| 312 | + Affine transformation array. Usually shape (4, 4), but can be any 2D |
| 313 | + array. |
| 314 | + all_angles : bool |
| 315 | + Whether the obliquity of the three axes should be returned, return the |
| 316 | + *obliquity* of the most deviated axis otherwise. |
| 317 | +
|
| 318 | + Returns |
| 319 | + ------- |
| 320 | + angles : 1D array-like or float |
| 321 | + The *obliquity* of each axis with respect to the cardinal axes, in radians. |
| 322 | + If ``all_angles`` is ``False``, return only that value for the most |
| 323 | + *oblique* axis. |
| 324 | +
|
309 | 325 | """
|
310 | 326 | vs = voxel_sizes(affine)
|
311 |
| - fig_merit = (affine[:-1, :-1] / vs[np.newaxis, ...]).max(axis=1).min() |
312 |
| - radians = abs(acos(fig_merit)) |
313 |
| - if not degrees: |
314 |
| - return radians |
315 |
| - return radians * 180 / PI |
| 327 | + best_cosines = np.abs((affine[:-1, :-1] / vs).max(axis=1)) |
| 328 | + angles = np.arccos(best_cosines) |
| 329 | + |
| 330 | + if all_angles: |
| 331 | + return angles |
| 332 | + |
| 333 | + return angles.max() |
0 commit comments