-
Notifications
You must be signed in to change notification settings - Fork 533
ENH WIP: Use geodesic distance in FramewiseDisplacement #2607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@ninamiolane - this would be a nice fix. it's a little closer to the implementation in artifactdetect i think. https://github.com/nipy/nipype/blob/master/nipype/algorithms/rapidart.py#L103 perhaps to keep compatibility with the original i will have to play with |
Thanks for the PR @ninamiolane! +1 for making this optional and keeping the default behavior (there is too much software depending on FD calculated in a particular way). |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2607 +/- ##
==========================================
- Coverage 64.85% 64.05% -0.80%
==========================================
Files 299 297 -2
Lines 39510 39446 -64
Branches 5220 5212 -8
==========================================
- Hits 25623 25267 -356
- Misses 12832 13138 +306
+ Partials 1055 1041 -14
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Hi @ninamiolane, do you want to try to get this in for the next release (1.1.1)? I suspect we could get this done in a couple days. |
Please keep me in the loop, I'll be more than happy to help fix the tests or whatever you may need from me :) |
Yes, that'd be great, thanks! Let me have another look tomorrow and I'll ping you if needed. |
@oesteban @effigies could maybe one of you tell me which parameterization is used for the frames, i.e. for each line of Each line of Thank you very much in advance. |
These have been normalized to SPM format: Lines 227 to 238 in 4b2a821
I believe they're in Euler angles, but perhaps @satra knows for certain here... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @ninamiolane. I took the liberty of reviewing this before you said it was ready. There are a few things that can be addressed before the final form of the geodesic metric is decided.
Also, could you merge the current master?
Please feel free to ask questions.
nipype/algorithms/confounds.py
Outdated
@@ -300,16 +307,37 @@ class FramewiseDisplacement(BaseInterface): | |||
'tags': ['method'] | |||
}] | |||
|
|||
def _run_interface(self, runtime): | |||
def _run_interface(self, runtime, metric='L1'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This metric
parameter should be in FramewiseDisplacementInputSpec
:
nipype/nipype/algorithms/confounds.py
Lines 229 to 258 in 1ffe23d
class FramewiseDisplacementInputSpec(BaseInterfaceInputSpec): | |
in_file = File(exists=True, mandatory=True, desc='motion parameters') | |
parameter_source = traits.Enum( | |
"FSL", | |
"AFNI", | |
"SPM", | |
"FSFAST", | |
"NIPY", | |
desc="Source of movement parameters", | |
mandatory=True) | |
radius = traits.Float( | |
50, | |
usedefault=True, | |
desc='radius in mm to calculate angular FDs, 50mm is the ' | |
'default since it is used in Power et al. 2012') | |
out_file = File( | |
'fd_power_2012.txt', usedefault=True, desc='output file name') | |
out_figure = File( | |
'fd_power_2012.pdf', usedefault=True, desc='output figure name') | |
series_tr = traits.Float(desc='repetition time in sec.') | |
save_plot = traits.Bool(False, usedefault=True, desc='write FD plot') | |
normalize = traits.Bool( | |
False, usedefault=True, desc='calculate FD in mm/s') | |
figdpi = traits.Int( | |
100, usedefault=True, desc='output dpi for the FD plot') | |
figsize = traits.Tuple( | |
traits.Float(11.7), | |
traits.Float(2.3), | |
usedefault=True, | |
desc='output figure size') |
I would suggest:
metric = traits.Enum('L1', 'SE3', usedefault=True, mandatory=True,
desc='Distance metric to apply: '
'L1 = Manhattan distance (original definition),
'SE3 = Special Euclidean group in 3D (geodesic)')
Or similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go ahead and remove the metric='L1'
parameter from _run_interface()
.
nipype/algorithms/confounds.py
Outdated
diff[:, 3:6] *= self.inputs.radius | ||
fd_res = np.abs(diff).sum(axis=1) | ||
|
||
if metric == 'L1': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then here (and below) you would use self.inputs.metric
, instead of metric
.
nipype/algorithms/confounds.py
Outdated
diff[:, 3:6] *= self.inputs.radius | ||
fd_res = np.abs(diff).sum(axis=1) | ||
|
||
elif metric == 'riemannian': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I said 'SE3'
above. If 'riemannian'
makes more sense, that's fine. I don't have strong opinions.
requirements.txt
Outdated
configparser | ||
funcsigs | ||
future>=0.16.0 | ||
geomstats>=1.7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please revert to the current master
version of this file and only add geomstats>=1.7
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to sort them in alphabetical order to improve readability. But sure, I can revert! Is there any specific reason why we don't use alphabetical order there? Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly just to make it obvious during PR review what's changed.
Hi @ninamiolane. Just a heads up that we'll try to make the next release on August 28, so it'd be great to try to get this in by August 20. Please let us know if you have any questions. |
SPM seems to be using Euler angles to representation rotations, however it is not clear to me which Euler angle convention is used. (There are -at least?- 12 Euler angles conventions.) @satra Would you know if the Euler angles used by SPM:
Thank you! Lines 227 to 238 in 4b2a821
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Just a couple mostly cosmetic changes. They can wait on hearing back from SPM.
nipype/algorithms/confounds.py
Outdated
@@ -13,6 +13,7 @@ | |||
|
|||
import nibabel as nb | |||
import numpy as np | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for the sake of keeping the diff clean, can you remove this newline?
@@ -12,6 +12,7 @@ def test_FramewiseDisplacement_inputs(): | |||
out_figure=dict(usedefault=True, ), | |||
out_file=dict(usedefault=True, ), | |||
parameter_source=dict(mandatory=True, ), | |||
metric=dict(usedefault=True, ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you re-run make specs
and re-commit test_auto_FramewiseDisplacement
?
The main remaining issue is establishing a ground truth for geodesic framewise displacement. The simplest approach would be simply to save the current output, so we'd get a regression test if something changes. Have you run this on some real data to make sure that the results you're getting are sensible? Just a cursory glance at the error:
We're going from 0.092 to 0.019 (first entry) and 0.103 to 0.045 (final entry). It definitely seems plausible to see a 2-6x compression when going from an L1 in 6 dimensions to a more geometrically meaningful norm, but you have more experience here. There's a secondary issue on Travis, which is that we cannot install geomstats on Python 3.7, as it depends on tensorflow, which currently does not have a binary distribution for 3.7. It appears this was resolved with tensorflow/tensorflow#21202, so we can expect this to fix itself with the next release. Fortunately, their release cycle looks like it's faster than monthly, so if we just keep an eye on that, we should be good to merge before 1.1.3. |
So we're looking to release next Monday, and tensorflow still hasn't had a full release support Python 3.7. Additionally, it's probably not great for nipype to start semi-requiring tensorflow or pytorch for such a small functionality increment. I've submitted an issue to geomstats/geomstats#136, and would be happy to submit a patch if you'd like. Any thoughts on the ground-truth file? |
Hi @ninamiolane, @oesteban. Any chance of finishing this up this week? |
@oesteban would you like to meet this week, for example thursday afternoon or friday afternoon? if not, next week? |
Just a heads up: We're looking to make the next release on Nov 26, if you want to try to get this in this month. |
Hi, just a reminder that the 1.1.8 release is targeted for January 28. Please let us know if you'd like to try to finish this up for that release. |
This is WIP fixing #2606.
Changes proposed in this PR:
geomstats
to perform computations on manifolds, like the space of frame displacements in 3D which is the Special Euclidean group in 3D or SE(3)FramewiseDisplacement
to compute the displacement of a frame as a geodesic distance on the space of frames SE(3).TODO:
mpars
@oesteban ?