-
Notifications
You must be signed in to change notification settings - Fork 530
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
[FIX] FSL model.py make multiple F-tests #3166
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3166 +/- ##
=========================================
+ Coverage 67.31% 67.6% +0.29%
=========================================
Files 299 299
Lines 39493 39493
Branches 5219 5219
=========================================
+ Hits 26585 26701 +116
+ Misses 12198 12083 -115
+ Partials 710 709 -1
Continue to review full report at Codecov.
|
This looks right to me from the perspective of fixing the Python error, but I have no experience with writing FTS files. Can you confirm it does what you want? This would also be a good thing to write a regression test for. This would be something like: # In nipype/interfaces/fsl/tests/test_models.py
# Make sure the following are imported:
from ...pipeline import engine as pe
from ..model MultipleRegressDesign
# Define a test. Here I suggest using the `tmp_path` feature which just provides
# a `Path()` pointing to an empty directory that will be deleted afterwards.
def test_MultipleRegressDesign_multi_ftest(tmp_path):
nd = pe.Node(MultipleRegressDesign(), name='nd', basedir=str(tmp_path))
# Add some inputs that would trigger the error, as small as possible...
nd.inputs.contrasts = ...
...
# Run the interface; this should fail before your fix and pass after
res = nd.run()
# Add some checks on the outputs, for example:
assert os.path.exists(res.outputs.design_fts)
design_fts = Path(res.outputs.design_fts)
assert "<some expected text>" in design_fts.read_text()
# And any other checks that seem appropriate |
@effigies sure I'll try to do this tomorrow! |
Would this be an appropriate regression test?
Alternativly more correct regarding the F contrasts would be something like:
However the regression test fails already before doing the checks in the current nipype version. After the fix, the regression test runs and all checks pass. |
I just realized that it is much easier to extend the existing example in nipype/interfaces/fsl/tests/test_models.py, so I changed the code there. |
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.
Nice! I have a few suggestions.
|
||
|
||
@pytest.mark.skipif(no_fsl(), reason="fsl is not installed") | ||
def test_MultipleRegressDesign(tmpdir): | ||
tmpdir.chdir() |
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.
We're going to need some way of keeping the outputs in a temporary directory. We can either keep this tmpdir.chdir()
or replace foo = ...
:
# Above
from ....pipeline import engine as pe # I think I have enough dots...
# Here
designer = pe.Node(fsl.MultipleRegressDesign(), name='designer', base_dir=str(tmpdir))
This uses the isolation of Node
to do the work without having to chdir
in the test, which is my personal preference.
(I'm updating foo
to designer
just because foo
is an annoying variable name. You don't need to do that.)
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.
thanks for all the suggestions! I think I changed the code regarding all your suggestions. Is it possible to use the from ....pipeline import engine as pe when testing the code locally too? It did no work for me, instead I had to write from nipype.pipeline import engine as pe .
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.
Relative imports only work within a package. If by "testing the code locally" you mean typing it into a >>>
shell, then no, you need to use the full path.
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.
yes, thats what I ment, thanks! Makes sense to me now!
foo = fsl.MultipleRegressDesign() | ||
foo.inputs.regressors = dict( | ||
voice_stenght=[1, 1, 1], age=[0.2, 0.4, 0.5], BMI=[1, -1, 2] | ||
) | ||
con1 = ["voice_and_age", "T", ["age", "voice_stenght"], [0.5, 0.5]] | ||
con2 = ["just_BMI", "T", ["BMI"], [1]] | ||
foo.inputs.contrasts = [con1, con2, ["con3", "F", [con1, con2]]] | ||
foo.inputs.contrasts = [con1, con2, ["con3", "F", [con1, con2]], ["con4", "F", [con2]]] |
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.
Nice!
res = foo.run() | ||
|
||
for ii in ["mat", "con", "fts", "grp"]: | ||
assert ( | ||
getattr(res.outputs, "design_" + ii) == tmpdir.join("design." + ii).strpath | ||
os.path.exists(eval('res.outputs.design_'+ii)) | ||
) |
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'm not a fan of eval
. It's a big heavy hammer for pulling a variable out of the local ether. I would rather do something like:
outputs = res.outputs.get_traitsfree() # This fetches `outputs` contents as a dict.
for ftype in ["mat", "con", "fts", "grp"]:
assert Path(outputs["design_" + ftype]).exists()
Co-Authored-By: Chris Markiewicz <[email protected]>
Co-Authored-By: Chris Markiewicz <[email protected]>
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.
LGTM.
Hello everybody,
I think there is a bug in the FSL model.py. If one attempts to make one F-contrast the FSL MultipleRegressDesign works fine, however it throws an error when trying to make two F-contrasts saying it cannot append to a string. With the changes below the error should be fixed.
I hope this helps!
Anna