Esempio n. 1
0
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
Esempio n. 2
0
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])
Esempio n. 3
0
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
Esempio n. 4
0
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()
Esempio n. 5
0
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()
Esempio n. 6
0
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)