FCP-INDI / C-PAC

Configurable Pipeline for the Analysis of Connectomes
https://fcp-indi.github.io/
GNU Lesser General Public License v3.0
62 stars 40 forks source link

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

Open sgiavasis opened 1 month ago

sgiavasis commented 1 month ago

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:

Proposed feature

Either:

Acceptance criteria

Alternatives

No response

Additional context

No response

birajstha commented 1 month ago

@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