Plots: adding plots to `twinx()` axis

I’m trying to construct a plot using the Plots package with a normal axis and a twinx() axis. Then I want to add plots to both axes, but it doesn’t seem to work:

using Plots
plot(sin,lc=:red, legend=:left)
fg = plot!(twinx(),sinc,lc=:blue,legend=:right)
plot!(fg, cos, lc=:red, ls=:dash)

gives:

Next, I want to add a plot to the twinx() axis, and I try with:

plot!(fg,twinx(),cosc,lc=:blue, ls=:dash)

but this gives an error message.

Question: Is there a way to add plots to the twinx() axis, too? [I’m trying to combine particle trajectory plots using Monte Carlo simulation…]

Assign this to a variable instead of making a new function call.
See this related thread and solution.

1 Like

Still not 100% intuitive… But I found a work-around:

using Plots
yaxis2 = twinx()
plot(sin,lc=:red, legend=:left)
fg = plot!(yaxis2,sinc,lc=:blue,legend=:right)
plot!(fg, cos, lc=:red, ls=:dash)

To add the second plot to yaxis2, the following does not work:

plot!(fg,yaxis2,cosc, lc=:blue, ls=:dash)

However, the following works:

plot(fg)
fg = plot!(yaxis2,cosc, lc=:blue, ls=:dash)

Thanks!

1 Like

Hm… upon further testing, there is something seriously weird with the above solution… or something that I just don’t understand. I’m trying to find a minimal example, but it seems like there is a memory problem/memory leak:

  • I have a lengthy Jupyter notebook with lots of (MTK) simulations, and try to plot the results. When I use the above procedure, some previous plots “leak” into the new plot.

I have to check more.

Check the following logic, I didn’t encounter any problems:

using Plots
yaxis1 = plot(sin, lc=:red, legend=:left, x_foreground_color_text=:black, y_foreground_color_text=:red)
yaxis2 = twinx()
plot!(yaxis2, sinc, lc=:blue, legend=:right, y_foreground_color_text=:blue)
plot!(yaxis2,  cos, lc=:blue, ls=:dash)
plot!(yaxis1, cosc, lc=:red,  ls=:dash)
1 Like

Note: my problem is not with my code above, but with using that strategy on a much more complex case.

OK… I think I understand the logic you present, and from that it follows that I had misunderstood what the twinx() function does.

So, if I understand it correctly, the twinx() creates a second axis of the previously displayed plot. And by setting yaxis2 = twinx(), you define a “plot handle” (in MATLAB terminology) to this second axis of that plot.

It was still somewhat convoluted to add xlabel and ylabel for the plots… Here is the plot I finally managed to create, after quite a bit of testing:

It is not relevant here to go into too much details, but here is more or less what I had to do… [note: I also created another plot in parallel with the one included above]:

# Preparing for the figure included above ("Voltages") ...
fg_1 = plot(sol,idxs=u, xlabel="",ylabel=L"$u$ [V]", title="Voltages",
                label=L"\leftarrow u", legend=:left)
fg_2 = twinx()
plot!(fg_2, sol,idxs=u_p, ylabel=L"$u_\mathrm{p}$ [V]",
        label=L"u_\mathrm{p} \rightarrow", legend=:right)

# Aother figure...

fg_a = plot(sol, idxs=p,...)

# Monte Carlo simulation
Np = 20

for i in 1:Np
    _u = 0.2*randn()
    _k = 1 + 0.2*randn()
    prob = remake(prob; u0=[u => _u], p=[k => _k])
    sol = solve(prob)

    plot!(fg_1 , sol, idxs=u, label="", xlabel="")
    plot!(fg_2 , sol, idxs=u_p, label="", xlabel="")

    plot!(fg_a,sol, idxs=p, ...)
end

plot!(fg_2, xlabel=L"$t$ [s]")
plot!(fg_1, frame=:box)

Note: if I replace the last two statements by plot!(fg_1, xlabel=L"$t$ [s]", frame=:box), this produces two labels on the abscissa (“x axis”). I had to add ylabel’s prior to the for loop in order to get them correctly placed. Etc., etc.

So: somewhat convoluted.