Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib 3: 3D scatter plots with tight_layout

I have some code which produces a 3D scatter plot using matplotlib's scatter in conjunction with tight_layout, see the simplified code below:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import proj3d 

fig = plt.figure()
ax = fig.gca(projection='3d')

N = 100
x = np.random.random(N)
y = np.random.random(N)
z = np.random.random(N)

ax.scatter(x, y, z)
plt.tight_layout()  # <-- Without this, everything is fine
plt.savefig('scatter.png')

In matplotlib 2.2.3 this makes a figure like so: enter image description here

Similar output is generated by older versions, at least back to 1.5.1. When using the new version 3.0.0, something goes wrong at plt.tight_layout() and I get the following output: enter image description here

Accompanying this is the warning

.../matplotlib/tight_layout.py:177: UserWarning: The left and right margins cannot be made large enough to accommodate all axes decorations

One may argue that using tight_layout with no arguments as here does not (on older matplotlibs) consistently lead to the expected tightened margins anyway, and so one should refrain from using tight_layout with 3D plots in the first place. However, by manually tweaking the arguments to tight_layout it is (used to be) a decent way to trim the margins even on 3D plots.

My guess is that this is a bug in matplotlib, but maybe they've made some deliberate change I havn't picked up on. Any pointers about a fix is appreciated.

like image 822
jmd_dk Avatar asked Nov 17 '22 01:11

jmd_dk


1 Answers

Thanks to the comment by ImportanceOfBeingErnest, it now works:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import proj3d 

fig = plt.figure()
ax = fig.gca(projection='3d')

N = 100
x = np.random.random(N)
y = np.random.random(N)
z = np.random.random(N)

ax.scatter(x, y, z)

# The fix
for spine in ax.spines.values():
    spine.set_visible(False)

plt.tight_layout()

plt.savefig('scatter.png')

From the links in the comment, it seems that this will be fixed in matplotlib 3.0.x. For now, the above may be used.

like image 80
jmd_dk Avatar answered Dec 10 '22 14:12

jmd_dk