Skip to content

ENH: Add SpatialReference field to some outputs - #513

Open
tsalo wants to merge 16 commits into
nipreps:masterfrom
tsalo:spatialreference
Open

ENH: Add SpatialReference field to some outputs#513
tsalo wants to merge 16 commits into
nipreps:masterfrom
tsalo:spatialreference

Conversation

@tsalo

@tsalo tsalo commented Dec 4, 2025

Copy link
Copy Markdown
Collaborator

Related to nipreps/fmriprep#3579.

This should add SpatialReference to volumetric, standard-space anatomical outputs.

@tsalo

tsalo commented Dec 5, 2025

Copy link
Copy Markdown
Collaborator Author

For TemplateFlow volumetric spaces, the SpatialReference field will just have a URL (e.g., "https://templateflow.s3.amazonaws.com/tpl-MNI152Lin/tpl-MNI152Lin_res-02_T1w.nii.gz"). For non-standard volumetric spaces, it will be the absolute path to the template (e.g., "/home/.cache/templateflow/tpl-MyTemplate/tpl-MyTemplate_T1w.nii.gz"). I can't think of a good way to make the latter into a BIDS URI without having dataset_links defined in the config object, which seems out of scope for sMRIPrep.

@effigies

effigies commented Dec 5, 2025

Copy link
Copy Markdown
Member

Does it make more sense to copy the BIDSURI functionality from fMRIPrep? I think threading a dataset_links dictionary through datasink workflows and anything that calls them is reasonable. I think I'd prefer that to one implementation for functional and a different one for structural derivatives.

@tsalo

tsalo commented Dec 5, 2025

Copy link
Copy Markdown
Collaborator Author

That makes sense. I can add that.

@tsalo

tsalo commented Dec 5, 2025

Copy link
Copy Markdown
Collaborator Author

I think it looks good now. Here's the value from ds054:

{
    "SpatialReference": "bids:templateflow:tpl-MNI152Lin/tpl-MNI152Lin_res-02_T1w.nii.gz"
}

@tsalo
tsalo requested a review from effigies December 5, 2025 20:21

@effigies effigies left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A few thoughts. I'm not sure that they're enough to finish this off on, but LMK what you think, and we can talk this over next week maybe?

Comment thread src/smriprep/workflows/outputs.py Outdated
Comment thread src/smriprep/workflows/outputs.py Outdated
Comment on lines +967 to +970
spatial_reference = pe.Node(
TemplateFlowReference(),
name='spatial_reference',
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm worried this is going to interfere with passing dataset_links from fmriprep, since that maps TF_LAYOUT.root onto bids:templateflow: and accepts raw paths.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think we should update fMRIPrep to point to the website when it's a built-in template, but I could pass the dataset_links into this node to use a local path if templateflow is a key in the dictionary and doesn't start with http.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

One reason I was leaning toward the website is that the CIFTI SpatialReference dictionary uses the website. If we do commit to using the local templateflow location then we should change that as well.

Comment thread src/smriprep/interfaces/templateflow.py Outdated
Comment on lines +246 to +247
if template_name in tf.TF_LAYOUT.get_templates():
self._results['uri'] = f'{tf_url}/{str(rel_path)}'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Presumably this is going to return custom templates found in TF_LAYOUT, so I'm not sure that the else branch will ever get hit.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Oh... I had hoped that get_templates would only return built-in templates, but that makes sense. Is there any way to distinguish built-in templates from custom ones?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm. I suppose we could inspect the skeleton in the templateflow client.

import zipfile
import templateflow

templates = [
    tpl.name.removeprefix('tpl-')
    for tpl in zipfile.Path(templateflow.conf.load_data('templateflow-skel.zip')).iterdir()
]

That's very much unsupported API, but it's doable.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Maybe it's easier to just reference TF_LAYOUT.root consistently until there's a more standard way to distinguish built-in and custom templates with the templateflow library. I would just need to change the SpatialReference in CIFTIs from URLs to BIDS-URIs.

@oesteban

oesteban commented Feb 18, 2026

Copy link
Copy Markdown
Member

@tsalo would nipreps/niworkflows#1024 help unlock this one?

@tsalo

tsalo commented Feb 18, 2026

Copy link
Copy Markdown
Collaborator Author

Having the BIDSURI interface in niworkflows will reduce the amount of code added in this PR, so I'm happy to wait until that is addressed before pushing forward with this, but the main hurdle currently is making sure SpatialReference for TemplateFlow templates is consistent across files (i.e., that it is either a pointer to the local TemplateFlow folder or to the right location online).

@codecov

codecov Bot commented Feb 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.00%. Comparing base (583c739) to head (3b0004d).
⚠️ Report is 12 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #513      +/-   ##
==========================================
+ Coverage   70.12%   75.00%   +4.87%     
==========================================
  Files          23       24       +1     
  Lines        2065     2128      +63     
  Branches      273      290      +17     
==========================================
+ Hits         1448     1596     +148     
+ Misses        558      461      -97     
- Partials       59       71      +12     
Flag Coverage Δ
ds054 46.30% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tsalo

tsalo commented Feb 18, 2026

Copy link
Copy Markdown
Collaborator Author

I think I've addressed the main blocker by sticking to the local TemplateFlow path, but will pause this PR until nipreps/niworkflows#1031 is merged.

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.

3 participants