views:

104

answers:

1

Hi

I've been looking high and low for a solution to this simple problem but I can't find it anywhere! There are a loads of posts detailing semilog / loglog plotting of data in 2D e.g. plt.setxscale('log') however I'm interested in using log scales on a 3d plot(mplot3d).

I don't have the exact code to hand and so can't post it here, however the simple example below should be enough to explain the situation. I'm currently using Matplotlib 0.99.1 but should shortly be updating to 1.0.0 - I know I'll have to update my code for the mplot3d implementation.

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FixedLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = Axes3D(fig)
X = np.arange(-5, 5, 0.025)
Y = np.arange(-5, 5, 0.025)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet, extend3d=True)
ax.set_zlim3d(-1.01, 1.01)

ax.w_zaxis.set_major_locator(LinearLocator(10))
ax.w_zaxis.set_major_formatter(FormatStrFormatter('%.03f'))

fig.colorbar(surf)

plt.show()

The above code will plot fine in 3D, however the three scales (X, Y, Z) are all linear. My 'Y' data spans several orders of magnitude (like 9!), so it would be very useful to plot it on a log scale. I can work around this by taking the log of the 'Y', recreating the numpy array and plotting the log(Y) on a linear scale, but in true python style I'm looking for smarter solution which will plot the data on a log scale.

Is it possible to produce a 3D surface plot of my XYZ data using log scales, ideally I'd like X & Z on linear scales and Y on a log scale?

Any help would be greatly appreciated. Please forgive any obvious mistakes in the above example, as mentioned I don't have my exact code to have and so have altered a matplotlib gallery example from my memory.

Thanks

+1  A: 

Use the set_scale() method on the appropriate axis. For instance, to set the y-axis to log scale use:

ax.w_yaxis.set_scale("log")
Justin Peel
Actually, that doesn't work quite correctly for 3D plots... It appears to work, but it's still displaying things on a linear scale. It just changes the tick locator, it doesn't actually change the way the data is plotted, unlike the way it works for a 2D plot... (This might be a bug, I'm not quite sure yet... I was playing around with it yesterday...)
Joe Kington
@Joe You're quite right. In the `set_xscale` method used in 2D, it calls `set_scale` and then 2 other methods. The problem, as far as I can tell, is that the method `_update_transScale` (one of the two) isn't defined for the 3D plots (it is using the 2D one currently). Personally, it seems to me like the 3D plots are a mess because they try to just extend the 2D plot objects rather than starting anew.
Justin Peel