Skip to content

Adding niftyseg #1911

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 18 commits into from
May 3, 2017
Merged

Adding niftyseg #1911

merged 18 commits into from
May 3, 2017

Conversation

byvernault
Copy link
Contributor

Dear nipype team,

We are ready to add niftyseg to nipype. I copied all the interfaces we generated for this package as well as the test.

I tested it with python 2 and python 3. It's working on my computer.

Let me know if you see anything not compatible or that I should change.

Kind Regards,

Ben

@codecov-io
Copy link

codecov-io commented Mar 29, 2017

Codecov Report

❗ No coverage uploaded for pull request base (master@38fa3d5). Click here to learn what that means.
The diff coverage is 62.45%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1911   +/-   ##
=========================================
  Coverage          ?   72.12%           
=========================================
  Files             ?     1115           
  Lines             ?    56246           
  Branches          ?     8083           
=========================================
  Hits              ?    40568           
  Misses            ?    14397           
  Partials          ?     1281
Flag Coverage Δ
#smoketests 72.12% <62.45%> (?)
#unittests 69.75% <62.45%> (?)
Impacted Files Coverage Δ
nipype/interfaces/setup.py 6.66% <0%> (ø)
...ype/interfaces/niftyseg/tests/test_label_fusion.py 10.34% <10.34%> (ø)
...rfaces/niftyseg/tests/test_auto_NiftySegCommand.py 100% <100%> (ø)
nipype/interfaces/niftyreg/tests/test_reg.py 13.88% <100%> (ø)
nipype/interfaces/niftyreg/__init__.py 100% <100%> (ø)
nipype/interfaces/niftyreg/tests/test_regutils.py 4.56% <100%> (ø)
nipype/interfaces/niftyseg/__init__.py 100% <100%> (ø)
nipype/interfaces/niftyseg/patchmatch.py 100% <100%> (ø)
nipype/interfaces/niftyseg/lesions.py 100% <100%> (ø)
nipype/interfaces/niftyseg/tests/test_maths.py 12% <12%> (ø)
... and 23 more

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 38fa3d5...3fb818f. Read the comment docs.

@byvernault
Copy link
Contributor Author

Hi,

I think we are finally good with this branch to add niftyseg interface to nipype.

Let me know if you have any question.

Kind Regards,
Ben

@oesteban
Copy link
Contributor

I'll look at this after #1913 is merged 👍

Copy link
Contributor

@oesteban oesteban left a comment

Choose a reason for hiding this comment

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

This is pretty mature and almost ready for merge. Great job!

The only outstanding issue is: why not creating just one nifty package? Then, the niftyreg and niftyseg interfaces would be inside.

If we finally have two submodules (and not one, as I propose). I think it'd be important to remove nipype/interfaces/niftyseg/base.py and import everything from nipype.interfaces.niftyreg.base. All the duplicated code should be removed.

Top-level namespace for niftyseg.
"""

from .base import no_niftyseg, get_custom_path
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these used outside the module? If not, I'd remove them

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmmm I don't think so. I will remove them.

return None

if ranking == 'ALL':
return '-%s' % ranking
Copy link
Contributor

Choose a reason for hiding this comment

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

woudn't return '-ALL' be more readable?

Copy link
Contributor Author

@byvernault byvernault May 1, 2017

Choose a reason for hiding this comment

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

yes indeed, we can do that.

desc='4D file containing the priors',
xor=['no_prior', 'priors'])

desc = 'List of priors filepaths.'
Copy link
Contributor

Choose a reason for hiding this comment

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

why not setting this string directly on the argument? (this holds for many traits defined below)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, it was for style and not go over 80 chars when they are very long but I should put this one back there as well as the other one.

try:
out_files = load_json(outfile)['files']
except IOError:
return self.run().outputs
Copy link
Contributor

Choose a reason for hiding this comment

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

I am doubtful of this self.run(), WDYT @satra?

outputs = self._outputs()
# local caching for backward compatibility
outfile = os.path.join(os.getcwd(), 'CalcTopNCC.json')
if runtime is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't be better to check for non-empty runtime.stdout as well?:

if runtime is None or not runtime.stdout:
...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure. Thanks.

_dtypes = ['float', 'char', 'int', 'short', 'double', 'input']

desc = 'datatype to use for output (default uses input type)'
output_datatype = traits.Enum(*_dtypes,
Copy link
Contributor

Choose a reason for hiding this comment

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

This is totally stylistic, but _dtypes is not used anymore right?, why not having the options in the Enum initialization?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure.

>>> node = niftyseg.UnaryStats()
>>> node.inputs.in_file = 'im1.nii'
>>> node.inputs.operation = 'v'
>>> node.cmdline # doctest: +ALLOW_UNICODE
Copy link
Contributor

Choose a reason for hiding this comment

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

I think all these interfaces would deserve some more doctests with more operations, so that we are sure that they work and that we don't break them in future maintenance.

>>> node.inputs.operand_file = 'im2.nii'
>>> node.inputs.output_datatype = 'float'
>>> node.cmdline # doctest: +ALLOW_UNICODE
'seg_maths im1.nii -sub im2.nii -odt float im1_sub.nii'
Copy link
Contributor

Choose a reason for hiding this comment

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

I think all these interfaces would deserve some more doctests with more operations, so that we are sure that they work and that we don't break them in future maintenance.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you think I can follow fslmaths doctests to edit those ones?

Copy link
Contributor

Choose a reason for hiding this comment

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

What I had in mind is something closer to the documentation of nipype.interfaces.ants.registration.Registration: https://github.com/nipy/nipype/blob/master/nipype/interfaces/ants/registration.py#L432-L640

Here, you'll see how the inputs to the interface are varied and then the new cmdline tested.

Copy link
Contributor Author

@byvernault byvernault May 2, 2017

Choose a reason for hiding this comment

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

I can do that but for those interfaces it's pretty easy, only the operation changed. It's kind of the same than fslmaths.

I added different exemples for some operation but by doing so I realised that I am not checking the inputs for some argument (for example pow, thr, uthr, ... use only a float or min uses only a file). I am adding that to the interface.

Let me know if you approve this and you really want to see one test per operation.

@@ -24,6 +24,7 @@ def configuration(parent_package='', top_path=None):
config.add_subpackage('mne')
config.add_subpackage('mrtrix')
config.add_subpackage('mrtrix3')
config.add_subpackage('niftyseg')
Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend having only one subpackage. I'll comment on this on the summary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Niftyreg/Niftyseg/Niftyfit are different packages that you install separately. Do you think having only one package won't be odd for the user? What do you think?

I could remove probably the base and use the same commands from niftyreg.base in this package. Or do you mean moving all the code into the same folder?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I don't have an special interest for having only one package. Let's observe that preference (reg/seg/fit packages) 👍 .

So if we keep the 3 packages structure, then I'm suggesting here to import from niftyreg.base and remove the duplicated code from niftyseg and niftyfit.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes sounds good. I jut did the changes and I renamed the function in niftyreg base for something more general like no_nifty_package.

What do you think about the changes?

Also do you prefer to import NiftyRegCommand like this:

import ..niftyreg.base.NiftyRegCommand as NiftySegCommand

Or do as I did?

I will do then the edits on niftyfit when you agree with those changes.

Kind Regards,
Ben

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh there are some issues for the test since most executables in niftyseg don't have a --version options that is working.

I will work on fixing this later today.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I add back the base.py just to create NiftySegCommand because of the version that isn't available for all the executables.

I also edited slightly the base.py for NiftyRegCommand.
The test should pass now.

Let me know what you think.

Cheers,
Ben

@satra satra merged commit a4cc711 into nipy:master May 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants