Closed dangom closed 7 months ago
I don't know if this is a correct start. It's a partial translation of this matlab code, which is discussed at the ANTs main repo, into python. It's missing a final RAS to LPS conversion, so there may be some sign flips. It also adds in a dependency on transforms3d, which may potentially be undesirable.
def ants_to_human(aff, fixed):
"""Convert an ATNs affine_3x3 and a fixed center of rotation into a 4x4
affine matrix.
"""
mat = np.hstack((np.reshape(aff[:9], (3, 3)).T, aff[9:]))
m_translation = mat[:, 3]
mat = np.vstack((mat, [0, 0, 0, 1]))
m_offset = np.zeros((3,))
for i in range(3):
m_offset[i] = m_translation[i] + fixed[i]
for j in range(3):
m_offset[i] -= mat[i, j] * fixed[j]
mat[:3, 3] = m_offset
mat = np.linalg.inv(mat)
return mat
def human_to_more_human(mat):
"""Return translation and rotation parameter estimates from 4x4 affine matrix.
"""
tra, mrot, zoom, shear = transforms3d.affines.decompose44(mat)
rx = np.arctan2(mrot[1, 2], mrot[2, 2])
ry = np.arctan2(-mrot[2, 0], np.sqrt(mrot[2, 1] ** 2 + mrot[2, 2] ** 2))
rz = np.arctan2(mrot[1, 0], mrot[0, 0])
rot = np.array((rx, ry, rz))
return np.hstack((tra, rot))
But a throw-away example shows that the estimated FD does not match what is currently implemented (but magnitudes are in the same ballpark).
from scipy.io import loadmat
affines = [loadmat(x[0])['AffineTransform_float_3_3'] for x in data_mcf['motion_parameters']]
fix = [loadmat(x[0])['fixed'].squeeze() for x in data_mcf['motion_parameters']]
mpars = np.vstack([human_to_more_human(ants_to_human(a, f)) for (a, f) in zip(affines, fix)])
fd_est = np.sum(np.abs(np.diff(mpars, axis=0)), axis=1)
plt.scatter(data_mcf['FD'], np.insert(fd_est, 0, 0, axis=0))
We have both a transform to point Operation and transform classes to do all of this in a (c)lean way and consistently with other ants tools ... under some of this: https://github.com/stnava/structuralFunctionalJointRegistration/blob/master/src/Default%20Mode%20Connectivity%20in%20ANTsPy.ipynb
That's awesome. Thanks for pointing out. It still only uses the FD though, not the X, Y, Z and rot_X, rot_Y, rot_Z, which I think are the most commonly used regressors in the fMRI literature (not judging whether that's a good thing or not).
this is how we report those in ANTsR:
obviously, fairly easy to port to python w/o dependencies
Thanks.
def _ants_affine_to_distance(affine):
dx, dy, dz = affine[9:]
rot_x = np.arcsin(affine[6])
cos_rot_x = np.cos(rot_x)
rot_y = np.arctan2(affine[7] / cos_rot_x, affine[8] / cos_rot_x)
rot_z = np.arctan2(affine[3] / cos_rot_x, affine[0] / cos_rot_x)
deg = np.degrees
return dx, dy, dz, deg(rot_x), deg(rot_y), deg(rot_z)
I think the 6 parameter estimates would be a great addition to the dictionary returned by ants.motion_correction
. I can open a PR if you think this would make sense.
And just for clarification, FD is computed based on rotations in radians, correct?
one note: this is only valid for a rigid map. the generic FD just uses point transformations. the
fdOffset: offset value to use in framewise displacement calculation
gives the amount one offsets from the center of mass of the image in order to compute the FD.
note edit of previous comment.
Thanks. As you mentioned, computing the FD directly from the motion estimates (from the function above _ants_affine_to_distance
) is in good agreement with the FD as currently implemented in ANTs for rigid transforms.
If you think adding these estimates to the output of motion_correction
would make sense (for Rigid and Affine), I could try a PR. The only issue here for ANTsPy is that reading the mat files from registration
requires pulling in scipy
as an extra dependency (at least for my knowledge - I haven't considered other ways of reading mat files from python yet without scipy.io).
Otherwise, feel free to close this issue
OK, I would definitely appreciate a pull request ... antsrtransform class And its associated functions will get you all the things you need without scipy ... We certainly appreciate the feedback and help, thank you.
On Tue, Jul 16, 2019 at 4:14 PM Daniel Gomez notifications@github.com wrote:
Thanks. As you mentioned, computing the FD directly from the motion estimates (from the function above _ants_affine_to_distance) is in good agreement with the FD as currently implemented in ANTs for rigid transforms. If you think adding these estimates to the output of motion_correction would make sense (for Rigid and Affine), I could try a PR. The only issue here for ANTsPy is that reading the mat files from registration requires pulling in scipy as an extra dependency (at least for my knowledge - I haven't considered other ways of reading mat files from python yet without scipy.io).
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/ANTsX/ANTsPy/issues/71?email_source=notifications&email_token=AACPE7W5NLUJOKZENH3ERBTP7YTZZA5CNFSM4H7HZ2W2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2CAGQI#issuecomment-511968065, or mute the thread https://github.com/notifications/unsubscribe-auth/AACPE7VXPPGZEMR7QEGWCNLP7YTZZANCNFSM4H7HZ2WQ .
--
brian
ants.read_transform
and ants.write_transform
,,, they also have get parameters and related ops.
谢谢。如您所提到的,直接从运动估计(根据上述函数
_ants_affine_to_distance
)计算出FD 与目前在ANT中为刚性变换实现的FD完全一致。 如果您认为将这些估算值添加到的输出中motion_correction
是有意义的(对于Rigid和Affine),我可以尝试PR。对于ANTsPy来说,唯一的问题是要从中读取Mat文件registration
需要scipy
额外的依赖(至少据我所知-我还没有考虑过从python读取scipy.io的其他方法)。 否则,请随时关闭此问题谢谢。如您所提到的,直接从运动估计(根据上述函数
_ants_affine_to_distance
)计算出FD 与目前在ANT中为刚性变换实现的FD完全一致。 如果您认为将这些估算值添加到的输出中motion_correction
是有意义的(对于Rigid和Affine),我可以尝试PR。ANTsPy唯一的问题是从中读取Mat文件registration
需要scipy
额外的依赖(至少据我所知-我还没有考虑过从python读取scipy.io的其他方法)。 否则,请随时关闭此问题
Hello, I got this temporary mat file after using ants' affine registration. I opened it with scipy.io, as follows. Then I got a matrix according to your ants_to_human, but it seems that I cannot convert the move image to fixed according to this matrix. I want to know: how do I get the rotation matrix of 4x4 according to this mat file? Can the two nii.gz before and after registration be converted by a 4x4 matrix in affine mode? I am a novice in this field and I look forward to your reply
@wangyibin0011 please open a different issue for this question
Is your feature request related to a problem? Please describe. Currently,
ants.motion_correction
outputsmotion_parameters
as a list of MAT files that are saved to a temporary folder. This makes it so that if the user wants to save these transformations (to my understanding), he has to move these outputs somewhere else, manually, and write a mapping.txt file that specifies which file belongs to each volume, given that names are random. It's also cumbersome to extract common motion parameter regressors from these MAT files from within python. My knowledge is that this requires calling in scipy or hdf5 to load the MAT files, extracting the affine from the dict, parsing it and storing the translation and rotation parameters manually. This also means that the end user has to know what the ANTs internal representation of an affine transformation looks like, which is well documented, but outside of ANTsPy.Describe the solution you'd like
have the user be able to specify where to save the transformation matrices, and have their filenames sorted by index. This would ease storing files and allow easy identification of which affine belongs to which volume. If the folder already contains files with the same name, either throw an error before starting the motion correction, have a parameter to toggle overwrite (could default to True I guess), or add a suffix (the FSL solution).
output an extra
motion_parameter_estimates
np.array or dictionary containing translation and rotation estimates for better interop with other software packages.Describe alternatives you've considered Open to suggestions.