I have this program which will solve a system of differential equations in such way that two values xi, yi are produced each time a for loop iterates. Is there some way i could plot these values as they are produced instead of waiting for the computation to finish, then plotting them all?
You might want to take a look at matplotlib (http://matplotlib.sourceforge.net/) or gnuplot.py (http://gnuplot-py.sourceforge.net/). I've used these to plot data after I was done, but I don't see a reason why you could not do this while you are generating the data. However, depending on how fast your loop executes, chances are this will slow down your whole program.
The gnuplot may not be maintained any longer, but I have been using it w/o any problems.
Let's say your algorithm looks like this:
import matplotlib
x_list = []
y_list = []
while True:
xi, yi = compute() # calculates your xi and yi value
if converged(xi, yi):
break
# capture history of your xi and yi
x_list.append(xi)
y_list.append(yi)
matplotlib.pyplot.plot(x, y) # create a graph representing x and y
Related
The signature of diffusive behaviour is that the average of the square of the distance of the walker from the origin after t steps is proportional to the number of steps.
Repeat the process for several walkers and step sizes (the text suggests 500 walkers and up to 100 steps), and plot a graph similar to the one in the textbook to confirm this. Confirm also that the slope of such a graph is 1 as predicted.
I implemented the following code in Python and each time I run it the gradient I get is half the wanted value, and I could not find the mistake. Furthermore, this is the desired graph, and my graph. Can anyone spot what's wrong with the code?
import numpy as np
import matplotlib.pyplot as plt
nwalks=500
nsteps=100
x=np.zeros(nsteps)
x2avg=np.zeros(nsteps)
array=np.zeros((nwalks,nsteps))
for j in range(nwalks):
x2=np.zeros(nsteps)
for i in range(1,nsteps):
rnd=np.random.random()
if rnd<0.5:
x[i]=x[i-1]+1
else:
x[i]=x[i-1]-1
x2[i]=x[i]**2
x2avg[i]=(np.sum(x2))/(i+1)
array[j,i]=x2avg[i]
y=np.mean(array, axis=0)
i=np.arange(nsteps)
coeffs,cov=np.polyfit(i,y,1,cov=True)
grad=coeffs[0]
intercept=coeffs[1]
dgrad=np.sqrt(cov[0][0])
dintercept=np.sqrt(cov[1][1])
print(grad,dgrad)
f1=plt.figure(1)
plt.scatter(i,y,color='black',marker='.')
#generating a function of the form y=mx + c
func = np.poly1d(coeffs)
# Getting the trendline(y values)
trendline = func(i)
plt.plot(i,trendline, 'k')
I have the impression that your line x2avg[i]=(np.sum(x2))/(i+1) is wrong. It calculates the mean squared distance over all steps in of the ith walker.
Just remove the x2 and x2avg arrays and just use array[j, i] = x[i]**2 in every inner loop:
for j in range(nwalks):
x2=np.zeros(nsteps)
for i in range(1,nsteps):
rnd=np.random.random()
if rnd<0.5:
x[i]=x[i-1]+1
else:
x[i]=x[i-1]-1
array[j,i]=x[i]**2
You do already calculate the mean in the very next line, which is the correct way:
y=np.mean(array, axis=0)
There is a for-loop in my part of code, and every step it can generate new tpr(as X), fpr(as Y) like that
0.05263157894736842 0.1896551724137931
0.06578947368421052 0.19540229885057472
0.07894736842105263 0.22988505747126436
0.07894736842105263 0.25862068965517243
0.07894736842105263 0.28735632183908044
I want collect all these points and get a full plot, but it didn't work. And my code are attached below
for i in range (-30,20):
predicted = (np.sign(t+i*1e-4)+1)/2.
vals, cm = re.get_CM_vals(y_test, predicted)
tpr = re.TPR_CM(cm)
fpr = re.FPR_CM(cm)
#print(tpr, fpr)
plt.plot(fpr, tpr,'b.-',linewidth=1)
plt.show()
Beside, I want to the the right angle line between points like that.is there a func in matplotlib?
Using your current code, I suggest adding the x values to an array and the y values to another array. You could also use something like: ArrayName = [[],[]], then append the x and y values to ArrayName[0] and ArrayName[1], respectively. Not only would this actually work, but it would be slightly faster, since the plt.plot and plt.scatter functions work faster plotting all the points at once instead of through a for loop.
If you don't want to plot the points connected with lines, I still suggest using an array since that would be faster. (It wouldn't be that much faster in this case, but it's a good habit to have.
I'm making a demonstration of a different types of regression in numpy with ipython, and so far, I've been able to plot a simple linear regression without difficulty. Now, when I go on to make a quadratic fit to my data and go to plot it, I don't get a quadratic curve but instead get many lines. Here's the code I'm running that generates the problem:
import numpy
from numpy import random
from matplotlib import pyplot as plt
import math
# Generate random data
X = random.random((100,1))
epsilon=random.randn(100,1)
f = 3+5*X+epsilon
# least squares system
A =numpy.array([numpy.ones((100,1)),X,X**2])
A = numpy.squeeze(A)
A = A.T
quadfit = numpy.linalg.solve(numpy.dot(A.transpose(),A),numpy.dot(A.transpose(),f))
# plot the data and the fitted parabola
qdbeta0,qdbeta1,qdbeta2 = quadfit[0][0],quadfit[1][0],quadfit[2][0]
plt.scatter(X,f)
plt.plot(X,qdbeta0+qdbeta1*X+qdbeta2*X**2)
plt.show()
What I get is this picture (zoomed in to show the problem):
You can see that rather than having a single parabola that fits the data, I have a huge number of individual lines doing something that I'm not sure of. Any help would be greatly appreciated.
Your X is ordered randomly, so it's not a good set of x values to use to draw one continuous line, because it has to double back on itself. You could sort it, I guess, but TBH I'd just make a new array of x coordinates and use those:
plt.scatter(X,f)
x = np.linspace(0, 1, 1000)
plt.plot(x,qdbeta0+qdbeta1*x+qdbeta2*x**2)
gives me
suppose I have
t= [0,7,10,17,23,29,31]
f_t= [4,3,11,19,12,9,17]
and I have plotted f_t vs t.
Now from plotting these 7 data points, I want to retrieve 100 data points and save them in a text file. What do I have to do?
Note that I am not asking about the fitting of the plot; I know between two points the plot is linear.
What I am asking If I create a array like t=np.arange(0,31,.1), then what is the corresponding array of f_t which agrees well with the previous plot, i.e., for any t between t=0 to t=7, f_t will be determined by using a straight line connecting (0,4) and (7,3), and so on.
You should use a linear regression, that gives you a straight line formula, in which you can grasp as many points as you want.
If the line is more of a curve, then you should try to have a polynomial regression of higher degree.
ie:
import pylab
import numpy
py_x = [0,7,10,17,23,29,31]
py_y = [4,3,11,19,12,9,17]
x = numpy.asarray(py_x)
y = numpy.asarray(py_y)
poly = numpy.polyfit(x,y,1) # 1 is the degree here. If you want curves, put 2, 3 or 5...
poly is now the polynome you can use to calculate other points with.
for z in range(100):
print numpy.polyval(poly,z) #this returns the interpolated f(z)
The function np.interp will do linear interpolation between your data points:
f2 = np.interp(np.arange(0,31,.1), t, ft)
Hey,
I have a set of values for frequency and power spectrum and I have to plot Power spectrum Versus frequency on log scale. Once done, I need to pass the best fit straight line through it.. I get the line on a linear scale.. but when I try to superimpose it onto the freq-power spectrum plot, the resultant plot does not show any line, instead the data points of 1st plot are merely shifted in space.
Also, the same line, if plotted on log scale using loglog function, does not show up.
Can somebody tell me what I should do in order to get the line on a Log scale?
SO I have a file having three columns; Frequency, Power spec. Power signal.. Here is a piece of what i wrote to plot the data and line..
#initialize all variables to 0
#open the data file
while 1:
ln = datafile.readline()
if ln:
data = ln.split()
x = float(n)
y = float(data[0])
z = float(data[1])
xval.append(float(n))
yval.append(y)
zval.append(z)
n += 1
sum_z += z
sum_y += y
sum_y_squared += y*y
sum_yz += y*z
else:
break
datafile.close()
# calculate slope and intercept using formulae
for num in xval:
res = intercept + slope*num
line.append(res)
#Plot data
pylab.figure(0)
matplotlib.pylab.loglog(yval,zval)
#Plot line
pylab.figure(0)
pylab.plotloglog(line)
Despite the fact that the plot line commands are not correct in your example I assume it is similar to what you actually do.
The second plot command plots on a different x range:
loglog(yval,zval) # plot yval vs zval
loglog(line) # plots range(0,len(line)) vs line
Also have you look at the values of line, do they make sense are they in the same range as yval, zval?
Additionally you might want to use numpy.loadtxt to load your data file.
As I understand your problem, you want to plot two lines to the same diagram. Here is how it is done in general:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(line1_x, line1_y)
ax.plot(line2_x, line2_y)
ax.set_yscale("log")
So, first you put them both in the same Axes, so they appear in the same diagram. TO modify the scaling, you can use set_xscale and set_yscale respectively.
Apart from that, I cannot help but notice that your code for reading the file is horrible. As #Bernhard suggests in his answer, try using numpy.loadtxt. This could look like this:
data = numpy.loadtxt("data.txt")
n = len(data)
x = numpy.arange(n)
sum_z = sum(data.T[1])
sum_y = sum(data.T[0])
sum_y_squared = sum(data.T[0]**2)
sum_yz = sum(data.T[0]*data.T[1])
This should give you the same results as your loop, only it is much more concise. I strongly recommend you read the Tentative NumPy Tutorial, as it explain a lot of the really cool features of numpy arrays.