How Z is calcutalted in
from matplotlib.pyplot import contour
contour([X, Y,] Z, [levels], **kwargs)
to draw a contour?
I know that Z means: The height values over which the contour is drawn.
But is it drawn by calculating a standard deviation or something like that?
An average between each point I have?
Z represents a quantity dependent on both X and Y axes. If X and Y represent a plane, Z can be thought of as a surface, whose point height depends on the X and Y coordinates of that given point. The contour is a "top view" of that surface, a projection. An example are the contour lines which report the heights of the mountains (Z) as longitude (X) and latitude (Y) change.
The contour function of matplotlib, as you wrote it, plots the values expressed in the Z variable (two-dimensional numpy.ndarray, as X and Y) as they are, without further processing. The relationship between Z and X and Y is defined outside the plot function.
I report an example below which, perhaps it may be useful:
# IMPORT
import numpy as np
import matplotlib.pyplot as pl
# INPUT
N = 100
x_min = 0
x_max = 10
y_min = 0
y_max = 10
z_min = 0
z_max = 50
z_step = 1
red = '#de7677'
# DEFINE MESH GRID
x = np.linspace(x_min, x_max, N)
y = np.linspace(y_min, y_max, N)
XX, YY = np.meshgrid(x, y)
# CALCULATE ZZ AS A FUNCTION OF XX AND YY, FOR ESAMPLE, THEIR SUM
ZZ = YY + XX
# PLOT THE CONTOUR
fig, ax = pl.subplots(figsize = (10, 10))
cont = ax.contour(XX,
YY,
ZZ,
levels = np.arange(z_min, z_max + z_step, z_step),
colors = red)
# SET THE CONTOUR LABELS
pl.clabel(cont, fmt = '%d')
# SET THE X AND Y LABEL
ax.set_xlabel('X')
ax.set_ylabel('Y')
pl.show()
Related
I am trying to use tricontourf to make a horizontal velocity contour plot for a metal rolling setup. Basically, the boundaries on the top and bottom of my horizontal velocity plot should be round but they are not because of tricontourf. Does anyone know how to fix this?
`
desired_quantity = "v_x"
x = df[["deformed_x"]].to_numpy()
x = np.transpose(x)
x = x.flatten()
y = df[["deformed_y"]].to_numpy()
y = np.transpose(y)
y = y.flatten()
z = df[[desired_quantity]].to_numpy()
z = np.transpose(z)
z = z.flatten()
y = y - y.min()
plt.figure(figsize=(12.6, 6))
levels = 18
plt.tricontourf(x, y, z, levels = levels)
plt.tricontourf(x, -1*y, z, levels = levels)
plt.colorbar()
plt.title(desired_quantity)
plt.show()`
I am trying to get isosurface's x-y coordinates from 3D plot. Here is my attempt;
import matplotlib.pyplot as plt
from numpy import pi, cos, sin, linspace, meshgrid
x = linspace(0,50,1000)
y = linspace(0,50,1000)
n = 5
L = 50
t = 0
def gyroid(x, y, n, L, t):
tanım1 = (sin(2*pi*n*x/L) * cos(2*pi*n*y/L) + sin(2*pi*n*y/L) + cos(2*pi*n*x/L))
return tanım1*tanım1 - t**2
XX, YY = meshgrid(x, y)
z = gyroid(XX, YY, n, L, t)
thickness = 0.1
contour = plt.contour(XX, YY, z,levels=[thickness])
# Attempt to get x-y coordinates
dat0= contour.allsegs[0][0]
plt.plot(dat0[:,0],dat0[:,1])
The gyroid function is normally looks like;
3D plot
I am getting isocontour for z = 0.1 plane;
Void plot
I need xy pairs of these voids. But when I try, the code is only getting lower left coordinates.
It is clear that function is strongly nonlinear, but is there any way to retrieve these coordinates?
Thanks for your responses in advance.
You specify contour.allsegs[0][0] so you get the very first line of the first contour line.
for lines in contour.allsegs:
for line in lines:
X, Y = line[:,0], line[:,1]
plt.plot(X, Y)
I have this function:
z = 0.000855995633558468*x**2 + 0.0102702516120239*x + 0.00451027901725375*y**2 - 2.23785431578513*y + 251.029058292935
I also have lists (X, Y, Z) of the coordinates of the points from this function. Then I made this code to do a plot, of that coordinates:
fig = plt.figure()
ax = fig.gca(projection='3d')
plt.plot(X, Y, Z)
plt.show()
As you can see, with this code, I join the points by segments. How can I plot the curve that passes through those points?
In short, Python does not know how all xyz points need to be connected to each other to create a surface, so it just plots lines between them.
If you want to plot a surface whose z-coordinates are a function of its x and y coordinates you need to create a grid of all the possible combinations of xy coordinates and get the resulting z-grid. Then you can plot the grids.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def z_func(x, y):
z = 0.000855995633558468 * x ** 2 + 0.0102702516120239 * x + \
0.00451027901725375 * y ** 2 - 2.23785431578513 * y + \
251.029058292935
return z
# Creates a 1D array of all possible x and y coordinates
x_coords = np.linspace(-30, 30, 100)
y_coords = np.linspace(180, 220, 100)
# Creates 2D array with all possible combinations of x and y coordinates,
# so x_grid.shape = (100, 100) and y_grid.shape = (100, 100)
[x_grid, y_grid] = np.meshgrid(x_coords, y_coords)
# Evaluates z at all grid points
z_grid = z_func(x_grid, y_grid)
# Plotting
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x_grid,y_grid,z_grid)
plt.show()
I want to plot 720 x 180 values of theta and phi into
theta range = (-180 to 180 with 0.5 step)
phi range = (0 to -90 with 0.5 step)
This is the example of dataset that I have:
Theta Phi Values
-180 0 0.2
-180 0.5 0.5
... ... ...
-180 -90 1.1
-179.5 0 0.92
... ... ...
0 -90 0.6
... ... ...
180 -89.5 0.17
180 -90 0.12
So eventually, I want to get a similar plot like this one:
I know how to create the half sphere with the code below, but how can assign the values from my dataframe?
import matplotlib.pyplot as plt
from matplotlib import cm, colors
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
# Create a sphere
r = 2
pi = np.pi
cos = np.cos
sin = np.sin
altitude
phi, theta = np.mgrid[0.0:0.5*pi:180j, 0.0:2.0*pi:720j] # phi = alti, theta = azi
x = r*sin(phi)*cos(theta)
y = r*sin(phi)*sin(theta)
z = r*cos(phi)
#Set colours and render
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(
x, y, z, rstride=4, cstride=4, color='w', alpha=0.1, linewidth=0)
ax.set_xlim([-2.2,2.2])
ax.set_ylim([-2.2,2.2])
ax.set_zlim([0,3])
ax.set_aspect("equal")
ax.plot_wireframe(x, y, z, color="k")
the code generate this one
Axes3D.plot_surface accepts 2D arrays as inputs. It provides the facecolors argument, which accepts an array of the same shape as the input arrays. This array should have the color for each face as rgba tuple in it. One can therefore normalize the array values to the range up to 1 and supply it the a colormap from matplotlib.cm.
The remaining problem is then to obtain this array from the 3 column list which is provided. Given a the datatable of length n*m where the first column denotes x values, second y values and the third some value, and where the sorting is first by x and then by y. One can then reshape the last column to an (n,m) array, where n is the number of x values and m of y values, using .reshape((m,n)).T.
Some further remarks:
In the solution below, I needed to mimic this array and directly used angles in radiant, instead of degrees.
The number of points, 180*720 seems a bit high. In order for the window not to take ages to rotate, I decreased that number.
I renamed the angles, such that they match with the usual textbook definition, phi = azimuthal angle, theta=inclination angle (from z axis).
The use of plot_wireframe may not make too much sense, since it will hide the surface below. If a wireframe is desired, one can play with the number of points to be drawn and the linewidth keyword argument. Setting linewidth to something big, like 3 or 5 makes the surface look nice, setting it to 1 leaves some wireframe look.
Here is the complete solution.
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
#theta inclination angle
#phi azimuthal angle
n_theta = 50 # number of values for theta
n_phi = 200 # number of values for phi
r = 2 #radius of sphere
theta, phi = np.mgrid[0.0:0.5*np.pi:n_theta*1j, 0.0:2.0*np.pi:n_phi*1j]
x = r*np.sin(theta)*np.cos(phi)
y = r*np.sin(theta)*np.sin(phi)
z = r*np.cos(theta)
# mimic the input array
# array columns phi, theta, value
# first n_theta entries: phi=0, second n_theta entries: phi=0.0315..
inp = []
for j in phi[0,:]:
for i in theta[:,0]:
val = 0.7+np.cos(j)*np.sin(i+np.pi/4.)# put something useful here
inp.append([j, i, val])
inp = np.array(inp)
print inp.shape
print inp[49:60, :]
#reshape the input array to the shape of the x,y,z arrays.
c = inp[:,2].reshape((n_phi,n_theta)).T
print z.shape
print c.shape
#Set colours and render
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
#use facecolors argument, provide array of same shape as z
# cm.<cmapname>() allows to get rgba color from array.
# array must be normalized between 0 and 1
ax.plot_surface(
x,y,z, rstride=1, cstride=1, facecolors=cm.hot(c/c.max()), alpha=0.9, linewidth=1)
ax.set_xlim([-2.2,2.2])
ax.set_ylim([-2.2,2.2])
ax.set_zlim([0,4.4])
ax.set_aspect("equal")
#ax.plot_wireframe(x, y, z, color="k") #not needed?!
plt.savefig(__file__+".png")
plt.show()
This question already has answers here:
Make contour of scatter
(3 answers)
Closed 5 years ago.
I have 3 lots of data. These are x and y values as well as a temperature value for each xy point. I would like to plot each point and interpolate the area between points to get a continuous surface. The issue I have is specifying the temperature values. I can't get it to work with an equal number of x,y and z (temperature) values and all the examples I can find online use a function of x and y to create z or have z values for every point on an xy grid.
Is there a simple way to do this?
import numpy as np
import matplotlib.pyplot as plt
fig, axs = plt.subplots()
x = np.linspace(0, 1, 100)
y = np.linspace(0,1,100)
X, Y = np.meshgrid(x, y)
#Z = np.sin(X)*np.sin(Y) # want to specify not an equation
Z = np.linspace(1,2,100)
levels = np.linspace(-1, 1, 40)
cs = axs.contourf(X, Y, Z, levels=levels)
fig.colorbar(cs, ax=axs, format="%.2f")
plt.show()
Update:
Here is what I have so far. I still need to work out a good method to fill in the area between points. Does anyone have any ideas?
import numpy as np
import matplotlib.pyplot as plt
fig, axs = plt.subplots()
# create a grid in the correct shape / size
x = np.linspace(0, 1, 3)
y = np.linspace(0,1,3)
X, Y = np.meshgrid(x, y)
# specify and change the relevent areas
y = [1,2,0] # location of point in x direction
x =[2,1,1] #location of point in y direction
z = [40,30,20] #temperature
Z = np.arange(1,10).reshape((3,3))
Z[y,x] = z
levels = np.linspace(0, 40, 40)
cs = axs.contourf(X, Y, Z, levels=levels)
fig.colorbar(cs, ax=axs, format="%.2f")
plt.show()
The reason people use a function of x and y is because your Z value has to be a function of x and y. In your test code Z is 1D but it needs to be 2D to plot the contours.
If you have Z (temperature) values that have the same shape as your x and y coordinates then it should work.
x = np.linspace(0, 1, 100)
y = np.linspace(0,1,100)
X, Y = np.meshgrid(x, y)
#Z = np.sin(X)*np.sin(Y) # want to specify not an equation
Z = np.linspace(1,2,100)
print X.shape
print Z.shape
(100L,100L)
(100L)