MATLAB vs. Python: what’s ported, what’s approximate, what’s missing¶
The Python port is a genuine reimplementation of MEA-NAP’s core analysis steps, actively validated against real MATLAB output. This page summarizes that validation honestly, so you know what to trust and what to double-check before using the Python port for a publication figure.
For contributors
This page is the short, user-facing summary. The full engineering log — with
exact test names, fixture files, and line-by-line gotchas for anyone touching
src/meanap/pipeline/ — lives in
python/PIPELINE_PORT_STATUS.md
in the repository.
Three kinds of “parity” with MATLAB¶
Not every metric can match MATLAB bit-for-bit, and that’s expected rather than a bug — it’s worth understanding the three categories before reading the table below:
Deterministic computations validated to match MATLAB’s own output to
floating-point precision (e.g. ~1e-15). Spike time tiling coefficient,
electrode coordinate lookup, core graph metrics (degree, density, clustering,
path length, efficiency, betweenness centrality) all fall here.
Some MATLAB steps use randomization that is never seeded — even two MATLAB runs of the same recording produce different numbers here. For these, the Python port validates that its formulas match MATLAB exactly when fed the same random intermediate result, without trying to reproduce MATLAB’s specific RNG stream (which isn’t reproducible even between two MATLAB runs). This covers significance thresholding (step 3), community detection and the normalized participation coefficient, and small-worldness’s null models.
Non-negative matrix factorization (NMF) uses scikit-learn’s coordinate
descent solver rather than MATLAB’s Alternating Least Squares — a genuinely
different algorithm, not just a different random seed. Treat
num_nnmf_components and related outputs as approximate.
Step-by-step status¶
Step |
Status |
|---|---|
1. Spike detection |
Threshold-based methods ( |
2. Neuronal activity (firing rates, bursts) |
Exact parity confirmed field-by-field against MATLAB’s own summary CSVs, when fed the same spike times. |
3. Functional connectivity (STTC) |
The STTC computation itself has exact parity. Significance thresholding is inherently non-reproducible between runs (see above) — this is true of MATLAB too. |
4. Network metrics |
Core graph metrics (ND, NS, density, clustering, path length, global/local efficiency, betweenness centrality) have exact parity. Modularity-dependent metrics (participation coefficient, module z-score, rich club, node cartography, hub classification, small-worldness) have exact parity given the same community assignment — the community assignment itself is stochastic in both MATLAB and Python. Controllability metrics are fully ported. NMF-based metrics are approximate (different algorithm, see above). |
Known gaps¶
No group-level statistical comparisons yet. MATLAB’s step 5 (comparing network features across ages/genotypes with statistics) is not implemented — the Python port currently produces per-recording, per-lag results plus batch-scaled plot variants, not MATLAB’s full
RecordingsByGroup/GraphMetricsByLaggroup-comparison figures and CSVs.Customchannel layout is not supported. MATLAB’s user-drawn custom electrode layout has no Python equivalent yet; the port supportsMCS60old,MCS60,MCS59,Axion64, andAxion16, all with confirmed exact coordinate parity against MATLAB.No single combined output
.matfile. MATLAB writes one<recording>_<output>.matper recording containingInfo/Params/spikeTimes/Ephys/adjMstogether. The Python port instead writes.npz/.json/.csvper step (see the output report page for the full folder layout) plus a per-recording adjacency.npz.Spatial/temporal autocorrelation metrics are not implemented — these aren’t in MATLAB’s own default metric list either, and MATLAB’s own code path for temporal autocorrelation is an explicit unfinished stub, so there’s no complete reference behavior to port yet.
Some diagnostic-only plots are not ported: the null-model-iteration convergence plot, and log-scaling on two of the step-2 burst heatmaps (cosmetic axis transform, not exercisable on the bundled example data since it has no detected bursts).
Performance expectations¶
The slowest parts of a full pipeline run are, by design, the parts that are doing genuine repeated-sampling statistics rather than being slow to implement:
Step 3 re-runs STTC significance thresholding (default 200 circular-shift surrogates) per lag, per recording.
Step 4’s normalized participation coefficient runs 100 degree-preserving network randomizations per (recording, lag).
Neither of these is a Python-vs-MATLAB speed question — MATLAB pays the same cost for the same statistical rigor. A full run on the bundled two-recording example dataset takes a few minutes; see Quickstart if you just want to see steps 1–2 (fast) without waiting for 3–4.