Reputation: 69
I have a set of data and I have fit a normal distribution to the data using numpy and scipy. But when I try to plot the pdf, I get the following error:
I have tried to change the dtype of Z, but that did not work. Any suggestions will help. Thanks.
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import numpy as np
import random
from sympy.matrices import Matrix
from sympy import symbols, pprint, N
from scipy.stats import multivariate_normal
from target import true_target_trajectory, target_posiion
def plot_gaussian(X, Y, Z):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z)
plt.show()
def covariance(x, y):
sigma1 = np.std(x, dtype=np.float64)
sigma2 = np.std(y, dtype=np.float64)
cov = np.matrix([[sigma1, sigma1*sigma2], [sigma1*sigma2, sigma2]])
min_eig = np.min(np.real(np.linalg.eigvals(cov)))
if min_eig < 0:
cov -= 10*min_eig * np.eye(*cov.shape)
return cov
def gaussian(x, mu, cov):
rv = multivariate_normal(mu, cov)
return rv.pdf(x)
#plot_gaussian()
vin = 300
qin = 9
x = []
y = []
time = np.linspace(0, 2*np.pi, 100)
for t in (time):
cc = target_posiion(vin, qin, t)
x.append(cc.T[0])
y.append(cc.T[1])
mu = np.array([np.mean(x), np.mean(y)])
cov = covariance(x, y)
X, Y = np.meshgrid(x, y)
pos = np.dstack((X, Y))
Z = gaussian(pos, mu, cov)
plot_gaussian(X, Y, Z)
I tried to reproduce the issue with x = np.linspace(-1, 3, 100) and y = np.linspace(0, 4, 100). But that did not give any error and i got the bell curve as expected. So i am attaching the code for target position. The code for target_position:
import random
import numpy as np
from sympy.vector.coordsysrect import CoordSys3D
from sympy.physics.mechanics import dynamicsymbols
from sympy import symbols, sin, pprint, Derivative, Identity, N
from sympy.matrices import Matrix, BlockMatrix, block_collapse
C = CoordSys3D('C')
i, j, k = C.base_vectors()
def evaluate_matrix(m, v_in, q_in, tk):
w, t = symbols('w t')
v0, q = symbols('v0 q')
params = {v0:v_in, q:q_in, t:tk}
return Matrix([[N(m[0].subs(params)), N(m[1].subs(params))]]).T
def true_target_trajectory(v_in, q_in, tk):
w, t = symbols('w t')
v0, q, A = symbols('v0 q A')
r, v, a, x, y = dynamicsymbols('r v a x y')
A = (v0**2)/q
w = q/(2*v0)
x = A*sin(w*t)*i
y = A*sin(2*w*t)*j
r = x + y
r_m = Matrix(r.to_matrix(C)[:2])
v = Derivative(r, t).doit()
v_m = Matrix(v.to_matrix(C)[:2])
a = Derivative(v, t).doit()
a_m = Matrix(a.to_matrix(C)[:2])
x_k = BlockMatrix([[r_m.T, v_m.T, a_m.T]]).T
I = Identity(2)
H = BlockMatrix([[I, I, I]])
z = evaluate_matrix(block_collapse(H*x_k), v_in, q_in, tk)
return z
def target_posiion(v_in, q_in, tk):
sigma = 50
u_k = Matrix([[random.gauss(0,1), random.gauss(0,1)]]).T
z = true_target_trajectory(v_in, q_in, tk)
z_c_k = z + sigma*u_k
return z_c_k
Upvotes: 0
Views: 2621
Reputation: 13997
The problem is that your x
and y
are lists of type sympy.core.numbers.Float
, not regular Python float
. Numpy doesn't know how to convert Sympy numeric types, so meshgrid ends up returning X
and Y
arrays of dtype=object
. Down the line, this ends up screwing up the call to ax.plot_surface
.
Just convert x
and y
to standard Numpy arrays of np.float64
before you pass them into meshgrid
:
X, Y = np.meshgrid(np.array(x).astype(float), np.array(y).astype(float))
Once you do that, everything should be fine. Here's the output:
Upvotes: 3