Skip to content

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

Merged
merged 7 commits into from
May 5, 2017
Merged

Fix/compcor #1992

merged 7 commits into from
May 5, 2017

Conversation

satra
Copy link
Member

@satra satra commented May 2, 2017

closes #1982 supercedes #1984

@satra satra requested review from mgxd and chrisgorgo May 2, 2017 23:08
@satra
Copy link
Member Author

satra commented May 2, 2017

confounds.py and test_compcor.py are the target files - a few other style and test fixes got included.

@codecov-io
Copy link

codecov-io commented May 3, 2017

Codecov Report

Merging #1992 into master will increase coverage by 0.02%.
The diff coverage is 90.67%.

Impacted file tree graph

@@            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
Flag Coverage Δ
#smoketests 72.33% <90.67%> (+0.02%) ⬆️
#unittests 69.86% <90.67%> (+0.02%) ⬆️
Impacted Files Coverage Δ
nipype/interfaces/afni/preprocess.py 85.61% <ø> (ø) ⬆️
nipype/interfaces/afni/utils.py 75.76% <ø> (ø) ⬆️
nipype/algorithms/tests/test_auto_ACompCor.py 85.71% <ø> (ø) ⬆️
nipype/algorithms/tests/test_auto_TCompCor.py 85.71% <100%> (-14.29%) ⬇️
nipype/algorithms/tests/test_compcor.py 100% <100%> (ø) ⬆️
nipype/interfaces/fsl/utils.py 72.73% <100%> (ø) ⬆️
nipype/algorithms/confounds.py 77.93% <89.32%> (+3.28%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a092cde...85b5692. Read the comment docs.

@mgxd
Copy link
Member

mgxd commented May 3, 2017

@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

if not isinstance(values, list):
    values = [values]

since we are assuming it is a list anyways.

@satra
Copy link
Member Author

satra commented May 3, 2017

@mgxd - is this with python 3 or 2? if 2, can you check with python 3? and are you using my branch to check?

@mgxd
Copy link
Member

mgxd commented May 3, 2017

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
@satra
Copy link
Member Author

satra commented May 3, 2017

@mgxd - thanks taking a look

Copy link
Member

@chrisgorgo chrisgorgo left a 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)]
Copy link
Member

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.

desc=('Merge method if multiple masks are '
'present - `union` aggregates all masks, '
'`intersect` computes the truth value of '
'all masks, `none` performs CompCor on '
Copy link
Member

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

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'))
Copy link
Member

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.

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"'))
Copy link
Member

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

@satra
Copy link
Member Author

satra commented May 3, 2017

this should be fixed now - good catch. the TCompCorOutputSpec was derived from CompCorInputSpec

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):
Copy link
Member

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?

class TCompCorOutputSpec(CompCorOutputSpec):
# and all the fields in CompCorOutputSpec
high_variance_masks = OutputMultiPath(File(exists=True),
desc=("voxels excedding the variance "
Copy link
Member

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):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah - I see now.

@satra
Copy link
Member Author

satra commented May 3, 2017

@chrisfilo - description changes updated. the traits Range trait is still an integer (or float) just allows validating with high and low.

@satra
Copy link
Member Author

satra commented May 3, 2017

@chrisfilo - if you have a chance to run fmriprep and compare that would be good feedback as well. should work as normal.

@satra
Copy link
Member Author

satra commented May 4, 2017

@chrisfilo - yeah, nay?

@satra satra merged commit a01275f into nipy:master May 5, 2017
@satra satra deleted the fix/compcor branch October 30, 2017 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CompCor issues
4 participants