Coder Social home page Coder Social logo

Motion correction: improve output about antspy HOT 13 CLOSED

antsx avatar antsx commented on August 15, 2024 1
Motion correction: improve output

from antspy.

Comments (13)

stnava avatar stnava commented on August 15, 2024 1

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

from antspy.

dangom avatar dangom commented on August 15, 2024

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))

scatterfd

from antspy.

dangom avatar dangom commented on August 15, 2024

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).

from antspy.

stnava avatar stnava commented on August 15, 2024

this is how we report those in ANTsR:

https://github.com/ANTsX/ANTsR/blob/69d65b697b14af6f2edf9fbd096a84c5fbc4d944/R/antsrMotionCalculation.R#L171-L189

obviously, fairly easy to port to python w/o dependencies

from antspy.

dangom avatar dangom commented on August 15, 2024

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?

from antspy.

stnava avatar stnava commented on August 15, 2024

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.

fdptsTxI = apply_transforms_to_points( idim - 1, fdpts, myreg[ 'fwdtransforms' ] )
if k > 0 and motion_parameters[ k - 1 ] != "NA":
fdptsTxIminus1 = apply_transforms_to_points( idim - 1, fdpts, motion_parameters[ k - 1 ] )
else:
fdptsTxIminus1 = fdptsTxI
# take the absolute value, then the mean across columns, then the sum
FD[ k ] = (fdptsTxIminus1-fdptsTxI).abs().mean().sum()

from antspy.

stnava avatar stnava commented on August 15, 2024

note edit of previous comment.

from antspy.

stnava avatar stnava commented on August 15, 2024

also here:

for k in range( myoffsets.shape[0] ):
if ( abs(myoffsets[k,:]).sum() == ( idim - 2 ) ):
useinds.append( k )
myoffsets[k,:] = myoffsets[k,:] * fdOffset / 2.0 + centerOfMass
fdpts = pd.DataFrame(data=myoffsets[useinds,:],columns=mycols)

from antspy.

dangom avatar dangom commented on August 15, 2024

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

from antspy.

stnava avatar stnava commented on August 15, 2024

from antspy.

stnava avatar stnava commented on August 15, 2024

ants.read_transform and ants.write_transform ,,, they also have get parameters and related ops.

from antspy.

wangyibin0011 avatar wangyibin0011 commented on August 15, 2024

谢谢。如您所提到的,直接从运动估计(根据上述函数_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
13

from antspy.

stnava avatar stnava commented on August 15, 2024

@wangyibin0011 please open a different issue for this question

from antspy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.