Plots.jl icon indicating copy to clipboard operation
Plots.jl copied to clipboard

Feature request: plot axes and ticks on all four sides

Open mihrits opened this issue 5 years ago • 14 comments

I would like to be able to make a plot that has (duplicated) ticks on all four sides.

Simple matplotlib example (although matplotlib in python already has axes on all four sides as default) from python3:

import matplotlib.pyplot as plt

plt.bar(range(10),range(10))
plt.tick_params(top=True, right=True)
plt.show()

It's a requisite for plots, when submitting an article to a scientific journal in my field.

mihrits avatar Oct 11 '19 12:10 mihrits

That should be plot(1:10, 1:10, framestyle = :box).

BeastyBlacksmith avatar Apr 23 '20 20:04 BeastyBlacksmith

With Julia v1.4.1 and Plots v1.0.12 plot(1:10, 1:10, framestyle = :box) still doesn't work for me. It does have borders on all four sides, but not the ticks.

mihrits avatar Apr 23 '20 23:04 mihrits

which backend?

BeastyBlacksmith avatar Apr 24 '20 08:04 BeastyBlacksmith

GR

mihrits avatar Apr 24 '20 10:04 mihrits

I see, looking at the documentation, the only backend that gives you the ticks at the moment is pgfplotsx.

BeastyBlacksmith avatar Apr 24 '20 12:04 BeastyBlacksmith

Try using twinx perhaps that is what you are looking for

isentropic avatar Jun 18 '20 05:06 isentropic

I'm sorry, I don't know how to use that. I couldn't find it in the docs either.

mihrits avatar Jun 26 '20 10:06 mihrits

It seems GRUtils has the ticks on all four sides by default.

Haoran-Feng avatar May 23 '21 14:05 Haoran-Feng

I think pyplot does this with box frame style

isentropic avatar May 24 '21 06:05 isentropic

GRUtils solution seems good to me. Thanks!

mihrits avatar May 31 '21 08:05 mihrits

Keeping open until its fixed

BeastyBlacksmith avatar May 31 '21 11:05 BeastyBlacksmith

Not a proper fix, but here is a workaround I found. I just create a twin axis in each direction, match the x and y boundaries and remove labels using a copy_ticks function.

function twiny(sp::Plots.Subplot)
    sp[:top_margin] = max(sp[:top_margin], 30Plots.px)
    plot!(sp.plt, inset = (sp[:subplot_index], bbox(0,0,1,1)))
    twinsp = sp.plt.subplots[end]
    twinsp[:xaxis][:mirror] = true
    twinsp[:background_color_inside] = RGBA{Float64}(0,0,0,0)
    Plots.link_axes!(sp[:yaxis], twinsp[:yaxis])
    twinsp
end
twiny(plt::Plots.Plot = current()) = twiny(plt[1])

function copy_ticks(sp::Plots.Subplot)
    ptx = twinx(sp)
    plot!(ptx,xlims=xlims(plt),ylims=ylims(plt),xformatter=_->"",yformatter=_->"")
    pty = twiny(sp)
    plot!(pty,xlims=xlims(plt),ylims=ylims(plt),xformatter=_->"",yformatter=_->"")
end
copy_ticks(plt::Plots.Plot = current()) = copy_ticks(plt[1])

plt = plot(sin)
copy_ticks()
display(plt)
savefig("sine.png")

This was built with code from two sources:

  • code for twiny (https://stackoverflow.com/questions/64176617/julia-two-x-axes-for-plot-of-same-data)
  • code to remove labels on twin axes (https://discourse.julialang.org/t/avoid-repeating-tick-labels-with-subplots-in-plots-jl/351)

sine

orlox avatar May 01 '22 17:05 orlox

I also come to a case that needs a second x axis, so a corresponding twiny in the Plots could be convinent, and should also be documented too.

function twiny(sp::Plots.Subplot)
    plot!(
        sp.plt,
        inset = (sp[:subplot_index], bbox(0, 0, 1, 1)),
        right_margin = sp[:right_margin],
        left_margin = sp[:left_margin],
        top_margin = sp[:top_margin],
        bottom_margin = sp[:bottom_margin],
    )
    twinsp = sp.plt.subplots[end]
    twinsp[:xaxis][:grid] = false
    twinsp[:yaxis][:grid] = false
    twinsp[:yaxis][:showaxis] = false
    twinsp[:xaxis][:mirror] = true
    twinsp[:background_color_inside] = RGBA{Float64}(0, 0, 0, 0)
    Plots.link_axes!(sp[:yaxis], twinsp[:yaxis])
    twinsp
end

babaq avatar Sep 16 '22 20:09 babaq

xref: #2579 https://github.com/JuliaPlots/Plots.jl/pull/3532

BeastyBlacksmith avatar Sep 16 '22 20:09 BeastyBlacksmith