Skip to content
Snippets Groups Projects
Commit 44966429 authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
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
No related branches found
No related tags found
No related merge requests found
...@@ -140,11 +140,11 @@ def isBIDSFile(filename): ...@@ -140,11 +140,11 @@ def isBIDSFile(filename):
"""Returns ``True`` if ``filename`` looks like a BIDS image or JSON file. """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)' pattern = r'([a-z0-9]+-[a-z0-9]+_)*([a-z0-9])+\.(nii|nii\.gz|json)'
flags = re.ASCII | re.IGNORECASE 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 @memoize.memoize
......
...@@ -35,6 +35,7 @@ and file names: ...@@ -35,6 +35,7 @@ and file names:
import os import os
import os.path as op import os.path as op
import itertools as it import itertools as it
import json
import string import string
import logging import logging
import tempfile import tempfile
...@@ -54,6 +55,7 @@ import fsl.utils.path as fslpath ...@@ -54,6 +55,7 @@ import fsl.utils.path as fslpath
import fsl.utils.deprecated as deprecated import fsl.utils.deprecated as deprecated
import fsl.data.constants as constants import fsl.data.constants as constants
import fsl.data.imagewrapper as imagewrapper import fsl.data.imagewrapper as imagewrapper
import fsl.data.bids as fslbids
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -904,6 +906,7 @@ class Image(Nifti): ...@@ -904,6 +906,7 @@ class Image(Nifti):
indexed=False, indexed=False,
threaded=False, threaded=False,
dataSource=None, dataSource=None,
loadMeta=False,
**kwargs): **kwargs):
"""Create an ``Image`` object with the given image data or file name. """Create an ``Image`` object with the given image data or file name.
...@@ -953,6 +956,12 @@ class Image(Nifti): ...@@ -953,6 +956,12 @@ class Image(Nifti):
used to specify the file from which the image was used to specify the file from which the image was
loaded. 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 All other arguments are passed through to the ``nibabel.load`` function
(if it is called). (if it is called).
""" """
...@@ -1077,6 +1086,9 @@ class Image(Nifti): ...@@ -1077,6 +1086,9 @@ class Image(Nifti):
if calcRange: if calcRange:
self.calcRange() self.calcRange()
if self.dataSource is not None and loadMeta:
self.updateMeta(loadMetadata(self))
self.__imageWrapper.register(self.__lName, self.__dataRangeChanged) self.__imageWrapper.register(self.__lName, self.__dataRangeChanged)
...@@ -1418,6 +1430,36 @@ def canonicalShape(shape): ...@@ -1418,6 +1430,36 @@ def canonicalShape(shape):
return 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): def looksLikeImage(filename, allowedExts=None):
"""Returns ``True`` if the given file looks like a NIFTI image, ``False`` """Returns ``True`` if the given file looks like a NIFTI image, ``False``
otherwise. otherwise.
......
...@@ -25,6 +25,7 @@ class Meta(object): ...@@ -25,6 +25,7 @@ class Meta(object):
metaItems metaItems
getMeta getMeta
setMeta setMeta
updateMeta
""" """
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
...@@ -67,3 +68,8 @@ class Meta(object): ...@@ -67,3 +68,8 @@ class Meta(object):
"""Add some metadata with the specified key (``dict.__setitem__``). """Add some metadata with the specified key (``dict.__setitem__``).
""" """
self.__meta.__setitem__(*args, **kwargs) self.__meta.__setitem__(*args, **kwargs)
def updateMeta(self, *args, **kwargs):
"""Update the metadata dict (``dict.update``). """
self.__meta.update(*args, **kwargs)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment