Skip to content

Commit f6687e1

Browse files
authored
Merge pull request #79 from mgxd/fix/validation
FIX: Add BIDS validation
2 parents 5ce167e + 32b2e34 commit f6687e1

File tree

2 files changed

+99
-5
lines changed

2 files changed

+99
-5
lines changed

Dockerfile

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ RUN useradd -m -s /bin/bash -G users nibabies
126126
WORKDIR /home/nibabies
127127
ENV HOME="/home/nibabies"
128128

129+
# Install node + npm packages
130+
RUN curl -sSL https://deb.nodesource.com/setup_14.x | bash - && \
131+
apt-get install -y --no-install-recommends \
132+
nodejs && \
133+
npm install -g svgo [email protected] && \
134+
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ~/.npm ~/.empty
135+
129136
# Installing and setting up miniconda
130137
RUN curl -sSLO https://repo.continuum.io/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh && \
131138
bash Miniconda3-4.5.11-Linux-x86_64.sh -b -p /usr/local/miniconda && \
@@ -143,11 +150,10 @@ RUN conda install -y python=3.7.1 \
143150
numpy=1.20 \
144151
scipy=1.6 \
145152
scikit-learn=0.19 \
146-
matplotlib=2.2.2 \
147-
pandas=0.23.4 \
148-
libxml2=2.9.8 \
149-
libxslt=1.1.32 \
150-
graphviz=2.40.1 \
153+
matplotlib=2.2 \
154+
libxml2=2.9 \
155+
libxslt=1.1 \
156+
graphviz=2.40 \
151157
traits=4.6.0 \
152158
pip=19.1 \
153159
zlib; sync && \

nibabies/utils/bids.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os
66
import json
77
from pathlib import Path
8+
import sys
89

910

1011
def write_bidsignore(deriv_dir):
@@ -186,3 +187,90 @@ def group_bolds_ref(*, layout, subject):
186187
assert len(combinations) == len(files), "Nonequal number of combinations and file buckets"
187188

188189
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

Comments
 (0)