I would like to plot a heatmap of y=f(r,phi).
The code I use is to get the values,
import numpy as np
h1=1.7
h2=0.5
inclination=np.pi/6
def power(inclination,phi):
h1=1.7
h2=0.5
D = np.arange(0.5, 12.0, 0.1)
r = np.sqrt((h1-h2)**2 + D**2)
freq = 865.7
lmb = 300/freq
H = D**2/(D**2+2*h1*h2)
theta = 4*np.pi*h1*h2/(lmb*D)
q_e = H**2*(np.sin(theta))**2 + (1 - H*np.cos(theta))**2
sigma = 1.94
N_1 = np.random.normal(0,sigma,D.shape)
rnd = 10**(-N_1/10)
F = 10
power=0.2
alpha=inclination + np.arcsin((h1-h2)/r)
gain=3.136*(np.tan(alpha)*np.sin(np.pi/2*np.cos(alpha)*np.sin(phi)))**2
y=10*np.log10( 1000*(power*gain*1.622*((lmb)**2) *0.5*1) / (((4*np.pi*r)**2) *1.2*1*F)*q_e*rnd )
return (r,phi,y)
phi=np.linspace(0, np.pi,num=115) + 10e-14
x,y,z = power(np.pi/6,phi)
I could plot the heatmap doing a meshgrid of x and y (i.e. r and phi)
X, Y = np.meshgrid(x, y)
X.shape
Y.shape
gives (115, 115) both.
I would need to reshape z values in the meshgrid before calling contourf() but I do not know how to do it.
The trick consists in to compute the function values using the meshgrid datapoints:
inclination = np.pi/6
def power(inclination,phi):
h1=1.7
h2=0.5
D = np.arange(0.5, 12.0, 0.015)
r = np.sqrt((h1-h2)**2 + D**2)
freq = 865.7
lmb = 300/freq
H = D**2/(D**2+2*h1*h2)
theta = 4*np.pi*h1*h2/(lmb*D)
q_e = H**2*(np.sin(theta))**2 + (1 - H*np.cos(theta))**2
sigma = 1.94
N_1 = np.random.normal(0,sigma,D.shape)
rnd = 10**(-N_1/10)
F = 10
power=0.8
R,PHI = np.meshgrid(r,phi[1:-1])
alpha=inclination + np.arcsin((h1-h2)/R)
gain=3.136*(np.tan(alpha)*np.sin(np.pi/2*np.cos(alpha)*np.sin(PHI)))**2
y=10*np.log10( 1000*(power*gain*1.622*((lmb)**2) *0.5*1) / (((4*np.pi*R)**2) *1.2*1*F)*q_e*rnd )
return (R,PHI,y)
Related
I have fitted a 2-D cubic spline using scipy.interpolate.RectBivariateSpline. I would like to access/reconstruct the underlying polynomials within each rectangular cell. How can I do this? My code so far is written below.
I have been able to get the knot points and the coefficients with get_knots() and get_coeffs() so it should be possible to build the polynomials, but I do not know the form of the polynomials that the coefficients correspond to. I tried looking at the SciPy source code but I could not locate the underlying dfitpack.regrid_smth function.
A code demonstrating the fitting:
import numpy as np
from scipy.interpolate import RectBivariateSpline
# Evaluate a demonstration function Z(x, y) = sin(sin(x * y)) on a mesh
# of points.
x0 = -1.0
x1 = 1.0
n_x = 11
x = np.linspace(x0, x1, num = n_x)
y0 = -2.0
y1 = 2.0
n_y = 21
y = np.linspace(y0, y1, num = n_y)
X, Y = np.meshgrid(x, y, indexing = 'ij')
Z = np.sin(np.sin(X * Y))
# Fit the sampled function using SciPy's RectBivariateSpline.
order_spline = 3
smoothing = 0.0
spline_fit_func = RectBivariateSpline(x, y, Z,
kx = order_spline, ky = order_spline, s = smoothing)
And to plot it:
import matplotlib.pyplot as plt
# Make axes.
fig, ax_arr = plt.subplots(1, 2, sharex = True, sharey = True, figsize = (12.0, 8.0))
# Plot the input function.
ax = ax_arr[0]
ax.set_aspect(1.0)
d_x = x[1] - x[0]
x_edges = np.zeros(n_x + 1)
x_edges[:-1] = x - (d_x / 2.0)
x_edges[-1] = x[-1] + (d_x / 2.0)
d_y = y[1] - y[0]
y_edges = np.zeros(n_y + 1)
y_edges[:-1] = y - (d_y / 2.0)
y_edges[-1] = y[-1] + (d_y / 2.0)
ax.pcolormesh(x_edges, y_edges, Z.T)
ax.set_title('Input function')
# Plot the fitted function.
ax = ax_arr[1]
ax.set_aspect(1.0)
n_x_span = n_x * 10
x_span_edges = np.linspace(x0, x1, num = n_x_span)
x_span_centres = (x_span_edges[1:] + x_span_edges[:-1]) / 2.0
#
n_y_span = n_y * 10
y_span_edges = np.linspace(y0, y1, num = n_y_span)
y_span_centres = (y_span_edges[1:] + y_span_edges[:-1]) / 2.0
Z_fit = spline_fit_func(x_span_centres, y_span_centres)
ax.pcolormesh(x_span_edges, y_span_edges, Z_fit.T)
x_knot, y_knot = spline_fit_func.get_knots()
X_knot, Y_knot = np.meshgrid(x_knot, y_knot)
# Plot the knots.
ax.scatter(X_knot, Y_knot, s = 1, c = 'r')
ax.set_title('Fitted function and knots')
plt.show()
Im trying to draw a heatmap from a given distribution. Ex, a normal distribution of a 2D array will look like this:
If i have another density graph like this:
How can i draw a heatmap that look like the 1st one. This is the code i used to draw the 1st heat map:
output_width = 40
output_height = 40
p_x = 20
p_y = 20
sigma = 1
X1 = np.linspace(0, output_width, output_width)
Y1 = np.linspace(0, output_height, output_height)
[X, Y] = np.meshgrid(X1, Y1)
X = X - floor(p_x)
Y = Y - floor(p_y)
D2 = X * X + Y * Y
E2 = 2.0 * sigma ** 2
Exponent = D2 / E2
heatmap = np.exp(-Exponent)
heatmap = (heatmap - heatmap.min()) / (heatmap.max() - heatmap.min())
plt.imshow(heatmap)
output_width = 40
output_height = 40
mu = 0; sigma=0.1
x, y = np.meshgrid(np.linspace(-1, 1, 40),
np.linspace(-1, 1, 40))
dst = np.sqrt(x**2+y**2)
# lower normal part of gaussian
normal = 1/(2.0 * np.pi * sigma**2)
# Calculating Gaussian filter
gauss = np.exp(-((dst-mu)**2 / (2.0 * sigma**2))) * normal
plt.imshow(gauss)
Gives:
I have following python code, and would like to:
Plot the same function in 1 (only one) figure with many different (lets say 4) 'v0' and 'theta' values, each trajectory in a different color.
Make 4 plots in 4 different figures, so that it looks like a square with 4 plots of 4 different 'v0' and 'theta' values
Make a widget to vary the v0 and theta values as the user wants with the mouse.
import numpy as np
import scipy.integrate as integrate
import matplotlib.pyplot as plt
%matplotlib inline
theta = 45.
theta = theta * np.pi/180.
v0 = 20.0
g = 9.81
R = 0.035
m = 0.057
rho = 1.2041
C = 0.5
k = (0.5*np.pi*R**2*C*rho)/m
x0=0
y0=10
vx0 = v0*np.sin(theta)
vy0 =
v0*np.cos(theta)
print(vx0)
print(vy0)
def f_func(X_vek,time):
f = np.zeros(4)
f[0] = X_vek[2]
f[1] = X_vek[3]
f[2] = - k*(f[0]**2 + f[1]**2)**(0.5)*f[0]
f[3] = -g - k*(f[0]**2 + f[1]**2)**(0.5)*f[1]
return f
X0 = [ x0, y0, vx0, vy0]
t0 = 0. tf = 10
tau = 0.05
t = np.arange(t0,tf,tau)
X = integrate.odeint(f_func,X0,t)
x = X[:,0]
y = X[:,1]
vx = X[:,2]
vy = X[:,3]
mask = y >= 0
plt.scatter(x[mask],y[mask])
plt.scatter(x[mask],y[mask])
plt.xlabel('x') plt.ylabel('y') plt.show()
I could do point 1 and 2 of my question with changing the values after plotting, then calculate vx0 and vy0 again and then call the integrate function and finally plot again, but that's kinda weird and not clean. Is there any better way to do that? like an array of different v0 and theta values or something?
Thanks!
Make your code as a function:
def func(theta=45, v0=20):
theta = theta * np.pi/180.
g = 9.81
R = 0.035
m = 0.057
rho = 1.2041
C = 0.5
k = (0.5*np.pi*R**2*C*rho)/m
x0=0
y0=10
vx0 = v0*np.sin(theta)
vy0 = v0*np.cos(theta)
def f_func(X_vek,time):
f0, f1 = X_vek[2:4].tolist()
f2 = - k*(f0**2 + f1**2)**(0.5)*f0
f3 = -g - k*(f0**2 + f1**2)**(0.5)*f1
return [f0, f1, f2, f3]
X0 = [ x0, y0, vx0, vy0]
t0 = 0.
tf = 10
tau = 0.05
t = np.arange(t0,tf,tau)
X = integrate.odeint(f_func,X0,t)
x = X[:,0]
y = X[:,1]
vx = X[:,2]
vy = X[:,3]
mask = y >= 0
return x[mask], y[mask]
then you can plot it with different parameters:
plt.plot(*func())
plt.plot(*func(theta=30))
plt.xlabel('x')
plt.ylabel('y')
plt.show()
I suggest you use Holoviews to make dynamic graph:
import holoviews as hv
hv.extension("bokeh")
hv.DynamicMap(
lambda theta, v0:hv.Curve(func(theta, v0)).redim.range(x=(0, 50), y=(0, 50)),
kdims=[hv.Dimension("theta", range=(0, 80), default=40),
hv.Dimension("v0", range=(1, 40), default=20)])
Here is the result:
Using a 2d matrix in python, how can I create a 3d surface plot, where columns=x, rows=y and the values are the heights in z?
I can't understand how to creat 3D surface plot using matplotlib.
Maybe it's different from MatLab.
example:
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
def p(eps=0.9, lmd=1, err=10e-3, m=60, n=40):
delta_phi = 2 * np.pi / m
delta_lmd = 2 / n
k = 1
P0 = np.zeros([m + 1, n + 1])
P = np.zeros([m + 1, n + 1])
GAP = 1
while GAP >= err:
k = k + 1
for i in range(0, m):
for j in range(0, n):
if (i == 1) or (j == 1) or (i == m + 1) or (i == n + 1):
P[i,j] = 0
else:
A = (1+eps*np.cos((i+1/2)*delta_phi))**3
B = (1+eps*np.cos((i-1/2)*delta_phi))**3
C = (lmd*delta_phi/delta_lmd)**2 * (1+eps*np.cos((i)*delta_phi))**3
D = C
E = A + B + C + D
F = 3*delta_phi*((1+eps*np.cos((i+1/2)*delta_phi))-(1+eps*np.cos((i-1/2)*delta_phi)))
P[i,j] = (A*P[i+1,j] + B*P[i-1,j] + C*P[i,j+1] + D*P[i,j-1] - F)/E
if P[i,j] < 0:
P[i,j] = 0
S = P.sum() - P0.sum()
T = P.sum()
GAP = S / T
P0 = P.copy()
return P, k
def main():
start = time.time()
eps = 0.9
lmd = 1
err = 10e-8
m = 60
n = 40
P, k = p()
fig = figure()
ax = Axes3D(fig)
X = np.linspace(0, 2*np.pi, m+1)
Y = np.linspace(-1, 1, n+1)
X, Y = np.meshgrid(X, Y)
#Z = P[0:m, 0:n]
#Z = Z.reshape(X.shape)
ax.set_xticks([0, np.pi/2, np.pi, np.pi*1.5, 2*np.pi])
ax.set_yticks([-1, -0.5, 0, 0.5, 1])
ax.plot_surface(X, Y, P)
show()
if __name__ == '__main__':
main()
ValueError: shape mismatch: objects cannot be broadcast to a single
shape
And the pic
pic by matplotlic
And I also use MatLab to generate,the pic:
pic by MatLab
I should think this is a problem of getting the notaton straight. A m*n matrix is a matrix with m rows and n columns. Hence Y should be of length m and X of length n, such that after meshgridding X,Y and P all have shape (m,n).
At this point there would be no need to reshape of reindex and just plotting
ax.plot_surface(X, Y, P)
would give your the desired result.
Let's assume if you have a matrix mat.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
h, w = mat.shape
plt.figure(figsize=(16, 8))
ax = plt.axes(projection='3d')
X, Y = np.meshgrid(np.arange(w), np.arange(h))
ax.plot_surface(X, Y, mat, rstride=1, cstride=1, cmap='viridis', edgecolor='none', antialiased=False)
I am trying to use the Python interpolation function to get the value y for a given x but I am getting the error "raise ValueError("x and y arrays must be equal in length along along interpolation axis" even though my arrays have both equal size and shape (according to what I get when I use .shape in my code). I am quite new to programming so I don't know how to check what else could be different in my arrays. Here is my code:
s = []
def slowroll(y, t):
phi, dphi, a = y
h = np.sqrt(1/3. * (1/2. * dphi**2 + 1/2.*phi**2))
da = h*a
ddphi = -3.*h*dphi - phi
return [dphi,ddphi,da]
phi_ini = 18.
dphi_ini = -0.1
init_y = [phi_ini,dphi_ini,1.]
h_ini =np.sqrt(1/3. * (1/2. * dphi_ini**2. + 1/2.*phi_ini**2.))
t=np.linspace(0.,20.,100.)
from scipy.integrate import odeint
sol = odeint(slowroll, init_y, t)
phi = sol[:,0]
dphi = sol[:,1]
a=sol[:,2]
n=np.log(a)
h = np.sqrt(1/3. * (1/2. * dphi**2 + 1/2.*phi**2))
s.extend(a*h)
x = np.asarray(s)
y = np.asarray(t)
F = interp1d(y, x, kind='cubic')
print F(7.34858263)
After adding in the required imports, I've been unable to duplicate your error with version 2.7.12. What python version are you running?
import numpy as np
from scipy.interpolate import interp1d
s = []
def slowroll(y, t):
phi, dphi, a = y
h = np.sqrt(1/3. * (1/2. * dphi**2 + 1/2.*phi**2))
da = h*a
ddphi = -3.*h*dphi - phi
return [dphi,ddphi,da]
phi_ini = 18.
dphi_ini = -0.1
init_y = [phi_ini,dphi_ini,1.]
h_ini =np.sqrt(1/3. * (1/2. * dphi_ini**2. + 1/2.*phi_ini**2.))
t=np.linspace(0.,20.,100.)
from scipy.integrate import odeint
sol = odeint(slowroll, init_y, t)
phi = sol[:,0]
dphi = sol[:,1]
a=sol[:,2]
n=np.log(a)
h = np.sqrt(1/3. * (1/2. * dphi**2 + 1/2.*phi**2))
s.extend(a*h)
x = np.asarray(s)
y = np.asarray(t)
F = interp1d(y, x, kind='cubic')
print F(7.34858263)
Output:
2.11688518961e+20