Skip to main content

End-to-end MEA data analysis for Axion Biosystems instruments

Project description

py-mea-axion

PyPI version Python GitHub

End-to-end analysis of multi-electrode array (MEA) recordings from Axion Biosystems instruments, in Python.

py-mea-axion reads raw .spk binary files and carries the analysis through spike metrics, burst detection, network-burst detection, and synchrony measurement, all the way to statistical comparisons and publication-ready figures, driven entirely from the command line.


Installation

conda create -n mea python=3.11
conda activate mea
pip install py-mea-axion

For development against a local clone:

git clone https://github.com/Molecularbiologyworld/py-mea-axion.git
cd py-mea-axion
pip install -e .

To install the latest commit on master directly from GitHub:

pip install git+https://github.com/Molecularbiologyworld/py-mea-axion.git

Requirements: Python ≥ 3.10, numpy, scipy, pandas, matplotlib, pingouin, statsmodels.


Workflow at a glance

The CLI is organised around four phases:

  1. mea-axion build processes a folder of .spk files into a single labelled master CSV.
  2. mea-axion plot <subcommand> generates figures from the master CSV.
  3. mea-axion stats writes a long-format CSV of pairwise condition-comparison results, using the same statistical dispatcher that drives the violin brackets.
  4. mea-axion show-layout prints the well-to-condition map encoded in any master CSV.

There are also mea-axion run (single recording, CSVs and figures) and mea-axion summary (single recording, stdout table) for one-off analyses.


Filename convention

build requires every .spk file to carry plate and DIV in its name:

<anything>_Plate<N>_DIV<N>.spk

Detection regex (case-insensitive): Plate(\d+)_DIV(\d+). Anything before or after that block is ignored. Files in the input folder that do not match are skipped with a warning.

Filename Plate DIV
Plate1_DIV14.spk 1 14
20251002_Plate2_DIV26.spk 2 26
LGI2KD_Plate3_DIV7_recording2.spk 3 7

Build a master CSV

You specify the well-to-condition layout once, on the command line:

mea-axion build "data/" --fs-override 12500 \
  --well 1_A1=SCRM,B1,T1,Batch1 \
  --well 1_A2=KD,B1,T1,Batch1 \
  --well 1_B1=SCRM,B1,T2,Batch1 \
  --well 1_B2=KD,B1,T2,Batch1 \
  ... \
  --out master.csv

Each --well entry follows the form <plate>_<well>=<condition>[,B<bio>,T<tech>,<batch>].

  • B<n> (biological replicate) and T<n> (technical replicate) are optional.
  • The 4th comma-separated value is the batch label (free-form, e.g. Batch1, Plate2).
  • Bio rep auto-derives from (plate, well) if not specified.

Output: master.csv (one row per well per DIV, with metric columns plus condition / bio_rep / tech_rep / batch columns) and a sibling master.build.sh containing the command for re-runs.

Re-using a layout

Three ways to avoid retyping the layout for a follow-up build:

# Option 1: re-run the auto-saved script.
bash master.build.sh

# Option 2: pull the layout from an existing master CSV.
mea-axion build "data_v2/" --fs-override 12500 --layout-from master.csv --out master_v2.csv

# Option 3: print the equivalent --well flags to stdout.
mea-axion show-layout master.csv

Plot subcommands

mea-axion plot heatmap     master.csv --metric mean_mfr_active_hz --div 21 --out figs/
mea-axion plot trajectory  master.csv --metric mean_mfr_active_hz --out figs/
mea-axion plot timepoint   master.csv --metric mean_mfr_active_hz --div 21 26 33 --out figs/
mea-axion plot pca         master.csv --out figs/
mea-axion plot raster      "recording.spk" --fs-override 12500 --wells A1 --out figs/
Subcommand Input What it produces
heatmap master CSV 4×6 plate grid, one panel per plate, coloured by metric. One PNG per (metric, DIV).
trajectory master CSV Mean ± SEM error-bars per condition across DIVs. One PNG per metric.
timepoint master CSV Violin and jitter per condition at one DIV, with user-selectable significance brackets. One PNG per (metric, DIV).
pca master CSV PCA scatter coloured by condition. One pooled PNG, or one per --div. Optional loadings figure.
raster .spk file Burst raster and ASDR histogram for each well.

Common plot flags

Flag Effect
--metric COL [COL ...] One or more metric columns. Omit to plot all numeric columns.
--div N [N ...] Specific time points (timepoint, pca, heatmap).
--div-min N --div-max N Filter the time range (trajectory, pca).
--filter COL=VAL[,VAL...] Restrict the input to specific column values. Repeatable; multiple flags AND together. Example: --filter condition=SCRM --filter DIV=14,28.
--group-order GROUP [GROUP ...] Explicit condition order (default: alphabetical). Listing a subset excludes other groups from the plot.
--color GROUP=#HEX Colour per condition. Repeatable. Hex codes or matplotlib named colours both work.
--pool Flatten bio/tech replicate hierarchy and treat every well as independent. Default is hierarchical (collapse tech reps within bio rep before stats).
--figsize W H Figure size in inches. Default depends on the plot type.
--out DIR Output directory (auto-created).

Flags specific to plot timepoint (violins)

Flag Effect
--test {tukey,mannwhitney,kruskal} Statistical test for the significance brackets. Default tukey (parametric all-pairs Tukey HSD). mannwhitney runs pairwise Mann-Whitney U with Bonferroni correction. kruskal runs Kruskal-Wallis omnibus followed by Dunn's pairwise post-hoc. The choice is yours; the package does not auto-select.
--compare GROUP_A GROUP_B Restrict significance brackets to specific pairs. Repeatable.
--point-hue COL Colour individual jitter points by another column (e.g. batch).
--point-color VALUE=#HEX Per-value colour palette for --point-hue. Repeatable.
--point-shape COL Use marker shape (in addition to or instead of colour) for individual jitter points. Default markers cycle circle, square, triangle, diamond, etc.
--point-shape-map VALUE=MARKER Per-value marker for --point-shape. Repeatable. Markers can be matplotlib codes (o, s, ^, ...) or aliases (circle, square, triangle, ...).
--point-size N Marker area for jitter points. Default 40.
--show-point-legend Show a legend mapping point colours to --point-hue values. Default hidden.

Flags specific to plot raster

Flag Effect
--asdr-bin S ASDR histogram bin width in seconds. Default 0.2.
--time-start S --time-end S Restrict to a time window in seconds within the recording. Displayed times keep the original timestamps.
--density-color Colour each spike tick by local spike density (binned at --asdr-bin). Adds a colour bar underneath the raster.
--density-cmap NAME Matplotlib colour map for --density-color. Default viridis.
--max-isi S --min-spikes N Burst-detection thresholds for the orange overlay rectangles.

Flags specific to plot pca

Flag Effect
--loadings Also save a per-feature PC loadings CSV and a horizontal bar chart of the top contributors to PC1 and PC2.
--top N Number of top features to show in the loadings figure. Default 10.
--point-shape COL --point-shape-map VALUE=MARKER Same as for timepoint, useful for indicating biological replicates by marker shape.

Run mea-axion plot <subcommand> --help for the full per-subcommand option list.

Example: a complete violin command

mea-axion plot timepoint master.csv \
  --metric mean_mfr_active_hz burst_freq_avg network_burst_freq mean_sttc \
  --div 21 26 33 \
  --group-order SCRM LGI2_KD4 LGI2_KD5 \
  --color SCRM=green --color LGI2_KD4=lightcoral --color LGI2_KD5=red \
  --point-shape batch --point-shape-map Batch1=circle --point-shape-map Batch2=square --point-shape-map Batch3=triangle \
  --compare LGI2_KD4 SCRM --compare LGI2_KD5 SCRM \
  --test tukey \
  --pool \
  --out figs/timepoint

Pretty axis labels

Axis labels and colour-bar titles render human-readable names (Mean firing rate (Hz) rather than mean_mfr_active_hz). The CLI flag values still use raw column names, which are easier to type.


Statistical analyses (mea-axion stats)

Beyond the brackets shown on violin plots, mea-axion stats writes a long-format CSV of pairwise condition-comparison results. Same data, same dispatcher as the violin brackets, just persisted as a tidy table for supplementary materials.

mea-axion stats master.csv \
  --metric mean_mfr_active_hz burst_freq_avg network_burst_freq mean_sttc \
  --div 28 41 \
  --compare LGI2_KD4 SCRM --compare LGI2_KD5 SCRM \
  --test tukey \
  --pool \
  --out stats_summary.csv

The output CSV has one row per (metric, time-point, pair) combination, with columns metric, DIV, test, group_a, group_b, mean_diff, p_adj, significance, n_a, n_b. Sort by metric and DIV in Excel for a clean supplementary table.

The same --test choice (tukey, mannwhitney, kruskal) applies. Significance labels (*, **, ***, ns) match those used in the figures.


Single-recording commands

For ad-hoc inspection of one .spk file without going through build:

# Quick per-well summary printed to the terminal (no files written)
mea-axion summary recording.spk --fs-override 12500

# Full pipeline: writes CSVs and figures to results/
mea-axion run recording.spk --out results/ --fs-override 12500

# Restrict to specific wells
mea-axion summary recording.spk --wells A1 B1 C1 --fs-override 12500

# Analyse only a time window
mea-axion run recording.spk --time-start 300 --time-end 600 --out results/ --fs-override 12500

Python API

For programmatic use:

from py_mea_axion import MEAExperiment

exp = MEAExperiment(
    "recording.spk",
    metadata="plate_map.csv",   # optional CSV with well_id, condition, DIV, replicate_id
    fs_override=12500,
).run()

exp.spike_metrics      # per-electrode metrics
exp.burst_table        # one row per detected burst
exp.well_summary       # per-well aggregate (27 metrics)
exp.to_csv("results.csv")

exp.plot_heatmap("A1")
exp.plot_raster("A1")
exp.plot_trajectory("mean_mfr_active_hz")

The py_mea_axion.stats module exposes the same statistical functions used by the CLI:

from py_mea_axion.stats import (
    pairwise_test,            # unified dispatcher: tukey / mannwhitney / kruskal
    tukey_hsd_pairwise,       # Tukey HSD only
    compare_conditions,       # auto-dispatch MW (2 groups) or KW (3+ groups)
    longitudinal_model,       # linear mixed-effects with time x group interaction
    compute_icc,              # intraclass correlation
)

Note on Axion .spk files

Some recordings lack a BlockVectorHeader (firmware-dependent). When that happens, sampling-rate detection may guess wrong; pass --fs-override explicitly:

mea-axion run recording.spk --fs-override 12500

12500 Hz is the standard rate for Axion CytoView 24-well plates.


Running the tests

pip install -e ".[dev]"
pytest

649 tests covering every module: binary parser, burst detection, network-burst detection, synchrony, statistical tests, every viz function, and every CLI subcommand.


Citing

If you use py-mea-axion in your research, please cite:

[manuscript in preparation]

DOI


License

MIT, see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_mea_axion-0.4.0.tar.gz (125.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_mea_axion-0.4.0-py3-none-any.whl (93.6 kB view details)

Uploaded Python 3

File details

Details for the file py_mea_axion-0.4.0.tar.gz.

File metadata

  • Download URL: py_mea_axion-0.4.0.tar.gz
  • Upload date:
  • Size: 125.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for py_mea_axion-0.4.0.tar.gz
Algorithm Hash digest
SHA256 e3049376f4fbbaa593c63e4e3486832fdad6faf8f807deb90651720d0f6bef96
MD5 8cb6ecca217b39e54fdcc5f5d9944a6b
BLAKE2b-256 d4c78dcedd378476eb439e6e475d12f80ec64867ece0776e174f0932ae955fd3

See more details on using hashes here.

File details

Details for the file py_mea_axion-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: py_mea_axion-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 93.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for py_mea_axion-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f43bfc87783ee671154658c975fc10b426d48d3fc6183387a4e6dec02432efea
MD5 3c4eeff01552313c595d1e9b9dfd07d6
BLAKE2b-256 98ba11ec0c13a4cef571eff6578707da5a50aa3904c66230e6dc5813bb2dada1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page