Skip to content

Commit

Permalink
Merge 1a998ed into b0346ec
Browse files Browse the repository at this point in the history
  • Loading branch information
corranwebster committed Jan 6, 2015
2 parents b0346ec + 1a998ed commit 62f18f0
Show file tree
Hide file tree
Showing 14 changed files with 708 additions and 82 deletions.
5 changes: 5 additions & 0 deletions .travis.yml
Expand Up @@ -5,6 +5,11 @@ python:
before_install:
- sudo apt-get update
- sudo apt-get install python-numpy swig
# Simlinks for PIL compilation
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libfreetype.so /usr/lib/
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libjpeg.so /usr/lib/
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libpng.so /usr/lib/
- sudo ln -s /usr/lib/`uname -i`-linux-gnu/libz.so /usr/lib/
- source .travis_before_install
install:
- pip install cython
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.txt
Expand Up @@ -4,6 +4,10 @@ Chaco CHANGELOG

Change summary since 4.5.0

Enhancements

* More comprehensive testing for AbstractDataSource subclasses (PR #244).

Fixes

* Fixed default position attribute in BetterZoom tool (PR#241)
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
@@ -1,4 +1,6 @@
include chaco/*.h
include chaco/tests/data/PngSuite/*.png
include chaco/tests/data/PngSuite/LICENSE.txt
include chaco/tools/toolbars/images*.png
include chaco/tools/toolbars/images*.svg
include chaco/tools/toolbars/images*.txt
Expand Down
2 changes: 1 addition & 1 deletion chaco/array_data_source.py
Expand Up @@ -251,7 +251,7 @@ def _compute_bounds(self, data=None):
data_len = 0
try:
data_len = len(data)
except:
except Exception:
pass
if data_len == 0:
self._min_index = 0
Expand Down
260 changes: 228 additions & 32 deletions chaco/tests/arraydatasource_test_case.py
@@ -1,49 +1,148 @@
"""
Test of basic dataseries behavior.
Tests of ArrayDataSource behavior.
"""

import unittest
import pickle

from numpy import arange, array, allclose, empty, isnan, nan
import unittest2 as unittest
from numpy import arange, array, allclose, empty, isnan, nan, ones
from numpy.testing import assert_array_equal
import numpy as np

from chaco.api import ArrayDataSource, PointDataSource
from traits.testing.unittest_tools import UnittestTools


class ArrayDataTestCase(unittest.TestCase):
def test_basic_set_get(self):
myarray = arange(10)
sd = ArrayDataSource(myarray)
self.assertTrue(allclose(myarray, sd._data))
self.assert_(sd.value_dimension == "scalar")
return
class ArrayDataSourceTestCase(UnittestTools, unittest.TestCase):

def setUp(self):
self.myarray = arange(10)
self.mymask = array([i % 2 for i in self.myarray], dtype=bool)
self.data_source = ArrayDataSource(self.myarray)

def test_init_defaults(self):
data_source = ArrayDataSource()
assert_array_equal(data_source._data, [])
self.assertEqual(data_source.value_dimension, "scalar")
self.assertEqual(data_source.index_dimension, "scalar")
self.assertEqual(data_source.sort_order, "none")
self.assertFalse(data_source.is_masked())
self.assertEqual(data_source.persist_data, True)

def test_basic_setup(self):
assert_array_equal(self.myarray, self.data_source._data)
self.assertEqual(self.data_source.value_dimension, "scalar")
self.assertEqual(self.data_source.sort_order, "none")
self.assertFalse(self.data_source.is_masked())

def test_set_data(self):
new_array = arange(0, 20, 2)

with self.assertTraitChanges(self.data_source, 'data_changed',
count=1):
self.data_source.set_data(new_array)

assert_array_equal(new_array, self.data_source._data)
self.assertEqual(self.data_source.get_bounds(), (0, 18))
self.assertEqual(self.data_source.sort_order, "none")

def test_set_data_ordered(self):
new_array = arange(20, 0, -2)

with self.assertTraitChanges(self.data_source, 'data_changed',
count=1):
self.data_source.set_data(new_array, sort_order='descending')

assert_array_equal(new_array, self.data_source._data)
self.assertEqual(self.data_source.get_bounds(), (2, 20))
self.assertEqual(self.data_source.sort_order, "descending")

def test_set_mask(self):
with self.assertTraitChanges(self.data_source, 'data_changed',
count=1):
self.data_source.set_mask(self.mymask)

assert_array_equal(self.myarray, self.data_source._data)
assert_array_equal(self.mymask, self.data_source._cached_mask)
self.assertTrue(self.data_source.is_masked())
self.assertEqual(self.data_source.get_bounds(), (0, 9))

def test_remove_mask(self):
self.data_source.set_mask(self.mymask)
self.assertTrue(self.data_source.is_masked())

with self.assertTraitChanges(self.data_source, 'data_changed',
count=1):
self.data_source.remove_mask()

assert_array_equal(self.myarray, self.data_source._data)
self.assertIsNone(self.data_source._cached_mask, None)
self.assertFalse(self.data_source.is_masked())
self.assertEqual(self.data_source.get_bounds(), (0, 9))

def test_get_data(self):
assert_array_equal(self.myarray, self.data_source.get_data())

def test_get_data_no_data(self):
data_source = ArrayDataSource(None)

assert_array_equal(data_source.get_data(), 0.0)

def test_get_data_mask(self):
self.data_source.set_mask(self.mymask)

data, mask = self.data_source.get_data_mask()
assert_array_equal(data, self.myarray)
assert_array_equal(mask, self.mymask)

@unittest.skip('get_data_mask() fails in this case')
def test_get_data_mask_no_data(self):
data_source = ArrayDataSource(None)

data, mask = data_source.get_data_mask()
assert_array_equal(data, 0.0)
assert_array_equal(mask, True)

def test_get_data_mask_no_mask(self):
data, mask = self.data_source.get_data_mask()
assert_array_equal(data, self.myarray)
assert_array_equal(mask, ones(shape=10, dtype=bool))

def test_bounds(self):
# ascending
myarray = arange(10)
sd = ArrayDataSource(myarray, sort_order="ascending")
bounds = sd.get_bounds()
self.assert_(bounds == (0,9))
bounds = self.data_source.get_bounds()
self.assertEqual(bounds, (0, 9))

# descending
myarray = arange(10)[::-1]
sd = ArrayDataSource(myarray, sort_order="descending")
bounds = sd.get_bounds()
self.assert_(bounds == (0,9))
data_source = ArrayDataSource(myarray, sort_order="descending")
bounds = data_source.get_bounds()
self.assertEqual(bounds, (0, 9))

# no order
myarray = array([12,3,0,9,2,18,3])
sd = ArrayDataSource(myarray, sort_order="none")
bounds = sd.get_bounds()
self.assert_(bounds == (0,18))
return
myarray = array([12, 3, 0, 9, 2, 18, 3])
data_source = ArrayDataSource(myarray, sort_order="none")
bounds = data_source.get_bounds()
self.assertEqual(bounds, (0, 18))

def test_data_size(self):
# We know that ScalarData always returns the exact length of its data
myarray = arange(913)
sd = ArrayDataSource(myarray)
self.assert_(len(myarray) == sd.get_size())
return
def test_bounds_length_one(self):
# this is special-cased in the code, so exercise the code path
data_source = ArrayDataSource(array([1.0]))
bounds = data_source.get_bounds()
self.assertEqual(bounds, (1.0, 1.0))

def test_bounds_length_zero(self):
# this is special-cased in the code, so exercise the code path
data_source = ArrayDataSource(array([]))
bounds = data_source.get_bounds()
# XXX this is sort of inconsistent with test_bounds_all_nans()
self.assertEqual(bounds, (0, 0))

def test_bounds_empty(self):
data_source = ArrayDataSource()
bounds = data_source.get_bounds()
# XXX this is sort of inconsistent with test_bounds_all_nans()
self.assertEqual(bounds, (0, 0))

def test_bounds_all_nans(self):
myarray = empty(10)
Expand All @@ -53,12 +152,108 @@ def test_bounds_all_nans(self):
self.assertTrue(isnan(bounds[0]))
self.assertTrue(isnan(bounds[1]))

def test_bounds_some_nan(self):
data_source = ArrayDataSource(array([np.nan, 3, 0, 9, np.nan, 18, 3]))
bounds = data_source.get_bounds()
self.assertEqual(bounds, (0, 18))

def test_bounds_negative_inf(self):
data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, 18, 3]))
bounds = data_source.get_bounds()
self.assertEqual(bounds, (-np.inf, 18))

def test_bounds_positive_inf(self):
data_source = ArrayDataSource(array([12, 3, 0, 9, 2, np.inf, 3]))
bounds = data_source.get_bounds()
self.assertEqual(bounds, (0, np.inf))

def test_bounds_negative_positive_inf(self):
data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, np.inf, 3]))
bounds = data_source.get_bounds()
self.assertEqual(bounds, (-np.inf, np.inf))

def test_bounds_non_numeric(self):
myarray = np.array([u'abc', u'foo', u'bar', u'def'], dtype=unicode)
sd = ArrayDataSource(myarray)
bounds = sd.get_bounds()
data_source = ArrayDataSource(myarray)
bounds = data_source.get_bounds()
self.assertEqual(bounds, (u'abc', u'def'))

def test_data_size(self):
# We know that ArrayDataTestCase always returns the exact length of
# its data
myarray = arange(913)
data_source = ArrayDataSource(myarray)
self.assertEqual(len(myarray), data_source.get_size())

def test_reverse_map(self):
# sort_order ascending
myarray = arange(10)
data_source = ArrayDataSource(myarray, sort_order='ascending')

self.assertEqual(data_source.reverse_map(4.0), 4)

# sort_order descending
myarray = arange(10)[::-1]
data_source = ArrayDataSource(myarray, sort_order='descending')

self.assertEqual(data_source.reverse_map(4.0), 5)

# sort_order none
myarray = array([12, 3, 0, 9, 2, 18, 3])
data_source = ArrayDataSource(myarray, sort_order='none')

with self.assertRaises(NotImplementedError):
data_source.reverse_map(3)

def test_metadata(self):
self.assertEqual(self.data_source.metadata,
{'annotations': [], 'selections': []})

def test_metadata_changed(self):
with self.assertTraitChanges(self.data_source, 'metadata_changed',
count=1):
self.data_source.metadata = {'new_metadata': True}

def test_metadata_items_changed(self):
with self.assertTraitChanges(self.data_source, 'metadata_changed',
count=1):
self.data_source.metadata['new_metadata'] = True

def test_serialization_state(self):
state = self.data_source.__getstate__()
self.assertNotIn('value_dimension', state)
self.assertNotIn('index_dimension', state)
self.assertNotIn('persist_data', state)

@unittest.skip("persist_data probably shouldn't be persisted")
def test_serialization_state_no_persist(self):
self.data_source.persist_data = False

state = self.data_source.__getstate__()
self.assertNotIn('value_dimension', state)
self.assertNotIn('index_dimension', state)
self.assertNotIn('persist_data', state)
for key in ["_data", "_cached_mask", "_cached_bounds", "_min_index",
"_max_index"]:
self.assertIn(key, state)

@unittest.skip("I think this is just broken")
def test_serialization_post_load(self):
self.data_source.set_mask(self.mymask)

pickled_data_source = pickle.dumps(self.data_source)
unpickled_data_source = pickle.loads(pickled_data_source)
unpickled_data_source._post_load()

self.assertEqual(unpickled_data_source._cached_bounds, ())
self.assertEqual(unpickled_data_source._cached_mask, None)

assert_array_equal(self.data_source.get_data(),
unpickled_data_source.get_data())

mask = unpickled_data_source.get_data_mask()[1]
assert_array_equal(mask, ones(10))


class PointDataTestCase(unittest.TestCase):
# Since PointData is mostly the same as ScalarData, the key things to
Expand All @@ -69,16 +264,17 @@ def create_array(self):
def test_basic_set_get(self):
myarray = self.create_array()
pd = PointDataSource(myarray)
self.assertTrue(allclose(myarray,pd._data))
self.assertTrue(allclose(myarray, pd._data))
self.assert_(pd.value_dimension == "point")
return

def test_bounds(self):
myarray = self.create_array()
pd = PointDataSource(myarray)
self.assertEqual(pd.get_bounds(),((0,0), (9,90)))
self.assertEqual(pd.get_bounds(), ((0, 0), (9, 90)))
return


if __name__ == '__main__':
import nose
nose.run()
8 changes: 8 additions & 0 deletions chaco/tests/data/PngSuite/LICENSE.txt
@@ -0,0 +1,8 @@
PngSuite
--------

Permission to use, copy, modify and distribute these images for any
purpose and without fee is hereby granted.


(c) Willem van Schaik, 1996, 2011
Binary file added chaco/tests/data/PngSuite/basi6a08.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chaco/tests/data/PngSuite/basn2c08.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 62f18f0

Please sign in to comment.