From e76d26b53d2142a070d90e5053f180b0cdce1a22 Mon Sep 17 00:00:00 2001 From: Steven Meisler Date: Tue, 24 Sep 2024 13:54:25 -0400 Subject: [PATCH 1/6] start ukb fixing --- ingress2qsirecon/cli/main.py | 2 +- ingress2qsirecon/utils/functions.py | 21 ++++++++++++++++----- ingress2qsirecon/utils/workflows.py | 11 ++++++++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/ingress2qsirecon/cli/main.py b/ingress2qsirecon/cli/main.py index c7a660f..c4985d4 100644 --- a/ingress2qsirecon/cli/main.py +++ b/ingress2qsirecon/cli/main.py @@ -56,7 +56,7 @@ def _ingress2qsirecon(**kwargs): layouts = create_layout(input_dir, output_dir, input_pipeline, participant_label) # Create and run overall workflow, which will be broken down to single subject workflows - ingress2qsirecon_wf = create_ingress2qsirecon_wf(layouts, base_dir=work_dir, skip_mni2009c_norm=skip_mni2009c_norm) + ingress2qsirecon_wf = create_ingress2qsirecon_wf(layouts, input_pipeline,base_dir=work_dir, skip_mni2009c_norm=skip_mni2009c_norm) ingress2qsirecon_wf.run() diff --git a/ingress2qsirecon/utils/functions.py b/ingress2qsirecon/utils/functions.py index 93a0ee5..ff8e468 100644 --- a/ingress2qsirecon/utils/functions.py +++ b/ingress2qsirecon/utils/functions.py @@ -124,22 +124,32 @@ def make_bids_file_paths(subject_layout: dict) -> dict: } # Now for optional files - if subject_layout['t1w_brain']: + if 't1w_brain' in subject_layout: bids_t1w_brain = os.path.join(bids_base, "anat", sub_session_string + "_desc-preproc_T1w.nii.gz") bids_file_paths.update({"bids_t1w_brain": Path(bids_t1w_brain)}) - if subject_layout['brain_mask']: + if "brain_mask" in subject_layout: bids_brain_mask = os.path.join(bids_base, "anat", sub_session_string + "_desc-brain_mask.nii.gz") bids_file_paths.update({"bids_brain_mask": Path(bids_brain_mask)}) - if subject_layout['subject2MNI']: + if "subject2MNI" in subject_layout: bids_subject2MNI = os.path.join( bids_base, "anat", sub_session_string + f"_from-T1w_to-{mni_template}_mode-image_xfm.h5" ) bids_file_paths.update({"bids_subject2MNI": Path(bids_subject2MNI)}) - if subject_layout['MNI2subject']: + else: + bids_subject2MNI = os.path.join( + bids_base, "anat", sub_session_string + f"_from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5" + ) + bids_file_paths.update({"bids_subject2MNI": Path(bids_subject2MNI)}) + if "MNI2subject" in subject_layout: bids_MNI2subject = os.path.join( bids_base, "anat", sub_session_string + f"_from-{mni_template}_to-T1w_mode-image_xfm.h5" ) bids_file_paths.update({"bids_MNI2subject": Path(bids_MNI2subject)}) + else: + bids_MNI2subject = os.path.join( + bids_base, "anat", sub_session_string + f"_from-MNI152NLin2009cAsym_to-T1w_mode-image_xfm.h5" + ) + bids_file_paths.update({"bids_MNI2subject": Path(bids_MNI2subject)}) return bids_file_paths @@ -204,6 +214,7 @@ def create_layout(input_dir: Path, output_dir: Path, input_pipeline: str, partic continue subject_layout = { + "original_name": potential_dir.name, "subject": subject, "session": renamed_ses, "path": Path(potential_dir), @@ -221,7 +232,7 @@ def create_layout(input_dir: Path, output_dir: Path, input_pipeline: str, partic layout = sorted(layout, key=lambda x: x["subject"]) # Raise warnings for requested subjects not in layout - missing_particpants = sorted(set(participant_label) - set([subject["subject"] for subject in layout])) + missing_particpants = sorted(set(participant_label) - set([subject["original_name"] for subject in layout])) if missing_particpants: warn( f"Requested participant(s) {missing_particpants} not found in layout, please confirm their data exists and are properly organized." diff --git a/ingress2qsirecon/utils/workflows.py b/ingress2qsirecon/utils/workflows.py index 081e36f..ad7865a 100644 --- a/ingress2qsirecon/utils/workflows.py +++ b/ingress2qsirecon/utils/workflows.py @@ -26,7 +26,7 @@ def parse_layout(subject_layout): return tuple(subject_layout.values()) -def create_single_subject_wf(subject_layout, skip_mni2009c_norm=False): +def create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm=False): """ Create a nipype workflow to ingest a single subject. @@ -140,6 +140,8 @@ def create_single_subject_wf(subject_layout, skip_mni2009c_norm=False): (parse_layout_node, create_bfile_node, [("bids_b", "b_file_out")]), ] ) + #if input_pipeline == "ukb": + # conform_dwi_node.inputs.orientation = "LAS" # Create nodes to conform anatomicals and save to BIDS layout # TMP If false because does not work yet @@ -333,7 +335,7 @@ def save_xfm_outputs( return wf -def create_ingress2qsirecon_wf(layouts, name="ingress2qsirecon_wf", base_dir=os.getcwd(), skip_mni2009c_norm=False): +def create_ingress2qsirecon_wf(layouts, input_pipeline, name="ingress2qsirecon_wf", base_dir=os.getcwd(), skip_mni2009c_norm=False): """ Creates the overall ingress2qsirecon workflow. @@ -342,6 +344,9 @@ def create_ingress2qsirecon_wf(layouts, name="ingress2qsirecon_wf", base_dir=os. layouts : list of dict A list of dictionaries, one per subject, from the create_layout function. + input_pipeline : str + The name of the input pipeline (e.g. 'hcpya', 'ukb') + name : str, optional The name of the workflow. Default is "ingress2qsirecon_wf". @@ -361,7 +366,7 @@ def create_ingress2qsirecon_wf(layouts, name="ingress2qsirecon_wf", base_dir=os. print(f"Subject(s) to run: {subjects_to_run}") for subject_layout in layouts: - single_subject_wf = create_single_subject_wf(subject_layout, skip_mni2009c_norm=skip_mni2009c_norm) + single_subject_wf = create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm=skip_mni2009c_norm) wf.add_nodes([single_subject_wf]) return wf From 3b2ed90e0b3530e726c2337326c5504d6cbf9648 Mon Sep 17 00:00:00 2001 From: Steven Meisler Date: Thu, 26 Sep 2024 11:42:22 -0400 Subject: [PATCH 2/6] add oblique checks and names --- ingress2qsirecon/cli/main.py | 4 ++- ingress2qsirecon/utils/functions.py | 53 +++++++++++++++++++++++----- ingress2qsirecon/utils/interfaces.py | 1 + ingress2qsirecon/utils/workflows.py | 18 +++++++--- 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/ingress2qsirecon/cli/main.py b/ingress2qsirecon/cli/main.py index c4985d4..9e2a857 100644 --- a/ingress2qsirecon/cli/main.py +++ b/ingress2qsirecon/cli/main.py @@ -56,7 +56,9 @@ def _ingress2qsirecon(**kwargs): layouts = create_layout(input_dir, output_dir, input_pipeline, participant_label) # Create and run overall workflow, which will be broken down to single subject workflows - ingress2qsirecon_wf = create_ingress2qsirecon_wf(layouts, input_pipeline,base_dir=work_dir, skip_mni2009c_norm=skip_mni2009c_norm) + ingress2qsirecon_wf = create_ingress2qsirecon_wf( + layouts, input_pipeline, base_dir=work_dir, skip_mni2009c_norm=skip_mni2009c_norm + ) ingress2qsirecon_wf.run() diff --git a/ingress2qsirecon/utils/functions.py b/ingress2qsirecon/utils/functions.py index ff8e468..72db869 100644 --- a/ingress2qsirecon/utils/functions.py +++ b/ingress2qsirecon/utils/functions.py @@ -37,7 +37,7 @@ "bvals": ["DTI", "dMRI", "dMRI", "bvals"], "bvecs": ["DTI", "dMRI", "dMRI", "bvecs"], "dwi": ["DTI", "dMRI", "dMRI", "data_ud.nii.gz"], - "dwiref": ["DTI", "dMRI", "dMRI", "dti_FA.nii.gz"], + # "dwiref": ["DTI", "dMRI", "dMRI", "dti_FA.nii.gz"], "t1w_brain": ["T1", "T1_unbiased_brain.nii.gz"], "brain_mask": ["T1", "T1_brain_mask.nii.gz"], # TODO: Add UKB XFM path @@ -97,6 +97,9 @@ def make_bids_file_paths(subject_layout: dict) -> dict: bids_file_paths : :obj:`dict` A dictionary of BIDS-ified file paths. """ + import nibabel as nb + import numpy as np + bids_base = str(subject_layout["bids_base"]) subject = str(subject_layout["subject"]) session = subject_layout["session"] @@ -106,13 +109,33 @@ def make_bids_file_paths(subject_layout: dict) -> dict: sub_session_string = f"sub-{subject}_ses-{session}" mni_template = str(subject_layout["MNI_template"]) + # Check for DWI obliquity + dwi_img = nb.load(subject_layout["dwi"]) + dwi_obliquity = np.any(nb.affines.obliquity(dwi_img.affine) > 1e-4) + if dwi_obliquity: + dwi_oblique_string = "_acq-VARIANTOBLIQUE" + else: + dwi_oblique_string = "" + # BIDS-ify required files - bids_dwi_file = os.path.join(bids_base, "dwi", sub_session_string + "_space-T1w_desc-preproc_dwi.nii.gz") - bids_bval_file = os.path.join(bids_base, "dwi", sub_session_string + "_space-T1w_desc-preproc_dwi.bval") - bids_bvec_file = os.path.join(bids_base, "dwi", sub_session_string + "_space-T1w_desc-preproc_dwi.bvec") - bids_b_file = os.path.join(bids_base, "dwi", sub_session_string + "_space-T1w_desc-preproc_dwi.b") - bids_bmtxt_file = os.path.join(bids_base, "dwi", sub_session_string + "_space-T1w_desc-preproc_dwi.bmtxt") - bids_dwiref_file = os.path.join(bids_base, "dwi", sub_session_string + "_space-T1w_dwiref.nii.gz") + bids_dwi_file = os.path.join( + bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.nii.gz" + ) + bids_bval_file = os.path.join( + bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bval" + ) + bids_bvec_file = os.path.join( + bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bvec" + ) + bids_b_file = os.path.join( + bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.b" + ) + bids_bmtxt_file = os.path.join( + bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bmtxt" + ) + bids_dwiref_file = os.path.join( + bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_dwiref.nii.gz" + ) bids_file_paths = { "bids_dwi": Path(bids_dwi_file), @@ -125,10 +148,22 @@ def make_bids_file_paths(subject_layout: dict) -> dict: # Now for optional files if 't1w_brain' in subject_layout: - bids_t1w_brain = os.path.join(bids_base, "anat", sub_session_string + "_desc-preproc_T1w.nii.gz") + # Check for T1w obliquity + t1_img = nb.load(subject_layout["t1w_brain"]) + t1_obliquity = np.any(nb.affines.obliquity(t1_img.affine) > 1e-4) + if t1_obliquity: + t1_oblique_string = "_acq-VARIANTOBLIQUE" + else: + t1_oblique_string = "" + + bids_t1w_brain = os.path.join( + bids_base, "anat", sub_session_string + t1_oblique_string + "_desc-preproc_T1w.nii.gz" + ) bids_file_paths.update({"bids_t1w_brain": Path(bids_t1w_brain)}) if "brain_mask" in subject_layout: - bids_brain_mask = os.path.join(bids_base, "anat", sub_session_string + "_desc-brain_mask.nii.gz") + bids_brain_mask = os.path.join( + bids_base, "anat", sub_session_string + t1_oblique_string + "_desc-brain_mask.nii.gz" + ) bids_file_paths.update({"bids_brain_mask": Path(bids_brain_mask)}) if "subject2MNI" in subject_layout: bids_subject2MNI = os.path.join( diff --git a/ingress2qsirecon/utils/interfaces.py b/ingress2qsirecon/utils/interfaces.py index 0494ecd..4443135 100644 --- a/ingress2qsirecon/utils/interfaces.py +++ b/ingress2qsirecon/utils/interfaces.py @@ -252,6 +252,7 @@ def _run_interface(self, runtime): else: LOGGER.info("Not applying reorientation to %s: already in %s", dwi_in_file, orientation) + input_img.to_filename(dwi_out_file) self._results["dwi_out_file"] = dwi_out_file # Copy and rename bvecs if not os.path.exists(bvec_out_file): diff --git a/ingress2qsirecon/utils/workflows.py b/ingress2qsirecon/utils/workflows.py index ad7865a..5f3cb54 100644 --- a/ingress2qsirecon/utils/workflows.py +++ b/ingress2qsirecon/utils/workflows.py @@ -3,6 +3,7 @@ """ import os +import shutil from pathlib import Path from nipype.pipeline.engine import Workflow @@ -57,6 +58,9 @@ def create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm= A nipype workflow that operates on a single subject. """ #### WHY DO I HAVE TO REIMPORT THIS STUFF?? + + import nibabel as nb + import numpy as np from nipype import ( Node, Workflow, @@ -140,14 +144,14 @@ def create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm= (parse_layout_node, create_bfile_node, [("bids_b", "b_file_out")]), ] ) - #if input_pipeline == "ukb": + # if input_pipeline == "ukb": # conform_dwi_node.inputs.orientation = "LAS" # Create nodes to conform anatomicals and save to BIDS layout - # TMP If false because does not work yet if "t1w_brain" in subject_layout.keys(): template_dimensions_node = Node(TemplateDimensions(), name="template_dimensions") conform_t1w_node = Node(Conform(), name="conform_t1w") + wf.connect( [ ( @@ -196,6 +200,8 @@ def create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm= ) ] ) + else: + shutil.copy(subject_layout["dwiref"], subject_layout["bids_dwiref"]) # Convert FNIRT nii warps to ITK nii, then ITK nii to ITK H5 # Start with subject2MNI @@ -335,7 +341,9 @@ def save_xfm_outputs( return wf -def create_ingress2qsirecon_wf(layouts, input_pipeline, name="ingress2qsirecon_wf", base_dir=os.getcwd(), skip_mni2009c_norm=False): +def create_ingress2qsirecon_wf( + layouts, input_pipeline, name="ingress2qsirecon_wf", base_dir=os.getcwd(), skip_mni2009c_norm=False +): """ Creates the overall ingress2qsirecon workflow. @@ -366,7 +374,9 @@ def create_ingress2qsirecon_wf(layouts, input_pipeline, name="ingress2qsirecon_w print(f"Subject(s) to run: {subjects_to_run}") for subject_layout in layouts: - single_subject_wf = create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm=skip_mni2009c_norm) + single_subject_wf = create_single_subject_wf( + subject_layout, input_pipeline, skip_mni2009c_norm=skip_mni2009c_norm + ) wf.add_nodes([single_subject_wf]) return wf From b0c2a48d03612d801419f40850d086efee3e82d4 Mon Sep 17 00:00:00 2001 From: Steven Meisler Date: Thu, 26 Sep 2024 18:22:55 -0400 Subject: [PATCH 3/6] Fix ukb anat outputs --- ingress2qsirecon/utils/functions.py | 30 +++++++++++++++-------------- ingress2qsirecon/utils/workflows.py | 8 ++++++-- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/ingress2qsirecon/utils/functions.py b/ingress2qsirecon/utils/functions.py index 72db869..3d19d83 100644 --- a/ingress2qsirecon/utils/functions.py +++ b/ingress2qsirecon/utils/functions.py @@ -105,8 +105,10 @@ def make_bids_file_paths(subject_layout: dict) -> dict: session = subject_layout["session"] if session == None: sub_session_string = f"sub-{subject}" + bids_base_session = bids_base, "func" else: sub_session_string = f"sub-{subject}_ses-{session}" + bids_base_session = os.path.join(bids_base, f"ses-{session}") mni_template = str(subject_layout["MNI_template"]) # Check for DWI obliquity @@ -119,22 +121,22 @@ def make_bids_file_paths(subject_layout: dict) -> dict: # BIDS-ify required files bids_dwi_file = os.path.join( - bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.nii.gz" + bids_base_session, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.nii.gz" ) bids_bval_file = os.path.join( - bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bval" + bids_base_session, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bval" ) bids_bvec_file = os.path.join( - bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bvec" + bids_base_session, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bvec" ) bids_b_file = os.path.join( - bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.b" + bids_base_session, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.b" ) bids_bmtxt_file = os.path.join( - bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bmtxt" + bids_base_session, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_desc-preproc_dwi.bmtxt" ) bids_dwiref_file = os.path.join( - bids_base, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_dwiref.nii.gz" + bids_base_session, "dwi", sub_session_string + dwi_oblique_string + "_space-T1w_dwiref.nii.gz" ) bids_file_paths = { @@ -157,32 +159,32 @@ def make_bids_file_paths(subject_layout: dict) -> dict: t1_oblique_string = "" bids_t1w_brain = os.path.join( - bids_base, "anat", sub_session_string + t1_oblique_string + "_desc-preproc_T1w.nii.gz" + bids_base, "anat", f"sub-{subject}" + t1_oblique_string + "_desc-preproc_T1w.nii.gz" ) bids_file_paths.update({"bids_t1w_brain": Path(bids_t1w_brain)}) if "brain_mask" in subject_layout: bids_brain_mask = os.path.join( - bids_base, "anat", sub_session_string + t1_oblique_string + "_desc-brain_mask.nii.gz" + bids_base, "anat", f"sub-{subject}" + t1_oblique_string + "_desc-brain_mask.nii.gz" ) bids_file_paths.update({"bids_brain_mask": Path(bids_brain_mask)}) if "subject2MNI" in subject_layout: bids_subject2MNI = os.path.join( - bids_base, "anat", sub_session_string + f"_from-T1w_to-{mni_template}_mode-image_xfm.h5" + bids_base, "anat", f"sub-{subject}" + f"_from-T1w_to-{mni_template}_mode-image_xfm.h5" ) bids_file_paths.update({"bids_subject2MNI": Path(bids_subject2MNI)}) else: bids_subject2MNI = os.path.join( - bids_base, "anat", sub_session_string + f"_from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5" + bids_base, "anat", f"sub-{subject}" + f"_from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5" ) bids_file_paths.update({"bids_subject2MNI": Path(bids_subject2MNI)}) if "MNI2subject" in subject_layout: bids_MNI2subject = os.path.join( - bids_base, "anat", sub_session_string + f"_from-{mni_template}_to-T1w_mode-image_xfm.h5" + bids_base, "anat", f"sub-{subject}" + f"_from-{mni_template}_to-T1w_mode-image_xfm.h5" ) bids_file_paths.update({"bids_MNI2subject": Path(bids_MNI2subject)}) else: bids_MNI2subject = os.path.join( - bids_base, "anat", sub_session_string + f"_from-MNI152NLin2009cAsym_to-T1w_mode-image_xfm.h5" + bids_base, "anat", f"sub-{subject}" + f"_from-MNI152NLin2009cAsym_to-T1w_mode-image_xfm.h5" ) bids_file_paths.update({"bids_MNI2subject": Path(bids_MNI2subject)}) @@ -231,8 +233,8 @@ def create_layout(input_dir: Path, output_dir: Path, input_pipeline: str, partic # Make BIDS base organization bids_base = output_dir / f"sub-{subject}" - if renamed_ses: - bids_base = bids_base / f"ses-{renamed_ses}" + # if renamed_ses: + # bids_base = bids_base / f"ses-{renamed_ses}" file_paths = get_file_paths(potential_dir, input_pipeline) # check if any required files do not exist diff --git a/ingress2qsirecon/utils/workflows.py b/ingress2qsirecon/utils/workflows.py index 5f3cb54..6ea4d9b 100644 --- a/ingress2qsirecon/utils/workflows.py +++ b/ingress2qsirecon/utils/workflows.py @@ -79,8 +79,12 @@ def create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm= # Make BIDS subject output folder bids_base = subject_layout['bids_base'] if not os.path.exists(bids_base): - os.makedirs(Path(bids_base / "anat").resolve()) - os.makedirs(Path(bids_base / "dwi").resolve()) + os.makedirs(Path(bids_base / "anat").resolve(), exist_ok=True) + session = subject_layout['session'] + if session == None: + os.makedirs(Path(bids_base / "dwi").resolve(), exist_ok=True) + else: + os.makedirs(Path(bids_base / f"ses-{session}" / "dwi").resolve(), exist_ok=True) # Create single subject workflow wf_name = f"ingress2qsirecon_single_subject_{subject_name}_wf" From 08bcc809e0ade607e2f8a693a03b3e42f95a601f Mon Sep 17 00:00:00 2001 From: Steven Meisler Date: Thu, 24 Oct 2024 14:07:01 -0400 Subject: [PATCH 4/6] fix HCP output organization --- ingress2qsirecon/utils/functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ingress2qsirecon/utils/functions.py b/ingress2qsirecon/utils/functions.py index 3d19d83..bc83263 100644 --- a/ingress2qsirecon/utils/functions.py +++ b/ingress2qsirecon/utils/functions.py @@ -105,7 +105,7 @@ def make_bids_file_paths(subject_layout: dict) -> dict: session = subject_layout["session"] if session == None: sub_session_string = f"sub-{subject}" - bids_base_session = bids_base, "func" + bids_base_session = bids_base else: sub_session_string = f"sub-{subject}_ses-{session}" bids_base_session = os.path.join(bids_base, f"ses-{session}") From b36cc55e4a44d756df72db808858595dbf564996 Mon Sep 17 00:00:00 2001 From: Steven Meisler Date: Thu, 24 Oct 2024 14:08:47 -0400 Subject: [PATCH 5/6] reversion --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 662a092..0f9c39e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "Ingress2QSIRecon" -version = "0.2.1" +version = "0.2.2rc0" description = "Tool to ingress data from other pipelines for use in QSIRecon" authors = ["Steven Meisler "] readme = "README.md" From 8131af2f69e5d157ac0fe45c3deead226d78d4fe Mon Sep 17 00:00:00 2001 From: Steven Meisler Date: Wed, 13 Nov 2024 14:13:47 -0500 Subject: [PATCH 6/6] fix Variant naming, remove ConvertWarpfield --- ingress2qsirecon/utils/functions.py | 4 +- ingress2qsirecon/utils/workflows.py | 103 ++++++++++++++-------------- pyproject.toml | 2 +- 3 files changed, 55 insertions(+), 54 deletions(-) diff --git a/ingress2qsirecon/utils/functions.py b/ingress2qsirecon/utils/functions.py index bc83263..b780c6b 100644 --- a/ingress2qsirecon/utils/functions.py +++ b/ingress2qsirecon/utils/functions.py @@ -115,7 +115,7 @@ def make_bids_file_paths(subject_layout: dict) -> dict: dwi_img = nb.load(subject_layout["dwi"]) dwi_obliquity = np.any(nb.affines.obliquity(dwi_img.affine) > 1e-4) if dwi_obliquity: - dwi_oblique_string = "_acq-VARIANTOBLIQUE" + dwi_oblique_string = "_acq-VARIANTOblique" else: dwi_oblique_string = "" @@ -154,7 +154,7 @@ def make_bids_file_paths(subject_layout: dict) -> dict: t1_img = nb.load(subject_layout["t1w_brain"]) t1_obliquity = np.any(nb.affines.obliquity(t1_img.affine) > 1e-4) if t1_obliquity: - t1_oblique_string = "_acq-VARIANTOBLIQUE" + t1_oblique_string = "_acq-VARIANTOblique" else: t1_oblique_string = "" diff --git a/ingress2qsirecon/utils/workflows.py b/ingress2qsirecon/utils/workflows.py index 6ea4d9b..fd49fbf 100644 --- a/ingress2qsirecon/utils/workflows.py +++ b/ingress2qsirecon/utils/workflows.py @@ -209,58 +209,59 @@ def create_single_subject_wf(subject_layout, input_pipeline, skip_mni2009c_norm= # Convert FNIRT nii warps to ITK nii, then ITK nii to ITK H5 # Start with subject2MNI - if "subject2MNI" in subject_layout.keys(): - convert_warpfield_node_subject2MNI = Node(ConvertWarpfield(), name="convert_warpfield_subject2MNI") - convert_warpfield_node_subject2MNI.inputs.itk_out_xfm = str(subject_layout["bids_subject2MNI"]).replace( - ".h5", ".nii.gz" - ) - nii_to_h5_node_subject2MNI = Node(NIFTItoH5(), name="nii_to_h5_subject2MNI") - wf.connect( - [ - ( - parse_layout_node, - convert_warpfield_node_subject2MNI, - [("subject2MNI", "fnirt_in_xfm"), ("MNI_ref", "fnirt_ref_file")], - ), - ( - convert_warpfield_node_subject2MNI, - nii_to_h5_node_subject2MNI, - [("itk_out_xfm", "xfm_nifti_in")], - ), - ( - parse_layout_node, - nii_to_h5_node_subject2MNI, - [("bids_subject2MNI", "xfm_h5_out")], - ), - ] - ) + if False: # We're going to skip this because it doesn't work great, remove workbench dependency + if "subject2MNI" in subject_layout.keys(): + convert_warpfield_node_subject2MNI = Node(ConvertWarpfield(), name="convert_warpfield_subject2MNI") + convert_warpfield_node_subject2MNI.inputs.itk_out_xfm = str(subject_layout["bids_subject2MNI"]).replace( + ".h5", ".nii.gz" + ) + nii_to_h5_node_subject2MNI = Node(NIFTItoH5(), name="nii_to_h5_subject2MNI") + wf.connect( + [ + ( + parse_layout_node, + convert_warpfield_node_subject2MNI, + [("subject2MNI", "fnirt_in_xfm"), ("MNI_ref", "fnirt_ref_file")], + ), + ( + convert_warpfield_node_subject2MNI, + nii_to_h5_node_subject2MNI, + [("itk_out_xfm", "xfm_nifti_in")], + ), + ( + parse_layout_node, + nii_to_h5_node_subject2MNI, + [("bids_subject2MNI", "xfm_h5_out")], + ), + ] + ) - # Then MNI2Subject - if "MNI2subject" in subject_layout.keys(): - convert_warpfield_node_MNI2subject = Node(ConvertWarpfield(), name="convert_warpfield_MNI2subject") - convert_warpfield_node_MNI2subject.inputs.itk_out_xfm = str(subject_layout["bids_MNI2subject"]).replace( - ".h5", ".nii.gz" - ) - nii_to_h5_node_MNI2subject = Node(NIFTItoH5(), name="nii_to_h5_MNI2subject") - wf.connect( - [ - ( - parse_layout_node, - convert_warpfield_node_MNI2subject, - [("MNI2subject", "fnirt_in_xfm"), ("MNI_ref", "fnirt_ref_file")], - ), - ( - convert_warpfield_node_MNI2subject, - nii_to_h5_node_MNI2subject, - [("itk_out_xfm", "xfm_nifti_in")], - ), - ( - parse_layout_node, - nii_to_h5_node_MNI2subject, - [("bids_MNI2subject", "xfm_h5_out")], - ), - ] - ) + # Then MNI2Subject + if "MNI2subject" in subject_layout.keys(): + convert_warpfield_node_MNI2subject = Node(ConvertWarpfield(), name="convert_warpfield_MNI2subject") + convert_warpfield_node_MNI2subject.inputs.itk_out_xfm = str(subject_layout["bids_MNI2subject"]).replace( + ".h5", ".nii.gz" + ) + nii_to_h5_node_MNI2subject = Node(NIFTItoH5(), name="nii_to_h5_MNI2subject") + wf.connect( + [ + ( + parse_layout_node, + convert_warpfield_node_MNI2subject, + [("MNI2subject", "fnirt_in_xfm"), ("MNI_ref", "fnirt_ref_file")], + ), + ( + convert_warpfield_node_MNI2subject, + nii_to_h5_node_MNI2subject, + [("itk_out_xfm", "xfm_nifti_in")], + ), + ( + parse_layout_node, + nii_to_h5_node_MNI2subject, + [("bids_MNI2subject", "xfm_h5_out")], + ), + ] + ) # Now get transform to MNI2009cAsym MNI_template = subject_layout["MNI_template"] diff --git a/pyproject.toml b/pyproject.toml index 0f9c39e..9119ead 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "Ingress2QSIRecon" -version = "0.2.2rc0" +version = "0.2.2" description = "Tool to ingress data from other pipelines for use in QSIRecon" authors = ["Steven Meisler "] readme = "README.md"