In order to create a 3d plot using plot_surface
and wireframe
I wrote this (looking here around)
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import rc
from matplotlib.ticker import MultipleLocator
import matplotlib.ticker as mticker
import numpy as np
from matplotlib.ticker import FormatStrFormatter
def log_tick_formatter(val, pos=None):
return f"10$^{{{int(val)}}}$"
data=np.genfromtxt('jpdfomegal2_90.dat')
x_len= len(np.unique(data[:, 0]))
y_len= len(np.unique(data[:, 1]))
X = data[:, 0].reshape(x_len, y_len)
Y = data[:, 1].reshape(x_len, y_len)
Z = data[:, 2].reshape(x_len, y_len)
#identify lowest non-negative Z value Zmin>0
Zmin = np.where(Z > 0, Z, np.inf).min()
Zmax = Z.max()
#and substitute zero with a slightly lower value than Zmin
Z[Z==0] = 0.9 * Zmin
#log transformation because the conversion in 3D
#does not work well in matplotlib
Zlog = np.log10(Z)
rc('font',family='palatino')
rc('font',size=18)
fig = plt.figure(figsize=(12,8))
#ax = fig.add_subplot(projection='3d')
ax = Axes3D(fig)
ax.set_xlim3d(0,15)
ax.set_zlim3d(np.floor(np.log10(Zmin))-1, np.ceil(np.log10(10)))
ax.zaxis.set_major_formatter(mticker.FuncFormatter(log_tick_formatter))
ax.zaxis.set_major_locator(mticker.MaxNLocator(integer=True))
rc('font',family='palatino')
rc('font',size=18)
tmp_planes = ax.zaxis._PLANES
ax.zaxis._PLANES = ( tmp_planes[2], tmp_planes[3],
tmp_planes[0], tmp_planes[1],
tmp_planes[4], tmp_planes[5])
ax.set_xlabel('$\omega^2 /<\omega^2>$')
ax.xaxis.labelpad = 10
ax.yaxis.labelpad = 10
ax.set_ylabel('cos$(\omega,\lambda^2)$')
ax.zaxis.set_rotate_label(False) # disable automatic rotation
ax.zaxis.labelpad = 10
ax.set_zlabel('')
ax.view_init(elev=17, azim=-60)
ax.grid(False)
ax.xaxis.pane.set_edgecolor('black')
ax.yaxis.pane.set_edgecolor('black')
ax.zaxis.pane.set_edgecolor('black')
ax.xaxis.pane.fill = False
ax.yaxis.pane.fill = False
ax.zaxis.pane.fill = False
ax.xaxis.set_major_locator(MultipleLocator(2))
ax.yaxis.set_major_locator(MultipleLocator(0.2))
ax.zaxis.set_major_locator(MultipleLocator(1))
#not sure this axis scaling routine is really necessary
scale_x = 1
scale_y = 1
scale_z = 0.8
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([scale_x, scale_y, scale_z, 1]))
ax.contour(X, Y, np.log10(Z), 4, lw=0.1, colors="k", linestyles="--", offset=np.floor(np.log10(Zmin))-1)#-7)
surf = ax.plot_surface(X, Y, np.log10(Z), cmap="binary", lw=0.1,alpha=0.5)
ax.plot_wireframe(X, Y, np.log10(Z),linewidth=1,color='k')
ax.contour(X, Y, np.log10(Z), 4, lw=0.1, colors="k", linestyles="solid")
fig.colorbar(surf, shrink=0.5, aspect=20)
plt.tight_layout()
plt.savefig('jpdf_lambda2_90.png', bbox_inches='tight')
plt.show()
the problem is related to the "minorticks" along zaxis .. I obtain this :
but I would have this format and ticks in the axis
Does somebody clarify how to obtain it and as well I did not find a way to use the log scale in pyplot 3d
CodePudding user response: