Skip to content
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

FIX: Use BIDS metadata for TR over nii header #357

Merged
merged 2 commits into from
Jan 29, 2019

Conversation

effigies
Copy link
Collaborator

Kind of fixes #355. Turns out the nifti (and BIDS metadata) had a TR of 2.00001 (or thereabouts), which caused a misestimation of duration, which caused one extra volume on a long time series.

This fix allows the change in the JSON sidecar (easier than editing NIFTI headers) to take effect. We should also generally prefer JSON metadata to NIFTI headers, anyway.

@tyarkoni
Copy link
Collaborator

LGTM, but are you sure we want to trust the JSON sidecar over the nifti header? I guess my naive expectation is that errors are likely to be more common in the former than the latter.

@satra
Copy link
Contributor

satra commented Jan 25, 2019

@tyarkoni - my naive expectation would be the opposite since most people don't write these sidecars by hand, and i think the bids spec says somewhere that sidecar takes precedence.

@tyarkoni
Copy link
Collaborator

@satra sure, but I don't think most people are editing nifti headers by hand either, and if I had to guess, I think it's more likely that the sidecars are being set based on information extracted from the headers than the other way around. That said, if the spec says that the sidecar takes precedence, that's good enough for me. :)

@yarikoptic
Copy link
Collaborator

+1 on @satra - .json sounds like a more reasonable place to allow for overrides...
although might be considered a separate (".json override what is in the original data files") issue, IMHO it relates to having a good/unambigous description for inheritance principle and how to formalize it (since currently it is not): bids-standard/bids-specification#102

@@ -147,7 +147,8 @@ def _load_time_variables(layout, dataset=None, columns=None, scan_length=None,
try:
import nibabel as nb
img = nb.load(img_f)
duration = img.shape[3] * img.header.get_zooms()[-1]
tr = layout.get_metadata(img_f)['RepetitionTime']
Copy link
Collaborator

Choose a reason for hiding this comment

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

what if it is not there?
The bible describes it as REQUIRED but then it says that it is "mutually exclusive" with VolumeTiming. I do not think that if a varying VolumeTiming is supported anywhere here but then it either must blow with a meaningful message if RepetitionTime is absent or look into VolumeTiming and verify that it is equispaced/deduce the TR, or fallback to lookup in .nii.gz
This echoes with another comment +1'ing Satra that .json ideally takes precendence since apparently with VolumeTiming it might be quite obscure case and pybids better blows if finds notably variable timing instead of plowing through

PS FWIW, I saw no dataset with VolumeTiming in metadata extracted from openneuro datasets, so it is more of a "future proofing" I guess

@effigies
Copy link
Collaborator Author

I agree with @satra, though I'm not sure the spec indicates precedence. My reasoning is that JSON is easier to inspect and fix than NIfTI headers if there are problems, and therefore should be presumed to indicate intent with higher reliability.

I'll also note that at line ~162, we do pull this TR out of the metadata just after this point, so we should probably be consistent about which we give precedence, regardless of the decision. I would suggest we just move that get_metadata() call to above this try: block.

So don't merge this yet. I'll try to find a couple minutes to clean things up.

Also, I agree with @yarikoptic that we should check on VolumeTiming and other sparse approaches. It's just... there are so many things.

@yarikoptic
Copy link
Collaborator

😈 advocate counter argument: other/basic tools have no clue about overrides in json and operate on information from .nii - so we would be running into the danger of obtaining inconsistent or wrong results if we allow such overrides in json. I think that we actually should explicitly in bids enforce consistency between json and .nii.gz . And iirc bids validator already does that right?

@tyarkoni
Copy link
Collaborator

To be clear, I have no problem at all with assuming that JSON overrides metadata extracted from other sources in pybids. It's a simple principle that's easy to implement. I'm happy with it. My question was meant more for my own personal edification—I was just curious whether, implementation aside, we should expect the nifti header to be more accurate than the JSON. Nothing important hangs on it one way or the other, so I suggest we go with the proposal here, and move on.

@codecov
Copy link

codecov bot commented Jan 27, 2019

Codecov Report

Merging #357 into master will increase coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #357      +/-   ##
==========================================
+ Coverage   73.27%   73.28%   +0.01%     
==========================================
  Files          24       24              
  Lines        2604     2605       +1     
  Branches      640      640              
==========================================
+ Hits         1908     1909       +1     
  Misses        513      513              
  Partials      183      183
Flag Coverage Δ
#unittests 73.28% <100%> (+0.01%) ⬆️
Impacted Files Coverage Δ
bids/variables/io.py 75.25% <100%> (+0.12%) ⬆️

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 e9fc2df...c418881. Read the comment docs.

1 similar comment
@codecov
Copy link

codecov bot commented Jan 27, 2019

Codecov Report

Merging #357 into master will increase coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #357      +/-   ##
==========================================
+ Coverage   73.27%   73.28%   +0.01%     
==========================================
  Files          24       24              
  Lines        2604     2605       +1     
  Branches      640      640              
==========================================
+ Hits         1908     1909       +1     
  Misses        513      513              
  Partials      183      183
Flag Coverage Δ
#unittests 73.28% <100%> (+0.01%) ⬆️
Impacted Files Coverage Δ
bids/variables/io.py 75.25% <100%> (+0.12%) ⬆️

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 e9fc2df...c418881. Read the comment docs.

@effigies
Copy link
Collaborator Author

Okay, this is ready for merge, IMO.

@KirstieJane
Copy link
Member

KirstieJane commented Jan 27, 2019

Would it be useful to open an issue at https://github.com/bids-standard/bids-specification about the precedence? Or is it already clear?

(This is orthogonal to merging the PR - just thinking about avoiding others having the same conversation!)

@effigies
Copy link
Collaborator Author

I agree. Thanks for the prod, @KirstieJane. If anybody wants to continue the discussion, let's have it on bids-standard/bids-specification#138.

@effigies effigies merged commit e89c6a5 into bids-standard:master Jan 29, 2019
@effigies effigies deleted the fix/repetition_time_source branch January 29, 2019 23:56
@effigies effigies mentioned this pull request Jan 30, 2019
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Design matrix has nvols + 1 rows after convolution
5 participants