Skip to content

Commit

Permalink
Implemented an option for scan exclusion.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gab-D-G committed Sep 25, 2023
1 parent 0195ddc commit 32f3461
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 5 deletions.
3 changes: 2 additions & 1 deletion rabies/analysis_pkg/main_wf.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ def init_main_analysis_wf(preprocess_opts, cr_opts, analysis_opts):
""")

# filter inclusion/exclusion lists
from rabies.utils import filter_scan_inclusion
from rabies.utils import filter_scan_inclusion, filter_scan_exclusion
split_name_list = filter_scan_inclusion(analysis_opts.inclusion_ids, split_name_list)
split_name_list = filter_scan_exclusion(analysis_opts.exclusion_ids, split_name_list)

# setting up iterables from the BOLD scan splits
main_split = pe.Node(niu.IdentityInterface(fields=['split_name']),
Expand Down
3 changes: 2 additions & 1 deletion rabies/confound_correction_pkg/main_wf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ def init_main_confound_correction_wf(preprocess_opts, cr_opts):
split_dict, split_name, target_list = read_preproc_workflow(preproc_output, nativespace=cr_opts.nativespace_analysis)

# filter inclusion/exclusion lists
from rabies.utils import filter_scan_inclusion
from rabies.utils import filter_scan_inclusion, filter_scan_exclusion
split_name = filter_scan_inclusion(cr_opts.inclusion_ids, split_name)
split_name = filter_scan_exclusion(cr_opts.exclusion_ids, split_name)

# setting up iterables from the BOLD scan splits
main_split = pe.Node(niu.IdentityInterface(fields=['split_name']),
Expand Down
11 changes: 11 additions & 0 deletions rabies/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ def get_parser():
"(default: %(default)s)\n"
"\n"
)
g_execution.add_argument(
'--exclusion_ids', type=str,
nargs="*", # 0 or more values expected => creates a list
default=['none'],
help=
"Instead of providing a list of scans to include, this argument provides a list of scans to exclude (while \n"
"keeping all other scans). This argument follows the same syntax rules as --includion_ids. --exclusion_ids \n"
"and --inclusion_ids cannot be used simultaneously. \n"
"(default: %(default)s)\n"
"\n"
)
g_execution.add_argument(
"-p", "--plugin", default='Linear',
choices=['Linear', 'MultiProc', 'SGE', 'SGEGraph',
Expand Down
2 changes: 1 addition & 1 deletion rabies/preprocess_pkg/main_wf.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def init_main_wf(data_dir_path, output_folder, opts, name='main_wf'):
bids.config.set_option('extension_initial_dot', True)
layout = bids.layout.BIDSLayout(data_dir_path, validate=False)
split_name, scan_info, run_iter, scan_list, bold_scan_list = prep_bids_iter(
layout, opts.bold_only, inclusion_list=opts.inclusion_ids)
layout, opts.bold_only, inclusion_list=opts.inclusion_ids, exclusion_list=opts.exclusion_ids)

# setting up all iterables
main_split = pe.Node(niu.IdentityInterface(fields=['split_name', 'scan_info']),
Expand Down
5 changes: 3 additions & 2 deletions rabies/preprocess_pkg/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
)
from rabies.utils import run_command

def prep_bids_iter(layout, bold_only=False, inclusion_list=['all']):
def prep_bids_iter(layout, bold_only=False, inclusion_list=['all'], exclusion_list=['none']):
'''
This function takes as input a BIDSLayout, and generates iteration lists
for managing the workflow's iterables depending on whether --bold_only is
Expand Down Expand Up @@ -39,9 +39,10 @@ def prep_bids_iter(layout, bold_only=False, inclusion_list=['all']):
"No functional file with the suffix 'bold' were found among the BIDS directory.")

# filter inclusion/exclusion lists
from rabies.utils import filter_scan_inclusion
from rabies.utils import filter_scan_inclusion, filter_scan_exclusion
boldname_list=[pathlib.Path(bold.filename).name.rsplit(".nii")[0] for bold in bold_bids]
updated_split_name = filter_scan_inclusion(inclusion_list, boldname_list)
updated_split_name = filter_scan_exclusion(exclusion_list, updated_split_name)

filtered_bold_bids=[]
for name in updated_split_name:
Expand Down
7 changes: 7 additions & 0 deletions rabies/run_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ def execute_workflow(args=None):
args += input
log.info(args)

# inclusion/exclusion list are incompatible parameters
if (not opts.inclusion_ids[0]=='all') and (not opts.exclusion_ids[0]=='none'):
raise ValueError(f"""
Either an inclusion list (--inclusion_ids) or exclusion list (--exclusion_ids)
can be provided, not both.
""")

if opts.rabies_stage == 'preprocess':
workflow = preprocess(opts, log)
elif opts.rabies_stage == 'confound_correction':
Expand Down
33 changes: 33 additions & 0 deletions rabies/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,39 @@ def flatten_list(l):
return l


def filter_scan_exclusion(exclusion_list, split_name):
# the function removes a list of scan IDs from split_name

# exclusion_list: the input provided by the user
# split_name: a list of all scan IDs that were found

import numpy as np
import pandas as pd
if os.path.isfile(os.path.abspath(exclusion_list[0])):
updated_split_name=[]
if not '.nii' in pathlib.Path(exclusion_list[0]).name:
# read the file as a .txt
exclusion_list = np.array(pd.read_csv(os.path.abspath(exclusion_list[0]), header=None)).flatten()
for split in split_name:
exclude = False
for scan in exclusion_list:
if split in scan:
exclude = True
if not exclude:
updated_split_name.append(split)
elif exclusion_list[0]=='none':
updated_split_name = split_name
else:
raise ValueError(f"The --exclusion_ids {exclusion_list} input had improper format. It must the full path to a .txt or .nii files.")

if len(updated_split_name)==0:
raise ValueError(f"""
No scans are left after scan exclusion!
""")

return updated_split_name


def filter_scan_inclusion(inclusion_list, split_name):
# the function will update the list of scan IDs in split_name to correspond to inclusion/exclusion list

Expand Down

0 comments on commit 32f3461

Please sign in to comment.