I have been plotting on Matplotlib for sometime and have noticed that some plotting techniques like 3D plotting and others require data to be present in arrays having dimensions of more than 1D. For instance, If I have 1D arrays X,Y,Z, then I won't be able to plot them in the 3D plots. However, if I reshape the same arrays to 2D or any ND and then I am able to plot them in 3D. My question is, why do you think this happens? More importantly, is there a difference between a reshaped and 1D array (in terms of its data)?
Let's investigate ax.contour. There is an example in the docs:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
print(X.shape, Y.shape, Z.shape)
# ((120, 120), (120, 120), (120, 120))
cset = ax.contour(X, Y, Z)
ax.clabel(cset, fontsize=9, inline=1)
plt.show()
The print statement shows that ax.contour can accept 2D inputs.
If we were to change the X and Y arrays to 1D arrays:
X, Y, Z = axes3d.get_test_data(0.05)
X = X.reshape(-1)
Y = Y.reshape(-1)
print(X.shape, Y.shape, Z.shape)
Then we get
((14400,), (14400,), (120, 120))
as the shapes, and a TypeError is raised:
TypeError: Length of x must be number of columns in z,
and length of y must be number of rows.
So it appears there is no choice. ax.contour expects 2D arrays.
Related
I am trying to get a heatmap kind of color map with known values at points in plane which are spread non-uniformly (i.e., not uniform or not in grid form)
import numpy as np
x = np.random.rand(100)
y = np.random.rand(100)
z = np.random.rand(100)
Here, Using x, y and z, I want a plot showing intensity z[i] at point coordinates (x[i], y[i])
I tried using pcolor mesh of matplotlib as follows
import matplotlib.pyplot as plt
plt.figure()
plt.pcolormesh(x.reshape(10, 10), y.reshape(10, 10), z.reshape(10, 10))
plt.colorbar()
plt.show()
But this is giving the following error,
UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
I'd rather use a tricontourf
In [11]: x = np.random.rand(10000)
...: y = np.random.rand(10000)
...: z = np.random.rand(10000)+3*x+2*y
...: plt.tricontourf(x, y, z)
...: plt.colorbar()
...: plt.show()
I have a large set of measurements that I want to visualize in 4D using matplotlib in Python.
Currently, my variables are arranged in this way:
x = np.array(range(0, v1))
y = np.array(range(0, v2))
z = np.array(range(0, v3))
I have C which is a 3D array containing measurement values for each combination of the previous variables. So it has a dimension of v1*v2*v3.
Currently, I visualize my measurements using contourf function and I plot that for each z value. This results in 3D contour plot i.e. 2D + color map for the values. Now, I want to combine all the variables and look at the measurements in 4D dimensions (x, y, z, and color corresponding to the measurement value). What is the most efficient way to do this in python?
Regarding to #Sameeresque answer, I think the question was about a 4D graph like this (three coordinates x, y, z and a color as the fourth coordinate):
import numpy as np
import matplotlib.pyplot as plt
# only for example, use your grid
z = np.linspace(0, 1, 15)
x = np.linspace(0, 1, 15)
y = np.linspace(0, 1, 15)
X, Y, Z = np.meshgrid(x, y, z)
# Your 4dimension, only for example (use yours)
U = np.exp(-(X/2) ** 2 - (Y/3) ** 2 - Z ** 2)
# Creating figure
fig = plt.figure()
ax = plt.axes(projection="3d")
# Creating plot
ax.scatter3D(X, Y, Z, c=U, alpha=0.7, marker='.')
plt.show()
A 4D plot with (x,y,z) on the axis and the fourth being color can be obtained like so:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.array(range(0, 50))
y = np.array(range(0, 50))
z = np.array(range(0, 50))
colors = np.random.standard_normal(len(x))
img = ax.scatter(x, y, z, c=colors, cmap=plt.hot())
fig.colorbar(img)
plt.show()
A simple way to visualize your 4D function, call it W(x, y, z), could be producing a gif of the cross-section contour plots along the z-axis.
Package plot4d could help you do it. An example plotting an isotropic 4D function:
from plot4d import plotter
import numpy as np
plotter.plot4d(lambda x,y,z:x**2+y**2+z**2, np.linspace(0,1,20), wbounds=(0,3), fps=5)
The code above generates this gif:
So, I've got three arrays of data, X, Y, and Z, each 225 numbers long. What I would like to do is to plot all three values at the same time on a surface plot. When I try to use
ax.plot_surface(X,Y,Z)
it tells me that Z needs to be a 2D array. I've looked it up and I've seen that it's possible to plot Z if it was a function of X and Y, but I need the first Z point to be associated with the first X and Y point etc. Is this possible in Python?
If your arrays are all 1-D, then I think what you want is
ax.plot_trisurf(X,Y,Z, triangles=tri.triangles, cmap=plt.cm.Spectral)
See more info at https://matplotlib.org/examples/mplot3d/trisurf3d_demo2.html
So, I've got three arrays of data, X, Y, and Z, each 225 numbers long. What I would like to do is to plot all three values at the same time on a surface plot.
So, from what i understood you want to plot a 3d surface plot.
But it seems you are only providing 3 1xn arrays. (in this case n == 255)
When plotting a surface plot, what you are doing in practice is getting each and every possible combination of a base (XY plane) and telling how high is a point Z on that given XY coordinates, hence Z is depicted as a function Z(i,j)
but I need the first Z point to be associated with the first X and Y point etc. Is this possible in Python?
Yes, but if you associate each Z point to the first X,Y and so on, you would only have the Z values for X==Y, which would be incomplete information for your surfaceplot!
A good (great) example of surface plot comes from matplotlib official docs
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
which results in:
What the code is actually doing:
Defining the input vectors X and Y (both range and interval)
Making a meshgrid out of those vectors (if unclear as to what a meshgrid is, print the output!)
Defining a function over the X,Y domain
Applying it to get Z
If you check, X,Y and Z are 2 dimensional arrays!
Hope it helps!
I'm trying to make a 3d plot from a list of lists of values. All the sublists have the same number of values.
I tried this: Plot a 3d surface from a 'list of lists' using matplotlib , but I get the error:
ValueError: shape mismatch: objects cannot be broadcast to a single shap
Here is how to reproduce:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
list_of_lists = [[1,2,3,4,1,2,3,4,1,2,3,4],[2,3,5,9,2,3,5,9,2,3,5,9],[5,9,8,1,5,9,8,1,5,9,8,1],[1,2,3,4,1,2,3,4,1,2,3,4],[2,3,5,9,2,3,5,9,2,3,5,9],[5,9,8,1,5,9,8,1,5,9,8,1]]
data = np.array(list_of_lists)
length = data.shape[0]
width = data.shape[1]
x, y = np.meshgrid(np.arange(length), np.arange(width))
fig = plt.figure()
ax = fig.add_subplot(1,1,1, projection='3d')
ax.plot_surface(x, y, data)
plt.show()
Thank you
Due to default cartesian indexing of meshgrid output (see docs for more info) your data has shape of (6, 12), but x and y have shapes of (12, 6). The easiest way to solve the problem is to transpose data array:
ax.plot_surface(x, y, data.T)
Or you can apply matrix indexing notation to meshgrid output:
x, y = np.meshgrid(np.arange(length), np.arange(width), indexing='ij')
I would like to plot a 3D matrix - essentially a box of numbers, each labelled by an x, y, z triad of coordinates- by assigning a different colour to each of the x, y, z point, according to its magnitude (for example, bigger numbers in red and smaller numbers in blue).
I cannot plot sections of the matrix, I rather need to plot the whole matrix together.
If we call matrix3D my matrix, its elements are built this way:
matrix3D[x][y][z] = np.exp(-(x**2+y**2+z**2))
How can I obtain the desired plot?
EDIT: Using Mayavi2 Contour3D(), I have tried to write the following:
from mayavi import mlab
X = np.arange(0, n_x, 1)
Y = np.arange(0, n_z, 1)
Z = np.arange(0, n_z, 1)
X, Y, Z = np.meshgrid(X, Y, Z)
obj = mlab.contour3d(X, Y, Z, matrix3D, contours=4, transparent=True)
where n_x, n_y, n_z are the dimension of the 3 axes. How can I actually see and/or save the image now?
If you need to plot the whole thing I think you're best taking a look at mayavi. This will let you plot a volume and you should be able to get the results you need.
I know you said you need to plot the whole thing at once, but this might still be of some use. You can use countourf to plot like this:
import numpy as np
import matplotlib.pyplot as plt
matrix3D = np.empty((10, 10, 10))
x = np.arange(10)
y = np.arange(10)
z = np.arange(10)
matrix3D[x][y][z] = np.exp(-(x**2+y**2+z**2))
fig = plt.figure()
ax = fig.add_subplot(plt.subplot(1, 1, 1))
ax.contourf(x, y, matrix3D[:, :, 3])
plt.show()
This gives you a slice of the 3D matrix (in this example the 4th slice).