Skip to content

Commit

Permalink
simplified use of manual segmetation (#325)
Browse files Browse the repository at this point in the history
* removed segT*w

* cropseg to manualseg

* Port v1.5.2 bugfixes into dev-v2.0.0 (#329) (#331)

* fix for using T1T2w model

run_inference was only accepting a single input image, this makes it
accept a list of images too, and makes it so --force-nnunet-model T1T2w grabs both T1w and T2w as inputs.

* hipp curvature was being used always, instead of wildcard

this didn't affect any workflow computations, just the subsequent
dscalar.nii and spec file that would have the wrong curvature map

* fix logical error

* Bump version to 1.5.2-pre.1

* Bump version to 1.5.2-pre.2

* keep pipeline_description changes

---------

Co-authored-by: Ali Khan <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* minor bugfix for passing modality

* lint

* cleaned more instances of segTxw

* lint

* removed unneeded def

---------

Co-authored-by: Jordan DeKraker <[email protected]>
Co-authored-by: Ali Khan <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Dec 17, 2024
1 parent 566b4b2 commit f642963
Show file tree
Hide file tree
Showing 18 changed files with 75 additions and 209 deletions.
5 changes: 2 additions & 3 deletions .dryrun_test_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ hippunfold test_data/bids_T1w test_out participant -np --modality T1w
hippunfold test_data/bids_hippb500 test_out participant -np --modality hippb500
hippunfold test_data/bids_T1w_longitudinal test_out participant -np --modality T1w
hippunfold test_data/bids_singleT2w_longitudinal test_out participant -np --modality T2w
hippunfold test_data/bids_segT2w test_out participant -np --modality segT2w
hippunfold . test_out participant -np --modality cropseg --path_cropseg test_data/data_cropseg/sub-{subject}_hemi-{hemi}_dseg.nii.gz
hippunfold . test_out participant -np --modality cropseg --path_cropseg test_data/data_cropseg_1hemi/sub-{subject}_hemi-{hemi}_dseg.nii.gz --hemi L
hippunfold test_data/bids_manualseg test_out participant -np --modality manualseg --path_manualseg test_data/bids_manualseg/sub-{subject}_hemi-{hemi}_dseg.nii.gz
hippunfold test_data/bids_manualseg_1hemi test_out participant -np --modality manualseg --hemi L
hippunfold test_data/bids_singleT2w test_out participant -np --modality T2w --t1_reg_template
hippunfold test_data/bids_singleT2w test_out participant -np --modality T2w --output_space T1w
hippunfold test_data/bids_T1w test_out participant -np --modality T1w --use-template-seg
12 changes: 4 additions & 8 deletions .github/workflows/python-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,13 @@ jobs:
run: |
poetry run hippunfold test_data/bids_singleT2w_longitudinal test_out participant -np --modality T2w
- name: Test manual seg T2w bids
- name: Test manualseg bids, with path override
run: |
poetry run hippunfold test_data/bids_segT2w test_out participant -np --modality segT2w
poetry run hippunfold test_data/bids_manualseg test_out participant -np --modality manualseg --path_manualseg test_data/bids_manualseg/sub-{subject}_hemi-{hemi}_dseg.nii.gz
- name: Test cropseg bids, with path override
- name: Test manualseg bids, one hemisphere hemi
run: |
poetry run hippunfold . test_out participant -np --modality cropseg --path_cropseg test_data/data_cropseg/sub-{subject}_hemi-{hemi}_dseg.nii.gz
- name: Test cropseg bids, with path override, left hemi
run: |
poetry run hippunfold . test_out participant -np --modality cropseg --path_cropseg test_data/data_cropseg_1hemi/sub-{subject}_hemi-{hemi}_dseg.nii.gz --hemi L
poetry run hippunfold test_data/bids_manualseg_1hemi test_out participant -np --modality manualseg --hemi L
- name: Test T2w with T1w template registration
run: |
Expand Down
20 changes: 3 additions & 17 deletions hippunfold/config/snakebids.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,7 @@ pybids_inputs:
- acquisition
- run

seg:
filters:
suffix: 'dseg'
extension: '.nii.gz'
datatype: 'anat'
invalid_filters: 'allow'
wildcards:
- subject
- session
- acquisition
- run

cropseg:
manualseg:
filters:
suffix: 'dseg'
extension: '.nii.gz'
Expand All @@ -100,15 +88,13 @@ pybids_inputs:
parse_args:

--modality:
help: 'Type of image to run hippunfold on. Modality prefixed with seg will import an existing (manual) hippocampal tissue segmentation from that space, instead of running neural network (default: %(default)s)'
help: 'Type of image to run hippunfold on. For manualseg and be sure to match the label scheme applied in the look up table (lut) online. For best performance, please also make sure the input is approximately aligned to the template space, with separate hemi-L|R in the name(s). (default: %(default)s)'
required: True
choices:
- T1w
- T2w
- hippb500
- segT1w
- segT2w
- cropseg
- manualseg


--template:
Expand Down
9 changes: 9 additions & 0 deletions hippunfold/resources/label_lut/manual_dseg.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
index name abbreviation
1 hippocampal grey matter GM
2 SRLM or 'dark band' SRLM
3 neocortex (entorhinal or parahippocampal) MTLC
4 pial surface Pial
5 hippocampal-amygdalar transition area HATA
6 indusium griseum IndGris
7 cysts Cyst
8 dentate gyrus DG
9 changes: 9 additions & 0 deletions hippunfold/resources/label_lut/subfields_dseg .tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#No. Label R G B A
1 subiculum 41 43 252 0
2 CA1 102 209 216 0
3 CA2 0 179 60 0
4 CA3 255 182 0 0
5 CA4 255 43 23 0
6 dentate_gyrus 245 236 0 0
7 SRLM 119 54 155 0
8 cysts 255 255 255 0
27 changes: 6 additions & 21 deletions hippunfold/workflow/Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,19 @@ template_modality = False


# set the lists used for output spaces
if (
config["modality"] == "T1w"
or config["modality"] == "segT1w"
or "T1w" in config["output_spaces"]
):
if config["modality"] == "T1w" or "T1w" in config["output_spaces"]:
ref_spaces.append("T1w")
crop_ref_spaces.append("cropT1w")
limit_to_list.add("T1w")
if (
(config["modality"] == "T2w" or config["modality"] == "segT2w")
and "native" in config["output_spaces"]
config["modality"] == "T2w" and "native" in config["output_spaces"]
) or "T2w" in config["output_spaces"]:
ref_spaces.append("T2w")
crop_ref_spaces.append("cropT2w")
limit_to_list.add("T2w")
if (
config["modality"] == "hippb500"
or config["modality"] == "cropseg"
or config["modality"] == "manualseg"
or "corobl" in config["output_spaces"]
):
ref_spaces.append("corobl")
Expand Down Expand Up @@ -64,13 +59,7 @@ elif "T1w" in config["modality"]:
if config["skip_inject_template_labels"]: # TODO do we need this?
config["autotop_labels"] = ["hipp"]


# add seg (if chosen) and the modality to the inputs
if config["modality"][:3] == "seg": # if modality is segT2w, then add seg
limit_to_list.add("seg")
limit_to_list.add(config["modality"][3:])
else:
limit_to_list.add(config["modality"])
limit_to_list.add(config["modality"])

# if atlas doesn't contain alignment features
if not config["atlas"] == ["multihist7"]:
Expand Down Expand Up @@ -118,13 +107,9 @@ if "T1w" in limit_to_list:


# include rules only as they are needed..
if config["modality"] == "segT1w" or config["modality"] == "segT2w":

include: "rules/preproc_seg.smk"

elif config["modality"] == "cropseg":
if config["modality"] == "manualseg":

include: "rules/preproc_cropseg.smk"
include: "rules/preproc_manualseg.smk"

else:

Expand Down
56 changes: 20 additions & 36 deletions hippunfold/workflow/rules/common.smk
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,16 @@ def get_avg_or_cp_scans_cmd(wildcards, input, output):
return cmd


def get_modality_key(modality):
if modality[:3] == "seg":
return "seg"
else:
return modality


def get_modality_suffix(modality):
if modality[:3] == "seg":
return modality[3:]
elif modality[:4] == "hipp":
if modality[:4] == "hipp":
return modality[4:]
else:
return modality


def get_final_spec():
if len(config["hemi"]) == 2:
specs = inputs[get_modality_key(config["modality"])].expand(
specs = inputs[config["modality"]].expand(
bids(
root=root,
datatype="surf",
Expand All @@ -66,7 +57,7 @@ def get_final_spec():
allow_missing=True,
)
else:
specs = inputs[get_modality_key(config["modality"])].expand(
specs = inputs[config["modality"]].expand(
bids(
root=root,
datatype="surf",
Expand All @@ -89,7 +80,7 @@ def get_final_spec():
def get_final_surf():
gii = []
gii.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="surf",
Expand All @@ -109,7 +100,7 @@ def get_final_surf():
)
)
gii.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="surf",
Expand All @@ -132,7 +123,7 @@ def get_final_surf():


def get_final_subfields():
return inputs[get_modality_key(config["modality"])].expand(
return inputs[config["modality"]].expand(
bids(
root=root,
datatype="anat",
Expand All @@ -159,7 +150,7 @@ def get_final_coords():
coords = []
# compute all laplace coords by default (incl IO)
coords.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="coords",
Expand All @@ -180,7 +171,7 @@ def get_final_coords():
)
)
coords.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="coords",
Expand All @@ -206,7 +197,7 @@ def get_final_transforms():
xfms = []

xfms.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="warps",
Expand All @@ -226,7 +217,7 @@ def get_final_transforms():
)

xfms.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="warps",
Expand All @@ -246,7 +237,7 @@ def get_final_transforms():
)

xfms.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="warps",
Expand All @@ -265,10 +256,9 @@ def get_final_transforms():

def get_final_anat():
anat = []

if "T1w" in ref_spaces or "T2w" in ref_spaces:
anat.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="anat",
Expand All @@ -293,7 +283,7 @@ def get_final_qc():

if not template_modality == False:
qc.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="qc",
Expand All @@ -307,7 +297,7 @@ def get_final_qc():
)
)
qc.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="qc",
Expand All @@ -325,7 +315,7 @@ def get_final_qc():
)
)
qc.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="qc",
Expand All @@ -346,7 +336,7 @@ def get_final_qc():
)
if len(config["hemi"]) == 2:
qc.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="qc",
Expand All @@ -364,7 +354,7 @@ def get_final_qc():
if (config["modality"] == "T1w") or (config["modality"] == "T2w"):
if not config["use_template_seg"]:
qc.extend(
inputs[get_modality_key(config["modality"])].expand(
inputs[config["modality"]].expand(
bids(
root=root,
datatype="qc",
Expand Down Expand Up @@ -401,27 +391,21 @@ def get_final_output():
final_output = []

modality_suffix = get_modality_suffix(config["modality"])
modality_key = get_modality_key(config["modality"])
modality_key = config["modality"]

# use a zip list for subject/session:
zip_list = inputs[modality_key].zip_lists
if "session" in zip_list:
zip_list = snakebids.filter_list(
zip_list,
{
"session": inputs[get_modality_key(config["modality"])].zip_lists[
"session"
]
},
{"session": inputs[config["modality"]].zip_lists["session"]},
)

final_output.extend(
expand(
expand(subj_output, zip, allow_missing=True, **zip_list),
modality_suffix=modality_suffix,
)
)

return final_output


Expand Down Expand Up @@ -464,7 +448,7 @@ def get_final_work_tar():


def get_work_dir(wildcards):
folder_with_file = inputs[get_modality_key(config["modality"])].expand(
folder_with_file = inputs[config["modality"]].expand(
bids(root=work, **inputs.subj_wildcards), **wildcards
)
folder_without_file = os.path.dirname(folder_with_file[0])
Expand Down
12 changes: 3 additions & 9 deletions hippunfold/workflow/rules/gifti.smk
Original file line number Diff line number Diff line change
Expand Up @@ -1331,9 +1331,7 @@ rule create_spec_file_hipp:
metric=get_gifti_metric_types(wildcards.label),
allow_missing=True,
),
subfields=lambda wildcards: inputs[
get_modality_key(config["modality"])
].expand(
subfields=lambda wildcards: inputs[config["modality"]].expand(
bids(
root=root,
datatype="surf",
Expand Down Expand Up @@ -1363,9 +1361,7 @@ rule create_spec_file_hipp:
space=["{space}", "unfold"],
allow_missing=True,
),
cifti_metrics=lambda wildcards: inputs[
get_modality_key(config["modality"])
].expand(
cifti_metrics=lambda wildcards: inputs[config["modality"]].expand(
bids(
root=root,
datatype="surf",
Expand All @@ -1378,9 +1374,7 @@ rule create_spec_file_hipp:
cifti=get_cifti_metric_types(wildcards.label),
allow_missing=True,
),
cifti_labels=lambda wildcards: inputs[
get_modality_key(config["modality"])
].expand(
cifti_labels=lambda wildcards: inputs[config["modality"]].expand(
bids(
root=root,
datatype="surf",
Expand Down
Loading

0 comments on commit f642963

Please sign in to comment.