Skip to content

Commit

Permalink
Update to match neurodatascience/nipoppy:main (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
michellewang authored Oct 12, 2023
2 parents 3e54b4c + 543bea7 commit 5dea76d
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 170 deletions.
31 changes: 24 additions & 7 deletions nipoppy/extractors/freesurfer/run_FS_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ def get_mris_preproc_cmd(FS_dir, participants_list, out_file, meas="thickness",
"""
participants_str_list = []
for participant in participants_list:
dirpath = Path(f"{FS_dir}/{participant}")
dirpath_status = Path.is_dir(dirpath)
if dirpath_status:
fpath_lh = Path(f"{FS_dir}/{participant}/surf/lh.thickness")
fpath_rh = Path(f"{FS_dir}/{participant}/surf/rh.thickness")
fpath_status = Path.is_file(fpath_lh) & Path.is_file(fpath_rh)
if fpath_status:
participants_str_list.append(f"--s {participant}")
else:
print(f"ignoring {participant} with missing surf files...")

participants_str = ' '.join(participants_str_list)
FS_CMD_dict = {}
Expand Down Expand Up @@ -61,7 +64,7 @@ def run(FS_dir, participants_list, out_file, meas, fwhm, template):
parser = argparse.ArgumentParser(description=HELPTEXT)
parser.add_argument('--global_config', type=str, help='path to global config file for your nipoppy dataset', required=True)
parser.add_argument('--session_id', type=str, help='session_id', required=True)
parser.add_argument('--visit_id', type=str, help='visit_id', required=True)
parser.add_argument('--visit_id', type=str, default=None, help='visit_id')
parser.add_argument('--group', type=str, default=None, help='filter participants based on a specific group value in the csv')
parser.add_argument('--output_dir', type=str, default=None, help='out_file path for the processed / aggregated output')
parser.add_argument('--meas', type=str, default="thickness", help='cortical measure')
Expand All @@ -81,7 +84,11 @@ def run(FS_dir, participants_list, out_file, meas, fwhm, template):
template = args.template

session = f"ses-{session_id}"
visit = f"V{visit_id}"

if visit_id is None:
visit = f"V{session_id}"
else:
visit = f"V{visit_id}"

# Read global config
with open(global_config_file, 'r') as f:
Expand All @@ -99,9 +106,13 @@ def run(FS_dir, participants_list, out_file, meas, fwhm, template):
FS_dir = f"{dataset_root}/derivatives/freesurfer/v{FS_VERSION}/output/{session}/"
FS_license = f"{FS_dir}/license.txt"



if output_dir is None:
output_dir = f"{dataset_root}/derivatives/freesurfer/v{FS_VERSION}/surfmaps/{session}/"

Path(f"{output_dir}").mkdir(parents=True, exist_ok=True)

# grab bids_ids
manifest = f"{dataset_root}/tabular/manifest.csv"

Expand All @@ -114,6 +125,13 @@ def run(FS_dir, participants_list, out_file, meas, fwhm, template):
# Read participant lists and filter by session and group
manifest_df = pd.read_csv(manifest)
manifest_df = manifest_df[manifest_df["session"] == session]

if "bids_id" not in manifest_df.columns:
# Append bids id col from id_map_file (participant_id --> bids_id)
id_mapping_csv = f"{dataset_root}/scratch/participant_id_bids_id_map.csv"
id_mapping_df = pd.read_csv(id_mapping_csv)
manifest_df = pd.merge(manifest_df, id_mapping_df[["participant_id","bids_id"]], on=["participant_id"])

manifest_df = manifest_df[~manifest_df["bids_id"].isna()]
n_bids = len(manifest_df["bids_id"].unique())

Expand Down Expand Up @@ -150,9 +168,8 @@ def run(FS_dir, participants_list, out_file, meas, fwhm, template):

out_file = f"/output_dir/surf_concat_{group}_{fwhm}mm.mgh"

run(FS_dir, proc_participants, out_file, meas, fwhm, template)

print("Running mris_preproc separately for left and right hemisphere\n")
run(FS_dir, proc_participants, out_file, meas, fwhm, template)

print(" -"*30)
print("")
Expand Down
255 changes: 168 additions & 87 deletions nipoppy/sample_run_nipoppy.py

Large diffs are not rendered by default.

26 changes: 14 additions & 12 deletions nipoppy/trackers/bids_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"func": ["bold"]
}

def check_staus(bids_layout, participant_id, session_id, run_id, datatype):
def check_status(bids_layout, participant_id, session_id, datatype, run_id, acq_label):
# Remove non-alphanumeric characters from participant_id
participant_id = participant_id_to_dicom_id(participant_id)
suffix_list = files_dict[datatype]
Expand All @@ -27,13 +27,15 @@ def check_staus(bids_layout, participant_id, session_id, run_id, datatype):
scan_file = bids_layout.get(subject=participant_id,
session=session_id,
datatype=datatype,
acquisition=acq_label,
run=run_id,
suffix=suffix,
extension='nii.gz')

sidecar_file = bids_layout.get(subject=participant_id,
session=session_id,
datatype=datatype,
acquisition=acq_label,
run=run_id,
suffix=suffix,
extension='json')
Expand All @@ -53,29 +55,29 @@ def check_staus(bids_layout, participant_id, session_id, run_id, datatype):

return status_msg

def check_T1w(bids_layout, participant_id, session_id, run_id):
def check_T1w(bids_layout, participant_id, session_id, run_id, acq_label=None):
datatype = "anat"
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype)
status = check_status(bids_layout, participant_id, session_id, datatype, run_id, acq_label)
return status

def check_dwi(bids_layout, participant_id, session_id, run_id):
def check_dwi(bids_layout, participant_id, session_id, run_id, acq_label=None):
datatype = "dwi"
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype)
status = check_status(bids_layout, participant_id, session_id, datatype, run_id, acq_label)
return status

def check_fmap(bids_layout, participant_id, session_id, run_id):
def check_fmap(bids_layout, participant_id, session_id, run_id, acq_label=None):
datatype = "fmap"
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype)
status = check_status(bids_layout, participant_id, session_id, datatype, run_id, acq_label)
return status

def check_func(bids_layout, participant_id, session_id, run_id):
def check_func(bids_layout, participant_id, session_id, run_id, acq_label=None):
datatype = "func"
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype)
status = check_status(bids_layout, participant_id, session_id, datatype, run_id, acq_label)
return status

def check_structural(bids_layout, participant_id, session_id, run_id):
T1_status = check_T1w(bids_layout, participant_id, session_id, run_id)
dwi_status = check_dwi(bids_layout, participant_id, session_id, run_id)
def check_structural(bids_layout, participant_id, session_id, run_id, acq_label=None):
T1_status = check_T1w(bids_layout, participant_id, session_id, run_id, acq_label)
dwi_status = check_dwi(bids_layout, participant_id, session_id, run_id, acq_label)
if (T1_status == SUCCESS) & (dwi_status == SUCCESS):
status = SUCCESS
else:
Expand Down
60 changes: 38 additions & 22 deletions nipoppy/trackers/fmriprep_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# sub-MNI0056D864854_ses-01_task-rest_run-1_space-T1w_desc-preproc_bold.nii.gz
# sub-MNI0056D864854_ses-01_task-rest_run-1_space-T1w_desc-brain_mask.json
# sub-PD01134_ses-01_task-rest_run-1_space-MNI152NLin2009cSym_res-1_desc-brain_mask.json
# sub-YLOPD160_ses-01_acq-bold_run-1_magnitude1.json (ACQ)

# Globals (any one of this would qualify as success)
default_tpl_spaces = ["MNI152NLin2009cAsym","MNI152NLin2009cSym"]
Expand All @@ -30,11 +31,16 @@
"preproc_bold.nii": "desc-preproc_bold.nii.gz",
}

def check_output(subject_dir, file_check_dict, session_id, run_id, modality,
tpl_spaces=default_tpl_spaces, tpl_resolutions=default_tpl_resolutions, task=None):
def check_output(subject_dir, file_check_dict, session_id, run_id, acq_label, modality,
tpl_spaces=default_tpl_spaces, tpl_resolutions=default_tpl_resolutions, task_label=None):

# bids file-name tags in the correct order
bids_id = os.path.basename(subject_dir)
session = f"ses-{session_id}"
task = f"task-{task_label}"
acq = f"acq-{acq_label}"
run = f"run-{run_id}"
participant_id = os.path.basename(subject_dir)

status_msg = SUCCESS
for k,v in file_check_dict.items():
if status_msg == SUCCESS:
Expand All @@ -43,16 +49,24 @@ def check_output(subject_dir, file_check_dict, session_id, run_id, modality,
for tpl_res in tpl_resolutions:
file_suffix = f"space-{tpl_space}_{tpl_res}_{v}"
if modality == "anat":
if run_id == None:
filepath = Path(f"{subject_dir}/{session}/{modality}/{participant_id}_{session}_{file_suffix}")
if (run_id == None) & (acq_label == None):
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{file_suffix}")
elif (run_id == None) & (acq_label != None):
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{acq}_{file_suffix}")
elif (run_id != None) & (acq_label == None):
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{run}_{file_suffix}")
else:
filepath = Path(f"{subject_dir}/{session}/{modality}/{participant_id}_{session}_{run}_{file_suffix}")
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{acq}_{run}_{file_suffix}")

elif modality == "func":
if run_id == None:
filepath = Path(f"{subject_dir}/{session}/{modality}/{participant_id}_{session}_{task}_{file_suffix}")
if (run_id == None) & (acq_label == None):
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{task}_{file_suffix}")
elif (run_id == None) & (acq_label != None):
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{task}_{acq}_{file_suffix}")
elif (run_id != None) & (acq_label == None):
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{task}_{run}_{file_suffix}")
else:
filepath = Path(f"{subject_dir}/{session}/{modality}/{participant_id}_{session}_{task}_{run}_{file_suffix}")
filepath = Path(f"{subject_dir}/{session}/{modality}/{bids_id}_{session}_{task}_{acq}_{run}_{file_suffix}")

else:
print(f"Unknown modality: {modality}")
Expand All @@ -69,67 +83,69 @@ def check_output(subject_dir, file_check_dict, session_id, run_id, modality,

return status_msg

def check_anat_output(subject_dir, session_id, run_id):
def check_anat_output(subject_dir, session_id, run_id, acq_label=None):
""" Check output paths for anat stream
"""
modality = "anat"
status_msg = check_output(subject_dir, anat_files_dict, session_id, run_id, modality)
status_msg = check_output(subject_dir, anat_files_dict, session_id, run_id, acq_label, modality)

return status_msg

def check_func_output(subject_dir, session_id, run_id, task="task-rest"):
def check_func_output(subject_dir, session_id, run_id, acq_label=None, task_label="rest"):
""" Check output paths for func stream
"""
modality = "func"
status_msg = check_output(subject_dir, func_files_dict, session_id, run_id, modality, task=task)
status_msg = check_output(subject_dir, func_files_dict, session_id, run_id, acq_label, modality, task_label=task_label)

return status_msg

# TODO
def check_MNI152NLin2009cSym(subject_dir, session_id, run_id):
# TODO ------------------ Add custom trackers ------------------
def check_MNI152NLin2009cSym(subject_dir, session_id, run_id, acq_label=None):
""" Checks availability of MNI152NLin2009cSym space images
"""
custom_tpl_spaces = ["MNI152NLin2009cSym"]
custom_tpl_resolutions = ["res-1"]
modality = "anat"
file_dict = anat_files_dict
status_msg = check_output(subject_dir, file_dict, session_id, run_id, modality,
status_msg = check_output(subject_dir, file_dict, session_id, run_id, acq_label, modality,
tpl_spaces=custom_tpl_spaces, tpl_resolutions=custom_tpl_resolutions)
return status_msg

def check_MNI152NLin2009cAsym(subject_dir, session_id, run_id):
def check_MNI152NLin2009cAsym(subject_dir, session_id, run_id, acq_label=None):
""" Checks availability of MNI152NLin2009cAsym space images
"""
custom_tpl_spaces = ["MNI152NLin2009cAsym"]
custom_tpl_resolutions = ["res-1"]
modality = "anat"
file_dict = anat_files_dict
status_msg = check_output(subject_dir, file_dict, session_id, run_id, modality,
status_msg = check_output(subject_dir, file_dict, session_id, run_id, acq_label, modality,
tpl_spaces=custom_tpl_spaces, tpl_resolutions=custom_tpl_resolutions)
return status_msg

def check_MNI152NLin6Sym(subject_dir, session_id, run_id):
def check_MNI152NLin6Sym(subject_dir, session_id, run_id, acq_label=None):
""" Checks availability of MNI152NLin6Sym space images
"""
custom_tpl_spaces = ["MNI152NLin6Sym"]
custom_tpl_resolutions = ["res-1"]
modality = "anat"
file_dict = anat_files_dict
status_msg = check_output(subject_dir, file_dict, session_id, run_id, modality,
status_msg = check_output(subject_dir, file_dict, session_id, run_id, acq_label, modality,
tpl_spaces=custom_tpl_spaces, tpl_resolutions=custom_tpl_resolutions)
return status_msg

def check_MNI152Lin(subject_dir, session_id, run_id):
def check_MNI152Lin(subject_dir, session_id, run_id, acq_label=None):
""" Checks availability of MNI152Lin space images
"""
custom_tpl_spaces = ["MNI152Lin"]
custom_tpl_resolutions = ["res-1"]
modality = "anat"
file_dict = anat_files_dict
status_msg = check_output(subject_dir, file_dict, session_id, run_id, modality,
status_msg = check_output(subject_dir, file_dict, session_id, run_id, acq_label, modality,
tpl_spaces=custom_tpl_spaces, tpl_resolutions=custom_tpl_resolutions)
return status_msg

# TODO ------------------ Add custom trackers ------------------

tracker_configs = {
"pipeline_complete": check_anat_output,

Expand Down
4 changes: 2 additions & 2 deletions nipoppy/trackers/fs_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def check_stats(subject_dir, PARCELS=DEFAULT_PARCELS):

return filepath_status & aseg_status

def check_run_status(subject_dir, session_id=None, run_id=None):
def check_run_status(subject_dir, session_id=None, run_id=None, acq_label=None):
check_list = [check_fsdirs,check_mri,check_label,check_surf,check_stats]
status_list = []
for cl in check_list:
Expand All @@ -84,7 +84,7 @@ def check_run_status(subject_dir, session_id=None, run_id=None):
status_msg = FAIL
return status_msg

def check_parcels(subject_dir, session_id=None, run_id=None):
def check_parcels(subject_dir, session_id=None, run_id=None, acq_label=None):
stats_status = check_stats(subject_dir,ALL_PARCELS)
if stats_status:
status_msg = SUCCESS
Expand Down
Loading

0 comments on commit 5dea76d

Please sign in to comment.