Skip to content

Classic

These functions are classic graph theoretic metrics.

ccc(matrix)

Computes the classical clustering coefficient of a directed graph

Parameters:

Name Type Description Default
matrix numpy array

the adjaceny matrix of a directed graph

required

Returns:

Type Description
float

the clustering coefficient

References

The formula is taken from the following paper.

..[1] G. Fagiolo, "Clustering in complex directed networks", 2006; DOI: 10.1103/PhysRevE.76.026107.

Source code in src/connalysis/network/classic.py
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
def ccc(matrix):
    """Computes the classical clustering coefficient of a directed graph

    Parameters
    ----------
    matrix : numpy array
        the adjaceny matrix of a directed graph

    Returns
    -------
    float
        the clustering coefficient

    References
    ----------
    The formula is taken from the following paper.

    ..[1] G. Fagiolo, "Clustering in complex directed networks", 2006;
           [DOI: 10.1103/PhysRevE.76.026107](https://doi.org/10.1103/PhysRevE.76.026107).

    """
    deg = node_degree(matrix)[0]
    numerator = np.linalg.matrix_power(matrix+np.transpose(matrix),3)[0][0]
    denominator = 2*(deg*(deg-1)-2*reciprocal_connections_adjacency(matrix, chief_only=True))
    if denominator == 0:
        return 0
    return numerator/denominator

centrality(self, sub_gids, kind='closenesgit rebases', directed=False)

Compute a centrality of the graph. kind can be 'betweeness' or 'closeness'

Source code in src/connalysis/network/classic.py
68
69
70
71
72
73
def centrality(self, sub_gids, kind="closenesgit rebases", directed=False):
    """Compute a centrality of the graph. `kind` can be 'betweeness' or 'closeness'"""
    if kind == "closeness":
        return self.closeness(sub_gids, directed)
    else:
        ValueError("Kind must be 'closeness'!")

closeness(adj, neuron_properties, directed=False)

Compute closeness centrality using sknetwork on all connected components or strongly connected component (if directed==True)

Source code in src/connalysis/network/classic.py
63
64
65
66
def closeness(adj, neuron_properties, directed=False):
    """Compute closeness centrality using sknetwork on all connected components or strongly connected
    component (if directed==True)"""
    return closeness_connected_components(adj, directed=directed)

closeness_connected_components(adj, neuron_properties=[], directed=False, return_sum=True)

Compute the closeness of each connected component of more than 1 vertex

Parameters:

Name Type Description Default
adj array_like

Adjacency matrix of the graph

required
directed bool

If True, will be computed using strongly connected components and directed closeness.

False
return_sum bool

If True, only one list will be returned, by summing over all the connected components.

True

Returns:

Type Description
array_like

A single array( if return_sum=True) or a list of arrays of shape n, containting closeness of vertices in that component, or 0 if the vertex is not in the component. Closeness cannot be zero otherwise.

Source code in src/connalysis/network/classic.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def closeness_connected_components(adj, neuron_properties=[], directed=False, return_sum=True):
    """Compute the closeness of each connected component of more than 1 vertex

    Parameters
    ----------
    adj : array_like
        Adjacency matrix of the graph
    directed : bool
        If `True`, will be computed using strongly connected components and directed closeness.
    return_sum : bool
        If `True`, only one list will be returned, by summing over all the connected components.


    Returns
    -------
    array_like
        A single array( if `return_sum=True`) or a list of arrays of shape `n`, containting closeness of vertices in that component, or 0 if the vertex is not in the component. Closeness cannot be zero otherwise.

    """
    from sknetwork.ranking import Closeness
    from scipy.sparse.csgraph import connected_components

    matrix=adj.toarray()
    if directed:
        n_comp, comp = connected_components(matrix, directed=True, connection="strong")
    else:
        n_comp, comp = connected_components(matrix, directed=False)
        matrix = matrix + matrix.T  # we need to make the matrix symmetric

    closeness = Closeness()  # if matrix is not symmetric automatically use directed
    n = matrix.shape[0]
    all_c = []
    for i in range(n_comp):
        c = np.zeros(n)
        idx = np.where(comp == i)[0]
        sub_mat = matrix[np.ix_(idx, idx)].tocsr()
        if sub_mat.getnnz() > 0:
            c[idx] = closeness.fit_transform(sub_mat)
            all_c.append(c)
    if return_sum:
        all_c = np.array(all_c)
        return np.sum(all_c, axis=0)
    else:
        return all_c

connected_components(adj, neuron_properties=[])

Returns a list of the size of the connected components of the underlying undirected graph on sub_gids, if None, compute on the whole graph

Source code in src/connalysis/network/classic.py
76
77
78
79
80
81
82
83
84
def connected_components(adj,neuron_properties=[]):
    """Returns a list of the size of the connected components of the underlying undirected graph on sub_gids,
    if None, compute on the whole graph"""

    matrix=adj.toarray()
    matrix_und = np.where((matrix+matrix.T) >= 1, 1, 0)
    # TODO: Change the code from below to scipy implementation that seems to be faster!
    G = nx.from_numpy_matrix(matrix_und)
    return [len(c) for c in sorted(nx.connected_components(G), key=len, reverse=True)]

core_number(adj, neuron_properties=[])

Returns k core of directed graph, where degree of a vertex is the sum of in degree and out degree

Source code in src/connalysis/network/classic.py
86
87
88
89
90
91
def core_number(adj, neuron_properties=[]):
    """Returns k core of directed graph, where degree of a vertex is the sum of in degree and out degree"""
    # TODO: Implement directed (k,l) core and k-core of underlying undirected graph (very similar to this)
    G = nx.from_numpy_matrix(adj.toarray())
    # Very inefficient (returns a dictionary!). TODO: Look for different implementation
    return nx.algorithms.core.core_number(G)

generate_degree_based_control(M, direction='efferent')

A shuffled version of a connectivity matrix that aims to preserve degree distributions. If direction = "efferent", then the out-degree is exactly preserved, while the in-degree is approximately preseved. Otherwise it's the other way around.

Source code in src/connalysis/network/classic.py
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
def generate_degree_based_control(M, direction="efferent"):
    """
    A shuffled version of a connectivity matrix that aims to preserve degree distributions.
    If direction = "efferent", then the out-degree is exactly preserved, while the in-degree is
    approximately preseved. Otherwise it's the other way around.
    """
    if direction == "efferent":
        M = M.tocsr()
        idxx = np.arange(M.shape[1])
        p_out = np.array(M.mean(axis=0))[0]
    elif direction == "afferent":
        M = M.tocsc()
        idxx = np.arange(M.shape[0])
        p_out = np.array(M.mean(axis=1))[:, 0]
    else:
        raise ValueError()

    for col in range(M.shape[1]):
        p = p_out.copy()
        p[col] = 0.0
        p = p / p.sum()
        a = M.indptr[col]
        b = M.indptr[col + 1]
        M.indices[a:b] = np.random.choice(idxx, b - a, p=p, replace=False)
    return M

largest_strongly_connected_component(adjacency_matrix)

Computes the largest strongly connected component of the graph with adjacency matrix adjacency_matrix, and returns the adjacency matrix of said component

Parameters:

Name Type Description Default
adjacency_matrix numpy array

the adjaceny matrix of the DiGraph as a numpy array

required

Returns:

Type Description
numpy array

The adjacency matrix of the largest strongly connected component

Source code in src/connalysis/network/classic.py
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
def largest_strongly_connected_component(adjacency_matrix):
    """Computes the largest strongly connected component of the graph with adjacency matrix adjacency_matrix,
        and returns the adjacency matrix of said component

    Parameters
    ----------
    adjacency_matrix : numpy array
        the adjaceny matrix of the DiGraph as a numpy array


    Returns
    -------
    numpy array
        The adjacency matrix of the largest strongly connected component

    """
    current_tribe_nx = np_to_nx(adjacency_matrix)
    largest_comp = max(nx.strongly_connected_components(current_tribe_nx), key=len)
    current_tribe_strong_nx = current_tribe_nx.subgraph(largest_comp)
    current_tribe_strong = nx_to_np(current_tribe_strong_nx)
    return current_tribe_strong

np_to_nx(adjacency_matrix)

Converts numpy array of an adjacency matrix to a networkx digraph

Parameters:

Name Type Description Default
adjacency_matrix numpy array

the adjaceny matrix of the DiGraph as a numpy array

required

Returns:

Type Description
networkx DiGraph

a directed graph

Source code in src/connalysis/network/classic.py
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
def np_to_nx(adjacency_matrix):
    """Converts numpy array of an adjacency matrix to a networkx digraph

    Parameters
    ----------
    adjacency_matrix : numpy array
        the adjaceny matrix of the DiGraph as a numpy array


    Returns
    -------
    networkx DiGraph
            a directed graph

    """
    return nx.from_numpy_array(adjacency_matrix,create_using=nx.DiGraph)

nx_to_np(directed_graph)

Converts networkx digraph to numpy array of the adjacency matrix

Parameters:

Name Type Description Default
directed_graph networkx DiGraph

a directed graph

required

Returns:

Type Description
numpy array

the adjaceny matrix of the DiGraph as a numpy array

Source code in src/connalysis/network/classic.py
466
467
468
469
470
471
472
473
474
475
476
477
478
479
def nx_to_np(directed_graph):
    """Converts networkx digraph to numpy array of the adjacency matrix 

    Parameters
    ----------
    directed_graph : networkx DiGraph
        a directed graph

    Returns
    -------
    numpy array
        the adjaceny matrix of the DiGraph as a numpy array
    """
    return nx.to_numpy_array(directed_graph,dtype=int)