Shared x axis for all subplots

Consider this plot from the EEG.jl package:

image

All signals share the x-axis, and the y-axis is also shared with the name of each signal. How can this be achieved? Using plots(x, my_list_of_signals, layout=(rows, 1)) does separate signals into subplotts, but each subplot has an axis of its own.

What’s the EEG package? The link to JuliaHub doesn’t find the package (not your fault, this is auto-generated by Discourse) and Google doesn’t seem to help.

Anyway your plot looks like a Plots plot, and also looks like it’s just a single plot with five lines in? I don’t know EEGs at all but to me it looks like every series has just been normalized and then plotted with an offset, so something like:

p = plot(ylabel = "Amplitude (uV)", xlabel = "Time (s)", yticks = (1:5, ["F5", "O1", "F6", "TP8", "O2"]));

for (i, s) in enumerate(series)
    plot!(1:length(s), i .+ (s .- mean(s)) ./ 1.5 * std(s), label = "")
end

current()

produces:

image

Where the 1.5 factor in the normalization effectively scales the vertical distance between the lines.

Now this feels somewhat hacky and to me it seems a bit weird to have an axis with a label that suggests some sort of numerical scale(uV) but then also have “categorical” labels, but maybe this is a standard plot in the field of EEG analysis?

1 Like

Very helpful! Thank you. And yes, that is standard for EEG. I am having trouble setting the y-labels with more channels. Using your code works but the labels are all together:

You might have forgotten the standardization of the data series in nilshg’s code:

I had tweaked it to solve an issue and created another. Your original answer was essentially correct. The only improvement, for future readers of this entry, is that it seems to be useful to add the number of signals being plotted as a factor in the scaling.

Final code (I’m using EEGToolkit.jl):

signals = [ eeg.signals[i].x for i in keys(eeg.signals)]
signals = signals[1:5] # Only first five
signals = [signal[1000:2000] for signal in signals]
p = plot(ylabel = "Amplitude (uV)", xlabel = "Time (s)", yticks = (1:5, cnames[1:5]));

for (i, s) in enumerate(signals)
    plot!(1:length(s), i .+ (s .- mean(s)) ./ (1.5 * length(signals) * std(s)), label = "")
end

plot(p)

If all signals are plotted,

Thank you very much, @Dan

1 Like