rtCommon.bidsArchive


bidsArchive.py

Implements interacting with an on-disk BIDS Archive.


Module Contents

Classes

BidsArchive

Functions

failIfEmpty(func)

Attributes

logger

rtCommon.bidsArchive.logger
rtCommon.bidsArchive.failIfEmpty(func)
class rtCommon.bidsArchive.BidsArchive(rootPath: str)
__str__(self)

Return str(self).

__getattr__(self, attr)
static _stripLeadingSlash(path: str) str

Strips a leading / from the path, if it exists. This prevents paths defined relative to dataset root (/sub-01/ses-01) from being interpreted as being relative to the root of the filesystem.

Parameters

path – Path to strip leading slash from.

Examples

>>> path = '/sub-01/ses-01/func/sub-01_task-test_bold.nii.gz'
>>> BidsArchive._stripLeadingSlash(path)
'sub-01/ses-01/func/sub-01_task-test_bold.nii.gz'
>>> path = 'sub-01/ses-01/func/sub-01_task-test_bold.nii.gz'
'sub-01/ses-01/func/sub-01_task-test_bold.nii.gz'
absPathFromRelPath(self, relPath: str) str

Makes an absolute path from the relative path within the dataset.

tryGetFile(self, path: str) bids.layout.BIDSFile

Tries to get a file from the archive using different interpretations of the target path. Interpretations considered are: 1) Path with leading slash, relative to filesystem root 2) Path with leading slash, relative to archive root 3) Path with no leading slash, assume relative to archive root

Parameters

path – Path to the file to attempt to get.

Returns

BIDSFile (or subclass) if a matching file was found, None otherwise.

Examples

>>> archive = BidsArchive('/path/to/archive')
>>> filename = 'sub-01_task-test_bold.nii.gz'
>>> archive.tryGetFile('/tmp/archive/sub-01/func/' + filename)
<BIDSImageFile filename=/tmp/archive/sub-01/func/sub-01_task-test            _bold.nii.gz
>>> archive.tryGetFile('/' + filename)
<BIDSImageFile filename=/tmp/archive/sub-01/func/sub-01_task-test            _bold.nii.gz
>>> archive.tryGetFile(filename)
<BIDSImageFile filename=/tmp/archive/sub-01/func/sub-01_task-test            _bold.nii.gz
dirExistsInArchive(self, relPath: str) bool
getReadme(self) bids.layout.BIDSFile
getImages(self, matchExact: bool = False, **entities) List[bids.layout.BIDSImageFile]

Return all images that have the provided entities. If no entities are provided, then all images are returned.

Parameters
  • matchExact – Only return images that have exactly the provided entities, no more and no less.

  • **entities – Entities that returned images must have.

Returns

A list of images matching the provided entities (empty if there are no matches, and containing at most a single image if an exact match is requested).

Examples

>>> archive = BidsArchive('/path/to/archive')

Using a dictionary to provide target entities.

>>> entityDict = {'subject': '01', 'datatype': 'func'}
>>> images = archive.getImages(**entityDict)

Using keyword arguments to provide target entities.

>>> images = archive.getImages(subject='01', datatype='func')

Accessing properties of the image.

>>> image = images[0]
>>> print(image.get_image()
(64, 64, 27, 3)
>>> print(image.path)
/tmp/archive/func/sub-01_task-test_bold.nii
>>> print(image.filename)
sub-01_task-test_bold.nii

An exact match must have exactly the same entities; since images must also have the task entity in their filename, the above entityDict will yield no exact matches in the archive.

>>> images = archive.getImages(entityDict, matchExact=True)
ERROR "No images were an exact match for: {'subject': '01',
'datatype': 'func'}"
>>> print(len(images))
0
_updateLayout(self)

Updates the layout of the dataset so that any new metadata or image files are added to the index.

_addImage(self, img: nibabel.Nifti1Image, path: str, updateLayout: bool = True) None

Replace the image in the dataset at the provided path, creating the path if it does not exist.

Parameters
  • img – The image to add to the archive

  • path – Relative path in archive at which to add image

  • updateLayout – Update the underlying layout object upon conclusion of the image addition.

_addMetadata(self, metadata: dict, path: str, updateLayout: bool = True) None

Replace the sidecar metadata in the dataset at the provided path, creating the path if it does not exist.

Parameters
  • metadata – Metadata key/value pairs to add.

  • path – Relative path in archive at which to add image

  • updateLayout – Update the underlying layout object upon conclusion of the metadata addition.

isEmpty(self) bool
getSidecarMetadata(self, image: Union[str, bids.layout.BIDSImageFile], includeEntities: bool = True) dict

Get metadata for the file at the provided path in the dataset. Sidecar metadata is always returned, and BIDS entities present in the filename are returned by default (this can be disabled).

Parameters
  • image – Path or BIDSImageFile pointing to the image file to get metadata for.

  • includeEntities – False to return only the metadata in the image’s sidecar JSON files. True to additionally include the entities in the filename (e.g., ‘subject’, ‘task’, and ‘session’). Defaults to True.

Raises

TypeError – If image is not a str or BIDSImageFile.

Returns

Dictionary with sidecar metadata for the file and any metadata that

can be extracted from the filename (e.g., subject, session).

Examples

>>> archive = BidsArchive('/path/to/archive')
>>> path = archive.getImages()[0].path
>>> archive.getSidecarMetadata(path)
{'AcquisitionMatrixPE': 320, 'AcquisitionNumber': 1, ... }
getEvents(self, matchExact: bool = False, **entities) List[bids.layout.BIDSDataFile]

Gets data from scanner run event files in the archive. Event files to retrieve can be filtered by entities present in the files’ names.

Parameters
  • matchExact – Whether to only return events files that have exactly the same entities as provided (no more, no less)

  • entities – Keyword arguments for entities to filter by. Provide in the format entity=’value’.

Returns

A list of BIDSDataFile objects encapsulating the events files matching the provided entities (empty if there are no matches, and containing at most a single object if an exact match is requested).

Raises

ValueError – If the ‘extension’ entity is provided and not valid for an events file (i.e., not ‘.tsv’ or ‘.tsv.gz’)

Examples

>>> archive = BidsArchive('.')
>>> archive.getEvents()
[<BIDSDataFile filename='/tmp/dataset/sub-01/func/            sub-01_task-test_events.tsv'>, <BIDSDataFile
filename='/tmp/dataset/sub-02/func/sub-02_task-test_events.tsv'>]
>>> sub1Events = archive.getEvents(subject='01')
[<BIDSDataFile filename='/tmp/dataset/sub-01/func/            sub-01_task-test_events.tsv'>]
>>> eventsDataFrame = sub1Events[0].get_df()
>>> print(eventsDataFrame[:][:1])
    onset   duration    trial_type
0   0       30          rest
_appendIncremental(self, incremental: rtCommon.bidsIncremental.BidsIncremental, makePath: bool = True, validateAppend: bool = True) bool

Appends a BIDS Incremental’s image data and metadata to the archive, creating new directories if necessary (this behavior can be overridden). For internal use only.

Parameters
  • incremental – BIDS Incremental to append

  • makePath – Create new directory path for BIDS-I data if needed. (default: True).

  • validateAppend – Compares image metadata and NIfTI headers to check that the images being appended are part of the same sequence and don’t conflict with each other (default: True).

Raises
  • RuntimeError – If the image to append to in the archive is not either 3D or 4D.

  • StateError – If the image path within the BIDS-I would result in directory creation and makePath is set to False.

  • ValidationError – If the data to append is incompatible with existing data in the archive.

Returns

True if the append succeeded, False otherwise.

Examples

Assume we have a NIfTI image ‘image’ and a metadata dictionary ‘metdata’ with all required metadata for a BIDS Incremental.

>>> archive = BidsArchive('.')
>>> incremental = BidsIncremental(image, metadata)
>>> archive._appendIncremental(incremental)

If we don’t want to create any new files/directories in the archive, makePath can be set to false.

>>> archive = BidsArchive('/tmp/emptyDirectory')
>>> archive._appendIncremental(incremental, makePath=False)
False
_getIncremental(self, imageIndex: int = 0, **entities) rtCommon.bidsIncremental.BidsIncremental

Creates a BIDS Incremental from the specified part of the archive. For internal use only.

Parameters
  • imageIndex – Index of 3-D image to select in a 4-D image volume.

  • entities – Keyword arguments for entities to filter by. Provide in the format entity=’value’.

Returns

BIDS-Incremental file with the specified image of the archive and its associated metadata.

Raises
  • IndexError – If the provided imageIndex goes beyond the bounds of the volume specified in the archive.

  • MissingMetadataError – If the archive lacks the required metadata to make a BIDS Incremental out of an image in the archive.

  • NoMatchError – When no images that match the provided entities are found in the archive

  • RuntimeError – 1) When too many images that match the provided entities are found in the archive. 2) If the image matching the provided entities has fewer than 3 dimensions or greater than 4.

Examples

>>> archive = BidsArchive('.')
>>> inc = archive._getIncremental(subject='01', task='test')
>>> entityFilterDict = {'subject': '01', 'task': 'test'}
>>> inc2 = archive._getIncremental(**entityFilterDict)
>>> inc == inc2
True

By default, _getIncremental has an imageIndex of 0. Changing that parameter will return a different 3-D image from the volume, using the same search metadata.

>>> inc.getImageDimensions()
(64, 64, 27, 1)
>>> inc3 = archive._getIncremental(imageIndex=1, **entityFilterDict)
>>> inc2 != inc3
True
getBidsRun(self, **entities) rtCommon.bidsRun.BidsRun

Get a BIDS Run from the archive.

Parameters

entities – Entities defining a run in the archive.

Returns

A BidsRun containing all the BidsIncrementals in the specified run.

Raises
  • NoMatchError – If the entities don’t match any runs in the archive.

  • QueryError – If the entities match more than one run in the archive.

Examples

>>> archive = BidsArchive('/tmp/dataset')
>>> run = archive.getBidsRun(subject='01', session='02',
                             task='testTask', run=1)
>>> print(run.numIncrementals())
53
appendBidsRun(self, run: rtCommon.bidsRun.BidsRun) None

Append a BIDS Run to this archive.

Parameters

run – Run to append to the archvie.

Examples

>>> archive1 = BidsArchive('/tmp/dataset1')
>>> archive2 = BidsArchive('/tmp/dataset2')
>>> archive1.getRuns()
[1, 2]
>>> archive2.getRuns()
[1]
>>> run2 = archive1.getBidsRun(subject='01', task='test', run=2)
>>> archive2.appendBidsRun(run2)
>>> archive2.getRuns()
[1, 2]