Skip to content

Commit b92d3bc

Browse files
committed
Opened ability to directly provide a Freesurfer output directory for ingress, and also increased the amount of surface write-outs.
1 parent f401439 commit b92d3bc

File tree

8 files changed

+100
-59
lines changed

8 files changed

+100
-59
lines changed

CPAC/pipeline/cpac_pipeline.py

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,8 @@ def build_anat_preproc_stack(rpool, cfg, pipeline_blocks=None):
790790
]
791791
pipeline_blocks += anat_init_blocks
792792

793-
pipeline_blocks += [freesurfer_preproc]
793+
if not rpool.check_rpool('freesurfer-subject-dir'):
794+
pipeline_blocks += [freesurfer_preproc]
794795

795796
if not rpool.check_rpool('desc-preproc_T1w'):
796797

@@ -805,7 +806,7 @@ def build_anat_preproc_stack(rpool, cfg, pipeline_blocks=None):
805806
]
806807
acpc_blocks.append(
807808
[brain_mask_acpc_freesurfer_fsl_tight,
808-
brain_mask_acpc_freesurfer_fsl_loose]
809+
brain_mask_acpc_freesurfer_fsl_loose]
809810
)
810811
else:
811812
acpc_blocks = [
@@ -845,8 +846,9 @@ def build_anat_preproc_stack(rpool, cfg, pipeline_blocks=None):
845846
anat_blocks = anat_preproc_blocks + acpc_blocks
846847

847848
pipeline_blocks += anat_blocks
848-
849-
pipeline_blocks += [freesurfer_abcd_preproc]
849+
850+
if not rpool.check_rpool('freesurfer-subject-dir'):
851+
pipeline_blocks += [freesurfer_abcd_preproc]
850852

851853
# Anatomical T1 brain masking
852854
if not rpool.check_rpool('space-T1w_desc-brain_mask') or \
@@ -947,9 +949,11 @@ def build_T1w_registration_stack(rpool, cfg, pipeline_blocks=None):
947949
if not rpool.check_rpool('from-T1w_to-template_mode-image_xfm'):
948950
reg_blocks = [
949951
[register_ANTs_anat_to_template, register_FSL_anat_to_template],
950-
overwrite_transform_anat_to_template,
951-
correct_restore_brain_intensity_abcd # ABCD-options pipeline
952+
overwrite_transform_anat_to_template
952953
]
954+
955+
if not rpool.check_rpool('desc-restore-brain_T1w'):
956+
reg_blocks.append(correct_restore_brain_intensity_abcd)
953957

954958
if cfg.voxel_mirrored_homotopic_connectivity['run']:
955959
if not rpool.check_rpool('from-T1w_to-symtemplate_mode-image_xfm'):
@@ -970,7 +974,6 @@ def build_segmentation_stack(rpool, cfg, pipeline_blocks=None):
970974
seg_blocks = [
971975
[tissue_seg_fsl_fast,
972976
tissue_seg_ants_prior]
973-
#tissue_seg_freesurfer
974977
]
975978
if 'T1_Template' in cfg.segmentation['tissue_segmentation'][
976979
'Template_Based']['template_for_segmentation']:
@@ -1046,10 +1049,7 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None,
10461049
pipeline_blocks = build_segmentation_stack(rpool, cfg, pipeline_blocks)
10471050

10481051
# Functional Preprocessing, including motion correction and BOLD masking
1049-
if cfg.functional_preproc['run'] and \
1050-
(not rpool.check_rpool('desc-brain_bold') or
1051-
not rpool.check_rpool('space-bold_desc-brain_mask') or
1052-
not rpool.check_rpool('movement-parameters')):
1052+
if cfg.functional_preproc['run']:
10531053
func_init_blocks = [
10541054
func_scaling,
10551055
func_truncate
@@ -1059,16 +1059,21 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None,
10591059
func_slice_time,
10601060
func_reorient
10611061
]
1062+
1063+
if not rpool.check_rpool('desc-mean_bold'):
1064+
func_preproc_blocks.append(func_mean)
1065+
1066+
func_mask_blocks = []
1067+
if not rpool.check_rpool('space-bold_desc-brain_mask'):
1068+
func_mask_blocks = [
1069+
[bold_mask_afni, bold_mask_fsl, bold_mask_fsl_afni,
1070+
bold_mask_anatomical_refined, bold_mask_anatomical_based,
1071+
bold_mask_anatomical_resampled, bold_mask_ccs],
1072+
bold_masking]
1073+
10621074
func_prep_blocks = [
1063-
[bold_mask_afni, bold_mask_fsl, bold_mask_fsl_afni,
1064-
bold_mask_anatomical_refined, bold_mask_anatomical_based,
1065-
bold_mask_anatomical_resampled,
1066-
bold_mask_ccs],
1067-
bold_masking,
10681075
calc_motion_stats,
1069-
func_mean,
1070-
func_normalize#,
1071-
#func_mask_normalize
1076+
func_normalize
10721077
]
10731078

10741079
# Distortion/Susceptibility Correction
@@ -1084,24 +1089,31 @@ def build_workflow(subject_id, sub_dict, cfg, pipeline_name=None,
10841089
distcor_blocks = [distcor_blocks]
10851090
func_prep_blocks += distcor_blocks
10861091

1087-
if cfg['functional_preproc']['motion_estimates_and_correction'][
1088-
'motion_estimates']['calculate_motion_first']:
1089-
func_motion_blocks = [
1090-
get_motion_ref,
1091-
func_motion_estimates,
1092-
motion_estimate_filter
1093-
]
1094-
func_blocks = func_init_blocks + func_motion_blocks + \
1095-
func_preproc_blocks + [func_motion_correct_only] + \
1096-
func_prep_blocks
1092+
func_motion_blocks = []
1093+
if not rpool.check_rpool('movement-parameters'):
1094+
if cfg['functional_preproc']['motion_estimates_and_correction'][
1095+
'motion_estimates']['calculate_motion_first']:
1096+
func_motion_blocks = [
1097+
get_motion_ref,
1098+
func_motion_estimates,
1099+
motion_estimate_filter
1100+
]
1101+
func_blocks = func_init_blocks + func_motion_blocks + \
1102+
func_preproc_blocks + [func_motion_correct_only] + \
1103+
func_mask_blocks + func_prep_blocks
1104+
else:
1105+
func_motion_blocks = [
1106+
get_motion_ref,
1107+
func_motion_correct,
1108+
motion_estimate_filter
1109+
]
1110+
func_blocks = func_init_blocks + func_preproc_blocks + \
1111+
func_motion_blocks + func_mask_blocks + \
1112+
func_prep_blocks
10971113
else:
1098-
func_motion_blocks = [
1099-
get_motion_ref,
1100-
func_motion_correct,
1101-
motion_estimate_filter
1102-
]
11031114
func_blocks = func_init_blocks + func_preproc_blocks + \
1104-
func_motion_blocks + func_prep_blocks
1115+
func_motion_blocks + func_mask_blocks + \
1116+
func_prep_blocks
11051117

11061118
pipeline_blocks += func_blocks
11071119

CPAC/pipeline/engine.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,6 +1466,12 @@ def ingress_raw_func_data(wf, rpool, cfg, data_paths, unique_id, part_id,
14661466
def ingress_output_dir(cfg, rpool, unique_id, creds_path=None):
14671467

14681468
out_dir = cfg.pipeline_setup['output_directory']['path']
1469+
1470+
if not os.path.isdir(out_dir):
1471+
print(f"\nOutput directory {out_dir} does not exist yet, "
1472+
"initializing.")
1473+
os.makedirs(out_dir)
1474+
14691475
source = False
14701476

14711477
if cfg.pipeline_setup['output_directory']['pull_source_once']:
@@ -1520,7 +1526,7 @@ def ingress_output_dir(cfg, rpool, unique_id, creds_path=None):
15201526
cpac_dir_anat = os.path.join(cpac_dir, 'anat')
15211527
cpac_dir_func = os.path.join(cpac_dir, 'func')
15221528

1523-
exts = ['.nii', '.gz', '.mat', '.1D', '.txt', '.csv', '.rms']
1529+
exts = ['.nii', '.gz', '.mat', '.1D', '.txt', '.csv', '.rms', '.mgz']
15241530

15251531
all_output_dir = []
15261532
if os.path.isdir(cpac_dir_anat):
@@ -1562,10 +1568,6 @@ def ingress_output_dir(cfg, rpool, unique_id, creds_path=None):
15621568

15631569
unique_data_label = str(data_label)
15641570

1565-
#if 'sub-' in data_label or 'ses-' in data_label:
1566-
# raise Exception('\n\n[!] Possibly wrong participant or '
1567-
# 'session in this directory?\n\nDirectory: '
1568-
# f'{cpac_dir_anat}\nFilepath: {filepath}\n\n')
15691571
suffix = data_label.split('_')[-1]
15701572
desc_val = None
15711573
for tag in data_label.split('_'):
@@ -1578,16 +1580,21 @@ def ingress_output_dir(cfg, rpool, unique_id, creds_path=None):
15781580
jsonpath = f"{jsonpath}.json"
15791581

15801582
if not os.path.exists(jsonpath):
1581-
print(f'\n\n[!] No JSON found for file {filepath}.\nCreating '
1582-
f'{jsonpath}..\n\n')
1583+
print(f'\n\n[!] No JSON found for file {filepath}.')
1584+
if not source:
1585+
print(f'Creating {jsonpath}..\n\n')
1586+
else:
1587+
print('Creating meta-data for the data..\n\n')
15831588
json_info = {
1589+
'CpacProvenance': [f'{data_label}:Non-C-PAC Origin'],
15841590
'Description': 'This data was generated elsewhere and '
15851591
'supplied by the user into this C-PAC run\'s '
15861592
'output directory. This JSON file was '
15871593
'automatically generated by C-PAC because a '
15881594
'JSON file was not supplied with the data.'
15891595
}
1590-
write_output_json(json_info, jsonpath)
1596+
if not source:
1597+
write_output_json(json_info, jsonpath)
15911598
else:
15921599
json_info = read_json(jsonpath)
15931600

@@ -1664,7 +1671,7 @@ def ingress_pipeconfig_paths(cfg, rpool, unique_id, creds_path=None):
16641671
res_keys = [x.lstrip() for x in resolution.split(',')]
16651672
tag = res_keys[-1]
16661673

1667-
json_info = {}
1674+
json_info = {}
16681675

16691676
if '$FSLDIR' in val:
16701677
val = val.replace('$FSLDIR', cfg.pipeline_setup[
@@ -1722,7 +1729,20 @@ def ingress_pipeconfig_paths(cfg, rpool, unique_id, creds_path=None):
17221729
)
17231730
rpool.set_data(key, config_ingress, 'outputspec.data', json_info,
17241731
"", f"{key}_config_ingress")
1725-
1732+
1733+
# Freesurfer directory, not a template, so not in cpac_templates.tsv
1734+
if cfg.surface_analysis['freesurfer']['freesurfer_dir']:
1735+
fs_ingress = create_general_datasource(f'gather_freesurfer_dir')
1736+
fs_ingress.inputs.inputnode.set(
1737+
unique_id=unique_id,
1738+
data=cfg.surface_analysis['freesurfer']['freesurfer_dir'],
1739+
creds_path=creds_path,
1740+
dl_dir=cfg.pipeline_setup['working_directory']['path']
1741+
)
1742+
rpool.set_data("freesurfer-subject-dir", fs_ingress, 'outputspec.data',
1743+
json_info, "", f"freesurfer_config_ingress")
1744+
1745+
17261746
# templates, resampling from config
17271747
'''
17281748
template_keys = [

CPAC/pipeline/schema.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ def _changes_1_8_0_to_1_8_1(config_dict):
682682
'freesurfer': {
683683
'run': bool,
684684
'reconall_args': Maybe(str),
685+
'freesurfer_dir': Maybe(str)
685686
},
686687
'post_freesurfer': {
687688
'run': bool,

CPAC/registration/registration.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,14 +2424,15 @@ def overwrite_transform_anat_to_template(wf, cfg, strat_pool, pipe_num, opt=None
24242424
"option_key": ["registration_workflows", "anatomical_registration",
24252425
"overwrite_transform", "using"],
24262426
"option_val": "FSL",
2427-
"inputs": ["desc-restore-brain_T1w",
2428-
["desc-brain_T1w", "space-longitudinal_desc-brain_T1w"],
2429-
["desc-restore_T1w", "desc-preproc_T1w", "desc-reorient_T1w", "T1w"],
2430-
["desc-preproc_T1w", "desc-reorient_T1w", "T1w"],
2431-
"space-T1w_desc-brain_mask",
2432-
"T1w-template",
2433-
"from-T1w_to-template_mode-image_xfm",
2434-
"from-template_to-T1w_mode-image_xfm"],
2427+
"inputs": [("desc-restore-brain_T1w",
2428+
["desc-brain_T1w", "space-longitudinal_desc-brain_T1w"],
2429+
["desc-restore_T1w", "desc-preproc_T1w", "desc-reorient_T1w", "T1w"],
2430+
["desc-preproc_T1w", "desc-reorient_T1w", "T1w"],
2431+
"space-T1w_desc-brain_mask",
2432+
"T1w-template",
2433+
"from-T1w_to-template_mode-image_xfm",
2434+
"from-template_to-T1w_mode-image_xfm",
2435+
"space-template_desc-brain_T1w")],
24352436
"outputs": ["space-template_desc-brain_T1w",
24362437
"space-template_desc-head_T1w",
24372438
"space-template_desc-T1w_mask",

CPAC/resources/cpac_outputs.tsv

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ rh-pial-surface-mesh surface-derived anat
139139
raw-average surface-derived anat
140140
lh-smoothed-surface-mesh surface-derived anat
141141
rh-smoothed-surface-mesh surface-derived anat
142+
space-fsLR_den-32k_bold-dtseries surface-derived anat
142143
lh-spherical-surface-mesh surface-derived anat Yes
143144
rh-spherical-surface-mesh surface-derived anat Yes
144145
lh-sulcal-depth-surface-maps surface-derived anat Yes
@@ -147,10 +148,13 @@ lh-surface-curvature surface-derived anat
147148
rh-surface-curvature surface-derived anat
148149
lh-white-matter-surface-mesh surface-derived anat Yes
149150
rh-white-matter-surface-mesh surface-derived anat Yes
151+
wmparc surface-derived anat Yes
150152
space-symtemplate_desc-brain_T1w T1w symmetric template anat NIfTI
151153
desc-brain_T1w T1w T1w anat NIfTI
152154
desc-preproc_T1w T1w T1w anat NIfTI
153155
desc-reorient_T1w T1w T1w anat NIfTI
156+
desc-restore_T1w T1w T1w anat NIfTI
157+
desc-restore-brain_T1w T1w T1w anat NIfTI
154158
space-template_desc-brain_T1w T1w template anat NIfTI
155159
desc-Mean_timeseries timeseries func 1D
156160
desc-MeanSCA_timeseries timeseries func 1D
@@ -194,4 +198,4 @@ from-template_to-longitudinal_mode-image_desc-nonlinear_xfm xfm anat NIfTI
194198
from-template_to-longitudinal_mode-image_xfm xfm anat NIfTI
195199
from-template_to-T1w_mode-image_desc-linear_xfm xfm anat NIfTI
196200
from-template_to-T1w_mode-image_desc-nonlinear_xfm xfm anat NIfTI
197-
from-template_to-T1w_mode-image_xfm xfm anat NIfTI
201+
from-template_to-T1w_mode-image_xfm xfm anat NIfTI

CPAC/surface/surf_preproc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def surface_connector(wf, cfg, strat_pool, pipe_num, opt):
116116
wf.connect(node, out, surf, 'scout_bold')
117117

118118
outputs = {
119-
'space-fsLR_den-32k_bold.dtseries': (surf, 'out_file')
119+
'space-fsLR_den-32k_bold-dtseries': (surf, 'out_file')
120120
}
121121

122122
return wf, outputs
@@ -136,9 +136,9 @@ def surface_preproc(wf, cfg, strat_pool, pipe_num, opt=None):
136136
"from-template_to-T1w_mode-image_xfm",
137137
"space-template_desc-brain_bold",
138138
"space-template_desc-scout_bold"],
139-
"outputs": ["space-fsLR_den-32k_bold.dtseries"]}
139+
"outputs": ["space-fsLR_den-32k_bold-dtseries"]}
140140
'''
141141

142142
wf, outputs = surface_connector(wf, cfg, strat_pool, pipe_num, opt)
143143

144-
return (wf, outputs)
144+
return (wf, outputs)

CPAC/utils/bids_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ def bids_decode_fname(file_path, dbg=False, raise_error=True):
3030

3131
if len(sub) > 1:
3232
print("Odd that there is more than one subject directory" +
33-
"in (%s), does the filename conform to" % file_path +
34-
" BIDS format?")
33+
"in (%s), does the filename conform to" % file_path +
34+
" BIDS format?")
3535
if sub:
3636
sub_ndx = file_path_vals.index(sub[0])
3737
if sub_ndx > 0 and file_path_vals[sub_ndx - 1]:

dev/docker_data/default_pipeline.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ surface_analysis:
162162

163163
# Add extra arguments to recon-all command
164164
reconall_args: None
165+
166+
# (Optional) Provide an already-existing FreeSurfer output directory to ingress already-computed surfaces
167+
freesurfer_dir: None
165168

166169
# Run ABCD-HCP post FreeSurfer and fMRISurface pipeline
167170
post_freesurfer:

0 commit comments

Comments
 (0)