networktools module
- clabtoolkit.networktools.adjacency_matrix_to_csr(adj_matrix)[source]
Convert a dense adjacency matrix to CSR (Compressed Sparse Row) format.
This method takes a square adjacency matrix where non-zero entries represent connections between vertices and converts it to an efficient sparse representation.
- Parameters:
adj_matrix (np.ndarray) – A square 2D numpy array representing the adjacency matrix. Shape should be (n_vertices, n_vertices) where n_vertices is the number of vertices in the graph. Non-zero values represent edge weights.
- Returns:
A scipy sparse CSR matrix representing the same graph connectivity.
- Return type:
csr_matrix
- Raises:
ValueError – If the input matrix is not 2D or not square.
TypeError – If the input is not a numpy array.
Examples
>>> import numpy as np >>> # Create a simple 4-vertex graph >>> adj = np.array([[0, 1, 1, 0], ... [1, 0, 1, 1], ... [1, 1, 0, 1], ... [0, 1, 1, 0]]) >>> csr_graph = adjacency_matrix_to_csr(adj) >>> print(csr_graph.toarray()) [[0 1 1 0] [1 0 1 1] [1 1 0 1] [0 1 1 0]]
>>> # With weighted edges >>> adj_weighted = np.array([[0, 2.5, 1.0, 0], ... [2.5, 0, 0, 3.2], ... [1.0, 0, 0, 1.8], ... [0, 3.2, 1.8, 0]]) >>> csr_weighted = adjacency_matrix_to_csr(adj_weighted) >>> print(f"Non-zero values: {csr_weighted.data}") Non-zero values: [2.5 1. 2.5 3.2 1. 1.8 3.2 1.8]
- clabtoolkit.networktools.triangulated_mesh_to_csr(faces, n_vertices=None)[source]
Convert triangulated mesh faces to a CSR graph representation.
This method constructs a graph where vertices are connected if they share an edge in any triangle face. All edge weights are set to 1. The resulting graph represents the 1-ring neighborhood connectivity of the mesh.
- Parameters:
faces (np.ndarray) – A 2D numpy array of shape (n_faces, 3) where each row contains the indices of three vertices forming a triangle. Vertex indices should be non-negative integers.
n_vertices (int, optional) – Total number of vertices in the mesh. If None, it will be inferred as the maximum vertex index + 1. Providing this parameter is recommended for meshes with isolated vertices.
- Returns:
A scipy sparse CSR matrix of shape (n_vertices, n_vertices) where entry (i,j) is 1 if vertices i and j are connected by an edge in the mesh, and 0 otherwise. The matrix is symmetric for undirected graphs.
- Return type:
csr_matrix
- Raises:
ValueError – If faces array is not 2D, doesn’t have 3 columns, contains negative indices, or if n_vertices is less than the maximum vertex index.
TypeError – If faces is not a numpy array or contains non-integer values.
Examples
>>> import numpy as np >>> # Define a simple tetrahedron (4 faces, 4 vertices) >>> faces = np.array([[0, 1, 2], ... [0, 1, 3], ... [0, 2, 3], ... [1, 2, 3]]) >>> csr_graph = triangulated_mesh_to_csr(faces) >>> print("Adjacency matrix:") >>> print(csr_graph.toarray()) Adjacency matrix: [[0 1 1 1] [1 0 1 1] [1 1 0 1] [1 1 1 0]]
>>> # Triangle mesh with explicit vertex count >>> faces_triangle = np.array([[0, 1, 2]]) >>> csr_triangle = triangulated_mesh_to_csr(faces_triangle, n_vertices=5) >>> print(f"Shape: {csr_triangle.shape}") >>> print("Connections for triangle [0,1,2]:") >>> print(csr_triangle.toarray()) Shape: (5, 5) Connections for triangle [0,1,2]: [[0 1 1 0 0] [1 0 1 0 0] [1 1 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
- clabtoolkit.networktools.edges_to_csr(edges, edge_values=None, n_vertices=None, symmetric=True)[source]
Convert an edge list with values to CSR graph representation.
This method constructs a graph from a list of edges and their corresponding weights/values. Useful for creating graphs from pre-computed edge lists.
- Parameters:
edges (np.ndarray) – A 2D numpy array of shape (n_edges, 2) where each row contains the indices of two connected vertices. Vertex indices should be non-negative integers.
edge_values (np.ndarray) – A 1D numpy array of length n_edges containing the weight/value for each edge. Values can be any numeric type (int, float, etc.).
n_vertices (int, optional) – Total number of vertices in the graph. If None, it will be inferred as the maximum vertex index + 1. Providing this parameter is recommended for graphs with isolated vertices.
symmetric (bool, default=True) – If True, creates an undirected graph by adding reverse edges with the same values. If False, creates a directed graph using only the provided edges.
- Returns:
A scipy sparse CSR matrix of shape (n_vertices, n_vertices) where entry (i,j) contains the weight of the edge from vertex i to vertex j. For undirected graphs (symmetric=True), the matrix is symmetric.
- Return type:
csr_matrix
- Raises:
ValueError – If edges array is not 2D, doesn’t have 2 columns, contains negative indices, edge_values length doesn’t match number of edges, or if n_vertices is less than the maximum vertex index.
TypeError – If edges contains non-integer values or edge_values is not numeric.
Examples
>>> import numpy as np >>> # Create a simple weighted graph >>> edges = np.array([[0, 1], ... [1, 2], ... [0, 2]]) >>> values = np.array([2.5, 1.0, 3.2]) >>> csr_graph = edges_to_csr(edges, values) >>> print("Symmetric weighted graph:") >>> print(csr_graph.toarray()) Symmetric weighted graph: [[0. 2.5 3.2] [2.5 0. 1. ] [3.2 1. 0. ]]
>>> # Directed graph example >>> edges_directed = np.array([[0, 1], [1, 2]]) >>> values_directed = np.array([0.8, 1.5]) >>> csr_directed = edges_to_csr(edges_directed, values_directed, symmetric=False) >>> print("Directed graph:") >>> print(csr_directed.toarray()) Directed graph: [[0. 0.8 0. ] [0. 0. 1.5] [0. 0. 0. ]]
>>> # Handle duplicate edges (values are summed) >>> edges_dup = np.array([[0, 1], [0, 1], [1, 0]]) >>> values_dup = np.array([1.0, 2.0, 0.5]) >>> csr_dup = edges_to_csr(edges_dup, values_dup) >>> print("Duplicate edges (summed):") >>> print(csr_dup.toarray()) Duplicate edges (summed): [[0. 3.5] [3.5 0. ]]
- clabtoolkit.networktools.edges_to_components(edges, verbose=True)[source]
Compute connected components from an edge array of arbitrary vertex indices. Components are labelled in decreasing order of size (0 = largest).
- Parameters:
edges (np.ndarray, shape (n_edges, 2)) – Array of vertex index pairs. Indices can be global/non-contiguous.
verbose (bool) – If True, print component sizes to the console. If False, suppress output.
- Returns:
n_components (int) – Number of connected components.
labels (np.ndarray, shape (n_vert, 2)) – Column 0: original vertex index. Column 1: component label (0 = largest).
sizes (dict) – {component_label: size} sorted by decreasing size.
- clabtoolkit.networktools.connected_components(csr_graph, verbose=True)[source]
Find connected components in a CSR graph representation.
This method identifies all connected components in an undirected graph represented as a CSR matrix. A connected component is a maximal set of vertices such that there is a path between every pair of vertices in the set.
- Parameters:
csr_graph (csr_matrix) – A scipy sparse CSR matrix representing the graph adjacency matrix. Should be square with shape (n_vertices, n_vertices). For undirected graphs, the matrix should be symmetric. Non-zero entries represent connections.
verbose (bool) – If True, print the number of components and their sizes to the console. If False, suppress output.
- Returns:
n_components (int) – The total number of connected components found in the graph.
labels (np.ndarray, shape (n_vertices, 2)) – A 2D array where the first column contains the original vertex indices (0 to n_vertices-1) and the second column contains the corresponding component label (0 for largest component).
sizes (dict) – A dictionary mapping component labels to their sizes (number of vertices), sorted by decreasing size.
- Raises:
TypeError – If csr_graph is not a scipy csr_matrix.
ValueError – If csr_graph is not square, method is not recognized, or graph is empty.
UserWarning – If the graph appears to be directed (non-symmetric) when undirected behavior is expected.
- Return type:
Examples
>>> import numpy as np >>> from scipy.sparse import csr_matrix >>> >>> # Create a graph with 3 components: [0,1], [2,3,4], [5] >>> row = np.array([0, 1, 2, 2, 3, 3, 4, 4]) >>> col = np.array([1, 0, 3, 4, 2, 4, 2, 3]) >>> data = np.ones(len(row)) >>> graph = csr_matrix((data, (row, col)), shape=(6, 6)) >>> >>> components = connected_components(graph) >>> print("Connected components:") >>> for i, comp in enumerate(components): ... print(f" Component {i}: {comp}") Connected components: Component 0: [0, 1] Component 1: [2, 3, 4] Component 2: [5]
>>> # Get component labels as well >>> components, labels = connected_components(graph, return_labels=True) >>> print(f"Component labels: {labels}") >>> print(f"Vertex 3 belongs to component: {labels[3]}") Component labels: [0 0 1 1 1 2] Vertex 3 belongs to component: 1
>>> # Using different algorithms >>> comp_bfs = connected_components(graph, method="bfs") >>> comp_dfs = connected_components(graph, method="dfs") >>> # All methods should give the same result (possibly in different order)
>>> # Example with weighted edges (weights are ignored for connectivity) >>> weighted_graph = edges_to_csr( ... np.array([[0, 1], [1, 2]]), ... np.array([2.5, 3.0]) ... ) >>> components = connected_components(weighted_graph) >>> print(f"Weighted graph components: {components}") Weighted graph components: [[0, 1, 2]]
Notes
Edge weights are ignored; only connectivity matters.
Self-loops (diagonal entries) are ignored for component detection.
- For directed graphs, this finds weakly connected components (treating
edges as undirected).
Empty components (isolated vertices) are included as single-vertex components.
The networktools module provides graph analysis and network theory tools specifically designed for brain connectivity and mesh-based analysis.
Key Features
Graph representation creation from brain meshes
Sparse matrix operations for large-scale networks
Connectivity analysis utilities
Network topology analysis
Efficient storage and manipulation of large graphs
Integration with scipy.sparse for performance
Main Functions
Graph Conversion
triangulated_mesh_to_csr(): Convert triangulated meshes to compressed sparse row formatadjacency_matrix_to_csr(): Convert adjacency matrices to sparse formatedges_to_csr(): Convert edge lists to compressed sparse row format
Common Usage Examples
Converting mesh to graph:
from clabtoolkit.networktools import triangulated_mesh_to_csr
import nibabel as nib
# Load surface mesh
vertices, faces = nib.freesurfer.read_geometry("lh.pial")
# Convert to sparse graph representation
graph_csr = triangulated_mesh_to_csr(vertices, faces)
print(f"Graph shape: {graph_csr.shape}")
print(f"Number of edges: {graph_csr.nnz}")
Working with connectivity matrices:
from clabtoolkit.networktools import adjacency_matrix_to_csr
import numpy as np
# Convert dense connectivity matrix to sparse format
connectivity_matrix = np.random.rand(100, 100)
connectivity_matrix = (connectivity_matrix + connectivity_matrix.T) / 2 # Make symmetric
# Convert to sparse format for efficient processing
sparse_conn = adjacency_matrix_to_csr(connectivity_matrix, threshold=0.1)
# Analyze network properties
print(f"Network density: {sparse_conn.nnz / (sparse_conn.shape[0]**2):.3f}")
Edge list conversion:
# Convert edge list to sparse matrix
edges = [[0, 1], [1, 2], [2, 0]] # Triangle connectivity
sparse_matrix = edges_to_csr(edges, n_nodes=3)
print(f"Graph shape: {sparse_matrix.shape}")
print(f"Number of edges: {sparse_matrix.nnz}")
print(f"Network density: {sparse_matrix.nnz / (sparse_matrix.shape[0]**2):.3f}")