Tricontourf changing the boundary of my plot - python

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()`

Related

How to create a numpy array filled with average value of a vector

I am not sure how to phrase my question in any way better. Basically, I have three lists of the same length x, y and z and I want to fill a 2D numpy array in the z/y plane with the average of the associated z values.
Here is how I can achieve what I wan to do:
import numpy as np
import matplotlib.pyplot as plt
x = [37.59390426045407, 38.00530354847739, 38.28412244348653, 38.74871247986305, 38.73175910429809, 38.869008864244016, 39.188234404976555, 39.92835838352555, 40.881394113153334, 41.686136269465884]
y = [0.1305391767832006, 0.13764519613447768, 0.14573326951792354, 0.15090729309032114, 0.16355823707239897, 0.17327106424274763, 0.17749746339532224, 0.17310384614773594, 0.16545780437882962, 0.1604752704890856]
z = [0.05738534353865021, 0.012572155256903583, -0.021709582561809437, -0.11191337750722108, -0.07931921785775153, -0.06241610118871843, 0.014216349927058225, 0.042002641153291886, -0.029354425271534645, 0.061894011359833856]
n = 5
image = np.zeros(shape=(n,n))
# Fill the 2D array
x0 = min(x)
y0 = min(y)
dx = (max(x) - min(x))/n
dy = (max(y) - min(y))/n
# Loop over each 2D cell
for index_x in range(n):
for index_y in range(n):
# find the limits of the cell
x1 = x0 + index_x * dx
x2 = x0 + (index_x+1) * dx
y1 = y0 + index_y * dy
y2 = y0 + (index_y+1) * dy
# find the points of z that lie within the range of the cell
vec_z = [z[idx] for idx in range(len(z)) if x[idx]>=x1 and x[idx]<x2 and y[idx]>=y1 and y[idx]<y2]
if vec_z:
image[index_x, index_y] = np.mean(vec_z)
# In the end, used to create a surface plot
fig, ax = plt.subplots()
ax.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
plt.show()
Is there a more easy way to achieve this? I can imagine there is a numpy method for that.
If I understand correctly what you want to do, maybe a 2D interpolation from scipy.interpolate.interp2d is what you are looking for.
You define the interpolation function of your points:
f = interp2d(x = x, y = y, z = z)
Then you define the X and Y meshgrid:
N = 50
x_axis = np.linspace(np.min(x), np.max(x), N)
y_axis = np.linspace(np.min(y), np.max(y), N)
X, Y = np.meshgrid(x_axis, y_axis)
Finally you can compute Z interpolated values on the meshgrid:
Z = np.zeros((N, N))
for i in range(N):
for j in range(N):
Z[i, j] = f(X[i, j], Y[i, j])
If you plot in 3D the interpolated surface, you get:
fig = plt.figure()
ax = fig.add_subplot(projection = '3d')
ax.plot_surface(X, Y, Z, cmap = 'jet', shade = False)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
plt.show()
Interpolated surface compared to interpolation data points:
ax.scatter(x, y, z, color = 'black', s = 100, alpha = 1)

Contour in Python

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()

Conditional contour plot

The below code is what I'm playing around with at the minute:
x = np.linspace(0,30,1000)
y = np.linspace(0,30,1000)
X,Y = np.meshgrid(x,y)
def f(x,y):
return x**2 + y**2
Z = f(X,Y)
plt.contour(X, Y, Z, colors='black');
I want this plot to display some forbidden region, say when f(x,y) < 9;
I want this shaded in and added to the plot.
How exactly would I do this?
I've tried using plt.contourf but I can't quite get it working.
I think you can do it this way using contourf, use contourf to fill with a solid color red then mask the region you want to display with your contour chart:
x = np.linspace(0,30,1000)
y = np.linspace(0,30,1000)
X,Y = np.meshgrid(x,y)
def f(x,y):
return x**2 + y**2
Z = f(X,Y)
d = np.ma.array(Z, mask=Z>9)
plt.contour(X, Y, Z, colors='black')
plt.contourf(X, Y, d, colors='red');
Output:

Contour plot in python [duplicate]

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)

Matplotlib: Remove Single Marker

I'm trying to plot a cdf with matplotlib. However, cdfs begin in the origin, thus I prepended zeros to the x and y arrays. The problem is now that the origin now is marked as a data point. I'd like to remove that single marker in the point (0,0).
Code and picture below.
#Part of the myplot (my own) class
def cdf(self):
markers = ["x","v","o","^","8","s","p","+","D","*"]
for index,item in enumerate(np.asarray(self.data).transpose()):
x = np.sort(item)
y = np.arange(1,len(x)+1) / len(x)
x = np.insert(x,0,0)
y = np.insert(y,0,0)
self.plot = plt.plot(x,
y,
marker=markers[index],
label=self.legend[index])
self.setLabels( xlabel=self.xlabel,
ylabel="cumulative density",
title=self.title)
self.ax.set_ylim(ymax=1)
You cannot remove a marker. What you may do is to plot all the markers first, then append the origin and then plot a line.
x = np.sort(item)
y = np.arange(1,len(x)+1) / len(x)
self.plot, = plt.plot(x, y, marker=markers[index], ls="", label=self.legend[index])
x = np.insert(x,0,0)
y = np.insert(y,0,0)
self.plot2, = plt.plot(x, y, marker="", color=self.plot.get_color())
Alternative: Use the markevery argument.
x = np.sort(item)
y = np.arange(1,len(x)+1) / len(x)
x = np.insert(x,0,0)
y = np.insert(y,0,0)
markevery = range(1, len(x))
self.plot, = plt.plot(x, y, marker=markers[index], markevery=markevery,
ls="", label=self.legend[index])

Categories