How to plot a branched sin(x) function - python

I'm a noob practicing how to use pylab, matplot lib etc.
Somehow I'm not able to plot this simple branched sin(x) function in pylab/matplotlib.
from math import sin
import pylab as plb
def f(x):
if sin(x) > 0:
return sin(x)
else:
return 0
x = plb.linspace(-4,4,10000)
plb.plot(x,f(x))
plb.show()
The following error outputs when I run the program:
Traceback (most recent call last):
File "C:/Users/...plot.py", line 12, in <module>
plb.plot(x,f(x))
File "C:/Users/......plot.py", line 5, in f
if sin(x) > 0:
TypeError: only size-1 arrays can be converted to Python scalars
Is there anyone who can help me out?

The inbuilt sine function inside math module accepts only a scalar value. You can use numpy sine instead to accomplish your plot as it accepts an array.
import numpy as np
import pylab as plb
def f(x):
sine_ = np.sin(x)
sine_[sine_< 0] = 0
return sine_
x = plb.linspace(-4,4,10000)
plb.plot(x,f(x))
plb.show()
The output is as shown below:
[]
However, as pointed out by Trenton McKinney, this answer states the use of pylab is no longer recommended. So, the alternate solution using matplotlib.pyplot is shown below:
import numpy as np
import matplotlib.pyplot as plt
def f(x):
sine_ = np.sin(x)
sine_[sine_< 0] = 0
return sine_
x = np.linspace(-4,4,10000)
plt.plot(x,f(x))
plt.show()
The output is the same as the image above.

Related

How to use math function in Python

How to execute this code:
import numpy as np
import math
x = np.arange(1,9, 0.5)
k = math.cos(x)
print(x)
I got an error like this:
TypeError: only size-1 arrays can be converted to Python scalars
Thank you in advance.
So this is happening because math.cos doesn't accept numpy arrays larger than size 1. That's why if you had a np array of size 1, your approach would still work.
A simpler way you can achieve the result is to use np.cos(x) directly:
import numpy as np
x = np.arange(1,9, 0.5)
k = np.cos(x)
print(x)
print(k)
If you have to use the math module, you can try iterating through the array and applying math.cos to each member of the array:
import numpy as np
import math
x = np.arange(1,9,0.5)
for item in x:
k = math.cos(item)
print(k) # or add to a new array/list
You're looking for something like this?
import numpy as np
import math
x = np.arange(1,9, 0.5)
for ang in x:
k = math.cos(ang)
print(k)
You are trying to pass ndarray (returned by arange) to a function, which expects just real number. Use np.cos instead.
If you want pure-Python:
You can use math.fun in map like below:
import math
x = range(1,9)
print(list(map(math.cos, x)))
Output:
[0.5403023058681398, -0.4161468365471424, -0.9899924966004454, -0.6536436208636119, 0.2836621854632263, 0.9601702866503661, 0.7539022543433046, -0.14550003380861354]

How to evaluate sympy piecewise-like expressions so it's easy to obtain numerical only output?

I have the following code which is part of a practice I'm working on:
Here is a function that obtains 2*N+1 coefficients of the Fourier series for the input function "ft" written in terms of sym.Heaviside(t), the goal is to get from this function only the numerical values so it is possible to perform operations with the obtained Power Spectral Density (PSD):
def ck_power(ft,f,N=5):
c_k_coeff=f*sym.integrate(ft*sym.exp(-2*j*np.pi*t*k*f),(t,-1/(2*f),1/(2*f)))
#C_k_coeff=sym.lambdify(k,c_k_coeff,modules=['numpy'])
#PSD=[abs((c_k_coeff(i)))**2 for i in range(-N,N+1)]
##PSD=[(c_k_coeff.subs(k,i))*(c_k_coeff.subs(k,-i)) for i in range(-N,N+1)]
### "worked" but keeps the same behavior. PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[sym.N(abs(i.subs({u(0):0.5})).evalf(3)) for i in PSD]
positive_PSD=PSD[len(PSD)//2:]
# because the k=0 c_k isn't twice in the k axis apporting power:
positive_PSD[1:]=[2*i for i in positive_PSD[1:]]
PSD=np.array(PSD)
positive_PSD=np.array(positive_PSD)
return PSD,positive_PSD
The problem is that when I use the function with the code below the figures I'm still having a weird piecewise function as the output (especially with the sawtooth wave)
The other functions don't have the same problem
But the sawtooth shows directly the piecewise output
these are the output expressions for k=0:
#vertical
type_hash=("Frequency","Power")
frequency_hash=("100KHz","1MHz","100MHz")
frequency=(100e+3,1e+6,100e+6)
waveform_hash=("Pulsetrain","Sawtooth","Triangle")
#horizontal
armonic=list(range(6))
signal={
"Pulsetrain":my.pulsetrain,
"Sawtooth":my.sawtooth,
"Triangle":my.triangle
}
t1={"waveform":[],"frequency":[],"type\\armonic":[]}
for i in armonic:
t1[str(i)]=[]
(A,D,Aoff,toff)=(1,0.5,0,0)
for iwav in waveform_hash:
for ifreq in range(len(frequency)):
ftemp=frequency[ifreq]
for itype in range(len(type_hash)):
f_now=signal[iwav](A,1/ftemp,D,Aoff,toff)
PSD,pPSD=my.ck_power(f_now,ftemp,N=5) #<<--right here is where the functions is called
for i in armonic:
if not itype:
t1[str(i)].append(f"{ftemp*i:.2e}")
else:
t1[str(i)].append(pPSD[i])# add here Power
t1["type\\armonic"].append(type_hash[itype])
t1["frequency"].append(frequency_hash[ifreq])
t1["waveform"].append(iwav)
d1=pd.DataFrame(t1)
d1
these are my imports:
import numpy as np
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
from scipy import signal
import sympy as sym
import sigplot as my
import pandas as pd
Lastly, this is part of my sigplot.py file
import numpy as np
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
from scipy import signal
import sympy as sym
from sympy import Heaviside as u
from IPython.display import display, Math
import pandas as pd
t=sym.symbols('t')
k=sym.symbols('k', integer=True)
j=sym.I
#Fourier
def ck(ft,T):
c_k=1/T*sym.integrate(ft*sym.exp(-j*k*(2*np.pi/T)*t),(t,-T/2,T/2))
c_0=c_k.subs(k,0)
#c_k_mag =[sym.simplify((abs(c_n_coeff.subs(n,i)))) for i in range (-N,N+1)]
return (c_k,c_0)
def espectral(c_k,f,N):
PSD=[abs((c_k.subs(k,i)))**2 for i in range(-N,N+1)]
positive_PSD=[2*abs((c_k.subs(k,i)))**2 if i!=0 else (c_k.subs(k,0))**2 for i in range(N+1)]
return PSD,positive_PSD
def ck_power(ft,f,N=5):
c_k_coeff=f*sym.integrate(ft*sym.exp(-2*j*np.pi*t*k*f),(t,-1/(2*f),1/(2*f)))
#C_k_coeff=sym.lambdify(k,c_k_coeff,modules=['numpy'])
#PSD=[abs((c_k_coeff(i)))**2 for i in range(-N,N+1)]
##PSD=[(c_k_coeff.subs(k,i))*(c_k_coeff.subs(k,-i)) for i in range(-N,N+1)]
### worked. PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[sym.N(abs(i.subs({u(0):0.5})).evalf(3)) for i in PSD]
positive_PSD=PSD[len(PSD)//2:]
# because the k=0 c_k isn't twice in the k axis apporting power.
positive_PSD[1:]=[2*i for i in positive_PSD[1:]]
PSD=np.array(PSD)
positive_PSD=np.array(positive_PSD)
return PSD,positive_PSD
def espectrump(c_k,f,N):
# this function should not be used for performance purposes
PSD=[abs((c_k.subs(k,i)))**2 for i in range(-N,N+1)]
positive_PSD=[2*abs((c_k.subs(k,i)))**2 if i!=0 else (c_k.subs(k,0))**2 for i in range(N+1)]
plt.stem(list(range(-N,N+1)),PSD,markerfmt='^',use_line_collection=True)
plt.xlabel("$k$")
plt.grid()
plt.show()
return positive_PSD
def psdplot(N,PSD):
plt.stem(list(range(-N,N+1)),PSD,markerfmt='^',use_line_collection=True)
plt.xlabel("$k$")
plt.ylabel("$y=10{log()}$")
plt.grid()
plt.show()
return None #excuse me, I can't hide it. Is that simple
#waveforms
def pulsetrain(A,T,D,off=0,toff=0):
f=A*(-u(t+T/2)+2*(u(t+D*T/2)-u(t-D*T/2))+u(t-T/2))
foff=f+off*(u(t+T/2)-u(t-T/2))
foff=foff.subs(t,t-toff)
return foff
def triangle(A,T,D=None,off=0,toff=0):
m = (2*A)/T
toff_temp=0.5
tri=m*t*u(t+T/2)-2*m*t*u(t)+m*t*u(t-T/2)
foff = tri+(off+toff_temp)*(u(t+T/2)-u(t-T/2))
foff = foff.subs(t,t-toff)
return foff
def sawtooth(A,T,D=None,off=0,toff=0):
m = A/T
saw =m*t*u(t+T/2)-m*t*u(t-T/2)-(m/2)*u(t-T/2)
foff = saw+off*(u(t+T/2)-u(t-T/2))
foff = foff.subs(t,t-toff)
return foff
Thanks in advance!

How to Prevent TypeError: only size-1 arrays can be converted to Python scalars from happening

I am trying to visualise a dataset with matplotlib.
The code is:
import time as ti
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import csv
from sklearn import preprocessing, svm
from sklearn.model_selection import train_test_split
from scipy.interpolate import *
data = pd.read_csv("includes\\csv.csv")
#x = array(data["day"])
#y = np.array(data["balance"])
x = float(np.array(data["day"]))
y = float(np.array(data["balance"]))
p1 = np.polyfit(x, y, 1)
print(p1)
plt.plot(x, y, "o")
plt.plot(x, polyval(p1, x), "-r")
plt.show()
The error that accurs is:
Traceback (most recent call last):
File "mittel.py", line 19, in <module>
x = float(np.array(data["day"]))
TypeError: only size-1 arrays can be converted to Python scalars
I am wondering why thats a thing because the csv file i am using is this simple:
balance,day
242537,28-5
246362,29-5
246659,30-5
246844,31-5
I have been working on this for hours.
Any answers appreciated.
Day column in your csv file is having value '28-5','29-5' ....
and np.array(data['day']) will result into a array so you cant cast array to float so getting TypeError.
change line 14-15 to this
x = [float(day_str.split('-')[0]) for day_str in np.array(data["day"])]
y = np.array(data["balance"], dtype=float)
I solved it by formatting it into a n/m/y format.

Python - How to plot argument in integral that is not the value being integrated

I want to integrate a function that has no closed form solution with an unknown variable and then plot vs the unknown variable. To try a simpler test, I tried to use the integral of f(x,c) = (x^2+c), integrated with respect to x and plot with different values of c. However, the code below gets the error
only size-1 arrays can be converted to Python scalars
even though the integral of a number, e.g. integral(5), seems to return the correct scalar value.
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
def f(x,c):
return x**2+c
def integral(c):
return integrate.quad(f,0,10, args = (c,))[0]
y = np.linspace(0,20,200)
plt.plot(y, integral(y))
You pass a numpy array as the argument c while you wanted to integrate over x for all the items of c. Therefore you can use this:
def f(x,c):
return x**2+c
def integrate_f(c):
result = np.zeros(len(c))
counter = 0
for item in c:
result[counter] = integrate.quad(f,0,10, args = (item))[0]
counter +=1
return result
c_array = np.linspace(0,1,200)
plt.plot(c_array, integrate_f(c_array))
onno was a bit faster. But here is my similar solution. You need to loop over all the different c:
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
def f(x,c):
return x**2+c
def getIntegral(c_list):
result = []
for c in c_list:
integral = integrate.quad(f,0,10,args = c)[0]
result.append(integral)
return result
if __name__ == "__main__":
c_list = np.linspace(0,20,200)
plt.plot(c_list, getIntegral(c_list))
plt.show()

Python AttributeError:cos

I'm trying to solve numerically an equation using Python2.7. This is the whole code:
from sympy import *
from sympy import Symbol
from sympy.solvers import nsolve
from scipy import *
from pylab import *
import numpy as np
# Symbols
theta = Symbol('theta')
phi = Symbol('phi')
phi0 = Symbol('phi0')
H0 = Symbol('H0')
# Constants
a = 0.05
b = 0.05**2/(8*pi*1e-7)
c= 0.001/(4*pi*1e-7)
phi0 = 60*pi/180
H0 = -0.03/(4*pi*1e-7)
def m(theta,phi):
return np.array([sin(theta)*cos(phi), sin(theta)*cos(phi), cos(phi)])
def h(phi0):
return np.array([cos(phi0), sin(phi0), 0])
def k(theta,phi,phi0):
return np.vdot(m(theta,phi),h(phi0))
def F(theta,phi,phi0,H0):
return -(a*H0)*k(theta,phi,phi0)+b*(cos(theta)**2)+c*(sin(2*theta)**2)+sin(theta)**4*sin(2*phi)**2
def F_phi(theta,phi,phi0,H0):
return simplify(diff(F(theta,phi,phi0,H0),phi))
def G(phi):
return F_phi(pi/2,phi,phi0,H0)
solution = nsolve(G(phi), phi)
print solution
and this is the traceback that I have:
Traceback (most recent call last):
File "Test.py", line 33, in <module>
solution = nsolve(G(phi), phi)
File "Test.py", line 32, in G
return F_phi(pi/2,phi,phi0,H0)
File "Test.py", line 30, in F_phi
return simplify(diff(F(theta,phi,phi0,H0),phi))
File "Test.py", line 28, in F
return -(a*H0)*k(theta,phi,phi0)+b*(cos(theta)**2)+c*(sin(2*theta)**2)+sin(theta)**4*sin(2*phi)**2
File "Test.py", line 26, in k
return np.vdot(m(theta,phi),h(phi0))
File "Test.py", line 22, in m
return np.array([sin(theta)*cos(phi), sin(theta)*cos(phi), cos(phi)])
AttributeError: cos
I am using the sympy, numpy and pylab libraries. So, I don't get a problem with the cos function. Any help?
The problem is using star imports instead of importing each package under a different namespace.
This imports function sympy.functions.elementary.trigonometric.cos under the cos name:
from sympy import *
After that, you import <ufunc 'cos'> under the name cos, overwriting the previous definition:
from scipy import *
Then, it overwrites the previous cos function by another copy of exactly the same function (from the matplotlib package):
from pylab import *
This also imports the same <ufunc 'cos'> but under the np.cos name. This is the proper way to import things:
import numpy as np
In the end, you're left with a copy of the cos function that knows how to apply itself to floats, not sympy objects. When you try to apply that function to sympy objects like phi you get the AttributeError. All in all, the solution to this particular problem is to fix the imports and know if you want the functions from sympy or the ones from numpy.
Did you import the cos function? It's in the math module
from math import cos
Same thing for sin.

Categories