From c46cb5e4b825e43a6bb50e4ffa1689faba2ece39 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Wed, 12 Jun 2024 15:24:58 -0400 Subject: [PATCH 01/15] vertex cleaning, especially for DG --- hippunfold/config/snakebids.yml | 13 +++-- hippunfold/workflow/rules/gifti.smk | 26 +++++---- hippunfold/workflow/rules/warps.smk | 4 +- hippunfold/workflow/scripts/create_warps.py | 12 ++-- .../workflow/scripts/fillbadvertices.py | 58 +++++++++++++++++++ .../workflow/scripts/fillnanvertices.py | 24 -------- 6 files changed, 90 insertions(+), 47 deletions(-) create mode 100644 hippunfold/workflow/scripts/fillbadvertices.py delete mode 100644 hippunfold/workflow/scripts/fillnanvertices.py diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index 0a2a97f6..c391e851 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -348,6 +348,7 @@ gifti_metric_types: dentate: - gyrification.shape - curvature.shape + - thickness.shape cifti_metric_types: hipp: @@ -357,8 +358,10 @@ cifti_metric_types: dentate: - gyrification.dscalar - curvature.dscalar + - thickness.dscalar - +outlierSmoothDist: 15 +vertexOutlierThreshold: 3 @@ -564,7 +567,7 @@ unfold_vol_ref: dims: - '256' - '128' - - '16' + - '8' voxdims: - '0.15625' - '0.15625' @@ -599,9 +602,9 @@ unfold_vol_ref: orient: RPI unfold_crop_epsilon_fractions: - - 0 - - 0 - - 0.0625 #1/16 + - 1 + - 1 + - 1 # space for uniform unfolded grid: # currently only used for interpolating hipp subfields on surface diff --git a/hippunfold/workflow/rules/gifti.smk b/hippunfold/workflow/rules/gifti.smk index 2ae35706..fcbf0a07 100644 --- a/hippunfold/workflow/rules/gifti.smk +++ b/hippunfold/workflow/rules/gifti.smk @@ -181,7 +181,7 @@ rule warp_gii_unfold2corobl1: datatype="surf", den="{density}", suffix="{surfname}.surf.gii", - desc="nonancorrect", + desc="nobadcorrect", space="corobl", unfoldreg="none", hemi="{hemi}", @@ -198,21 +198,24 @@ rule warp_gii_unfold2corobl1: " -surface-secondary-type {params.secondary_type}" -# previous rule seems to be where nan vertices emerge, so we'll correct them here immediately after -rule correct_nan_vertices1: +# previous rule seems to be where bad vertices emerge, so we'll correct them here immediately after +rule correct_bad_vertices1: input: gii=bids( root=work, datatype="surf", den="{density}", suffix="{surfname}.surf.gii", - desc="nonancorrect", + desc="nobadcorrect", space="corobl", unfoldreg="none", hemi="{hemi}", label="hipp", **config["subj_wildcards"] ), + params: + dist=config["outlierSmoothDist"], + threshold=config["vertexOutlierThreshold"], output: gii=bids( root=work, @@ -230,7 +233,7 @@ rule correct_nan_vertices1: container: config["singularity"]["autotop"] script: - "../scripts/fillnanvertices.py" + "../scripts/fillbadvertices.py" # morphological features, calculated in native space: @@ -730,7 +733,7 @@ rule warp_gii_unfold2corobl2: datatype="surf", den="{density}", suffix="{surfname}.surf.gii", - desc="nonancorrect", + desc="nobadcorrect", space="corobl", hemi="{hemi}", label="{autotop}", @@ -746,20 +749,23 @@ rule warp_gii_unfold2corobl2: " -surface-secondary-type {params.secondary_type}" -# previous rule seems to be where nan vertices emerge, so we'll correct them here immediately after -rule correct_nan_vertices2: +# previous rule seems to be where bad vertices emerge, so we'll correct them here immediately after +rule correct_bad_vertices2: input: gii=bids( root=work, datatype="surf", den="{density}", suffix="{surfname}.surf.gii", - desc="nonancorrect", + desc="nobadcorrect", space="corobl", hemi="{hemi}", label="{autotop}", **config["subj_wildcards"] ), + params: + dist=config["outlierSmoothDist"], + threshold=config["vertexOutlierThreshold"], output: gii=bids( root=work, @@ -776,7 +782,7 @@ rule correct_nan_vertices2: container: config["singularity"]["autotop"] script: - "../scripts/fillnanvertices.py" + "../scripts/fillbadvertices.py" # needed for if native_modality is corobl diff --git a/hippunfold/workflow/rules/warps.smk b/hippunfold/workflow/rules/warps.smk index cbdd11d8..8e328377 100644 --- a/hippunfold/workflow/rules/warps.smk +++ b/hippunfold/workflow/rules/warps.smk @@ -167,7 +167,7 @@ rule create_warps_hipp: ), labelmap=get_labels_for_laplace, params: - interp_method="linear", + interp_method="nearest", gm_labels=lambda wildcards: config["laplace_labels"]["AP"]["gm"], epsilon=lambda wildcards: config["unfold_crop_epsilon_fractions"], resources: @@ -294,7 +294,7 @@ rule create_warps_dentate: ), labelmap=get_labels_for_laplace, params: - interp_method="linear", + interp_method="nearest", gm_labels=lambda wildcards: config["laplace_labels"]["PD"]["sink"], epsilon=lambda wildcards: config["unfold_crop_epsilon_fractions"], resources: diff --git a/hippunfold/workflow/scripts/create_warps.py b/hippunfold/workflow/scripts/create_warps.py index cc923fb1..7db55e14 100644 --- a/hippunfold/workflow/scripts/create_warps.py +++ b/hippunfold/workflow/scripts/create_warps.py @@ -111,18 +111,18 @@ def summary(name, array): # add some noise to avoid perfectly overlapping datapoints! points = ( - coord_flat_ap + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, - coord_flat_pd + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, - coord_flat_io + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, + coord_flat_ap * unfold_dims[0] + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, + coord_flat_pd * unfold_dims[1] + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, + coord_flat_io * unfold_dims[2] + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, ) # get unfolded grid (from 0 to 1, not world coords), using meshgrid: # note: indexing='ij' to swap the ordering of x and y epsilon = snakemake.params.epsilon (unfold_gx, unfold_gy, unfold_gz) = np.meshgrid( - np.linspace(0 + float(epsilon[0]), 1 - float(epsilon[0]), unfold_dims[0]), - np.linspace(0 + float(epsilon[1]), 1 - float(epsilon[1]), unfold_dims[1]), - np.linspace(0 + float(epsilon[2]), 1 - float(epsilon[2]), unfold_dims[2]), + np.linspace(0 + float(epsilon[0]), unfold_dims[0] - float(epsilon[0]), unfold_dims[0]), + np.linspace(0 + float(epsilon[1]), unfold_dims[1] - float(epsilon[1]), unfold_dims[1]), + np.linspace(0 + float(epsilon[2]), unfold_dims[2] - float(epsilon[2]), unfold_dims[2]), indexing="ij", ) diff --git a/hippunfold/workflow/scripts/fillbadvertices.py b/hippunfold/workflow/scripts/fillbadvertices.py new file mode 100644 index 00000000..32f8f362 --- /dev/null +++ b/hippunfold/workflow/scripts/fillbadvertices.py @@ -0,0 +1,58 @@ +import nibabel as nib +import numpy as np +from scipy.stats import zscore +import copy + +SDthreshold = snakemake.params.threshold +iters = snakemake.params.dist + +gii = nib.load(snakemake.input.gii) +varr = gii.get_arrays_from_intent("NIFTI_INTENT_POINTSET")[0] +V = varr.data +farr = gii.get_arrays_from_intent("NIFTI_INTENT_TRIANGLE")[0] +F = farr.data + + +# find local outliers by smoothing and then substracting from original +# https://github.com/MICA-MNI/hippomaps/blob/master/hippomaps/utils.py +def avg_neighbours(F, cdat, n): + frows = np.where(F == n)[0] + v = np.unique(F[frows, :]) + cdat = np.reshape(cdat, (len(cdat), -1)) + out = np.nanmean(cdat[v,:], 0) + return out + +def surfdat_smooth(F, cdata, iters=1): + sz = cdata.shape + cdata = cdata.reshape(cdata.shape[0], -1) + cdata_smooth = copy.deepcopy(cdata) + for i in range(iters): + for n in range(len(cdata)): + cdata_smooth[n,:] = avg_neighbours(F, cdata, n) + cdata = copy.deepcopy(cdata_smooth) + return cdata_smooth.reshape(sz) + +Vsmooth = surfdat_smooth(F, V, iters=iters) +Vdiffs = V - Vsmooth +Vdists = np.sqrt((Vdiffs[:,0])**2 + (Vdiffs[:,1])**2 + (Vdiffs[:,2])**2) +Vzscored = zscore(Vdists) +outliers = ((Vzscored > SDthreshold) | (Vzscored < -SDthreshold)) +V[outliers,:] = np.nan + + + +# most nans should be just isolated points, but in case there is an island of nans this will erode it, replacing with decent (but not perfect) guesses of where vertices should be +while np.isnan(np.sum(V)): + # index of vertices containing nan + i = np.where(np.isnan(V)) + ii = np.unique(i[0]) + # replace with the nanmean of neighbouring vertices + newV = V + for n in ii: + f = np.where(F == n) + v = F[f[0]] + vv = np.unique(v) + newV[n, :] = np.nanmean(V[vv, :], 0) + V = newV + +nib.save(gii, snakemake.output.gii) diff --git a/hippunfold/workflow/scripts/fillnanvertices.py b/hippunfold/workflow/scripts/fillnanvertices.py deleted file mode 100644 index 22e7b1db..00000000 --- a/hippunfold/workflow/scripts/fillnanvertices.py +++ /dev/null @@ -1,24 +0,0 @@ -import nibabel as nib -import numpy as np - -gii = nib.load(snakemake.input.gii) -varr = gii.get_arrays_from_intent("NIFTI_INTENT_POINTSET")[0] -V = varr.data -farr = gii.get_arrays_from_intent("NIFTI_INTENT_TRIANGLE")[0] -F = farr.data - -# most nans should be just isolated points, but in case there is an island of nans this will erode it, replacing with decent (but not perfect) guesses of where vertices should be -while np.isnan(np.sum(V)): - # index of vertices containing nan - i = np.where(np.isnan(V)) - ii = np.unique(i[0]) - # replace with the nanmean of neighbouring vertices - newV = V - for n in ii: - f = np.where(F == n) - v = F[f[0]] - vv = np.unique(v) - newV[n, :] = np.nanmean(V[vv, :], 0) - V = newV - -nib.save(gii, snakemake.output.gii) From 3f73bf3d59002883d7bca1ca1cabaedde228d19f Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Wed, 12 Jun 2024 15:31:42 -0400 Subject: [PATCH 02/15] effectively resotres parameters to previous defaults --- hippunfold/config/snakebids.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index c391e851..c347a312 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -348,7 +348,6 @@ gifti_metric_types: dentate: - gyrification.shape - curvature.shape - - thickness.shape cifti_metric_types: hipp: @@ -358,7 +357,6 @@ cifti_metric_types: dentate: - gyrification.dscalar - curvature.dscalar - - thickness.dscalar outlierSmoothDist: 15 vertexOutlierThreshold: 3 @@ -567,7 +565,7 @@ unfold_vol_ref: dims: - '256' - '128' - - '8' + - '16' voxdims: - '0.15625' - '0.15625' @@ -602,8 +600,8 @@ unfold_vol_ref: orient: RPI unfold_crop_epsilon_fractions: - - 1 - - 1 + - 0 + - 0 - 1 # space for uniform unfolded grid: From 8f1367c28ff2a63a07dc4e06a39230223c4a23c6 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Wed, 12 Jun 2024 15:35:38 -0400 Subject: [PATCH 03/15] lint --- hippunfold/workflow/scripts/create_warps.py | 21 +++++++++++++------ .../workflow/scripts/fillbadvertices.py | 13 ++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/hippunfold/workflow/scripts/create_warps.py b/hippunfold/workflow/scripts/create_warps.py index 7db55e14..6562d753 100644 --- a/hippunfold/workflow/scripts/create_warps.py +++ b/hippunfold/workflow/scripts/create_warps.py @@ -111,18 +111,27 @@ def summary(name, array): # add some noise to avoid perfectly overlapping datapoints! points = ( - coord_flat_ap * unfold_dims[0] + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, - coord_flat_pd * unfold_dims[1] + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, - coord_flat_io * unfold_dims[2] + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, + coord_flat_ap * unfold_dims[0] + + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, + coord_flat_pd * unfold_dims[1] + + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, + coord_flat_io * unfold_dims[2] + + (np.random.rand(coord_flat_ap.shape[0]) - 0.5) * 1e-6, ) # get unfolded grid (from 0 to 1, not world coords), using meshgrid: # note: indexing='ij' to swap the ordering of x and y epsilon = snakemake.params.epsilon (unfold_gx, unfold_gy, unfold_gz) = np.meshgrid( - np.linspace(0 + float(epsilon[0]), unfold_dims[0] - float(epsilon[0]), unfold_dims[0]), - np.linspace(0 + float(epsilon[1]), unfold_dims[1] - float(epsilon[1]), unfold_dims[1]), - np.linspace(0 + float(epsilon[2]), unfold_dims[2] - float(epsilon[2]), unfold_dims[2]), + np.linspace( + 0 + float(epsilon[0]), unfold_dims[0] - float(epsilon[0]), unfold_dims[0] + ), + np.linspace( + 0 + float(epsilon[1]), unfold_dims[1] - float(epsilon[1]), unfold_dims[1] + ), + np.linspace( + 0 + float(epsilon[2]), unfold_dims[2] - float(epsilon[2]), unfold_dims[2] + ), indexing="ij", ) diff --git a/hippunfold/workflow/scripts/fillbadvertices.py b/hippunfold/workflow/scripts/fillbadvertices.py index 32f8f362..ee9284c6 100644 --- a/hippunfold/workflow/scripts/fillbadvertices.py +++ b/hippunfold/workflow/scripts/fillbadvertices.py @@ -19,26 +19,27 @@ def avg_neighbours(F, cdat, n): frows = np.where(F == n)[0] v = np.unique(F[frows, :]) cdat = np.reshape(cdat, (len(cdat), -1)) - out = np.nanmean(cdat[v,:], 0) + out = np.nanmean(cdat[v, :], 0) return out + def surfdat_smooth(F, cdata, iters=1): sz = cdata.shape cdata = cdata.reshape(cdata.shape[0], -1) cdata_smooth = copy.deepcopy(cdata) for i in range(iters): for n in range(len(cdata)): - cdata_smooth[n,:] = avg_neighbours(F, cdata, n) + cdata_smooth[n, :] = avg_neighbours(F, cdata, n) cdata = copy.deepcopy(cdata_smooth) return cdata_smooth.reshape(sz) + Vsmooth = surfdat_smooth(F, V, iters=iters) Vdiffs = V - Vsmooth -Vdists = np.sqrt((Vdiffs[:,0])**2 + (Vdiffs[:,1])**2 + (Vdiffs[:,2])**2) +Vdists = np.sqrt((Vdiffs[:, 0]) ** 2 + (Vdiffs[:, 1]) ** 2 + (Vdiffs[:, 2]) ** 2) Vzscored = zscore(Vdists) -outliers = ((Vzscored > SDthreshold) | (Vzscored < -SDthreshold)) -V[outliers,:] = np.nan - +outliers = (Vzscored > SDthreshold) | (Vzscored < -SDthreshold) +V[outliers, :] = np.nan # most nans should be just isolated points, but in case there is an island of nans this will erode it, replacing with decent (but not perfect) guesses of where vertices should be From 426058aed37622dd785b9429fffb356852cfbc53 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Wed, 12 Jun 2024 15:36:43 -0400 Subject: [PATCH 04/15] note --- hippunfold/config/snakebids.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index c347a312..02726824 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -358,6 +358,8 @@ cifti_metric_types: - gyrification.dscalar - curvature.dscalar +# params for detecting and removing outlier vertices +# NOTE this is currently dependent on surface density outlierSmoothDist: 15 vertexOutlierThreshold: 3 From c8190729fd324c54d24478c5207771f3a1fc6861 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Wed, 12 Jun 2024 15:44:27 -0400 Subject: [PATCH 05/15] restoreing one more parameter --- hippunfold/workflow/rules/warps.smk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hippunfold/workflow/rules/warps.smk b/hippunfold/workflow/rules/warps.smk index 8e328377..cbdd11d8 100644 --- a/hippunfold/workflow/rules/warps.smk +++ b/hippunfold/workflow/rules/warps.smk @@ -167,7 +167,7 @@ rule create_warps_hipp: ), labelmap=get_labels_for_laplace, params: - interp_method="nearest", + interp_method="linear", gm_labels=lambda wildcards: config["laplace_labels"]["AP"]["gm"], epsilon=lambda wildcards: config["unfold_crop_epsilon_fractions"], resources: @@ -294,7 +294,7 @@ rule create_warps_dentate: ), labelmap=get_labels_for_laplace, params: - interp_method="nearest", + interp_method="linear", gm_labels=lambda wildcards: config["laplace_labels"]["PD"]["sink"], epsilon=lambda wildcards: config["unfold_crop_epsilon_fractions"], resources: From f863be6dbd487f86fee8a94e4312de73d31a4bec Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Thu, 13 Jun 2024 11:32:58 -0400 Subject: [PATCH 06/15] addresses configurable DG surface --- hippunfold/workflow/rules/common.smk | 93 ++++++++++++++++++---------- 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/hippunfold/workflow/rules/common.smk b/hippunfold/workflow/rules/common.smk index b0e5db03..41e29196 100644 --- a/hippunfold/workflow/rules/common.smk +++ b/hippunfold/workflow/rules/common.smk @@ -24,43 +24,67 @@ def get_modality_suffix(modality): def get_final_spec(): - if len(config["hemi"]) == 2: - specs = expand( - bids( - root=root, - datatype="surf", - den="{density}", - space="{space}", - label="{autotop}", - suffix="surfaces.spec", - **config["subj_wildcards"], - ), - density=config["output_density"], - space=ref_spaces, - autotop=config["autotop_labels"], - allow_missing=True, - ) - else: - specs = expand( - bids( - root=root, - datatype="surf", - den="{density}", - space="{space}", - hemi="{hemi}", - label="{autotop}", - suffix="surfaces.spec", - **config["subj_wildcards"], - ), - density=config["output_density"], - space=ref_spaces, - hemi=config["hemi"], - autotop=config["autotop_labels"], - allow_missing=True, - ) + specs = expand( + bids( + root=root, + datatype="surf", + den="{density}", + space="{space}", + hemi="{hemi}", + label="{autotop}", + suffix="surfaces.spec", + **config["subj_wildcards"], + ), + density=config["output_density"], + space=ref_spaces, + hemi=config["hemi"], + autotop=config["autotop_labels"], + allow_missing=True, + ) return specs +def get_final_surf(): + gii = [] + gii.extend(expand( + bids( + root=root, + datatype="surf", + den="{density}", + suffix="{surfname}.surf.gii", + space="{space}", + hemi="{hemi}", + label="{autotop}", + **config["subj_wildcards"], + ), + density=config["output_density"], + space=ref_spaces, + hemi=config["hemi"], + autotop=config["autotop_labels"], + surfname=config["surf_types"]["hipp"], + allow_missing=True, + )) + gii.extend(expand( + bids( + root=root, + datatype="surf", + den="{density}", + suffix="{surfname}.surf.gii", + space="{space}", + hemi="{hemi}", + label="{autotop}", + **config["subj_wildcards"], + ), + density=config["output_density"], + space=ref_spaces, + hemi=config["hemi"], + autotop=config["autotop_labels"], + surfname=config["surf_types"]["dentate"], + allow_missing=True, + )) + return gii + + def get_final_subfields(): return expand( bids( @@ -313,6 +337,7 @@ def get_final_qc(): def get_final_subj_output(): subj_output = [] subj_output.extend(get_final_spec()) + subj_output.extend(get_final_surf()) subj_output.extend(get_final_subfields()) subj_output.extend(get_final_coords()) subj_output.extend(get_final_transforms()) From cbf3b0a5f6065dc398facb27680658fc2ec81dbc Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Thu, 13 Jun 2024 11:35:53 -0400 Subject: [PATCH 07/15] lint --- hippunfold/workflow/rules/common.smk | 76 +++++++++++++++------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/hippunfold/workflow/rules/common.smk b/hippunfold/workflow/rules/common.smk index 41e29196..4c568f95 100644 --- a/hippunfold/workflow/rules/common.smk +++ b/hippunfold/workflow/rules/common.smk @@ -46,42 +46,46 @@ def get_final_spec(): def get_final_surf(): gii = [] - gii.extend(expand( - bids( - root=root, - datatype="surf", - den="{density}", - suffix="{surfname}.surf.gii", - space="{space}", - hemi="{hemi}", - label="{autotop}", - **config["subj_wildcards"], - ), - density=config["output_density"], - space=ref_spaces, - hemi=config["hemi"], - autotop=config["autotop_labels"], - surfname=config["surf_types"]["hipp"], - allow_missing=True, - )) - gii.extend(expand( - bids( - root=root, - datatype="surf", - den="{density}", - suffix="{surfname}.surf.gii", - space="{space}", - hemi="{hemi}", - label="{autotop}", - **config["subj_wildcards"], - ), - density=config["output_density"], - space=ref_spaces, - hemi=config["hemi"], - autotop=config["autotop_labels"], - surfname=config["surf_types"]["dentate"], - allow_missing=True, - )) + gii.extend( + expand( + bids( + root=root, + datatype="surf", + den="{density}", + suffix="{surfname}.surf.gii", + space="{space}", + hemi="{hemi}", + label="{autotop}", + **config["subj_wildcards"], + ), + density=config["output_density"], + space=ref_spaces, + hemi=config["hemi"], + autotop=config["autotop_labels"], + surfname=config["surf_types"]["hipp"], + allow_missing=True, + ) + ) + gii.extend( + expand( + bids( + root=root, + datatype="surf", + den="{density}", + suffix="{surfname}.surf.gii", + space="{space}", + hemi="{hemi}", + label="{autotop}", + **config["subj_wildcards"], + ), + density=config["output_density"], + space=ref_spaces, + hemi=config["hemi"], + autotop=config["autotop_labels"], + surfname=config["surf_types"]["dentate"], + allow_missing=True, + ) + ) return gii From 92113225b9ea4cbb6353e2651fe0b66af54080f8 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Thu, 13 Jun 2024 11:36:28 -0400 Subject: [PATCH 08/15] surface configuration now more editable --- hippunfold/config/snakebids.yml | 14 +++++++++++--- hippunfold/workflow/rules/gifti.smk | 4 ++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index 02726824..dee56824 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -327,11 +327,14 @@ parse_args: - synthseg_v0.2 - neonateT1w_v2 + + +# --- surface specific configuration -- + autotop_labels: - 'hipp' - 'dentate' - surf_types: hipp: - midthickness @@ -339,6 +342,8 @@ surf_types: - outer dentate: - midthickness +# - inner +# - outer gifti_metric_types: hipp: @@ -359,8 +364,11 @@ cifti_metric_types: - curvature.dscalar # params for detecting and removing outlier vertices -# NOTE this is currently dependent on surface density -outlierSmoothDist: 15 +outlierSmoothDist: + unfoldiso: 15 + 0p5mm: 7 + 1mm: 3 + 2mm: 1 vertexOutlierThreshold: 3 diff --git a/hippunfold/workflow/rules/gifti.smk b/hippunfold/workflow/rules/gifti.smk index fcbf0a07..32db0bd1 100644 --- a/hippunfold/workflow/rules/gifti.smk +++ b/hippunfold/workflow/rules/gifti.smk @@ -214,7 +214,7 @@ rule correct_bad_vertices1: **config["subj_wildcards"] ), params: - dist=config["outlierSmoothDist"], + dist=lambda wildcards: config["outlierSmoothDist"][wildcards.density], threshold=config["vertexOutlierThreshold"], output: gii=bids( @@ -764,7 +764,7 @@ rule correct_bad_vertices2: **config["subj_wildcards"] ), params: - dist=config["outlierSmoothDist"], + dist=lambda wildcards: config["outlierSmoothDist"][wildcards.density], threshold=config["vertexOutlierThreshold"], output: gii=bids( From e03417a047f26ad172e31ac5f751813bba21ecab Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Tue, 18 Jun 2024 13:41:25 -0400 Subject: [PATCH 09/15] bigbrain filled; not on OSF --- hippunfold/config/snakebids.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index dee56824..25c78364 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -151,6 +151,7 @@ parse_args: - 'MBMv3' - 'CIVM' - 'ABAv3' + - 'bigbrain' default: 'CITI168' help: 'Set the template to use for registration to coronal oblique (and optionally for template-based segmentation if --use-template-seg is enabled). CITI168 is for adult human data, dHCP is for neonatal human data, MBMv2 is for ex vivo marmoset data, MBMv3 is for in vivo marmoset data, CIVM is for in vivo macaque data, and ABAv3 is for mouse data. When using a non-human template, consider using a corresponding atlas. (default: %(default)s)' @@ -163,6 +164,7 @@ parse_args: - 'MBMv3' - 'CIVM' - 'ABAv3' + - 'bigbrain' default: 'upenn' help: 'Set the template to use for shape injection. (default: %(default)s)' @@ -402,6 +404,10 @@ template_based_segmentation: hemi: - R - L + bigbrain: + hemi: + - R + - L template_files: @@ -455,6 +461,13 @@ 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 + bigbrain: + T1w: tpl-bigbrain_100um_T1w.nii.gz + xfm_corobl: tpl-bigbrain_from-native_to-corobl_type-itk_affine.txt + crop_ref: tpl-bigbrain_hemi-{hemi}_space-corobl_40um_T1w.nii.gz + Mask_crop: tpl-bigbrain_hemi-{hemi}_space-corobl_desc-tissuemanual_40um_dseg.nii.gz + dseg: tpl-bigbrain_hemi-{hemi}_space-corobl_desc-tissuemanual_40um_dseg.nii.gz + coords: tpl-bigbrain_dir-{dir}_hemi-{hemi}_space-corobl_label-{autotop}_desc-laplace_coords.nii.gz atlas_files: multihist7: @@ -555,6 +568,7 @@ resource_urls: upenn: 'files.ca-1.osf.io/v1/resources/v8acf/providers/osfstorage/65395c1613d27b122a94ca09/?zip=' CIVM: 'files.ca-1.osf.io/v1/resources/v8acf/providers/osfstorage/65395bf62827451220b86e24/?zip=' ABAv3: 'files.ca-1.osf.io/v1/resources/v8acf/providers/osfstorage/6668855b6b6c8e2cc704ca97/?zip=' + bigbrain: 'files.ca-1.osf.io/v1/resources/v8acf/providers/osfstorage/666b1bc765e1de5972893e59/?zip=' #to get hash, see https://github.com/CenterForOpenScience/osf.io/issues/8256#issuecomment-379833911 From 8f08698e5292e9602e9343dcf563453664d0374a Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Mon, 16 Dec 2024 11:31:49 -0500 Subject: [PATCH 10/15] renaming & lower resolution --- hippunfold/config/snakebids.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index 25c78364..c92e870b 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -378,7 +378,7 @@ vertexOutlierThreshold: 3 #--- workflow specific configuration -- singularity: - autotop: 'docker://khanlab/hippunfold_deps:v0.5.0' + autotop: 'docker://khanlab/hippunfold_deps:v0.5.1' xfm_identity: resources/etc/identity_xfm.txt xfm_identity_itk: resources/etc/identity_xfm_itk.txt @@ -462,11 +462,12 @@ template_files: 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 bigbrain: - T1w: tpl-bigbrain_100um_T1w.nii.gz + T1w: tpl-bigbrain_1mm_merker.nii.gz + T2w: tpl-bigbrain_1mm_merker.nii.gz xfm_corobl: tpl-bigbrain_from-native_to-corobl_type-itk_affine.txt - crop_ref: tpl-bigbrain_hemi-{hemi}_space-corobl_40um_T1w.nii.gz - Mask_crop: tpl-bigbrain_hemi-{hemi}_space-corobl_desc-tissuemanual_40um_dseg.nii.gz - dseg: tpl-bigbrain_hemi-{hemi}_space-corobl_desc-tissuemanual_40um_dseg.nii.gz + crop_ref: tpl-bigbrain_hemi-{hemi}_space-corobl_100um_merker.nii.gz + 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 atlas_files: From 003dbf36773548c6ebfd3df490cbe6f0e868c2e6 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Mon, 16 Dec 2024 11:51:53 -0500 Subject: [PATCH 11/15] grouped outlier opts --- hippunfold/config/snakebids.yml | 15 ++++++++------- hippunfold/workflow/rules/gifti.smk | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/hippunfold/config/snakebids.yml b/hippunfold/config/snakebids.yml index c92e870b..4a449f0b 100644 --- a/hippunfold/config/snakebids.yml +++ b/hippunfold/config/snakebids.yml @@ -366,12 +366,13 @@ cifti_metric_types: - curvature.dscalar # params for detecting and removing outlier vertices -outlierSmoothDist: - unfoldiso: 15 - 0p5mm: 7 - 1mm: 3 - 2mm: 1 -vertexOutlierThreshold: 3 +outlier_opts: + outlierSmoothDist: + unfoldiso: 15 + 0p5mm: 7 + 1mm: 3 + 2mm: 1 + vertexOutlierThreshold: 3 @@ -627,7 +628,7 @@ unfold_vol_ref: unfold_crop_epsilon_fractions: - 0 - 0 - - 1 + - 1 #in unfolded space voxels # space for uniform unfolded grid: # currently only used for interpolating hipp subfields on surface diff --git a/hippunfold/workflow/rules/gifti.smk b/hippunfold/workflow/rules/gifti.smk index 32db0bd1..a485ba3b 100644 --- a/hippunfold/workflow/rules/gifti.smk +++ b/hippunfold/workflow/rules/gifti.smk @@ -214,8 +214,8 @@ rule correct_bad_vertices1: **config["subj_wildcards"] ), params: - dist=lambda wildcards: config["outlierSmoothDist"][wildcards.density], - threshold=config["vertexOutlierThreshold"], + dist=lambda wildcards: config["outlier_opts"]["outlierSmoothDist"][wildcards.density], + threshold=config["outlier_opts"]["vertexOutlierThreshold"], output: gii=bids( root=work, @@ -764,8 +764,8 @@ rule correct_bad_vertices2: **config["subj_wildcards"] ), params: - dist=lambda wildcards: config["outlierSmoothDist"][wildcards.density], - threshold=config["vertexOutlierThreshold"], + dist=lambda wildcards: config["outlier_opts"]["outlierSmoothDist"][wildcards.density], + threshold=config["outlier_opts"]["vertexOutlierThreshold"], output: gii=bids( root=work, From 482ad53518b3d5fbc1e565e447b64e7cfe6ad05f Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Mon, 16 Dec 2024 11:54:41 -0500 Subject: [PATCH 12/15] lint --- hippunfold/workflow/rules/gifti.smk | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hippunfold/workflow/rules/gifti.smk b/hippunfold/workflow/rules/gifti.smk index a485ba3b..4c317fac 100644 --- a/hippunfold/workflow/rules/gifti.smk +++ b/hippunfold/workflow/rules/gifti.smk @@ -214,7 +214,9 @@ rule correct_bad_vertices1: **config["subj_wildcards"] ), params: - dist=lambda wildcards: config["outlier_opts"]["outlierSmoothDist"][wildcards.density], + dist=lambda wildcards: config["outlier_opts"]["outlierSmoothDist"][ + wildcards.density + ], threshold=config["outlier_opts"]["vertexOutlierThreshold"], output: gii=bids( @@ -764,7 +766,9 @@ rule correct_bad_vertices2: **config["subj_wildcards"] ), params: - dist=lambda wildcards: config["outlier_opts"]["outlierSmoothDist"][wildcards.density], + dist=lambda wildcards: config["outlier_opts"]["outlierSmoothDist"][ + wildcards.density + ], threshold=config["outlier_opts"]["vertexOutlierThreshold"], output: gii=bids( From b57eaeee74e00a28eff26e760a84a59d8ead280c Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Tue, 17 Dec 2024 09:05:39 -0500 Subject: [PATCH 13/15] lint --- hippunfold/workflow/rules/common.smk | 1 - 1 file changed, 1 deletion(-) diff --git a/hippunfold/workflow/rules/common.smk b/hippunfold/workflow/rules/common.smk index 9bce0bd6..a31f2bf7 100644 --- a/hippunfold/workflow/rules/common.smk +++ b/hippunfold/workflow/rules/common.smk @@ -89,7 +89,6 @@ def get_final_spec(): surfname=config["surf_types"]["dentate"], allow_missing=True, ) - ) return specs From 09c3e49683f02fc3e70d3a48e74f4b5a84160a58 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Tue, 17 Dec 2024 09:08:53 -0500 Subject: [PATCH 14/15] removed redudant hemi conditional; replaced with hippVSdentate --- hippunfold/workflow/rules/common.smk | 44 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/hippunfold/workflow/rules/common.smk b/hippunfold/workflow/rules/common.smk index a31f2bf7..6e8e948e 100644 --- a/hippunfold/workflow/rules/common.smk +++ b/hippunfold/workflow/rules/common.smk @@ -49,28 +49,27 @@ def get_modality_suffix(modality): def get_final_spec(): - if len(config["hemi"]) == 2: - specs = inputs[get_modality_key(config["modality"])].expand( - bids( - root=root, - datatype="surf", - den="{density}", - suffix="{surfname}.surf.gii", - space="{space}", - hemi="{hemi}", - label="{autotop}", - suffix="surfaces.spec", - **inputs.subj_wildcards, - ), - density=config["output_density"], - space=ref_spaces, - hemi=config["hemi"], - autotop=config["autotop_labels"], - surfname=config["surf_types"]["hipp"], - allow_missing=True, - ) - else: - specs = inputs[get_modality_key(config["modality"])].expand( + specs = inputs[get_modality_key(config["modality"])].expand( + bids( + root=root, + datatype="surf", + den="{density}", + suffix="{surfname}.surf.gii", + space="{space}", + hemi="{hemi}", + label="{autotop}", + suffix="surfaces.spec", + **inputs.subj_wildcards, + ), + density=config["output_density"], + space=ref_spaces, + hemi=config["hemi"], + autotop=config["autotop_labels"], + surfname=config["surf_types"]["hipp"], + allow_missing=True, + ) + specs.extent( + inputs[get_modality_key(config["modality"])].expand( bids( root=root, datatype="surf", @@ -89,6 +88,7 @@ def get_final_spec(): surfname=config["surf_types"]["dentate"], allow_missing=True, ) + ) return specs From 2d945d9944c86635ca95aaa04e1517798d2ae985 Mon Sep 17 00:00:00 2001 From: Jordan DeKraker Date: Tue, 17 Dec 2024 09:15:21 -0500 Subject: [PATCH 15/15] bugfixes --- hippunfold/workflow/rules/common.smk | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/hippunfold/workflow/rules/common.smk b/hippunfold/workflow/rules/common.smk index 6e8e948e..ea2d3007 100644 --- a/hippunfold/workflow/rules/common.smk +++ b/hippunfold/workflow/rules/common.smk @@ -49,32 +49,33 @@ def get_modality_suffix(modality): def get_final_spec(): - specs = inputs[get_modality_key(config["modality"])].expand( - bids( - root=root, - datatype="surf", - den="{density}", - suffix="{surfname}.surf.gii", - space="{space}", - hemi="{hemi}", - label="{autotop}", - suffix="surfaces.spec", - **inputs.subj_wildcards, - ), - density=config["output_density"], - space=ref_spaces, - hemi=config["hemi"], - autotop=config["autotop_labels"], - surfname=config["surf_types"]["hipp"], - allow_missing=True, + specs = [] + specs.extend( + inputs[get_modality_key(config["modality"])].expand( + bids( + root=root, + datatype="surf", + den="{density}", + space="{space}", + hemi="{hemi}", + label="{autotop}", + suffix="surfaces.spec", + **inputs.subj_wildcards, + ), + density=config["output_density"], + space=ref_spaces, + hemi=config["hemi"], + autotop=config["autotop_labels"], + surfname=config["surf_types"]["hipp"], + allow_missing=True, + ) ) - specs.extent( + specs.extend( inputs[get_modality_key(config["modality"])].expand( bids( root=root, datatype="surf", den="{density}", - suffix="{surfname}.surf.gii", space="{space}", hemi="{hemi}", label="{autotop}", @@ -344,7 +345,6 @@ def get_final_qc(): def get_final_subj_output(): subj_output = [] subj_output.extend(get_final_spec()) - subj_output.extend(get_final_surf()) subj_output.extend(get_final_subfields()) subj_output.extend(get_final_coords()) subj_output.extend(get_final_transforms())