Source code for iblutil.tests.test_numerical

import unittest
import uuid

import iblutil.numerical as num
import numpy as np
import pandas as pd


[docs] class HashUUIDs(unittest.TestCase):
[docs] def test_hash_uuids(self): the_hash = 'fc898a58172960bcc2d49577e17d34e0e59ded74567ee236533c0757f016262f' uuids = [ 'c5cabbda-1f74-4168-ad5e-7c5a2f533d9f', '5b5176f2-228f-46b5-85c8-205cf9d90a53', '19930b44-2f8a-44e1-a8ce-46184f7334cb' ] self.assertEqual(the_hash, num.hash_uuids(uuids)) self.assertEqual(the_hash, num.hash_uuids(np.array(uuids))) self.assertEqual(the_hash, num.hash_uuids(pd.Series(uuids))) self.assertEqual(the_hash, num.hash_uuids([uuid.UUID(hex=uid) for uid in uuids]))
[docs] class TestRcoeff(unittest.TestCase):
[docs] def test_rcoeff(self): x = np.random.rand(2, 1000) y = x[0, :] r = np.corrcoef(x[1, :], y) assert num.rcoeff(x[0, :], y) == 1 assert np.isclose(num.rcoeff(x[1, :], y), r[1, 0]) assert np.all(np.isclose(num.rcoeff(x, y), r[0, :])) assert np.all(np.isclose(num.rcoeff(y, x), r[0, :]))
[docs] class TestBetweeenSorted(unittest.TestCase):
[docs] def test_between_sorted_single_time(self): # test single time, falling right on edges t = np.arange(100) bounds = [10, 25] ind = num.between_sorted(t, bounds) assert np.all( t[ind] == np.arange(int(np.ceil(bounds[0])), int(np.floor(bounds[1] + 1))) ) # test single time in between edges bounds = [10.4, 25.2] ind = num.between_sorted(t, bounds) assert np.all(t[ind] == np.arange(np.ceil(bounds[0]), np.floor(bounds[1]) + 1)) # out of bounds ind = num.between_sorted(t, [-5, 800]) assert np.all(ind)
[docs] def test_between_sorted_multiple_times(self): t = np.arange(100) # non overlapping ranges bounds = np.array([[10.4, 25.2], [67.2, 86.4]]) ind_ = np.logical_or( num.between_sorted(t, bounds[0]), num.between_sorted(t, bounds[1]) ) ind = num.between_sorted(t, bounds) assert np.all(ind == ind_) # overlapping ranges bounds = np.array([[10.4, 83.2], [67.2, 86.4]]) ind_ = np.logical_or( num.between_sorted(t, bounds[0]), num.between_sorted(t, bounds[1]) ) ind = num.between_sorted(t, bounds) assert np.all(ind == ind_) # one range contains the other bounds = np.array([[10.4, 83.2], [34, 78]]) ind_ = np.logical_or( num.between_sorted(t, bounds[0]), num.between_sorted(t, bounds[1]) ) ind = num.between_sorted(t, bounds) assert np.all(ind == ind_) # case when one range starts exactly where another stops bounds = np.array([[10.4, 83.2], [83.2, 84]]) ind = num.between_sorted(t, bounds) ind_ = np.logical_or( num.between_sorted(t, bounds[0]), num.between_sorted(t, bounds[1]) ) assert np.all(ind == ind_)
[docs] def test_between_sorted_out_of_range(self): # np searchsorted was returning out of range index when the start time # was greater than the max or the end time lower than the min bounds = np.array([[-10.4, -3], [10.4, 20], [34, 78]]) array = np.arange(30) assert np.sum(num.between_sorted(array, bounds)) == 10
[docs] class TestIsmember(unittest.TestCase):
[docs] def test_ismember2d(self): b = np.reshape([0, 0, 0, 1, 1, 1], [3, 2]) locb = np.array([0, 1, 0, 2, 2, 1]) lia = np.array([True, True, True, True, True, True, False, False]) a = np.r_[b[locb, :], np.array([[2, 1], [1, 2]])] lia_, locb_ = num.ismember2d(a, b) assert np.all(lia == lia_) & np.all(locb == locb_)
[docs] def test_ismember2d_uuids(self): nb = 20 na = 500 np.random.seed(42) a = np.random.randint(0, nb + 3, na) b = np.arange(nb) lia, locb = num.ismember(a, b) bb = np.random.randint( low=np.iinfo(np.int64).min, high=np.iinfo(np.int64).max, size=(nb, 2), dtype=np.int64, ) aa = np.zeros((na, 2), dtype=np.int64) aa[lia, :] = bb[locb, :] lia_, locb_ = num.ismember2d(aa, bb) assert np.all(lia == lia_) & np.all(locb == locb_) bb[:, 0] = 0 aa[:, 0] = 0 # if the first column is equal, the distinction is to be made on the second\ assert np.unique(bb[:, 1]).size == nb lia_, locb_ = num.ismember2d(aa, bb) assert np.all(lia == lia_) & np.all(locb == locb_)
[docs] def test_ismember(self): def _check_ismember(a, b, lia_, locb_): lia, locb = num.ismember(a, b) self.assertTrue(np.all(a[lia] == b[locb])) self.assertTrue(np.all(lia_ == lia)) self.assertTrue(np.all(locb_ == locb)) b = np.array([0, 1, 3, 4, 4]) a = np.array([1, 4, 5, 4]) lia_ = np.array([True, True, False, True]) locb_ = np.array([1, 3, 3]) _check_ismember(a, b, lia_, locb_) b = np.array([0, 4, 3, 1, 4]) a = np.array([1, 4, 5, 4]) lia_ = np.array([True, True, False, True]) locb_ = np.array([3, 1, 1]) _check_ismember(a, b, lia_, locb_) b = np.array([0, 1, 3, 4]) a = np.array([1, 4, 5]) lia_ = np.array([True, True, False]) locb_ = np.array([1, 3]) _check_ismember(a, b, lia_, locb_)
[docs] class TestWithinRanges(unittest.TestCase):
[docs] def test_within_ranges(self): verifiable = num.within_ranges(np.arange(11), [(1, 2), (5, 8)]) expected = np.array([0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0], dtype=int) np.testing.assert_array_equal(verifiable, expected) # Matrix mode ranges = np.array([[1, 2], [5, 8]]) verifiable = num.within_ranges( np.arange(10) + 1, ranges, labels=np.array([0, 1]), mode="matrix" ) expected = np.array( [[1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 0, 0]], dtype=int ) np.testing.assert_array_equal(verifiable, expected) # Test overlap verifiable = num.within_ranges( np.arange(11), [(1, 2), (5, 8), (4, 6)], labels=[0, 1, 1], mode="matrix" ) expected = np.array( [[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 2, 2, 1, 1, 0, 0]], dtype=int, ) np.testing.assert_array_equal(verifiable, expected) # Vector mode verifiable = num.within_ranges( np.arange(10) + 1, ranges, np.array([3, 1]), mode="vector" ) expected = np.array([3, 3, 0, 0, 1, 1, 1, 1, 0, 0], dtype=int) np.testing.assert_array_equal(verifiable, expected) # Boolean verifiable = num.within_ranges( np.arange(11), [(1, 2), (5, 8), (4, 6)], dtype=bool ) expected = np.array( [False, True, True, False, True, True, True, True, True, False, False] ) np.testing.assert_array_equal(verifiable, expected) # Edge cases verifiable = num.within_ranges(np.arange(11), []) expected = np.zeros(11, dtype=int) np.testing.assert_array_equal(verifiable, expected) with self.assertRaises(ValueError): num.within_ranges(np.arange(11), [(1, 2)], mode="array")
[docs] class TestBincount2D(unittest.TestCase):
[docs] def test_bincount_2d(self): # first test simple with indices x = np.array([0, 1, 1, 2, 2, 3, 3, 3]) y = np.array([3, 2, 2, 1, 1, 0, 0, 0]) r, xscale, yscale = num.bincount2D(x, y, xbin=1, ybin=1) r_ = np.zeros_like(r) # sometimes life would have been simpler in c: for ix, iy in zip(x, y): r_[iy, ix] += 1 self.assertTrue(np.all(np.equal(r_, r))) # test with negative values y = np.array([3, 2, 2, 1, 1, 0, 0, 0]) - 5 r, xscale, yscale = num.bincount2D(x, y, xbin=1, ybin=1) self.assertTrue(np.all(np.equal(r_, r))) # test unequal bins r, xscale, yscale = num.bincount2D(x / 2, y / 2, xbin=1, ybin=2) r_ = np.zeros_like(r) for ix, iy in zip(np.floor(x / 2), np.floor((y / 2 + 2.5) / 2)): r_[int(iy), int(ix)] += 1 self.assertTrue(np.all(r_ == r)) # test with weights w = np.ones_like(x) * 2 r, xscale, yscale = num.bincount2D(x / 2, y / 2, xbin=1, ybin=2, weights=w) self.assertTrue(np.all(r_ * 2 == r)) # test aggregation instead of binning x = np.array([0, 1, 1, 2, 2, 4, 4, 4]) y = np.array([4, 2, 2, 1, 1, 0, 0, 0]) r, xscale, yscale = num.bincount2D(x, y) self.assertTrue( np.all(xscale == yscale) and np.all(xscale == np.array([0, 1, 2, 4])) ) # test aggregation on a fixed scale r, xscale, yscale = num.bincount2D( x + 10, y + 10, xbin=np.arange(5) + 10, ybin=np.arange(3) + 10 ) self.assertTrue(np.all(xscale == np.arange(5) + 10)) self.assertTrue(np.all(yscale == np.arange(3) + 10)) self.assertTrue(np.all(r.shape == (3, 5)))