meanap.pipeline.network_metrics

Network metrics, ported from the Brain Connectivity Toolbox (Functions/2019_03_03_BCT/*.m) as called by ExtractNetMet.m.

Most of this module is pure, deterministic functions of a fixed adjacency matrix — ND, NS, MEW, Dens, CC (raw), PL (raw), Eglob, Eloc, BC, NE, plus participation_coef (raw), module_degree_zscore, and rich_club_wu. These (plus classify_node_cartography, a simple deterministic threshold classification of PC/Z) require a community assignment (Ci) as input — deterministic given Ci, but Ci itself comes from modularity.py’s consensus clustering, which is stochastic (see that module’s docstring).

participation_coef_norm is additionally stochastic on top of that — it needs 100 iterations of degree-preserving network randomization (null_models.null_model_und_sign, also not bit-reproducible against MATLAB) to normalize the raw participation coefficient. This is the function whose first output MEA-NAP actually saves as ``NetMet.PC``participation_coef’s raw formula is genuinely a different, deterministic quantity, kept because it’s independently useful and testable.

small_worldness_rl_wu (SW/SWw, and the saved NetMet.CC/ NetMet.PL) is likewise stochastic on top of its deterministic formula — it needs a random (null_models.randmio_und_v2) and a lattice-like (null_models.latmio_und_v2) null model built from the same adjacency matrix to normalize against (10000/5000 rewiring iterations respectively, matching ExtractNetMet.m’s call site). This module’s compute_network_ metrics (in step4.py) keeps the raw, unnormalized clustering coefficient / path length available too, under CC_raw/PL_raw — NOT the same numbers MATLAB saves into NetMet.CC/NetMet.PL, but independently useful/testable deterministic quantities in their own right, same relationship as PC/PC_raw.

num_nnmf_components/nComponentsRelNS/nnmf_residuals/ nnmf_var_explained (NMF-based dimensionality, port of calNMF.m) live in nmf.py rather than here, since they operate on spike times/matrices rather than an adjacency matrix — read that module’s docstring, this one is not just RNG-stream-different from MATLAB but algorithm-different (sklearn’s NMF solvers vs. MATLAB’s built-in nnmf), so even num_nnmf_components itself can legitimately differ, not just the underlying factor matrices.

Still NOT ported (out of scope): spatial/temporal autocorrelation (SA_lambda/SA_inf/TA_regional/TA_global) — these aren’t in MATLAB’s own default netMetToCal list either (AdvancedSettings.m calls them out as “other optional ones”), and the temporal-autocorrelation code path is an explicit % TODO stub in ExtractNetMet.m itself, so there’s no complete MATLAB reference behavior to port yet. Cmcblty (communicability) also needs no work: not actually computed by MATLAB’s current pipeline either, the code path that would call it (fcn_find_hubs_wu.m) is commented out in ExtractNetMet.m.

Functions

average_controllability(adj_m)

Returns values of average controllability for each node in a network.

betweenness_wei(g)

Node betweenness centrality (Brandes' algorithm) from a length matrix.

charpath(d)

Returns (lambda, efficiency): mean shortest path length + mean inverse.

classify_node_cartography(pc, z, ...)

Classify each node into one of 6 cartography roles from PC/Z.

clustering_coef_wu(w)

Weighted clustering coefficient (geometric mean of triangle intensities).

density_und(adj_m)

distance_wei(length_mat)

Dijkstra shortest-path distance matrix from a connection-length matrix.

effective_rank(spike_times, fs, duration_s, ...)

Computes Effective Rank of the network activity.

efficiency_wei_global(w)

efficiency_wei_local(w)

Modified local efficiency (efficiency_wei(W, 2)), for normalized W.

find_node_deg_edge_weight(adj_m[, ...])

Returns (ND, MEW): mean node degree and mean edge weight per node.

hub_classification(nd, pc, bc, ne)

Returns (Hub3, Hub4): fraction of nodes in the top 10% by >=3 / all 4 of {node degree, participation coefficient, betweenness centrality, nodal efficiency}.

modal_controllability(adj_m)

Returns values of modal controllability for each node in a network.

module_degree_zscore(w, ci)

Within-module degree z-score (undirected graph, flag=0 in MATLAB).

participation_coef(w, ci)

Raw (unnormalized) participation coefficient (Guimera & Amaral 2005).

participation_coef_norm(w, ci[, n_iter, rng])

Normalized participation coefficient — this is what MEA-NAP actually saves as ``NetMet.PC``, and what colors 4_MEA_NetworkPlotNodedegreeParticipationcoefficient.png.

rich_club_wu(adj_m[, k_level])

Weighted rich-club coefficient curve, Rw[k-1] for k = 1..k_level.

small_worldness_rl_wu(a, r, l)

Small-worldness sigma/omega, port of small_worldness_RL_wu.m.

strengths_und(adj_m)

Node strength: sum of edge weights connected to each node.

weight_conversion_lengths(w)

Invert nonzero weights to lengths: L[E] = 1/W[E].

weight_conversion_normalize(w)

Rescale by the maximal absolute weight.

meanap.pipeline.network_metrics.average_controllability(adj_m)[source]

Returns values of average controllability for each node in a network.

Port of ave_control.m (Bassett Lab, 2016). Average controllability measures the ease by which input at that node can steer the system into many easily-reachable states.

Parameters:

adj_m (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.betweenness_wei(g)[source]

Node betweenness centrality (Brandes’ algorithm) from a length matrix.

Parameters:

g (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.charpath(d)[source]

Returns (lambda, efficiency): mean shortest path length + mean inverse.

Matches charpath(D, 0, 0): excludes the diagonal and infinite (disconnected) path lengths from both statistics.

Parameters:

d (ndarray)

Return type:

tuple[float, float]

meanap.pipeline.network_metrics.classify_node_cartography(pc, z, hub_boundary_wm_d_deg, peri_part_coef, non_hub_connector_part_coef, pro_hub_part_coef, connector_hub_part_coef)[source]

Classify each node into one of 6 cartography roles from PC/Z.

Returns (nd_cart_div, pop_num_nc):

  • nd_cart_div: (n,) int array, 1-6 per node — 1 Peripheral node, 2 Non-hub connector, 3 Non-hub kinless node, 4 Provincial hub, 5 Connector hub, 6 Kinless hub. 0 if a node doesn’t fall in any region (shouldn’t happen given MATLAB’s boundaries are exhaustive, but a node can be missed if PC/Z are NaN).

  • pop_num_nc: (6,) count of nodes in each role, 1-indexed by role.

Parameters:
  • pc (ndarray)

  • z (ndarray)

  • hub_boundary_wm_d_deg (float)

  • peri_part_coef (float)

  • non_hub_connector_part_coef (float)

  • pro_hub_part_coef (float)

  • connector_hub_part_coef (float)

Return type:

tuple[ndarray, ndarray]

meanap.pipeline.network_metrics.clustering_coef_wu(w)[source]

Weighted clustering coefficient (geometric mean of triangle intensities).

Parameters:

w (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.density_und(adj_m)[source]
Parameters:

adj_m (ndarray)

Return type:

float

meanap.pipeline.network_metrics.distance_wei(length_mat)[source]

Dijkstra shortest-path distance matrix from a connection-length matrix.

Parameters:

length_mat (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.effective_rank(spike_times, fs, duration_s, eff_fs, method='covariance')[source]

Computes Effective Rank of the network activity.

Port of calEffRank.m (Roy and Vetterli, 2007). Constructs the dense binary spike matrix at fs, resamples it down to eff_fs using a polyphase FIR filter, and computes the Shannon entropy of the eigenvalues of the covariance/correlation matrix.

Parameters:
  • spike_times (list[ndarray])

  • fs (float)

  • duration_s (float)

  • eff_fs (float)

  • method (str)

Return type:

float

meanap.pipeline.network_metrics.efficiency_wei_global(w)[source]
Parameters:

w (ndarray)

Return type:

float

meanap.pipeline.network_metrics.efficiency_wei_local(w)[source]

Modified local efficiency (efficiency_wei(W, 2)), for normalized W.

Parameters:

w (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.find_node_deg_edge_weight(adj_m, edge_thresh=0.0001, exclude_zeros=True)[source]

Returns (ND, MEW): mean node degree and mean edge weight per node.

Parameters:
  • adj_m (ndarray)

  • edge_thresh (float | list[float])

  • exclude_zeros (bool)

Return type:

tuple[ndarray, ndarray]

meanap.pipeline.network_metrics.hub_classification(nd, pc, bc, ne)[source]

Returns (Hub3, Hub4): fraction of nodes in the top 10% by >=3 / all 4 of {node degree, participation coefficient, betweenness centrality, nodal efficiency}.

Ties at the top-10% cutoff are all included (MATLAB uses value-based ismember against the top-N values, not a strict top-N count, so a tie can pull in more than round(aN/10) nodes) — reproduced here with np.isin for the same reason.

Parameters:
  • nd (ndarray)

  • pc (ndarray)

  • bc (ndarray)

  • ne (ndarray)

Return type:

tuple[float, float]

meanap.pipeline.network_metrics.modal_controllability(adj_m)[source]

Returns values of modal controllability for each node in a network.

Port of modal_control.m (Bassett Lab, 2016). Modal controllability indicates the ability of that node to steer the system into difficult-to-reach states.

Parameters:

adj_m (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.module_degree_zscore(w, ci)[source]

Within-module degree z-score (undirected graph, flag=0 in MATLAB).

Parameters:
  • w (ndarray)

  • ci (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.participation_coef(w, ci)[source]

Raw (unnormalized) participation coefficient (Guimera & Amaral 2005).

ci is a 1-indexed community affiliation vector (e.g. from modularity.mod_consensus_cluster_iterate). This is the 3rd output of MATLAB’s participation_coef_norm.m — NOT the normalized value MEA-NAP saves as NetMet.PC (that requires 100 iterations of degree-preserving randomization on top of this).

Parameters:
  • w (ndarray)

  • ci (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.participation_coef_norm(w, ci, n_iter=100, rng=None)[source]

Normalized participation coefficient — this is what MEA-NAP actually saves as ``NetMet.PC``, and what colors 4_MEA_NetworkPlotNodedegreeParticipationcoefficient.png.

Full port of participation_coef_norm.m: computes the raw PC (same as participation_coef()), then runs n_iter degree-preserving network randomizations (null_models.null_model_und_sign) to measure how much of each node’s raw PC is attributable to its module sizes alone vs. genuine cross-module diversity, and normalizes it out.

Not bit-reproducible against MATLAB (the randomizations are stochastic) — see null_models.py’s docstring. n_iter=100 at ~59-64 nodes takes roughly 15-35s; budget for that per (recording, lag).

Returns (PC_norm, PC_residual, PC, between_mod_k) — matching MATLAB’s output order exactly (MEA-NAP’s caller only keeps the first).

Parameters:
  • w (ndarray)

  • ci (ndarray)

  • n_iter (int)

  • rng (Generator | None)

Return type:

tuple[ndarray, ndarray, ndarray, ndarray]

meanap.pipeline.network_metrics.rich_club_wu(adj_m, k_level=None)[source]

Weighted rich-club coefficient curve, Rw[k-1] for k = 1..k_level.

Two distinct sources of NaN, both faithfully reproduced from rich_club_wu.m even though the first looks like an odd condition to special-case: (1) MATLAB skips (leaves NaN) whenever no nodes have degree < k — i.e. when every node already qualifies, no filtering is needed, and the loop takes an early continue rather than computing normally; (2) at the highest k-levels, only 1-2 nodes survive the degree cutoff, giving zero edges among them (Er=0) and a genuine 0/0 MATLAB division producing NaN, reproduced here the same way (not special-cased to 0).

Parameters:
  • adj_m (ndarray)

  • k_level (int | None)

Return type:

ndarray

meanap.pipeline.network_metrics.small_worldness_rl_wu(a, r, l)[source]

Small-worldness sigma/omega, port of small_worldness_RL_wu.m.

a is the real (sub-)network; r a degree-preserving random null model built from a (null_models.randmio_und_v2); l a lattice-like null model built from a (null_models.latmio_und_v2). Deterministic given fixed a/r/l — the stochasticity lives entirely in how r/l were generated (see null_models.py).

Returns (sw, sww, cc, pl):

  • sw: sigma small-worldness, (C/Cr) / (PL/PLr). > 1 indicates small-world properties.

  • sww: omega small-worldness, (PLr/PL) - (C/Cl), in [-1, 1]. Close to 0 is small-world; close to 1 is random-like; close to -1 is lattice-like.

  • cc: clustering coefficient normalized against the lattice model (C/Cl) — what MEA-NAP actually saves as NetMet.CC.

  • pl: path length normalized against the random model (PL/PLr) — what MEA-NAP actually saves as NetMet.PL.

Parameters:
  • a (ndarray)

  • r (ndarray)

  • l (ndarray)

Return type:

tuple[float, float, float, float]

meanap.pipeline.network_metrics.strengths_und(adj_m)[source]

Node strength: sum of edge weights connected to each node.

Parameters:

adj_m (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.weight_conversion_lengths(w)[source]

Invert nonzero weights to lengths: L[E] = 1/W[E].

Parameters:

w (ndarray)

Return type:

ndarray

meanap.pipeline.network_metrics.weight_conversion_normalize(w)[source]

Rescale by the maximal absolute weight.

Parameters:

w (ndarray)

Return type:

ndarray