I get TypeError: only size-1 arrays can be converted to Python scalars, how to fix that - numpy

import numpy as np from math import * from matplotlib.pyplot import* def f(x,y) : return np.exp(-2*x)((sqrt(3)/6)*sin(2*sqrt(3)*x)+(1/2)*cos(2*sqrt(3)*x)) dx=0.1 a=0 b=6 N= int((b-a)/dx) x=np.linspace(a,b,N+1) y=np.zeros(N+1) y[0] = 6 y[1] = y[0] for i in range (N-1): y[i+2]=(2-4*dx)*y[i+1]+(-1+4*dx-16*dx**2)*y[i] Y2 = f(x,y) Err = abs (Y2-y) plot(x,y,'r',x,Y2,'b') show () plot(x,Err) show()
how to fix that? i kept get TypeError: only size-1 arrays can be converted to Python scalars

First of all don't give code examples like that please.
I cleaned up your code and I think you can use this:
import numpy as np
from math import *
from matplotlib.pyplot import*
def f(x,y) :
return np.exp(-2*x)*((np.sqrt(3)/6)*np.sin(2*np.sqrt(3)*x)+(1/2)*np.cos(2*np.sqrt(3)*x))
dx=0.1
a=0
b=6
N= int((b-a)/dx)
x=np.linspace(a,b,N+1)
y=np.zeros(N+1)
y[0] = 6
y[1] = y[0]
for i in range (N-1):
y[i+2]=(2-4*dx)*y[i+1]+(-1+4*dx-16*dx**2)*y[i]
Y2 = f(x,y)
Err = abs (Y2-y)
plot(x,y,'r',x,Y2,'b')
plot(x,Err)

Related

Lambdify a function in two variables and plot a surface

I have a function f(x,y) where t is a parameter. I'm trying to plot the function where t = 1 for x and y values ranging from -5 to 5. The plot doesn't render.
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook
C = sv.CoordSys3D("")
x, y, z = C.base_scalars()
t = sp.symbols("t")
f = sp.sin(2*sp.pi*t)*sp.exp(-(x-3*sp.sin(sp.pi*t))**2 -(y-3*sp.cos(sp.pi*t))**2)
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(projection='3d')
X = np.linspace(-5,5,100)
Y = np.linspace(-5,5,100)
xvals, yvals = np.meshgrid(X,Y)
zvals = sp.lambdify((x,y),f.subs(t,1),"numpy")(xvals,yvals)
ax.plot_surface(xvals,yvals,zvals)
plt.show()
I get an error 'int' object has no attribute 'ndim' which I don't know how to solve.
The problem is that when you execute f.subs(t,1) it returns a number (zero in this case). So, f=0 is the expression that you are going to lambdify. Let's see the function generated by lambdify:
import inspect
print(inspect.getsource(sp.lambdify((x,y),f.subs(t,1),"numpy")))
# def _lambdifygenerated(Dummy_25, Dummy_24):
# return 0
So, no matter the values and shape of xvals and yvals, that numerical function will always return 0, which is an integer number.
However, ax.plot_surface requires zvals to have the same shape as xvals or yval. Luckily, we can easily fix that with a simple if statement:
import sympy as sp
import sympy.vector as sv
import numpy as np
import matplotlib.pyplot as plt
C = sv.CoordSys3D("")
x, y, z = C.base_scalars()
t = sp.symbols("t")
f = sp.sin(2*sp.pi*t)*sp.exp(-(x-3*sp.sin(sp.pi*t))**2 -(y-3*sp.cos(sp.pi*t))**2)
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(projection='3d')
X = np.linspace(-5,5,100)
Y = np.linspace(-5,5,100)
xvals, yvals = np.meshgrid(X,Y)
zvals = sp.lambdify((x,y),f.subs(t,1),"numpy")(xvals,yvals)
# if zvals is just a number, create a proper matrix
if not isinstance(zvals, np.ndarray):
zvals = zvals * np.ones_like(xvals)
ax.plot_surface(xvals,yvals,zvals)
plt.show()
The fact that this doesn't render is bug in lambdify that it doesn't work well for constant expressions.
Your real problem though is that the expression you are trying to plot is just zero:
In [5]: f
Out[5]:
2 2
- (x_ - 3⋅sin(π⋅t)) - (y_ - 3⋅cos(π⋅t))
ℯ ⋅sin(2⋅π⋅t)
In [6]: f.subs(t, 1)
Out[6]: 0

Levi-Civita tensor in numpy

I am looking for compact numpy code to produce the Levi-Civita tensor in any user-selected number of dimensions. Any ideas?
From the sympy tensor functions:
In [13]: tensor_functions.eval_levicivita(x,y,z)
Out[13]:
(-x + y)⋅(-x + z)⋅(-y + z)
──────────────────────────
2
def eval_levicivita(*args):
"""Evaluate Levi-Civita symbol."""
from sympy import factorial
n = len(args)
return prod(
prod(args[j] - args[i] for j in range(i + 1, n))
/ factorial(i) for i in range(n))
File: /usr/local/lib/python3.6/dist-packages/sympy/functions/special/tensor_functions.py
Type: function
For a reasonable number of dimensions the tensor size isn't that big, so I wouldn't worry about efficiency. For a start I'd try an iterative solution; it doesn't need to be fancy.
Using itertools
import numpy as np
import itertools
def levi_cevita_tensor(dim):
arr=np.zeros(tuple([dim for _ in range(dim)]))
for x in itertools.permutations(tuple(range(dim))):
mat = np.zeros((dim, dim), dtype=np.int32)
for i, j in zip(range(dim), x):
mat[i, j] = 1
arr[x]=int(np.linalg.det(mat))
return arr
https://en.wikipedia.org/wiki/Levi-Civita_symbol#Product

2nd ODE with mixed IVP and BVP, (ie.) y(0) and y'(L). How to solve?

this is a 2nd ODE with boundaries that I'm trying to solve, but I can't figure out. It is a heat transfer problem. If you have insights, it would be very appreciable.
Basically, boundary problem, but with different location. One at 0 and the other at the end.
T(0) unknown, y'(0) is a func. of T(0.06), but T(0.06) is given.
The key is how to connect the known value, T(0.06)=300, to solve the problem.
y''=0, y(0)=t0, y'(0)=(4.82e-08*T0**4-208.0)/1.2, y(0.06)=300
I tried this code, but no luck.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.integrate import odeint
def dU_dx(U, x):
return [U[1], 0]
#set initial values
y0 = T0
z0 = (4.82e-08*T0**4-208.0)/1.2
U0 = [y0, z0]
yL = 300 # how do I use this boundary condition?
L=0.006
#solve 2nd ode
xs = np.linspace(0, L, 100)
Us = odeint(dU_dx, U0, xs)
ys = Us[:,0]
plt.xlabel("x")
plt.ylabel("T")
plt.title("2nd ODE")
plt.plot(xs,ys);
from scipy.interpolate import interp1d
g = interp1d(xs,ys)
T=g(0)
print("Temp(at 0)=",T)
This would definitely not an elegant code, but this is the way I get the answer I want. But please, feel free to pose if you know better code.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.integrate import odeint
def dU_dx(U, x):
return [U[1], 0]
#Assume initial value
T0=292.75
y0 = T0
z0 = (4.82e-08*T0**4-208.0)/1.2
U0 = [y0, z0]
L=0.06
xs = np.linspace(0, L, 100)
Us = odeint(dU_dx, U0, xs)
ys = Us[:,0]
plt.xlabel("x")
plt.ylabel("T")
plt.title("2nd ODE")
plt.plot(xs,ys);
from scipy.interpolate import interp1d
g = interp1d(xs,ys)
#Repeat until see T(0.06)=300
T0=g(L)
print("Temp(0)=",T0)

Using pdsit with string value in python scipy

I have a following code and I want to calculate the hamming strings of the strings:
from pandas import DataFrame
import numpy as np
import pandas as pd
from scipy.spatial.distance import pdist, squareform
df = pd.read_csv("3d_printing.csv", encoding='utf-8', error_bad_lines=False, low_memory=False, names=['file_name', 'phash', 'dhash', 'file_date'])
def hamming_distance(s1, s2):
if len(s1) != len(s2):
raise ValueError("Undefined for sequences of unequal length")
return sum(el1 != el2 for el1, el2 in zip(s1, s2))
df.sort_values(by='file_date', ascending=0)
x = pd.DataFrame(np.triu(squareform(pdist(df[['phash']], hamming_distance))),
columns=df.file_name.str.split('_').str[0],
index=df.file_name.str.split('_').str[0]).replace(0, np.nan)
z = x[x.apply(lambda col: col.index != col.name)].max(1).max(level=0)
z.to_csv("3d_printing_x.csv", mode='a')
When I run the code I get
ValueError: could not convert string to float: '002889898888b8a9'
I know that pdist requires float values, but at this point I don't know what to do

Get the y value of a given x

I have a simple question but have not found any answer..
Let's have a look at this code :
from matplotlib import pyplot
import numpy
x=[0,1,2,3,4]
y=[5,3,40,20,1]
pyplot.plot(x,y)
It is plotted and all the points ared linked.
Let's say I want to get the y value of x=1,3.
How can I get the x values matching with y=30 ? (there are two)
Many thanks for your help
You could use shapely to find the intersections:
import matplotlib.pyplot as plt
import numpy as np
import shapely.geometry as SG
x=[0,1,2,3,4]
y=[5,3,40,20,1]
line = SG.LineString(list(zip(x,y)))
y0 = 30
yline = SG.LineString([(min(x), y0), (max(x), y0)])
coords = np.array(line.intersection(yline))
print(coords[:, 0])
fig, ax = plt.subplots()
ax.axhline(y=y0, color='k', linestyle='--')
ax.plot(x, y, 'b-')
ax.scatter(coords[:, 0], coords[:, 1], s=50, c='red')
plt.show()
finds solutions for x at:
[ 1.72972973 2.5 ]
The following code might do what you want. The interpolation of y(x) is straight forward, as the x-values are monotonically increasing. The problem of finding the x-values for a given y is not so easy anymore, once the function is not monotonically increasing as in this case. So you still need to know roughly where to expect the values to be.
import numpy as np
import scipy.interpolate
import scipy.optimize
x=np.array([0,1,2,3,4])
y=np.array([5,3,40,20,1])
#if the independent variable is monotonically increasing
print np.interp(1.3, x, y)
# if not, as in the case of finding x(y) here,
# we need to find the zeros of an interpolating function
y0 = 30.
initial_guess = 1.5 #for the first zero,
#initial_guess = 3.0 # for the secon zero
f = scipy.interpolate.interp1d(x,y,kind="linear")
fmin = lambda x: np.abs(f(x)-y0)
s = scipy.optimize.fmin(fmin, initial_guess, disp=False)
print s
I use python 3.
print(numpy.interp(1.3, x, y))
Y = 30
eps = 1e-6
j = 0
for i, ((x0, x1), (y0, y1)) in enumerate(zip(zip(x[:-1], x[1:]), zip(y[:-1], y[1:]))):
dy = y1 - y0
if abs(dy) < eps:
if y0 == Y:
print('There are infinite number of solutions')
else:
t = (Y - y0)/dy
if 0 < t < 1:
sol = x0 + (x1 - x0)*t
print('solution #{}: {}'.format(j, sol))
j += 1