11from argparse import ArgumentParser
22from bids_validator import BIDSValidator
3- from os import walk , sep , listdir
3+ from os import walk , sep , listdir , path
44from typing import Union
55from pathlib import Path
66import json
77import subprocess
8+ import glob
9+ import sys
810
911
1012def collect_data_set (curl_download_file ):
@@ -24,8 +26,12 @@ def check_for_bids_validator_js():
2426
2527def report_number_of_files_bids_validator_js_found (input_folder : Union [str , Path ]) -> int :
2628 if check_for_bids_validator_js :
27- # run the js bids validator on the folder
28- js = subprocess .check_output (["bids-validator" , str (input_folder ), "--json" ])
29+ try :
30+ # run the js bids validator on the folder
31+ js = subprocess .check_output (["bids-validator" , str (input_folder ), "--json" ])
32+ except subprocess .CalledProcessError as e :
33+ js = e .output
34+
2935 validator_output = json .loads (js )
3036 totalFiles = validator_output .get ('summary' , {}).get ('totalFiles' )
3137 else :
@@ -54,7 +60,7 @@ def check_bids_valid(manifest: list) -> dict:
5460 validity = {}
5561 validator = BIDSValidator ()
5662 for file in manifest :
57- validity [str (file )] = {'ValidBids ' : validator .is_bids (str (file )), 'bidsignored' : False }
63+ validity [str (file )] = {'ValidBIDS ' : validator .is_bids (str (file )), 'bidsignored' : False }
5864 return validity
5965
6066
@@ -72,25 +78,160 @@ def collect_bidsignored(input_folder: Union[str, Path]) -> list:
7278 ignored = []
7379 print ("No .bidsignore file found" )
7480
81+ pop_index = []
82+ for entry in ignored :
83+ if entry .startswith ('#' ):
84+ pop_index .append (entry )
85+ elif entry == '' :
86+ pop_index .append (entry )
87+
88+ for index in pop_index :
89+ ignored .remove (index )
90+
7591 return ignored
7692
7793
78- def determine_if_file_is_ignored (validity : dict , bidsignore : list ) -> dict :
94+ def expand_bids_ignored (ignored : list , root_path : Union [str , Path ]) -> list :
95+ """given a bidsignore file, expand the entries to include all files that match the pattern"""
96+ expanded_paths = []
97+ for entry in ignored :
98+ if '*' in entry :
99+ matching_paths = glob .glob (str (Path (root_path ) / entry ))
100+ for path in matching_paths :
101+ if Path (path ).is_dir ():
102+ # if the path is a directory, add a trailing slash
103+ for root , dirs , files in walk (path ):
104+ for file in files :
105+ expanded_paths .append (str (Path (root ) / file ))
106+ if Path (path ).is_file ():
107+ expanded_paths .append (path )
108+ else :
109+ pass
110+
111+ # create a set from the expanded paths to remove duplicates
112+ expanded_paths = set (expanded_paths )
113+
114+ return list (expanded_paths )
115+
116+
117+ def determine_ignored_files (validity : dict , bidsignore : list , print_output = False ) -> dict :
79118 """
80119 Given a dict from check_bids_valid, determine if the valid file falls under the scope of the .bidsignore file
81120 """
121+ common_path = path .commonpath (bidsignore )
122+ all_bids_ignored = expand_bids_ignored (bidsignore , common_path )
123+
124+ for key in validity .keys ():
125+ for ignored in all_bids_ignored :
126+ if key in ignored :
127+ validity [key ]['bidsignored' ] = True
128+
129+ # count the number of valid but ignored files
130+ valid_and_ignored = []
131+ valid_bids_files = []
132+ valid_bids_files_not_ignored = []
133+ invalid_bids_files_and_ignored = []
134+ invalid_and_not_ignored = []
135+
82136 for k , v in validity .items ():
83- print (f"{ k } : { v } " )
137+ if v ['ValidBIDS' ] and v ['bidsignored' ]:
138+ valid_and_ignored .append (k )
139+ if v ['ValidBIDS' ]:
140+ valid_bids_files .append (k )
141+ if v ['ValidBIDS' ] and not v ['bidsignored' ]:
142+ valid_bids_files_not_ignored .append (k )
143+ if not v ['ValidBIDS' ] and v ['bidsignored' ]:
144+ invalid_bids_files_and_ignored .append (k )
145+ if not v ['ValidBIDS' ] and not v ['bidsignored' ]:
146+ invalid_and_not_ignored .append (k )
147+
148+ output = {
149+ 'valid_and_ignored' : valid_and_ignored ,
150+ 'valid_bids_files' : valid_bids_files ,
151+ 'valid_bids_files_not_ignored' : valid_bids_files_not_ignored ,
152+ 'invalid_bids_files_and_ignored' : invalid_bids_files_and_ignored ,
153+ 'invalid' : invalid_and_not_ignored
154+ }
155+
156+ if print_output :
157+ for k , v in output .items ():
158+ print (f"Found { len (v )} files that are { k } " )
159+ for file in v :
160+ print (file )
161+ print ("\n " )
162+
163+ return output
164+
165+
166+ def run_all (bids_dir ):
167+ """
168+ Run all the functions in this module.
169+ """
170+ manifest = make_manifest (bids_dir )
171+ bids_ignored = collect_bidsignored (bids_dir )
172+ check_if_valid = check_bids_valid (manifest )
173+ valid_bids_files = []
174+ invalid_bids_files = []
175+ for file , validity in check_if_valid .items ():
176+ if validity ['ValidBIDS' ]:
177+ valid_bids_files .append (file )
178+ if not validity ['ValidBIDS' ]:
179+ invalid_bids_files .append (file )
180+
181+ num_bids_validator_found = report_number_of_files_bids_validator_js_found (bids_dir )
182+
183+ all_bids_ignored = expand_bids_ignored (bids_ignored , bids_dir )
184+
185+ for key in check_if_valid .keys ():
186+ for ignored in all_bids_ignored :
187+ if key in ignored :
188+ check_if_valid [key ]['bidsignored' ] = True
84189
190+ file_lists = determine_ignored_files (check_if_valid , all_bids_ignored , print_output = True )
85191
192+ return file_lists
86193
87194if __name__ == "__main__" :
88195 parser = ArgumentParser ()
89- parser .add_argument ("input-folder" , help = "input folder to check for bids files" , type = str )
196+ parser .add_argument ("input_folder" , help = "input folder to check for bids files" , type = str )
197+ parser .add_argument ("--show-valid-and-ignored" , help = "show all valid and ignored files" , action = "store_true" )
198+ parser .add_argument ("--show-valid-bids-files" , help = "show all valid bids files" , action = "store_true" )
199+ parser .add_argument ("--show-valid-bids-files-not-ignored" , help = "show all valid bids files that are not ignored" ,
200+ action = "store_true" )
201+ parser .add_argument ("--show-invalid-bids-files-and-ignored" , help = "show all invalid bids files that are ignored" ,
202+ action = "store_true" )
203+ parser .add_argument ("--show-invalid" , help = "show all invalid files" , action = "store_true" )
204+
90205 args = parser .parse_args ()
91206 manifest = make_manifest (args .input_folder )
92207 check_if_valid = check_bids_valid (manifest )
208+ bidsignore = collect_bidsignored (args .input_folder )
209+ if not bidsignore :
210+ print ("Exiting" )
211+ sys .exit (1 )
212+ output = determine_ignored_files (check_if_valid , bidsignore , print_output = False )
213+ if not args .show_valid_and_ignored and not args .show_valid_bids_files and not args .show_valid_bids_files_not_ignored and not args .show_invalid_bids_files_and_ignored and not args .show_invalid :
214+ output = determine_ignored_files (check_if_valid , bidsignore , print_output = True )
215+ elif args .show_valid_and_ignored :
216+ print ("Found the following valid and ignored files:" )
217+ for file in output .get ('valid_and_ignored' ):
218+ print (file )
219+ elif args .show_valid_bids_files :
220+ print ("Found the following valid bids files:" )
221+ for file in output .get ('valid_bids_files' ):
222+ print (file )
223+ elif args .show_valid_bids_files_not_ignored :
224+ print ("Found the following valid bids files that are not ignored:" )
225+ for file in output .get ('valid_bids_files_not_ignored' ):
226+ print (file )
227+ elif args .show_invalid_bids_files_and_ignored :
228+ print ("Found the following invalid bids files that are ignored:" )
229+ for file in output .get ('invalid_bids_files_and_ignored' ):
230+ print (file )
231+ elif args .show_invalid :
232+ print ("Found the following invalid and ignored files:" )
233+ for file in output .get ('invalid' ):
234+ print (file )
235+ else :
236+ pass
93237
94-
95-
96- print ("stop" )
0 commit comments