Commit 9609e647 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Image class conditionally uses indexed_gzip module for compressed

files. Log messages added to memoize functions.
parent 9c4ce29a
......@@ -289,11 +289,6 @@ class Image(Nifti1, notifier.Notifier):
access managed by a :class:`.ImageWrapper`.
.. todo:: If the image appears to be large, it is loaded using the
:mod:`indexed_gzip` module. Implement this, and also write
a note here about what it means.
In addition to the attributes added by the :meth:`Nifti1.__init__` method,
the following attributes/properties are present on an ``Image`` instance
as properties (https://docs.python.org/2/library/functions.html#property):
......@@ -346,7 +341,8 @@ class Image(Nifti1, notifier.Notifier):
header=None,
xform=None,
loadData=True,
calcRange=True):
calcRange=True,
indexed=False):
"""Create an ``Image`` object with the given image data or file name.
:arg image: A string containing the name of an image file to load,
......@@ -378,6 +374,10 @@ class Image(Nifti1, notifier.Notifier):
:meth:`calcRange`). Otherwise, the image range is
incrementally updated as more data is read from memory
or disk.
:arg indexed: If ``True``, and the file is gzipped, it is opened
using the :mod:`indexed_gzip` package. Otherwise the
file is opened by ``nibabel``.
"""
import nibabel as nib
......@@ -388,8 +388,39 @@ class Image(Nifti1, notifier.Notifier):
# The image parameter may be the name of an image file
if isinstance(image, six.string_types):
image = op.abspath(addExt(image))
nibImage = nib.load(image)
image = op.abspath(addExt(image))
# Use indexed_gzip to open gzip files
# if requested - this provides fast
# on-disk access to the compressed
# data.
#
# If using indexed_gzip, we store a
# ref to the file object - we'll close
# it when we are destroyed.
if indexed and image.endswith('.gz'):
import indexed_gzip as igzip
log.debug('Loading {} using indexed gzip'.format(image))
fobj = igzip.IndexedGzipFile(
filename=image,
spacing=4194304,
readbuf_size=131072)
fmap = nib.Nifti1Image.make_file_map()
fmap['image'].fileobj = fobj
nibImage = nib.Nifti1Image.from_file_map(fmap)
self.__fileobj = fobj
# Otherwise we let nibabel
# manage the file reference(s)
else:
nibImage = nib.load(image)
self.__fileobj = None
dataSource = image
# Or a numpy array - we wrap it in a nibabel image,
......@@ -461,6 +492,12 @@ class Image(Nifti1, notifier.Notifier):
"""See the :meth:`__str__` method."""
return self.__str__()
def __del__(self):
"""Closes any open file handles. """
if self.__fileobj is not None:
self.__fileobj.close()
@property
def dataSource(self):
......
......@@ -16,10 +16,14 @@ a function:
"""
import logging
import hashlib
import functools
import six
log = logging.getLogger(__name__)
# TODO Make this a class, and add
# a "clearCache" method to it.
......@@ -72,6 +76,9 @@ def memoize(args=None, kwargs=None):
result = func(*a, **kwa)
cache[key] = result
log.debug('Adding to cache[{}]: {}'.format(
key, result))
return result
return wrapper
......@@ -104,6 +111,9 @@ def memoizeMD5(func):
result = func(*args, **kwargs)
log.debug('Adding to MD5 cache[{}]: {}'.format(
digest, result))
cache[digest] = result
return result
......
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