Quality

What the automated tests check

The test suite (tests/, run with run_tests) analyses synthetic data with known answers, analytic signals and published textbook examples, and compares the results with stated tolerances. Continuous integration runs it in real MATLAB, with a virtual display, on every push.

Scope and limits

Demo ground truth recovered

QuantitySimulated / exactChecked withinTest
LDF: response peak delay (trial average)4 s± 0.5 sDemoDataTest, LDFPipelineTest
LDF: response amplitude30 PU± 25% (DemoDataTest); ± 5 PU (LDFPipelineTest)DemoDataTest, LDFPipelineTest
LDF: onsets and trials9 onsets, 8 complete trialsonsets ± 1 sample; exact countLDFPipelineTest
LDF processing vs the previous in-app codesame trials1e-12LDFPipelineTest
ERP: N1 latency on the sink channel15 ms± 3 msDemoDataTest, LFPFeaturesTest
ERP: channel with the deepest N1; CSD sink channelchannel 4exactDemoDataTest, LFPFeaturesTest
ERP: stimulus onsets15 onsets± 1 sampleLFPFeaturesTest
ERSP: 40 Hz burst, 100–200 ms (oscillation demo)phase-locked burst> 6 dB; ITPC > 0.8; < 3 dB on channel 8LFPFeaturesTest
Band power: theta on channel 8A² = (40 µV)²± 20%, not modulated by the stimuliLFPFeaturesTest
MUA: threshold crossings on channel 4simulated spike count0.6× to 1.5×DemoDataTest
MUA: units after sorting + auto-merge (channel 4)2 home units (+1 from channel 5)2 to 3 unitsMUAFeaturesTest
Imaging: time of the last calcium peak11 s± 0.6 sDemoDataTest
Imaging: mean vessel diameter12 px± 3 pxDemoDataTest
Imaging: red blood cell speed from the kymograph2 px/frame± 0.3DemoDataTest
Motion correction: per-frame shift errorrandom walk, max 3 px< 0.3 px (mean reference), < 0.4 px (first frame)ImagingFeaturesTest
Detect cells3 cellsexactly 3, centres within 3 pxImagingFeaturesTest
ΔF/F per detected cellevent times per cellpeaks ± 0.5 s; < 0.1 at other cells' eventsImagingFeaturesTest
Robust vessel diameter with a crossing blood cell12 ± 3 px sinemax error < 2.5 px, RMS < 1 px (standard: jumps > 10 px)ImagingFeaturesTest
Group demo: paired t-test, Control vs Stimulated+12 PU (population)p < 0.05, CI above 0, dz within 30% of the sample valueStatsFeaturesTest
Batch LDF: latency / amplitude per file3–4.5 s / 20–35 PU± 0.4 s / ± 3 PUBatchFeaturesTest
Batch LFP: N1 latency / amplitude / sink channel12–18 ms / −100 to −140 µV / 3–5± 1.5 ms / ± 20% / exactBatchFeaturesTest
Batch imaging: peak ΔF/F / time / mean diameter0.5–1.5 / known / 10–14 px± 0.1 / ± 0.15 s / ± 0.75 pxBatchFeaturesTest
Batch features: latency / amplitude3–4.5 s / realised mean± 0.35 s / ± 1.5 PUBatchFeaturesTest
Batch MUA: same recording at 2× gainidentical spikesspike count ± 5%; 2–3 units; evoked rate > 3× baselineBatchFeaturesTest
CSD methods (core/demo/demoCSD.m): depth of the sinksink at contact 8 of 16 (4 of 8) at 15 ms; discs 500 µm widewithin one contact for Standard, iCSD delta / step / spline and kCSD; the inverse methods have a lower error than Standard; Standard is bit-identical to the previous CSDCSDFeaturesTest, CSDWalkthroughTest

Analytic checks

FunctionKnown answerTest
Peak latency, amplitude, onset delay (50%), FWHM, rise (10–90%), decay (to 50%), AUCclosed-form values of a Gaussian response on a raised baseline, also mirrored (negative); NaN on empty or flat windowsSignalFeaturesTest
ROI intensity, ΔF/F, movement, kymograph speed (three methods), vessel diametersmall synthetic stacks with exact answersImagingTest
Sub-pixel vessel diametersoft-walled synthetic profiles: error < 0.5 px, better than sample countingImagingFeaturesTest
Hampel filterflags exactly the injected spikesImagingFeaturesTest
Morlet waveletspeak at a 25 Hz sinusoid (± 1 Hz), correct phase, flat power for white noise (± 15%)LFPFeaturesTest
EEG time–frequency per condition (ERSP, ITPC, band power)the same ERSP and ITPC as TimeFrequency.ersp (LFP Analysis) on the continuous recording, where the whole wavelet lies inside the trial (± 0.01); an amplitude halved: −6.02 dB (± 0.05) and −75% band power (± 1%); the same phase in every trial: ITPC 1; no value where the wavelet does not fitEEGAnalysisTest
Welch spectrumpeak at 50 Hz; total power = variance (± 2%); white-noise floor 2σ²/fsLFPFeaturesTest
Spectrogramtracks a 10 → 30 Hz change (± 2 Hz)LFPFeaturesTest
Band power|analytic signal|² = A² (± 1%), nothing outside the bandLFPFeaturesTest
CSDV(z) = z² gives CSD = −2 everywhereLFPFeaturesTest
Epoch averagingedge epochs excluded, not zero-filledLFPFeaturesTest
Auto-mergemerges two copies of one unit (r > 0.95); keeps units that differ in size or shapeMUAFeaturesTest
Splitseparates two mixed units (> 97% correct); merge undoes the splitMUAFeaturesTest
PSTHrecovers a 10 → 100 spikes/s step (± 15%)MUAFeaturesTest
Correlogramsempty within the 2 ms dead time; cross-correlogram peak at a known 5.5 ms lagMUAFeaturesTest

Statistics

GroupStats is written in base MATLAB and checked on made-up numbers written for the tests (no published data set is used), whose expected results were computed independently with SciPy 1.17.1 (scipy.stats) on the same numbers:

File formats and sessions

Checked against other software during development

The readers and electrode positions added in versions 0.6.0 and 0.7.0, and the skull maps of 0.8.0, were compared during development with established Python packages, as recorded in the changelog. These comparisons were made while the features were built; the Python packages are not needed to use the toolbox. For the flat maps of skull layouts, the numbers from scipy are written into tests/ScalpMapTest.m, so every test run checks them again. In version 1.0.1 the EEG filters and the spherical-spline scalp maps were rewritten from the papers that describe them (Widmann, Schröger and Maess, 2015; Perrin et al., 1989, 1990); the tests check them against the rules and formulas of those papers.

WhatChecked againstVersion
Flat maps of skull layouts: thin-plate spline in the planescipy RBFInterpolator (thin_plate_spline, degree 1) (within 1e-9)0.8.0
Electrode position files: angles and positionsMNE-Python read_custom_montage (within 2e-6 degrees)0.7.0
EDF, EDF+ and BDF: values and annotationspyedflib and MNE-Python0.6.0
XDFpyxdf reads the files written here with the same values, time stamps and markers0.6.0
EEG-BIDSMNE-BIDS, both ways0.6.0
SpikeGLX, Blackrock, Neuralynx, Intan .rhs and Open Ephys legacy readerspython-neo, on files from each reader's synthetic writer0.6.0

The synthetic writers (core/io/write*.m) are used by the tests and the demo: the test suite reads their files back. Electrode position files are written by writeElectrodes in each format's own convention for tests/ElectrodesFileTest.m; electrode layouts are tested in tests/EEGLayoutTest.m.

Every window, driven step by step

AppSmokeTest opens every window and dialog. The walkthrough tests (DemoWalkthroughTest and the per-area walkthroughs) drive each window through its steps on the demo data through the same public methods the buttons call, save a screenshot after every step (the frames on this site), and fail if a step errors or, for several steps, if the result misses the simulated values.

Examples: simulated vs measured in the screenshots

WhereSimulatedShown in the window
Batch, LDF: peak latency per file3, 3.5, 4, 4.5 s3.06, 3.65, 3.90, 4.47 s
Batch, imaging: peak ΔF/F per file0.5, 1.0, 1.50.504, 1.006, 1.521
Batch, response features: peak latency (mean trace)3, 3.5, 4, 4.5 s3.1, 3.6, 4.1, 4.4 s
MUA: units on channel 4 after auto-merge2 units on channel 4, 1 on channel 53 units (356, 177, 62 spikes); merge r = 0.98
Motion correction: largest shift3 px3.0 px
Groups: Stimulated − Control12 PU (population)11.9 PU [95% CI 9.1, 14.7], p < 0.0001
Estimated rigid shifts (solid) against the true shifts of the advanced demo (dashed).DEMO DATA — synthetic, generated by core/demo/demoImagingAdvanced.m
Estimated rigid shifts (solid) against the true shifts of the advanced demo (dashed).
Robust vessel diameter (green) against the standard estimate (grey), which jumps when the blood cell crosses the line.DEMO DATA — synthetic, generated by core/demo/demoImagingAdvanced.m
Robust vessel diameter (green) against the standard estimate (grey), which jumps when the blood cell crosses the line.