Description
Bug summary
Whenever creating a 3D plot with vertical_axis = 'y'
option the set_box_aspect()
method scales the axes incorrectly. The 3-tuple is expected to behave as x:y:z
, instead it behaves like z:x:y
Code for reproduction
"""
Created on Mon Oct 31 18:30:31 2022
@author: Michel Gordillo
"""
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure(num=4, clear=True)
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax.view_init(vertical_axis='y')
(theta, phi) = np.meshgrid(np.linspace(0, 2 * np.pi, 41),
np.linspace(0, 2 * np.pi, 41))
x = (3 + np.cos(phi)) * np.cos(theta)
z = (3 + np.cos(phi)) * np.sin(theta)
y = np.sin(phi)
k = 4
xlim = [-k, k] #2k
ylim = [-k/2, k/2] #k
zlim = [-k, k] #2k
box_aspect = (4,2,4) #(x,y,z)
def fun(t, f): return (np.cos(f + 2 * t) + 1) / 2
dplot = ax.plot_surface(x, y, z, facecolors=cm.jet(fun(theta, phi)))
ax.set(xlabel='x',
ylabel='y',
zlabel='z',
xlim = xlim,
ylim = ylim,
zlim = zlim,
# xticks = [-4, -2, 2, 4],
# yticks = [-4, -2, 2, 4],
# zticks = [-1, 0, 1],
title='Donut!')
ax.set_box_aspect(aspect = box_aspect)
fig.tight_layout()
Actual outcome
The box_aspect tuple:
box_aspect = (4,2,4)
#(x,y,z)
Actually the axis scaled as
box_aspect = (4,2,4)
-> #(z,x,y)
Like if shifting y to the right.
Expected outcome
To produce this result i just applied the same logic in reverse:
box_aspect = (4,4,2)
#(z,x,y) <- Expecting the outcome to be applied like this
And it actually does.
Additional information
This only happens as explained in the title when both vertical = y
option is enabled and we try to manually scale_box_aspect(). The problem is probably from how was vertical axis selection actually implemented.
From the documentation:
set_box_aspect(aspect, *, zoom=1)
[...]
aspect3-tuple of floats or None
Changes the physical dimensions of the Axes3D, such that the ratio of the axis lengths in display units is x:y:z.
This behaviour is not respected when vertical_axis = 'y'
in enabled. The behaviour appears to be: z:x:y
instead.
To actually fix this I just created a tuple with the new definition in mind, this could just be patched by shifting the tuple to make the vertical axis be the last element of the tuple
(x,y,z) -> input tuple
vertical axis == 'z' -> (x,y,z) no problem
vertical axis == 'y' -> (z,x,y) rotate right the tuple
vertical axis == 'x' -> (y,z,x) rotate right twice the tuple
Operating system
Windows
Matplotlib Version
'3.6.1'
Matplotlib Backend
Qt5Agg
Python version
Python 3.8.5
Jupyter version
Spyder 4.1.5
Installation
conda