Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1a9dfdb
added intial tests for Context class
ubdbra001 Sep 5, 2025
2db6ba9
Context class WIP
ubdbra001 Sep 5, 2025
5cc92f5
PR feedback changes
ubdbra001 Sep 8, 2025
0d427f4
add missing docstrings
ubdbra001 Sep 8, 2025
72dbbeb
add and use global mapping for datatype to modality
ubdbra001 Sep 8, 2025
eeb692f
add more tests for next stage
ubdbra001 Sep 9, 2025
3d70d8f
Merge branch 'main' into i32-develop-context-class
ubdbra001 Sep 24, 2025
7200e99
remove sessions.phenotype test
ubdbra001 Sep 24, 2025
729bf51
add sessions class
ubdbra001 Sep 24, 2025
96dd2dc
add subject as an input param for Context class
ubdbra001 Sep 24, 2025
1513ff8
Update and validate function
ubdbra001 Sep 24, 2025
685b978
Update walk function
ubdbra001 Sep 24, 2025
d2d9975
update tests
ubdbra001 Sep 24, 2025
441dd49
tidy for ruff
ubdbra001 Sep 24, 2025
fa203d1
add schema_path cli option
ubdbra001 Sep 24, 2025
3aa3fec
Update validate function
ubdbra001 Sep 24, 2025
fbbe129
feedback changes
ubdbra001 Sep 24, 2025
fdd4408
added tests for sidecar property
ubdbra001 Sep 24, 2025
ecc0f37
add sidecar method to context class
ubdbra001 Sep 24, 2025
0343be1
use orjson over built-in json package
ubdbra001 Sep 24, 2025
162a7c9
refine tests for sidecar
ubdbra001 Sep 24, 2025
fe42bb7
add test for json property
ubdbra001 Sep 24, 2025
adb4b75
ruffed test_context
ubdbra001 Sep 24, 2025
85f7733
add json property to context class
ubdbra001 Sep 24, 2025
6a90acc
feedback changes
ubdbra001 Sep 29, 2025
37df90a
update test for context.sidecar
ubdbra001 Sep 29, 2025
1360680
update typing for main
ubdbra001 Sep 29, 2025
e68bc1d
rf: Replace direntry with UPath in FileTree
effigies Sep 29, 2025
0d31404
test: Generate dataset in-memory, test sidecar overrides
effigies Sep 30, 2025
2fc29ed
Merge pull request #1 from effigies/rf/upath
ubdbra001 Oct 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions src/bids_validator/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,103 @@ def from_file(cls, file: FileTree, schema: Namespace) -> t.Self:
suffix=suffix,
extension=extension,
)


@attrs.define
class Context:
"""A context object that creates context for file on access."""

file: FileTree
dataset: Dataset
file_parts: FileParts = attrs.field(init=False)

def __attrs_post_init__(self):
self.file_parts = FileParts.from_file(self.file, self.schema)

@property
def schema(self) -> Namespace:
"""The BIDS specification schema."""
return self.dataset.schema

@property
def path(self) -> str:
"""Path of the current file."""
return self.file_parts.path

@property
def entities(self) -> dict[str, str] | None:
"""Entities parsed from the current filename."""
return self.file_parts.entities

@property
def datatype(self) -> str | None:
"""Datatype of current file, for examples, anat."""
return self.file_parts.datatype

@property
def suffix(self) -> str | None:
"""Suffix of current file."""
return self.file_parts.suffix

@property
def extension(self) -> str | None:
"""Extension of current file including initial dot."""
return self.file_parts.extension

@property
def modality(self) -> str | None:
"""Modality of current file, for examples, MRI."""
modalities = self.schema.rules.modalities
for mod_name, mod_dtypes in modalities.items():
if self.datatype in mod_dtypes.datatypes:
return mod_name

@property
def size(self) -> int:
"""Length of the current file in bytes."""
return self.file.direntry.stat().st_size

@property
def subject(self) -> ctx.Subject | None:
"""Properties and contents of the current subject."""
return ctx.Subject()

@property
def associations(self) -> ctx.Associations:
"""Associated files, indexed by suffix, selected according to the inheritance principle."""
return ctx.Associations()

@property
def columns(self) -> None:
"""TSV columns, indexed by column header, values are arrays with column contents."""
pass

@property
def json(self) -> None:
"""Contents of the current JSON file."""
pass

@property
def gzip(self) -> None:
"""Parsed contents of gzip header."""
pass

@property
def nifti_header(self) -> None:
"""Parsed contents of NIfTI header referenced elsewhere in schema."""
pass

@property
def ome(self) -> None:
"""Parsed contents of OME-XML header, which may be found in OME-TIFF or OME-ZARR files."""
pass

@property
def tiff(self) -> None:
"""TIFF file format metadata."""
pass

@property
def sidecar(self) -> None:
"""Sidecar metadata constructed via the inheritance principle."""
pass
29 changes: 29 additions & 0 deletions tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,32 @@ def test_fileparts(examples, schema):
suffix='T1w',
extension='.nii',
)

def test_context(examples, schema):

tree = FileTree.read_from_filesystem(examples / 'synthetic')
ds = context.Dataset(tree, schema)
T1w = tree / 'sub-01' / 'ses-01' / 'anat' / 'sub-01_ses-01_T1w.nii'

file_context = context.Context(T1w, ds)

assert file_context.schema is schema
assert file_context.dataset is ds
assert file_context.entities == {'sub': '01', 'ses': '01'}
assert file_context.path == '/sub-01/ses-01/anat/sub-01_ses-01_T1w.nii'
assert file_context.datatype == 'anat'
assert file_context.suffix == 'T1w'
assert file_context.extension == '.nii'
assert file_context.modality == 'mri'
assert file_context.size == 352

## Tests for:
# subject
# sidecar
# associations
# columns
# json
# gzip
# nifti_header
# ome
# tiff
Loading