diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index 114d29b4..850a729d 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -354,41 +354,7 @@ singularity: xfm_identity: resources/etc/identity_xfm.txt xfm_identity_itk: resources/etc/identity_xfm_itk.txt -#templates enabled for template-based segmentation are here # TODO: should also perhaps include modalities avaialble, and any custom crop_native_res settings -template_based_segmentation: - CITI168: - hemi: - - R - - L - dHCP: - hemi: - - R - - L - - MBMv2: - hemi: - - R - MBMv3: - hemi: - - R - CIVM: - hemi: - - R - - L - upenn: - hemi: - - R - ABAv3: - hemi: - - R - - L - bigbrain: - hemi: - - R - - L - - template_files: CITI168: T1w: T1w_head_700um.nii.gz @@ -399,6 +365,9 @@ template_files: Mask_crop: Mask_300umCoronalOblique_hemi-{hemi}.nii.gz dseg: sub-CITI168_hemi-{hemi}_space-cropT1w_desc-postproc_dseg.nii.gz coords: sub-CITI168_dir-{dir}_hemi-{hemi}_space-cropT1w_label-{autotop}_desc-laplace_coords.nii.gz + hemi_wildcards: + - L + - R dHCP: T1w: tpl-dHCP_cohort-1_res-1_T1w.nii.gz T2w: tpl-dHCP_cohort-1_res-1_T2w.nii.gz @@ -408,6 +377,10 @@ template_files: Mask_crop: tpl-dHCP_cohort-1_res-1_space-corobl_hemi-{hemi}_desc-hipp_mask.nii.gz dseg: tpl-dHCP_space-corobl_hemi-{hemi}_desc-tissuemanualseg_dseg.nii.gz coords: tpl-dHCP_dir-{dir}_hemi-{hemi}_space-corobl_label-{autotop}_desc-laplace_coords.nii.gz + hemi_wildcards: + - L + - R + MBMv2: T1w: Template_sym_MTR_80um.nii.gz T2w: Template_sym_T2_80um.nii.gz @@ -416,6 +389,9 @@ template_files: Mask_crop: tpl-MBMv2_hemi-R_space-corobl_desc-hipp_mask.nii.gz dseg: tpl-MBMv2_hemi-R_space-corobl_desc-tissuemanual_dseg.nii.gz coords: tpl-MBMv2_dir-{dir}_hemi-R_space-corobl_label-{autotop}_desc-laplace_coords.nii.gz + hemi_wildcards: + - R + MBMv3: T1w: tpl-MBMv3_T1w.nii.gz T2w: tpl-MBMv3_T2w.nii.gz @@ -424,6 +400,10 @@ template_files: Mask_crop: tpl-MBMv3_hemi-R_space-corobl_desc-hipp_mask.nii.gz dseg: tpl-MBMv3_hemi-R_space-corobl_desc-tissuemanual_dseg.nii.gz coords: tpl-MBMv3_dir-{dir}_hemi-R_space-corobl_label-{autotop}_desc-laplace_coords.nii.gz + hemi_wildcards: + - R + + CIVM: T1w: tpl-CIVM_T1w.nii.gz xfm_corobl: tpl-CIVM_from-native_to-corobl_type-itk_affine.txt @@ -431,10 +411,18 @@ template_files: Mask_crop: tpl-CIVM_hemi-{hemi}_space-corobl_desc-hipp_mask.nii.gz dseg: tpl-CIVM_hemi-{hemi}_space-corobl_desc-tissuemanual_dseg.nii.gz coords: tpl-CIVM_dir-{dir}_hemi-{hemi}_space-corobl_label-{autotop}_desc-laplace_coords.nii.gz + hemi_wildcards: + - L + - R + + upenn: T1w: tpl-upenn_desc-hipptissue_dseg.nii.gz dseg: tpl-upenn_desc-hipptissue_dseg.nii.gz coords: tpl-upenn_dir-{dir}_label-{autotop}_coords.nii.gz + hemi_wildcards: + - R + ABAv3: T1w: tpl-ABAv3_T1w.nii.gz xfm_corobl: tpl-ABAv3_from-native_to-corobl_type-itk_affine.txt @@ -442,6 +430,10 @@ template_files: Mask_crop: tpl-ABAv3_hemi-{hemi}_space-corobl_desc-tissuemanual_dseg.nii.gz dseg: tpl-ABAv3_hemi-{hemi}_space-corobl_desc-tissuemanual_dseg.nii.gz coords: tpl-ABAv3_dir-{dir}_hemi-{hemi}_space-corobl_label-{autotop}_desc-laplace_coords.nii.gz + hemi_wildcards: + - L + - R + bigbrain: T1w: tpl-bigbrain_1mm_merker.nii.gz T2w: tpl-bigbrain_1mm_merker.nii.gz @@ -450,6 +442,10 @@ template_files: Mask_crop: tpl-bigbrain_hemi-{hemi}_space-corobl_desc-tissuemanual_100um_dseg.nii.gz dseg: tpl-bigbrain_hemi-{hemi}_space-corobl_desc-tissuemanual_100um_dseg.nii.gz coords: tpl-bigbrain_dir-{dir}_hemi-{hemi}_space-corobl_label-{autotop}_desc-laplace_coords.nii.gz + hemi_wildcards: + - L + - R + atlas_files: diff --git a/hippunfold/workflow/rules/download.smk b/hippunfold/workflow/rules/download.smk index 2a60b38b..87b7df40 100644 --- a/hippunfold/workflow/rules/download.smk +++ b/hippunfold/workflow/rules/download.smk @@ -29,3 +29,134 @@ rule download_extract_template: shell: "wget https://{params.url} -O temp.zip && " " unzip -d {output.unzip_dir} temp.zip" + + +## unpack template +# this is used in both shape_inject.smk and templateseg.smk, so instead of having redundant rules I will simply apply them hemisphere +# Template-based segmentation supports templates that have only a single hemisphere +# by flipping it + + +def copy_or_flip(wildcards, file_to_process): + if ( + wildcards.hemi + in config["template_files"][config["inject_template"]]["hemi_wildcards"] + ): + cmd = f"cp {file_to_process}" + else: + cmd = f"c3d {file_to_process} -flip x -o" + return cmd + + +rule import_template_dseg: + input: + template_dir=Path(download_dir) / "template" / config["inject_template"], + params: + template_seg=lambda wildcards: Path(download_dir) + / "template" + / config["inject_template"] + / config["template_files"][config["inject_template"]]["dseg"].format( + **wildcards + ), + copy_or_flip_cmd=lambda wildcards: copy_or_flip( + wildcards, + Path(download_dir) + / "template" + / config["inject_template"] + / config["template_files"][config["inject_template"]]["dseg"].format( + **wildcards + ), + ), + output: + template_seg=bids( + root=work, + datatype="anat", + space="template", + **inputs.subj_wildcards, + desc="hipptissue", + hemi="{hemi}", + suffix="dseg.nii.gz" + ), + group: + "subj" + container: + config["singularity"]["autotop"] + shell: + "{params.copy_or_flip_cmd} {output.template_seg}" + + +rule import_template_coords: + input: + template_dir=Path(download_dir) / "template" / config["inject_template"], + params: + template_coords=lambda wildcards: Path(download_dir) + / "template" + / config["inject_template"] + / config["template_files"][config["inject_template"]]["coords"].format( + **wildcards + ), + copy_or_flip_cmd=lambda wildcards: copy_or_flip( + wildcards, + Path(download_dir) + / "template" + / config["inject_template"] + / config["template_files"][config["inject_template"]]["coords"].format( + **wildcards + ), + ), + output: + template_coords=bids( + root=work, + datatype="coords", + **inputs.subj_wildcards, + dir="{dir}", + label="{autotop}", + suffix="coords.nii.gz", + desc="init", + space="template", + hemi="{hemi}", + ), + group: + "subj" + container: + config["singularity"]["autotop"] + shell: + "{params.copy_or_flip_cmd} {output.template_coords}" + + +rule import_template_anat: + input: + template_dir=Path(download_dir) / "template" / config["inject_template"], + params: + template_anat=lambda wildcards: Path(download_dir) + / "template" + / config["inject_template"] + / config["template_files"][config["inject_template"]][ + get_modality_suffix(config["modality"]) + ].format(**wildcards), + copy_or_flip_cmd=lambda wildcards: copy_or_flip( + wildcards, + Path(download_dir) + / "template" + / config["inject_template"] + / config["template_files"][config["inject_template"]][ + get_modality_suffix(config["modality"]) + ].format(**wildcards), + ), + output: + template_anat=bids( + root=work, + datatype="anat", + space="template", + **inputs.subj_wildcards, + hemi="{hemi}", + suffix="{modality}.nii.gz".format( + modality=get_modality_suffix(config["modality"]) + ), + ), + group: + "subj" + container: + config["singularity"]["autotop"] + shell: + "{params.copy_or_flip_cmd} {output.template_anat}" diff --git a/hippunfold/workflow/rules/gifti.smk b/hippunfold/workflow/rules/gifti.smk index 8f26acca..91276efa 100644 --- a/hippunfold/workflow/rules/gifti.smk +++ b/hippunfold/workflow/rules/gifti.smk @@ -1,5 +1,5 @@ # lookup tables for structure: -hemi_to_structure = {"L": "CORTEX_LEFT", "Lflip": "CORTEX_LEFT", "R": "CORTEX_RIGHT"} +hemi_to_structure = {"L": "CORTEX_LEFT", "R": "CORTEX_RIGHT"} surf_to_secondary_type = { "midthickness": "MIDTHICKNESS", "inner": "PIAL", diff --git a/hippunfold/workflow/rules/nnunet.smk b/hippunfold/workflow/rules/nnunet.smk index 04f31515..92061012 100644 --- a/hippunfold/workflow/rules/nnunet.smk +++ b/hippunfold/workflow/rules/nnunet.smk @@ -133,7 +133,7 @@ rule run_inference: suffix="dseg.nii.gz", desc="nnunet", space="corobl", - hemi="{hemi,Lflip|R}" + hemi="{hemi}" ), log: bids( @@ -141,7 +141,7 @@ rule run_inference: **inputs.subj_wildcards, suffix="nnunet.txt", space="corobl", - hemi="{hemi,Lflip|R}" + hemi="{hemi}" ), shadow: "minimal" @@ -171,48 +171,6 @@ rule run_inference: "cp {params.temp_lbl} {output.nnunet_seg}" -rule unflip_nnunet_nii: - """Unflip the Lflip nnunet seg""" - input: - nnunet_seg=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="dseg.nii.gz", - desc="nnunet", - space="corobl", - hemi="{hemi}flip" - ), - unflip_ref=( - bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="{modality}.nii.gz".format(modality=config["modality"]), - space="corobl", - desc="preproc", - hemi="{hemi}", - ), - ), - output: - nnunet_seg=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="dseg.nii.gz", - desc="nnunet", - space="corobl", - hemi="{hemi,L}" - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input.nnunet_seg} -flip x -popas FLIPPED " - " {input.unflip_ref} -push FLIPPED -copy-transform -o {output.nnunet_seg} " - - def get_f3d_ref(wildcards, input): if config["modality"] == "T2w": nii = Path(input.template_dir) / config["template_files"][config["template"]][ diff --git a/hippunfold/workflow/rules/preproc_hippb500.smk b/hippunfold/workflow/rules/preproc_hippb500.smk index 1f07a2ee..51790936 100644 --- a/hippunfold/workflow/rules/preproc_hippb500.smk +++ b/hippunfold/workflow/rules/preproc_hippb500.smk @@ -35,33 +35,6 @@ rule resample_hippdwi_to_template: " -trim 0vox -o {output}" -rule lr_flip_b500: - input: - nii=bids( - root=work, - datatype="dwi", - **inputs.subj_wildcards, - suffix="b500.nii.gz", - space="corobl", - hemi="{hemi}" - ), - output: - nii=bids( - root=work, - datatype="dwi", - **inputs.subj_wildcards, - suffix="b500.nii.gz", - space="corobl", - hemi="{hemi,L}flip" - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input} -flip x -o {output}" - - rule cp_b500_to_anat_dir: input: nii=bids( diff --git a/hippunfold/workflow/rules/preproc_manualseg.smk b/hippunfold/workflow/rules/preproc_manualseg.smk index 23996799..94b60a4f 100644 --- a/hippunfold/workflow/rules/preproc_manualseg.smk +++ b/hippunfold/workflow/rules/preproc_manualseg.smk @@ -4,9 +4,10 @@ rule import_manualseg_to_corobl: in_img=partial(get_single_bids_input, component="manualseg"), template_dir=Path(download_dir) / "template" / config["template"], params: - std_to_cor=lambda wildcards: config["template_files"][config["template"]][ - "xfm_corobl" - ].format(**wildcards), + std_to_cor=lambda wildcards, input: Path(input.template_dir) + / config["template_files"][config["template"]]["xfm_corobl"].format( + **wildcards + ), ref=lambda wildcards, input: Path(input.template_dir) / config["template_files"][config["template"]]["crop_ref"].format(**wildcards), output: @@ -25,30 +26,3 @@ rule import_manualseg_to_corobl: shell: "ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS={threads} " "antsApplyTransforms -d 3 --interpolation MultiLabel -i {input.in_img} -o {output.nii} -r {params.ref} -t {params.std_to_cor}" - - -rule lr_flip_seg: - input: - nii=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="dseg.nii.gz", - space="corobl", - hemi="{hemi}" - ), - output: - nii=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="dseg.nii.gz", - space="corobl", - hemi="{hemi,L}flip" - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input} -flip x -o {output}" diff --git a/hippunfold/workflow/rules/preproc_t1.smk b/hippunfold/workflow/rules/preproc_t1.smk index 334f7fe8..68e657ea 100644 --- a/hippunfold/workflow/rules/preproc_t1.smk +++ b/hippunfold/workflow/rules/preproc_t1.smk @@ -102,32 +102,3 @@ rule warp_t1_to_corobl_crop: shell: "ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS={threads} " "antsApplyTransforms -d 3 --interpolation Linear -i {input.t1} -o {output.t1} -r {params.ref} -t {input.xfm}" - - -rule lr_flip_t1: - input: - nii=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="T1w.nii.gz", - space="corobl", - desc="{desc}", - hemi="{hemi}" - ), - output: - nii=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="T1w.nii.gz", - space="corobl", - desc="{desc}", - hemi="{hemi,L}flip" - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input} -flip x -o {output}" diff --git a/hippunfold/workflow/rules/preproc_t2.smk b/hippunfold/workflow/rules/preproc_t2.smk index 5b6b066a..728e4935 100644 --- a/hippunfold/workflow/rules/preproc_t2.smk +++ b/hippunfold/workflow/rules/preproc_t2.smk @@ -412,32 +412,3 @@ rule warp_t2_to_corobl_crop: shell: "ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS={threads} " "antsApplyTransforms -d 3 --interpolation Linear -i {input.nii} -o {output.nii} -r {params.ref} -t {input.xfm}" - - -rule lr_flip_t2: - input: - nii=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="T2w.nii.gz", - space="corobl", - desc="{desc}", - hemi="{hemi}" - ), - output: - nii=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix="T2w.nii.gz", - space="corobl", - desc="{desc}", - hemi="{hemi,L}flip" - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input} -flip x -o {output}" diff --git a/hippunfold/workflow/rules/shape_inject.smk b/hippunfold/workflow/rules/shape_inject.smk index 922493ad..4c921007 100644 --- a/hippunfold/workflow/rules/shape_inject.smk +++ b/hippunfold/workflow/rules/shape_inject.smk @@ -1,34 +1,5 @@ # Template-based segmentation supports templates that have only a single hemisphere -# by mapping it to the flipped version of the other hemisphere. -# If a template has both L and R files, then we set hemi_constrained_wildcard to L|R. -# If a hemisphere is missing data, then we set it to flip that, e.g. if L missing, then use Lflip|R - -hemi_constraints = [] -if config["template"] in config["template_based_segmentation"]: - for hemi in config["hemi"]: - if hemi in config["template_based_segmentation"][config["template"]]["hemi"]: - hemi_constraints.append(hemi) - else: - hemi_constraints.append(f"{hemi}flip") - -hemi_constrained_wildcard = "{{hemi,{constraints}}}".format( - constraints="|".join(hemi_constraints) -) - - -def flipped(wildcards): - """function to map hemi in wildcards from Lflip to R, or Rflip to L, - for use in rules where e.g. the output wildcard is Lflip, but for the input, R is desired, such as - when mapping a R hemi dseg to the Lflip hemisphere of a subject.""" - - if wildcards.hemi == "L" or wildcards.hemi == "R": - return wildcards - elif wildcards.hemi == "Lflip": - wildcards.hemi = "R" - return wildcards - elif wildcards.hemi == "Rflip": - wildcards.hemi = "L" - return wildcard +# by flipping it def get_input_for_shape_inject(wildcards): @@ -94,32 +65,6 @@ rule prep_segs_for_greedy: "c3d {input} -retain-labels {params.labels} -split -foreach -smooth {params.smoothing_stdev} -endfor -oo {output}/label_%02d.nii.gz" -rule import_template_shape: - input: - template_dir=Path(download_dir) / "template" / config["inject_template"], - params: - template_seg=lambda wildcards, input: Path(input.template_dir) - / config["template_files"][config["inject_template"]]["dseg"].format( - **flipped(wildcards) - ), - output: - template_seg=bids( - root=work, - datatype="anat", - space="template", - **inputs.subj_wildcards, - desc="hipptissue", - hemi=hemi_constrained_wildcard, - suffix="dseg.nii.gz" - ), - group: - "subj" - container: - config["singularity"]["autotop"] - shell: - "cp {params.template_seg} {output.template_seg}" - - def get_image_pairs(wildcards, input): """This rule requires snakemake 6.4.0, since it uses the new feature to execute if input files are not found""" @@ -193,7 +138,7 @@ rule template_shape_reg: to="subject", space="corobl", type_="ras", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), warp=bids( root=work, @@ -204,7 +149,7 @@ rule template_shape_reg: from_="template", to="subject", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), group: "subj" @@ -215,7 +160,7 @@ rule template_shape_reg: bids( root="logs", **inputs.subj_wildcards, - hemi=hemi_constrained_wildcard, + hemi="{hemi}", suffix="templateshapereg.txt" ), shell: @@ -269,14 +214,14 @@ rule template_shape_inject: suffix="dseg.nii.gz", desc="inject", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), log: bids( root="logs", **inputs.subj_wildcards, suffix="templateshapeinject.txt", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), group: "subj" @@ -313,12 +258,18 @@ rule inject_init_laplace_coords: space="corobl", hemi="{hemi}", ), - template_dir=Path(download_dir) / "template" / config["inject_template"], - params: - coords=lambda wildcards, input: Path(input.template_dir) - / config["template_files"][config["inject_template"]]["coords"].format( - **wildcards + coords=bids( + root=work, + datatype="coords", + **inputs.subj_wildcards, + dir="{dir}", + label="{autotop}", + suffix="coords.nii.gz", + desc="init", + space="template", + hemi="{hemi}" ), + params: interp_opt="-ri NN", output: init_coords=bids( @@ -330,7 +281,7 @@ rule inject_init_laplace_coords: suffix="coords.nii.gz", desc="init", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), log: bids( @@ -340,7 +291,7 @@ rule inject_init_laplace_coords: label="{autotop}", suffix="injectcoords.txt", desc="init", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), group: "subj" @@ -348,43 +299,7 @@ rule inject_init_laplace_coords: config["singularity"]["autotop"] threads: 8 shell: - "greedy -d 3 -threads {threads} {params.interp_opt} -rf {input.subject_seg} -rm {params.coords} {output.init_coords} -r {input.warp} {input.matrix} &> {log}" - - -rule unflip_init_coords: - """Unflip the Lflip init coords""" - input: - nnunet_seg=bids( - root=work, - datatype="coords", - **inputs.subj_wildcards, - dir="{dir}", - label="{autotop}", - suffix="coords.nii.gz", - desc="init", - space="corobl", - hemi="{hemi}flip" - ), - unflip_ref=get_input_for_shape_inject, - output: - nnunet_seg=bids( - root=work, - datatype="coords", - **inputs.subj_wildcards, - dir="{dir}", - label="{autotop}", - suffix="coords.nii.gz", - desc="init", - space="corobl", - hemi="{hemi,L|R}" - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input.nnunet_seg} -flip x -popas FLIPPED " - " {input.unflip_ref} -push FLIPPED -copy-transform -o {output.nnunet_seg} " + "greedy -d 3 -threads {threads} {params.interp_opt} -rf {input.subject_seg} -rm {input.coords} {output.init_coords} -r {input.warp} {input.matrix} &> {log}" rule reinsert_subject_labels: @@ -411,7 +326,7 @@ rule reinsert_subject_labels: suffix="dseg.nii.gz", desc="postproc", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), group: "subj" @@ -419,34 +334,3 @@ rule reinsert_subject_labels: config["singularity"]["autotop"] shell: "c3d {input.subject_seg} -retain-labels {params.labels} -popas LBL -push LBL -threshold 0 0 1 0 {input.inject_seg} -multiply -push LBL -add -o {output.postproc_seg}" - - -rule unflip_postproc: - input: - nii=bids( - root=work, - datatype="anat", - suffix="dseg.nii.gz", - desc="postproc", - space="corobl", - hemi="{hemi}flip", - **inputs.subj_wildcards - ), - unflip_ref=get_input_for_shape_inject, - output: - nii=bids( - root=work, - datatype="anat", - suffix="dseg.nii.gz", - desc="postproc", - space="corobl", - hemi="{hemi,L|R}", - **inputs.subj_wildcards - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input.nii} -flip x -popas FLIPPED " - " {input.unflip_ref} -push FLIPPED -copy-transform -o {output.nii} " diff --git a/hippunfold/workflow/rules/templateseg.smk b/hippunfold/workflow/rules/templateseg.smk index bbcbc4e9..cd7348c8 100644 --- a/hippunfold/workflow/rules/templateseg.smk +++ b/hippunfold/workflow/rules/templateseg.smk @@ -7,39 +7,6 @@ def get_smoothing_opt(wildcards): return f"-s {gradient_sigma}vox {warp_sigma}vox" -# Template-based segmentation supports templates that have only a single hemisphere -# by mapping it to the flipped version of the other hemisphere. -# If a template has both L and R files, then we set hemi_constrained_wildcard to L|R. -# If a hemisphere is missing data, then we set it to flip that, e.g. if L missing, then use Lflip|R - -hemi_constraints = [] -if config["template"] in config["template_based_segmentation"]: - for hemi in config["hemi"]: - if hemi in config["template_based_segmentation"][config["template"]]["hemi"]: - hemi_constraints.append(hemi) - else: - hemi_constraints.append(f"{hemi}flip") - -hemi_constrained_wildcard = "{{hemi,{constraints}}}".format( - constraints="|".join(hemi_constraints) -) - - -def flipped(wildcards): - """function to map hemi in wildcards from Lflip to R, or Rflip to L, - for use in rules where e.g. the output wildcard is Lflip, but for the input, R is desired, such as - when mapping a R hemi dseg to the Lflip hemisphere of a subject.""" - - if wildcards.hemi == "L" or wildcards.hemi == "R": - return wildcards - elif wildcards.hemi == "Lflip": - wildcards.hemi = "R" - return wildcards - elif wildcards.hemi == "Rflip": - wildcards.hemi = "L" - return wildcards - - rule template_reg: input: fixed_img=bids( @@ -53,12 +20,18 @@ rule template_reg: desc="preproc", hemi="{hemi}" ), + moving_img=bids( + root=work, + datatype="anat", + suffix="{modality}.nii.gz".format( + modality=get_modality_suffix(config["modality"]) + ), + space="template", + hemi="{hemi}", + **inputs.subj_wildcards + ), template_dir=Path(download_dir) / "template" / config["template"], params: - moving_img=lambda wildcards, input: Path(input.template_dir) - / config["template_files"][config["template"]][ - get_modality_suffix(config["modality"]) - ].format(**flipped(wildcards)), xfm_corobl=lambda wildcards, input: Path(input.template_dir) / config["template_files"][config["template"]]["xfm_corobl"].format( **wildcards @@ -76,7 +49,7 @@ rule template_reg: from_="template", to="subject", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}" ), group: "subj" @@ -86,7 +59,7 @@ rule template_reg: shell: "greedy -threads {threads} {params.general_opts} " " {params.smoothing_opts} {params.iteration_opts} " - " -i {input.fixed_img} {params.moving_img} -it {params.xfm_corobl} -o {output.warp}" + " -i {input.fixed_img} {input.moving_img} -it {params.xfm_corobl} -o {output.warp}" rule warp_template_dseg: @@ -111,12 +84,16 @@ rule warp_template_dseg: space="corobl", hemi="{hemi}" ), - template_dir=Path(download_dir) / "template" / config["template"], - params: - template_dseg=lambda wildcards, input: Path(input.template_dir) - / config["template_files"][config["template"]]["dseg"].format( - **flipped(wildcards) + template_dseg=bids( + root=work, + datatype="anat", + suffix="dseg.nii.gz", + desc="hipptissue", + space="template", + hemi="{hemi}", + **inputs.subj_wildcards ), + params: interp_opt="-ri LABEL 0.2vox", output: inject_seg=bids( @@ -126,7 +103,7 @@ rule warp_template_dseg: suffix="dseg.nii.gz", desc="postproc", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}" ), group: "subj" @@ -134,7 +111,7 @@ rule warp_template_dseg: config["singularity"]["autotop"] threads: 8 shell: - "greedy -d 3 -threads {threads} {params.interp_opt} -rf {input.ref} -rm {params.template_dseg} {output.inject_seg} -r {input.warp}" + "greedy -d 3 -threads {threads} {params.interp_opt} -rf {input.ref} -rm {input.template_dseg} {output.inject_seg} -r {input.warp}" rule warp_template_coords: @@ -160,12 +137,19 @@ rule warp_template_coords: space="corobl", hemi="{hemi}" ), + template_coords=bids( + root=work, + datatype="coords", + **inputs.subj_wildcards, + dir="{dir}", + label="{autotop}", + suffix="coords.nii.gz", + desc="init", + space="template", + hemi="{hemi}" + ), params: interp_opt="-ri NN", - template_coords=lambda wildcards, input: Path(input.template_dir) - / config["template_files"][config["template"]]["coords"].format( - **flipped(wildcards) - ), output: init_coords=bids( root=work, @@ -176,7 +160,7 @@ rule warp_template_coords: suffix="coords.nii.gz", desc="init", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}" ), group: "subj" @@ -184,7 +168,7 @@ rule warp_template_coords: config["singularity"]["autotop"] threads: 8 shell: - "greedy -d 3 -threads {threads} {params.interp_opt} -rf {input.ref} -rm {params.template_coords} {output.init_coords} -r {input.warp}" + "greedy -d 3 -threads {threads} {params.interp_opt} -rf {input.ref} -rm {input.template_coords} {output.init_coords} -r {input.warp}" rule warp_template_anat: @@ -209,12 +193,17 @@ rule warp_template_anat: space="corobl", hemi="{hemi}" ), - template_dir=Path(download_dir) / "template" / config["template"], - params: - template_anat=lambda wildcards, input: Path(input.template_dir) - / config["template_files"][config["template"]][config["modality"]].format( - **flipped(wildcards) + template_anat=bids( + root=work, + datatype="anat", + suffix="{modality}.nii.gz".format( + modality=get_modality_suffix(config["modality"]) + ), + space="template", + hemi="{hemi}", + **inputs.subj_wildcards ), + params: xfm_corobl=lambda wildcards, input: Path(input.template_dir) / config["template_files"][config["template"]]["xfm_corobl"].format( **wildcards @@ -227,7 +216,7 @@ rule warp_template_anat: suffix=f"{config['modality']}.nii.gz", desc="warpedtemplate", space="corobl", - hemi=hemi_constrained_wildcard, + hemi="{hemi}", ), group: "subj" @@ -236,85 +225,3 @@ rule warp_template_anat: threads: 8 shell: "greedy -d 3 -threads {threads} -rf {input.ref} -rm {params.template_anat} {output.warped} -r {input.warp} {params.xfm_corobl}" - - -rule unflip_template_dseg: - input: - nii=bids( - root=work, - datatype="anat", - suffix="dseg.nii.gz", - desc="postproc", - space="corobl", - hemi="{hemi}flip", - **inputs.subj_wildcards - ), - unflip_ref=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix=f"{config['modality']}.nii.gz", - space="corobl", - desc="preproc", - hemi="{hemi}", - ), - output: - nii=bids( - root=work, - datatype="anat", - suffix="dseg.nii.gz", - desc="postproc", - space="corobl", - hemi="{hemi,L|R}", - **inputs.subj_wildcards - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input.nii} -flip x -popas FLIPPED " - " {input.unflip_ref} -push FLIPPED -copy-transform -o {output.nii} " - - -rule unflip_template_coords: - input: - nii=bids( - root=work, - datatype="coords", - **inputs.subj_wildcards, - dir="{dir}", - label="{autotop}", - suffix="coords.nii.gz", - desc="init", - space="corobl", - hemi="{hemi}flip" - ), - unflip_ref=bids( - root=work, - datatype="anat", - **inputs.subj_wildcards, - suffix=f"{config['modality']}.nii.gz", - space="corobl", - desc="preproc", - hemi="{hemi}", - ), - output: - nii=bids( - root=work, - datatype="coords", - **inputs.subj_wildcards, - dir="{dir}", - label="{autotop}", - suffix="coords.nii.gz", - desc="init", - space="corobl", - hemi="{hemi,L|R}", - ), - container: - config["singularity"]["autotop"] - group: - "subj" - shell: - "c3d {input.nii} -flip x -popas FLIPPED " - " {input.unflip_ref} -push FLIPPED -copy-transform -o {output.nii} "