File: test_bids_validator.py

package info (click to toggle)
python-bids-validator 1.14.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 308 kB
  • sloc: python: 192; sh: 15; makefile: 7
file content (153 lines) | stat: -rw-r--r-- 5,282 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""Test BIDSValidator functionality.

git-annex and datalad are used to download a test data structure without the
actual file contents.

"""
import os

import pytest
import datalad.api

from bids_validator import BIDSValidator

HOME = os.path.expanduser('~')

TEST_DATA_DICT = {
    'eeg_matchingpennies': (
        'https://gin.g-node.org/sappelhoff/eeg_matchingpennies'
    ),
    }

EXCLUDE_KEYWORDS = ['git', 'datalad', 'sourcedata', 'bidsignore']


def _download_test_data(test_data_dict, dsname):
    """Download test data using datalad."""
    url = test_data_dict[dsname]
    dspath = os.path.join(HOME, dsname)
    datalad.api.clone(source=url, path=dspath)
    return dspath


def _gather_test_files(dspath, exclude_keywords):
    """Get test files from dataset path, relative to dataset."""
    files = []
    for r, _, f in os.walk(dspath):
        for file in f:
            fname = os.path.join(r, file)
            fname = fname.replace(dspath, '')
            if not any(keyword in fname for keyword in exclude_keywords):
                files.append(fname)

    return files


dspath = _download_test_data(TEST_DATA_DICT, 'eeg_matchingpennies')
files = _gather_test_files(dspath, EXCLUDE_KEYWORDS)


@pytest.fixture(scope='module')
def validator():
    """Return a BIDSValidator instance."""
    validator = BIDSValidator()
    return validator


@pytest.mark.parametrize('fname', files)
def test_datasets(validator, fname):
    """Test that is_bids returns true for each file in a valid BIDS dataset."""
    assert validator.is_bids(fname)


@pytest.mark.parametrize('fname, matches', [
    ('/T1w.json', True),
    ('/dataset_description.json', True),
    ('/README', True),
    ('/CHANGES', True),
    ('/participants.tsv', True),
    ('/sub-01/anat/sub-01_T1w.nii.gz', False),
])
def test_top_level(validator, fname, matches):
    """Test that is_top_level returns true for top-level files."""
    assert validator.is_top_level(fname) is matches


@pytest.mark.parametrize('fname, matches', [
    ('/sourcedata/unstructured_data.nii.gz', True),
    ('/sourcedata/dicom_dir/xyz.dcm', True),
    ('/code/my_analysis/analysis.py', True),
    ('/derivatives/preproc/sub-01/anat/sub-01_desc-preproc_T1w.nii.gz', True),
    ('/stimuli/pic.jpg', True),
    ('/sub-01/anat/sub-01_T1w.nii.gz', False),
])
def test_associated_data(validator, fname, matches):
    """Test that is_associated_data returns true for associated data."""
    assert validator.is_associated_data(fname) is matches


@pytest.mark.parametrize('fname, matches', [
    ('/sub-01/ses-1/sub-01_ses-1_scans.tsv', True),
    ('/sub-01/ses-1/sub-01_ses-1_scans.json', True),
    ('/sub-01/sub-01_scans.tsv', True),
    ('/sub-01/sub-01_scans.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_task-rest_bold.json', True),
    ('/sub-01/sub-01_task-rest_bold.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_asl.json', True),
    ('/sub-01/sub-01_asl.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_pet.json', True),
    ('/sub-01/sub-01_pet.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_proc-test_channels.tsv', True),
    ('/sub-01/ses-1/sub-01_ses-1_channels.json', True),
    ('/sub-01/sub-01_proc-test_channels.tsv', True),
    ('/sub-01/sub-01_channels.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_space-CapTrak_electrodes.tsv', True),
    ('/sub-01/ses-1/sub-01_ses-1_coordsystem.json', True),
    ('/sub-01/sub-01_space-CapTrak_electrodes.tsv', True),
    ('/sub-01/sub-01_coordsystem.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_motion.json', True),
    ('/sub-01/sub-01_motion.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_TEM.json', True),
    ('/sub-01/sub-01_TEM.json', True),
    ('/sub-01/ses-1/sub-01_ses-1_nirs.json', True),
    ('/sub-01/sub-01_nirs.json', True),
    # Mismatch sessions
    ('/sub-01/sub-01_ses-1_scans.tsv', False),
    ('/sub-01/sub-01_ses-1_scans.json', False),
    ('/sub-01/ses-1/sub-01_ses-2_scans.tsv', False),
    # File-level
    ('/sub-01/ses-1/func/sub-01_ses-1_task-rest_bold.nii.gz', False),
    ('/sub-01/anat/sub-01_T1w.nii.gz', False),
])
def test_session_level(validator, fname, matches):
    """Test that is_session_level returns true for session level files."""
    assert validator.is_session_level(fname) is matches


@pytest.mark.parametrize('fname, matches', [
    ('/sub-01/sub-01_sessions.tsv', True),
    ('/sub-01/sub-01_sessions.json', True),
    ('/sub-01/anat/sub-01_T1w.nii.gz', False),
])
def test_subject_level(validator, fname, matches):
    """Test that is_subject_level returns true for subject level files."""
    assert validator.is_subject_level(fname) is matches


@pytest.mark.parametrize('fname, matches', [
    ('/phenotype/measure.tsv', True),
    ('/phenotype/measure.json', True),
    ('/sub-01/anat/sub-01_T1w.nii.gz', False),
])
def test_phenotpic(validator, fname, matches):
    """Test that is_phenotypic returns true for phenotypic files."""
    assert validator.is_phenotypic(fname) is matches


@pytest.mark.parametrize('fname, matches', [
    ('/sub-01/ses-1/func/sub-01_ses-1_task-rest_bold.nii.gz', True),
    ('/sub-01/anat/sub-01_T1w.nii.gz', True),
])
def test_file_level(validator, fname, matches):
    """Test that is_file returns true for file level files."""
    assert validator.is_file(fname) is matches