PyBIDS → bids2table Migration Comparison

Task PyBIDS bids2table_compat bids2table + pandas bids2table + polars
Initialization
from bids import BIDSLayout

layout = BIDSLayout(
    '/path/to/dataset',
    validate=False
)
from bids2table_compat import BIDSLayout

layout = BIDSLayout(
    '/path/to/dataset',
    validate=False
)
import bids2table as b2t
import pandas as pd

tab = b2t.index_dataset('/path/to/dataset')
df = tab.to_pandas(types_mapper=pd.ArrowDtype)
import bids2table as b2t
import polars as pl

tab = b2t.index_dataset('/path/to/dataset')
df = pl.from_arrow(tab)
Query Files
files = layout.get(
    suffix='T1w',
    extension='.nii.gz',
    return_type='filename'
)
files = layout.get(
    suffix='T1w',
    extension='.nii.gz',
    return_type='filename'
)
files = df[
    (df['suffix'] == 'T1w') &
    (df['ext'] == '.nii.gz')
]['path'].tolist()
files = df.filter(
    (pl.col('suffix') == 'T1w') &
    (pl.col('ext') == '.nii.gz')
)['path'].to_list()
Multi-Entity Query
files = layout.get(
    subject='01',
    task='rest',
    suffix='bold',
    return_type='filename'
)
files = layout.get(
    subject='01',
    task='rest',
    suffix='bold',
    return_type='filename'
)
files = df[
    (df['sub'] == '01') &
    (df['task'] == 'rest') &
    (df['suffix'] == 'bold')
]['path'].tolist()
files = df.filter(
    (pl.col('sub') == '01') &
    (pl.col('task') == 'rest') &
    (pl.col('suffix') == 'bold')
)['path'].to_list()
List Subjects
subjects = layout.get_subjects()
subjects = layout.get_subjects()
subjects = df['sub'].dropna().unique().tolist()
subjects = df['sub'].drop_nulls().unique().to_list()
List Tasks
tasks = layout.get_tasks()
tasks = layout.get_entities()['task']
tasks = df['task'].dropna().unique().tolist()
tasks = df['task'].drop_nulls().unique().to_list()
Get Metadata
metadata = layout.get_metadata(file_path)
metadata = layout.get_metadata(file_path)
metadata = b2t.load_bids_metadata(
    file_path,
    dataset_root
)
metadata = b2t.load_bids_metadata(
    file_path,
    dataset_root
)
Optional Entity
from bids.layout import Query

files = layout.get(
    subject='01',
    session=Query.OPTIONAL,
    suffix='bold',
    return_type='filename'
)
from bids2table_compat import Query

files = layout.get(
    subject='01',
    session=Query.OPTIONAL,
    suffix='bold',
    return_type='filename'
)
# Omit session filter = matches all

files = df[
    (df['sub'] == '01') &
    (df['suffix'] == 'bold')
]['path'].tolist()
# Omit session filter = matches all

files = df.filter(
    (pl.col('sub') == '01') &
    (pl.col('suffix') == 'bold')
)['path'].to_list()
Derivatives
layout = BIDSLayout(
    '/path/to/dataset',
    derivatives='/path/to/derivatives'
)
layout = BIDSLayout(
    '/path/to/dataset',
    derivatives='/path/to/derivatives'
)
import pyarrow as pa

raw_tab = b2t.index_dataset('/path/to/dataset')
deriv_tab = b2t.index_dataset('/path/to/derivatives')
tab = pa.concat_tables([raw_tab, deriv_tab])
df = tab.to_pandas(types_mapper=pd.ArrowDtype)
raw_tab = b2t.index_dataset('/path/to/dataset')
deriv_tab = b2t.index_dataset('/path/to/derivatives')

raw_df = pl.from_arrow(raw_tab)
deriv_df = pl.from_arrow(deriv_tab)
df = pl.concat([raw_df, deriv_df])
Filter by List
files = layout.get(
    subject=['01', '02', '03'],
    suffix='bold',
    return_type='filename'
)
files = layout.get(
    subject=['01', '02', '03'],
    suffix='bold',
    return_type='filename'
)
files = df[
    (df['sub'].isin(['01', '02', '03'])) &
    (df['suffix'] == 'bold')
]['path'].tolist()
files = df.filter(
    (pl.col('sub').is_in(['01', '02', '03'])) &
    (pl.col('suffix') == 'bold')
)['path'].to_list()
Custom Entities
# No native support
# Must track separately
qc_grades = {'01': 'pass', '02': 'fail', ...}
layout.add_custom_entity('qc_grade', qc_grades)

files = layout.get(
    qc_grade='pass',
    suffix='T1w',
    return_type='filename'
)
qc_grades = {'01': 'pass', '02': 'fail', ...}
df['qc_grade'] = df['sub'].map(qc_grades)

files = df[
    (df['qc_grade'] == 'pass') &
    (df['suffix'] == 'T1w')
]['path'].tolist()
qc_grades = {'01': 'pass', '02': 'fail', ...}
df = df.with_columns(
    pl.col('sub').replace(qc_grades).alias('qc_grade')
)

files = df.filter(
    (pl.col('qc_grade') == 'pass') &
    (pl.col('suffix') == 'T1w')
)['path'].to_list()
Subject-Session Iteration
for subject in layout.get_subjects():
    sessions = layout.get_sessions(
        subject=subject
    ) or [None]
    for session in sessions:
        process(subject, session)
for subject in layout.get_subjects():
    sessions = layout.get_sessions(
        subject=subject
    ) or [None]
    for session in sessions:
        process(subject, session)
for (sub, ses), group in df.groupby(
    ['sub', 'ses'],
    dropna=False
):
    process(sub, ses)
for (sub, ses), group in df.group_by(
    ['sub', 'ses']
):
    process(sub, ses)
Check if Files Exist
has_t1w = len(layout.get(
    subject='01',
    suffix='T1w'
)) > 0
has_t1w = len(layout.get(
    subject='01',
    suffix='T1w'
)) > 0
has_t1w = (
    (df['sub'] == '01') &
    (df['suffix'] == 'T1w')
).any()
has_t1w = df.filter(
    (pl.col('sub') == '01') &
    (pl.col('suffix') == 'T1w')
).height > 0
Parse Entities from Path
entities = layout.parse_file_entities(
    '/path/to/sub-01_task-rest_bold.nii.gz'
)
# Returns: {'subject': '01', 'task': 'rest', ...}
from bids2table import parse_bids_entities

entities = parse_bids_entities(
    '/path/to/sub-01_task-rest_bold.nii.gz'
)
# Returns: {'sub': '01', 'task': 'rest', ...}
from bids2table import parse_bids_entities

entities = parse_bids_entities(
    '/path/to/sub-01_task-rest_bold.nii.gz'
)
# Returns: {'sub': '01', 'task': 'rest', ...}
from bids2table import parse_bids_entities

entities = parse_bids_entities(
    '/path/to/sub-01_task-rest_bold.nii.gz'
)
# Returns: {'sub': '01', 'task': 'rest', ...}

See interactive notebooks for executable examples with real BIDS data