How can I move an axis in a 3d plot, so that it is shown "outside" of the grid?

Hi all,
I’m making a plot using Plots.jl with the default GR backend.

When I run this code

    # density_matrix contains the data I want to plot
    p = plot(density_matrix, st = :surface, xlabel="Binary weight", ylabel="Power",
        zlabel="Density",
        zlims=(0,200),
        c=cgrad(:heat, scale = :exp),

    ) # create surface
    gui()

I obtain this nice plot:
dispersion-usual
However, if I change the camera, like here:

    p = plot(density_matrix, st = :surface, xlabel="Binary weight", ylabel="Power",
        zlabel="Density",
        zlims=(0,200),
        c=cgrad(:heat, scale = :exp),
        camera = (-45,50) # NOTE HERE
    ) # create surface
    gui()

I get:
dispersion-tilted
Now, I want this angle for the camera, but as you see the axis are all misplaced. How can I move them?

Thanks!

I may have found a trick I think you can try to overcome the current limitation of Plots.jl gr() for negative camera azimuths, which hides the axes behind the surface.

using Plots; gr(dpi=600)

f(x,y) = x.^3 .* y'

x = range(0,3,100)
y = range(0,40,200)
θ = 60                  # camera azimuth [deg]

# Positive camera azimuth, axes OK:
Plots.surface(x, y, f, zlim=(0,30), clim=(0,30), camera=(θ,50), framestyle=:box)

# Axes hidden for negative camera azimuth:
Plots.surface(x, y, f, zlim=(0,30), clim=(0,30), camera=(-θ,50), framestyle=:box)

# Trick to get the axes to the front:
g(y,x) = f(x,y)
Plots.surface(y, x, g, xflip=true, zlim=(0,30), clim=(0,30), camera=(90 - θ,50), framestyle=:box, title="equivalent of camera=(-$θ, 50)")

2 Likes

Thanks, it kinda works but correct me if I’m wrong: I also need to switch xlabel and ylabel, right?

Of course you do.

1 Like

Then it works, thanks! :tada: Seems like quite a bug of the GR backend tho. Where should I report it?

1 Like

You can create a new issue here:

2 Likes

Thanks, I will, also because with this workaround I perform KDE on the other dimension ("Power" instead of "Binary weight"), which is something I wanted to preserve
Edit: nevermind, I realised this happened also with the “usual” plot, so I probably misinterpreted the plot or performed the KDE wrongly, anyway it shouldn’t be an issue of Plots.jl

Perhaps I am missing something, but if we have as input a density_matrix (instead of a function as in my example), then we only need to plot the transpose with the xflip and 90-θ azimuth.

Try for example:

Plots.surface(transpose(density_matrix), xflip=true, zlim=(0,30), clim=(0,30), camera=(90 - θ,50), framestyle=:box, title="equivalent of camera=(-$θ, 50)")

It’s what I did:

    transposed_matrix = transpose(density_matrix)
    p = plot(transposed_matrix, st = :surface, title=plot_title,
        ylabel="Binary weight", xlabel="Power", # inverted as well
        zlabel="Density",
        xflip=true,
        dpi=500,
        # zlims=(0,200),
        c=cgrad(:heat, scale = :exp),
        camera = (45,50)
    ) # create surface

plus I switched the labels.

This is better than the hack I just came up with in 99% of situations, but if anyone is picky like me about not wanting to edit the data (and potentially mess it up) before plotting it, you can try this function I made.

BE FOREWARNED: IT TRULY IS AN UGLY, DIRTY HACK AND @rafael.guerra’s SOLUTION IS LIKELY THE LESSER OF TWO EVILS.