Skip to content
Merged
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
15 changes: 10 additions & 5 deletions nibabel/dft.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@
# Copyright (C) 2011 Christian Haselgrove

import os
import struct
import tempfile
import StringIO
import numpy
import nibabel
import sqlite3
import dicom

import numpy

from .nifti1 import Nifti1Header

# Shield optional dicom import
from .optpkg import optional_package
dicom, have_dicom, _ = optional_package('dicom')


class DFTError(Exception):
"base class for DFT exceptions"
Expand Down Expand Up @@ -176,7 +181,7 @@ def as_nifti(self):

m = numpy.array(m)

hdr = nibabel.nifti1.Nifti1Header(endianness='<')
hdr = Nifti1Header(endianness='<')
hdr.set_intent(0)
hdr.set_qform(m, 1)
hdr.set_xyzt_units(2, 8)
Expand Down
86 changes: 86 additions & 0 deletions nibabel/optpkg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
""" Routines to support optional packages """

try:
import nose
except ImportError:
have_nose = False
else:
have_nose = True

from .tripwire import TripWire, is_tripwire

def optional_package(name, trip_msg=None):
""" Return package-like thing and module setup for package `name`

Parameters
----------
name : str
package name
trip_msg : None or str
message to give when someone tries to use the return package, but we
could not import it, and have returned a TripWire object instead.
Default message if None.

Returns
-------
pkg_like : module or ``TripWire`` instance
If we can import the package, return it. Otherwise return an object
raising an error when accessed
have_pkg : bool
True if import for package was successful, false otherwise
module_setup : function
callable usually set as ``setup_module`` in calling namespace, to allow
skipping tests.

Example
-------
Typical use would be something like this at the top of a module using an
optional package:

>>> from nipy.utils.optpkg import optional_package
>>> pkg, have_pkg, setup_module = optional_package('not_a_package')

Of course in this case the package doesn't exist, and so, in the module:

>>> have_pkg
False

and

>>> pkg.some_function()
Traceback (most recent call last):
...
TripWireError: We need package not_a_package for these functions, but ``import not_a_package`` raised an ImportError

If the module does exist - we get the module

>>> pkg, _, _ = optional_package('os')
>>> hasattr(pkg, 'path')
True

Or a submodule if that's what we asked for

>>> subpkg, _, _ = optional_package('os.path')
>>> hasattr(subpkg, 'dirname')
True
"""
# fromlist=[''] results in submodule being returned, rather than the top
# level module. See help(__import__)
try:
pkg = __import__(name, fromlist=[''])
except ImportError:
pass
else: # import worked
# top level module
return pkg, True, lambda : None
if trip_msg is None:
trip_msg = ('We need package %s for these functions, but '
'``import %s`` raised an ImportError'
% (name, name))
pkg = TripWire(trip_msg)
def setup_module():
if have_nose:
raise nose.plugins.skip.SkipTest('No %s for these tests'
% name)
return pkg, False, setup_module

32 changes: 23 additions & 9 deletions nibabel/tests/test_dft.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,28 @@

from os.path import join as pjoin, dirname
import StringIO
import PIL.Image
from nose.tools import assert_true, assert_false, assert_equal, assert_raises

import numpy as np

from .. import dft
from .. import nifti1

from nose.tools import (assert_true, assert_false, assert_equal, assert_raises)

# Shield optional package imports
from ..optpkg import optional_package
# setup_module will raise SkipTest if no dicom to import
dicom, have_dicom, setup_module = optional_package('dicom')
PImage, have_pil, _ = optional_package('PIL.Image')
pil_test = np.testing.dec.skipif(not have_pil, 'could not import PIL.Image')

data_dir = pjoin(dirname(__file__), 'data')


def test_init():
dft.clear_cache()
dft.update_cache(data_dir)
return


def test_study():
studies = dft.get_studies(data_dir)
Expand Down Expand Up @@ -42,32 +53,35 @@ def test_series():
assert_equal(ser.bits_allocated, 16)
assert_equal(ser.bits_stored, 12)


def test_storage_instances():
studies = dft.get_studies(data_dir)
sis = studies[0].series[0].storage_instances
assert_equal(len(sis), 2)
assert_equal(sis[0].instance_number, 1)
assert_equal(sis[1].instance_number, 2)
assert_equal(sis[0].uid,
assert_equal(sis[0].uid,
'1.3.12.2.1107.5.2.32.35119.2010011420300180088599504.0')
assert_equal(sis[1].uid,
assert_equal(sis[1].uid,
'1.3.12.2.1107.5.2.32.35119.2010011420300180088599504.1')


def test_storage_instance():
return
pass


@pil_test
def test_png():
studies = dft.get_studies(data_dir)
data = studies[0].series[0].as_png()
im = PIL.Image.open(StringIO.StringIO(data))
im = PImage.open(StringIO.StringIO(data))
assert_equal(im.size, (256, 256))
return


def test_nifti():
studies = dft.get_studies(data_dir)
data = studies[0].series[0].as_nifti()
assert_equal(len(data), 352 + 2*256*256*2)
h = nifti1.Nifti1Header(data[:348])
assert_equal(h.get_data_shape(), (256, 256, 2))
return

48 changes: 48 additions & 0 deletions nibabel/tripwire.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
""" Class to raise error for missing modules or other misfortunes
"""

class TripWireError(Exception):
""" Exception if trying to use TripWire object """


def is_tripwire(obj):
""" Returns True if `obj` appears to be a TripWire object

Examples
--------
>>> is_tripwire(object())
False
>>> is_tripwire(TripWire('some message'))
True
"""
try:
obj.any_attribute
except TripWireError:
return True
except:
pass
return False


class TripWire(object):
""" Class raising error if used

Standard use is to proxy modules that we could not import

Examples
--------
>>> try:
... import silly_module_name
... except ImportError:
... silly_module_name = TripWire('We do not have silly_module_name')
>>> silly_module_name.do_silly_thing('with silly string')
Traceback (most recent call last):
...
TripWireError: We do not have silly_module_name
"""
def __init__(self, msg):
self._msg = msg

def __getattr__(self, attr_name):
''' Raise informative error accessing attributes '''
raise TripWireError(self._msg)