# lc.py: Lorenz Composer 
# euler integration

print"\n\n------***Lorenz Composer***------\n"


from visual import *
from liner import *
from musical import *

def Lrnzdxdt(sigma,x,y):
	return sigma*(y-x)

def Lrnzdydt(R,x,y,z):
	return R*x-y-x*z

def Lrnzdzdt(b,x,y,z):
	return x*y-b*z

def RKinteg(sigma,R,b,y,dt):
	kx1 = dt*Lrnzdxdt(sigma,y[0],y[1])
	ky1 = dt*Lrnzdydt(R,y[0],y[1],y[2])
	kz1 = dt*Lrnzdzdt(b,y[0],y[1],y[2])
	kx2 = dt*Lrnzdxdt(sigma,y[0]+kx1/2.0,y[1]+ky1/2.0)
	ky2 = dt*Lrnzdydt(R,y[0]+kx1/2.0,y[1]+ky1/2.0,y[2]+kz1/2.0)
	kz2 = dt*Lrnzdzdt(b,y[0]+kx1/2.0,y[1]+ky1/2.0,y[2]+kz1/2.0)
	kx3 = dt*Lrnzdxdt(sigma,y[0]+kx2/2.0,y[1]+ky2/2.0)
	ky3 = dt*Lrnzdydt(R,y[0]+kx2/2.0,y[1]+ky2/2.0,y[2]+kz2/2.0)
	kz3 = dt*Lrnzdzdt(b,y[0]+kx2/2.0,y[1]+ky2/2.0,y[2]+kz2/2.0)
	kx4 = dt*Lrnzdxdt(sigma,y[0]+kx3,y[1]+ky3)
	ky4 = dt*Lrnzdydt(R,y[0]+kx3,y[1]+ky3,y[2]+kz3)
	kz4 = dt*Lrnzdzdt(b,y[0]+kx3,y[1]+ky3,y[2]+kz3)
	y[0] = y[0]+(kx1+2.0*kx2+2.0*kx3+kx4)/6.0
	y[1] = y[1]+(ky1+2.0*ky2+2.0*ky3+ky4)/6.0
	y[2] = y[2]+(kz1+2.0*kz2+2.0*kz3+kz4)/6.0
	y_new = vector(y[0],y[1],y[2])
	return y_new

dt = 0.001
y = vector(-10,-10,30)
print("For the following parameters, enter 0 for the default value...")
mus = input("enter 1 for chromatic scale, 0 for major scale:")
sigma = input("sigma? (10.0) :")
if sigma == 0:
	sigma = 10.0
R = input("R? (28.0) :")
if R == 0:
	R = 28.0
b = input("b? (8.0/3.0) :")
if b == 0:
	b = (8.0/3.0)
iterations = input("iterations? (10000) :")
if iterations == 0:
	iterations = 10000
span = iterations*dt
numnotes = input("number of notes? (20) :")
if numnotes == 0:
	numnotes = 20
notes = span/numnotes
fpoint1 = sqrt(b*(R-1))
fpoint2 = -1 * fpoint1
x_interval = fpoint1 / 3.5
if (mus == 1):
	x_interval = fpoint1 / 6

print """
Opening Window...
Standard Visual Controls
"""
scene.title = "Lorenz Composer"
scene.center = vector(0,0,25)
scene.height = 600
scene.width = 600
scene.background = (0,0,0)
scene.forward = (0,1,-0.5)
scene.lights = [ vector(-0.25, -0.5, -1.0) ,vector(0.25, 0.5, 1.0) ]

curve_calc(R,b,mus)

lorenz = curve(color = color.black, radius=0.1)

song=[]
ballnum=0
theta = 7.0 * pi / 4.0

for t in arange(0,span,dt):
  y = RKinteg(sigma,R,b,y,dt)
  xt = cos(theta) * y[0] - sin(theta) * y[1]
  yt = sin(theta) * y[0] + cos(theta) * y[1]
  lorenz.append( pos=(xt,yt,y[2]), color=(1,1,1) )
  if (t>=ballnum*(float(span)/float(numnotes))):
	  c = ballnum*(1.0/numnotes)
	  sphere (pos=(xt,yt,y[2]), radius=1, color=(c,0.1,1-c))
	  song.append([tab(int(.5+(y[0]+fpoint1*3)/x_interval),mus),4])
	  ballnum += 1
song.append(['C4',1])
music(song)
print "rendering finished: result.wav"
