import numpy as np
def h(x,y):
return x+y
xline = np.linspace(1, 5, 20)
yline = np.linspace(1, 5, 20)
xi = xline
yi = yline
N = 10
for i in range(N):
xOld = xi
yOld = yi
xNew = h(xOld,yOld)
yNew = xOld
xi = xNew
yi = yNew
print(xNew[-1],yNew[-1])
So here is my code, and I was trying to get only the 10th xNew and yNew.
And when I print(xNew[-1],yNew[-1]), I got the 10th element of all 10 arrays we have. What should I do to get only the 10th xi and yi? And xi ,yi should contain 20 elements.
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()
I am trying to make some code that calculates the trajectory of a particle, given its initial position and the velocity field. Here is an example of a working bit of code that nearly does what I want:
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
def velocity(t, coord):
# velocity gives the velocity of the particle
# coord gives the coordinate of the particle where
# coord[0] = x, coord[1] = y and coord[2] = z
return [coord[0], coord[1], -2 * coord[2]]
n_points = 100
lim = 5
coord0 = [2, 2, 5]
t = np.linspace(0, lim, n_points)
sol = solve_ivp(velocity, [0, lim], t_eval = t, y0 = coord0)
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ln = ax.plot3D(sol.y[0], sol.y[1], sol.y[2])
ax.set_xlim((0, lim))
ax.set_ylim((0, lim))
ax.set_zlim((0, lim))
plt.savefig('particle_trajectory.png')
Here is the outputted figure:
I want the code to calculate the particle's trajectory if I only have an array describing the velocity field. My plan is to use interpolation so I can calculate the particle's trajectory using a similar method to that shown above. Here is my attempt to do this:
import numpy as np
from scipy.interpolate import RegularGridInterpolator
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
def velocity(t, coord):
# velocity gives the velocity of the particle
# coord gives the coordinate of the particle where
# coord[0] = x, coord[1] = y and coord[2] = z
return [vx_interp([coord[0], coord[1], coord[2]]), \
vy_interp([coord[0], coord[1], coord[2]]), \
vz_interp([coord[0], coord[1], coord[2]])]
n_points = 100
lim = 5
# Create an example of a velocity array
x = np.linspace(0, lim, n_points)
y = np.linspace(0, lim, n_points)
z = np.linspace(0, lim, n_points)
X, Y, Z = np.meshgrid(x, y, z)
vx = X
vy = Y
vz = -2 * Z
vx_interp = RegularGridInterpolator((x, y, z), vx)
vy_interp = RegularGridInterpolator((x, y, z), vy)
vz_interp = RegularGridInterpolator((x, y, z), vz)
coord0 = [2, 2, 5]
t_range = np.linspace(0, 0.2 * lim, n_points)
sol = solve_ivp(velocity, [0, 2 * lim], t_eval = t_range, y0 = coord0)
But this gives the following error:
File "/home/lex/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/ivp.py", line 542, in solve_ivp
solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
File "/home/lex/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/rk.py", line 96, in __init__
self.h_abs = select_initial_step(
File "/home/lex/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/common.py", line 111, in select_initial_step
f1 = fun(t0 + h0 * direction, y1)
File "/home/lex/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/base.py", line 138, in fun
return self.fun_single(t, y)
File "/home/lex/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/base.py", line 20, in fun_wrapped
return np.asarray(fun(t, y), dtype=dtype)
File "Python/low_and_lou/stack2.py", line 10, in velocity
return [vx_interp([coord[0], coord[1], coord[2]]), \
File "/home/lex/.local/lib/python3.8/site-packages/scipy/interpolate/interpolate.py", line 2509, in __call__
raise ValueError("One of the requested xi is out of bounds "
ValueError: One of the requested xi is out of bounds in dimension 2
I think the problem is that I am using a 'RegularGridInterpolator' inside of the solve_ivp routine. Do you know how to fix this problem?
I don't know that how make the code the three graph in damping harmonic oscillation model,
[X - t(time)], [V(velocity) - t(time)], [a(acceleration) - t(time)] graph
i can make the [X - t(time)] graph
but i don`t know how to make another graphs..
import numpy as np
from matplotlib import pyplot as plt
# mx'' = - bx' - kx
x_0 = 3
v_0 = 0
y_0 = np.array([x_0,v_0]) # first array
def Euler_Method(f,a,b,y0,step):
t = np.linspace(a,b,step)
h = t[1] - t[0]
Y = [y0]
N = len(t)
n = 0
y = y0
for n in range(0,N-1) :
y = y + h*f(y,t[n])
Y.append(y)
n = n+1
Y = np.array(Y)
return Y, t
def harmonic(y,t) :
k = 50
m = 200
b = 20 # drag coefficient
a = (-1*k/m)*y[0] - (b/m)*y[1] # x'' = a, y[0] : first position
v = y[1] # v = first velocity : y[1]
f = np.array([v,a])
return f
a = Euler_Method(harmonic, 0, 100, y_0, 100000)
X = a[0][:,0]
t = a[1]
plt.plot(t,X)
plt.show()
Why can't you just take the derivative of X to get V and A?
V = np.diff(X)
A = np.diff(V)
fig, (ax1, ax2, ax3) = plt.subplots(3)
fig.suptitle('Vertically stacked subplots')
ax1.plot(t, X)
ax2.plot(t[1:], V)
ax3.plot(t[2:], A)
plt.show()
Gives,
My code:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
y = np.tan(x)
y2 = 4 + x*0
y3 = -4 + x*0
fig = plt.figure(figsize=(8,5))
ax = fig.add_subplot(111)
diffs = np.sqrt(np.diff(x)**2+np.diff(y)**2)
length = diffs.sum()
numbers = [2, 4, 6, 8, 10]
p2 = []
for i in range(len(numbers)):
cumlenth = np.cumsum(diffs)
s = np.abs(np.diff(np.sign(cumlenth-numbers[i]))).astype(bool)
c = np.argwhere(s)[0][0]
p = x[c], y[c]
p2.append(p)
ax.cla()
ax = fig.add_subplot(111)
for j in range(len(p2)):
ax.scatter(p2[j][0],p2[j][1], color="crimson", s=5)
plt.plot(np.tan(x))
plt.plot(y2)
plt.plot(y3)
plt.ylim(-10, 10)
I'm trying to find the length of the tan() function cut off by two lines y2, y3 in a certain compartment. This means that only the part marked in red below should be taken to the total length of the chart:
Next, I try to mark the position of a points from list numbers = [] on this the graph, which are lying in the distance equal to the value of these points, starting from the beginning of the graph in point (x,y)=(0,0), and I want get their coordinates. Which for my sample list numbers = [] would give something like this:
What am I missing? Can this be achieved?
I will be grateful for any tips.
plt.plot takes two arguments, an x array and a y array; without providing both, pyplot assumes that you wanted to plot them against the index of the value in the array. So, your first hurdle is to change the lines at the bottom to:
plt.plot(x, np.tan(x))
plt.plot(x, y2)
plt.plot(x, y3)
Now we have the issue of the fact that your calculation is taking the whole graph into account, not just the parts between -4 and 4. You could solve this by filtering the x array by your thresholds:
x_all = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
x_above = x_all[ -4 < np.tan(x_all) ]
x = x_above[ np.tan(x_above) < 4 ]
Finally, we have the issue that the diff calculation seems to be taking the jump from +4 to -4 into account. We can mitigate this by filtering out anywhere the diff in y is negative:
y_up = np.diff(y) > 0
y_diff = np.where( y_up, np.diff(y), 0 )
x_diff = np.where( y_up, np.diff(x), 0 )
diffs = np.sqrt( x_diff**2 + y_diff**2 )
My final code looks like this, and seems to be working as you expect it to:
import matplotlib.pyplot as plt
import numpy as np
x_all = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
x_above = x_all[ -4 < np.tan(x_all) ]
x = x_above[ np.tan(x_above) < 4 ]
y = np.tan(x)
y2 = 4 + x*0
y3 = -4 + x*0
y_up = np.diff(y) > 0
y_diff = np.where( y_up, np.diff(y), 0 )
x_diff = np.where( y_up, np.diff(x), 0 )
diffs = np.sqrt( x_diff**2 + y_diff**2 )
length = diffs.sum()
numbers = [2, 4, 6, 8, 10]
p2 = []
for i in range(len(numbers)):
cumlenth = np.cumsum(diffs)
s = np.abs(np.diff(np.sign(cumlenth-numbers[i]))).astype(bool)
c = np.argwhere(s)[0][0]
p = x[c], y[c]
p2.append(p)
for j in range(len(p2)):
plt.scatter( p2[j][0], p2[j][1], color="crimson", s=5)
plt.plot(x, np.tan(x))
plt.plot(x, y2)
plt.plot(x, y3)
plt.ylim(-10, 10)
plt.show()
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)