Added inital xnat_to_bids function and error checking for it#317
Added inital xnat_to_bids function and error checking for it#317DESm1th merged 6 commits intoTIGRLab:masterfrom
Conversation
|
Thanks for opening this pull request! We have detected this is the first time for you to contribute to datman. Please check out our contributing guidelines. Of course, if you want to opt-out this time there is no problem at all with adding your name later. You will be always welcome to add it in the future whenever you feel it should be listed. |
There was a problem hiding this comment.
Good work putting this together @slimnsour! Just have some comments on code-styling and 1 bigger ask to simplify the CLI interface. Lmk if you have questions :)
| --use-dcm2bids Pull xnat data and convert to bids using dcm2bids | ||
| --keep-dcm Keep raw dcm pulled from xnat in temp folder | ||
| --dcm-config CONFIG Path to dcm2bids config file | ||
| --bids-out BIDS_OUT Path to output bids folder | ||
| --forceDcm2niix Force dcm2niix to be rerun in dcm2bids | ||
| --clobber Clobber previous bids data |
There was a problem hiding this comment.
With all the new bids-specific CLI options would it make sense to perhaps switch over to argparse with a sub-parser to avoid over-crowding w/options that are specific to particular circumstances?
There was a problem hiding this comment.
Added the CLI in the new commits! Thanks for the suggestion
| keep_dcm=keep_dcm, | ||
| dcm2bids_config=dcm2bids_config, | ||
| bids_out=bids_out, | ||
| forceDcm2niix=forceDcm2niix, | ||
| clobber=clobber) |
There was a problem hiding this comment.
I'd refactor this and bundle these parameters as a dcm2bids Config object/dataclass
There was a problem hiding this comment.
I second Jer's suggestion here
There was a problem hiding this comment.
Added dataclass in the new commits, great suggestion!
| if (use_dcm2bids): | ||
| # Ensure the config is available | ||
| if dcm2bids_config is None: | ||
| try: | ||
| dcm2bids_config = datman.utils.locate_metadata("dcm2bids.json", config=cfg) | ||
| except datman.scanid.ParseException: | ||
| logger.error("No config file available for study {}." | ||
| "".format(study)) | ||
| # Ensure the bids output is available | ||
| if bids_out is None: | ||
| bids_out = cfg.get_path("bids") | ||
| xnat_to_bids(xnat, | ||
| project, | ||
| experiment, | ||
| keep_dcm=keep_dcm, | ||
| dcm2bids_config=dcm2bids_config, | ||
| bids_out=bids_out, | ||
| forceDcm2niix=forceDcm2niix, | ||
| clobber=clobber) | ||
| else: | ||
| process_experiment(xnat, project, experiment) |
There was a problem hiding this comment.
I'm even more convinced that we should use a sub-parser now! You could set up subparser.set_defaults(function=<target_func>) to simplify the logic:
https://stackoverflow.com/questions/49038616/argparse-subparsers-with-functions
There was a problem hiding this comment.
Added the new argparse parser in the new commits but no subparser, see #317 (comment)
Agreed, I think this is a good solution
Perf! This is how
Maybe we could have datman have a |
DESm1th
left a comment
There was a problem hiding this comment.
This looks good Salim, thank you! It looks like the 'making symlinks for the legacy datman folders' part was abandoned though. Without it a lot of our bin scripts and stuff will break at the moment so we might have to hold off on running nightly with the dcm2bids flag for a while
| keep_dcm=keep_dcm, | ||
| dcm2bids_config=dcm2bids_config, | ||
| bids_out=bids_out, | ||
| forceDcm2niix=forceDcm2niix, | ||
| clobber=clobber) |
There was a problem hiding this comment.
I second Jer's suggestion here
…y comments, specified error catching
|
Hello @slimnsour, Thank you for updating!
To test for issues locally, Comment last updated at 2021-11-19 21:48:25 UTC |
|
@slimnsour maybe instead of a sub-parser we could use It would achieve separation of bids options from base options to mitigate overcrowding as we had originally wanted |
…d over to argparse for organized argument groups
Great suggestion! I've added that to the newest commit. For context, the subparsers in argparse (from my testing) requires that the option to select the subparser be the very first positional argument choose between the subparsers. So, if we wanted to have subparsers to separate between extracting using our usual datman way and dcm2bids, we would have to call it like Here's the new output of |
| g_dcm2bids.add_argument( | ||
| "--use-dcm2bids", action="store_true", default=False, | ||
| help="Pull xnat data and convert to bids using dcm2bids" |
There was a problem hiding this comment.
Should the --use-dcm2bids option exist outside of this? And then, only if that option is used, the g_dcm2bids options are exposed.
There was a problem hiding this comment.
I moved it to the main group cause it makes more sense there like you said, but Im not sure how to only expose dcm2bids arguments when we read from the parser with argparse. Reading from a specific group is not supported and subparsers would break the usage I mentioned in #317 (comment)
There was a problem hiding this comment.
i think @josephmje wants to warn/prevent users from using BIDS related flags when --use-dcm2bids isn't selected. What we could do is to add a bit of code after parsing to check if any of the BIDS config exists when --dcm2bids is not selected and either:
- Throw up a warning indicated that those args will be ignored
- Use
ArgumentParser.errorwith a message
I prefer option 2 personally as it'll prevent mistakes from running through
There was a problem hiding this comment.
Yup! Could do something like
if not args.use_dcm2bids and (args.bids_out or args.dcm_config or ...):
parser.error("dcm2bids configuration requires --use-dcm2bids")
There was a problem hiding this comment.
Ah gotcha, thank you guys for laying that out! I added it in b1cb96b
Co-authored-by: Michael Joseph <josephmje.22@gmail.com>
…and switched to os.path instead of pathlib
jerdra
left a comment
There was a problem hiding this comment.
Good work and thanks for incorporating our feedback @slimnsour!
This is my base work for getting xnat_to_bids working on our system. This adds the function
xnat_to_bidsthat pulls the data directly from xnat into a tmp folder, and then dcm2bids is run on that tmp folder with an appropriate json for that study. This is called instead of the usual xnat to nii pull if you calldm_xnat_extract.pywith the tag--use-dcm2bids. Several arguments for dcm2bids are also allowed to be controlled (like--dcm-config,--forceDcm2niix, and--clobber).I would greatly appreciate feedback on this! Right now I have some design decisions that I'm unsure of as well:
/archive/data/$STUDY/metadata/dcm2bids.json. I think this might be a good idea instead of forcing it into the yamls for each of the studies, since the jsons mapping each study could overwhelm the file contents. Instead, we can have a separate location (its own repo or a folder or in datman-config) for all the jsons and then soft link them tometadata/dcm2bids.json. An example folder is already in our bids_dev repo./archive/data/$STUDY/data/bids. I believe this makes sense, especially with the option--bids-outthat allows you to override it for testing purposes.I still have other features I might add in the future (fixing fmap json intendedFor's, defacing), but I'd like to get the base functionality out there to get your guys' opinions on it.