Plotting and Topography#

Scalp maps, curve summaries, figure-layout helpers, logarithmic image displays, event rasters, artifact review plots, and replayable scalp movies. Movie frames are returned as uint8 RGB arrays so they can be inspected in notebooks, tested headlessly, encoded by downstream tools, or replayed with seemovie. The movieframes argument follows EEGLAB’s 1-based public indexing convention.

savefig writes a Matplotlib figure to a MATLAB .fig file that openfig can open. The file stores the figure, its axes, and the lines, images, and text on those axes, including data, limits, colors, scales, and labels. Figure text, such as a suptitle, is stored on the first axes. figure.savefig("name.fig") uses the same writer. Scatter plots, bars, patches, and legends are omitted. The figure colormap is the first image’s colormap. Characters outside ASCII are stored as ASCII, and mathtext tick labels are stored as the plain tick value, so MATLAB can read the file.

eegprep.savefig(figure, filename)

Save figure as a MATLAB .fig file.

eegprep.hist2(data1, data2[, bins, ax])

Plot two semi-transparent histograms on one Matplotlib axes.

eegprep.axcopy(figure, redraws)

Enlarge the left-clicked axes into a pop-up window, like EEGLAB axcopy.

eegprep.cbar([arg, colors, minmax, grad, ...])

Display a full or partial color bar, following EEGLAB cbar.

eegprep.copyaxis([command, source])

Copy the current axes into an enlarged standalone figure.

eegprep.eegplot2event(eegplotrej[, ...])

Convert continuous eegplot marks to EEGPrep eeg_eegrej rows.

eegprep.eegplot2trial(eegplotrej, pnts, sweeps)

Convert eegplot marks to EEGLAB trial and electrode rejection arrays.

eegprep.envtopo(data, weights, *[, ...])

Rank component contributions to a data epoch and plot their envelopes/maps.

eegprep.erpimage(data[, sortvar, times, ...])

Image single trials sorted and smoothed across trials, as EEGLAB erpimage.

eegprep.forcelocs(chanlocs, *locations)

Rotate an electrode montage to force named channels to X/Y positions.

eegprep.headplot(values[, arg1])

Plot values on a spline-interpolated 3-D head mesh.

eegprep.plotcurve(times, data, *args[, target])

Plot curves and highlight samples outside significance limits.

eegprep.plottopo(data, *[, times, chanlocs, ...])

Plot channel/component traces in an EEGLAB-like array.

eegprep.sbplot(rows, columns, grid_position, ...)

Create an axes in one tile or across two corner tiles.

eegprep.slider(handler, horiz[, vert, ...])

Add horizontal and/or vertical viewport controls to a figure.

eegprep.spectopo(data, frames, srate, *[, ...])

Compute and optionally plot channel/component log power spectra.

eegprep.timtopo(data, chanlocs, *[, times, ...])

Plot all channel traces and scalp maps at selected latencies.

eegprep.gradmap(maps, locations[, draw])

Compute x/y gradients of one or more scalp maps at electrode sites.

eegprep.gradplot(maps, locations[, draw])

Compute scalp-map gradients and optionally draw their vector fields.

eegprep.imagesclogy(times, freqs, data[, ...])

Plot frequency-by-time values on a logarithmic y-axis.

eegprep.imagescloglog(times, freqs, data[, ...])

Plot frequency-by-time values on logarithmic x- and y-axes.

eegprep.show_events(EEG, *args[, ...])

Return an RGB raster showing epoch-relative event latencies.

eegprep.setfont(handle, *args[, handletype])

Apply font properties to text in a Matplotlib figure or axes.

eegprep.eegmovie(data[, srate, elec_locs, ...])

Render channel-by-frame data as a sequence of RGB scalp-map images.

eegprep.headmovie(data, elec_loc[, ...])

Render a 3-D scalp movie using EEGPrep's maintained eegmovie path.

eegprep.seemovie(movie[, ntimes, colormap, ...])

Return an animation for an EEGPrep movie.

eegprep.topoplot(datavector, chan_locs, **kwargs)

Plot a 2D topographic map of EEG data.

eegprep.loc_subsets(chanlocs, subset_sizes)

Separate channels into maximally spaced subsets.

eegprep.vis_artifacts(clean_eeg[, ...])

Compare a cleaned dataset against its original clean_rawdata source.

eegprep.vis_artifacts_diagnostics(clean_eeg)

Return clean_rawdata sample/channel rejection diagnostics.

Low-level EEGLAB plotting workflows#

The low-level helpers retain EEGLAB’s familiar names while returning ordinary Matplotlib objects. cbar draws full or one-based partial colormap ranges; copyaxis copies the current plot into a standalone figure; and sbplot creates axes that may span opposite corners of a one-based subplot grid. slider returns its widget handles so scripts can pan or remove a magnified viewport without relying on hidden callback strings.

plotcurve accepts data with curves in rows or columns, plots individual and mean traces, and supports confidence-limit highlighting. A two-value maskarray=[low, high] marks samples whose comparison values fall outside that interval. highlightmode="background" shades the curve axes, while highlightmode="bottom" puts the significance runs in a narrow lower axes.

forcelocs rotates X/Z or Y/Z channel coordinates and refreshes the spherical and topographic fields after every rotation. headplot renders reusable 3-D spline maps; headplot("example") and headplot("cartesian") return and print the corresponding electrode-file examples for interactive use.

ERP images#

erpimage images single trials of one channel or component, sorted and smoothed across trials, with the ERP and, optionally, wavelet amplitude and inter-trial coherence traces underneath. It takes EEGLAB’s arguments in EEGLAB’s order, erpimage(data, sortvar, times, title, avewidth, decimate), where data is (frames, trials) (for example EEG["data"][ch]), sortvar holds one value per trial and times holds latencies in ms. Options follow either as EEGLAB tokens or as keywords; these two calls are equivalent:

from eegprep import erpimage

result = erpimage(data, rt, times, "Pz", 10, 1, "erp", "cbar", "phasesort", [300, 25, 10])
result = erpimage(data, rt, times, "Pz", 10, 1, erp=True, cbar=True, phasesort=[300, 25, 10])

The result unpacks like EEGLAB’s fifteen outputs, followed by the figure: outdata, outvar, outtrials, limits, axhndls, erp, amps, cohers, cohsig, ampsig, outamps, phsangls, phsamp, sortidx, erpsig, figure = result, and the same values are available as attributes (result.outdata). outdata is (frames, smoothed_trials); outputs that were not computed are None. Pass target= a Matplotlib Figure or SubFigure to draw into it, NoShow=True to compute without drawing (not combined with target), and rng= a seed or NumPy random generator to make the coherence bootstrap and the erpalpha permutations reproducible (numpy.random.RandomState(seed) gives the same bootstrap draws as MATLAB’s rng(seed, 'twister')).

The numbers come from eegprep.functions.sigprocfunc.erpimage_engine, a single module that needs only NumPy and the Python standard library (ast, dataclasses, logging, typing). Across 46 recorded scenarios (sorting, smoothing and decimation, phase and amplitude sorting with trial rejection, coherence and its significance, amplitude images, time warping, percentile ERPs and axis limits), every output matches EEGLAB’s erpimage run on MATLAB R2025b to within 1e-12 of the output’s largest magnitude (of the input data’s largest magnitude for outputs in data units, such as the image and the ERP).

Differences from EEGLAB#

Where EEGLAB’s behavior contradicts its own help text, EEGPrep follows the help:

  • sortidx holds 0-based indices into the input trials. EEGLAB returns 1-based indices into the trials left after removing NaN sortvar values.

  • 'noplot' hides only the sortvar trace. In EEGLAB it suppresses the whole figure.

  • 'erpalpha' draws unbiased random signs for its permutation test. EEGLAB draws sign(randn - 0.5), which is +1 only about 31% of the time (mean sign -0.38), so its thresholds are inflated (sccn/eeglab#976). EEGPrep’s erpalpha bands therefore differ slightly from MATLAB’s; the rest of the computation is unchanged.

  • 'signif' with 'coher' uses the given thresholds. On MATLAB R2025b this combination stops with an error (a vector operand to ||).

  • Per-trial 'timewarp' events and per-trial 'vert' latencies stay with their trials through sorting and trial rejection; EEGLAB applies them by position after sorting.

Other behavior to know when moving from EEGLAB:

  • Invalid inputs raise ValueError where EEGLAB prints a message and returns, or carries on with a wrong result: option values of the wrong size or type (EEGLAB often uses the first element), data whose trial count does not match sortvar, data containing infinite values, limits or baseline windows without samples, renorm 'yes' on a constant sortvar, amplitude rejection that leaves fewer than two trials, 'timewarp' events outside the epoch or with the wrong number of rows, 'plotamps' or 'coher' with zero wavelet amplitude (no dB value), a 'topo' channel outside the channel locations, and a 'spec' band above the Nyquist frequency. 'allcohers', which erpimage.m marks UNIMPLEMENTED, raises. target must be a Figure or SubFigure (TypeError).

  • The notes EEGLAB prints and then continues past go to the eegprep.functions.sigprocfunc.erpimage_engine logger: replaced NaN data, removed NaN-sortvar trials, clamped avewidth and decimate, trials kept after amplitude rejection, alignment shifts larger than the epoch, clipped limits, sorting bands reduced to the Nyquist frequency, a single ERP drawn because 'erpalpha' was given with 'erp' above 1, and options that have no effect in the chosen sorting mode.

  • A negative decimate must lie between minus the trial count and the trial count; EEGLAB allocates as many output rows as asked.

  • Boxcar avewidth must be a whole number of trials, as on MATLAB R2025b, which rejects non-integer window sizes.

  • A three-sample times vector is a time vector, not EEGLAB’s compact [start_ms, frames, srate] form, when the data also have three frames.

  • 'timewarp' cannot be combined with 'phasesort', 'ampsort' or 'plotamps'; EEGLAB applies the warp marks inconsistently there.