Edit axes appearance on surface plot - python

My code plots a surface plot for the below data. I want to change the appearance of X and Y axis. Right now it displays only 10 and 100. How can I edit it so that it displays values between them as well? I haven't understood the use of tickformatter in the code, I had received the suggestion from one of the member on the forum for my previous question.
(Please note: Image for reresentation purposes, the below data gives similar image but with different values)
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter, FuncFormatter
from mpl_toolkits.mplot3d import axes3d
import numpy as np
def format_log(x, pos=None):
x1 = 10**x
s = "%.3f" % x1
return s[:-4] if s[-3:]=="000" else " "
fig = plt.figure()
ax = fig.gca(projection='3d')
X=[2,3,5,8,20,30,50,80,100,150,175,200,250,300]
Y=[2,3,4,5,10,15,20,30,40,50,80,100,125,150,175,200]
X = np.log10(np.array(X))
Y = np.log10(np.array(Y))
Y,X=np.meshgrid(Y,X)
Z=np.array([
[0.2885307,0.269452,0.259193,0.2548041,0.2731868,0.4801551,0.7992361,1.7577641,3.2611327,5.428839,19.647976,37.59729,78.0871,152.21466,268.14572,0],
[0.2677955,0.2538363,0.2380033,0.2306999,0.4779794,0.9251045,1.5448972,3.508644,6.4968576,11.252151,0,0,0,0,0,0],
[0.2432982,0.2283371,0.2514196,0.3392502,0,0,0,0,0,0,0,0,0,0,0,0],
[0.2342575,0.3158406,0.4770729, 0.6795485,2.353042, 5.260077,9.78172,25.87004,59.52568, 0,0,0,0,0,0,0],
[0.6735384, 1.3873291,2.346506, 3.5654,0,0,0,0,0,0,0,0,0,0,0,0],
[1.3584715, 2.9405127,5.096819,8.155857,0,0,0,0,0,0,0,0,0,0,0,0],
[3.558062,8.216592,15.768077,27.386694,0,0,0,0,0,0,0,0,0,0,0,0],
[9.537899,25.202589,58.20041,0,0,0,0,0,0,0,0,0,0,0,0,0],
[16.083374,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[54.936775,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[89.185974,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]])
my_col = cm.jet(Z/np.amax(Z))
surf = ax.plot_surface(X, Y, Z,cmap=cm.coolwarm)
ax.set_zlim(0, 300)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
ax.xaxis.set_major_formatter(FuncFormatter(format_log))
ax.yaxis.set_major_formatter(FuncFormatter(format_log))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

If you are fine with specifying all ticks manually, you can just add something like
ax.set_xticks([np.log10(x) for x in [10, 20, 60, 100]])
ax.set_yticks([np.log10(y) for y in [10, 30, 60, 100]])
Besides, you can follow the "progress" on the 3D-log scale issue here.

Related

Colorbars for 2D plots using Numpy, Matplotlib and os (rendering probelm)?

I have multiple .plx files that contain two column of numbers formatted as strings (1.plx , 2.plx...)
I managed to modify a code to load the data, convert it to floats, and plot it with the appropriate colorbar, but there are two issues I couldn't solve:
The color of the lines does not update
The lines rendering looks wrong (probably due to duplicates)
I want to try to avoid that rendering problem by plotting a numpy matrix, so I want to :
Load the data
store it in a numpy matrix (outside the loop so that I can do other data processing stuff)
create a 2D plot with the colorbar
Here is my attempt and the result:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import os
IdVg = [IdVg for IdVg in os.listdir() if IdVg.endswith(".plx")]
n_lines = 20
steps = np.linspace(0.1, 50, 20)
norm = mpl.colors.Normalize(vmin=steps.min(), vmax=steps.max())
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.BuPu)
cmap.set_array([])
for i in IdVg:
x, y = np.loadtxt(i, delimiter=' ', unpack=True, skiprows= 1, dtype=str)
x = x.astype(np.float64)
y = y.astype(np.float64)
for z, ai in enumerate(steps.T): # Problem here, I want to store x, y values in a 40XN matrix
# (x1, y1, x2, y2...x20, y20) and find a way to plot them
# using Matplotlib and numpy
plt.plot(x, y, c=cmap.to_rgba(z+1))
plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0))
plt.xlabel('$V_{GS}$ (V)', fontsize=14)
plt.ylabel('$I_{DS}$ (A)', fontsize=14)
plt.tick_params(axis='both', labelsize='12')
plt.grid(True, which="both", ls="-")
plt.colorbar(cmap, ticks=steps)
plt.show()
Thanks !
Since you didn't provide data, I'm going to generate my own. I assume you want to obtain the following result:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import os
n_lines = 20
steps = np.linspace(0.1, 50, 20)
norm = mpl.colors.Normalize(vmin=steps.min(), vmax=steps.max())
norm_steps = norm(steps)
cmap = mpl.cm.BuPu
plt.figure()
x = np.linspace(0, np.pi / 2)
for i in range(n_lines):
y = i / n_lines * np.sin(x)
plt.plot(x, y, c=cmap(norm_steps[i]))
plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0))
plt.xlabel('$V_{GS}$ (V)', fontsize=14)
plt.ylabel('$I_{DS}$ (A)', fontsize=14)
plt.tick_params(axis='both', labelsize='12')
plt.grid(True, which="both", ls="-")
plt.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.BuPu), ticks=steps)
plt.show()
Obviously, you would have to change the colormap to something more readable in the lower values!

Plotting a two variable function with two parameters in python

I am trying to plot a 2 variable function with additional parameters which can be changed. Below is the function-
f(x,y) = (x - a*y)/(b+y)
I want to plot it in 3d and would like to see the change in the plot by changing the values of a and b, i.e. when a=1 and b=0, etc.
I can plot it for specific a and b cases, below is the code that works for a=1 and b=0. Is there any way where I don't need to map separately for different cases of a and b?
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import numpy as np
x = np.linspace(30,7000,10000)
y = np.linspace(1,11000, 10000)
def delCAD(x,y):
return (x-y)/(y) # the function when a=1 and b=0
fig = plt.figure(figsize=(12,8))
ax = Axes3D(fig)
ax = fig.gca(projection = "3d")
surf = ax.plot_trisurf(x, y, delCAD(x,y), cmap = cm.coolwarm)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
I generally use IPython or Jupyter for that sort of thing — maybe that's an option for you? For example, using ipywidgets.interact():
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact
x = np.linspace(1, 20, 50)
y = np.linspace(1, 20, 50)
y, x = np.meshgrid(y, x)
def delCAD(x, y, a=1, b=0):
return (x - a * y) / (b + y)
#interact(a=(1, 10), b=(0, 10))
def plot(a, b):
fig, ax = plt.subplots(subplot_kw={"projection": "3d"}, figsize=(12, 6))
surf = ax.plot_trisurf(x.flat, y.flat, delCAD(x, y, a, b).flat, cmap='coolwarm')
fig.colorbar(surf, ax=ax, shrink=0.5, aspect=5)
ax.view_init(elev=30, azim=160)
plt.show()
return
Produces this:
As well as the interact wrapper, I introduced the meshgrid line to compute all the locations in the grid, and I changed some of your parameters a bit so you can see more going on in the function. I hope you can unpick the various pieces to fit your needs.

Plotting 3D image form a data in NumPy-array

I have a data file in NumPy array, I would like to view the 3D-image. I am sharing an example, where I can view 2D image of size (100, 100), this is a slice in xy-plane at z = 0.
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
X, Y, Z = np.mgrid[-10:10:100j, -10:10:100j, -10:10:100j]
T = np.sin(X*Y*Z)/(X*Y*Z)
T=T[:,:,0]
im = plt.imshow(T, cmap='hot')
plt.colorbar(im, orientation='vertical')
plt.show()
How can I view a 3D image of the data T of shape (100, 100, 100)?
I think the main problem is, that you do have 4 informations for each point, so you are actually interessted in a 4-dimensional object. Plotting this is always difficult (maybe even impossible). I suggest one of the following solutions:
You change the question to: I'm not interessted in all combinations of x,y,z, but only the ones, where z = f(x,y)
You change the accuracy of you plot a bit, saying that you don't need 100 levels of z, but only maybe 5, then you simply make 5 of the plots you already have.
In case you want to use the first method, then there are several submethods:
A. Plot the 2-dim surface f(x,y)=z and color it with T
B. Use any technic that is used to plot complex functions, for more info see here.
The plot given by method 1.A (which I think is the best solution) with z=x^2+y^2 yields:
I used this programm:
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib as mpl
X, Y = np.mgrid[-10:10:100j, -10:10:100j]
Z = (X**2+Y**2)/10 #definition of f
T = np.sin(X*Y*Z)
norm = mpl.colors.Normalize(vmin=np.amin(T), vmax=np.amax(T))
T = mpl.cm.hot(T) #change T to colors
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, facecolors=T, linewidth=0,
cstride = 1, rstride = 1)
plt.show()
The second method gives something like:
With the code:
norm = mpl.colors.Normalize(vmin=-1, vmax=1)
X, Y= np.mgrid[-10:10:101j, -10:10:101j]
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in np.linspace(-1,1,5):
Z = np.zeros(X.shape)+i
T = np.sin(X*Y*Z)
T = mpl.cm.hot(T)
ax.plot_surface(X, Y, Z, facecolors=T, linewidth=0, alpha = 0.5, cstride
= 10, rstride = 10)
plt.show()
Note: I changed the function to T = sin(X*Y*Z) because dividing by X*Y*Zmakes the functions behavior bad, as you divide two number very close to 0.
I have got a solution to my question. If we have the NumPy data, then we can convert them into TVTK ImageData and then visualization is possible with the help of mlab form Mayavi. The code and its 3D visualization are the following
from tvtk.api import tvtk
import numpy as np
from mayavi import mlab
X, Y, Z = np.mgrid[-10:10:100j, -10:10:100j, -10:10:100j]
data = np.sin(X*Y*Z)/(X*Y*Z)
i = tvtk.ImageData(spacing=(1, 1, 1), origin=(0, 0, 0))
i.point_data.scalars = data.ravel()
i.point_data.scalars.name = 'scalars'
i.dimensions = data.shape
mlab.pipeline.surface(i)
mlab.colorbar(orientation='vertical')
mlab.show()
For another randomly generated data
from numpy import random
data = random.random((20, 20, 20))
The visualization will be

Relocate the "ten raised to the power" in scientific notation of z axis in matplotlib

I want to plot a 3D figure whose z axis is written in scientific notation. However, the "ten raised to the power" of the sci notation is located at the left and not at top of the axis, and therefore, it is overlapping with the zlabel text. Is there one line command or any other solution to relocate this number and put it at the top.
PD:
For a given data matrix Sigma_ww, the code looks like this:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
sigma_ww = np.loadtxt("Sigma_ww_post.txt",delimiter=',')
xx = np.linspace(0,5,100)
X, Y = np.meshgrid(xx, xx)
matplotlib.rcParams.update({'font.size': 25, 'text.usetex': True})
fig = plt.figure(1)
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, sigma_ww, rstride=5, cstride=5, cmap=cm.pink)
ax.set_xlabel('$x$')
ax.set_ylabel('$x\prime$')
ax.zaxis.set_rotate_label(False)
ax.set_zlabel('$C_{ww|\\tilde{w}}(x,x^\prime)$',rotation=90)
ax.set_xlim3d(0, 5)
ax.set_ylim3d(0, 5)
ax.set_zlim3d(0, Sigma_ww.max())
ax.view_init(elev=30, azim=-130)
ax.xaxis._axinfo['label']['space_factor'] = 2.0
ax.yaxis._axinfo['label']['space_factor'] = 2.0
ax.zaxis._axinfo['label']['space_factor'] = 2.0
ax.ticklabel_format(style='sci', axis='z', scilimits=(0,0), useOffset=False)
plt.tight_layout()
plt.show()
and the figure looks like this:

Setting the labels of a chart

I copy this example from matplotlib site and now I want to change the font, color and size of the labels, but not the numbers size. And there is a possiblity to just see the numbers that are in the middle and at the end of each side?
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
X, Y = np.mgrid[0:6*np.pi:0.25, 0:4*np.pi:0.25]
Z = np.sqrt(np.abs(np.cos(X) + np.cos(Y)))
surf = ax.plot_surface(X + 1e5, Y + 1e5, Z, cmap='autumn', cstride=2, rstride=2)
ax.set_xlabel("X-Label")
ax.set_ylabel("Y-Label")
ax.set_zlabel("Z-Label")
ax.set_zlim(0, 2)
plt.show()
Thank you
You can change the font size, color and type by setting text properties when you create the label like this:
ax.set_xlabel("X-Label", size = 40, color = 'r', family = 'fantasy')
You can control which tick marks are displayed using ax.set_xticks.

Categories

Resources