Neural Spike Train Analysis Toolbox for Matlab
π Start here: 5-minute introduction page β hero, install, five runnable snippets covering simulation β fitting β KS goodness-of-fit β decoding β SSGLM, plus a paper-example thumbnail gallery and v1.4.0 release highlights.
nSTAT is the reference MATLAB implementation of the point-process / state-space framework for spike-train analysis: PP-GLM fitting (Poisson and binomial), time-rescaling KS goodness-of-fit, PPAF (point-process adaptive filter β the spike-train analog of the Kalman filter), PPHF (hybrid discrete + continuous-state filter), SSGLM (state-space GLM for trial-drifting coefficients), and PPLFP (multi-modal spike + LFP sensor-fusion filter).
For the canonical textbook treatment of the math β including full derivations of the time-rescaling theorem, the PPAF as one Newton step on the variational free energy, and the PPLFP additive innovation β see Decoding the Brain, Chapter 4 (Cajigas Lab Curriculum).
nSTAT also provides tools for Gaussian signals (correlation analysis, Kalman filter / smoother) for continuous normally-distributed neural signals such as LFP / EEG / ECoG. Although created with neural signal processing in mind, the SignalObj / Covariate abstractions can be applied to any discrete and continuous signal types.
For new work in Python, see nSTAT-python. This MATLAB repository remains the canonical site for reproducing Cajigas et al. 2012 and is the lab's MATLAB-side reference implementation.
The current release version of nSTAT can be downloaded from https://github.com/cajigaslab/nSTAT/ . Lab websites:
- Neuroscience Statistics Research Laboratory: https://www.neurostat.mit.edu
- RESToRe Lab: https://www.med.upenn.edu/cajigaslab/
- Clone this repository and open MATLAB.
- Change directory to the repository root (the folder containing
nSTAT_Install.m). - Run the installer:
nSTAT_InstallWhen the paper-example dataset is not present, the installer now prompts to
download it from figshare into the repository data/ folder.
Noninteractive install:
nSTAT_Install('DownloadExampleData',true)Optional installer flags:
nSTAT_Install('RebuildDocSearch', true, 'CleanUserPathPrefs', false, 'DownloadExampleData', 'prompt')RebuildDocSearchrebuilds the help search database inhelpfiles/.CleanUserPathPrefsremoves stale user MATLAB path entries.DownloadExampleDataacceptstrue/'always',false/'never', or'prompt'.
Quickstart (MATLAB 2025b):
cd('/path/to/nSTAT')
nSTAT_Install('RebuildDocSearch',true,'CleanUserPathPrefs',true);
addpath(fullfile(pwd,'tools'));
run_all_checks('GenerateBaseline',false,'CheckParity',true,'RunTests',true,'PublishDocs',false,'Style','legacy');Canonical source files:
helpfiles/nSTATPaperExamples.mlx(preferred narrative source)helpfiles/nSTATPaperExamples.m(script source used for extraction)
Single command to regenerate every standalone paper example and figure:
cd('/path/to/nSTAT')
addpath(genpath(pwd));
build_paper_examples;This produces docs/figures/<example_id>/... and
docs/figures/manifest.json. All images are generated from MATLAB code in
this repository; no figures are copied from the publication PDF.
| Example | Thumbnail | What question it answers | Run command | Links |
|---|---|---|---|---|
| Example 01 | ![]() |
Do mEPSCs follow constant vs piecewise Poisson firing under Mg2+ washout? | example01_mepsc_poisson('ExportFigures',true,'ExportDir',fullfile(pwd,'docs','figures','example01')); |
Script Β· Figures |
| Example 02 | ![]() |
How do explicit whisker stimulus and spike history improve thalamic GLM fits? | example02_whisker_stimulus_thalamus('ExportFigures',true,'ExportDir',fullfile(pwd,'docs','figures','example02')); |
Script Β· Figures |
| Example 03 | ![]() |
How do PSTH and SSGLM capture within-trial and across-trial dynamics? | example03_psth_and_ssglm('ExportFigures',true,'ExportDir',fullfile(pwd,'docs','figures','example03')); |
Script Β· Figures |
| Example 04 | ![]() |
Which receptive-field basis (Gaussian vs Zernike) better fits place cells? | example04_place_cells_continuous_stimulus('ExportFigures',true,'ExportDir',fullfile(pwd,'docs','figures','example04')); |
Script Β· Figures |
| Example 05 | ![]() |
How well do adaptive/hybrid point-process filters decode stimulus and reach state? | example05_decoding_ppaf_pphf('ExportFigures',true,'ExportDir',fullfile(pwd,'docs','figures','example05')); |
Script Β· Figures |
Expanded paper-example index and figure gallery:
Plot style policy:
% Modern readability-focused plots (default)
nstat.setPlotStyle('modern');
% Legacy visual style for strict reproduction
nstat.setPlotStyle('legacy');Rendered help documentation (GitHub Pages):
For mathematical and programmatic details of the toolbox, see:
Cajigas I, Malik WQ, Brown EN. nSTAT: Open-source neural spike train analysis toolbox for Matlab. Journal of Neuroscience Methods 211: 245β264, Nov. 2012 https://doi.org/10.1016/j.jneumeth.2012.08.009 PMID: 22981419
To keep terminology and workflows consistent with the 2012 toolbox paper, the MATLAB help system includes a dedicated mapping page:
helpfiles/PaperOverview.m(published asPaperOverview.html)
This page ties major toolbox components to the paper's workflow categories:
- Class hierarchy and object model (
SignalObj,Covariate,Trial,Analysis,FitResult,DecodingAlgorithms) - Fitting and assessment workflow (GLM fitting, diagnostics, summaries)
- Simulation workflow (conditional intensity and thinning examples)
- Decoding workflow (univariate/bivariate and history-aware decoding)
- Example-to-paper section mapping via
nSTATPaperExamples
If you use nSTAT in your work, please remember to cite the above paper in any publications. nSTAT is protected by the GPL v2 Open Source License.
The code repository for nSTAT is hosted on GitHub at https://github.com/cajigaslab/nSTAT. The paper-example dataset is distributed separately from the Git repository:
- Figshare dataset DOI: https://doi.org/10.6084/m9.figshare.4834640.v3
- Paper DOI: https://doi.org/10.1016/j.jneumeth.2012.08.009
A comprehensive 5-phase code audit identified and fixed 67 bugs across 8
core files. All changes are tagged with inline % FIX: comments for easy
review. See AUDIT_REPORT.md for full details.
Critical bugs fixed:
- FitResult.m β Time-rescaling KS test used
sampleRateas bin width instead of1/sampleRate, invalidating goodness-of-fit for any sampleRate != 1 - DecodingAlgorithms.m β
isa(condNum,'nan')always returned false, so NaN condition numbers were never caught and singular matrices passed unchecked through PPAF/PPHF decoding;ExplambdaDeltaCubedused.^2instead of.^3, corrupting higher-order filter corrections - CIF.m β
symvar()reordered variables alphabetically, but all callers passed arguments invarInorder, causing silent argument mismatch inmatlabFunction-generated handles for non-alphabetical variable names - SignalObj.m β
findPeaks('minima')silently returned maxima;findGlobalPeak('minima')always crashed due tosOBjtypo; handle aliasing intimes/rdivide/ldividemutated input signals - nspikeTrain.m β Burst detection had off-by-one index error and wrong append order
Code quality improvements:
- 22
eval()βfeval()conversions (SignalObj.m) - 11 silent
catchβ named exception captures - 7
roundnβroundreplacements (removes Mapping Toolbox dependency) - 3
log(0)guards, division-by-zero guards, floating-point index fixes fitTypevalidation in CIF constructor- Deprecated function annotations (
histc,simget)
A follow-up wave of work in May 2026 added correctness fixes, architectural cleanup, and CI-replacing local gates. See docs/superpowers/plans/2026-05-19-nstat-review-action-plan.md for the action plan.
Additional correctness fixes (Phase 0):
- FitResult.m / Analysis.m β Bernoulli log-likelihood missing
log()wrap on1βΞ»Ξ(commitsacd57c7,d1e96cf) - Analysis.m β KS U-clamping before
ks_statcomputation inflated KS statistics (ef01a82); DT-correction branch was unreachable for typical inputs (f460aa8);ksdiscreteignored caller-set RNG seed (f2307e9) - FitResult.m β multi-result Ξ» branch indexed result 1 for all
results (
1520034);plotSeqCorrhad no non-finite guard for U-transform overflow (f5b5734) - DecodingAlgorithms.m β PPAF goal-directed predict time-indexing
(
3ffebd5); PPHF A/Q time-index + missing x0/Pi0 goal fusion (bc5f879,1bcb63e,ba7069a)
Architectural cleanup (Phase 3):
+nstat/+decoding/package: 8 cluster classes (PPAF,PPHF,PPLFP,SSGLM,KalmanFilter,UKF,KF_EM,PointProcessEM) extracted from the 10860-lineDecodingAlgorithms.m, which is now a 1189-line facade with 47 deprecation shims.mPPCO_*methods renamed toPPLFP_*(paper Β§4.B.7 alignment;mPPCO_*retained as deprecation shims).- Woodbury matrix-inversion update step centralized in
+nstat/+decoding/+internal/computeGainMatrix.m. nstat.Defaultsclass for centralized tolerances (EM_TolAbs=1e-3,EM_MaxIter=100,DTRegimeBound=0.4, β¦).
New capabilities (Phase 3.5 + 4):
LinearCIFβ canonical-link CIF with closed-form gradient and Hessian; drop-in replacement for symbolicCIFwhen the Symbolic Math Toolbox is undesirable (Poisson and binomial supported).History.raisedCosine(K, tMin, tMax)β Pillow 2008 log-spaced raised-cosine basis.PPAF.PPDecode_updateIterated/PPDecode_updateLinearIteratedβ iterated-Laplace PPAF update with prior-gradient correction term.
Local test gate (no MATLAB CI):
The team's MathWorks license does not extend to GitHub-hosted runners,
so the test gate is local. Run tools/run_unit_tests.sh (20 unit tests)
and tools/check_readme_figures.sh (README figure parity) before
pushing changes that touch core code. See CONTRIBUTING.md
for the full developer workflow and docs/superpowers/plans/
for plan documents.
Comprehensive audit (2026-05-20):
See docs/superpowers/plans/2026-05-20-comprehensive-codebase-audit.md for the four-phase help-system + cross-document + bug-pattern + deploy-gate audit and docs/verification/ for the empirical reports it produced.
The standalone Python port now lives in a separate repository:
This nSTAT repository is MATLAB-focused and retains:
- Original MATLAB class/source files
- MATLAB helpfiles and help index (
helpfiles/helptoc.xml) - MATLAB example workflows, including
.mlxexamples




