#!/usr/bin/python

import os,thread,sys,string,time,glob,traceback,types
import copy as pycopy

from Tkinter import *
from tkMessageBox import askokcancel
from tkMessageBox import showerror
from tkFileDialog import asksaveasfilename 
from tkFileDialog import askopenfilename

from numpy import *

from pNbody import *
from pNbody import param
from pNbody import io
from pNbody import geometry as geo
from pNbody import liblog
from pNbody import mpi


try:
  from optparse import OptionParser
except ImportError:
  from optik import OptionParser



########################################  
#					  
# parser				  
#					  
######################################## 



def parse_options():

  usage = "usage: %prog [options] file"
  parser = OptionParser(usage=usage)
  
  parser.add_option("-t",
		   action="store", 
		   dest="ftype",
		   type="string",
		   default = None,		   
		   help="type of the file",	 
		   metavar=" TYPE")    

  parser.add_option("--stereo",
                    action="store_true", 
		    dest="stereo", 
		    default=0,
                    help="enable stereo view")

  parser.add_option("-p",
  		    action="store", 
  		    dest="palette",
  		    type="string",
		    default = None,		    
  		    help="palette name",       
  		    metavar=" PALETTE NAME")
		    
  parser.add_option("-f",
  		    action="store", 
  		    dest="parameters_file",
  		    type="string",
		    default = None,		    
  		    help="parameter file",       
  		    metavar=" FILE NAME")
		    
  parser.add_option("-u",
  		    action="store", 
  		    dest="unitsparameters_file",
  		    type="string",
		    default = None,		    
  		    help="unitsparameter file",       
  		    metavar=" FILE NAME")


  parser.add_option("--fullscreen",
                    action="store_true", 
		    dest="fullscreen", 
		    default=0,
                    help="fullscreen mode")

  parser.add_option("--pio",
                    action="store_true", 
		    dest="pio", 
		    default=0,
                    help="parallel io mode")
		    		    		    
  (options, args) = parser.parse_args()
   
  if len(args) == 0:
    #print "you must specify a filename"
    #sys.exit(0)
    file = None
  else:  
    #file = args[0]
    file = args  
  
  return file,options





########################################  
#					  
# History class				  
#					  
######################################## 

class History:
  '''
  History class
  '''

  def __init__(self,file):

    if os.path.isfile(file):
      self.f = open(file,'r+')
      self.cmds = self.f.readlines()
    else:
      self.f = open(file,'w')
      self.cmds = []
      
    self.file = file  
    self.index = len(self.cmds)    

  def add(self,cmd):
    self.cmds.append(cmd)
    self.f.write('%s\n'%cmd)
    self.f.flush()
    # force index to be the last index + 1
    self.index = len(self.cmds)
    
  def get(self):
    return self.cmds[self.index]  

  def up(self):
    if self.index < len(self.cmds)-1:
      self.index = self.index + 1
  
  def down(self):
    if self.index > 0:
      self.index = self.index - 1
          
  def close(self):
    self.f.close()  
  
  def write(self):
    f = open(self.file,'w')
    for cmd in self.cmds:
      f.write('%s\n'%cmd)
    f.close()  
    
  

########################################  
#					  
# Ginteractor classes				  
#					  
######################################## 

class Ginter:
  '''
  abstract Interactor class
  '''
  
  def __init__(self):
    self.M1 = self.R1
    self.M2 = self.R2
    self.M3 = self.R3
    
  def set_mode(self,mode):
    if   mode == 'r':
      self.M1 = self.R1
      self.M2 = self.R2
      self.M3 = self.R3  
    elif mode == 't':
      self.M1 = self.T1
      self.M2 = self.T2
      self.M3 = self.T3      
    
  def R1(self,obs,dx,dy,dxw,dyw):
    return obs       
  
  def R2(self,obs,dx,dy,dxw,dyw):
    return obs    

  def R3(self,obs,dx,dy,dxw,dyw):
    return obs  
        
  def T1(self,obs,dx,dy,dxw,dyw):
    return obs  

  def T2(self,obs,dx,dy,dxw,dyw):
    return obs  
    
  def T3(self,obs,dx,dy,dxw,dyw):
    return obs          
     
     
class Ginter_xp(Ginter):
  '''
  
   - - xp fixed - -
  
  move x0 with respect to xp
  '''
  
  def R1(self,obs,dx,dy,dxw,dyw):
    '''
    rotation around xp (obs[1]) of axis e3-e0
    rotation around xp (obs[1]) of axis e2-e0
    '''    
    angle_x = -dxw*pi/180.
    angle_y =  dyw*pi/180.
    axis_x = (obs[3]-obs[0])
    axis_y = (obs[2]-obs[0])
    obs = geo.rotate(obs,angle=angle_x,axis=axis_x,point=obs[1])
    obs = geo.rotate(obs,angle=angle_y,axis=axis_y,point=obs[1])
    return obs  
    
  def R2(self,obs,dx,dy,dxw,dyw):
    '''
    rotation around xp (obs[1]) of axis e1-e0
    '''
    dzw = (dxw+dyw)/2.
    angle_z = -dzw*pi/180.
    axis_z = (obs[1]-obs[0])
    obs = geo.rotate(obs,angle=angle_z,axis=axis_z,point=obs[1])
    return obs  
    
  def T1(self,obs,dx,dy,dxw,dyw):  
    '''
    idem R1
    '''
    return self.R1(obs,dx,dy,dxw,dyw)
    

  def T2(self,obs,dx,dy,dxw,dyw):  
    '''
    translation along axis e1-e0
    '''
    dz = (dx+dy)/2.
    axis_z = (obs[1]-obs[0])/geo.norm(obs[1]-obs[0])
    obs[0] = obs[0] + axis_z*dz
    obs[2] = obs[2] + axis_z*dz
    obs[3] = obs[3] + axis_z*dz
    return obs      
        
    
class Ginter_x0(Ginter):
  '''
  
  - - x0 fixed - - 
  
  move xp with respect to x0
  '''
      
  def R1(self,obs,dx,dy,dxw,dyw):
    '''
    rotation around xp (obs[0]) of axis e3-e0
    rotation around xp (obs[0]) of axis e2-e0
    '''
    angle_x = -dxw*pi/180.
    angle_y =  dyw*pi/180.
    axis_x = (obs[3]-obs[0])
    axis_y = (obs[2]-obs[0])
    obs = geo.rotate(obs,angle=angle_x,axis=axis_x,point=obs[0])
    obs = geo.rotate(obs,angle=angle_y,axis=axis_y,point=obs[0])
    return obs  
    
  def R2(self,obs,dx,dy,dxw,dyw):
    '''
    rotation around xp (obs[0]) of axis e1-e0
    '''
    dzw = (dxw+dyw)/2.
    angle_z = -dzw*pi/180.
    axis_z = (obs[1]-obs[0])
    obs = geo.rotate(obs,angle=angle_z,axis=axis_z,point=obs[0])
    return obs  

  def T1(self,obs,dx,dy,dxw,dyw):
    '''
    idem R1
    '''
    return self.R1(obs,dx,dy,dxw,dyw)
    
    
  def T2(self,obs,dx,dy,dxw,dyw):
    '''
    translation along axis e1-e0
    '''
    dz = (dx+dy)/2.
    axis_z = (obs[1]-obs[0])/geo.norm(obs[1]-obs[0])
    obs[1] = obs[1] + axis_z*dz
    return obs  
    
class Ginter_x0xp(Ginter):
  '''
  
   - - x0xp fixed - -
  
  move x0 and xp
  '''
  

  def T1(self,obs,dx,dy,dxw,dyw):
    '''
    translation along axis e2-e0
    translation along axis e3-e0
    '''
    
    dx = dx
    dy = dy
	
    axis_x = (obs[2]-obs[0])/geo.norm(obs[2]-obs[0])
    axis_y = (obs[3]-obs[0])/geo.norm(obs[3]-obs[0])
    
    obs = obs + axis_x*dx
    obs = obs + axis_y*dy
        
    return obs  

    
  def T2(self,obs,dx,dy,dxw,dyw):
    '''
    translation along axis e1-e0
    '''
    
    dz = dx
    
    axis_z = (obs[1]-obs[0])/geo.norm(obs[1]-obs[0])
    
    obs = obs + axis_z*dz
    
    return obs  
  
########################################  
#					  
# Gcan class				  
#					  
########################################  
class Gcan(Canvas):
  '''
  extended tkinter canvas object
  
  self.obs   : position of the observer (very useful frame)
  self.lab   : label coord (arbitrary and unused frame)
  '''

  ###########################
  def init(self,params,root=None,eye=None,twin=None,labsize=1):
  ###########################  

    self.root = root
    self.eye = eye
    self.twin = twin
    self.init_params(params)  
    self.labsize = labsize
                        
    # init coord and lab
    self.init_obs()
    self.init_lab()

    # link an interactor
    self.interactor = Ginter_xp()  
    
    # bind events
    self.bindevents()    

  ###########################
  def init_params(self,params):
  ########################### 
    '''
    init params
    '''
    self.params = params
    
    if self.params.get('obs')!=None:
      self.obs       = array(self.params.get('obs'),float)
    else:
      self.obs = None  
    
    if self.params.get('xp')!=None:
      self.xp       = array(self.params.get('xp'),float)
    else:
      self.xp = None
    
    if self.params.get('x0')!=None:    
      self.x0       = array(self.params.get('x0'),float)
    else:
      self.x0 = None
        
    self.alpha    = self.params.get('alpha')
    
    if self.twin == None:
      self.eye      = self.params.get('eye')
    
    self.dist_eye = self.params.get('dist_eye') 
    self.r_obs    = self.params.get('r_obs') 
    self.foc      = self.params.get('foc') 
    self.view     = self.params.get('view')	# ?
    self.persp    = self.params.get('persp')  
    
    self.size     = self.params.get('size')
    self.shape    = self.params.get('shape')
    self.clip     = self.params.get('clip')
    self.cut      = self.params.get('cut')
    
        
  ###########################
  def set_interactor(self,mode='xp'):
  ########################### 
    '''
    set type of interactor
    '''
    
    if    mode == 'xp':
      self.interactor = Ginter_xp() 
    elif  mode == 'x0':
      self.interactor = Ginter_x0() 
    elif  mode == 'x0xp':
      self.interactor = Ginter_x0xp()     
    else:
      self.interactor = Ginter_xp() 
    

  ###########################
  def set_interactor_mode(self,mode='r'):
  ########################### 
    '''
    set interactor mode
    '''
    self.interactor.set_mode(mode)

      
  ###########################
  def init_obs(self):
  ###########################
    '''
    initialize the coord system
    '''
    if self.obs == None:
      self.obs = geo.get_obs(x0=self.x0,xp=self.xp,alpha=self.alpha,view=self.view,r_obs=self.r_obs)  
        
  ###########################
  def init_lab(self):
  ########################### 
    '''
    init the label (pointer towards an arbitrary center)
    
    # ref. frame
    x0,y0,z0
    xp,yp,zp
    
    '''
    
    e0 = array([0,0,0],float)
    e1 = array([1,0,0],float)  
    e2 = array([0,1,0],float)  
    e3 = array([0,0,1],float)  
    
    e4 = e1*1.2
    e5 = e2*1.2
    e6 = e3*1.2
         
    self.lab =  array([e0,e1,e2,e3,e4,e5,e6],float)*self.labsize 
  
  ###########################
  def set_view(self,mode):
  ########################### 
    '''
    Set where obs look at$
    
    mode = xz,xy,xz
    '''
    
    r_obs = sqrt((self.obs[0][0]-self.obs[1][0])**2+(self.obs[0][1]-self.obs[1][1])**2+(self.obs[0][2]-self.obs[1][2])**2)
    obs = geo.get_obs(x0=None,xp=None,alpha=None,view=mode,r_obs=r_obs)
    self.obs = obs-obs[1]+self.obs[1]

      
  ###########################
  def draw_lab(self):
  ###########################    

    if self.obs!=None:

      try:
       self.del_lab()
      except:
        pass

      lab = pycopy.deepcopy(self.lab)
      lab = concatenate((lab,array([self.obs[1]])))
    
      # model-view transformation (could be better)
      lab = geo.expose(lab,self.obs,eye=self.eye,dist_eye=self.dist_eye,foc=self.foc)
          
      # projection transformation
      if self.persp == 'on':
        lab = geo.frustum(lab,self.clip,self.size)
      else:
        lab = geo.ortho(lab,self.clip,self.size)
    
      # flag point outside 1:1:1
      if self.cut=='yes':
        c = logical_not((fabs(lab[:,0])>1) | (fabs(lab[:,1])>1) | (fabs(lab[:,2])>1))
      else:
        c = ones(len(lab))
            
      # viewport transformation
      lab = geo.viewport(lab,self.shape)
    
    
      # reference frame
      for i in range (1,4):	  # reference frame
        if c[i]:
          x1,y1 = lab[0][0],lab[0][1]
          x2,y2 = lab[i][0],lab[i][1]
          id = self.create_line(x1,y1,x2,y2,tag='lab',fill="red") 
           
      # label  
    
      if c[4]:  
        x,y = lab[4][0],lab[4][1]
        id = self.create_text(x,y,text="x",tag='lab',fill="red")  

      if c[5]: 
        x,y = lab[5][0],lab[5][1]
        id = self.create_text(x,y,text="y",tag='lab',fill="red")  
   
      if c[6]:  
        x,y = lab[6][0],lab[6][1]
        id = self.create_text(x,y,text="z",tag='lab',fill="red") 
    
      # pointer
      if c[7]: 
        x,y = lab[7][0],lab[7][1]
        id = self.create_text(x,y,text="o",tag='lab',fill="green")     

  ###########################
  def draw_marker(self,lab):
  ###########################    

    self.delete('mrk')
    
    lab = array([lab,lab])
    
    # model-view transformation (could be better)
    lab = geo.expose(lab,self.obs,eye=self.eye,dist_eye=self.dist_eye,foc=self.foc)
        
    # projection transformation
    if self.persp == 'on':
      lab = geo.frustum(lab,self.clip,self.size)
    else:
      lab = geo.ortho(lab,self.clip,self.size)
    
    # flag point outside 1:1:1
    if self.cut=='yes':
      c = logical_not((fabs(lab[:,0])>1) | (fabs(lab[:,1])>1) | (fabs(lab[:,2])>1))
    else:
      c = ones(len(lab))

          
    # viewport transformation
    lab = geo.viewport(lab,self.shape)
    
    # pointer
    if c[0]: 
      x,y = lab[0][0],lab[0][1]
      id = self.create_text(x,y,text="X",tag='mrk',fill="yellow")      
          

  ###########################
  def change_lab_size(self,size):
  ########################### 
      
    self.labsize = size  
      
    # translate to the origin
    dl = self.lab[0]
    self.lab = self.lab - dl
    
    # get the old norm
    norm = sqrt(self.lab[1][0]**2 + self.lab[1][1]**2 + self.lab[1][2]**2)
    fact = self.labsize/norm
				     			    
    # scale it
    self.lab = self.lab*fact	 
    	 
    # translate back				     			    
    self.lab = self.lab + dl		    


  ###########################
  def del_lab(self):
  ###########################   
    '''
    delete lab
    '''
    self.delete('lab')

  ###########################
  def del_object(self,obj):
  ###########################   
    
    self.delete(obj)   


  ###########################
  def bindevents(self):
  ########################### 
    '''
    bind events
    '''

    #self.bind('<Button-3>',self.click1)
    #self.bind('<Button-3>',self.click2)
    self.bind('<Button-3>',self.click3)
    
    self.bind('<Enter>',self.enter_window)			  
    self.bind('<Leave>',self.leave_window)
 
    # is defined in the master
    #self.bind('<Motion>',self.move)	
  
    self.bind('<B1-Motion>',self.move1)
    self.bind('<B2-Motion>',self.move2)
    #self.bind('<B3-Motion>',self.move3)
    										      
    #self.bind('<Double-1>',self.double1)
    #self.bind('<Double-2>',self.double2)				  
    #self.bind('<Double-3>',self.double3)
    
    

  ###########################
  def click3(self,event):
  ########################### 
    self.root.redisplay()

  ###########################
  def enter_window(self,event):
  ########################### 
    self.last_event = event
    self.draw_lab()
    if self.twin!=None:
      self.twin.draw_lab()
    
  ###########################
  def leave_window(self,event):
  ########################### 
    self.last_event = event
    self.del_lab()
    if self.twin!=None:
      self.twin.del_lab()    

  ###########################
  def move1(self,event):
  ########################### 

    dxw,dyw=self.getdiff(event)  
        
    # dx,dy in phys coord (cf +- inv_viewport)
    dx = self.size[0]*2.*dxw/self.shape[0] 
    dy = self.size[0]*2.*dyw/self.shape[0]
    
    # compute motion 1
    self.obs = self.interactor.M1(self.obs,dx,-dy,dxw,-dyw)
        
    # draw label
    self.draw_lab()
    
    # send to twin
    if self.twin!=None:
      self.twin.obs = self.obs
      self.twin.draw_lab()
  
  
  ###########################
  def move2(self,event):
  ########################### 

    dxw,dyw=self.getdiff(event)

    # dx,dy in phys coord (cf +- inv_viewport)
    dx = self.size[0]*2.*dxw/self.shape[0] 
    dy = self.size[0]*2.*dyw/self.shape[0]
        
    # compute motion 2
    self.obs = self.interactor.M2(self.obs,dx,-dy,dxw,-dyw)
        
    # draw label
    self.draw_lab()
    
    # send to twin
    if self.twin!=None:
      self.twin.obs = self.obs
      self.twin.draw_lab()
    
  ###########################
  def move3(self,event):
  ########################### 
    pass
    
  ###########################
  def double1(self,event):
  ########################### 
    diffx,diffy=self.getdiff(event)     

  ###########################
  def double2(self,event):
  ########################### 
    diffx,diffy=self.getdiff(event) 

  ###########################
  def double3(self,event):
  ########################### 
    diffx,diffy=self.getdiff(event)    
    
    
    
  ###########################
  def getdiff(self,event):
  ########################### 
    canvas = event.widget	
    diffx = float(event.x - self.last_event.x)
    diffy = float(-event.y + self.last_event.y) 
    self.last_event = event    
    return diffx,diffy    
    
 
 
 
 
 
 
 
 
     
################################################################################ 
#					 
# Gwin class				 
#					 
################################################################################ 
class Gwin:

  ###########################
  def __init__(self,file=None,options=None,comm=None):
  ###########################


    # logfiles
    self.log = liblog.Log(os.path.join(HOME,'.gwinlog'),show='no')  
  
    #self.gather_functions()
    self.comm = comm
    
  
    self.file = file
    self.ftype = options.ftype
    palette = options.palette
    self.d3 = options.stereo
    self.fullscreen = options.fullscreen
    self.parameters_file = options.parameters_file
    self.unitsparameters_file = options.unitsparameters_file
    if options.pio:
      self.pio = "yes"
    else:
      self.pio = "no"
        
    self.subs = None
    
  
    self.winw = 512
    self.winh = 512+300
    
    self.selected_point = None


    # init parameters
    self.init_parameters(self.parameters_file) 
    
    # init unitsparameters
    self.init_unitsparameters(self.unitsparameters_file)   
    
    # init palette tables
    self.init_palette(palette) 
    
    
    if self.comm.mpi_IsMaster():

      # create main window
      self.root = Tk()
      self.root.configure(bg='black')
    
    
      # fullscreen mode
      if self.fullscreen:
        height = self.root.winfo_screenheight()
        width  = self.root.winfo_screenwidth()
        self.root.overrideredirect(1)
        self.root.geometry(str(width)+"x"+str(height))
    
    
      # string var
      self.varRad = StringVar()
      self.varMod = StringVar()
      self.strlabsize = StringVar()
      self.strwinxsize = StringVar()
      self.strwinysize = StringVar()
      self.val = StringVar()
      self.xpos=StringVar()
      self.ypos=StringVar()   
    
              
      # init history
      self.init_hist() 
   
      # create frames
      self.create_main_frame()
      if not self.fullscreen:
        self.create_header_frame(0,0)
        self.create_info_frame(0,1)
        
      self.create_display_frame(0,2)
        
      if not self.fullscreen: 
        self.create_palette_frame(0,3)
    
        self.create_cmdwin_frame(1,0,1,1)
        self.create_control_frame(1,2,1,1)
        self.create_cmd_frame(0,4,3,1)
        self.create_log_frame(0,5,3,1)
    
      if not self.fullscreen: 
        # create menu bar
        self.create_menu_bar()
    
      # display params
      self.update_param()
      
      # init axes
      self.init_axes_size()
    
      # bind events
      self.bindevents()
      
      

    
      # open and display a model if file give
      if self.file != None:
        self.open(file=self.file,pio=self.pio)
	self.redisplay()
    
      self.root.mainloop() 
  
    else:	# we are slave      
      self.WaitForACommand()	  

  ########################################
  #
  # function used for parallelism
  #
  ########################################

  ############################
  #def gather_functions(self):
  ############################
  #  '''
  #  This function gather all available functions of the class
  #  and record it into the dictionary self.allfct
  #  '''
  #  
  #  fs = dir(self)	       
  #  self.allfct = {}	 
  #  for f in fs:
  #    exec("func = self.%s"%(f))			# here it could be better
  #    if type(func) == types.MethodType:
  #      self.allfct[f] = func	
	  

  ###########################
  def WaitForACommand(self,*arg,**kw):	
  ###########################      
    
    # wait for the command
    
    if self.comm.NTask==1:
      #name = self.comm[0].Bcast(None) 
      #arg  = self.comm[0].Bcast(None) 
      #kw   = self.comm[0].Bcast(None) 
    
      name = self.comm.mpi_Bcast(0,None) 
      arg  = self.comm.mpi_Bcast(0,None) 
      kw   = self.comm.mpi_Bcast(0,None) 
    
    else:   
      name = MPI.COMM_WORLD[0].Bcast(None) 
      arg  = MPI.COMM_WORLD[0].Bcast(None) 
      kw   = MPI.COMM_WORLD[0].Bcast(None)  
    
    # now, execute the command
    #print "(%d)"%(ThisTask),name,arg,kw
    apply(getattr(self,name),arg,kw)
    #apply(self.allfct[name],arg,kw)
    #print "(%d) done :"%(ThisTask),name,arg,kw
    
    # recursive call
    self.WaitForACommand()    # !!! here, we have the rist to never quit !!!
    #thread.start_new_thread(self.WaitForACommand,arg,kw)
	
  ###########################
  def BroadcastCmd(self,name,arg,kw):
  ###########################      
    if self.comm.mpi_IsMaster():
    
      if self.comm.ThisTask==0:

        if self.comm.NTask==1:

          #name = self.comm[0].Bcast(name)
          #arg  = self.comm[0].Bcast(arg) 
          #kw	= self.comm[0].Bcast(kw)  
    	
	  name = self.comm.mpi_Bcast(0,None) 
    	  arg  = self.comm.mpi_Bcast(0,None) 
    	  kw   = self.comm.mpi_Bcast(0,None)	

        else:
	  name = MPI.COMM_WORLD[0].Bcast(name) 
    	  arg  = MPI.COMM_WORLD[0].Bcast(arg)  
    	  kw   = MPI.COMM_WORLD[0].Bcast(kw)       
  
  ########################################
  #
  # init
  #
  ########################################


  
  ###########################
  def init_parameters(self,file):
  ###########################grab_set_global()
    '''
    init Nbody parameters
    '''
    if file != None:
      self.params = param.Params(file,self)
    else:
      self.params = param.Params(PARAMETERFILE,self)

  ###########################
  def init_unitsparameters(self,file):
  ###########################grab_set_global()
    '''
    init Nbody unitsparameters
    '''
    if file != None:
      self.unitsparams = param.Params(file,self)
    else:
      self.unitsparams = param.Params(UNITSPARAMETERFILE,self)



  ###########################
  def init_palette(self,palette):
  ###########################
    '''
    init palettes
    '''

    # look at the availables colormap tables
    self.tables = glob.glob(os.path.join(PALETTEDIR,'*'))
    # create a pallette object
    self.palette = Palette()
    
        
    if palette != None:
    
      if os.path.isfile(palette):
        pass
      else:
        palette = os.path.join(PALETTEDIR,palette)
      
      self.palette.change(palette)
    


    
  ###########################
  def bindevents(self):
  ########################### 
    '''
    bind events
    ''' 
    self.canvas1.bind('<Motion>',self.move)
    self.canvas1.bind('<Double-1>',self.select_point)
    self.canvas1.bind('<Double-3>',self.oldset_xp)
    
    if self.d3:
      self.canvas2.bind('<Motion>',self.move)
      self.canvas2.bind('<Double-1>',self.select_point)
      self.canvas2.bind('<Double-3>',self.oldset_xp)
  
    if self.fullscreen:
      self.root.bind('<Double-Button-2>',lambda event:self.quit())
      
    self.root.bind('<KeyPress>',self.OnKeyPressed) 
    
  ###########################
  def init_hist(self):
  ###########################
    '''
    init history
    '''
    self.hist = History(os.path.join(HOME,'.ghist'))

   

  ########################################
  #
  # create some frames
  #
  ########################################

  ###########################
  def create_main_frame(self): 
  ###########################     
    '''
    create the main frame
    '''
    
    if self.fullscreen:
      self.main_frame = Frame(self.root,bg='black',highlightbackground='black')
    else:
      self.main_frame = Frame(self.root,highlightbackground='black')
    
    self.main_frame.pack()

  ###########################
  def create_header_frame(self,x,y): 
  ###########################     
    '''
    create the header frame
    '''
    self.header_frame = Frame(self.main_frame,relief=RIDGE,borderwidth=1)
    self.header_frame.grid(column=x,row=y,sticky=E+N+S+W)
  
    # filename
    self.filenameLab = Label(self.header_frame,text="fname : ",width=10)
    self.filenameLab.grid(column=0,row=0,sticky=E+N+S+W)
    
    self.fnameEnt = Entry(self.header_frame)
    self.fnameEnt.grid(column=1,row=0,columnspan=4,sticky=E+N+S+W)

    # file type
    self.ftypeLab = Label(self.header_frame,text="ftype :",width=10)
    self.ftypeLab.grid(column=0,row=1,sticky=E+N+S+W)
    
    self.ftypeEnt = Entry(self.header_frame,width=28)
    self.ftypeEnt.grid(column=1,row=1,columnspan=1,sticky=E+N+S+W)

    # mass
    self.massLab = Label(self.header_frame,text="m_tot :",width=10)
    self.massLab.grid(column=2,row=1,sticky=E+N+S+W)
    
    self.massEnt = Entry(self.header_frame,width=28)
    self.massEnt.grid(column=3,row=1,columnspan=1,sticky=E+N+S+W)

    # nbody
    self.nbodyLab = Label(self.header_frame,text="nbody :",width=10)
    self.nbodyLab.grid(column=0,row=2,sticky=E+N+S+W)  
    
    self.nbodyEnt = Entry(self.header_frame,width=28)
    self.nbodyEnt.grid(column=1,row=2,columnspan=1,sticky=E+N+S+W)	 

    # npart_tot
    self.nbody_totLab = Label(self.header_frame,text="nbody_tot : ",width=10)
    self.nbody_totLab.grid(column=2,row=2,sticky=E+N+S+W)  
    
    self.nbody_totEnt = Entry(self.header_frame,width=28)
    self.nbody_totEnt.grid(column=3,row=2,columnspan=1,sticky=E+N+S+W)

    # npart
    self.npartLab = Label(self.header_frame,text="npart :",width=10)
    self.npartLab.grid(column=0,row=3,sticky=E+N+S+W)  
    
    self.npartEnt = Entry(self.header_frame,width=28)
    self.npartEnt.grid(column=1,row=3,columnspan=1,sticky=E+N+S+W)	 

    # npart_tot
    self.npart_totLab = Label(self.header_frame,text="npart_tot : ",width=10)
    self.npart_totLab.grid(column=2,row=3,sticky=E+N+S+W)  
    
    self.npart_totEnt = Entry(self.header_frame,width=28)
    self.npart_totEnt.grid(column=3,row=3,columnspan=1,sticky=E+N+S+W)

  
    # bind
    # 
    #self.labelEnt.bind("<Return>",self.update_from_header) 
    #self.ftypeEnt.bind("<Return>",self.update_from_header)
    #self.tnowEnt.bind("<Return>",self.update_from_header)
    #self.firstpartEnt.bind("<Return>",self.update_from_header)
    #self.lastpartEnt.bind("<Return>",self.update_from_header)

  ###########################
  def create_palette_frame(self,x,y): 
  ###########################     
    '''
    create the palette frame
    '''

    self.paletteFrame = Frame(self.main_frame,height=48,width=512,relief=RIDGE,borderwidth=1)
    self.paletteFrame.grid(column=x,row=y) 
    self.palette.addFrame(self.paletteFrame)  


  ###########################
  def create_info_frame(self,x,y,dx=1,dy=1): 
  ###########################     
    '''
    create the info frame
    '''

    labwidth = 10
    valwidth = 10

    self.info_frame = Frame(self.main_frame,relief=RIDGE,borderwidth=1,height=60)
    self.info_frame.grid(column=x,row=y,columnspan=dx,rowspan=dy,sticky=E+N+S+W)


    # label for the label size  					       
    self.labsizeLab = Label(self.info_frame,text="lab  = ",width=labwidth)  	       
    self.labsizeLab.grid(column=0,row=2)				       
    									      
    self.labsizeVal = Label(self.info_frame,textvariable=self.strlabsize,width=valwidth)  
    self.labsizeVal.grid(column=1,row=2)				       
 
    # label for the window size 					       
    self.winsizexLab = Label(self.info_frame,text="winx = ",width=labwidth)  	       
    self.winsizexLab.grid(column=0,row=0)				       
    
    self.winsizeyLab = Label(self.info_frame,text="winy = ",width=labwidth)  	       
    self.winsizeyLab.grid(column=2,row=0)	
        									       
    self.winsizexVal = Label(self.info_frame,textvariable=self.strwinxsize,width=valwidth)  
    self.winsizexVal.grid(column=1,row=0)				       

    self.winsizeyVal = Label(self.info_frame,textvariable=self.strwinysize,width=valwidth)  
    self.winsizeyVal.grid(column=3,row=0)
        									       
    # x win								       
    self.xLab = Label(self.info_frame,text="x    = ",width=labwidth)  		       
    self.xLab.grid(column=0,row=1)					       
    									       
    self.xVal = Label(self.info_frame,textvariable=self.xpos,width=valwidth)	       
    self.xVal.grid(column=1,row=1)					       

    # y win								       
    self.yLab = Label(self.info_frame,text="y    = ",width=labwidth)  		       
    self.yLab.grid(column=2,row=1)					       
    									       
    self.yVal = Label(self.info_frame,textvariable=self.ypos,width=valwidth)	       
    self.yVal.grid(column=3,row=1)
        
    # val
    self.valLab = Label(self.info_frame,text="val  = ",width=labwidth)  		       
    self.valLab.grid(column=2,row=2)					       
    									       
    self.valVal = Label(self.info_frame,textvariable=self.val,width=valwidth)	       
    self.valVal.grid(column=3,row=2)        				       




  ###########################
  def create_display_frame(self,x,y):      
  ###########################
    '''
    create the display frame
    '''
    self.display_frame = Frame(self.main_frame,bg='black',highlightbackground='black')
    self.display_frame.grid(column=x,row=y)
    								 
    self.canvas1 = Gcan(self.display_frame,height=self.params.get('shape')[1],width=self.params.get('shape')[0],bg="black",highlightbackground='black') 
    self.canvas1.grid(column=0,row=0)
    
    if self.d3:
      self.canvas2 = Gcan(self.display_frame,height=self.params.get('shape')[1],width=self.params.get('shape')[0],bg="black",highlightbackground='black')
      self.canvas2.grid(column=2,row=0)
      if self.fullscreen:
        width = (self.root.winfo_screenwidth()-2*self.params.get('shape')[0])/2
	height = self.root.winfo_screenheight()
        self.canvas = Canvas(self.display_frame,bg='black'  ,height=height,width=width,highlightbackground='black')
	self.canvas.grid(column=1,row=0)
   
    if self.d3:
      self.canvas1.init(self.params,root=self,eye='left' ,twin=self.canvas2)
      self.canvas2.init(self.params,root=self,eye='right',twin=self.canvas1)
    else:
      self.canvas1.init(self.params,root=self,eye='left' ,twin=None) 
         

  ###########################
  def create_cmdwin_frame(self,x,y,dx,dy):      
  ###########################
    '''
    create the cmdwin frame
    '''
    self.cmdwin_frame = Frame(self.main_frame,relief=RIDGE,borderwidth=1)
    self.cmdwin_frame.grid(column=x,row=y,columnspan=dx,rowspan=dy,sticky=N)

    # quit button											      
    self.quitBut = Button(self.cmdwin_frame,text="QUIT",fg="black",width=16,height=2,command=lambda:self.quit())			      
    self.quitBut.grid(column=0,row=0,sticky=E+N+S+W)   						      
    
    # reset button											      
    self.resetBut = Button(self.cmdwin_frame,text="RESET",fg="black",width=16,height=2,command=lambda:self.reset())			      
    self.resetBut.grid(column=0,row=1,sticky=E+N+S+W)         					      


  ###########################
  def create_control_frame(self,x,y,dx,dy):      
  ###########################
    '''
    create the control frame
    '''
    self.control_frame = Frame(self.main_frame,relief=RIDGE,borderwidth=1)
    self.control_frame.grid(column=x,row=y,columnspan=dx,rowspan=dy,sticky=N)
    								 

    #
    # zoom
    #
   
    # frame for the zoom								 
    self.zoomFr = Frame(self.control_frame,relief=RIDGE,borderwidth=1)							 
    self.zoomFr.grid(column=0,row=0)     													      

    # zoomin button											      
    self.zoominBut = Button(self.zoomFr,text="IN",fg="black",width=16,height=2,command=lambda:self.cmd_zoom('in'))			      
    self.zoominBut.grid(column=0,row=0,sticky=E+N+S+W)   						      

    # zoomout button											      
    self.zoomoutBut = Button(self.zoomFr,text="OUT",fg="black",width=16,height=2,command=lambda:self.cmd_zoom('out'))			      
    self.zoomoutBut.grid(column=0,row=1,sticky=E+N+S+W)         					      
    	   	

    #
    # ctrl
    #

    # frame for the control								 
    self.ctrlFr = Frame(self.control_frame,relief=RIDGE,borderwidth=1)							 
    self.ctrlFr.grid(column=0,row=1) 		
													      
    													         													         													      
    self.bnBut = Button(self.ctrlFr,text="N",fg="black",command=lambda :self.cmd_rotate('n'),width=3,height=2)	      
    self.bnBut.grid(column=1,row=0,sticky=E+N+S+W)							      

    self.bsBut = Button(self.ctrlFr,text="S",fg="black",command=lambda :self.cmd_rotate('s'),width=3,height=2)	      
    self.bsBut.grid(column=1,row=2,sticky=E+N+S+W)							      
    	 												      
    self.beBut = Button(self.ctrlFr,text="E",fg="black",command=lambda :self.cmd_rotate('e'),width=3,height=2)	      
    self.beBut.grid(column=0,row=1,sticky=E+N+S+W)	    						      

    self.bwBut = Button(self.ctrlFr,text="W",fg="black",command=lambda :self.cmd_rotate('w'),width=3,height=2)	      
    self.bwBut.grid(column=2,row=1,sticky=E+N+S+W)							      

    self.bmBut = Button(self.ctrlFr,text="M",fg="black",command=lambda :self.cmd_rotate('m'),width=3,height=2)	      
    self.bmBut.grid(column=0,row=0,sticky=E+N+S+W)							      
    													      
    self.bpBut = Button(self.ctrlFr,text="P",fg="black",command=lambda :self.cmd_rotate('p'),width=3,height=2)	      
    self.bpBut.grid(column=2,row=0,sticky=E+N+S+W)	    						      

    self.brBut = Button(self.ctrlFr,text="*",fg="black",command=lambda :self.redisplay())	      
    self.brBut.grid(column=1,row=1,sticky=E+N+S+W)	

    #
    # params Ang
    #
    
    self.parFrAng = Frame(self.control_frame,relief=RIDGE,borderwidth=1)									      
    self.parFrAng.grid(column=0,row=2,sticky=E+N+S+W)    
    
    # rotation angle
    self.rotLab = Label(self.parFrAng,text="angle:",width=7,height=2)
    self.rotLab.grid(column=0,row=0,sticky=E+N+S+W)
    
    self.rotEnt = Entry(self.parFrAng,width=7)									 
    self.rotEnt.grid(column=1,row=0,sticky=E+N+S+W) 							 
    self.rotEnt.insert(INSERT,"90") 
    
    #
    # params Mod1
    #           

    self.parFrMod1 = Frame(self.control_frame,relief=RIDGE,borderwidth=1)									      
    self.parFrMod1.grid(column=0,row=3,sticky=E+N+S+W)    
    
    self.Radlab = Label(self.parFrMod1,text="rotation/translat",width=14,height=2)
    self.Radlab.grid(column=0,row=0,columnspan=2,sticky=E+N+S+W)    
    self.transRad=Radiobutton(self.parFrMod1,text="trans",command=self.cmdRad,var=self.varRad,value="t")	    										  
    self.transRad.grid(column=0,row=1)  
    self.rotRad=Radiobutton(self.parFrMod1,text="rotat",command=self.cmdRad,var=self.varRad,value="r")    
    self.rotRad.grid(column=1,row=1)									         
    self.varRad.set('r')
    								     

    #
    # params Mod2
    #       

    self.parFrMod2 = Frame(self.control_frame,relief=RIDGE,borderwidth=1)									      
    self.parFrMod2.grid(column=0,row=4,sticky=E+N+S+W)        

    self.Radlab = Label(self.parFrMod2,text="motion mode",width=14,height=2)
    self.Radlab.grid(column=0,row=0,columnspan=3,sticky=E+N+S+W)    
    self.transRad=Radiobutton(self.parFrMod2,text="xp",command=self.cmdMod,var=self.varMod,value="xp")	    										  
    self.transRad.grid(column=0,row=1)  
    self.rotRad=Radiobutton(self.parFrMod2,text="x0",command=self.cmdMod,var=self.varMod,value="x0")    
    self.rotRad.grid(column=1,row=1)									     
    self.rotRad=Radiobutton(self.parFrMod2,text="x0xp",command=self.cmdMod,var=self.varMod,value="x0xp")    
    self.rotRad.grid(column=2,row=1)	
    self.varMod.set('xp')		
    
    #
    # obs params
    #      
    self.obsparFr = Frame(self.control_frame,relief=RIDGE,borderwidth=1)									      
    self.obsparFr.grid(column=0,row=5,sticky=E+N+S+W) 
    
    self.resetobsBut = Button(self.obsparFr,text="Reset Obs",fg="black",command=self.reset_obs,width=18,height=2)	      
    self.resetobsBut.grid(column=0,columnspan=3,row=0,sticky=E+N+S+W)	    		
		
    self.autoobsBut = Button(self.obsparFr,text="Auto Obs",fg="black",command=lambda:self.auto_obs(),width=18,height=2)	      
    self.autoobsBut.grid(column=0,columnspan=3,row=1,sticky=E+N+S+W)						      


    self.xzobsBut = Button(self.obsparFr,text="xz",fg="black",command=lambda:self.setview('xz'),width=6,height=2)	      
    self.xzobsBut.grid(column=0,row=2,sticky=E+N+S+W)						      

    self.xyobsBut = Button(self.obsparFr,text="xy",fg="black",command=lambda:self.setview('xy'),width=6,height=2)	      
    self.xyobsBut.grid(column=1,row=2,sticky=E+N+S+W)	
    
    self.yzobsBut = Button(self.obsparFr,text="yz",fg="black",command=lambda:self.setview('yz'),width=6,height=2)	      
    self.yzobsBut.grid(column=2,row=2,sticky=E+N+S+W)	    


    #
    # axes size
    #
    
    self.axeFr = Frame(self.control_frame,relief=RIDGE,borderwidth=1)									      
    self.axeFr.grid(column=0,row=6,sticky=E+N+S+W)    

    self.axesizeLab = Label(self.axeFr,text="axes size:",width=10,height=2)
    self.axesizeLab.grid(column=0,row=0,sticky=E+N+S+W)
    
    self.axesizeEnt = Entry(self.axeFr,width=7)									 
    self.axesizeEnt.grid(column=2,row=0,sticky=E+N+S+W) 							 
    self.axesizeEnt.insert(INSERT,"10") 
    
    self.axesizeEnt.bind("<Return>",self.set_axes_size)

  ###########################
  def create_cmd_frame(self,x,y,dx,dy):      
  ###########################
    '''
    create the cmd frame
    '''

    def ok(arg):
      
      goodcmd = 1
      cmd = self.command_entry.get()
      try:
	self.execute_command(cmd)
      except Exception,message:	
	self.log.write("""command "%s" failed\n"""%(cmd))
	self.log.write_traceback()
	self.log.write(str(message))	
	goodcmd = 0
	
	
	
      
      if goodcmd: 
        self.hist.add(cmd)
	self.command_entry.delete(0,len(self.command_entry.get())+1)
	self.display_info()
	#self.redisplay()        
    
    
    def up(event):
      self.hist.down()
      cmd = string.strip(self.hist.get())
      self.command_entry.delete(0,len(self.command_entry.get())+1)
      self.command_entry.insert(INSERT,cmd)

    def down(event):
      self.hist.up()
      cmd = string.strip(self.hist.get())
      self.command_entry.delete(0,len(self.command_entry.get())+1)
      self.command_entry.insert(INSERT,cmd)    
      
    def cancel():
      pass
      
    def clear():
      self.log.clear()  

    self.cmd_frame = Frame(self.main_frame,relief=RIDGE,borderwidth=1)
    self.cmd_frame.grid(column=x,row=y,columnspan=dx,rowspan=dy,sticky=N)					 
    									      
    # label command							      
    #label = Label(self.cmd_frame,text='command')		      
    #label.grid(column=0,row=0)	
    
    # entry command 							      
    self.command_entry = Entry(self.cmd_frame,width=104)					   
    self.command_entry.grid(column=1,row=0,sticky=N+S+E+W) 
    self.command_entry.bind("<Return>",ok) 
    self.command_entry.bind("<Down>",down)
    self.command_entry.bind("<Up>",up)
        

    # buttons								      
    clearbutton = Button(self.cmd_frame,text='clear',command=clear,width=2)    	 
    clearbutton.grid(column=2,row=0)					 
    									      
    #cancelbutton = Button(self.cmd_frame,text='cancel',command=cancel)  
    #cancelbutton.grid(column=3,row=0)					 
     													      
						      
  ###########################
  def create_log_frame(self,x,y,dx,dy):      
  ###########################
    '''
    create the control frame
    '''
    self.log_frame = Frame(self.main_frame,relief=RIDGE,borderwidth=1,background='white')
    self.log_frame.grid(column=x,row=y,columnspan=dx,rowspan=dy,sticky=E+N+S+W)


    sbar = Scrollbar(self.log_frame)
    	    													   
    self.logText = Text(self.log_frame,relief=SUNKEN,padx=5, wrap='none',width=106,height=10,background='white')
    sbar.config(command=self.logText.yview)									  
    self.logText.config(yscrollcommand=sbar.set)	
    sbar.grid(column=1,row=0,sticky=E+N+S)		     							  
    self.logText.grid(column=0,row=0,sticky=E+N+S+W)									  
    self.logText.config(state=DISABLED)       		
    
    # link to the log object
    self.log.show = 1
    self.log.logframe = self.logText							  
      
  ############################
  #def write_log(self,line):      
  ############################
  #  
  #  self.logText.config(state=NORMAL)
  #  self.logText.insert(INSERT,line)
  #  self.logText.yview(MOVETO,1) 
  #  self.logText.config(state=DISABLED)


  ###########################
  def create_menu_bar(self): 
  ###########################     
    '''
    create the menu bar
    '''
            
    self.menubar = Menu(self.root)								        
    
    # file menu
    self.filemenu = Menu(self.menubar,tearoff=0)	
    					        
    	
    
    if self.comm.NTask==1:				        
      self.filemenu.add_command(label="open file",command=lambda:self.open_file(pio='no'))	
    else:
      self.filemenu.add_command(label="open single file",command=lambda:self.open_file(pio='no'))	
      self.filemenu.add_command(label="open multi files",command=lambda:self.open_file(pio='yes'))	
    
    self.filemenu.add_separator()
    if self.comm.NTask==1:				        
      self.filemenu.add_command(label="write file",command=lambda:self.write('single'))	
    else:
      self.filemenu.add_command(label="write single file",command=lambda:self.write('single'))	
      self.filemenu.add_command(label="write multi files",command=lambda:self.write('multi'))	
      	
    self.filemenu.add_separator()  			            
    if self.comm.NTask==1:				        
      self.filemenu.add_command(label="write num ",command=lambda:self.write_num('single'))	
    else:
      self.filemenu.add_command(label="write num single file",command=lambda:self.write_num('single'))	
      self.filemenu.add_command(label="write num multi files",command=lambda:self.write_num('multi'))	

    self.filemenu.add_separator()
    self.filemenu.add_command(label="save image",command=self.save_image)			        
      
    
    #								        
    #self.filemenu.add_command(label="about",command=self.about) 				        
    self.filemenu.add_separator()								        
    self.filemenu.add_command(label="quit",command=lambda:self.quit())					        
    
    # palette menu
    self.palettemenu = Menu(self.menubar,tearoff=0)	
    self.tables.sort()					        
    for table in self.tables:	
      self.palettemenu.add_command(label=os.path.basename(table),				        
    				   command=lambda table=table,colormap=self.colormap:colormap(table))   
    							   					        					        
    # operation menu
    self.opermenu = Menu(self.menubar,tearoff=0)						        
    self.opermenu.add_command(label="reset",command=self.reset) 
    self.opermenu.add_separator()			        
    self.opermenu.add_command(label="model info",command=self.info) 
    self.opermenu.add_command(label="object info",command=self.object_info)	
    self.opermenu.add_command(label="nodes info",command=self.nodes_info)
    self.opermenu.add_separator()
    
    if self.comm.NTask>1:
      self.opermenu.add_command(label="redistribute particles",command=lambda:self.redistribute())
      self.opermenu.add_separator()    
    
    if self.comm.NTask==1:
      self.opermenu.add_command(label="select from num file",command=lambda:self.open_num_file(mode='single'))
    else:
      self.opermenu.add_command(label="select from num file (single)",command=lambda:self.open_num_file(mode='single'))
      self.opermenu.add_command(label="select from num file (multi)",command=lambda:self.open_num_file(mode='multi'))
    
    self.opermenu.add_separator()				        
    self.opermenu.add_command(label="plug-in",command=self.plugins) 
    #self.opermenu.add_separator()
    #self.opermenu.add_command(label="subs",command=self.open_subs)
    #self.opermenu.add_command(label="reset subs",command=self.reset_subs)				        
  
    
    # mode menu
    self.modemenu = Menu(self.menubar,tearoff=0)						        
    self.modemenu.add_command(label="pos  ",	  command=lambda :self.set_mode('pos')) 	        
    self.modemenu.add_command(label="vel  ",	  command=lambda :self.set_mode('vel')) 	        
    self.modemenu.add_separator()								        
    self.modemenu.add_command(label="m    ",	  command=lambda :self.set_mode('m'))	
    self.modemenu.add_command(label="u  ",	  command=lambda :self.set_mode('u'))		        
    self.modemenu.add_command(label="rho  ",	  command=lambda :self.set_mode('rho')) 	        
    self.modemenu.add_command(label="T  ",	  command=lambda :self.set_mode('T'))
    self.modemenu.add_command(label="A  ",	  command=lambda :self.set_mode('A'))
    self.modemenu.add_command(label="P  ",	  command=lambda :self.set_mode('P'))	
    self.modemenu.add_command(label="Tcool",	  command=lambda :self.set_mode('Tcool'))
    self.modemenu.add_command(label="Lum",	  command=lambda :self.set_mode('Lum'))  
    self.modemenu.add_command(label="Ne ",	  command=lambda :self.set_mode('Ne'))  
    self.modemenu.add_separator() 
    self.modemenu.add_command(label="x    ",	 command=lambda :self.set_mode('x'))
    self.modemenu.add_command(label="y    ",	 command=lambda :self.set_mode('y'))
    self.modemenu.add_command(label="z    ",	 command=lambda :self.set_mode('z'))
    self.modemenu.add_command(label="x2    ",	 command=lambda :self.set_mode('x2'))
    self.modemenu.add_command(label="y2    ",	 command=lambda :self.set_mode('y2'))
    self.modemenu.add_command(label="z2    ",	 command=lambda :self.set_mode('z2'))       
    self.modemenu.add_command(label="vx    ",	 command=lambda :self.set_mode('vx'))
    self.modemenu.add_command(label="vy    ",	 command=lambda :self.set_mode('vy'))
    self.modemenu.add_command(label="vz    ",	 command=lambda :self.set_mode('vz')) 
    self.modemenu.add_command(label="vx2  ",	 command=lambda :self.set_mode('vx2'))  	       
    self.modemenu.add_command(label="vy2  ",	 command=lambda :self.set_mode('vy2'))  	       
    self.modemenu.add_command(label="vz2  ",	 command=lambda :self.set_mode('vz2'))  
    self.modemenu.add_separator()						
    self.modemenu.add_command(label="lx  ",	 command=lambda :self.set_mode('lx')) 
    self.modemenu.add_command(label="ly  ",	 command=lambda :self.set_mode('ly')) 
    self.modemenu.add_command(label="lz  ",	 command=lambda :self.set_mode('lz')) 
    self.modemenu.add_command(label="Lx  ",	 command=lambda :self.set_mode('Lx')) 
    self.modemenu.add_command(label="Ly  ",	 command=lambda :self.set_mode('Ly')) 
    self.modemenu.add_command(label="Lz  ",	 command=lambda :self.set_mode('Lz'))     
    self.modemenu.add_separator()		        
    self.modemenu.add_command(label="r    ",	  command=lambda :self.set_mode('r'))	
    self.modemenu.add_command(label="r2    ",	  command=lambda :self.set_mode('r2'))	        
    self.modemenu.add_command(label="sr   ",	  command=lambda :self.set_mode('sr'))		        
    self.modemenu.add_command(label="vr   ",	  command=lambda :self.set_mode('vr'))	
    self.modemenu.add_command(label="vr2   ",	  command=lambda :self.set_mode('vr2'))		        
    self.modemenu.add_command(label="svr  ",	  command=lambda :self.set_mode('svr')) 	        
    self.modemenu.add_command(label="vxyr  ",	  command=lambda :self.set_mode('vxyr'))
    self.modemenu.add_command(label="vxyr2   ",	  command=lambda :self.set_mode('vxyr2'))	 	        
    self.modemenu.add_command(label="svxyr ",	  command=lambda :self.set_mode('svxyr'))	        
    self.modemenu.add_command(label="vtr   ",	  command=lambda :self.set_mode('vtr'))
    self.modemenu.add_command(label="vtr2   ",	  command=lambda :self.set_mode('vtr2'))			        
    self.modemenu.add_command(label="svtr  ",	  command=lambda :self.set_mode('svtr')) 	        
    self.modemenu.add_command(label="szr  ",	  command=lambda :self.set_mode('szr')) 	        
  
    
    # parameter menu
    self.parammenu = Menu(self.menubar,tearoff=0)						        
    self.parammenu.add_command(label="set",command=self.set_param) 				        
    self.parammenu.add_separator()								        
    self.parammenu.add_command(label="reset",command=self.read_param)	 			        
    self.parammenu.add_command(label="open",command=self.open_param)  				        
    self.parammenu.add_separator()								        
    self.parammenu.add_command(label="save",command=self.save_param)				        
    self.parammenu.add_command(label="save as",command=self.saveas_param)			        
    

    # unitsparameter menu
    self.unitsparammenu = Menu(self.menubar,tearoff=0)						        
    self.unitsparammenu.add_command(label="set",command=self.set_unitsparam) 				        
    self.unitsparammenu.add_separator()								        
    self.unitsparammenu.add_command(label="reset",command=self.read_unitsparam)	 			        
    self.unitsparammenu.add_command(label="open",command=self.open_unitsparam)  				        
    self.unitsparammenu.add_separator()								        
    self.unitsparammenu.add_command(label="save",command=self.save_unitsparam)				        
    self.unitsparammenu.add_command(label="save as",command=self.saveas_unitsparam)			        

    	    											        
    self.menubar.add_cascade(label="File",menu=self.filemenu)					        
    self.menubar.add_cascade(label="Palette",menu=self.palettemenu)				        
    self.menubar.add_cascade(label="Operations",menu=self.opermenu) 				        
    self.menubar.add_cascade(label="Mode",menu=self.modemenu) 					        
    self.menubar.add_cascade(label="Parameters",menu=self.parammenu)	
    self.menubar.add_cascade(label="Units Parameters",menu=self.unitsparammenu)			        
    
    self.root.config(menu=self.menubar)							        
     												        

  ########################################
  #
  # functions linked to the menu
  #
  ########################################
  
  ###########################
  def open_file(self,filename=None,pio='no'):
  ###########################
    '''
    open a file
    
    This function may be called only by the master
    '''   
    
    if filename == None and self.comm.mpi_IsMaster():
      filename = askopenfilename(initialdir='.') 
            
      if filename=="":
        filename==None
          
    if filename!=None:
      self.open(file=filename,pio=pio)   
      self.redisplay()	
		   
   
  ###########################
  def open_num_file(self,filename=None,mode='single'):
  ###########################
    '''
    open a num file and select particles from it
    '''   
    
    filename = askopenfilename(initialdir='.')
    if mode=='single':
      self.select_from_num_single(file=filename)
    else:
      self.select_from_num_multi(file=filename)      

  ###########################
  def select_from_num_single(self,*arg,**kw):
  ###########################
    self.BroadcastCmd("select_from_num_single",arg,kw)	
  
    if kw.has_key('file'):
      file = kw['file']
    
    if self.comm.mpi_IsMaster():
      num = io.read_ascii(file,[0])[0] 
    else:
      num = None  
    
    # broadcast
    num = self.comm.mpi_Bcast(0,num)
    
    # apply
    self.nb = self.nb.selectp(num)
    
    if self.comm.mpi_IsMaster():
      self.redisplay() 


  ###########################
  def select_from_num_multi(self,*arg,**kw):
  ###########################
    self.BroadcastCmd("select_from_num_multi",arg,kw)	
  
    if kw.has_key('file'):
      file = kw['file']
    

    numfile = "%s.%d"%(file,self.comm.ThisTask)
    if os.path.getsize(numfile)>0:
      num = io.read_ascii(numfile,[0])[0] 
    else:
      num = array([],int)


    
    # apply
    self.nb = self.nb.selectp(num)
    
    if self.comm.mpi_IsMaster():
      self.redisplay()    
               	   
    
  ###########################
  def write(self,mode):
  ###########################	 
    '''
    write a file
    '''        
    initialfile = self.fnameEnt.get() 
    savename = asksaveasfilename(initialdir='.',initialfile=initialfile)
    if savename != "":
      if mode == 'single':
        self.write_single(name=savename)
      elif mode == 'multi':
        self.write_multi(name=savename)	
	
      
  ###########################
  def write_single(self,*arg,**kw):
  ###########################
    self.BroadcastCmd("write_single",arg,kw)	 
    '''
    write only a file
    '''        
    
    if kw.has_key('name'):
      savename = kw['name']
    
    self.nb.set_pio('no')
    self.nb.rename(savename)
    self.nb.write()    
      
  ###########################
  def write_multi(self,*arg,**kw):
  ###########################
    self.BroadcastCmd("write_multi",arg,kw)	 
    '''
    write files in parallel
    '''        
    
    if kw.has_key('name'):
      savename = kw['name']    
    
    self.nb.set_pio('yes')
    self.nb.rename(savename)
    self.nb.write()  



  ###########################
  def write_num(self,mode):
  ###########################	 
    '''
    write a num file
    '''        
    savename = asksaveasfilename(initialdir='.',initialfile='num.dat')
    if savename != "":
      if mode == 'single':
        self.write_num_single(name=savename)
      elif mode == 'multi':
        self.write_num_multi(name=savename)	
	
      
  ###########################
  def write_num_single(self,*arg,**kw):
  ###########################
    self.BroadcastCmd("write_num_single",arg,kw)	 
    '''
    write only a file
    '''        
    
    if kw.has_key('name'):
      savename = kw['name']
    
    f = open(savename,'w') 
    
    if self.comm.mpi_IsMaster():
    
      for Task in range(self.comm.NTask-1,-1,-1):
        
	if Task != 0:
	  num = self.comm.mpi_Recv(source = Task)
          for n in num:
            f.write('%8i\n'%(n))
	else:
	  for n in self.nb.num:
            f.write('%8i\n'%(n))
	        
    else:
      self.comm.mpi_Send(self.nb.num, dest = 0)
    
      
  ###########################
  def write_num_multi(self,*arg,**kw):
  ###########################
    self.BroadcastCmd("write_num_multi",arg,kw)	 
    '''
    write files in parallel
    '''        
    
    if kw.has_key('name'):
      savename = kw['name']    
    
    f = open("%s.%d"%(savename,self.comm.ThisTask),'w') 
    for n in self.nb.num:
      f.write('%8i\n'%(n))
    f.close()  

  

  ###########################
  def save_image(self):
  ########################### 
      
    savename = asksaveasfilename(initialdir='.')
    if savename != "":
      if os.path.splitext(savename)[1] == ".fits":
        io.WriteFits(transpose(self.mat1).astype(float32),savename, None)
      else:	
        self.image1.save(savename)
     

  ###########################
  def about(self):
  ########################### 
    '''
    about this program
    '''	  
    import Pmw

    Pmw.aboutversion('1.0')
    Pmw.aboutcopyright('Copyright Revax 2001\nAll rights reserved')	     
    Pmw.aboutcontact('''Yves Revaz
  Geneva Observatory
  ch. des Maillettes
  1290 Sauverny
  Switzerland
				   	     
  email: yves.revaz@obs.unige.ch''')
  								   	     
#    self.about = Pmw.AboutDialog(self.master, applicationname = 'gdisp')	     
#    self.about.withdraw()					   	     
#    self.about.show()         

  ###########################	    
  def quit(self,*arg,**kw):
  ###########################
    self.BroadcastCmd("quit",arg,kw)
    '''
    Quit the application
    '''
    sys.exit()

  ########################### 
  def reset(self):
  ###########################
    '''
    Reset (reload) the current file 
    '''
    self.open(file=self.file,ftype=self.ftype,pio=self.pio)
    self.redisplay()
    
    
  ###########################
  def redisplay(self,*arg,**kw):
  ###########################  
    self.BroadcastCmd("redisplay",arg,kw)
    '''
    Send the display command interactively
    
    !!! This command must be called only by the master !!!
    '''
    
    self.display()
    self.display_info()
    

  ########################### 
  def colormap(self,name):
  ###########################    
   
    # change the color in the colormap menu
    self.palette.read(name)
    self.palette.draw() 
     
    try:
      self.nbodyviewer.colormap(self.palette)  
    except:
      pass      
      
    self.display_image()  	

    
  ###########################
  def info(self,*arg,**kw):
  ########################### 
    self.BroadcastCmd("info",arg,kw)
    '''
    Display info on the current file
    '''  
    self.nb.info() 

  ###########################
  def object_info(self,*arg,**kw):
  ########################### 
    self.BroadcastCmd("object_info",arg,kw)
    '''
    Display info on the current file
    '''  
    self.nb.object_info() 

  ###########################
  def nodes_info(self,*arg,**kw):
  ########################### 
    self.BroadcastCmd("nodes_info",arg,kw)
    '''
    Display info on the current nodes
    '''  
    self.nb.nodes_info() 

  ###########################
  def redistribute(self,*arg,**kw):
  ########################### 
    self.BroadcastCmd("redistribute",arg,kw)
    '''
    Redistribute particles amoung nodes
    '''  
    self.nb.redistribute() 

  ########################### 
  def plugins(self):
  ###########################
    '''
    Open a plugin
    '''
  
    filtername = askopenfilename(initialdir=PLUGINSDIR) 
    if filtername!="":								     
      execfile(filtername)							     

  ########################### 
  def open_subs(self):
  ###########################
    '''
    Open a sub file
    '''
  
    filename = askopenfilename(initialdir='.') 
    if filename!="":								     
      execfile(filename)	
      self.redisplay()

  ########################### 
  def reset_subs(self):
  ###########################
    '''
    Reset subs
    '''
  
    self.subs = None	

  ########################### 
  def set_mode(self,mode):
  ###########################  
   
    if mode == 'pos' or mode == 'vel':
      self.params.set('space',mode) 
    else:  
      self.params.set('mode',mode)
    
    self.send_param()    
    self.redisplay()     





  ########################### 
  def set_param(self):
  ###########################
    self.params.edit()

  ########################### 
  def read_param(self):
  ###########################
  
    paramname = PARAMETERFILE
    if os.path.exists(paramname):
      self.params.read(paramname) 
      self.send_param()   

  ########################### 
  def open_param(self):
  ###########################
  
     paramname = askopenfilename()
     if paramname!="":
       self.params.read(paramname) 
       self.send_param()         
       
       
  ########################### 
  def save_param(self):
  ###########################
    
    savename = PARAMETERFILE
    self.params.save(savename)
       
  ########################### 
  def saveas_param(self):
  ########################### 
  
    savename = asksaveasfilename(initialfile=PARAMETERFILE)
    if savename != "":  
      self.params.save(savename)
       
       
       
  ########################### 
  def set_unitsparam(self):
  ###########################
    self.unitsparams.edit()

  ########################### 
  def read_unitsparam(self):
  ###########################
  
    unitsparamname = UNITSPARAMETERFILE
    if os.path.exists(unitsparamname):
      self.unitsparams.read(unitsparamname) 
      self.send_unitsparam()   

  ########################### 
  def open_unitsparam(self):
  ###########################
  
     unitsparamname = askopenfilename()
     if unitsparamname!="":
       self.unitsparams.read(unitsparamname) 
       self.send_unitsparam()         
       
       
  ########################### 
  def save_unitsparam(self):
  ###########################
    
    savename = UNITSPARAMETERFILE
    self.unitsparams.save(savename)
       
  ########################### 
  def saveas_unitsparam(self):
  ########################### 
  
    savename = asksaveasfilename(initialfile=UNITSPARAMETERFILE)
    if savename != "":  
      self.unitsparams.save(savename)
       
       
       
       
       
  ########################################
  #
  # functions linked to the header
  #
  ########################################

  ########################### 
  def update_from_header(self,event):
  ########################### 
    '''
    Read the values from the header frame and update data
    '''
    
    # gather values for the header	
    new_p_name = self.fnameEnt.get()
    if new_p_name != self.nb.p_name:
      self.file = new_p_name
      status = self.open(file=self.file)
      if status == -1:
        return
          
    #self.nb.p_name = self.fnameEnt.get()
    #self.file = self.nb.p_name 
    		      
    #self.nb.label = self.labelEnt.get()       
    #self.nb.tnow = float(self.tnowEnt.get())  
    		
    #self.nb = self.nb.set_ftype(self.ftypeEnt.get())
    #self.ftype = self.ftypeEnt.get()		
    
    #self.tnow = float(self.tnowEnt.get())
					      
    #n1 = int(self.firstpartEnt.get())	      
    #n2 = int(self.lastpartEnt.get())	     
    #self.nb = self.nb.sub(n1,n2) 	      


    self.redisplay()


  ########################################
  #
  # functions linked to the buttons
  #
  ########################################


  ########################### 
  def cmd_zoom(self,cmd):
  ########################### 
    '''
    set zoom
    
    zooming corresponds to changing the physical width and height
    of the canvas in physical coordinates
    '''
    
    wx = self.params.get('size')[0]
    wy = self.params.get('size')[1]
    #zf = self.params.get('zfact')
    zf = 0.75
    if   cmd == 'out':
      wx = wx/zf
      wy = wy/zf
    elif cmd == 'in':
      wx = wx*zf
      wy = wy*zf
    
    self.params.set('size',(wx,wy))
    
    self.send_param()
    

  ########################### 
  def cmd_rotate(self,cmd):
  ########################### 
    '''
    set rotation
    '''
    angle = float(self.rotEnt.get())
    mode = None
    
    if cmd =='e':
      dx = -angle
      dy = 0
      mode = 1
    elif cmd =='w':
      dx = angle
      dy = 0
      mode = 1
    elif cmd =='n':
      dx = 0
      dy = angle
      mode = 1
    elif cmd =='s':
      dx = 0
      dy = -angle
      mode = 1
    elif cmd =='m':
      dx = -angle
      dy = 0
      mode = 2
    elif cmd =='p':
      dx = angle
      dy = 0
      mode = 2          
      
    # compute rotation
    if   mode  == 1:
      self.canvas1.obs = self.canvas1.interactor.M1(self.canvas1.obs,dx,-dy,dx,-dy)
      if self.d3:
        self.canvas2.obs = self.canvas2.interactor.M1(self.canvas1.obs,dx,-dy,dx,-dy)
    elif mode == 2:
      self.canvas1.obs = self.canvas1.interactor.M2(self.canvas1.obs,dx,-dy,dx,-dy) 
      if self.d3:
        self.canvas2.obs = self.canvas2.interactor.M2(self.canvas1.obs,dx,-dy,dx,-dy)  
    # draw label
    self.canvas1.draw_lab() 
    if self.d3:
      self.canvas2.draw_lab()   

  ########################### 
  def reset_obs(self):
  ########################### 
    '''
    Reset observer position
    '''
    
    self.canvas1.init_obs()
    if self.d3:
      self.canvas2.init_obs()

  ########################### 
  def auto_obs(self,*arg,**kw):
  ########################### 
    self.BroadcastCmd("auto_obs",arg,kw)  
    '''
    Choose observer parameters automatically
    '''
    
    # center of mass of the model
    cm = self.nb.cm()
    
    # extention of the model
    dm = max(self.nb.minert())
    #dm = max(ravel(self.nb.pos))    

    
    if self.comm.mpi_IsMaster():
        
      # lab xp,r_obs,view
      self.params.set('obs',None)
      #self.params.set('xp',cm)
      self.params.set('x0',None)
      self.params.set('alpha',None)
      self.params.set('view','xz')
      self.params.set('r_obs',dm*4)
    
      self.params.set('clip',(dm*4-dm*2,2*(dm*4)))
      self.params.set('size',(dm,dm))
    
      #self.params.set('labsize',0.5*dm)
      labsize = 0.5*dm
              	      
      # send params init obs and display      
      self.send_param()
      self.canvas1.init_obs()  

            
      if self.d3:
        self.canvas2.init_obs()  
    
      self.set_axes_size(labsize)
          
      self.redisplay()     

      

  ########################### 
  def setview(self,mode):
  ########################### 
    '''
    Choose view xy,xz or yz
    '''

    self.canvas1.set_view(mode) 
    self.canvas1.draw_lab() 
    if self.d3:
      self.canvas2.set_view(mode)
      self.canvas2.draw_lab()       
    

  ###########################
  def cmdRad(self):
  ###########################  
    self.canvas1.set_interactor_mode(self.varRad.get())
    if self.d3:
      self.canvas2.set_interactor_mode(self.varRad.get())
    
  ###########################
  def cmdMod(self):
  ###########################  
    self.canvas1.set_interactor(self.varMod.get())
    if self.d3:
      self.canvas2.set_interactor(self.varMod.get())



  ########################################
  #
  # functions linked to the model
  #
  ########################################
  
  ###########################
  def open(self,*arg,**kw):
  ###########################  
    self.BroadcastCmd("open",arg,kw)
    '''
    open a model
    '''
    
    if kw.has_key('file'):
      file = kw['file']
    else:
      file = None  
      
    if kw.has_key('ftype'):
      ftype = kw['ftype'] 
    else:
      ftype = None  

    if kw.has_key('pio'):
      pio = kw['pio'] 
    else:
      pio = 'no'   
              
    
    
    #if not os.path.exists(file):
    #  showerror("error","the file %s does not exists !" %(file)) 
    #  return -1 
  
    if ftype == None:
      ftype = self.ftype
    

    self.nb = Nbody(file,ftype=ftype,pio=pio,log=self.log) 
    
  
  ###########################
  def display(self):
  ###########################      
    '''
    display the model
    (this function must be called by the master and the slaves)
    
    create
    
    self.mat
    self.matint
    self.image
    self.photo
    '''

    params = {}
    if self.comm.mpi_IsMaster():
      # read obs and send it
      obs = self.canvas1.obs 
      self.params.set('obs',obs)
      
      # gather parameters 
      params = self.params.get_dic()
      
      #if self.canvas1.obs != None:
      #params['x0'] = self.canvas1.obs[0]
      #params['xp'] = self.canvas1.obs[1]
          
    # send params to everybody
    params = self.comm.mpi_Bcast(0,params)
    
    
    
    # value of the eye for the first image
    if self.d3:
      eye = 'left'

    
    # compute map1
    self.mat1,self.matint1,mn_opts1,mx_opts1,cd_opts1 = self.nb.Map(params) 	       
    self.log.write( "%002d min=%10.3e max=%10.3e cd=%10.3e"%(1.,mn_opts1[0],mx_opts1[0],cd_opts1[0]) )

    # compute map2
    if self.d3:
      self.mat2,self.matint2,mn_opts2,mx_opts2,cd_opts2 = self.nb.Map(params)		 
      self.log.write( "%002d min=%10.3e max=%10.3e cd=%10.3e"%(2,mn_opts2[0],mx_opts2[0],cd_opts2[0]) )

    # display image
    if self.comm.mpi_IsMaster():
      self.display_image()
    
          
  ###########################
  def display_image(self):
  ###########################  
    '''
    display the image(s)    
    '''    
    
    # create first image
    # create an image and insert a palette
    self.image1 = get_image(self.matint1,name=None)

    # include the palette
    self.image1.putpalette(self.palette.palette)

    # make the photo					
    self.photo1 = ImageTk.PhotoImage(self.image1)	

    # change the size of the canvas
    self.canvas1.config(width=self.mat1.shape[0],height=self.mat1.shape[1])

    # displaying the photo					
    self.canvas1.create_image(0.,0.,anchor=NW,image=self.photo1)  

    # displaying the label
    self.canvas1.draw_lab()


    # create second image
    # compute map2
    if self.d3:

      # create an image and insert a palette
      self.image2 = get_image(self.matint2,name=None)

      # include the palette
      self.image2.putpalette(self.palette.palette)

      # make the photo  				  
      self.photo2 = ImageTk.PhotoImage(self.image2)		      

      # change the size of the canvas
      self.canvas2.config(width=self.mat2.shape[0],height=self.mat2.shape[1])

      # displaying the photo					  
      self.canvas2.create_image(0.,0.,anchor=NW,image=self.photo2)

      # displaying the label
      self.canvas2.draw_lab()
      
    
     
  ###########################
  def display_info(self):
  ###########################  
    '''
    display info of the model
    '''
    
    if self.comm.mpi_IsMaster():
    
      if not self.fullscreen:
    
        # filename
        self.fnameEnt.delete(0,len(self.fnameEnt.get())+1)
        self.fnameEnt.insert(INSERT,self.nb.p_name[0])
       
        # ftype
        self.ftypeEnt.delete(0,len(self.ftypeEnt.get())+1)
        self.ftypeEnt.insert(INSERT,self.nb.ftype)    


        # mass
	self.massEnt.delete(0,len(self.massEnt.get())+1)
        self.massEnt.insert(INSERT,self.nb.mass_tot)
	
        # nbody
	self.nbodyEnt.delete(0,len(self.nbodyEnt.get())+1)
        self.nbodyEnt.insert(INSERT,self.nb.nbody)

        # nbody_tot
	self.nbody_totEnt.delete(0,len(self.nbody_totEnt.get())+1)
        self.nbody_totEnt.insert(INSERT,self.nb.nbody_tot)
	
        # npart
	self.npartEnt.delete(0,len(self.npartEnt.get())+1)
	self.npartEnt.insert(INSERT,"%s"%(str(self.nb.npart)))
        #self.npartEnt.insert(INSERT,"%d,%d,%d,%d,%d,%d"%(self.nb.npart[0],self.nb.npart[1],self.nb.npart[2],self.nb.npart[3],self.nb.npart[4],self.nb.npart[5]))
	
        # npart_tot
	self.npart_totEnt.delete(0,len(self.npart_totEnt.get())+1)
	self.npart_totEnt.insert(INSERT,"%s"%(str(self.nb.npart_tot)))
        #self.npart_totEnt.insert(INSERT,"%d,%d,%d,%d,%d,%d"%(self.nb.npart_tot[0],self.nb.npart_tot[1],self.nb.npart_tot[2],self.nb.npart_tot[3],self.nb.npart_tot[4],self.nb.npart_tot[5]))		



    
  ########################### 
  def update_param(self):
  ###########################    
    '''
    update the display of some params
    '''
    
    # window size 
    wx = self.params.get('size')[0]
    wy = self.params.get('size')[0]
    self.strwinxsize.set("%10.3f"%wx) 
    self.strwinysize.set("%10.3f"%wy)    
    
    # label size
    #size = self.params.get('labsize')
    #size = float(self.axesizeEnt.get())
    #self.strlabsize.set("%10.3f"%size)  
    
    self.shape = self.params.get('shape')
    self.size = self.params.get('size')
    
  ########################### 
  def send_param(self):
  ###########################
    '''
    send params to the canvas class
    '''
    
    # copy the params to the nbody class
    self.nb.set_parameters(self.params)
    self.nb.set_unitsparameters(self.unitsparams)
    
    # update display of some params
    self.update_param()
    
    # send to canvas
    self.canvas1.init_params(self.params)   
    #self.canvas1.change_lab_size()
    self.canvas1.draw_lab()
    
    if self.d3:
      self.canvas2.init_params(self.params) 
      #self.canvas2.change_lab_size()
      self.canvas2.draw_lab()
      
     


  ########################### 
  def print_param(self):
  ###########################
    '''
    print params
    '''
        
    obs =  ravel(self.canvas1.obs)
    self.log.write("%s"%str(obs))
    obs.shape = (4,3)
    
  ###########################
  def execute_command(self,*arg,**kw):        
  ###########################
    self.BroadcastCmd("execute_command",arg,kw)
    '''
    execute a command
    '''
    sto_stdout = sys.stdout
    sys.stdout = self.log.f
	    
    exec(arg[0])
    self.log.write_content()
    
    sys.stdout = sto_stdout
         
    
  ########################################
  #
  # events
  #
  ########################################

  ###########################
  def OnKeyPressed(self,event):
  ###########################
    
    #if event.char == 'q':
    #  self.quit()
    #if event.char == 'p':
    #  self.print_param()
    pass
  
  ###########################
  def move(self,event):
  ###########################

    self.canvas1.last_event = event
    if self.d3:
      self.canvas2.last_event = event
    
    x = event.x         			
    y = event.y   
    

    # local value of the matrix
    try:
      self.val.set('%10.3e' % self.mat1[x,y])	
    except :
      pass  
      
          
    # position on the window
    x,y,z = geo.inv_viewport(x,y,0,self.shape)
    x = x*self.size[0]
    y = y*self.size[1]
    
    self.xpos.set('%10.5f' % x)				      
    self.ypos.set('%10.5f' % y)	   
    
  ###########################
  def select_point(self,event):
  ###########################

    self.canvas1.last_event = event
    if self.d3:
      self.canvas2.last_event = event
    
    x = event.x         			
    y = event.y   
    

    # local value of the matrix
    try:
      self.val.set('%10.3e' % self.mat[x,y])	
    except :
      pass  
      
          
    # position on the window
    x,y,z = geo.inv_viewport(x,y,0,self.shape)
    x = x*self.size[0]
    y = y*self.size[1]
    
    
    # !!! here, we should also inverse the projection matrix !!!
    
    self.selected_point = array([x,y,0])
    
    self.canvas1.draw_marker(self.selected_point)
    if self.d3:
      self.canvas2.draw_marker(self.selected_point)

  ###########################
  def oldset_xp(self,event):
  ###########################
    
    if self.selected_point != None:

      x0  = self.canvas1.obs[0]
      xp  = self.canvas1.obs[1]
      xpn = xp + (self.selected_point-xp)
            
      # rotate lab in order to align (xp-x0) with (xpn-x0)
      obs = geo.align(self.canvas.obs,axis1=xp-x0,axis2=xpn-x0,point=x0)
      obs[1] = xpn
      
      self.canvas1.obs = obs
      if self.d3:
        self.canvas2.obs = obs
      
      self.redisplay()


  ###########################
  def set_xp(self,pos):
  ###########################

    
    xp       = pos
    x0       = array(self.params.get('x0'),float)
    alpha    = self.params.get('alpha')
    r_obs    = self.params.get('r_obs') 
    view     = self.params.get('view')


    obs = geo.get_obs(x0=x0,xp=xp,alpha=alpha,view=view,r_obs=r_obs)  
    self.params.set('obs',obs)
           
    self.send_param()
    self.redisplay()




  ###########################
  def init_axes_size(self):
  ###########################
    
    size = 10
           
    self.axesizeEnt.delete(0,len(self.axesizeEnt.get())+1)
    self.axesizeEnt.insert(INSERT,"%s"%(str(size)))   
    
    self.set_axes_size(None)


            
  ###########################
  def set_axes_size(self,labsize):
  ###########################
      
    if (type(labsize) == types.IntType) or (type(labsize) == types.FloatType):
      size = labsize
      self.axesizeEnt.delete(0,len(self.axesizeEnt.get())+1)
      self.axesizeEnt.insert(INSERT,"%s"%(str(size)))   
    else:    
      size = float( self.axesizeEnt.get() )
      
    self.strlabsize.set("%10.3f"%size)
    
    self.canvas1.change_lab_size(size)
    self.canvas1.draw_lab()
    
    
    if self.d3:
      self.canvas2.change_lab_size(size)
      self.canvas2.draw_lab()
    
    
  
      
################################################################################
#
#                                    MAIN
#
################################################################################

file,options = parse_options()
#w = Gwin(file,options,comm=MPI.COMM_WORLD)
w = Gwin(file,options,comm=mpi)
