-
Notifications
You must be signed in to change notification settings - Fork 59
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
Nipype1 interface wrapper and simple workflow #171
Comments
Some initial fiddling: import pydra
import nipype
import dataclasses as dc
import typing as ty
from nipype.interfaces import fsl
def traitedspec_to_specinfo(traitedspec):
return pydra.specs.SpecInfo(
name="Inputs",
fields=[
(name, ty.Any, dc.field(metadata={"help_string": trait.desc}))
for name, trait in traitedspec.traits().items()
]
) I don't really see how to create a task except by subclassing class Nipype1Task(pydra.TaskBase):
"""Wrap a Python callable as a task element."""
def __init__(
self,
interface: nipype.interfaces.base.BaseInterface,
audit_flags: pydra.AuditFlag = pydra.AuditFlag.NONE,
cache_dir=None,
cache_locations=None,
messenger_args=None,
messengers=None,
name=None,
**kwargs,
):
self.input_spec = traitedspec_to_specinfo(interface.input_spec())
self._interface = interface
if name is None:
name = interface.__class__.__name__
super(Nipype1Task, self).__init__(
name,
inputs=kwargs,
audit_flags=audit_flags,
messengers=messengers,
messenger_args=messenger_args,
cache_dir=cache_dir,
cache_locations=cache_locations,
)
self.output_spec = traitedspec_to_specinfo(interface.output_spec())
def _run_task(self):
inputs = dc.asdict(self.inputs)
res = self._interface.run(**inputs)
self.output = res.outputs This isn't quite ideal, because it means that newBET = Nipype1Task(fsl.BET)
bet = newBET(...) Anyway, I'm getting stuck on actually running the thing: wf = pydra.Workflow(name='unifize_and_skullstrip_wf', input_spec=['in_file'])
bet = Nipype1Task(fsl.BET())
bet.in_file = wf.lzin.in_file
wf.add(bet)
with pydra.Submitter() as sub:
sub(wf) The results in:
|
When people get a minute, maybe we can discuss the status of this, post |
my_input_spec = SpecInfo(
name="Input",
fields=[
(
"text",
attr.ib(
type=str,
metadata={"position": 1, "help_string": "text", "mandatory": True},
),
)
],
) |
How is the current progress on this issue? I suggested the introduction of a
Advantages:
Disadvantages:
Since workflows are tasks in pydra, it would make sense to do the same for workflows. Regarding tests, one could rewrite original nipype1 tests to use yaml-based pydra tasks instead. What do you think? |
I just noticed that you already implemented a nipype1 task wrapper with the PR nipype/pydra-nipype1#1 |
@dafrose Yes, a method to translate the nipype1 packages to YAML files that could be loaded as Pydra tasks would be fantastic. The Converting the input and output specs automatically via a YAML representation seems useful, as it would give us a declarative, Python-independent representation. The only problem I see is with interfaces that have more complicated internal workings that cannot be determined only from input and output specs. |
@effigies happy to hear that you like the idea :-)
Do you have something in particular in mind? Anything that strictly requires user input via the command line during runtime does not work with nipype1 anyway, does it? Regarding more complex relations between inputs and output filenames, it would always be possible to reference any Python function from the YAML spec. Anything beyond that? |
Here's an example of something that would be painful: https://github.com/nipy/nipype/blob/07af08f98/nipype/interfaces/freesurfer/preprocess.py#L1010-L1569 ANTs tools are often other examples. They may be doable within the YAML, but I think the YAML would need to be designed, not automatically generated from what currently exists. |
i just want to point you to my branch where I'm working on fsl package. My way of doing is to have a converter that needs nipype1 interface and a hand-written yml file for things that I can't automatically take from nipype. @effigies @dafrose - perhaps we could zoomeet one day, what do you think? |
Can generally call in the 9-11am (Eastern US) range. In the next two weeks, any days but Friday Oct 30 and Tuesday Nov 3 work. If you need more precision, can you send a poll? |
ok, i've created the poll for times suggested by @effigies https://doodle.com/poll/8fei4vdawvyg66me we can think who should we ping. |
I filled in my availabilities. Sorry for the late reply. With my current situation being quite dynamic, it is a bit difficult to judge in advance, but I'll try to make it work, if you decide on a time.
I had a brief look at the code and can see why this would be problematic. With pydra's workflows being subclasses of tasks: Would it work to split up something as complex as In principle, you could represent conditions in a YAML-based task template, but I do not see how that would be better than doing it directly in Python. Maybe for some Considering, that an automatic YAML-translator might not be the best/only reasonable option, here an idea how to spice up your existing implementation that you presented above: Instead of making the nipype1 wrapper a class that instantiates a def nipype1_wrapper(interface, name, base = pydra.BaseTask, **kwargs):
attr_dict = magic_nipype1_parser(interface)
attr_dict.update(kwargs)
return type(name, base, attr_dict) This can of course be mixed with the YAML parser, because as soon as you parse the nipype1 interface into a dict, you can probably also serialize it into valid (machine-readable) YAML. It would not look nice, but probably work. |
@dafrose @effigies - thanks for answering to the poll - let's meet this Thursday at 9am EDT / 2pm CET Feel free to invite others |
I just want to stick this here, so it won't be forgotten in the call: I stumbled upon issue #42 which resulted in a prototype for a nipype1topydratask function by @dPys. The function seems to solve the same problem as the code by @effigies, but differently. Instead of taking the original interface class, the function takes an instance of a nipype1 interface to create an instance of its counterpart in pydra. |
Yep, will definitely try to join in! Thanks for bumping this issue @dafrose |
this is the google doc from the meeting: https://docs.google.com/document/d/12_oJKLx58c2iF_oRgPopETIX7G9qL9IH4cAa8dky8CU/edit |
Paths may be an issue...
The text was updated successfully, but these errors were encountered: