I'm doing some 3d scatter plots with jupyter notebooks in VSCode, and they aren't showing properly.
I went to the documentation in matlab and downloaded the jupyter notebook for the 3d scatter plot and tried running that in vscode, getting the same results, the z label gets cut off.
I've seen a lot of questions about making the plot interactive with matplotlib magic, and some of those solutions (%matplotlib qt
) do work (the image isn't cropped anymore, but gets created in a separate window. I want the plot to be inline, because I'm doing a lot of them and having one 40 windows created every time is a mess.
I've tried the magic %matplotlib widget
and %matplotlib notebook
, as suggested here, and the %matplotlib ipympl
as suggested here but when I use those the plot stops showing, appearing only after I change to %matplotlib inline
and showing any plot I've done before at that point (all cropped).
I've also checked the code in jupyter lab and it does not have this problem, the image shows completely fine, so it seems to be a problem with Jupyter notebooks in VsCode.
I'm not trying to change the position of the z axis, It's fine where it is, I just want to make the image bigger so the z label is shown properly.
Just in case, I've tried the comment of Trenton McKinney of doing ax.zaxis._axinfo['juggled'] = (1, 2, 2)
to change the z-label to the other side, and it still gets cut, just in the other side of the image.
So it's not an issue of where the z axes and label are.
PS: As requested, I put the from the example here for ease of use.
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
def randrange(n, vmin, vmax):
"""
Helper function to make an array of random numbers having shape (n, )
with each number distributed Uniform(vmin, vmax).
"""
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
n = 100
# For each set of style and range settings, plot n random points in the box
# defined by x in [23, 32], y in [0, 100], z in [zlow, zhigh].
for m, zlow, zhigh in [('o', -50, -25), ('^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zlow, zhigh)
ax.scatter(xs, ys, zs, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
Update: I've posted an issue in the github VSCode repo, link here
Update on the update: The issue has been found to be a matplotlib/jupyter problem, so I've opened a new issue in the matplotlib repo, link here
So, after a pair of issues in github, I've finally found an answer. I'll leave here the answer in github for reference
It appears the problem is caused by the default inline backend saving the figure with bbox_inches= 'tight'
which causes the code to crop the image. this can be solved using the inline magic
%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
which overthrows the default and gives you a nice, big image with plenty of room for labels and everything else. In case this doesn't work (the image created is rather big) I leave here the link to the docs.
Another option is to add padding, which can be done with the magic
%config InlineBackend.print_figure_kwargs = {'pad_inches': .3}
This option might need some trial and error to get the size right. In my case 0.3 worked as a charm.