Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions src/schema/rules/errors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ SidecarWithoutDatafile:
level: error
selectors:
- extension == ".json"
- suffix != "coordsystem" || modality != "emg"
# ↑ EMG allows multiple coordsys files per data file (distinguished via `space` entity)
- suffix != "coordsystem"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably correct, but these selectors are not actually used by the validator. The SIDECAR_WITHOUT_DATAFILE error is a separate check after walking the whole dataset, so the context isn't available for selecting, at least in the JS implementation.

# ↑ coordsystem files can be shared via inheritance principle and may not have direct data files

# BIDS Validator Original Issue Code #97
MissingSession:
Expand Down
17 changes: 17 additions & 0 deletions src/schema/rules/files/raw/channels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,29 @@ coordsystem__eeg:
space: optional

# emg may have a `recording` entity
# EMG coordsystem files can be at root level (no subject) when using
# the inheritance principle for shared coordinate systems across subjects
coordsystem__emg:
$ref: rules.files.raw.channels.coordsystem__eeg
datatypes:
- emg
entities:
$ref: rules.files.raw.channels.coordsystem__eeg.entities
subject: optional
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subject is always optional for TSV or JSON files, due to the inheritance principle.

recording: optional
space: optional

# EMG coordsystem files at dataset root level (no datatype directory)
# Used for sharing coordinate systems across all subjects via inheritance
# Example: /space-leftForearm_coordsystem.json
coordsystem__emg_root:
suffixes:
- coordsystem
extensions:
- .json
datatypes: []
entities:
session: optional
recording: optional
space: optional

Expand Down
28 changes: 26 additions & 2 deletions src/schema/rules/tabular_data/emg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,41 @@ EMGChannels:
index_columns: [name__channels]
additional_columns: allowed_if_defined

# EMG electrodes without group column - name must be unique
EMGElectrodes:
selectors:
- datatype == "emg"
- suffix == "electrodes"
- extension == ".tsv"
- '!columns.group'
initial_columns:
- name__electrodes
- x
- y
columns:
name__electrodes: required
x: required
y: required
z: optional
coordinate_system: recommended
type__electrodes: recommended
material: recommended
impedance: recommended
group__emg: recommended
index_columns: [name__electrodes]
Comment on lines +39 to +53
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional index and initial columns were implemented in bids-standard/bids-validator#243.

additional_columns: allowed_if_defined

# EMG electrodes with group column - (name, group) must be unique
EMGElectrodes__grouped:
selectors:
- datatype == "emg"
- suffix == "electrodes"
- extension == ".tsv"
- columns.group
initial_columns:
- name__electrodes
- x
- y
- z
- coordinate_system
columns:
name__electrodes: required
x: required
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ def test_make_filename_template(schema_obj, schema_dir, placeholders):
continue
if line.startswith(" [ses-<label>/]"):
continue
# Skip patterns with optional subject (EMG coordsystem allows root-level placement)
if line.lstrip().startswith("[sub-<label>]"):
continue

if line in datatype_bases:
datatype_bases_found += 1
Expand Down Expand Up @@ -154,6 +157,9 @@ def test_make_filename_template(schema_obj, schema_dir, placeholders):
continue
if line.startswith(" [ses-<label>/]"):
continue
# Skip patterns with optional subject (EMG coordsystem allows root-level placement)
if line.lstrip().startswith("[sub-<label>]"):
continue

if line in datatype_bases:
datatype_bases_found += 1
Expand Down