Commit 44966429 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

ENH,BF: New image.loadMetadata function, and loadMeta option to Image class, to

auto-load any JSON files that sre found. Fix to bids.isBIDSFile
parent dedb67a0
......@@ -140,11 +140,11 @@ def isBIDSFile(filename):
"""Returns ``True`` if ``filename`` looks like a BIDS image or JSON file.
"""
filename = op.basename(filename)
name = op.basename(filename)
pattern = r'([a-z0-9]+-[a-z0-9]+_)*([a-z0-9])+\.(nii|nii\.gz|json)'
flags = re.ASCII | re.IGNORECASE
return inBIDSDir(filename) and re.fullmatch(pattern, filename, flags)
return inBIDSDir(filename) and re.fullmatch(pattern, name, flags)
@memoize.memoize
......
......@@ -35,6 +35,7 @@ and file names:
import os
import os.path as op
import itertools as it
import json
import string
import logging
import tempfile
......@@ -54,6 +55,7 @@ import fsl.utils.path as fslpath
import fsl.utils.deprecated as deprecated
import fsl.data.constants as constants
import fsl.data.imagewrapper as imagewrapper
import fsl.data.bids as fslbids
log = logging.getLogger(__name__)
......@@ -904,6 +906,7 @@ class Image(Nifti):
indexed=False,
threaded=False,
dataSource=None,
loadMeta=False,
**kwargs):
"""Create an ``Image`` object with the given image data or file name.
......@@ -953,6 +956,12 @@ class Image(Nifti):
used to specify the file from which the image was
loaded.
:arg loadMeta: If ``True``, any metadata contained in JSON sidecar
files is loaded and attached to this ``Image`` via
the :class:`.Meta` interface. if ``False``, metadata
can be loaded at a later stage via the
:func:`loadMeta` function. Defaults to ``False``.
All other arguments are passed through to the ``nibabel.load`` function
(if it is called).
"""
......@@ -1077,6 +1086,9 @@ class Image(Nifti):
if calcRange:
self.calcRange()
if self.dataSource is not None and loadMeta:
self.updateMeta(loadMetadata(self))
self.__imageWrapper.register(self.__lName, self.__dataRangeChanged)
......@@ -1418,6 +1430,36 @@ def canonicalShape(shape):
return shape
def loadMetadata(image):
"""Searches for and loads any sidecar JSON files associated with the given
:class:`.Image`.
If the image looks to be part of a BIDS data set,
:func:`.bids.loadMetadata` is used. Otherwise, if a JSON file with the same
file prefix is present alongside the image, it is directly loaded.
:arg image: :class:`.Image` instance
:returns: Dict containing any metadata that was loaded.
"""
if image.dataSource is None:
return {}
filename = image.dataSource
basename = op.basename(removeExt(filename))
dirname = op.dirname(filename)
if fslbids.inBIDSDir(image.dataSource):
return fslbids.loadMetadata(image.dataSource)
jsonfile = op.join(dirname, '{}.json'.format(basename))
if op.exists(jsonfile):
with open(jsonfile, 'rt') as f:
return json.load(f)
return {}
def looksLikeImage(filename, allowedExts=None):
"""Returns ``True`` if the given file looks like a NIFTI image, ``False``
otherwise.
......
......@@ -25,6 +25,7 @@ class Meta(object):
metaItems
getMeta
setMeta
updateMeta
"""
def __new__(cls, *args, **kwargs):
......@@ -67,3 +68,8 @@ class Meta(object):
"""Add some metadata with the specified key (``dict.__setitem__``).
"""
self.__meta.__setitem__(*args, **kwargs)
def updateMeta(self, *args, **kwargs):
"""Update the metadata dict (``dict.update``). """
self.__meta.update(*args, **kwargs)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment