forked from aces/EEG2BIDS
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
872 changed files
with
267,450 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
"""BIDS validator common Python package.""" | ||
from .bids_validator import BIDSValidator | ||
__all__ = ['BIDSValidator'] | ||
|
||
from . import _version | ||
__version__ = _version.get_versions()['version'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
|
||
# This file was generated by 'versioneer.py' (0.20) from | ||
# revision-control system data, or from the parent directory name of an | ||
# unpacked source archive. Distribution tarballs contain a pre-generated copy | ||
# of this file. | ||
|
||
import json | ||
|
||
version_json = ''' | ||
{ | ||
"date": "2022-03-28T15:30:05-0500", | ||
"dirty": false, | ||
"error": null, | ||
"full-revisionid": "fd78d856d5b3785456a9eb4659c223f5a15bc512", | ||
"version": "1.9.3" | ||
} | ||
''' # END VERSION_JSON | ||
|
||
|
||
def get_versions(): | ||
return json.loads(version_json) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
"""Validation class for BIDS projects.""" | ||
import re | ||
import os | ||
import json | ||
|
||
|
||
class BIDSValidator(): | ||
"""Object for BIDS (Brain Imaging Data Structure) verification. | ||
The main method of this class is `is_bids()`. You should use it for | ||
checking whether a file path is compatible with BIDS. | ||
""" | ||
|
||
def __init__(self, index_associated=True): | ||
"""Initialize BIDSValidator object. | ||
Parameters | ||
---------- | ||
index_associated : bool | ||
Specifies if an associated data should be checked. If it is true | ||
then any file paths in directories `code/`, `derivatives/`, | ||
`sourcedata/` and `stimuli/` will pass the validation, else they | ||
won't. Defaults to True. | ||
""" | ||
self.dir_rules = os.path.join(os.path.dirname(__file__)) + "/rules/" | ||
self.index_associated = index_associated | ||
|
||
def is_bids(self, path): | ||
"""Check if file path adheres to BIDS. | ||
Main method of the validator. uses other class methods for checking | ||
different aspects of the file path. | ||
Parameters | ||
---------- | ||
path : str | ||
Path of a file to be checked. Must be relative to root of a BIDS | ||
dataset. | ||
Notes | ||
----- | ||
When you test a file path, make sure that the path is relative to the | ||
root of the BIDS dataset the file is part of. That is, as soon as the | ||
file path contains parts outside of the BIDS dataset, the validation | ||
will fail. For example "home/username/my_dataset/participants.tsv" will | ||
fail, although "participants.tsv" is a valid BIDS file. | ||
Examples | ||
-------- | ||
>>> from bids_validator import BIDSValidator | ||
>>> validator = BIDSValidator() | ||
>>> filepaths = ["/sub-01/anat/sub-01_rec-CSD_T1w.nii.gz", | ||
... "/sub-01/anat/sub-01_acq-23_rec-CSD_T1w.exe", # wrong extension | ||
... "home/username/my_dataset/participants.tsv", # not relative to root | ||
... "/participants.tsv"] | ||
>>> for filepath in filepaths: | ||
... print(validator.is_bids(filepath)) | ||
True | ||
False | ||
False | ||
True | ||
""" | ||
conditions = [] | ||
|
||
conditions.append(self.is_top_level(path)) | ||
conditions.append(self.is_associated_data(path)) | ||
conditions.append(self.is_session_level(path)) | ||
conditions.append(self.is_subject_level(path)) | ||
conditions.append(self.is_phenotypic(path)) | ||
conditions.append(self.is_file(path)) | ||
|
||
return (any(conditions)) | ||
|
||
def is_top_level(self, path): | ||
"""Check if the file has appropriate name for a top-level file.""" | ||
regexps = self.get_regular_expressions(self.dir_rules + | ||
'top_level_rules.json') | ||
|
||
conditions = [False if re.compile(x).search(path) is None else True for | ||
x in regexps] | ||
|
||
return (any(conditions)) | ||
|
||
def is_associated_data(self, path): | ||
"""Check if file is appropriate associated data.""" | ||
if not self.index_associated: | ||
return False | ||
|
||
regexps = self.get_regular_expressions(self.dir_rules + | ||
'associated_data_rules.json') | ||
|
||
conditions = [(re.compile(x).search(path) is not None) for | ||
x in regexps] | ||
|
||
return any(conditions) | ||
|
||
def is_session_level(self, path): | ||
"""Check if the file has appropriate name for a session level.""" | ||
regexps = self.get_regular_expressions(self.dir_rules + | ||
'session_level_rules.json') | ||
|
||
conditions = [self.conditional_match(x, path) for x in regexps] | ||
|
||
return (any(conditions)) | ||
|
||
def is_subject_level(self, path): | ||
"""Check if the file has appropriate name for a subject level.""" | ||
regexps = self.get_regular_expressions(self.dir_rules + | ||
'subject_level_rules.json') | ||
|
||
conditions = [(re.compile(x).search(path) is not None) for | ||
x in regexps] | ||
|
||
return (any(conditions)) | ||
|
||
def is_phenotypic(self, path): | ||
"""Check if file is phenotypic data.""" | ||
regexps = self.get_regular_expressions(self.dir_rules + | ||
'phenotypic_rules.json') | ||
|
||
conditions = [(re.compile(x).search(path) is not None) for | ||
x in regexps] | ||
|
||
return (any(conditions)) | ||
|
||
def is_file(self, path): | ||
"""Check if file is phenotypic data.""" | ||
regexps = self.get_regular_expressions(self.dir_rules + | ||
'file_level_rules.json') | ||
|
||
conditions = [(re.compile(x).search(path) is not None) for | ||
x in regexps] | ||
|
||
return (any(conditions)) | ||
|
||
def get_regular_expressions(self, file_name): | ||
"""Read regular expressions from a file.""" | ||
regexps = [] | ||
|
||
with open(file_name, 'r') as fin: | ||
rules = json.load(fin) | ||
|
||
for key in list(rules.keys()): | ||
rule = rules[key] | ||
|
||
regexp = rule["regexp"] | ||
|
||
if "tokens" in rule: | ||
tokens = rule["tokens"] | ||
|
||
for token in list(tokens): | ||
regexp = regexp.replace(token, "|".join(tokens[token])) | ||
|
||
regexps.append(regexp) | ||
|
||
return regexps | ||
|
||
def conditional_match(self, expression, path): | ||
"""Find conditional match.""" | ||
match = re.compile(expression).findall(path) | ||
match = match[0] if len(match) >= 1 else False | ||
# adapted from JS code and JS does not support conditional groups | ||
if (match): | ||
if ((match[1] == match[2][1:]) | (not match[1])): | ||
return True | ||
else: | ||
return False | ||
else: | ||
return False |
Oops, something went wrong.