forked from nipoppy/nipoppy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update to match neurodatascience/nipoppy:main (#69)
- Loading branch information
Showing
12 changed files
with
413 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,94 +1,95 @@ | ||
import numpy as np | ||
import pandas as pd | ||
from pathlib import Path | ||
import argparse | ||
import glob | ||
from bids import BIDSLayout | ||
import os | ||
|
||
|
||
HELPTEXT = """ | ||
Script to check participant-session availability | ||
""" | ||
#Author: nikhil153 | ||
#Date: 1-Dec-2022 | ||
|
||
modality_suffic_dict = { | ||
"anat": "T1w", | ||
"dwi": "dwi" | ||
# Status flags | ||
from nipoppy.trackers.tracker import ( | ||
SUCCESS, | ||
FAIL | ||
) | ||
|
||
from nipoppy.workflow.utils import participant_id_to_dicom_id | ||
|
||
# File dicts per BIDS datatype | ||
# "datatype":"suffix" | ||
files_dict = { | ||
"anat": ["T1w"], | ||
"dwi": ["dwi"], | ||
"fmap": ["phasediff", "magnitude1", "magnitude2"], | ||
"func": ["bold"] | ||
} | ||
|
||
# argparse | ||
parser = argparse.ArgumentParser(description=HELPTEXT) | ||
|
||
# data | ||
parser.add_argument('--bids_dir', help='path to bids_dir with all the subjects') | ||
parser.add_argument('--modalities', nargs='*', default=["anat"], | ||
help='modalities to check') | ||
parser.add_argument('--file_ext', default='nii.gz', help='file extension to query') | ||
parser.add_argument('--output_csv', help='path to output csv file') | ||
|
||
args = parser.parse_args() | ||
bids_dir = args.bids_dir | ||
modalities = args.modalities | ||
file_ext = args.file_ext | ||
|
||
print(f"Validating output in: {modalities}") | ||
|
||
output_csv = args.output_csv | ||
participants_tsv = f"{bids_dir}/participants.tsv" | ||
|
||
# Check participants tsv and actual participant dirs | ||
tsv_participants = set(pd.read_csv(participants_tsv,sep="\t")["participant_id"].values) | ||
bids_dir_paths = glob.glob(f"{bids_dir}/sub*") | ||
bids_dir_participants = set([os.path.basename(x) for x in bids_dir_paths]) | ||
|
||
participants_missing_in_tsv = list(bids_dir_participants - tsv_participants) | ||
participants_missing_in_bids_dir = list(tsv_participants - bids_dir_participants) | ||
|
||
print(f"n_participants_tsv: {len(tsv_participants)}, \ | ||
n_participants_bids_dir: {len(bids_dir_participants)}, \ | ||
n_participants_missing_in_tsv: {len(participants_missing_in_tsv)}, \ | ||
n_participants_missing_in_bids_dir: {len(participants_missing_in_bids_dir)}") | ||
|
||
if tsv_participants == bids_dir_participants: | ||
layout = BIDSLayout(bids_dir) | ||
sessions = layout.get_sessions() | ||
|
||
bids_status_df = pd.DataFrame() | ||
for participant in tsv_participants: | ||
participant_id = participant.split("-",2)[1] | ||
|
||
session_df = pd.DataFrame(index=sessions, columns=modalities) | ||
for ses in sessions: | ||
f_count = [] | ||
for modality in modalities: | ||
file_suffix = modality_suffic_dict[modality] | ||
f = layout.get(subject=participant_id, | ||
session=ses, | ||
extension=file_ext, | ||
suffix=file_suffix, | ||
return_type='filename') | ||
|
||
f_count.append(len(f)) | ||
|
||
session_df.loc[ses] = f_count | ||
|
||
session_df = session_df.reset_index().rename(columns={"index":"session_id"}) | ||
session_df["participant_id"] = participant | ||
bids_status_df = bids_status_df.append(session_df) | ||
|
||
print(f"Saving bids_status_df at {output_csv}") | ||
bids_status_df = bids_status_df.set_index("participant_id") | ||
bids_status_df.to_csv(output_csv) | ||
|
||
else: | ||
print(f"participants_tsv and bids_dir participants mismatch...") | ||
output_csv = os.path.join(os.path.dirname(output_csv) + "/mismatched_participants.csv") | ||
missing_tsv_status = len(participants_missing_in_tsv) * ["participants_missing_in_tsv"] | ||
missing_bids_status = len(participants_missing_in_bids_dir) * ["participants_missing_in_bids_dir"] | ||
missing_df = pd.DataFrame() | ||
missing_df["participant_id"] = participants_missing_in_tsv + participants_missing_in_bids_dir | ||
missing_df["status"] = missing_tsv_status + missing_bids_status | ||
print(f"Saving missing participants csv at {output_csv}") | ||
missing_df.to_csv(output_csv,index=None) | ||
def check_staus(bids_layout, participant_id, session_id, run_id, datatype): | ||
# Remove non-alphanumeric characters from participant_id | ||
participant_id = participant_id_to_dicom_id(participant_id) | ||
suffix_list = files_dict[datatype] | ||
filepath_status_list = [] | ||
for suffix in suffix_list: | ||
scan_file = bids_layout.get(subject=participant_id, | ||
session=session_id, | ||
datatype=datatype, | ||
run=run_id, | ||
suffix=suffix, | ||
extension='nii.gz') | ||
|
||
sidecar_file = bids_layout.get(subject=participant_id, | ||
session=session_id, | ||
datatype=datatype, | ||
run=run_id, | ||
suffix=suffix, | ||
extension='json') | ||
|
||
|
||
if (len(scan_file) > 0) & (len(sidecar_file) > 0): | ||
filepath_status = (Path.is_file(Path(scan_file[0].path))) & (Path.is_file(Path(sidecar_file[0].path))) | ||
else: | ||
filepath_status = False | ||
|
||
filepath_status_list.append(filepath_status) | ||
|
||
if not any(filepath_status_list): | ||
status_msg = FAIL | ||
else: | ||
status_msg = SUCCESS | ||
|
||
return status_msg | ||
|
||
def check_T1w(bids_layout, participant_id, session_id, run_id): | ||
datatype = "anat" | ||
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype) | ||
return status | ||
|
||
def check_dwi(bids_layout, participant_id, session_id, run_id): | ||
datatype = "dwi" | ||
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype) | ||
return status | ||
|
||
def check_fmap(bids_layout, participant_id, session_id, run_id): | ||
datatype = "fmap" | ||
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype) | ||
return status | ||
|
||
def check_func(bids_layout, participant_id, session_id, run_id): | ||
datatype = "func" | ||
status = check_staus(bids_layout, participant_id, session_id, run_id, datatype) | ||
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) | ||
if (T1_status == SUCCESS) & (dwi_status == SUCCESS): | ||
status = SUCCESS | ||
else: | ||
status = FAIL | ||
|
||
return status | ||
|
||
tracker_configs = { | ||
"pipeline_complete": check_structural, | ||
|
||
"PHASE__": { | ||
"anat": check_T1w, | ||
"dwi": check_dwi, | ||
"fmap": check_fmap, | ||
"func": check_func | ||
} | ||
} |
Oops, something went wrong.