Skip to content

Commit

Permalink
Merge pull request #188 from caspervdw/fix-deps
Browse files Browse the repository at this point in the history
Drop PIL and Scipy dependencies
  • Loading branch information
danielballan committed Oct 23, 2015
2 parents bfd1aaf + 7e612eb commit e29f0d4
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 19 deletions.
17 changes: 12 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
language: python
sudo: false

python:
- 2.7
- 3.4
matrix:
include:
- python: "2.7"
env: DEPS="numpy=1.9*" DEPSSM="tifffile"
- python: "2.7"
env: DEPS="numpy=1.9* scipy pillow<3 matplotlib scikit-image jinja2" DEPSSM="pyav tifffile"
- python: "3.4"
env: DEPS="numpy=1.9*" DEPSSM="tifffile"
- python: "3.4"
env: DEPS="numpy=1.9* scipy pillow<3 matplotlib scikit-image jinja2" DEPSSM="pyav tifffile"

install:
- conda update --yes conda
- conda create -n testenv --yes numpy=1.9* scipy nose "pillow<3" matplotlib scikit-image jinja2 pip python=$TRAVIS_PYTHON_VERSION
- conda install -n testenv -c soft-matter --yes pyav tifffile
- conda create -n testenv --yes $DEPS nose pip python=$TRAVIS_PYTHON_VERSION
- conda install -n testenv -c soft-matter --yes $DEPSSM
- source activate testenv
- if [ ${TRAVIS_PYTHON_VERSION:0:1} == "2" ]; then pip install libtiff; fi
- pip install slicerator jpype1;
Expand Down
2 changes: 1 addition & 1 deletion pims/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def raiser(*args, **kwargs):
else:
raise ImportError()
except (ImportError, IOError):
Video = not_available("PyAV")
Video = not_available("PyAV and/or PIL/Pillow")

import pims.tiff_stack
from pims.tiff_stack import (TiffStack_pil, TiffStack_libtiff,
Expand Down
6 changes: 4 additions & 2 deletions pims/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
ColorConverter = None
mpl = None
plt = None
from PIL import Image


def export(sequence, filename, rate=30, bitrate=None,
Expand Down Expand Up @@ -244,7 +243,10 @@ def scrollable_stack(sequence, width=512, normed=True):

def _as_png(arr, width, normed=True):
"Create a PNG image buffer from an array."
from PIL import Image
try:
from PIL import Image
except ImportError:
raise ImportError("This feature requires PIL/Pillow.")
w = width # for brevity
h = arr.shape[0] * w // arr.shape[1]
if normed:
Expand Down
5 changes: 5 additions & 0 deletions pims/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from numpy import ndarray, asarray
from pims.display import _scrollable_stack, _as_png, to_rgb
from warnings import warn


WIDTH = 512 # width of rich display, in pixels
Expand Down Expand Up @@ -76,6 +77,10 @@ def __setstate__(self, state):

def _repr_html_(self):
from jinja2 import Template
try:
from PIL import Image
except ImportError:
warn('Rich display in IPython requires PIL/Pillow.')
ndim = self.ndim
shape = self.shape
image = self
Expand Down
14 changes: 10 additions & 4 deletions pims/image_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from pims.frame import Frame
from pims.utils.sort import natural_keys

from PIL import Image
# skimage.io.plugin_order() gives a nice hierarchy of implementations of imread.
# If skimage is not available, go down our own hard-coded hierarchy.
try:
Expand All @@ -26,7 +25,10 @@
try:
from matplotlib.pyplot import imread
except ImportError:
from scipy.ndimage import imread
try:
from scipy.ndimage import imread
except:
imread = None


class ImageSequence(FramesSequence):
Expand Down Expand Up @@ -110,9 +112,13 @@ def __del__(self):
self.close()

def imread(self, filename, **kwargs):
if imread is None:
raise ImportError("One of the following packages are required for "
"using the ImageSequence reader: "
"scipy, matplotlib or scikit-image.")
if self._is_zipfile:
img = StringIO(self._zipfile.read(filename))
return np.array(Image.open(img))
file_handle = StringIO(self._zipfile.read(filename))
return imread(file_handle, **kwargs)
else:
return imread(filename, **kwargs)

Expand Down
1 change: 1 addition & 0 deletions pims/pyav_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
def available():
try:
import av
from PIL import Image
except ImportError:
return False
else:
Expand Down
39 changes: 32 additions & 7 deletions pims/tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from numpy.testing import (assert_equal, assert_allclose)
from nose.tools import assert_true
import pims
from PIL import Image

path, _ = os.path.split(os.path.abspath(__file__))
path = os.path.join(path, 'data')
Expand All @@ -40,6 +39,26 @@ def _skip_if_no_tifffile():
raise nose.SkipTest('tifffile not installed. Skipping.')


def _skip_if_no_imread():
if pims.image_sequence.imread is None:
raise nose.SkipTest('ImageSequence requires either scipy, matplotlib or'
' scikit-image. Skipping.')


def _skip_if_no_skimage():
try:
import skimage
except ImportError:
raise nose.SkipTest('skimage not installed. Skipping.')


def _skip_if_no_PIL():
try:
from PIL import Image
except ImportError:
raise nose.SkipTest('PIL/Pillow not installed. Skipping.')


def assert_image_equal(actual, expected):
if np.issubdtype(actual.dtype, np.integer):
assert_equal(actual, expected)
Expand All @@ -50,6 +69,7 @@ def assert_image_equal(actual, expected):


def save_dummy_png(filepath, filenames, shape):
from PIL import Image
if not os.path.isdir(filepath):
os.mkdir(filepath)
frames = []
Expand Down Expand Up @@ -180,6 +200,7 @@ def compare_slice_to_list(actual, expected):
class TestRecursiveSlicing(unittest.TestCase):

def setUp(self):
_skip_if_no_imread()
class DemoReader(pims.ImageSequence):
def imread(self, filename, **kwargs):
return np.array([[filename]])
Expand Down Expand Up @@ -533,6 +554,7 @@ def setUp(self):

class TestImageSequenceWithPIL(_image_series, unittest.TestCase):
def setUp(self):
_skip_if_no_skimage()
self.filepath = os.path.join(path, 'image_sequence')
self.filenames = ['T76S3F00001.png', 'T76S3F00002.png',
'T76S3F00003.png', 'T76S3F00004.png',
Expand All @@ -559,6 +581,7 @@ def tearDown(self):

class TestImageSequenceWithMPL(_image_series, unittest.TestCase):
def setUp(self):
_skip_if_no_skimage()
self.filepath = os.path.join(path, 'image_sequence')
self.filenames = ['T76S3F00001.png', 'T76S3F00002.png',
'T76S3F00003.png', 'T76S3F00004.png',
Expand All @@ -579,6 +602,7 @@ def tearDown(self):

class TestImageSequenceAcceptsList(_image_series, unittest.TestCase):
def setUp(self):
_skip_if_no_imread()
self.filepath = os.path.join(path, 'image_sequence')
self.filenames = ['T76S3F00001.png', 'T76S3F00002.png',
'T76S3F00003.png', 'T76S3F00004.png',
Expand All @@ -601,6 +625,7 @@ def tearDown(self):

class TestImageSequenceNaturalSorting(_image_series, unittest.TestCase):
def setUp(self):
_skip_if_no_imread()
self.filepath = os.path.join(path, 'image_sequence')
self.filenames = ['T76S3F1.png', 'T76S3F20.png',
'T76S3F3.png', 'T76S3F4.png',
Expand Down Expand Up @@ -635,6 +660,7 @@ def check_skip(self):
pass

def setUp(self):
_skip_if_no_PIL()
self.filename = os.path.join(path, 'stuck.tif')
self.frame0 = np.load(os.path.join(path, 'stuck_frame0.npy'))
self.frame1 = np.load(os.path.join(path, 'stuck_frame1.npy'))
Expand Down Expand Up @@ -693,6 +719,9 @@ def test_metadata(self):


class TestOpenFiles(unittest.TestCase):
def setUp(self):
_skip_if_no_PIL()

def test_open_pngs(self):
self.filepath = os.path.join(path, 'image_sequence')
self.filenames = ['T76S3F00001.png', 'T76S3F00002.png',
Expand All @@ -713,10 +742,8 @@ def test_open_tiff(self):


class ImageSequenceND(_image_series, unittest.TestCase):
def check_skip(self):
pass

def setUp(self):
_skip_if_no_imread()
self.filepath = os.path.join(path, 'image_sequence3d')
self.filenames = ['file_t001_z001_c1.png',
'file_t001_z001_c2.png',
Expand Down Expand Up @@ -777,10 +804,8 @@ def test_sizeC(self):


class ImageSequenceND_RGB(_image_series, unittest.TestCase):
def check_skip(self):
pass

def setUp(self):
_skip_if_no_imread()
self.filepath = os.path.join(path, 'image_sequence3d')
self.filenames = ['file_t001_z001_c1.png',
'file_t001_z002_c1.png',
Expand Down
9 changes: 9 additions & 0 deletions pims/tests/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@
unicode_literals)

import six
import nose
import numpy as np
from pims.frame import Frame
from nose.tools import assert_true, assert_equal


def _skip_if_no_PIL():
try:
from PIL import Image
except ImportError:
raise nose.SkipTest('PIL/Pillow not installed. Skipping.')


def test_scalar_casting():
tt = Frame(np.ones((5, 3)), frame_no=42)
sum1 = tt.sum()
Expand All @@ -25,6 +33,7 @@ def test_creation_md():


def test_repr_html_():
_skip_if_no_PIL()
# This confims a bugfix, where 16-bit images would raise
# an error.
Frame(10000*np.ones((50, 50), dtype=np.uint16))._repr_html_()
Expand Down

0 comments on commit e29f0d4

Please sign in to comment.