from Tkinter import *
from visual import *
from random import *

import time,sys,thread

from NumericUnitCell import *
from VisualSphere import *



     
class Simulation:
    nSpinsX = 4
    nSpinsY = 1

    tracerLength = 8

    uc = NumericUnitCell(nSpinsX,nSpinsY)
    vSphere = VisualSphere(nSpinsX,nSpinsY,tracerLength)
    
    dt = .001
    animDuty = 64                       # Number of cycles per animation frame

    Ja = -1.0
    Jbx = 1.8
    Jby = -1.0
        
    temp = 0.00*abs(Ja)

    MFu = 0.00*abs(Ja)
    MFd = -0.00*abs(Ja)

    paused = 1
    pause = 1

    k = 3.1416*vector(.05,0.0,0.0)
    baseSigma = .333

    dummySphere = sphere(pos=(0.0,0.0,1.0), color=(0.5,0.7,1.0), radius=0.03)

        
    def __init__(self,parent):
        self.uc.setCouplings(self.Ja, self.Jbx, self.Jby)
        self.uc.setState(self.k, self.baseSigma)

        self.toggleVarPoints = BooleanVar()           # Other placements of these variables do not work -- why?
        self.toggleVarVectors = BooleanVar()          #

        self.toggleVarPoints.set(1)
        self.toggleVarVectors.set(1)
        
             
        thread.start_new_thread(self.animSpins,(self.animDuty,))
        self.pause = 0


    def animSpins(self,animDuty):
        print '-----------------------------'
        print "Animation Started"
        print time.ctime()
      
        self.vSphere.addPoints(self.uc.getState())
        self.vSphere.addTracers(self.uc.getState())
        self.vSphere.addVectors(self.uc.getState())

        self.vSphere.togglePoints()
        self.vSphere.toggleVectors()

        while 1:
            for k in range(animDuty):
                self.paused = self.pause
                if self.paused != 1:
                    self.uc.getTorques()

                    if abs(self.MFu) != 0.0 or abs(self.MFd != 0.0):
                        self.uc.addExternalField(self.MFu,self.MFd)
                    if self.temp != 0.0:
                        self.uc.thermalize(self.temp)
                                        
                    self.uc.timeEvolveState(self.dt)
                 
            self.vSphere.updatePoints(self.uc.getState())
            self.vSphere.updateTracers(self.uc.getState())
            self.vSphere.updateVectors(self.uc.getState())

            self.dummySphere.pos = self.uc.getCommonAxis()



    def setKx(self,kx):
        self.hold()
        if (self.k.y == 0.0 and float(kx) == 0.0):
            pass
        else:
            self.k.x = float(kx)/(self.nSpinsX)
            self.reset()
        self.unhold()
      
    def setKy(self,ky):
        self.hold()
        if (self.k.x == 0.0 and float(ky) == 0.0):
            pass
        else:
            self.k.y = float(ky)/(self.nSpinsY)
            self.reset()
        self.unhold()


    def setJbx(self, Jbx):
        self.hold()
        self.Jbx = float(Jbx)
        self.uc.setCouplings(self.Ja, self.Jbx, self.Jby)
        self.unhold()

    def setJby(self, Jby):
        self.hold()
        self.Jby = float(Jby)
        self.uc.setCouplings(self.Ja, self.Jbx, self.Jby)
        self.unhold()


    def setMFu(self, MFd):
        self.hold()
        self.MFd = float(MFd)
        self.unhold()

    def setMFd(self, MFu):
        self.hold()
        self.MFu = float(MFu)
        self.unhold()

        
    def setTemp(self, temp):
        self.hold()
        self.temp = float(temp)*self.Ja
        self.unhold()

    def setDt(self, dt):
        self.hold()
        self.dt = float(dt)/10000.0
        self.unhold()


    def randomize(self):
        self.hold()
        self.uc.randomizeState()
        self.uc.timeEvolveState(self.dt)
        self.unhold()


    def reset(self):
        self.hold()
        self.uc.setState(self.k, self.baseSigma)
        self.vSphere.delTracers()
        self.unhold()

    def hold(self):
        self.pause = 1
        while self.paused == 0: pass

    def unhold(self):
        self.pause = 0



    def togglePoints(self):
        self.hold()
        self.vSphere.togglePoints()
        self.unhold()
        
    def toggleVectors(self):
        self.hold()
        self.vSphere.toggleVectors()
        self.unhold()

    def setTracerLength(self, tracerLength):
        self.hold()
        self.tracerLength = float(tracerLength)
        self.unhold()

        

######-------------------------------------------------------######
###                             TKR                             ###
        
##  Instance creation ##
tkr = Tk()
simu = Simulation(tkr)

##  TKR appearance and widget creation ##

########
tkr.wm_geometry(newGeometry="360x513+900+320")   
tkr.wm_title("Controls")

########
topFrame = Frame(tkr,relief=SUNKEN, borderwidth=0)
topFrame.grid(row=0, column=0, padx=0, pady=0)


######
toggleFrame = Frame(topFrame, relief=FLAT, borderwidth=0)
toggleFrame.grid(row=0, column=0, padx=4, pady=4)

####
modesFrame = Frame(toggleFrame, relief=FLAT, borderwidth=1)
modesFrame.grid(row=0, column=0, padx=4, pady=4)

#
modesLabel = Label(modesFrame, text="Mode Options:").grid(row=0, column=0, sticky=W)

##sigmaRepLabel = Label(modesFrame, text="Sigmas").grid(row=1, column=0, sticky=E)
##sigmaRepWidget = Checkbutton(modesFrame, text="", variable=simu.tvSigmaRep, command=simu.tSigmaRep).grid(row=1, column=1)
##
##boxRepLabel = Label(modesFrame, text="Boxes").grid(row=2, column=0, sticky=E)
##boxRepWidget = Checkbutton(modesFrame, text="", variable=simu.tv_boxRep, command=simu.t_boxRep).grid(row=2, column=1)
##
##sphereRepLabel = Label(modesFrame, text="Sphere").grid(row=3, column=0, sticky=E)
##sphereRepWidget = Checkbutton(modesFrame, text="", variable=simu.tvSphereRep, command=simu.tSphereRep).grid(row=3, column=1)

##circlesLabel = Label(modesFrame, text="Circles").grid(row=1, column=2, sticky=E)
##circlesWidget = Checkbutton(modesFrame, text="", variable=simu.tv_circles, command=simu.t_circles).grid(row=1, column=3)
##
##flattenLabel = Label(modesFrame, text="Flatten").grid(row=2, column=2, sticky=E)
##flattenWidget = Checkbutton(modesFrame, text="", variable=simu.tvFlatten, command=simu.tFlatten).grid(row=2, column=3)
##

vectorsLabel = Label(modesFrame, text="Vectors").grid(row=0, column=0, sticky=E)
vectorsWidget = Checkbutton(modesFrame, text="", variable=simu.toggleVarPoints, command=simu.toggleVectors)
vectorsWidget.grid(row=0, column=1)

pointsLabel = Label(modesFrame, text="Points").grid(row=1, column=0, sticky=E)
pointsWidget = Checkbutton(modesFrame, text="", variable=simu.toggleVarVectors, command=simu.togglePoints)
pointsWidget.grid(row=1, column=1)
#


####
##visualsFrame = Frame(toggleFrame, relief=FLAT, borderwidth=1)
##visualsFrame.grid(row=0, column=0, padx=4, pady=4)

#
##visualsLabel = Label(visualsFrame, text="Visual Options:").grid(row=0, column=0, sticky=W)
##
##tracerWidget = Scale(visualsFrame, orient=VERTICAL, from_=256, to=0, resolution=1.0, label="Tracer Length", command=lambda str: simu.setTracerLength(str))
##tracerWidget.set(simu.tracerLength)
##tracerWidget.grid(row=0, column=1)

##sublatticesLabel = Label(visualsFrame, text="Sublattices").grid(row=1, column=0, sticky=E)
##sublatticesWidget = Checkbutton(visualsFrame, text="", variable=simu.tvSublattices, command=simu.tSublattices).grid(row=1, column=1)
##
##torqueLabel = Label(visualsFrame, text="Torques").grid(row=2, column=0, sticky=E)
##torqueWidget = Checkbutton(visualsFrame, text="", variable=simu.tv_torques, command=simu.t_torques).grid(row=2, column=1)
##
##colorLabel = Label(visualsFrame, text="Colors").grid(row=3, column=0, sticky=E)
##colorWidget = Checkbutton(visualsFrame, text="", variable=simu.tv_colors, command=simu.t_colors)
##colorWidget.grid(row=3, column=1)
##colorWidget.toggle()
##
##fmFilterLabel = Label(visualsFrame, text="FM Filter").grid(row=4, column=0, sticky=E)
##fmFilterWidget = Checkbutton(visualsFrame, text="", variable=simu.tvFmFilter, command=simu.tFmFilter).grid(row=4, column=1)
###



##
simuFrame = Frame(toggleFrame, relief=FLAT, borderwidth=0)
simuFrame.grid(row=1, column=0, columnspan=2, padx=4, pady=4)

#
simuLabel = Label(simuFrame, text="Simulation:").grid(row=0, column=0, sticky=W)
##
##stripesLabel = Label(simuFrame, text="Stripes").grid(row=1, column=0, sticky=E)
##stripesWidget = Checkbutton(simuFrame, text="", variable=simu.tvStripes, command=simu.tStripes).grid(row=1, column=1)
##
randomizeWidget = Button(simuFrame, text="Randomize", command=simu.randomize).grid(row=1, column=2, padx=4, pady=2)
resetWidget = Button(simuFrame, text="Reset", command=simu.reset).grid(row=1, column=3, padx=4, pady=2)




####
scalesFrame = Frame(topFrame, relief=FLAT, borderwidth=1)
scalesFrame.grid(row=1, column=0, columnspan=2, padx=10, pady=10)

#
scalesLabel = Label(scalesFrame, text="Scales:").grid(row=0, column=0, sticky=W)

kxWidget = Scale(scalesFrame, orient=VERTICAL, from_=4.0*3.1416, to=0.0, resolution=0.05, label="kxLx", command=lambda str: simu.setKx(str))
kxWidget.set(simu.k.x)
kxWidget.grid(row=1, column=0)

kyWidget = Scale(scalesFrame, orient=VERTICAL, from_=4.0*3.1416, to=0.0, resolution=0.05, label="kyLy", command=lambda str: simu.setKy(str))
kyWidget.set(simu.k.y)
kyWidget.grid(row=1, column=1)

JbxRatioWidget = Scale(scalesFrame, orient=VERTICAL, from_=5.0, to=-5.0, resolution=0.04, label="Jbx", command=lambda str: simu.setJbx(str))
JbxRatioWidget.set(simu.Jbx)
JbxRatioWidget.grid(row=1, column=2)

JbyRatioWidget = Scale(scalesFrame, orient=VERTICAL, from_=5.0, to=-5.0, resolution=0.04, label="Jby", command=lambda str: simu.setJby(str))
JbyRatioWidget.set(simu.Jby)
JbyRatioWidget.grid(row=1, column=3)
#


####
scales2Frame = Frame(topFrame, relief=FLAT, borderwidth=1)
scales2Frame.grid(row=2, column=0, columnspan=2, padx=10, pady=10)

#
meanFieldDownWidget = Scale(scales2Frame, orient=VERTICAL, from_=1.00, to=-1.00, resolution=0.01, label="MFD", command=lambda str: simu.setMFd(str))
meanFieldDownWidget.set(simu.MFd)
meanFieldDownWidget.grid(row=0, column=0)

meanFieldUpWidget = Scale(scales2Frame, orient=VERTICAL, from_=1.00, to=-1.00, resolution=0.01, label="MFU", command=lambda str: simu.setMFu(str))
meanFieldUpWidget.set(simu.MFu)
meanFieldUpWidget.grid(row=0, column=1)

tempWidget = Scale(scales2Frame, orient=VERTICAL, from_=2.0, to=0, resolution=0.05, label="kT", command=lambda str: simu.setTemp(str))
tempWidget.set(simu.temp/simu.Ja)
tempWidget.grid(row=0, column=2)

DtWidget = Scale(scales2Frame, orient=VERTICAL, from_=200, to=0, label="dt", command=lambda str: simu.setDt(str))
DtWidget.set(simu.dt*10000.0)
DtWidget.grid(row=0, column=3)
#


##  Enter the main TKR loop, starting the interface and program ##
tkr.mainloop()


