np.linspace vs range in Bokeh - python

I'm a coding newcomer and I'm trying to work with Bokeh. Newcomer to StackOverflow too, so please tell me if I did something wrong here.
I'm playing with this example from Bokeh website and I ran into a problem. When the x values are set, as in the example, using np.linspace, I'm able to use the interact and play with the update function. But, if I change x to a list, using range(), then I get this error: TypeError: can only concatenate list (not "float") to list. As I understand it, the problem lies in "x + phi", since x is a list and phi is a float.
I get that it's not possible to concatenate a list with a float, but why is it only when I use a numpy.ndarray that Python understands that I want to modify the function that controls the y values?
Here is the code (I'm using Jupyter Notebook):
x = np.linspace(0,10,1000)
y = np.sin(x)
p = figure(title="example", plot_height=300, plot_width=600, y_range=(-5,5))
r = p.line(x, y)
def update(f, w=1, A=1, phi=0):
if f == "sin": func = np.sin
elif f == "cos": func = np.cos
elif f == "tan": func = np.tan
r.data_source.data["y"] = A * func(w * x + phi)
push_notebook()
show(p, notebook_handle=True)
interact(update, f=["sin", "cos", "tan"], w=(0,100), A=(1,5), phi=(0,20, 0.1))

Yes, please compare your numpy documentation with the documentation of lists: https://docs.python.org/3.6/tutorial/datastructures.html
You can also play with the following code:
from numpy import linspace
a = linspace(2, 3, num=5)
b = range(5)
print(type(a), a)
print(type(b), b)
print()
print("array + array:", a + a)
print("list + list:", b + b)
print(a + 3.14159)
print(b + 2.718) # will fail as in your example, because it is a list
My advise is to not mix lists and arrays if there is no other good reason to do so. I personally often cast function arguments to arrays if necessary:
def f(an_array):
an_array = numpy.array(an_array)
# continue knowing that it is an array now,
# being aware that I make a copy of an_array at this point

Related

float() argument must be a string or a number, not 'function'. What is wrong with this code?

I am trying to make a function call from a choice of two functions based on the variable 't' value. But "float() argument must be a string or a number, not 'function'" comes up. Please help.
import numpy as np
import sympy as sym
import matplotlib.pyplot as plt
n = 9
t = np.linspace(0,10,n)
u = np.linspace(0.0,n)
v = np.linspace(0.0,n)
a = np.linspace(0.0,n)
def T_td(t,utd,vtd):
t = sym.symbols('t')
y = utd*sym.sin(5*t) + vtd*sym.cos(5*t)
yp = y.diff(t)
ypp = yp.diff(t)
j = sym.lambdify(t,y)
k = sym.lambdify(t,yp)
l = sym.lambdify(t,ypp)
return j,k,l
def td_T(t):
t = sym.symbols('t')
y = sym.sin(5*t) + sym.cos(5*t)
yp = y.diff(t)
ypp = yp.diff(t)
j = sym.lambdify(t,y)
k = sym.lambdify(t,yp)
l = sym.lambdify(t,ypp)
return j,k,l
def func(t,utd,vtd):
if t < 5:
u,v,a = td_T(t)
utd = 0
vtd = 0
elif t == 5:
u,v,a = td_T(t)
utd = u
vtd = v
else:
u,v,a = T_td(t,utd,vtd)
return u,v,a,utd,vtd
#print(t)
for i in range(0,n,1):
u[i],v[i],a[i],u_td,v_td = func(t[i],0,0)
The first 3 values in the tuple returned by func() are of the type <function _lambdifygenerated at 0x1282cd090>
The target is a numpy array of floats.
Hence the error
Well, there are many probable errors in this code. The linspace arguments. The useless "t" arguments to td_T and T_td (since the first thing you do in it, is overwrite t with a symbolic value), the apparently useless u_dt and v_td in the main loop.
But the one causing your error, is the fact that u, v and a are numpy arrays of floats. And you are trying to force feed them with functions.
3 1st values returned by func are the values returned by td_T and T_td functions. Which are all the result of sym.lambdify. And as its name suggest, sym.lambdify returns a function, not a float. You are supposed to call those functions with some parameters. And since I've no idea what you are trying to do, I've no idea neither about which would be those parameters. But there have to be some.
Otherwise, it is like you where trying to do
u[i]=sin
v[i]=cos
a[i]=len
sin, cos or len are functions. sin(0), cos(0) and len([]) are numbers.
Likewise, the j, k, l your td_T and T_td functions returns are functions. j(0), k(1), l(2) would be numbers suited to be stored in u[i] and its kind.

TypeError: bad operand type for unary -: 'list' python

I Keep getting this error, It's so simple and error is about (-x) in function but I don't know how I can fix it.
Please help me.
This is my code:
import numpy as np
x = list(np.arange(0, 1, 0.1))
print (x)
def f(x):
f = np.exp(-x)
return f
y =f(x)
print (y)
Broadcasting isn't supported for vanilla Python lists. You should use list() after the operation involving broadcasting, like so:
import numpy as np
x = np.arange(0, 1, 0.1)
print(x)
def f(x):
f = np.exp(-x)
return f
y = list(f(x))
print(y)
First of all, please use different names
import numpy as np
x = list(np.arange(0, 1, 0.1))
print (x)
def func(param):
retval = np.exp(-param)
return retval
y = func(x)
print (y)
for start.
Then, you make a list from the np.arange, python lists don't support the unary operation - (minus) as you are using in the function (i.e. f = np.exp(-x))
numpy arrays on the other hand do support it.
what you can do is not convert it to python list, or only convert it to a python list later in the process (after using the minus)

How do I break up a squared term in sympy

I am using python (3.7.3) with sympy (1.6.2) to store a function with squared terms and non-squared terms, with each term being the product of exactly two variables.
For example,
>> import sympy as sy
>> x = sy.Symbol('x')
>> y = sy.Symbol('y')
>> F = x*x+x*y
>> print(F)
x**2+x*y
I want to be able to iterate through the terms and get each operand.
For example,
terms = F.expand(basic=True).args
for term in terms
(t0,t1) = term.args
print('t0:{}, t1:{}'.format(t0,t1))
# do some stuff using t0, t1
This works for the x*y term, but not the x**2 term.
>> print((x*y).args)
(x,y)
>> print((x**2).args) # I want this to be (x,x)
(x,2)
I tried running (x**2).expand(), but this appears to be the fully expanded version of the expression.
My question is twofold:
is there a way to expand x**2 so that it is stored as x*x?
is there a better way to go about getting each operand in each term than the for loop I show above?
You could define a custom function that defactors in the way you want:
def get_factors(expr):
if expr.func == sy.Mul:
return expr.args
elif expr.func == sy.Pow:
return tuple(expr.args[0] for _ in range(expr.args[1]))
else:
raise NotImplementedError()
Usage:
>>> a, b = terms
>>> get_factors(a)
(x, x)
>>> get_factors(b)
(x, y)

Ode solver in python

I am trying to solve an ODE (dx^2/dt^2 = -4(x^2+y^2)^(3/2)) using scipy odeint, but I can't get it to work. Here is my code:
import numpy as np
from scipy.integrate import odeint
def system(x,t,y):
x1 = x[0]
x2 = x[1]
y1 = y
dx1_dt = x2
dx2_dt = -4*(x1**2+y1**2)**(3/2)
dx_dt = [dx1_dt,dx2_dt]
return dx_dt
x_0 = [2,3]
y_0 = [8,6]
t = np.linspace(0,1,30)
x_solved = odeint(system,x_0,t,args=(y_0[0]))
I am getting this error:
odepack.error: Extra arguments must be in a tuple
But I am passing the extra arguments as a tuple: args=(y_0[0]). What am i doing wrong? Thank you!
A tuple with single element should be in the format
(y_0[0],). Note the comma.
(x) evaluates to x
(x,) evaluates to a tuple with one element
( ) are often used for syntactic and better readability reasons.
is_true = (x and y) or (a or k)
Since ( ) are already used for creating tuples, the way to differentiate a single element tuple and an expression is that comma.

Sum of Functions in Python

I have a function f(x,a) where 'x' is a variable and 'a' is a parameter. I want creat a function F(x) that is a sum of f(x,a) for a range of parameter 'a', for instance:
F(x) = f(x,a1) + f(x,a2) + f(x,a3) + ... + f(x,aN) but how I have a large range for 'a' (a=[a1,a2,a3,...,aN]) I want to write a program for this but I don't now how. For instance:
import numpy as np
# Black-Body radiation equation: 'x' is related to frequency and 'a' is related to temperature
def f(x,a):
return x**3/(np.exp(a*x) - 1)
# range for parameter a:
a = [1000,2000,3000,4000,5000,6000]
# Superposition of spectrum
def F(x):
return f(x,a[0]) + f(x,a[1]) + f(x,a[2]) + f(x,a[3]) + f(x,a[4]) + f(x,a[5])
The last line for function F(x) isn't very smart, so I tried make a loop in the above sum with sum() function
def F(x):
spectrum = []
for i in a:
spectrum = sum(f(x,i))
return spectrum
But as I don't have much experience with Python this doesn't work and I got the error:
import matplotlib.pyplot as plt
x = np.linspace(0,100,500)
plt.plot(x,F(x))
plt.show()
# ValueError: x and y must have same first dimension, but have shapes (500,) and (1,)
Does anyone know how to do this? thank you very much
From what i understand, this should do the job:
def F(x):
return sum(f(x, _a) for _a in a)
The thing I do in the sum() function is called list comprehension, feel free to look this Python feature if you are interested by Python coding: it is very powerful.

Categories