-
Notifications
You must be signed in to change notification settings - Fork 4
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
Add BIDS reading support and prepare input loading for pydra workflow #7
Conversation
physutils/tasks.py
Outdated
@@ -0,0 +1,34 @@ | |||
import logging | |||
|
|||
import pydra |
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 definitely adds complexity, but since physutils might be used by modules that are not based in pydra, could we try to create a safe import and make it optional, like the one we have for duecredit?
https://github.com/physiopy/phys2denoise/blob/master/phys2denoise/due.py
The idea would then to try from pydra.mark import task
, but if it is not found, import task
from a stub submodule of physutils. That task
would be a decorator that returns the function.
(like here: https://github.com/BMRRgroup/wfTFI/blob/ec5a62cf2ffb347c752293e6234b7c89cebe711d/QSM.py#L7C1-L13C1)
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.
That task would be a decorator that returns the function
What do you mean here? I'm not sure I understand how you'd like this to be done (mostly given the duecredit example).
I tried doing smth like this, but it didn't really work out
def mark_task_wrapper(func):
try:
import pydra
logger.debug("Pydra is installed and is currently enabled.")
return pydra.mark.task(func)
except ImportError:
logger.warning("Pydra is not installed and is currently disabled. Please install it to use this module.")
return func
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.
@smoia feel free to check, I implemented it with just a wrapper and it seems to work
Other than the changes requested by Stef, LGTM ! |
physutils/tasks.py
Outdated
|
||
@pydra.mark.task | ||
def transform_to_physio( | ||
input_file: str, mode="physio", fs=None, bids_parameters=dict(), bids_channel=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.
It makes a lot of sense to add this as a task, great addition to the phys2denoise workflow and to continue to build up physutils :)
I'd like to suggest changing the name of bids_channel to col_physio_type to increase consistency with the load_from_bids function - since there is not a lot of documentation within the code itself, I think it's important to try to maintain intuitive links!
Beyond that, I'm wondering why the task is named transform_to_physio when it can either transform to physio or read-in an existing physio object. Perhaps e.g. generate_physio would be more appropriate? At minimum I think it's helpful to describe the goal of this task and its potential use cases in the description for the PR. Also, please indicate the change type in the PR description :)
Other than these considerations and what Stef mentioned above regarding avoiding a dependency on pydra, this looks good to me!
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.
Imo, it's ok as transform_to_physio
, as even in case it reads a .phys file, it transforms a pickled Physio object file, into a Physio object instance to be used in further tasks.
Also maybe it'd be better to change the variable name in load_from_bids? It's not an interface variable (not used outside the function scope) so I don't think we should take this naming as a basis
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.
Kudos on changing name to generate_physio
or something similar.
Double kudos on adding a good docstring for explanations!
I also added an auto mode, as per physiopy/phys2denoise#57 (comment) |
physutils/tasks.py
Outdated
def mark_task(pydra_imported=pydra_imported): | ||
def decorator(func): | ||
if pydra_imported: | ||
# If the decorator exists, apply it | ||
@wraps(func) | ||
def wrapped_func(*args, **kwargs): | ||
logger.debug(f"Creating pydra task for {func.__name__}") | ||
return pydra.mark.task(func)(*args, **kwargs) | ||
|
||
return wrapped_func | ||
# Otherwise, return the original function | ||
return func | ||
|
||
return decorator |
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.
That may work, but I honestly was thinking about something like:
def task(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
In a utils
module, and then here:.
try:
from pydra.mark import task
except ImportError:
from .utils import task
physutils/tasks.py
Outdated
input_file: str, mode="physio", fs=None, bids_parameters=dict(), bids_channel=None | ||
) -> Physio: | ||
if not pydra_imported: | ||
LGR.warning( |
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.
LGR.warning( | |
LGR.debug( |
setup.cfg
Outdated
loguru | ||
pydra |
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.
Move this to an extra
setup.cfg
Outdated
loguru | ||
pydra | ||
pybids |
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.
Eventually, we need to move this to extras as well (it comes with SO MANY dependencies). Could you please open an issue to generically move as many dependencies as possible to extra dependencies? Not now, but it would be good to do so later.
@maestroque do you need any help addressing @smoia's comments? |
@maestroque any progress on this side? |
@smoia @m-miedema I didnt have in mind that there was something pending for this sorry. As far as i can tell only the dependencies issue opening |
physutils/tasks.py
Outdated
if not fs: | ||
fs = 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.
I'm a bit confused about these two lines, was there something you were trying to check?
…trings, rename transform_to_physio function
@maestroque @m-miedema @me-pic I opened a PR to @maestroque 's branch: It should take care of most issues. Emphasis on should. |
The only thing is that logging is still a bit weird cause it uses logging on one side and loguru on the other. Maybe we should just use logging for the moment? |
A few mods stemming from PR convo
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!
physutils/tests/test_tasks.py
Outdated
input_file=bids_dir, | ||
mode="bids", | ||
bids_parameters=bids_parameters, | ||
bids_channel="cardiac", |
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 failing since bids_channel
is not a valid argument in the generate_physio
function
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.
Ok just realized looking at the previous comments that bids_channel
was changed to col_physio_type
in generate_physio, but the test_tasks.py
have not been update accordingly
assert task.inputs.input_file == physio_file | ||
assert task.inputs.mode == "physio" | ||
assert task.inputs.fs is 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.
pytest is failing.. inputs
is not an attribute included in the Physio class, nor input_file
or mode
...
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.
inputs
is a pydra task attribute specifying the input struct of the task, it may be that the new changes making pydra optional broke the tests. Before the tests were successful
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.
All the tests in test_tasks.py
are failing... Not sure I understand the inputs
attribute. Also all the bids_channel
need to be changed to col_physio_type
physutils/tasks.py
Outdated
# from loguru import logger | ||
|
||
try: | ||
from pydra import task |
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.
@smoia Is it possible that here it should be from pydra.mark import task
instead of from pydra import task
?
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.
With that change test_generate_physio_bids_file
and test_generate_physio_auto
in test_tasks.py
are now passing 🤔
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 that could be it actually. Thank you for catching it!
🚀 PR was released in |
Closes #9
Proposed Changes
transform_to_physio
pydra task to be used in all worfklowsChange Type
bugfix
(+0.0.1)minor
(+0.1.0)major
(+1.0.0)refactoring
(no version update)test
(no version update)infrastructure
(no version update)documentation
(no version update)other
Checklist before review