polyfit error 1d or 2d array needed for y - python

Click here to see traceback
I have the following question:
Write a Python program to generate data that uses the sum of a random variable (which has a Gaussian distribution) and a 4th-degree polynomial equation (3x4+x3+3x2+4x+5). Using least squares polynomial fit, curve the generated data using a model until your model can accurately predict all values
with the following start on the question:
import random
import numpy as np
import matplotlib.pyplot as plt
def mainFunc():
poly_coeff=[3,1,3,4,5]
poly=np.poly1d(poly_coeff)
print(poly)
y = poly(random.randint(0,10)) + min(10,max(0,random.gauss(2,3)))
x=np.arange(-10,10)
curvefit=np.polyfit(x,y,4)
y_new=np.polyfit(curvefit,x)
plt.plot(x,y, '-or')
plt.plot(x,y_new, '-b')
plt.show()
mainFunc()
Can anyone help with the array error that is being generated?

Related

savgol_filter from scipy.signal library, get the resulting polinormial function?

savgol_filter gives me the series.
I want to get the underlying polynormial function.
The function of the red line in a below picture.
So that I can extrapolate a point beyond the given x range.
Or I can find the slope of the function at the two extreme data points.
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import savgol_filter
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
yhat = savgol_filter(y, 51, 3) # window size 51, polynomial order 3
plt.plot(x,y)
plt.plot(x,yhat, color='red')
plt.show()
** edit**
Since the filter uses least squares regression to fit the data in a small window to a polynomial of given degree, you can probably only extrapolate from the ends. I think the fitted curve is a piecewise function of these 'fits' and each function would not be a good representation of the entire data as a whole. What you could do is take the end windows of your data, and fit them to the same polynomial degree as the savitzy golay filter (using scipy's polyfit). It likely will not be accurate very far from the window though.
You can also use scipy.signal.savgol_coeffs() to get the coefficients of the filter. I think you dot product the coefficient array with your array of data to get the value at each point. You can include a derivative argument to get the slope at the ends of your data.
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.savgol_coeffs.html#scipy.signal.savgol_coeffs

Graph in logarithmic scale for ordinates for the Jacobi method

I have to program the Jacobi, Gauss Seidel and SOR methods to resolve Ax=b. We use a decomposition A=M-N.
For the Jacobi method, for example, we use M=diag(A) and N=M-A.
I programmed a function
jacobi(A,b,Imax,err,x0)
with the matrix A, the column vector b, a maximum number of iterations Imax, a tolerance err, for the Jacobi method. I used a "stop test" where is the "residual" at the step k.
Here is my code :
import numpy as np
import scipy.linalg as la
def jacobi(A,b,Imax,eps,x0):
M=np.diag(np.diag(A))
N=M-A
r=np.dot(A,x0)-b
x=x0
i=0
err=1+eps
res=[]
while ((i<Imax) and ((la.norm(r))>=eps)):
x=np.dot(np.dot((la.inv(M)),N),x)+np.dot((la.inv(M)),b)
r=np.dot(A,x)-b
err = la.norm(r,2)
res.append(err)
i=i+1
return (x,i,res)
and the test :
A=np.array([[2,0,0],[4,5.4,0],[7,8,9]])
x0=np.array([[1],[1],[1]])
b=np.array([[20],[8],[7]])
print(jacobi(A,b,1000,10**(-3),x0))
Now, I have to represent on a graph (in logarithmic scale for ordinates) the values in function of n.
I just would like to know how to represent a graph in logarithmic scal ? I'm beginner in Python and I don't know how to represent a graph... I tried to be clear, sorry for my bad English...
here is a log plot for some dummy values
import matplotlib.pyplot as plt
import numpy as np
j = np.power(10,range(10)) # <--- here use your computed values instead
plt.plot(j)
plt.yscale('log')
plt.show()
If you want log-log set the xscale as well.

Finding scaling factor of related datasets

I have two datasets from two sources vovering one signal and want to find the factor between the two.
They have different resolutions in x and y as well as one set being more noisy than the other.
the following gives a simple approximation, though the actual data does not follow an easy-to-fit polynomial.
import numpy as np
import matplotlib.pyplot as plt
datax1 = np.linspace(0,100,1000)
datay1 = np.around(datax1,-1)**2
datax2 = np.linspace(0,100,80)+np.random.normal(0,0.2,80)
datay2 = (datax2**2)*np.random.normal(5,0.5)+np.random.normal(0,500,80)
plt.title('Data 1 VS Data 2')
plt.plot(datax1,datay1,'b',label='Data 1')
plt.plot(datax2,datay2,'r',label='Data 2')
plt.legend()
plt.savefig('img.png', bbox_inches='tight', dpi=72)
similar data, different noise and rez
I need to automate finding this factor since I have more datasets to analyse, but SciPy's curve_fit does not play nice with interpolate as
import scipy.optimize as opt
import scipy.interpolate as interp
def func(x,k):
fun=interp(datax1,datay1*k)
return fun(x)
print opt.curve_fit(func,datax2,datay2)
only returns TypeError: 'module' object is not callable at the definition of fun
Is there any way to do this with numpy or scipy or do I have to build my own least-squares function to find the scaling of the data?

How to convert Uniform normality variables in python?

assign x~U(a,b)
get a uniform distribution array:
x_U=uniform(a,b,1000)
There is a normality distribution:
y~N(μ,σ)
I want get array y_N which is correspondently related to x_U elements.
How to carry out in python? It looks like easy in matlab. Such as this link explainnation.
The code as follows is Normality convert to Uniform:
from numpy.random import *
import matplotlib.pyplot as plt
a = normal(25,5.4,1000)
hist_N = plt.hist(a,bins=20,normed=True)
a_cum = np.cumsum(a)
hist_U = plt.hist(a_cum,bins=20,normed=True)
a_cum is uniform correspondent related to a elements
Generating unifrom random number will be applied to Monto-Carlo simulation.But the original parameter is normality distribution.So it needs convertion. My purpose is to inverse above coding process.
If I follow the link in your question, it tells me what to do. I am not sure that the erfinv does, but this code seems to convert a random uniform array to a gaussian shaped array:
import matplotlib.pyplot as plt
import numpy as np
from scipy.special import erfinv
X = np.random.uniform(0,1,1000)
Gauss = lambda x, mu, sigma: mu + np.sqrt(2)*sigma*erfinv(2*X-1)
plt.hist(Gauss(X, 1, 0.2), bins = 20)
plt.show()
Gauss is here a function, made with the lambda statement, which basically works the same as defining a function with def. The function I used is the one that was in your link.
The gaussian shape looks like
and the uniform shape like
.

Fitting a Gaussian to a set of x,y data

Firstly this is an assignment I've been set so I'm only after pointers, and I am restricted to using the following libraries, NumPy, SciPy and MatPlotLib.
We have been given a txt file which includes x and y data for a resonance experiment and have to fit both a gaussian and lorentzian fit. I'm working on the gaussian fit at the minute and have tried following the code laid out in a previous question as a basis for my own code. (Gaussian fit for Python)
from numpy import *
from matplotlib import *
import matplotlib.pyplot as plt
import pylab
from scipy.optimize import curve_fit
energy, intensity = numpy.loadtxt('resonance_data.txt', unpack=True)
n = size(energy)
mean = 30.7
sigma = 10
intensity0 = 45
def gaus(energy, intensity0, energy0, sigma):
return intensity0 * exp(-(energy - energy0)**2 / (sigma**2))
popt, pcov = curve_fit(gaus, energy, intensity, p0=[45, mean, sigma])
plt.plot(energy, intensity, 'o')
plt.xlabel('Energy/eV')
plt.ylabel('Intensity')
plt.title('Plot of Intensity against Energy')
plt.plot(energy, gaus(energy, *popt))
plt.show()
Which returns the following graph
If I keep the expressions for mean and sigma, as in the url posted the curve fit is a horizontal line, so I'm guessing the problem lies in the curve fit not converging or something.
Looks like your data skews heavily to the left, why Gaussian? Not Boltzmann, Log-Normal, or anything else?
Much of these are already implemented in scipy.stats. See scipy.stats.cauchy for lorentzian and scipy.stats.normal gaussian. An example:
import scipy.stats as ss
A=ss.norm.rvs(0, 5, size=(100)) #Generate a random variable of 100 elements, with expected mean=0, std=5
ss.norm.fit_loc_scale(A) #fit both the mean and std
(-0.13053732553697531, 5.163322485150271) #your number will vary.
And I think you don't need the intensity0 parameter, it is just going to be 1/sigma/srqt(2*pi), because the density function has to sum up to 1.

Categories