plotting vector equations with increasing variables on both axes python - python

i have been attempting a vector plot (by using quiver) in which every location on the grid is assigned a vector dependant on the location and equations but i am stuck on trying to use a range of both axis parameters (x1 and x3), getting an error:TypeError: only length-1 arrays can be converted to Python scalars
this is the code as built so far and any help would be amazing:
def SVmotion(t,A,beta,f,j):
x1= np.arange(0,10001,100)
x3= np.arange(0,10001,100)
w=2*np.pi*f
k=w/beta
k1=k*np.sin(j)
k3=k*np.cos(j)
k_beta_x = k1*x1+k3*x3
theta = k_beta_x-w*t
Usvx1 = k3*A*complex(-np.sin(theta),np.cos(theta))
Usvx3 = k1*A*complex(-np.sin(theta),np.cos(theta))
Usvx1_real=Usvx1.real
Usvx3_real=Usvx3.real
return Usvx1_real, Usvx3_real
fig ,ax = plt.subplots()
ax.quiver(x1,x3,Usvx1_real,Usvx3_real)
SVmotion(0,1,3000,2,0)

The issue is that 'theta' is an array. Please check if the following helps.
import numpy as np
def SVmotion(t,A,beta,f,j):
x1= np.arange(0,10001,100)
x3= np.arange(0,10001,100)
w=2*np.pi*f
k=w/beta
k1=k*np.sin(j)
k3=k*np.cos(j)
k_beta_x = k1*x1+k3*x3
theta = k_beta_x-w*t
for t in theta:
Usvx1 = k3*A*complex(-np.sin(t),np.cos(t))
Usvx3 = k1*A*complex(-np.sin(t),np.cos(t))
Usvx1_real=Usvx1.real
Usvx3_real=Usvx3.real
return Usvx1_real, Usvx3_real
SVmotion(0,1,3000,2,0)
#(0.003627598728468422, 0.0)

Related

Obtaining an isosurface from 3D data and the corresponding indices

I have a 3D numpy array of temperature values on a grid. From this I can compute the gradients using dTdx, dTdy, dYdz = np.gradient(T). Now I'm only interested in the values of the gradients on the isosurface where the temperature is 900. What I want to do is something like (pseudo-codish):
import nympy as np
def regular(x,y,z,q=100,k=175,a=7.1e-5):
R = np.sqrt(x**2+y**2+z**2)
return 100 / (2*np.pi*k) * (1/R) * np.exp(-0.5/a*(R+x))
x = np.arange(-1.5,0.5+res/2,res)*1e-3
y = np.arange(-1.0,1.0+res/2,res)*1e-3
z = np.arange(0.0,0.5+res/2,res)*1e-3
Y,X,Z = np.meshgrid(y,x,z)
T = regular(X,Y,Z)
dTdx, dTdy, dYdz = np.gradient(T)
(xind,yind,zind) = <package>.get_contour_indices(X,Y,Z,T,value=900)
x_gradients_at_isosurface = dTdx[xind,yind,zind]
...
I've tried:
import numpy as np
from skimage import measure
contour_data = measure.find_contours(T[:,:,0],900)
contour_data = np.int_(np.round(contour_data[0]))
xs,ys = contour_data[:,0],contour_data[:,1]
gradients_of_interest = np.array([G[x,y,0] for x,y in zip( xs,ys )])
which works fine, but only works for 2D data. I'm looking for the 3D equivalent. I've found the following:
import plotly.graph_objects as go
surf = go.Isosurface(x=X.flatten(),y=Y.flatten(),z=Z.flatten(),value=T.flatten(),isomin=900,isomax=900)
fig = go.Figure(data=surf)
plt.show()
But I'm not interested in plotting it. I want to know the indices where the temperature is T=900 so I can use it on the gradients. Any ideas?
You need skimage.measure.marching_cubes.

Spline in 3D can not be differentiated due to an AttributeError

I am trying to fit a smoothing B-spline to some data and I found this very helpful post on here. However, I not only need the spline, but also its derivatives, so I tried to add the following code to the example:
tck_der = interpolate.splder(tck, n=1)
x_der, y_der, z_der = interpolate.splev(u_fine, tck_der)
For some reason this does not seem to work due to some data type issues. I get the following traceback:
Traceback (most recent call last):
File "interpolate_point_trace.py", line 31, in spline_example
tck_der = interpolate.splder(tck, n=1)
File "/home/user/anaconda3/lib/python3.7/site-packages/scipy/interpolate/fitpack.py", line 657, in splder
return _impl.splder(tck, n)
File "/home/user/anaconda3/lib/python3.7/site-packages/scipy/interpolate/_fitpack_impl.py", line 1206, in splder
sh = (slice(None),) + ((None,)*len(c.shape[1:]))
AttributeError: 'list' object has no attribute 'shape'
The reason for this seems to be that the second argument of the tck tuple contains a list of numpy arrays. I thought turning the input data to be a numpy array as well would help, but it does not change the data types of tck.
Does this behavior reflect an error in scipy, or is the input malformed?
I tried manually turning the list into an array:
tck[1] = np.array(tck[1])
but this (which didn't surprise me) also gave an error:
ValueError: operands could not be broadcast together with shapes (0,8) (7,1)
Any ideas of what the problem could be? I have used scipy before and on 1D splines the splder function works just fine, so I assume it has something to do with the spline being a line in 3D.
------- edit --------
Here is a minimum working example:
import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate
from mpl_toolkits.mplot3d import Axes3D
total_rad = 10
z_factor = 3
noise = 0.1
num_true_pts = 200
s_true = np.linspace(0, total_rad, num_true_pts)
x_true = np.cos(s_true)
y_true = np.sin(s_true)
z_true = s_true / z_factor
num_sample_pts = 80
s_sample = np.linspace(0, total_rad, num_sample_pts)
x_sample = np.cos(s_sample) + noise * np.random.randn(num_sample_pts)
y_sample = np.sin(s_sample) + noise * np.random.randn(num_sample_pts)
z_sample = s_sample / z_factor + noise * np.random.randn(num_sample_pts)
tck, u = interpolate.splprep([x_sample, y_sample, z_sample], s=2)
x_knots, y_knots, z_knots = interpolate.splev(tck[0], tck)
u_fine = np.linspace(0, 1, num_true_pts)
x_fine, y_fine, z_fine = interpolate.splev(u_fine, tck)
# this is the part of the code I inserted: the line under this causes the crash
tck_der = interpolate.splder(tck, n=1)
x_der, y_der, z_der = interpolate.splev(u_fine, tck_der)
# end of the inserted code
fig2 = plt.figure(2)
ax3d = fig2.add_subplot(111, projection='3d')
ax3d.plot(x_true, y_true, z_true, 'b')
ax3d.plot(x_sample, y_sample, z_sample, 'r*')
ax3d.plot(x_knots, y_knots, z_knots, 'go')
ax3d.plot(x_fine, y_fine, z_fine, 'g')
fig2.show()
plt.show()
Stumbled into the same problem...
I circumvented the error by using interpolate.splder(tck, n=1) and instead used interpolate.splev(spline_ev, tck, der=1) which returns the derivatives at the points spline_ev (see Scipy Doku).
If you need the spline I think you can then use interpolate.splprep() again.
In total something like:
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
points = np.random.rand(10,2) * 10
(tck, u), fp, ier, msg = interpolate.splprep(points.T, s=0, k=3, full_output=True)
spline_ev = np.linspace(0.0, 1.0, 100, endpoint=True)
spline_points = interpolate.splev(spline_ev, tck)
# Calculate derivative
spline_der_points = interpolate.splev(spline_ev, tck, der=1)
spline_der = interpolate.splprep(spline_der_points.T, s=0, k=3, full_output=True)
# Plot the data and derivative
fig = plt.figure()
plt.plot(points[:,0], points[:,1], '.-', label="points")
plt.plot(spline_points[0], spline_points[1], '.-', label="tck")
plt.plot(spline_der_points[0], spline_der_points[1], '.-', label="tck_der")
# Show tangent
plt.arrow(spline_points[0][23]-spline_der_points[0][23], spline_points[1][23]-spline_der_points[1][23], 2.0*spline_der_points[0][23], 2.0*spline_der_points[1][23])
plt.legend()
plt.show()
EDIT:
I also opened an Issue on Github and according to ev-br the usage of interpolate.splprep is depreciated and one should use make_interp_spline / BSpline instead.
As noted in other answers, splprep output is incompatible with splder, but is compatible with splev. And the latter can evaluate the derivatives.
However, for interpolation, there is an alternative approach, which avoids splprep altogether. I'm basically copying a reply on the SciPy issue tracker (https://github.com/scipy/scipy/issues/10389):
Here's an example of replicating the splprep outputs. First let's make sense out of the splprep output:
# start with the OP example
import numpy as np
from scipy import interpolate
points = np.random.rand(10,2) * 10
(tck, u), fp, ier, msg = interpolate.splprep(points.T, s=0, k=3, full_output=True)
# check the meaning of the `u` array: evaluation of the spline at `u`
# gives back the original points (up to a list/transpose)
xy = interpolate.splev(u, tck)
xy = np.asarray(xy)
np.allclose(xy.T, points)
Next, let's replicate it without splprep. First, build the u array: the curve is represented parametrically, and u is essentially an approximation for the arc length. Other parametrizations are possible, but here let's stick to what splprep does. Translating the pseudocode from the doc page, https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.splprep.html
vv = np.sum((points[1:, :] - points[:-1, :])**2, axis=1)
vv = np.sqrt(vv).cumsum()
vv/= vv[-1]
vv = np.r_[0, vv]
# check:
np.allclose(u, vv)
Now, interpolate along the parametric curve: points vs vv:
spl = interpolate.make_interp_spline(vv, points)
# check spl.t vs knots from splPrep
spl.t - tck[0]
The result, spl, is a BSpline object which you can evaluate, differentiate etc in a usual way:
np.allclose(points, spl(vv))
# differentiate
spl_derivative = spl.derivative(vv)

Creating a bifurcation diagram in python

I am trying to come up with a code that will allow me to plot a diagram for period doubling bifurcation.
I am using the equation x = rx − 1(1 − x), and am trying to model it with r values from 0.5 to 4. Here is code that I am working with
startr = 0.5
finalr = 4
max_time = 200
x = [0.1]
r= np.linspace(.5,4,200)
for n in range(0,200):
x = np.append(r * x[n] * (1-x[n]))
plt.plot(x, label='x');
plt.xlabel('t');
This keeps getting kicked out
TypeError: append() missing 1 required positional argument: 'values'
The are the two absolutely necessary arguments for numpy.append(), taken from the Numpy reference.
arr : array_like Values are appended to a copy of this array.
values :
array_like These values are appended to a copy of arr. It must be of
the correct shape (the same shape as arr, excluding axis). If axis is
not specified, values can be any shape and will be flattened before
use.
Therefore, try using
np.append(x, r * x[n] * (1-x[n]))
inside your loop.
Logistic Map
Save file and run, png image file of graph will save in the same folder
import numpy as np
import matplotlib.pyplot as plt
Many =50000
x = np.random.rand(Many)
r = np.linspace(0,4.0, num= Many)
for i in range(1, 54):
x_a = 1-x
Data= np.multiply(x,r)
Data= np.multiply(Data, x_a)
x = Data
plt.title(r'Logistic map: $x_{n+1} = r x_{n} (1-x_{n}).$ n = '+ str(i) )
plt.ylabel('x-Random number')
plt.xlabel('r-Rate')
plt.scatter(r, Data, s=0.1, c='k')
plt.show()
plt.savefig(str(i) + " Logistic Map.png", dpi = 300)
plt.clf()

3-D interpolation using LinearNDInterpolator (Python)

I want to interpolate some 3-d data using the scipy LinearNDInterpolator function (Python 2.7). I can't quite figure out how to use it, though: below is my attempt. I'm getting the error ValueError: different number of values and points. This leads me to believe that the shape of "coords" is not appropriate for these data, but it looks in the documentation like the shape is okay.
Note that in the data I really want to use (instead of this example) the spacing of my grid is irregular, so something like RegularGridInterpolator will not do the trick.
Thanks very much for your help!
def f(x,y,z):
return 2 * x**3 + 3 * y**2 - z
x = np.linspace(1,2,2)
y = np.linspace(1,2,2)
z = np.linspace(1,2,2)
data = f(*np.meshgrid(x, y, z, indexing='ij', sparse=True))
coords = np.zeros((len(x),len(y),len(z),3))
coords[...,0] = x.reshape((len(x),1,1))
coords[...,1] = y.reshape((1,len(y),1))
coords[...,2] = z.reshape((1,1,len(z)))
coords = coords.reshape(data.size,3)
my_interpolating_function = LinearNDInterpolator(coords,data)
pts = np.array([[2.1, 6.2, 8.3], [3.3, 5.2, 7.1]])
print(my_interpolating_function(pts))

numpy contour plot with cost function

a = np.array(x)
b = np.array(y)
a_transpose = a.transpose()
a_trans_times_a = np.dot(a_transpose,a)
a_trans_times_b = np.dot(a_transpose,b)
def cost(theta):
x_times_theta = np.dot(a, theta)
_y_minus_x_theta = b - x_times_theta
_y_minus_x_theta_transpose = _y_minus_x_theta.transpose()
return np.dot(_y_minus_x_theta_transpose, _y_minus_x_theta)
n = 256
p = np.linspace(-100,100, n)
q= np.linspace(-100,100, n)
P, Q = np.meshgrid(p,q)
pl.contourf(P, Q, cost(np.array([P,Q])) ,8, alpha =0.75, cmap = 'jet')
C = pl.contour(P,Q, cost(np.array([P,Q])), 8, colors = 'black', linewidth = 0.5 )
Hi, I'm trying to make a contour plot using a cost function on two parameters, involving matrix multiplication. I've tested the cost function and it works properly in interactive session. However, running it on a linspace makes it get error "ValueError: objects are not aligned". I understand now that it has to do with how I structure P,Q. Would the solution involve writing a for loop to explicitly get an array of outputs? How would I write this?
EDIT: a,b are matrices with correct size. The cost function takes a 2-vector and outputs a number.
It's hard to know exactly without having at hand the shapes of a and b, but this error is probably caused by np.array[P,Q] being a 3-dimensional array. It seems you expect it to be 2-dimensional and for np.dot(a,theta) to perform matrix multiplication.
Presumably you want theta to be the the angular coordinate at a particular x and y value. In this case you should do
theta = np.arctan2(Q,P) #this is a 2D array of theta coordinates
costarray = cost(theta)
pl.contourf(P,Q,costarray,8,alpha=0.75,cmap='jet')

Categories

Resources