|
5 | 5 | import os
|
6 | 6 | import json
|
7 | 7 | from pathlib import Path
|
| 8 | +import sys |
8 | 9 |
|
9 | 10 |
|
10 | 11 | def write_bidsignore(deriv_dir):
|
@@ -186,3 +187,90 @@ def group_bolds_ref(*, layout, subject):
|
186 | 187 | assert len(combinations) == len(files), "Nonequal number of combinations and file buckets"
|
187 | 188 |
|
188 | 189 | return combinations, files
|
| 190 | + |
| 191 | + |
| 192 | +def validate_input_dir(exec_env, bids_dir, participant_label): |
| 193 | + # Ignore issues and warnings that should not influence NiBabies |
| 194 | + import tempfile |
| 195 | + import subprocess |
| 196 | + validator_config_dict = { |
| 197 | + "ignore": [ |
| 198 | + "EVENTS_COLUMN_ONSET", |
| 199 | + "EVENTS_COLUMN_DURATION", |
| 200 | + "TSV_EQUAL_ROWS", |
| 201 | + "TSV_EMPTY_CELL", |
| 202 | + "TSV_IMPROPER_NA", |
| 203 | + "VOLUME_COUNT_MISMATCH", |
| 204 | + "BVAL_MULTIPLE_ROWS", |
| 205 | + "BVEC_NUMBER_ROWS", |
| 206 | + "DWI_MISSING_BVAL", |
| 207 | + "INCONSISTENT_SUBJECTS", |
| 208 | + "INCONSISTENT_PARAMETERS", |
| 209 | + "BVEC_ROW_LENGTH", |
| 210 | + "B_FILE", |
| 211 | + "PARTICIPANT_ID_COLUMN", |
| 212 | + "PARTICIPANT_ID_MISMATCH", |
| 213 | + "TASK_NAME_MUST_DEFINE", |
| 214 | + "PHENOTYPE_SUBJECTS_MISSING", |
| 215 | + "STIMULUS_FILE_MISSING", |
| 216 | + "DWI_MISSING_BVEC", |
| 217 | + "EVENTS_TSV_MISSING", |
| 218 | + "TSV_IMPROPER_NA", |
| 219 | + "ACQTIME_FMT", |
| 220 | + "Participants age 89 or higher", |
| 221 | + "DATASET_DESCRIPTION_JSON_MISSING", |
| 222 | + "FILENAME_COLUMN", |
| 223 | + "WRONG_NEW_LINE", |
| 224 | + "MISSING_TSV_COLUMN_CHANNELS", |
| 225 | + "MISSING_TSV_COLUMN_IEEG_CHANNELS", |
| 226 | + "MISSING_TSV_COLUMN_IEEG_ELECTRODES", |
| 227 | + "UNUSED_STIMULUS", |
| 228 | + "CHANNELS_COLUMN_SFREQ", |
| 229 | + "CHANNELS_COLUMN_LOWCUT", |
| 230 | + "CHANNELS_COLUMN_HIGHCUT", |
| 231 | + "CHANNELS_COLUMN_NOTCH", |
| 232 | + "CUSTOM_COLUMN_WITHOUT_DESCRIPTION", |
| 233 | + "ACQTIME_FMT", |
| 234 | + "SUSPICIOUSLY_LONG_EVENT_DESIGN", |
| 235 | + "SUSPICIOUSLY_SHORT_EVENT_DESIGN", |
| 236 | + "MALFORMED_BVEC", |
| 237 | + "MALFORMED_BVAL", |
| 238 | + "MISSING_TSV_COLUMN_EEG_ELECTRODES", |
| 239 | + "MISSING_SESSION" |
| 240 | + ], |
| 241 | + "error": ["NO_T1W"], |
| 242 | + "ignoredFiles": ['/dataset_description.json', '/participants.tsv'] |
| 243 | + } |
| 244 | + # Limit validation only to data from requested participants |
| 245 | + if participant_label: |
| 246 | + all_subs = set([s.name[4:] for s in bids_dir.glob('sub-*')]) |
| 247 | + selected_subs = set([s[4:] if s.startswith('sub-') else s |
| 248 | + for s in participant_label]) |
| 249 | + bad_labels = selected_subs.difference(all_subs) |
| 250 | + if bad_labels: |
| 251 | + error_msg = 'Data for requested participant(s) label(s) not found. Could ' \ |
| 252 | + 'not find data for participant(s): %s. Please verify the requested ' \ |
| 253 | + 'participant labels.' |
| 254 | + if exec_env == 'docker': |
| 255 | + error_msg += ' This error can be caused by the input data not being ' \ |
| 256 | + 'accessible inside the docker container. Please make sure all ' \ |
| 257 | + 'volumes are mounted properly (see https://docs.docker.com/' \ |
| 258 | + 'engine/reference/commandline/run/#mount-volume--v---read-only)' |
| 259 | + if exec_env == 'singularity': |
| 260 | + error_msg += ' This error can be caused by the input data not being ' \ |
| 261 | + 'accessible inside the singularity container. Please make sure ' \ |
| 262 | + 'all paths are mapped properly (see https://www.sylabs.io/' \ |
| 263 | + 'guides/3.0/user-guide/bind_paths_and_mounts.html)' |
| 264 | + raise RuntimeError(error_msg % ','.join(bad_labels)) |
| 265 | + |
| 266 | + ignored_subs = all_subs.difference(selected_subs) |
| 267 | + if ignored_subs: |
| 268 | + for sub in ignored_subs: |
| 269 | + validator_config_dict["ignoredFiles"].append("/sub-%s/**" % sub) |
| 270 | + with tempfile.NamedTemporaryFile(mode='w+', suffix='.json') as temp: |
| 271 | + temp.write(json.dumps(validator_config_dict)) |
| 272 | + temp.flush() |
| 273 | + try: |
| 274 | + subprocess.check_call(['bids-validator', str(bids_dir), '-c', temp.name]) |
| 275 | + except FileNotFoundError: |
| 276 | + print("bids-validator does not appear to be installed", file=sys.stderr) |
0 commit comments