Permalink
Please sign in to comment.
Showing
with
364 additions
and 0 deletions.
- +1 −0 .gitignore
- +1 −0 MANIFEST.in
- +1 −0 setup.py
- +23 −0 tests/__init__.py
- BIN tests/boxes.png
- BIN tests/boxes.tiff
- +39 −0 tests/test_base.py
- +76 −0 tests/test_deepzoom.py
- +102 −0 tests/test_imageslide.py
- +121 −0 tests/test_openslide.py
- BIN tests/unopenable.tiff
| @@ -1,3 +1,4 @@ | ||
| include *.txt | ||
| recursive-include doc *.py *.rst | ||
| recursive-include examples *.html *.js *.png *.py | ||
| +recursive-include tests *.png *.py *.tiff |
| @@ -0,0 +1,23 @@ | ||
| +# | ||
| +# openslide-python - Python bindings for the OpenSlide library | ||
| +# | ||
| +# Copyright (c) 2016 Benjamin Gilbert | ||
| +# | ||
| +# This library is free software; you can redistribute it and/or modify it | ||
| +# under the terms of version 2.1 of the GNU Lesser General Public License | ||
| +# as published by the Free Software Foundation. | ||
| +# | ||
| +# This library is distributed in the hope that it will be useful, but | ||
| +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
| +# License for more details. | ||
| +# | ||
| +# You should have received a copy of the GNU Lesser General Public License | ||
| +# along with this library; if not, write to the Free Software Foundation, | ||
| +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| +# | ||
| + | ||
| +import os | ||
| + | ||
| +def file_path(name): | ||
| + return os.path.join(os.path.dirname(__file__), name) |
BIN
tests/boxes.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
tests/boxes.tiff
Binary file not shown.
| @@ -0,0 +1,39 @@ | ||
| +# | ||
| +# openslide-python - Python bindings for the OpenSlide library | ||
| +# | ||
| +# Copyright (c) 2016 Benjamin Gilbert | ||
| +# | ||
| +# This library is free software; you can redistribute it and/or modify it | ||
| +# under the terms of version 2.1 of the GNU Lesser General Public License | ||
| +# as published by the Free Software Foundation. | ||
| +# | ||
| +# This library is distributed in the hope that it will be useful, but | ||
| +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
| +# License for more details. | ||
| +# | ||
| +# You should have received a copy of the GNU Lesser General Public License | ||
| +# along with this library; if not, write to the Free Software Foundation, | ||
| +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| +# | ||
| + | ||
| +import openslide | ||
| +from openslide import open_slide, OpenSlide, ImageSlide | ||
| +import sys | ||
| +import unittest | ||
| + | ||
| +from . import file_path | ||
| + | ||
| +# Tests should be written to be compatible with Python 2.6 unittest. | ||
| + | ||
| +class TestLibrary(unittest.TestCase): | ||
| + def test_version(self): | ||
| + string = unicode if sys.version[0] == '2' else str | ||
| + self.assertTrue(isinstance(openslide.__version__, string)) | ||
| + self.assertTrue(isinstance(openslide.__library_version__, string)) | ||
| + | ||
| + def test_open_slide(self): | ||
| + self.assertTrue(isinstance(open_slide(file_path('boxes.tiff')), | ||
| + OpenSlide)) | ||
| + self.assertTrue(isinstance(open_slide(file_path('boxes.png')), | ||
| + ImageSlide)) |
| @@ -0,0 +1,76 @@ | ||
| +# | ||
| +# openslide-python - Python bindings for the OpenSlide library | ||
| +# | ||
| +# Copyright (c) 2016 Benjamin Gilbert | ||
| +# | ||
| +# This library is free software; you can redistribute it and/or modify it | ||
| +# under the terms of version 2.1 of the GNU Lesser General Public License | ||
| +# as published by the Free Software Foundation. | ||
| +# | ||
| +# This library is distributed in the hope that it will be useful, but | ||
| +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
| +# License for more details. | ||
| +# | ||
| +# You should have received a copy of the GNU Lesser General Public License | ||
| +# along with this library; if not, write to the Free Software Foundation, | ||
| +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| +# | ||
| + | ||
| +from openslide import OpenSlide, ImageSlide | ||
| +from openslide.deepzoom import DeepZoomGenerator | ||
| +import unittest | ||
| + | ||
| +from . import file_path | ||
| + | ||
| +# Tests should be written to be compatible with Python 2.6 unittest. | ||
| + | ||
| +class _BoxesDeepZoomTest(object): | ||
| + def setUp(self): | ||
| + self.osr = self.CLASS(file_path(self.FILENAME)) | ||
| + self.dz = DeepZoomGenerator(self.osr, 254, 1) | ||
| + | ||
| + def tearDown(self): | ||
| + self.osr.close() | ||
| + | ||
| + def test_metadata(self): | ||
| + self.assertEqual(self.dz.level_count, 10) | ||
| + self.assertEqual(self.dz.tile_count, 11) | ||
| + self.assertEqual(self.dz.level_tiles, | ||
| + ((1, 1), (1, 1), (1, 1), (1, 1), (1, 1), | ||
| + (1, 1), (1, 1), (1, 1), (1, 1), (2, 1))) | ||
| + self.assertEqual(self.dz.level_dimensions, | ||
| + ((1, 1), (2, 1), (3, 2), (5, 4), (10, 8), | ||
| + (19, 16), (38, 32), (75, 63), (150, 125), (300, 250))) | ||
| + | ||
| + def test_get_tile(self): | ||
| + self.assertEqual(self.dz.get_tile(9, (1, 0)).size, (47, 250)) | ||
| + | ||
| + def test_get_tile_bad_level(self): | ||
| + self.assertRaises(ValueError, lambda: self.dz.get_tile(-1, (0, 0))) | ||
| + self.assertRaises(ValueError, lambda: self.dz.get_tile(10, (0, 0))) | ||
| + | ||
| + def test_get_tile_bad_address(self): | ||
| + self.assertRaises(ValueError, lambda: self.dz.get_tile(0, (-1, 0))) | ||
| + self.assertRaises(ValueError, lambda: self.dz.get_tile(0, (1, 0))) | ||
| + | ||
| + def test_get_tile_coordinates(self): | ||
| + self.assertEqual(self.dz.get_tile_coordinates(9, (1, 0)), | ||
| + ((253, 0), 0, (47, 250))) | ||
| + | ||
| + def test_get_tile_dimensions(self): | ||
| + self.assertEqual(self.dz.get_tile_dimensions(9, (1, 0)), (47, 250)) | ||
| + | ||
| + def test_get_dzi(self): | ||
| + self.assertTrue('http://schemas.microsoft.com/deepzoom/2008' in | ||
| + self.dz.get_dzi('jpeg')) | ||
| + | ||
| + | ||
| +class TestSlideDeepZoom(_BoxesDeepZoomTest, unittest.TestCase): | ||
| + CLASS = OpenSlide | ||
| + FILENAME = 'boxes.tiff' | ||
| + | ||
| + | ||
| +class TestImageDeepZoom(_BoxesDeepZoomTest, unittest.TestCase): | ||
| + CLASS = ImageSlide | ||
| + FILENAME = 'boxes.png' |
| @@ -0,0 +1,102 @@ | ||
| +# | ||
| +# openslide-python - Python bindings for the OpenSlide library | ||
| +# | ||
| +# Copyright (c) 2016 Benjamin Gilbert | ||
| +# | ||
| +# This library is free software; you can redistribute it and/or modify it | ||
| +# under the terms of version 2.1 of the GNU Lesser General Public License | ||
| +# as published by the Free Software Foundation. | ||
| +# | ||
| +# This library is distributed in the hope that it will be useful, but | ||
| +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
| +# License for more details. | ||
| +# | ||
| +# You should have received a copy of the GNU Lesser General Public License | ||
| +# along with this library; if not, write to the Free Software Foundation, | ||
| +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| +# | ||
| + | ||
| +from openslide import ImageSlide, OpenSlideError | ||
| +from PIL import Image | ||
| +import unittest | ||
| + | ||
| +from . import file_path | ||
| + | ||
| +# Tests should be written to be compatible with Python 2.6 unittest. | ||
| + | ||
| +class TestImageWithoutOpening(unittest.TestCase): | ||
| + def test_detect_format(self): | ||
| + self.assertTrue( | ||
| + ImageSlide.detect_format(file_path('__missing_file')) is None) | ||
| + self.assertTrue( | ||
| + ImageSlide.detect_format(file_path('../setup.py')) is None) | ||
| + self.assertEqual( | ||
| + ImageSlide.detect_format(file_path('boxes.png')), 'PNG') | ||
| + | ||
| + def test_open(self): | ||
| + self.assertRaises(IOError, | ||
| + lambda: ImageSlide(file_path('__does_not_exist'))) | ||
| + self.assertRaises(IOError, | ||
| + lambda: ImageSlide(file_path('../setup.py'))) | ||
| + | ||
| + # passing PIL.Image to ImageSlide | ||
| + self.assertEqual( | ||
| + ImageSlide(Image.open(file_path('boxes.png'))).dimensions, | ||
| + (300, 250)) | ||
| + | ||
| + def test_operations_on_closed_handle(self): | ||
| + img = Image.open(file_path('boxes.png')) | ||
| + osr = ImageSlide(img) | ||
| + osr.close() | ||
| + self.assertRaises(AttributeError, | ||
| + lambda: osr.read_region((0, 0), 0, (100, 100))) | ||
| + # If an Image is passed to the constructor, ImageSlide.close() | ||
| + # shouldn't close it | ||
| + self.assertEqual(img.getpixel((0, 0)), 3) | ||
| + | ||
| + def test_context_manager(self): | ||
| + osr = ImageSlide(file_path('boxes.png')) | ||
| + with osr: | ||
| + pass | ||
| + self.assertRaises(AttributeError, | ||
| + lambda: osr.read_region((0, 0), 0, (100, 100))) | ||
| + | ||
| + | ||
| +class TestImage(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.osr = ImageSlide(file_path('boxes.png')) | ||
| + | ||
| + def tearDown(self): | ||
| + self.osr.close() | ||
| + | ||
| + def test_metadata(self): | ||
| + self.assertEqual(self.osr.level_count, 1) | ||
| + self.assertEqual(self.osr.level_dimensions, ((300, 250),)) | ||
| + self.assertEqual(self.osr.dimensions, (300, 250)) | ||
| + self.assertEqual(self.osr.level_downsamples, (1.0,)) | ||
| + | ||
| + self.assertEqual(self.osr.get_best_level_for_downsample(0.5), 0) | ||
| + self.assertEqual(self.osr.get_best_level_for_downsample(3), 0) | ||
| + | ||
| + self.assertEqual(self.osr.properties, {}) | ||
| + self.assertEqual(self.osr.associated_images, {}) | ||
| + | ||
| + def test_read_region(self): | ||
| + self.assertEqual(self.osr.read_region((-10, -10), 0, (400, 400)).size, | ||
| + (400, 400)) | ||
| + | ||
| + def test_read_region_size_dimension_zero(self): | ||
| + self.assertEqual(self.osr.read_region((0, 0), 0, (400, 0)).size, | ||
| + (400, 0)) | ||
| + | ||
| + def test_read_region_bad_level(self): | ||
| + self.assertRaises(OpenSlideError, | ||
| + lambda: self.osr.read_region((0, 0), 1, (100, 100))) | ||
| + | ||
| + def test_read_region_bad_size(self): | ||
| + self.assertRaises(OpenSlideError, | ||
| + lambda: self.osr.read_region((0, 0), 0, (400, -5))) | ||
| + | ||
| + def test_thumbnail(self): | ||
| + self.assertEqual(self.osr.get_thumbnail((100, 100)).size, (100, 83)) |
| @@ -0,0 +1,121 @@ | ||
| +# | ||
| +# openslide-python - Python bindings for the OpenSlide library | ||
| +# | ||
| +# Copyright (c) 2016 Benjamin Gilbert | ||
| +# | ||
| +# This library is free software; you can redistribute it and/or modify it | ||
| +# under the terms of version 2.1 of the GNU Lesser General Public License | ||
| +# as published by the Free Software Foundation. | ||
| +# | ||
| +# This library is distributed in the hope that it will be useful, but | ||
| +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
| +# License for more details. | ||
| +# | ||
| +# You should have received a copy of the GNU Lesser General Public License | ||
| +# along with this library; if not, write to the Free Software Foundation, | ||
| +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| +# | ||
| + | ||
| +from ctypes import ArgumentError | ||
| +from openslide import (OpenSlide, OpenSlideError, | ||
| + OpenSlideUnsupportedFormatError) | ||
| +import unittest | ||
| + | ||
| +from . import file_path | ||
| + | ||
| +# Tests should be written to be compatible with Python 2.6 unittest. | ||
| + | ||
| +class TestSlideWithoutOpening(unittest.TestCase): | ||
| + def test_detect_format(self): | ||
| + self.assertTrue( | ||
| + OpenSlide.detect_format(file_path('__missing_file')) is None) | ||
| + self.assertTrue( | ||
| + OpenSlide.detect_format(file_path('../setup.py')) is None) | ||
| + self.assertEqual( | ||
| + OpenSlide.detect_format(file_path('boxes.tiff')), | ||
| + 'generic-tiff') | ||
| + | ||
| + def test_open(self): | ||
| + self.assertRaises(OpenSlideUnsupportedFormatError, | ||
| + lambda: OpenSlide('__does_not_exist')) | ||
| + self.assertRaises(OpenSlideUnsupportedFormatError, | ||
| + lambda: OpenSlide('setup.py')) | ||
| + self.assertRaises(OpenSlideError, | ||
| + lambda: OpenSlide('unopenable.tiff')) | ||
| + | ||
| + def test_operations_on_closed_handle(self): | ||
| + osr = OpenSlide(file_path('boxes.tiff')) | ||
| + props = osr.properties | ||
| + associated = osr.associated_images | ||
| + osr.close() | ||
| + self.assertRaises(ArgumentError, | ||
| + lambda: osr.read_region((0, 0), 0, (100, 100))) | ||
| + self.assertRaises(ArgumentError, lambda: osr.close()) | ||
| + self.assertRaises(ArgumentError, lambda: props['openslide.vendor']) | ||
| + self.assertRaises(ArgumentError, lambda: associated['label']) | ||
| + | ||
| + def test_context_manager(self): | ||
| + osr = OpenSlide(file_path('boxes.tiff')) | ||
| + with osr: | ||
| + self.assertEqual(osr.level_count, 4) | ||
| + self.assertRaises(ArgumentError, lambda: osr.level_count) | ||
| + | ||
| + | ||
| +class TestSlide(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.osr = OpenSlide(file_path('boxes.tiff')) | ||
| + | ||
| + def tearDown(self): | ||
| + self.osr.close() | ||
| + | ||
| + def test_basic_metadata(self): | ||
| + self.assertEqual(self.osr.level_count, 4) | ||
| + self.assertEqual(self.osr.level_dimensions, | ||
| + ((300, 250), (150, 125), (75, 62), (37, 31))) | ||
| + self.assertEqual(self.osr.dimensions, (300, 250)) | ||
| + | ||
| + self.assertEqual(len(self.osr.level_downsamples), self.osr.level_count) | ||
| + self.assertEqual(self.osr.level_downsamples[0:2], (1, 2)) | ||
| + self.assertAlmostEqual(self.osr.level_downsamples[2], 4, places=0) | ||
| + self.assertAlmostEqual(self.osr.level_downsamples[3], 8, places=0) | ||
| + | ||
| + self.assertEqual(self.osr.get_best_level_for_downsample(0.5), 0) | ||
| + self.assertEqual(self.osr.get_best_level_for_downsample(3), 1) | ||
| + self.assertEqual(self.osr.get_best_level_for_downsample(37), 3) | ||
| + | ||
| + def test_properties(self): | ||
| + self.assertEqual(self.osr.properties['openslide.vendor'], | ||
| + 'generic-tiff') | ||
| + self.assertRaises(KeyError, | ||
| + lambda: self.osr.properties['__does_not_exist']) | ||
| + # test __len__ and __iter__ | ||
| + self.assertEqual(len([v for v in self.osr.properties]), | ||
| + len(self.osr.properties)) | ||
| + | ||
| + def test_associated_images(self): | ||
| + # XXX test an associated image | ||
| + self.assertRaises(KeyError, | ||
| + lambda: self.osr.associated_images['__missing']) | ||
| + # test __len__ and __iter__ | ||
| + self.assertEqual(len([v for v in self.osr.associated_images]), | ||
| + len(self.osr.associated_images)) | ||
| + | ||
| + def test_read_region(self): | ||
| + self.assertEqual(self.osr.read_region((-10, -10), 1, (400, 400)).size, | ||
| + (400, 400)) | ||
| + | ||
| + def test_read_region_size_dimension_zero(self): | ||
| + self.assertEqual(self.osr.read_region((0, 0), 1, (400, 0)).size, | ||
| + (400, 0)) | ||
| + | ||
| + def test_read_region_bad_level(self): | ||
| + self.assertEqual(self.osr.read_region((0, 0), 4, (100, 100)).size, | ||
| + (100, 100)) | ||
| + | ||
| + def test_read_region_bad_size(self): | ||
| + self.assertRaises(OpenSlideError, | ||
| + lambda: self.osr.read_region((0, 0), 1, (400, -5))) | ||
| + | ||
| + def test_thumbnail(self): | ||
| + self.assertEqual(self.osr.get_thumbnail((100, 100)).size, (100, 83)) |
Binary file not shown.
0 comments on commit
9681548