Got this question from 'how to think like a computer scientist' course:
Interpret the data file labdata.txt such that each line contains a an x,y coordinate pair. Write a function called plotRegression that reads the data from this file and uses a turtle to plot those points and a best fit line according to the following formulas:
y=y¯+m(x−x¯)
m=∑xiyi−nx¯y¯∑x2i−nx¯2
http://interactivepython.org/runestone/static/thinkcspy/Files/Exercises.html?lastPosition=1308
my code doesnt seem to be working and i cant figure out why. it looks like python is interpreting the data as str as opposed to float.
def plotregression(t):
labfile = open('labdata.txt','r')
sumx = 0
sumy = 0
count = 0
sumprod = 0
sumsqrx =0
sumsqrnx = 0
for i in labfile:
points = i.split()
print (points)
t.up()
t.setpos(points[0],points[1])
t.stamp()
sumx = sumx + int(points[0])
sumy = sumy + int(points[1])
prod = points[0]*int(points[1])
sumprod = sumprod + prod
count += 1
sqrx = int(points[0])**2
sumsqrx = sumsqrx + sqrx
sqrnx = int(points[0])**(-2)
sumsqrnx = sumsqrnx + sqrnx
avgx = sumx/count
avgy = sumy/count
m = (sumprod - count(avgx*avgy))/sumsqrx- (count(avgx**2))
print(m)
for bestline in labfile:
line = bestline.split()
y= avgy + m(int(line[0])-avgx)
t.down()
t.setpos(0,0)
t.setpos(line[0],y)
plotregression(kj)
Appreciate your help.
Thnx
I actually worked out the problem myself and it finally seems to be doing what i'm telling it to. But i would love to know if i can cut out any unnecessary lines of code. I'm thinking its a bit too long and i'm missing out something which would make this more simpler to do.
import turtle
wn= turtle.Screen()
kj = turtle.Turtle()
kj.shape('circle')
kj.turtlesize(0.2)
kj.color('blue')
kj.speed(1)
def plotregression(t):
sumx = 0
sumy = 0
count = 0
sumprod = 0
sumsqrx =0
labfile = open('labdata.txt','r')
for i in labfile:
points = i.split()
print (points)
t.up()
t.setpos(int(points[0]),int(points[1]))
t.stamp()
sumx = sumx + int(points[0])
sumy = sumy + int(points[1])
prod = int(points[0])*int(points[1])
sumprod = sumprod + prod
count += 1
sqrx = int(points[0])**2
sumsqrx = sumsqrx + sqrx
avgx = sumx/count
avgy = sumy/count
m = (sumprod - count*(avgx*avgy))/(sumsqrx- (count*(avgx**2)))
print('M is: ',m )
labfile.close()
labfile = open('labdata.txt','r')
besttfit = open('bestfit.txt','w')
for bestline in labfile:
line = bestline.split()
y = avgy + m*(int(line[0])-avgx)
print('y is:' ,y)
besttfit.write((line[0])+'\t'+str(y)+'\n')
labfile.close()
besttfit.close()
bestfitline = open('bestfit.txt','r')
for regline in bestfitline:
reg = regline.split()
t.goto(float(reg[0]),float(reg[1]))
t.down()
t.write('Best fit line')
bestfitline.close()
wn.setworldcoordinates(-10,-10,120,120)
figure = plotregression(kj)
wn.exitonclick()
please let me know if i can cut down anywhere
I was solving the same problem form the interactive python. Here is how I did it.
import turtle
def plotRegression(data):
win = turtle.Screen()
win.bgcolor('pink')
t = turtle.Turtle()
t.shape('circle')
t.turtlesize(0.2)
x_list, y_list = [i[0] for i in plot_data], [i[1] for i in plot_data]
x_list, y_list = [float(i) for i in x_list], [float(i) for i in y_list]
x_sum, y_sum = sum(x_list), sum(y_list)
x_bar, y_bar = x_sum / len(x_list), y_sum / len(y_list)
x_list_square = [i ** 2 for i in x_list]
x_list_square_sum = sum(x_list_square)
xy_list = [x_list[i] * y_list[i] for i in range(len(x_list))]
xy_list_sum = sum(xy_list)
m = (xy_list_sum - len(x_list) * x_bar * y_bar) / (x_list_square_sum - len(x_list) * x_bar ** 2)
# best y
y_best = [ (y_bar + m * (x_list[i] - x_bar)) for i in range( len(x_list) ) ]
# plot points
max_x = max(x_list)
max_y = max(y_list)
win.setworldcoordinates(0, 0, max_x, max_y)
for i in range(len(x_list)):
t.penup()
t.setposition(x_list[i], y_list[i])
t.stamp()
#plot best y
t.penup()
t.setposition(0,0)
t.color('blue')
for i in range(len(x_list)):
t.setposition(x_list[i],y_best[i])
t.pendown()
win.exitonclick()
with open('files/labdata.txt', 'r') as f:
plot_data = [aline.split() for aline in f]
plotRegression(plot_data)
I am about 5 years too late but here is my two cents.
The problem might be in the line:
t.setpos(points[0],points[1])
This is telling the turtle to go to the string value of the points[0] and points[1].
For example, if points[0] stores the value of "50" and points[1] holds the value "60" then "50" + "60" would be return the string "5060"
This line might have problems as well:
prod = points[0]*int(points[1])
This is adding the string value in points[0] to the integer value in points[1]
In this case, using the previous values points[0] would be "50" and int(points[1]) would be 60. That is 60 and not "60". So you cant add the string "50" with the integer 60.
Here is how I worked out the problem:
import turtle
import math
import statistics as stats
def get_line(means, slope, xlist):
"""Return a list of best y values."""
line = [(means[1] + slope * (xlist[x] + means[0]))
for x in range(len(xlist))]
return line
def get_mtop(xlist, ylist, n, means):
"""Return top half of m expression."""
xbyy_list = [xlist[x] * ylist[x] for x in range(len(xlist))]
xbyy_sum = sum(xbyy_list)
nby_means = n * (means[0] * means[1])
top = xbyy_sum - nby_means
return top
def get_mbot(xlist, n, means):
"""Return bottom half of m expression."""
sqr_comprehension = [x**2 for x in xlist]
sqr_sum = sum(sqr_comprehension)
nbymean_sqr = n * means[0]**2
bot = sqr_sum - nbymean_sqr
return bot
def get_mean(xlist, ylist):
"""Return a tuple that contains the means of xlist and ylist
in form of (xmean,ymean)."""
xmean = stats.mean(xlist)
ymean = stats.mean(ylist)
return xmean, ymean
def plotRegression(input_file, input_turtle):
"""Draw the plot regression.""""
infile = open(input_file, 'r')
input_turtle.shape("circle")
input_turtle.penup()
# Get a list of xcoor and a list of ycoor
xcoor = []
ycoor = []
for line in infile:
coor = line.split()
xcoor.append(int(coor[0]))
ycoor.append(int(coor[1]))
# Plot and count the points
num_points = 0
for count in range(len(xcoor)):
input_turtle.goto(xcoor[count], ycoor[count])
input_turtle.stamp()
num_points += 1
# Get the mean values of the xcoor and ycoor lists
means_tup = get_mean(xcoor, ycoor)
print(means_tup)
# Get the value for M
mtop = get_mtop(xcoor, ycoor, num_points, means_tup)
mbot = get_mbot(xcoor, num_points, means_tup)
m = mtop / mbot
print(m)
# Draw the line
yline = get_line(means_tup, m, xcoor)
input_turtle.color("green")
input_turtle.goto(xcoor[0], yline[0])
input_turtle.pendown()
for x in range(len(xcoor)):
print(xcoor[x], yline[x])
input_turtle.goto(xcoor[x], yline[x])
input_turtle.hideturtle()
def main():
"""Create the canvas and the turtle. Call the function(s)"""
# Set up the screen
sc = turtle.Screen()
sc.setworldcoordinates(0, 0, 100, 100)
sc.bgcolor("black")
# Create the turtle
Donatello = turtle.Turtle()
Donatello.color("purple")
# Run plot Regression
labdata = """C:\\Users\\user\\pathtofile\\labdata.txt"""
plotRegression(labdata, Donatello)
sc.exitonclick()
if __name__ == "__main__":
main()
I don't know if this is the correct slope but it seems to be in the right direction. Hopefully this helps some one who has the same problem.
Related
Here is my code. In the calculateOptimalLambda() function, I am attempting to declare a copy of n and
store it as m, remove one point from m, and make some calculations and a graph. Then, the loop should
restart, make a fresh copy of m, remove the next point, and so on.
However, when in the next iteration
of the loop, a point has been removed. Eventually, I run out of points to remove, and I get an error.
How do I declare a fresh copy of m so I can remove the next point?
import numpy as np
from matplotlib import pyplot as plt
class Data:
def __init__(self, points, sigma, lamda):
self.points = points
self.sigma = sigma
self.sample = np.random.uniform(-1,1, (points, 2))
self.transformedData = np.ones((points, 5))
self.weight = np.zeros((5,1))
self.lamda = lamda
def changeLamda(self,x):
self.lamda = x
def removePoint(self, x):
self.points = self.points - 1
self.sample = np.delete(self.sample, x, 0)
self.transformedData = np.delete(self.transformedData, x, 0)
def transformedFunction(self, x):
transformedData = np.ones((1, 5))
transformedData[0,1] = x
transformedData[0,2] = 0.5 * (3*x**2 -1)
transformedData[0,3]= 0.5 * (5*x**3 - 3*x)
transformedData[0,4] = 0.125 * (35*x**4 -30*x**2 + 3)
return np.dot(transformedData, self.weight)
def setY(self):
for i in range(len(self.sample[0:,0])):
self.sample[i,1] = np.random.normal(0, self.sigma) + self.sample[i,0]**2
def transform(self):
for i in range(len(self.sample[0:,0])):
self.transformedData[i,1] = self.sample[i,0]
self.transformedData[i,2] = 0.5 * (3*self.sample[i,0]**2 -1)
self.transformedData[i,3]= 0.5 * (5*self.sample[i,0]**3 - 3*self.sample[i,0])
self.transformedData[i,4] = 0.125 * (35*self.sample[i,0]**4 -30*self.sample[i,0]**2 + 3)
def calculateWeight(self):
z = n.transformedData
zProd = np.linalg.inv(np.matmul(np.transpose(z), z) + np.identity(5)*self.lamda)
next1 = np.matmul(zProd,np.transpose(z))
a = self.sample[0:,1]
a = a.reshape((-1, 1))
print(a)
self.weight = np.matmul(next1,a)
def calculateError(self):
error= (np.matmul(self.transformedData, self.weight) - self.sample[1,0:])
return error/self.points
def calculateOptimalLambda(n, L):
a = 0
for i in range(len(L)):
n.changeLamda(L[i])
for x in range(n.getPoints()):
a+=1
plt.subplot(4,5,a)
m = n
m.removePoint(x)
m.calculateWeight()
weight = m.getWeight()
error = m.calculateError()
twoD_plot(m)
print(error)
def twoD_plot(n):
t = np.linspace(-1, 1, 400)
x = np.square(t)
plt.plot(t,x,'b')
error = 0
y = x
for i in range(len(t)):
y[i] = n.transformedFunction(t[i])
error += (y[i] - t[i]**2)**2
"""print(error/len(t))"""
plt.plot(t,y,'r')
plt.scatter(n.getSample()[0:,0],n.getSample()[0:,1], c = 'g', marker = 'o')
n = Data(5,0.1,0)
n.setY()
n.transform()
n.calculateWeight()
L = [1, 0.01, 0.00001, 0]
calculateOptimalLambda(n, L)
plt.show()
I have been using matplotlib from python to show the animation of 1D wave equation.But I got a problem of making the animation.I want the image of the wave to change with time.It means that I may need a loop to form many different pictures of the wave equation.But it seems that the time cannot be put into the wave functions ,so the images do not change at all.Please help me with the mistake that I made.
Here are the codes that I wrote:(Part of the codes comes from the book "Python Scripting for Computational Science")
from numpy import zeros,linspace,sin,pi
import matplotlib.pyplot as mpl
def I(x):
return sin(2*x*pi/L)
def f(x,t):
return sin(x*t)
def solver0(I,f,c,L,n,dt,tstop):
# f is a function of x and t, I is a function of x
x = linspace(0,L,n+1)
dx = L/float(n)
if dt <= 0:
dt = dx/float(c)
C2 = (c*dt/dx)**2
dt2 = dt*dt
up = zeros(n+1)
u = up.copy()
um = up.copy()
t = 0.0
for i in range(0,n):
u[i] = I(x[i])
for i in range(1,n-1):
um[i] = u[i]+0.5*C2*(u[i-1] - 2*u[i] + u[i+1]) + dt2*f(x[i],t)
um[0] = 0
um[n] = 0
while t <= tstop:
t_old = t
t += dt
#update all inner points:
for i in range(1,n-1):
up[i] = -um[i] + 2*u[i] + C2*(u[i-1] - 2*u[i] + u[i+1]) + dt2*f(x[i],t_old)
#insert boundary conditions:
up[0] = 0
up[n] = 0
#update data structures for next step
um = u.copy()
u = up.copy()
return u
c = 3.0 #given by myself
L = 10
n = 100
dt = 0
tstart = 0
tstop = 6
x = linspace(0,L,n+1)
t_values = linspace(tstart,tstop,31)
mpl.ion()
y = solver0(I, f, c, L, n, dt, tstop)
lines = mpl.plot(x,y)
mpl.axis([x[0], x[-1], -1.0, 1.0])
mpl.xlabel('x')
mpl.ylabel('y')
counter = 0
for t in t_values:
y = solver0(I,f,c,L,n,dt,tstop)
lines[0].set_ydata(y)
mpl.draw()
mpl.legend(['t=%4.1f' % t])
mpl.savefig('sea_%04d.png' %counter)
counter += 1
Maybe that's what you need?
y = solver0(I,f,c,L,n,dt,t)
This question already has answers here:
Why doesn't calling a string method (such as .replace or .strip) modify (mutate) the string?
(3 answers)
Closed 7 years ago.
I am having trouble getting my code to run. I keep getting the error that my x variable such as 'hsGPA' is not defined. Below is my code. Ive tried the solutions posted on the pother thread and none have helped so please don't mark this as a duplicate. THANKS!
def readData(fileName):
hsGPA = [] #High School GPA
mathSAT = [] #Math SAT scores
crSAT = [] #Verbal SAT scores
collegeGPA = [] #College GPA
FullList=[]
inputFile = open(fileName, 'r', encoding = 'utf-8')
for line in inputFile:
FullList=line.split(',')
hsGPA.append(float(FullList[0]))
mathSAT.append(int(FullList[1]))
crSAT.append(int(FullList[2]))
collegeGPA.append(float(FullList[3]))
return hsGPA, mathSAT, crSAT, collegeGPA
def plotData(hsGPA, mathSAT, crSAT, collegeGPA):
GPA1 = [] #High School GPA
Score1 = [] #Math SAT scores
Score2= [] #Verbal SAT scores
GPA2 = [] #College GPA
hsGPA, mathGPA, crSAT, collegeGPA = readData('SAT.txt')
pyplot.figure(1)
pyplot.subplot(4,1,1)
for line in range(len(hsGPA)):
GPA1.append(line)
pyplot.plot(GPA1,hsGPA)
pyplot.subplot(4,1,2)
for line in range(len(mathSAT)):
Score1.append(line)
pyplot.plot(Score1,mathSAT)
pyplot.subplot(4,1,3)
for line in range(len(crSAT)):
Score2.append(line)
pyplot.plot(Score2,crSAT)
pyplot.subplot(4,1,4)
for line in range(len(collegeGPA)):
GPA2.append(line)
pyplot.plot(GPA2,collegeGPA)
pyplot.show()
def LinearRegression(xList, yList):
'''
This function finds the constants in the y = mx+b, or linear regression
forumula
xList - a list of the x values
yList - a list of the y values
m - the slope f the line
b - where the line intercepts the y axis
'''
n = len(xList)
sumX = 0
sumXX = 0
sumXY = 0
sumY = 0
for index in range(n):
sumX += xList[index]
sumXY += xList[index] * yList[index]
sumXX += xList[index]**2
sumY += yList[index]
#the components needed to find m and b
m = (n*(sumXY - (sumX*sumY)))/(n*(sumXX - (sumX**2)))
b = (sumY - (m*sumX))/n
#actually implements formula
return m, b
def plotRegression(x,y, xLabel, yLabel):
ScoreT = []
pyplot.scatter(x,y)
m,b = linearRegression(xList,yList)
minX = min(x)
maxX = max(x)
pyplot.plot([minX, maxX], [m * minX + b, m * maxX + b], color ='red')
pyplot.xlabel(xLabel)
pyplot.ylabel(yLabel)
pyplot.show()
for index in range(len(mathSAT)):
sumscore = mathSAT[index] + crSAT[index]
ScoreT.append(sumscore)
return ScoreT
def rSquared(x,y,m,b):
n = len(x)
R=0
sumS=0
sumT=0
sumY=0
for index in range(n):
a=(y[index]-((m*x[index])+b))**2
sumS = sumS+a
for index in range(len(y)):
sumY = sumY= y[index]
MeanY= sumY/(len(y))
e=(y[index]-MeanY)**2
sumT = sumT+e
m,b= LinearRegression(xList, yList)
RG=1-(sumS/sumT)
def main():
print(readData('SAT.txt'))
plotData(*readData('SAT.txt'))
plotRegression(hsGPA,collegeGPA, 'highGPA', 'collegeGPA')
plotRegression(mathSAT,collegeGPA, 'highGPA' , 'collegeGPA')
plotRegression(crSAT,collegeGPA, 'highGPA' , 'collegeGPA')
plotRegression(ScoreT,collegeGPA, 'highGPA' , 'collegeGPA')
main()
It's giving the error in main, after plotRegression for each of the x variables. Please Help! Thanks!
Try this:
def plotRegression(x,y, xLabel, yLabel):
# I deleted ScoreT = [] here
pyplot.scatter(x,y)
m,b = linearRegression(x,y)
minX = min(x)
maxX = max(x)
pyplot.plot([minX, maxX], [m * minX + b, m * maxX + b], color ='red')
pyplot.xlabel(xLabel)
pyplot.ylabel(yLabel)
pyplot.show()
# I deleted the loop and return statement here
# ....
def main():
data = readData('SAT.txt')
print(data)
plotData(*data)
hsGPA, mathSAT, crSAT, collegeGPA = data
# added ScoreT calculation here
ScoreT = [sum(x) for x in zip(mathSAT, crSAT)]
plotRegression(hsGPA,collegeGPA, 'highGPA', 'collegeGPA')
plotRegression(mathSAT,collegeGPA, 'highGPA' , 'collegeGPA')
plotRegression(crSAT,collegeGPA, 'highGPA' , 'collegeGPA')
plotRegression(ScoreT,collegeGPA, 'highGPA' , 'collegeGPA')
In your main(), hsGPA is never defined. It's defined inside other function and is not shared in the global context. So main cannot access it.
You need to it from readData()'s return
I'm writing a program that utilizes Euler's Method to calculate whether or not an asteroid's orbit will result in a collision with Earth. At the end of each iteration of the main loop, there is an if statement that uses the distance between the asteroid and earth to determine whether or not a collision would have occurred. When I try running the program I get a Overflow error: numerical result is out of range, I assume that this is due to the fact that I'm using trigonometric functions to convert to and out of polar coordinates and was wondering how I would restrict the size of the floating point values returned by these functions so as to fix the error?
EDIT: Here's the exception:
Traceback (most recent call last):
File "/home/austinlee/eclipse/plugins/org.python.pydev_2.7.0.2013032300/pysrc/pydevd.py", line 1397, in <module>
debugger.run(setup['file'], None, None)
File "/home/austinlee/eclipse/plugins/org.python.pydev_2.7.0.2013032300/pysrc/pydevd.py", line 1090, in run
pydev_imports.execfile(file, globals, locals) #execute the script
File "/home/austinlee/workspace/test/src/orbit.py", line 72, in <module>
if( Dist(x_a, x_e, y_a, y_e) < d_close):
File "/home/austinlee/workspace/test/src/orbit.py", line 37, in Dist
return sqrt((b-a)**2+(d-c)**2)
OverflowError: (34, 'Numerical result out of range')
Here's the code:
from math import *
##position of earth and ast. relative to sun, units in m/s/kg
r_earth = 1.4959787E11
x_e = r_earth
y_e = 0
v_ye = 29784.3405
v_xe = 0
x_a = 1.37801793E11
y_a = 2.31478719E11
v_ya = -14263.6905
v_xa = -8490.32975
##constants- masses and radius's of objects
G = 6.67384E-11
M_sun = 1.988500E30
M_earth = 5.9726E24
R_earth = 6371.0E3
M_ast = 1.30E11
R_ast = 250
t = 0
delta_t = 10
t_max = 10000000
a_xe = 0
a_ye = 0
a_xa = 0
a_ya = 0
##Define Acceleration due to Gravity and Distance Formulas
def Grav(a,b):
return (G*a)/(b**2)
def Dist(a,b,c,d):
return sqrt((b-a)**2+(d-c)**2)
##Derived Constants
t_close = 0
d_close = Dist(x_a,x_e,y_a,y_e)
r_a = Dist(0,x_a,0,y_a)
theta_e = 0
theta_a = atan2(y_a,x_a)
v_angle = sqrt(v_xa**2+v_ya**2)/r_a
v_r1 = v_angle
v_r = sqrt(v_xa**2+v_ya**2)
T = 2* pi/(365*24*3600)
a_r = v_xa**2+v_ya**2
a_theta = (-Grav(M_sun, Dist(x_a,0,y_a,0))-Grav(M_earth,Dist(x_a,x_e,y_a,y_e)))**2-a_r**2
## Main Loop- assuming constant, circular orbit for earth (i.e M_ast is negligible)
for t in range(0, t_max):
t += delta_t
theta_e = T*t
x_e = r_earth*cos( theta_e )
y_e = r_earth*sin( theta_e )
## Convert asteroid parameters into polar coordinates and solve using Euler's Method
a_r = v_xa**2+v_ya**2
a_theta = (-Grav(M_sun, Dist(x_a,0,y_a,0))-Grav(M_earth,Dist(x_a,x_e,y_a,y_e)))**2-a_r**2
v_r1 = v_r
v_r += (a_r + r_a*v_angle**2)*delta_t
v_angle += (a_theta - 2*v_r1*v_angle)* delta_t
theta_a += r_a*theta_a*delta_t
r_a += v_r*delta_t
x_a = r_a*cos( theta_a)
y_a = r_a*sin( theta_a)
## Test for minimum distance
if( Dist(x_a, x_e, y_a, y_e) < d_close):
d_close = Dist( x_a, x_e, y_a, y_e)
t_close = t/(3600*24)
continue
##Print Results:
print "d_close: ", d_close/1000, "km"
print "t_close: ", t_close
if( d_close < R_earth):
print "Impact: Y"
else:
print "Impact: N"
Thanks in advance!
The problem is in your Dist function. When you calculate the distance between two points, you calculate the squared distance as an intermediate. That intermediate value can overflow for moderately large distances. Wikipedia has a nice discussion of the problem and its solution. In short, the following replacement for the dist function will solve your immediate problem:
def Dist(a,b,c,d):
x = float(b - a)
y = float(d - c)
u = min(x, y)
v = max(x, y)
return abs(v) * sqrt(1 + (u/v)**2)
It's just a mathematically equivalent function that avoids calculating the squared distance as an intermediate. After fixing this overflow error, I got two more that can be fixed using similar techniques. I changed your Grav function to this:
def Grav(a,b):
return (G*a/b)/(b)
and v_r formula to:
v_r += (a_r/v_angle + r_a*v_angle)*delta_t*v_angle
from your original:
v_r += (a_r + r_a*v_angle**2)*delta_t
However, there are still problems. Once I make those changes I am able to avoid the overflow errors, but eventually get a domain error in the cos function when theta_a gets too large. If theta_a is what I think it is, you can fix this last problem by adding a mod 2*pi, like this:
theta_a += r_a*theta_a*delta_t % (2*pi)
in place of:
theta_a += r_a*theta_a*delta_t
Below is the working code after all changes. I'm not sure if it's right, but there are no errors raised.
from math import *
##position of earth and ast. relative to sun, units in m/s/kg
r_earth = 1.4959787E11
x_e = r_earth
y_e = 0
v_ye = 29784.3405
v_xe = 0
x_a = 1.37801793E11
y_a = 2.31478719E11
v_ya = -14263.6905
v_xa = -8490.32975
##constants- masses and radius's of objects
G = 6.67384E-11
M_sun = 1.988500E30
M_earth = 5.9726E24
R_earth = 6371.0E3
M_ast = 1.30E11
R_ast = 250
t = 0
delta_t = 10
t_max = 10000000
a_xe = 0
a_ye = 0
a_xa = 0
a_ya = 0
##Define Acceleration due to Gravity and Distance Formulas
def Grav(a,b):
return (G*a/b)/(b) #Changed by jcrudy
def Dist(a,b,c,d): #Changed by jcrudy
x = float(b - a)
y = float(d - c)
u = min(x, y)
v = max(x, y)
return abs(v) * sqrt(1 + (u/v)**2)
# return sqrt((b-a)**2+(d-c)**2)
##Derived Constants
t_close = 0
d_close = Dist(x_a,x_e,y_a,y_e)
r_a = Dist(0,x_a,0,y_a)
theta_e = 0
theta_a = atan2(y_a,x_a)
v_angle = sqrt(v_xa**2+v_ya**2)/r_a
v_r1 = v_angle
v_r = sqrt(v_xa**2+v_ya**2)
T = 2* pi/(365*24*3600)
a_r = v_xa**2+v_ya**2
a_theta = (-Grav(M_sun, Dist(x_a,0,y_a,0))-Grav(M_earth,Dist(x_a,x_e,y_a,y_e)))**2-a_r**2
## Main Loop- assuming constant, circular orbit for earth (i.e M_ast is negligible)
for t in range(0, t_max):
t += delta_t
theta_e = T*t
x_e = r_earth*cos( theta_e )
y_e = r_earth*sin( theta_e )
## Convert asteroid parameters into polar coordinates and solve using Euler's Method
a_r = v_xa**2+v_ya**2
a_theta = (-Grav(M_sun, Dist(x_a,0,y_a,0))-Grav(M_earth,Dist(x_a,x_e,y_a,y_e)))**2-a_r**2
v_r1 = v_r
v_r += (a_r/v_angle + r_a*v_angle)*delta_t*v_angle # Changed by jcrudy
v_angle += (a_theta - 2*v_r1*v_angle)* delta_t
theta_a += r_a*theta_a*delta_t % (2*pi) # Changed by jcrudy
r_a += v_r*delta_t
x_a = r_a*cos( theta_a)
y_a = r_a*sin( theta_a)
## Test for minimum distance
if( Dist(x_a, x_e, y_a, y_e) < d_close):
d_close = Dist( x_a, x_e, y_a, y_e)
t_close = t/(3600*24)
continue
##Print Results:
print "d_close: ", d_close/1000, "km"
print "t_close: ", t_close
if( d_close < R_earth):
print "Impact: Y"
else:
print "Impact: N"
Guys I have asked this question before but did not receive a single comment or answer
I want to simulate a search algorithm on a power law graph and want to visually see the algorithm move from one node to another on the graph. How do I do that?
You can adapt this completely different code I happen to have written for Find the most points enclosed in a fixed size circle :)
The useful bit is:
It uses the basic windowing system tkinter to create a frame containing a canvas; it then does some algorithm, calling it's own 'draw()' to change the canvas and then 'update()' to redraw the screen, with a delay. From seeing how easy it is to chart in tkinter, you can perhaps move on to interactive versions etc.
import random, math, time
from Tkinter import * # our UI
def sqr(x):
return x*x
class Point:
def __init__(self,x,y):
self.x = float(x)
self.y = float(y)
self.left = 0
self.right = []
def __repr__(self):
return "("+str(self.x)+","+str(self.y)+")"
def distance(self,other):
return math.sqrt(sqr(self.x-other.x)+sqr(self.y-other.y))
def equidist(left,right,dist):
u = (right.x-left.x)
v = (right.y-left.y)
if 0 != u:
r = math.sqrt(sqr(dist)-((sqr(u)+sqr(v))/4.))
theta = math.atan(v/u)
x = left.x+(u/2)-(r*math.sin(theta))
if x < left.x:
x = left.x+(u/2)+(r*math.sin(theta))
y = left.y+(v/2)-(r*math.cos(theta))
else:
y = left.y+(v/2)+(r*math.cos(theta))
else:
theta = math.asin(v/(2*dist))
x = left.x-(dist*math.cos(theta))
y = left.y + (v/2)
return Point(x,y)
class Vis:
def __init__(self):
self.frame = Frame(root)
self.canvas = Canvas(self.frame,bg="white",width=width,height=height)
self.canvas.pack()
self.frame.pack()
self.run()
def run(self):
self.count_calc0 = 0
self.count_calc1 = 0
self.count_calc2 = 0
self.count_calc3 = 0
self.count_calc4 = 0
self.count_calc5 = 0
self.prev_x = 0
self.best = -1
self.best_centre = []
for self.sweep in xrange(0,len(points)):
self.count_calc0 += 1
if len(points[self.sweep].right) <= self.best:
break
self.calc(points[self.sweep])
self.sweep = len(points) # so that draw() stops highlighting it
print "BEST",self.best+1, self.best_centre # count left-most point too
print "counts",self.count_calc0, self.count_calc1,self.count_calc2,self.count_calc3,self.count_calc4,self.count_calc5
self.draw()
def calc(self,p):
for self.right in p.right:
self.count_calc1 += 1
if (self.right.left + len(self.right.right)) < self.best:
# this can never help us
continue
self.count_calc2 += 1
self.centre = equidist(p,self.right,radius)
assert abs(self.centre.distance(p)-self.centre.distance(self.right)) < 1
count = 0
for p2 in p.right:
self.count_calc3 += 1
if self.centre.distance(p2) <= radius:
count += 1
if self.best < count:
self.count_calc4 += 4
self.best = count
self.best_centre = [self.centre]
elif self.best == count:
self.count_calc5 += 5
self.best_centre.append(self.centre)
self.draw()
self.frame.update()
time.sleep(0.1)
def draw(self):
self.canvas.delete(ALL)
# draw best circle
for best in self.best_centre:
self.canvas.create_oval(best.x-radius,best.y-radius,\
best.x+radius+1,best.y+radius+1,fill="red",\
outline="red")
# draw current circle
if self.sweep < len(points):
self.canvas.create_oval(self.centre.x-radius,self.centre.y-radius,\
self.centre.x+radius+1,self.centre.y+radius+1,fill="pink",\
outline="pink")
# draw all the connections
for p in points:
for p2 in p.right:
self.canvas.create_line(p.x,p.y,p2.x,p2.y,fill="lightGray")
# plot visited points
for i in xrange(0,self.sweep):
p = points[i]
self.canvas.create_line(p.x-2,p.y,p.x+3,p.y,fill="blue")
self.canvas.create_line(p.x,p.y-2,p.x,p.y+3,fill="blue")
# plot current point
if self.sweep < len(points):
p = points[self.sweep]
self.canvas.create_line(p.x-2,p.y,p.x+3,p.y,fill="red")
self.canvas.create_line(p.x,p.y-2,p.x,p.y+3,fill="red")
self.canvas.create_line(p.x,p.y,self.right.x,self.right.y,fill="red")
self.canvas.create_line(p.x,p.y,self.centre.x,self.centre.y,fill="cyan")
self.canvas.create_line(self.right.x,self.right.y,self.centre.x,self.centre.y,fill="cyan")
# plot unvisited points
for i in xrange(self.sweep+1,len(points)):
p = points[i]
self.canvas.create_line(p.x-2,p.y,p.x+3,p.y,fill="green")
self.canvas.create_line(p.x,p.y-2,p.x,p.y+3,fill="green")
radius = 60
diameter = radius*2
width = 800
height = 600
points = []
# make some points
for i in xrange(0,100):
points.append(Point(random.randrange(width),random.randrange(height)))
# sort points for find-the-right sweep
points.sort(lambda a, b: int(a.x)-int(b.x))
# work out those points to the right of each point
for i in xrange(0,len(points)):
p = points[i]
for j in xrange(i+1,len(points)):
p2 = points[j]
if p2.x > (p.x+diameter):
break
if (abs(p.y-p2.y) <= diameter) and \
p.distance(p2) < diameter:
p.right.append(p2)
p2.left += 1
# sort points in potential order for sweep, point with most right first
points.sort(lambda a, b: len(b.right)-len(a.right))
# debug
for p in points:
print p, p.left, p.right
# show it
root = Tk()
vis = Vis()
root.mainloop()
You can use matplotlib for that.
Here is a simlple example of a mesh with an animated highlighted point:
import matplotlib.pyplot as plt
import time
x_size = 4
y_size = 3
# create the points and edges of the mesh
points = [(x,y) for y in range(y_size) for x in range(x_size)]
vert_edges = [((i_y*x_size)+i_x,(i_y*x_size)+i_x+1)
for i_x in range(x_size-1) for i_y in range(y_size)]
horz_edges = [((i_y*x_size)+i_x,((i_y+1)*x_size)+i_x)
for i_x in range(x_size) for i_y in range(y_size-1)]
edges = vert_edges + horz_edges
# plot all the points and edges
lines = []
for edge in edges:
x_coords, y_coords = zip(points[edge[0]], points[edge[1]])
lines.extend((x_coords, y_coords, 'g'))
plt.plot(linewidth=1, *lines)
x, y = zip(*points)
plt.plot(x, y, 'o')
# create the highlighted point
point_plot = plt.plot([0], [0], 'ro')[0]
# turn on interactive plotting mode
plt.ion()
plt.ylim(-1, y_size)
plt.xlim(-1, x_size)
# animate the highlighted point
for i_point in range(1, len(x)):
point_plot.set_xdata([x[i_point]])
point_plot.set_ydata([y[i_point]])
plt.draw()
time.sleep(0.5)
plt.show()