-
Notifications
You must be signed in to change notification settings - Fork 110
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
added script to create jsons files for MP2RAGE #101
Conversation
Can someone with Python & MPRage experience have a look at this? Not sure whom, trying @emdupre @KirstieJane |
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 great ! Thanks so much, @Remi-Gau
I had a few comments on ways you could improve the readability of the code, and a few questions on what was happening so that hopefully we could streamline a little more ! Looking forward to seeing this integrated 👍
pythonCode/create_MP2RAGE_json.py
Outdated
DEFINE CONTENT OF JSON FILES | ||
''' | ||
# sub-*_inv-1_MPRAGE.json | ||
data_inv_1 = OrderedDict() |
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.
One option that might be a little cleaner -- since you know all of the key-value pairs at the start, you could include all of them in the definition. So here, for data_inv_1
, you might do:
data_inv_1 = OrderedDict([
('InversionTime', '900'),
('FlipAngle', '5')
])
Totally stylistic, but might be nice from a human readability perspective !
pythonCode/create_MP2RAGE_json.py
Outdated
data_inv_1['FlipAngle'] = '5' | ||
|
||
# sub-*_inv-2_MPRAGE.json | ||
data_inv_2 = OrderedDict() |
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.
Same thing for this dictionary !
pythonCode/create_MP2RAGE_json.py
Outdated
data_inv_2['InversionTime'] = '2750' # ms | ||
data_inv_2['FlipAngle'] = '3' | ||
|
||
# sub-*_T1map.json |
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.
Could you remove these lines since they're unused and not clarifying comments ?
pythonCode/create_MP2RAGE_json.py
Outdated
|
||
|
||
# sub-*_MPRAGE.json | ||
data_MP2RAGE = OrderedDict() |
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.
Same stylistic comment is above -- you can really see the difference here with many fields !
pythonCode/create_MP2RAGE_json.py
Outdated
from collections import OrderedDict | ||
|
||
''' | ||
DEFINE CONTENT OF JSON FILES |
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.
Since these are single line comments, can you just do them in the #
format rather than as block quotes ?
pythonCode/create_MP2RAGE_json.py
Outdated
|
||
|
||
''' | ||
WRITE THEM |
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.
Same thing here about single-line comments !
pythonCode/create_MP2RAGE_json.py
Outdated
start_dir = "" # insert here path to your BIDS data set | ||
|
||
# list all subjects | ||
subj_ls = next(os.walk(start_dir))[1] |
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.
instead of using os.walk
, have you thought about using glob
? It's another standard import and might be a little cleaner, here !
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.
Still gotta do that one.
pythonCode/create_MP2RAGE_json.py
Outdated
|
||
# sub-01_T1map.json | ||
# sub-01_T1w.json | ||
data_T1['BasedOn'] = \ |
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 a little hard to read -- could you define these strings first and then assign them as a value to this key ?
pythonCode/create_MP2RAGE_json.py
Outdated
with open(os.path.join(json_folder, json_name), 'w') as ff: | ||
json.dump(data_MP2RAGE, ff, sort_keys=False, indent=4) | ||
|
||
# sub-01_T1map.json |
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 not sure if these are clarifying or not ! Could you add more text, if they're intended to be ?
pythonCode/create_MP2RAGE_json.py
Outdated
with open(os.path.join(json_folder, json_name), 'w') as ff: | ||
json.dump(data_T1, ff, sort_keys=False, indent=4) | ||
|
||
json_name = name[:12] + '_T1w.json' |
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 can't test this locally right now, so just to confirm -- why is it name[:12]
?
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.
why is it name[:12]
Well spotted! That was one issue I had to fix. The script will now write the JSON files if it finds a_inv1_part-mag_MPRAGE.nii.gz
and the name of the JSON files to create can then be based on the end index of that file without worrying how people decide to name their subjects / session...
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.
Ah, I see now ! One other way to do this, then, that might be a little clearer -- something like:
sid = '_'.join(name.split('_')[:-3]) # excludes last three key-value pairs
Avoiding counting characters just eases the cognitive burden when reading the code ! And writing it, too :)
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.
Also, then, rather calling e.g. name[:-29]
multiple times, you could just assign the above string to a value and pop that in as you need it ✨
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.
Thanks for the feedback: helps me learn new stuff! Will implement that and directory walking today hopefully.
Also the multiple calling is definitely a bad habit from years of matlab coding: gotta lose that one fast!
I have covered most the changes suggested expect the |
Thanks, @Remi-Gau ! Great to see this moving forward 🚀 |
@emdupre I have tried implementing a few of your suggestions.
|
c2f7d5c
to
258cd26
Compare
Hum... Silly question from a git / github beginners. A bit of googling and some fascinating and thrilling reads of the git doc taught me a lot of things but did not answer my question. e.g git ls-remote tells me that your commits don't show on this PR. But I don't think that commits live somewhere in the ether unattached to anything so I am most unclear how I can get them on my machine to actually test them. I am sure I am missing somthing but not sure what. |
Hi @Remi-Gau ! Yes, sorry, I had accidentally committed directly to your pull request at first ! I had forgotten I had write permissions. To fix it, I opened a new PR with the desired commits and then rebased your branch to remove the extra commits, which was definitely confusing 😄 If you go to your fork, you should see that there's an open PR. On the PR, it will tell you where the commits are coming from in a So in this case, it says You can |
Ha. That makes sense. I was getting confused as to what was going on. |
Everything checks out. So I rebased your PR on top of mine and pushed the whole thing here.
Yup that helped a lot and was way quicker than doing a lot of googling in all possible directions!
As much as I try to be conservative with matlab and SPM (preference for backward and octave compatibility) I am just getting started with python so I went in straight thinking that I would stick to python 3. But I am still at a stage where I don't know what would break backward compatibility. So having only python 3 is fine by me. |
Great, glad it was helpful @Remi-Gau ! I did one other thing that I thought might be helpful to you and to the reader, which is to try and minimize duplicated code by putting it in a function. It's now a PR on your fork -- let me know what you think ! |
Just saw that. Looks very good to me (and it helps me learn new python functions I did not know). |
[ENH] create functions
Great, glad it was helpful ! ✨ This is a +1 on merging from me, then. Thanks so much, @Remi-Gau EDIT: Will merge in today unless I hear otherwise from @KirstieJane @dorahermes |
Just a little python script to create the appropriate JSON files for MP2RAGE sequences in the relevant folders in a BIDS data set (see #99 )
PS: first python script ever, be gentle plz. :-)