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

✨ Nifti header orientation checks and decisions for downstream resources #2138

Open
1 task
sgiavasis opened this issue Jul 26, 2024 · 1 comment · Fixed by #2140
Open
1 task

✨ Nifti header orientation checks and decisions for downstream resources #2138

sgiavasis opened this issue Jul 26, 2024 · 1 comment · Fixed by #2140
Assignees
Milestone

Comments

@sgiavasis
Copy link
Collaborator

sgiavasis commented Jul 26, 2024

Related problem

C-PAC by default updates all incoming data to have its orientation set to RPI in the Nifti headers.
This matches the atlases and parcellations that come bundled with C-PAC.

However, outside of the errors or warnings that several tools already have bulit-in, there are no strong C-PAC-side catches or guard-rails for the possibility that:

  • A user might use a template in another orientation which switches the orientation when the warp application causes the result to adopt the reference header information, then enables template-space analysis.
  • A user might use a custom atlas or parcellation that is not in RPI.

Proposed feature

Either:

  • We add functionality to check the header orientation of all incoming resources and data (templates, atlases, etc.), which then throws an error if these do not align.
  • Expand the reorient nodes at the beginning to also run on all other incoming resources to lock everything to the chosen orientation.
    • (This may get in the way of users who want to maintain the orientation of the provided template, although they can then choose this in the config anyway).

Acceptance criteria

  • Any data of one orientation being used with resources of another should be impossible, regardless of pipeline config intersections.

Alternatives

No response

Additional context

No response

@birajstha
Copy link
Contributor

@sgiavasis , If we have list of all the NIFTI files including atlases and templates, we could do something like this?

from nipype import Node, Workflow, Function
from CPAC.pipeline import nipype_pipeline_engine as pe
from nipype.interfaces import afni
from nipype.interfaces.afni import Info
import os
import pandas as pd
timeseries_paths = ["/home/biraj/bids_parsing/dataset/anna/raw/sub-PA001/ses-V1W1/func/sub-PA001_ses-V1W1_task-facesmatching_run-1_bold.nii.gz"]*10
def find_orientation(input_file):
    import subprocess
    cmd_3dinfo = [
        "3dinfo",
        "-orient", input_file
    ]

    orientation = subprocess.run(cmd_3dinfo, capture_output=True, text=True).stdout.strip().upper()
    return orientation
    
find_orient = Node(Function(input_names=["input_file"],
                            output_names=["orientation"],
                            function=find_orientation),
                   name="find_orient")

reorient_image = Node(interface=afni.Resample(),
                              name='reorient',
                              mem_gb=1,
                              mem_x=(0.0115, 'in_file', 't'))
reorient_image.inputs.outputtype = 'NIFTI_GZ'
def check_all_orientations(input_images:list, desired_orientation:str="RPI", reorient=False):
    desired_orientation = desired_orientation.upper()
    orientations = []
    for image in input_images:
        find_orient.inputs.input_file = image
        orientation = find_orient.run().outputs.orientation
        if orientation == desired_orientation:
            comment = "Matches desired orientation"
        else:
            comment = f"Doesnot match the desired orientation: {desired_orientation}"
            if reorient:
                reorient_image.inputs.in_file = image
                reorient_image.inputs.orientation = desired_orientation.upper()
                _result = reorient_image.run().outputs.out_file
                comment = f"Reoriented to {desired_orientation}"
        orientations.append([image,orientation, comment])
    return orientations
    
table = check_all_orientations(
                            input_images = timeseries_paths, 
                            desired_orientation = "RAI", 
                            reorient = True )
df = pd.DataFrame(table, columns = ['Data', 'Orientation', 'Comment'])
df
Data Orientation Comment
0 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
1 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
2 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
3 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
4 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
5 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
6 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
7 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
8 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI
9 /home/biraj/bids_parsing/dataset/anna/raw/sub-... RPI Reoriented to RAI

@birajstha birajstha self-assigned this Aug 16, 2024
@birajstha birajstha linked a pull request Aug 16, 2024 that will close this issue
8 tasks
@sgiavasis sgiavasis moved this from 🔖 Ready/Next to 🏗 In progress in C-PAC Development Sep 18, 2024
@birajstha birajstha linked a pull request Sep 20, 2024 that will close this issue
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 👀 In review
Development

Successfully merging a pull request may close this issue.

2 participants