-
Notifications
You must be signed in to change notification settings - Fork 532
Fix/compcor #1992
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/compcor #1992
Conversation
confounds.py and test_compcor.py are the target files - a few other style and test fixes got included. |
Codecov Report
@@ Coverage Diff @@
## master #1992 +/- ##
==========================================
+ Coverage 72.31% 72.33% +0.02%
==========================================
Files 1089 1089
Lines 55624 55623 -1
Branches 8017 8012 -5
==========================================
+ Hits 40222 40234 +12
+ Misses 14148 14138 -10
+ Partials 1254 1251 -3
Continue to review full report at Codecov.
|
@satra still running into the error mentioned in #1982, mapnode of the interface causes a crash tcompcor = MapNode(TCompCor(),
iterfield=['mask_files', 'realigned_file'],
name='tcompcor')
func1 = 'somefunc'
func2 = 'anotherfunc'
tcompcor.inputs.components_file = 'comp_file.txt'
tcompcor.inputs.realigned_file = ['somefunc', 'anotherfunc']
tcompcor.inputs.mask_files = ['mask1', 'mask2']
tcompcor.run()
Automatic pdb calling has been turned ON
170503-11:32:14,653 workflow INFO:
Executing node tcompcor in dir: /code/tcompcor/tcompcor
170503-11:32:14,659 workflow INFO:
Executing node _tcompcor0 in dir: /code/tcompcor/tcompcor/mapflow/_tcompcor0
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-46cbc0876b60> in <module>()
1 get_ipython().magic('pdb')
----> 2 eg = tcompcor.run()
/code/nipype/nipype/pipeline/engine/nodes.py in run(self, updatehash)
370 self.inputs.get_traitsfree())
371 try:
--> 372 self._run_interface()
373 except:
374 os.remove(hashfile_unfinished)
/code/nipype/nipype/pipeline/engine/nodes.py in _run_interface(self, execute, updatehash)
1285 nodenames = ['_' + self.name + str(i) for i in range(nitems)]
1286 self._collate_results(self._node_runner(self._make_nodes(cwd),
-> 1287 updatehash=updatehash))
1288 self._save_results(self._result, cwd)
1289 # remove any node directories no longer required
/code/nipype/nipype/pipeline/engine/nodes.py in _collate_results(self, nodes)
1170 values = []
1171 if node.result.outputs:
-> 1172 values.insert(i, node.result.outputs.get()[key])
1173 else:
1174 values.insert(i, None)
AttributeError: 'str' object has no attribute 'insert'
> /code/nipype/nipype/pipeline/engine/nodes.py(1172)_collate_results()
1170 values = []
1171 if node.result.outputs:
-> 1172 values.insert(i, node.result.outputs.get()[key])
1173 else:
1174 values.insert(i, None)
ipdb> self.outputs
Bunch(components_file='components_file.txt', header=<undefined>, high_variance_masks=<undefined>, ignore_exception=False, mask_files=<undefined>, mask_index=<undefined>, merge_method=<undefined>, num_components=6, realigned_file=<undefined>, regress_poly_degree=1, use_regress_poly=True) After running into this, I'm wondering if we should add a basic check at the node.output level that converts the value to a list, something like
since we are assuming it is a list anyways. |
@mgxd - is this with python 3 or 2? if 2, can you check with python 3? and are you using my branch to check? |
py-3.6.1, your branch |
* upstream/master: enh: preliminary testing + altered auto tests minor typo Instead of invoking Popen, use CommandLine fix: clarity allow_compression fix: trailing parenthesis enh: imagetype base for spm, new image formats, allow_compression wip: check against image format enh: new traits applied to spm fix: catch compressed files for spm realign set memory minimum to 0.25 GB [ENH] Migrating resource handler to Node level
@mgxd - thanks taking a look |
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.
Sorry I did not go through the original PR thoroughly enough.
There is some serious refactoring going on (+1) which makes the diff hard to read, but I trust the tests.
@@ -142,7 +142,8 @@ def run_cc(self, ccinterface, expected_components, expected_header='CompCor'): | |||
components_data = [line.split('\t') for line in components_file] | |||
|
|||
header = components_data.pop(0) # the first item will be '#', we can throw it out | |||
expected_header = [expected_header + str(i) for i in range(expected_n_components)] | |||
expected_header = [expected_header + '{:02d}'.format(i) for i in | |||
range(expected_n_components)] |
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.
It's ok to change those names now, but after this will be released we need to be more careful since it's technically an API change.
nipype/algorithms/confounds.py
Outdated
desc=('Merge method if multiple masks are ' | ||
'present - `union` aggregates all masks, ' | ||
'`intersect` computes the truth value of ' | ||
'all masks, `none` performs CompCor on ' |
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.
What about
union
uses voxels included in at least one input mask, intersect
uses only voxels present in all input masks
nipype/algorithms/confounds.py
Outdated
mask_index = traits.Range(low=0, xor=['merge_method'], | ||
requires=['mask_files'], | ||
desc=('Position of mask in `mask_files` to use - ' | ||
'first is the default')) |
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 is a bit confusing, because it suggests that only the first mask will be used by default. Also the field does have usedefaults
. Is it a single index or range? This should be fleshed out in the description.
nipype/algorithms/confounds.py
Outdated
desc='the degree polynomial to use') | ||
header = traits.Str(desc=('the desired header for the output tsv file (one ' | ||
'column). If undefined, will default to ' | ||
'"CompCor"')) |
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.
Since we are breaking API I would rename this to header_prefix
this should be fixed now - good catch. the https://github.com/nipy/nipype/blob/master/nipype/algorithms/confounds.py#L493 i also missed it during the refactor. |
np.savetxt(components_file, components, fmt=b"%.10f", delimiter='\t', | ||
header=self._make_headers(components.shape[1]), comments='') | ||
return runtime | ||
|
||
def _process_masks(self, mask_images, timeseries=None): |
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.
for my curiosity - why split this up?
nipype/algorithms/confounds.py
Outdated
class TCompCorOutputSpec(CompCorOutputSpec): | ||
# and all the fields in CompCorOutputSpec | ||
high_variance_masks = OutputMultiPath(File(exists=True), | ||
desc=("voxels excedding the variance " |
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.
typo
self._header = 'tCompCor' | ||
self._mask_files = [] | ||
|
||
def _process_masks(self, mask_images, timeseries=None): |
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.
ah - I see now.
@chrisfilo - description changes updated. the traits Range trait is still an integer (or float) just allows validating with |
@chrisfilo - if you have a chance to run fmriprep and compare that would be good feedback as well. should work as normal. |
@chrisfilo - yeah, nay? |
closes #1982 supercedes #1984