def test_has_numba(): if_numba = has_numba() if if_numba: try: from numba import jit numba_imported = True except ImportError: numba_imported = False assert numba_imported
def test_3d_clustering_with_min_adj_ch(): # test data data = [[[0, 1, 1, 0, 0], [1, 1, 1, 1, 0], [1, 1, 1, 1, 0], [0, 1, 1, 0, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 1, 1, 0, 0], [0, 1, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 1, 0]], [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 1, 1]], [[0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 1, 1, 0], [0, 0, 0, 1, 1], [0, 0, 0, 1, 1]]] data = np.array(data).astype('bool') # first case - lattice adjacency: adjacency = [[0, 1, 0, 0, 0], [1, 0, 1, 0, 0], [0, 1, 0, 1, 0], [0, 0, 1, 0, 1], [0, 0, 0, 1, 0]] adjacency = np.array(adjacency).astype('bool') # standard clustering clusters = _cluster_3d_numpy(data, adjacency) assert ((clusters == clusters.max()) == data).all() # clustering with min_adj_ch=1 will give two clusters instead of one data_copy = data.copy() clusters1 = _cluster_3d_numpy(data_copy, adjacency, min_adj_ch=1) # we test with 3 because we include 0 (background) assert len(np.unique(clusters1)) == 3 # make sure data were modified in-place # (this is not ideal but is ok for find_clusters which passes copies # data > threshold) assert not (data == data_copy).all() # with higher min_adj_ch only two points remain - all others have < 2 # adjacent elements in channel dimension clusters = _cluster_3d_numpy(data.copy(), adjacency, min_adj_ch=2) cluster_ids = np.unique(clusters)[1:] for clst_id in cluster_ids: assert (clusters == clst_id).sum() == 1 # numba min_adj_ch > 0 if has_numba(): from borsar.cluster.label_numba import _cluster_3d_numba clusters1_numba = _cluster_3d_numba(data.copy(), adjacency, min_adj_ch=1) assert len(np.unique(clusters1)) == 3 masks = [clusters1 == idx for idx in range(1, 3)] masks_numba = [clusters1_numba == idx for idx in range(1, 3)] assert any([(masks_numba[0] == m).all() for m in masks]) assert any([(masks_numba[1] == m).all() for m in masks])
def test_get_cluster_fun(): from borsar.cluster.label import _get_cluster_fun # check expected errors # --------------------- data = np.random.random((4, 10)) > 0.75 adj = np.zeros((4, 4), dtype='bool') adj[[0, 0, 1, 1, 2, 3], [1, 3, 0, 2, 1, 0]] = True expected_msg = 'Currently only "numba" backend can handle ' with pytest.raises(ValueError, match=expected_msg): _get_cluster_fun(data, adj, backend='numpy') if not has_numba(): expected_msg = 'You need numba package to use the "numba"' with pytest.raises(ValueError, match=expected_msg): _get_cluster_fun(data, adj, backend='numba') expected_msg = 'only for three- and two-dimensional data' with pytest.raises(ValueError, match=expected_msg): _get_cluster_fun(data, backend='numba') # check correct outputs # --------------------- if has_numba(): from borsar.cluster.label_numba import (_cluster_2d_numba, _cluster_3d_numba) func = _get_cluster_fun(data, adj, backend='auto') assert func == _cluster_2d_numba data = np.random.random((4, 10, 5)) > 0.75 func = _get_cluster_fun(data, adj, backend='auto') assert func == _cluster_3d_numba if not has_numba(): from borsar.cluster.label import _cluster_3d_numpy data = np.random.random((4, 10, 5)) > 0.75 func = _get_cluster_fun(data, adj, backend='auto') assert func == _cluster_3d_numpy
def test_2d_clustering(): '''Test clustering/labeling in 2d with numba and various settings of ``min_adj_ch``.''' if has_numba(): from borsar.cluster.label_numba import _cluster_2d_numba T, F = True, False data = np.array([[T, T, F, F, F, F, T, F], [F, T, T, F, F, T, T, T], [F, F, F, F, F, F, T, F], [F, F, F, F, F, T, F, F]]) adjacency = np.zeros((4, 4), dtype='bool') adjacency[0, [1, 2]] = T adjacency[[1, 2], 0] = T adjacency[1, 3] = T adjacency[3, 1] = T correct_labels = np.array([[1, 1, 0, 0, 0, 0, 2, 0], [0, 1, 1, 0, 0, 2, 2, 2], [0, 0, 0, 0, 0, 0, 2, 0], [0, 0, 0, 0, 0, 2, 0, 0]]) correct_labels_minadj1 = np.array([[0, 1, 0, 0, 0, 0, 2, 0], [0, 1, 0, 0, 0, 2, 2, 0], [0, 0, 0, 0, 0, 0, 2, 0], [0, 0, 0, 0, 0, 2, 0, 0]]) correct_labels_minadj2 = np.array([[0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) correct_answers = [ correct_labels, correct_labels_minadj1, correct_labels_minadj2 ] # test 2d numba clustering for min_adj_ch 0, 1 and 2 for minadj, correct in zip([0, 1, 2], correct_answers): labels = _cluster_2d_numba(data.copy(), adjacency, min_adj_ch=minadj) assert (labels == correct).all()
def test_numba_3d_clustering(): '''Test clustering/labeling with numba.''' if has_numba(): from borsar.cluster.label_numba import _cluster_3d_numba data = np.load(op.join(data_dir, 'test_clustering.npy')) # smooth each 'channel' independently for idx in range(data.shape[0]): data[idx] = gaussian(data[idx]) mask_test = data > (data.mean() + data.std()) # adjacency T, F = True, False adj = np.array([[F, T, T, F, F], [T, F, T, F, T], [T, T, F, F, F], [F, F, F, F, T], [F, T, F, T, F]]) clst1 = _cluster_3d_numpy(mask_test, adj) clst2 = _cluster_3d_numba(mask_test, adj) assert (clst1 == clst2).all()
def test_find_clusters(): threshold = 2. T, F = True, False adjacency = np.array([[F, T, F], [T, F, T], [F, T, F]]) data = np.array([[[2.1, 2., 2.3], [1.2, -2.1, -2.3], [2.5, -2.05, 1.3]], [[2.5, 2.4, 2.2], [0.3, -2.4, 0.7], [2.3, -2.1, 0.7]], [[2.2, 1.7, 1.4], [2.3, 1.4, 1.9], [2.1, 1., 0.5]]]) correct_clst = [data > threshold, data < -threshold] backends = ['auto', 'numpy'] if has_numba(): backends.append('numba') for backend in backends: clst, stat = find_clusters(data, threshold, adjacency=adjacency, backend=backend) assert (clst[0] == correct_clst[0]).all() assert (clst[1] == correct_clst[1]).all() assert data[correct_clst[0]].sum() == stat[0] assert data[correct_clst[1]].sum() == stat[1] # check using mne backend adjacency = np.array([[F, T, F], [T, F, T], [F, T, F]]) data = np.array([[1., 1.5, 2.1, 2.3, 1.8], [1., 1.4, 1.9, 2.3, 2.2], [0.1, 0.8, 1.5, 1.9, 2.1]]) correct_clst = data.T > threshold clst, stat = find_clusters(data.T, threshold, adjacency=adjacency, backend='mne') assert (clst[0] == correct_clst).all() # warnings # -------- # data has to match the shape of adjacency with pytest.raises(ValueError, match='of the correct size'): clst, stat = find_clusters(data, threshold, adjacency=adjacency, backend='mne') # mne does not support min_adj_ch data = np.random.random((5, 5, 3)) mssg = 'mne backend does not supprot ``min_adj_ch``' with pytest.raises(ValueError, match=mssg): clst, stat = find_clusters(data, threshold, adjacency=adjacency, backend='mne', min_adj_ch=1) # min_adj_ch > 0 is currently available only for 3d data if not has_numba(): data = np.random.random((3, 5)) with pytest.raises(ValueError, match='for 3d clustering.'): clst, stat = find_clusters(data, threshold, adjacency=adjacency, backend='auto', min_adj_ch=1)