Get Value from Contourplot - Python Matplotlib - matplotlib

i have a problem with my contourplot. I have messured data from experimental work, then i interpolated and plot it with matplotlib contourplot. Now i want to validate my interpolation.
For this validation i need to know the plottet value from a specific (x,y) point out of my contourplot. Due to i want to check how close my interpolation at (x,y) to my messured data at (x,y) is.
At the end i want to plot the difference over x.
i hope you understand my problem and can help me!
thanks a lot!
import pandas as pd
import numpy as np
from matplotlib.pyplot import griddata
from matplotlib.pyplot import plot
df = pd.read_excel("my_work.xlsx")
x = df.loc["x_messured" ]
y = df.loc["y_messured" ]
z = df.loc["z_messured" ]
x_interp = np.linspace(0, max(x), 200)
y_interp = np.linspace(0, max(y), 200)
z2d = griddata((x, y), z, (x_interp[None,:], y_interp[:,None]))
matplotlib.pyplot.figure()
cs = plt.contour(x_interp, y_interp, z2d)
csf = plt.contourf(x_interp, y_interp, z2d, cmap="viridis")
diff = []
for q in range(len(x)):
diff.append( abs( z[q] - get_from_z2d(x[q], y[q]) ) )
plot(x, diff)
I need the function get_from_z2d()...

Related

Vector field with numpy and a curve

I'm trying to create a vector field and some curve, I've created a vector field as shown
import matplotlib.pyplot as plt
import numpy as np
x,y = np.meshgrid(np.arange(-3,3,.35),np.arange(-3,3,.35))
u = x
v = y
plt.quiver(x, y, u, v, color = 'black')
plt.show()
But I want to add the curve $y=x^2$ in the same plot, how could I do that?
I've tryeid to add plt.plot and the curve but the result is weird.
You probably want to keep the y-axis limit as was in the mesh grid. plt.ylim is helpful in that case
import matplotlib.pyplot as plt
import numpy as np
x, y = np.meshgrid(np.arange(-3, 3, .35), np.arange(-3, 3, .35))
u = x
v = y
plt.quiver(x, y, u, v, color = 'black')
x = np.linspace(-3, 3, 100)
ylim = plt.ylim()
plt.plot(x, x**2)
plt.ylim(ylim)
plt.show()
Output:

Problem finding proper angle (in degrees) for trendline created in matplotlib using polyfit

If someone could please explain/show how to get the proper angle read...
In my example, the Angle should be between 40-45 degrees but I only show 5.71 degrees or just over 90 degrees (if I try reverse x/y). I have searched for awhile which has got me this far but I don't see how to fix this.. Help would be appreciated. Thank you in advance.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
x = [1,2,3,4,5,6,7,8,9]
y = [1.1,1.4,1.3,1.6,1.1,1.6,1.7,2.2,1.9]
plt.plot(x,y, marker='o', markersize=1, color="green")
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
plt.plot(x,p(x),"r--")
degree = np.rad2deg(np.arctan2(y[-1] - y[0], x[-1] - x[0]))
degree2 = np.rad2deg(np.arctan2(x[-1] - x[0], y[-1] - y[0]))
print(degree, degree2)
plt.show()
In case anyone else is trying to figure this out. Method can find angle,radian,slope, and intersect without plotting.
plt.axis('equal') is needed to plot the angle correctly...
Would like a better way if anyone knows to get the angle to display properly without zooming in.
Thank you to everyone for your knowledge and help.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import style
style.use('ggplot')
from statistics import mean
import math
def best_fit_slope_and_intercept(xs,ys):
m = (((mean(xs)*mean(ys)) - mean(xs*ys)) / ((mean(xs)*mean(xs)) - mean(xs*xs)))
b = mean(ys) - m*mean(xs)
return m, b
ys = np.asarray([1,2,3,4,5,6,7,8,9])
#ys = np.asarray([1.03,1.035,1.04,1.05,1.06,1.08,1.12,1.09,1.15])
xs = np.arange(len(ys))
m, b = best_fit_slope_and_intercept(xs,ys)
angle_in_radians = math.atan(m)
angle_in_degrees = math.degrees(angle_in_radians)
print("Slope=" + str(m))
print("Intercept=" + str(b))
print("Radians=" + str(angle_in_radians))
print("Degrees=" + str(angle_in_degrees))
regression_line = []
for x in xs:
regression_line.append((m*x)+b)
plt.scatter(xs,ys,color='#003F72')
plt.plot(xs, regression_line)
plt.axis('equal')
plt.show()

ValueError: Contour levels must be increasing - how to plot 3 feature data

import numpy as np
from matplotlib import pyplot as plt
data = np.random.normal(0,1,[100,3])
x = data[:,0]
y = data[:,1]
z = data[:,2]
plt.contour([x,y],z)
When I run this code with dummy data I get:
ValueError: Contour levels must be increasing
Do you have any idea what would this mean and how I could fix it?
plt.contour is a bit particular about its input, the z values must be on values on a rectangular 2D grid, see for example:
import matplotlib.pyplot as plt
import numpy as np
x = np.expand_dims(np.arange(1,11,1), axis=1)
y = np.expand_dims(np.arange(2,21,2), axis=0)
z = y * x
print(x.shape)
print(y.shape)
print(z.shape)
plt.figure()
plt.contour(z)
plt.show()
You can also provide x and y values for plt.contour by using np.meshgrid :
XX,YY = np.meshgrid(x,y)
plt.figure()
plt.contour(XX, YY, z)
plt.show()
If you have z-values with irregular values for x and y, you might use plt.tricontour, see the following example:
from matplotlib.tri import Triangulation
data = np.random.normal(0,1,[100,3])
x = data[:,0]
y = data[:,1]
#z = data[:,2]
z = x * y
tri = Triangulation(x,y)
plt.figure()
plt.tricontour(tri, z, )
plt.scatter(x,y, c=z)
plt.show()
Edit: from JohanC's comment i learned that this can be simplified without importing matplotlib.tri by:
plt.figure()
plt.tricontour(x,y,z)
plt.scatter(x,y, c=z)
plt.show()

Matplotlib 3d barplot failing to draw just one face

import numpy as np
import matplotlib.pyplot as plt
x, y = np.array([[x, y] for x in range(5) for y in range(x+1)]).T
z = 1/ (5*x + 5)
fig = plt.figure()
ax = fig.gca(projection = '3d')
ax.bar3d(x, y, np.zeros_like(z), dx = 1, dy = 1, dz = z)
yields
How do I get the face at (1,0) to display properly?
There is currently no good solution to this. Fortunately though, it happens only for some viewing angles. So you can choose an angle where it plots fine, e.g.
ax.view_init(azim=-60, elev=25)

Scatter plot with scalar data

I want to create a scatter plot with matplotlib where the data points have scalar data attached to them and are assigned a color depending on how large their attached value is relative to the other points in the set. I.e., I want something akin to a heatmap. However, I'm looking for a "discrete" heatmap, i.e. nothing should be ploted where there were no points in the original data set and, in particular, no interpolation (in space) should be performed.
Can this be done?
you can use scatter, and set the attached value to c parameter:
import numpy as np
import pylab as pl
x = np.random.uniform(-1, 1, 1000)
y = np.random.uniform(-1, 1, 1000)
z = np.sqrt(x*x+y*y)
pl.scatter(x, y, c=z)
pl.colorbar()
pl.show()
Solving this in Altair.
import numpy as np
import pylab as pl
x = np.random.uniform(-1, 1, 1000)
y = np.random.uniform(-1, 1, 1000)
z = np.sqrt(x*x+y*y)
df = pd.DataFrame({'x':x,'y':y, 'z':z})
from altair import *
Chart(df).mark_circle().encode(x='x',y='y', color='z')