Skip to content

Commit e6ab7df

Browse files
authored
Merge pull request #69 from childmindresearch/pybids
Adds pybids compatability layer to bids2table
2 parents 561057f + c5a46c3 commit e6ab7df

10 files changed

Lines changed: 1210 additions & 1 deletion

File tree

bids2table/pybids/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
__all__ = ["BIDSLayout", "BIDSFile", "Query", "listify"]
2+
3+
from ._bidsfile import BIDSFile
4+
from ._layout import BIDSLayout
5+
from ._utils import (
6+
Query,
7+
listify,
8+
)

bids2table/pybids/_bidsfile.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""
2+
BIDSFile wrapper for file paths with entity access.
3+
4+
Provides a PyBIDS-compatible file object that can parse and cache
5+
BIDS entities from file paths.
6+
"""
7+
8+
from typing import Any
9+
10+
from .._entities import parse_bids_entities
11+
12+
13+
class BIDSFile:
14+
"""
15+
Wrapper around a BIDS file path with entity parsing.
16+
17+
Provides PyBIDS-compatible interface for accessing file entities.
18+
Entities are lazily parsed and cached on first access.
19+
20+
Example:
21+
>>> from bids2table_compat import BIDSFile
22+
>>> f = BIDSFile('sub-01/func/sub-01_task-rest_bold.nii.gz')
23+
>>> entities = f.get_entities()
24+
>>> print(entities)
25+
{'sub': '01', 'task': 'rest', 'suffix': 'bold', 'ext': '.nii.gz'}
26+
"""
27+
28+
def __init__(self, path: str):
29+
"""
30+
Initialize BIDSFile.
31+
32+
Args:
33+
path: Path to BIDS file (absolute or relative)
34+
"""
35+
self.path = str(path)
36+
self._entities: dict[str, Any] | None = None
37+
38+
def get_entities(self) -> dict[str, Any]:
39+
"""
40+
Parse and return BIDS entities from filename.
41+
42+
Entities are cached after first parse for performance.
43+
44+
Returns:
45+
Dictionary of BIDS entities (e.g., {'sub': '01', 'task': 'rest'})
46+
"""
47+
if self._entities is None:
48+
self._entities = parse_bids_entities(self.path)
49+
return self._entities
50+
51+
def __str__(self) -> str:
52+
"""String representation showing file path."""
53+
return self.path
54+
55+
def __repr__(self) -> str:
56+
"""Developer-friendly representation."""
57+
return f"BIDSFile('{self.path}')"
58+
59+
def __eq__(self, other) -> bool:
60+
"""Equality based on path."""
61+
if isinstance(other, BIDSFile):
62+
return self.path == other.path
63+
return False
64+
65+
def __hash__(self) -> int:
66+
"""Allow use in sets/dicts."""
67+
return hash(self.path)
68+
69+
def __lt__(self, other) -> bool:
70+
"""Less-than comparison based on path (for sorting)."""
71+
if isinstance(other, BIDSFile):
72+
return self.path < other.path
73+
return NotImplemented
74+
75+
def __le__(self, other) -> bool:
76+
"""Less-than-or-equal comparison based on path."""
77+
if isinstance(other, BIDSFile):
78+
return self.path <= other.path
79+
return NotImplemented
80+
81+
def __gt__(self, other) -> bool:
82+
"""Greater-than comparison based on path."""
83+
if isinstance(other, BIDSFile):
84+
return self.path > other.path
85+
return NotImplemented
86+
87+
def __ge__(self, other) -> bool:
88+
"""Greater-than-or-equal comparison based on path."""
89+
if isinstance(other, BIDSFile):
90+
return self.path >= other.path
91+
return NotImplemented
92+
93+
def __contains__(self, item) -> bool:
94+
"""Check if substring is in the file path (for 'in' operator)."""
95+
return item in self.path

0 commit comments

Comments
 (0)