Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop PIL and Scipy dependencies #188

Merged
merged 4 commits into from
Oct 23, 2015
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
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