"""
     pygl/moleculargraphicsmodel.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009-2010 University of York
     Copyright (C) 2012 STFC

     This library is free software: you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public License
     version 3, modified in accordance with the provisions of the 
     license to address the requirements of UK law.
 
     You should have received a copy of the modified GNU Lesser General 
     Public License along with this library.  If not, copies may be 
     downloaded from http://www.ccp4.ac.uk/ccp4license.php
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Lesser General Public License for more details.
"""


import time
#from primitive import *
from displayobject import *
import graphicsmodel
from texture import *
from atom_util import *
from mmdb2 import *
import pygl_coord
import math
import cprim
import os
import sys
import functools
import global_definitions
import mginterrupt
import UtilityThread
import model

from PyQt4 import QtCore, QtGui

try:
  # This module is not important for distribution.
  import memusage
except:
  pass

ALPHAHELIX = 6
BETASTRAND = 1
BETABULGE = 1

class moleculargraphicsmodel(graphicsmodel.graphicsmodel):

   def __del__(self):
      #print "moleculargraphicsmodel.__del__"
      if hasattr(self,"conn_lists") and self.conn_lists:
         #print "Clear Connectivity lists"
         del self.conn_lists
         self.conn_lists = ()
      return
      if hasattr(self,'conn_draw') and self.conn_draw:
         del self.conn_draw

   def setparams(self,**keywords):
      for key in keywords.keys():
         setattr(self,key,keywords[key])
         if key == 'symmetry_radius':
            self.symmetry_radius = float(keywords[key])
         elif key == 'draw_symmetry':
            self.obj.SetDrawSymmetry(int(keywords[key]))
         elif key == 'parameters':
            self.rebuild()

   def SetupSymmetry(self,point,extents):
       if self.doBiomolecule:
         if self.obj.GetNumSymmetryMatrices()>0:
           return
         matrices = self.molHnd.GetBiomoleculeAsMatrices(0,1);
         if len(matrices)==0:
           return
         numbers = pygl_coord.IntVector(len(matrices))
         self.obj.SetDrawSymmetry(1)
         self.obj.SetSymmetryMatrices(matrices)
         self.obj.SetSymmetryMatrixNumbers(numbers)
         self.obj.SetDrawSymmetryColoured(0)
         return
       elif self.draw_symmetry == 0 or not self.doSymmetry:
          self.doCentralSymmetry = True
          self.obj.SetSymmetryMatrices([])
          return
       self.setup_symmetry(point,extents)

   def DrawUnitCell(self,draw_unit_cell=0,xshift=0,yshift=0,zshift=0):
       self.draw_unit_cell = draw_unit_cell
       self.xshifts = xshift
       self.yshifts = yshift
       self.zshifts = zshift

   def update_conn_atoms(self):
     if self.conn_atoms:
        self.conn_atoms = None

     if self.mode in [cprim.SPLINE,cprim.WORM,cprim.FATWORM,cprim.VARIABLEWORM]:
     	import mmut
        selindexp = pygl_coord.intp()
        
	"""
     	redSelHnd = self.selHnd
     	reducedSelAtoms = mmut.newPPCAtom()
     	nreducedSelAtoms = self.molHnd.GetSelIndex (redSelHnd,reducedSelAtoms)
	print "Initial no of atoms:", nreducedSelAtoms; sys.stdout.flush()
	"""
     	redSelHnd = mmut.GetCAFromSelection(self.molHnd,self.selHnd)
     	reducedSelAtoms = mmut.newPPCAtom()
     	#nreducedSelAtoms = self.molHnd.GetSelIndex (redSelHnd,reducedSelAtoms)
        reducedSelAtoms = mmut.GetAtomSelIndex(self.molHnd,redSelHnd,selindexp)
        nreducedSelAtoms = selindexp.value()
	#print "Reduced no of atoms:", nreducedSelAtoms; sys.stdout.flush()
        self.conn_atoms = reducedSelAtoms
        self.conn_natoms = nreducedSelAtoms
	self.SplineConnectivity = mmut.Connectivity()
	self.SplineConnectivity.AddBonds(self.molHnd,redSelHnd,reducedSelAtoms,nreducedSelAtoms,0,0)
     else:
        self.conn_atoms = self.Connectivity.GetAtoms()
        self.conn_natoms = self.Connectivity.GetNumberOfAtoms()
     """
     self.conn_atoms = self.Connectivity.GetAtoms()
     self.conn_natoms = self.Connectivity.GetNumberOfAtoms()
     #print 'moleculargraphicsmodel.update_conn_atoms',self.conn_atoms
     #print 'moleculargraphicsmodel.update_conn_atoms',self.conn_natoms
     """

   def GetAtomsInVolume(self,contained_volume):
     self.update_conn_atoms()
     carts =  CartesiansFromAtoms(self.conn_atoms, self.conn_natoms)

     selected_atoms = cprim.GetPointsInVolume(self.obj,carts,contained_volume)

     atom_list = []
     for i in range(len(selected_atoms)):
        atom = getPCAtom(self.conn_atoms,selected_atoms[i])
        atom_list.append(atom)
     return atom_list
     
   def ClickedPrimitiveCoords(self):
     line = self.line
     if line[0] < 0 and line[1] < 0:
        return None

     if line[0] >= 0 and line[1] >=0 :
        return None

     if line[0] >= 0:
        atomid = line[0]

     if line[1] >= 0:
        atomid = line[1]

     if atomid < 0: return
     at = getPCAtom(self.conn_atoms,atomid)
     return [at.x,at.y,at.z]

   def GetClickedAtoms(self,xyzbox,near,far):
     if not self.conn_atoms or not self.conn_natoms:
	return
     line = self.GetClickedLinesAndPoints(xyzbox,near,far)
     if line[0] >=0:
        at1 = getPCAtom(self.conn_atoms,line[0])
     else:
        at1 = None
     if line[1] >=0:
        at2 = getPCAtom(self.conn_atoms,line[1])
     else:
        at2 = None
     return [at1,at2,line[2],line[3]]
   
   def GetClickedLinesAndPoints(self,xyzbox,near,far):
     if not hasattr(self,"conn_atoms"):
        self.update_conn_atoms()
     if not self.conn_atoms or not self.conn_natoms:
	return
     carts = CartesiansFromAtoms(self.conn_atoms, self.conn_natoms)
     if self.mode in [cprim.SPLINE,cprim.WORM,cprim.FATWORM,cprim.VARIABLEWORM]:
       line = cprim.FindLine(self.obj,carts,xyzbox,self.SplineConnectivity,self.draw_symmetry)
     else:
       line = cprim.FindLine(self.obj,carts,xyzbox,self.Connectivity,self.draw_symmetry)

     # Prioritise picking at atom by reducing its assigned distance
     if line.first< 0 or line.second<0:
       self.line = [ line.first, line.second, line.dist-0.5, line.symm ]
     else:
       self.line = [ line.first, line.second, line.dist, line.symm ]
     return self.line

   def ClickedLineCoords(self):
     line = self.line
     if line[0] < 0 or line[1] < 0:
       return

     at = getPCAtom(self.conn_atoms,line[0])
     coord1 = [at.x,at.y,at.z]
     at = getPCAtom(self.conn_atoms,line[1])
     coord2 = [at.x,at.y,at.z]
     return [coord1,coord2]

   def AddLineLabel(self):
     line = self.line
     if line[0] < 0 or line[1] < 0:
       return
     at = getPCAtom(self.conn_atoms,line[0])
     import atom_picking
     atom_picking.picklabels.insts.draw_atom_label(self.ui.parent,self.ui,at)
     at = getPCAtom(self.conn_atoms,line[1])
     atom_picking.picklabels.insts.draw_atom_label(self.ui.parent,self.ui,at)

   def AddLabel(self,text_label=""):
     line = self.line
     if line[0] < 0 and line[1] < 0:
        return None

     if line[0] >= 0 and line[1] >=0 :
        return None

     if line[0] >= 0:
        atomid = line[0]

     if line[1] >= 0:
        atomid = line[1]

     at = getPCAtom(self.conn_atoms,atomid)

     atname = at.GetAtomName()
     
     if atname != "DUMMY":
       import atom_picking
       atom_picking.picklabels.insts.draw_atom_label(self.ui.parent,self.ui,at)
     return at

   def GetPrimitiveLabel(self,user_defined=0):
      

     atomid = []
     for ll in self.line[0:2]:
       if ll >= 0:
         at = getPCAtom(self.conn_atoms,ll)
         if at:
           atom_name = self.GetAtomLabel(at,user_defined=user_defined)
           if atom_name != "/-/-/-/DUMMY":
             atomid.append(atom_name)
     #print "atomid",atomid
     return atomid
    
   def GetAtomLabel(self,atomPtr,user_defined=1):
     if not user_defined:
       text_label = atomPtr.GetAtomID()[0]
     else:
       import display_table
       import atom_picking
       pl = atom_picking.picklabels.insts
       mapping = display_table.DT().moldisplay.label_style_mask
       mask = inta(20)
       for j in range(0,20): mask[j] = 0
       for j in range(0,len(pl.atom_label_style)):
         if pl.atom_label_style[j]:
           for k in mapping[j]:
             mask[k] = 1

       text_label = self.molHnd.AtomLabel_mask(atomPtr,mask)
     return text_label

   def GetMaxDimension(self):
      import time
      t1 = time.time()
      """
      Work out how big viewport should be and tell OpenGL.
      """
      import symmetry
      if self.nSelAtoms<1: return
      ext = symmetry.molecule_extents_t(self.selAtoms,self.nSelAtoms)
      left = ext.get_left()
      right = ext.get_right()
      top = ext.get_top()
      bottom = ext.get_bottom()
      front = ext.get_front()
      back = ext.get_back()
      minx = left.get_x()
      maxx = right.get_x()
      miny = bottom.get_y()
      maxy = top.get_y()
      minz = front.get_z()
      maxz = back.get_z()

      xdist = maxx - minx
      ydist = maxy - miny
      zdist = maxz - minz
      dist = max(xdist,ydist,zdist)
      t2 = time.time()

      #print "time to calculate max dim", t2 - t1
      return dist
     
   def __init__(self,ui='',com=[0,0,0],origin=[0,0,0], \
          selAtoms=None,nSelAtoms=0,Connectivity=None, \
          style=None,visible=1,molHnd=None,selHnd=0, \
          atomColourVector=None,atomRadii=None, \
          draw_symmetry=0,parameters=None,global_parameters=None,
          side_to_ribbon=0,side_to_worm=0,splineinfo_ribbon=None,splineinfo_worm=None):

     self.doSymmetry=True
     self.doBiomolecule=False
     t1 = time.time()

     self.graphicsmodel_init(ui=ui)

     # The data structure to be drawn
     self.molHnd = molHnd
     self.selHnd = selHnd
     self.selAtoms = selAtoms
     self.nSelAtoms = nSelAtoms
     self.Connectivity = Connectivity
     self.atomRadii=atomRadii
     self.diagnostic_timing = 0
     self.stick_colour = -1
     self.external_bonds_mode = cprim.DRAW_ALL_BONDS
     self.side_to_ribbon = side_to_ribbon
     self.side_to_worm = side_to_worm
     import mmut
     if splineinfo_ribbon is None:
       self.splineinfo_ribbon = mmut.SplineInfo()
     else:
       self.splineinfo_ribbon = splineinfo_ribbon
     if splineinfo_worm is None:
       self.splineinfo_worm = mmut.SplineInfo()
     else:
       self.splineinfo_worm = splineinfo_worm

     self.draw_symmetry = draw_symmetry
     self.draw_unit_cell = 0
     self.old_draw_unit_cell = 0
     self.draw_contacts = 0
     self.old_draw_contacts = 0
     self.xshifts = 0
     self.yshifts = 0
     self.zshifts = 0
     self.old_xshifts = -9999
     self.old_yshifts = -9999
     self.old_zshifts = -9999
     self.symmetry_radius = 75
     self.symmetry_labels = 0

     # Colour and style
     self.style = style
     self.atomColourVector = atomColourVector
     
     self.tree = pygl_coord.Tree();
     self.parameters = parameters
     self.global_parameters = global_parameters
     self.update_surface = 1
     t2 = time.time()
     self.conn_atoms = ''
     self.conn_natoms = 0
     self.mode = None

     self.customWidthUDD = -1

   def setup_symmetry(self,p,extents):
     #print 'moleculargraphicsmodel.setup_symmetry'
     point = -pygl_coord.Cartesian(p)

     tl = -pygl_coord.Cartesian(extents[0])
     tr = -pygl_coord.Cartesian(extents[1])
     br = -pygl_coord.Cartesian(extents[2])
     bl = -pygl_coord.Cartesian(extents[3])

     import symmetry
     #self.update_conn_atoms()

     if ((self.draw_contacts == 0 and self.draw_unit_cell == 0) or self.draw_contacts != self.old_draw_contacts or self.draw_unit_cell != self.old_draw_unit_cell) or self.xshifts != self.old_xshifts or self.yshifts != self.old_yshifts or self.zshifts != self.old_zshifts:
       self.symmetry = symmetry.Symmetry(self.molHnd,self.selHnd,point,tl,tr,br,bl,self.draw_unit_cell,self.xshifts,self.yshifts,self.zshifts,self.symmetry_radius,self.draw_contacts);
       self.obj.SetSymmetryMatrices(self.symmetry.GetSymmetryMatrices())
       self.obj.SetUnitCell(self.symmetry.GetUnitCell())
       self.obj.SetSymmetryMatrixNumbers(self.symmetry.GetSymmetryMatrixNumbers())
       if self.doBiomolecule:
          self.obj.SetSymmetryMatrices([])
     self.old_xshifts = self.xshifts
     self.old_yshifts = self.yshifts
     self.old_zshifts = self.zshifts
     self.old_draw_unit_cell = self.draw_unit_cell
     self.old_draw_contacts = self.draw_contacts

   def build_primitives(self,structure_changed=1):
      debug_memory = False
      if os.environ.has_key("CCP4MG_DEBUG_MEMORY"):
        debug_memory = True
      if debug_memory:
        print "Memory build_primitives 1"
        memusage.print_memory_usage()
      """
      This does the donkey work of turning MMDB selection
      data into pretty pictures. This decides how to draw bonds
      or whatever on your display criteria. It also calculates
      splines for C-alpha traces, etc.
      """
      if debug_memory:
        print "Memory build_primitives 2"
        memusage.print_memory_usage()

      #print "build_primitives, structure_changed",structure_changed

      nSelAtoms = self.nSelAtoms
      selAtoms = self.selAtoms
      origin = self.origin
      style = self.style

      if style is None or not style:
        style = "TREE"

      molHnd=self.molHnd
      selHnd=self.selHnd

      if (style == 'CIRCLES'  or style == 'SURFACE') and (self.obj and hasattr(self.obj,"SetAnchored") and callable(self.obj.SetAnchored)):
         self.obj.SetAnchored(True)
      else:
         self.obj.SetAnchored(False)

      if debug_memory:
        print "Memory build_primitives 3"
        memusage.print_memory_usage()
      self.obj.clear_prims()

      if debug_memory:
        print "Memory build_primitives 4"
        memusage.print_memory_usage()
      #print 'moleculargraphicsmodel.build_primitives',nSelAtoms,selAtoms,style,'Connectivity',self.Connectivity.GetNumberOfAtoms()
      if self.diagnostic_timing: print "STYLE 1:",style
      if style == "TREE":
         self.mode = cprim.BONDS
      else:
        tree_styles = ["BONDS","FATBONDS","THINBONDS","SPHERES","PYRAMIDS","CYLINDERS","BALLSTICK",
            'SPLINE','FATWORM','WORM','VARIABLEWORM']
        tree_modes = [cprim.BONDS,cprim.FATBONDS,cprim.THINBONDS,cprim.SPHERES,cprim.PYRAMIDS,
                        cprim.CYLINDERS,cprim.BALLSTICK,cprim.SPLINE,cprim.FATWORM,cprim.WORM,cprim.VARIABLEWORM]
        if style.startswith(model.MolDisp.custom_spline_style_prefix) and style in model.MolDisp.custom_style_methods:
           try:
             self.customWidthUDD, molHnd,selHnd = model.MolDisp.custom_style_methods[style](obj=self.obj,molHnd=self.molHnd,selHnd=self.selHnd)
             self.mode = cprim.VARIABLEWORM
           except:
             self.customWidthUDD = -1
             self.mode = cprim.WORM
           style = "TREE"                               
        elif style.startswith(model.MolDisp.custom_spline_style_prefix):
           self.customWidthUDD = -1
           self.mode = cprim.WORM
           style = "TREE"                               
        if tree_styles.count(style):         
           self.mode = tree_modes[tree_styles.index(style)]
           style = "TREE"                               
        if style == "LIPIDS":
           style = "LIPIDS"
           self.mode = cprim.LIPIDS
        if style == 'NUCLEICBASEPAIRS':
           style = "NUCLEICBASEPAIRS"
           self.mode = cprim.NUCLEICBASEPAIRS
        if style == 'CIRCLES':
           self.mode = cprim.CIRCLES
        if style == 'IMPOSTER_SPHERES':
           self.mode = cprim.IMPOSTER_SPHERES
        if style == 'ANISOU':
           self.mode = cprim.ANISOU
        if style == 'BLOB_ELLIPSOIDS':
           self.mode = cprim.BLOB_ELLIPSOIDS
        if style == 'SUGAR_BLOCKS':
           self.mode = cprim.SUGAR_BLOCKS

      if debug_memory:
        print "Memory build_primitives 5"
        memusage.print_memory_usage()
      if self.diagnostic_timing: print "STYLE 2:",style

      useVBO = False
      useVA = True

      rpm = global_definitions.PM('render_quality')
      # But not for Intel 965/963 Graphics Media Accelerator and friends.
      if sys.platform == "win32" and not sys.argv.count('-quit'):
        import opengl
        gl_renderer = opengl.glGetString(opengl.GL_RENDERER)
        useVAopt = rpm.get('force_use_va')
        if not useVAopt:
          if "Intel" in gl_renderer:
            print "Disabling use of VA on Windows with Intel GMA because of probable CCP4MG bug"
            useVA = False
         
      mainwin = global_definitions.MAINWINDOW()
      useVBOopt = rpm.get('use_vbo')
      if useVBOopt and hasattr(mainwin,"glWidget") and hasattr(mainwin.glWidget,"format") and callable(mainwin.glWidget.format):
         if hasattr(mainwin.glWidget.format(),"directRendering") and callable(mainwin.glWidget.format().directRendering):
            if mainwin.glWidget.format().directRendering()==True:
               useVBO = True

      

      if [cprim.DRAW_ALL_BONDS,cprim.DRAW_INTERNAL_BONDS].count(self.external_bonds_mode):

        if style == "SURFACE":
          self.update_conn_atoms()
          print self,"drawing a surface"
          import surface
          pm = global_definitions.PM('surface_drawing_style')
          probe_radius = pm.get('probe_radius')
          resolution_delta = pm.get('resolution_delta')*math.pi/180.0
          blend_edges =  pm.get('blend_edges')
          def calcSurface():
            print "Recalc surface"; sys.stdout.flush()
            self.surf.calculate(self.molHnd,self.selHnd,probe_radius,resolution_delta,blend_edges)
            print "Finished recalc surface"; sys.stdout.flush()

          def drawSurface():
            self.surf.ColourSurface(self.molHnd,self.selHnd, self.atomColourVector )
            surface.add_surface(self.surf,self.obj)
            self.update_surface = 0

          if (not sys.argv.count('-quit')) and sys.platform == 'linux2' and self.update_surface:
            self.surf = surface.surface()
            self.interruptButton = QtGui.QToolButton(mainwin)
            self.interruptButton.setText("Interrupt surface calculation")
            self.interruptButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon);
            icondir = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','qticons'))
            icon = QtGui.QIcon(os.path.join(icondir,"stop_sign_128x128.png"))
            self.interruptButton.setIcon(icon)
            mainwin.connect(self.interruptButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(mginterrupt.mginterrupt.SetStatus,1))
            while hasattr(self,"surfaceThread") and (self.surfaceThread.isRunning() or not self.surfaceThread.isFinished()):
              mginterrupt.mginterrupt.SetStatus(1)
              self.surfaceThread.wait()
            mginterrupt.mginterrupt.SetStatus(0)
            self.surfaceThread = UtilityThread.UtilityThread(calcSurface)
            mainwin.connect(self.surfaceThread,QtCore.SIGNAL("finished()"),drawSurface)
            mainwin.connect(self.surfaceThread,QtCore.SIGNAL("finished()"), functools.partial(mainwin.statusBar().removeWidget,self.interruptButton))
            self.surfaceThread.start()
            mainwin.statusBar().addPermanentWidget(self.interruptButton)
          else:
            if self.update_surface:
               self.surf = surface.surface()
               calcSurface()
            drawSurface()

        if style == "LIPIDS":
          self.update_conn_atoms()
          import mmut
          def calcLipids():
            t1_lipid = time.time()
            self.lipids = mmut.MMUTLipidCalculate(self.molHnd, self.selHnd,7)
            t2_lipid = time.time()
            print "Time to calculate lipids",t2_lipid-t1_lipid; sys.stdout.flush()
          def drawLipids():
            t1_lipid = time.time()
            if hasattr(self,"lipids") and len(self.lipids)>0:
              cprim.DrawLipids(self.obj, self.lipids, self.molHnd,self.atomColourVector,self.parameters.CParamsManager,self.global_parameters.CParamsManager)
            t2_lipid = time.time()
            self.lipids = []
            print "Time to draw lipids",t2_lipid-t1_lipid; sys.stdout.flush()
            if useVA: self.obj.SetUseVertexArrays(True)
            if useVBO:
              # Now it seems it can take ages to buffer the data for suitably large things,
              # on OS X snow Leopard Radeon HD 5670, so leave off until we work that out.
              if sys.platform == 'linux2':
                self.obj.SetAnchored(True)
                if useVA: self.obj.SetUseVBO(True)

          if (not sys.argv.count('-quit')) and sys.platform == 'linux2':
            self.interruptButton = QtGui.QToolButton(mainwin)
            self.interruptButton.setText("Interrupt lipid calculation")
            self.interruptButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon);
            icondir = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','qticons'))
            icon = QtGui.QIcon(os.path.join(icondir,"stop_sign_128x128.png"))
            self.interruptButton.setIcon(icon)
            mainwin.connect(self.interruptButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(mginterrupt.mginterrupt.SetStatus,1))
            while hasattr(self,"lipidThread") and (self.lipidThread.isRunning() or not self.lipidThread.isFinished()):
              mginterrupt.mginterrupt.SetStatus(1)
              self.lipidThread.wait()
            mginterrupt.mginterrupt.SetStatus(0)
            self.lipidThread = UtilityThread.UtilityThread(calcLipids)
            mainwin.connect(self.lipidThread,QtCore.SIGNAL("finished()"),drawLipids)
            mainwin.connect(self.lipidThread,QtCore.SIGNAL("finished()"), functools.partial(mainwin.statusBar().removeWidget,self.interruptButton))
            self.lipids = []
            self.lipidThread.start()
            mainwin.statusBar().addPermanentWidget(self.interruptButton)
          else:
            calcLipids()
            drawLipids()
            self.lipids = []

        if style == "NUCLEICBASEBLOCKS":
          self.update_conn_atoms()
          cprim.DrawBaseBlocks(self.obj,self.molHnd, self.selHnd, self.conn_atoms, self.conn_natoms,self.atomColourVector,self.parameters.CParamsManager)
          if useVA: self.obj.SetUseVertexArrays(True)
          if useVBO:
            if sys.platform == 'win32' or sys.platform == 'linux2' or sys.platform == 'darwin':
              self.obj.SetAnchored(True)
              if useVA: self.obj.SetUseVBO(True)

        if style == "ANISOU":
          self.update_conn_atoms()
          style = getattr(self,'anisou_style',cprim.SPHEROID_AXES)
          scale = getattr(self,'anisou_scale',1.0)
          #print "moleculargraphicsmodel",style,scale
          radVec = pygl_coord.DoubleVector(self.conn_natoms)
          for i in range(len(radVec)):
            radVec[i] = 1.0
          if self.parameters.get('anisou_scale_byvdw') == 1:
            cprim.DrawAnisoU(self.obj,self.selHnd, self.conn_atoms, self.conn_natoms,self.atomColourVector,self.atomRadii,style,scale,self.global_parameters.CParamsManager)
          else:
            cprim.DrawAnisoU(self.obj,self.selHnd, self.conn_atoms, self.conn_natoms,self.atomColourVector,radVec,style,scale,self.global_parameters.CParamsManager)
          if useVA: self.obj.SetUseVertexArrays(True)
          if sys.platform == 'win32' or sys.platform == 'linux2' or sys.platform == 'darwin':
            self.obj.SetAnchored(True)
            if useVA: self.obj.SetUseVBO(True)
          
        if style == "CIRCLES":
            self.update_conn_atoms()
            cprim.DrawCircles(self.obj,self.Connectivity,self.atomColourVector,self.parameters.CParamsManager,self.global_parameters.CParamsManager,self.stick_colour)
          
        if style == "BLOB_ELLIPSOIDS":
            self.update_conn_atoms()
            cprim.DrawBlobEllipsoids(self.obj,self.selHnd,self.Connectivity,self.atomColourVector,self.parameters.CParamsManager,self.global_parameters.CParamsManager)
            if useVA: self.obj.SetUseVertexArrays(True)
            self.obj.SetAnchored(True)
            if useVA: self.obj.SetUseVBO(True)

        if style == "SUGAR_BLOCKS":
            self.update_conn_atoms()
            cprim.DrawSugarBlocks(self.obj,self.molHnd, self.selHnd, self.conn_atoms, self.conn_natoms,self.atomColourVector,self.parameters.CParamsManager)
            if useVA: self.obj.SetUseVertexArrays(True)
            self.obj.SetAnchored(True)
            if useVA: self.obj.SetUseVBO(True)

        if style == "IMPOSTER_SPHERES":
            self.update_conn_atoms()
            cprim.DrawImposterSpheres(self.obj,self.Connectivity,self.atomColourVector,self.parameters.CParamsManager,self.global_parameters.CParamsManager,self.atomRadii)
            if useVA: self.obj.SetUseVertexArrays(True)
            self.obj.SetAnchored(True)
            if useVA: self.obj.SetUseVBO(True)
          
        if style == "NUCLEICBASEPAIRS":
          self.update_conn_atoms()
          import mmut
          if self.mode == cprim.NUCLEICBASEPAIRS:
            base_pairs = mmut.CNABasePairs()
            # FIXME - We might be able to use a "custom" one here, I guess.
            pm = global_definitions.PM('HBond_param')
            print "NUCLEICBASEPAIRS:",pm
            hb_params =  pm.getparams()
            hb_params_array = pygl_coord.doublea(8)
            hb_params_array[0] = hb_params['min_D_A']
            hb_params_array[1] = hb_params['max_D_A']
            hb_params_array[2] = hb_params['max_D_A_S']
            hb_params_array[3] = hb_params['max_H_A']
            hb_params_array[4] = hb_params['min_DD_D_A']
            hb_params_array[5] = hb_params['min_D_A_AA']
            hb_params_array[6] = hb_params['min_H_A_AA']
            hb_params_array[7] = hb_params['min_D_H_A']
            
            base_pairs.Calculate(self.molHnd, self.selHnd, self.conn_atoms, self.conn_natoms, self.atomColourVector, hb_params_array)
            spline_accu = 4
            sinfo = mmut.GetSplineInfo(self.molHnd,self.selHnd, self.atomColourVector,spline_accu,-1,-1,1,self.parameters.get('flatten_loop'))
            cprim.DrawBasePairs(self.obj,base_pairs,sinfo,self.parameters.CParamsManager)
            if useVA: self.obj.SetUseVertexArrays(True)
            self.obj.SetAnchored(True)
            if useVA: self.obj.SetUseVBO(True)
          
      if debug_memory:
        print "Memory build_primitives 6"
        memusage.print_memory_usage()
      if style == "TREE":

        if debug_memory:
          print "Memory build_primitives 6.1"
          memusage.print_memory_usage()
        ta = time.time()
        t1 = time.time()

        if debug_memory:
          print "Memory build_primitives 6.2"
          memusage.print_memory_usage()
        t2 = time.time()
        if self.diagnostic_timing:
           print "Time to do simple stuff",t2-t1
           sys.stdout.flush()

        if debug_memory:
          print "Memory build_primitives 6.3"
          memusage.print_memory_usage()
        t1 = time.time()
        self.update_conn_atoms()
        t2 = time.time()
        if debug_memory:
          print "Memory build_primitives 6.4"
          memusage.print_memory_usage()
        if self.diagnostic_timing:
           print "Time to do update_conn_atoms",t2-t1
           sys.stdout.flush()


        if debug_memory:
          print "Memory build_primitives 6.5"
          memusage.print_memory_usage()
        if nSelAtoms == 0:
           return
        #print "self.conn_natoms",self.conn_natoms

        if debug_memory:
          print "Memory build_primitives 6.6"
          memusage.print_memory_usage()
        t1 = time.time()
        self.setup_symmetry((0,0,0),[[50,-50,0],[-50,-50,0],[-50,50,0],[50,50,0]]) # The extents values are hacks, we need to know them ....
        if debug_memory:
          print "Memory build_primitives 6.7"
          memusage.print_memory_usage()
        self.obj.SetSymmetryMatrices(self.symmetry.GetSymmetryMatrices())
        if self.doBiomolecule:
          self.obj.SetSymmetryMatrices([])
        if self.diagnostic_timing:
           t2 = time.time()
           print "Time to do self.obj.SetSymmetryMatrices()",t2-t1
           sys.stdout.flush()

        if debug_memory:
          print "Memory build_primitives 6.8"
          memusage.print_memory_usage()
        bumpmap = ""
        
        if self.atomRadii:
           atomRad= self.atomRadii
        else:
           atomRad=  pygl_coord.DoubleVector(2)
        #print "moleculegr atomRad",atomRad
        
        if debug_memory:
          print "Memory build_primitives 6.9"
          memusage.print_memory_usage()
        if not [cprim.SPLINE,cprim.WORM,cprim.FATWORM,cprim.VARIABLEWORM].count(self.mode):

           if debug_memory:
             print "Memory build_primitives 7"
             memusage.print_memory_usage()
           t1 = time.time()
           if structure_changed:
             if hasattr(self,'conn_draw') and self.conn_draw:
                del self.conn_draw
             #print "ConnectivityDraw"
             tbcd = time.time()
             self.conn_draw = cprim.ConnectivityDraw()
             tacd = time.time()
             if debug_memory:
               print "Memory build_primitives 7.1"
               memusage.print_memory_usage()
             if self.diagnostic_timing: print "Time to create ConnectivityDraw",tacd-tbcd
             self.conn_draw.SetParametersAndCalculate(self.Connectivity,self.molHnd, self.obj,self.mode,self.parameters.CParamsManager,self.global_parameters.CParamsManager,nSelAtoms,self.atomColourVector,atomRad,self.splineinfo_ribbon,self.splineinfo_worm,"",bumpmap,self.stick_colour,self.side_to_ribbon,self.side_to_worm,self.external_bonds_mode)
             if debug_memory:
               print "Memory build_primitives 7.2"
               memusage.print_memory_usage()
             #self.obj.clear_prims()
             #print "Memory build_primitives 7.3 (after clear)"
             #memusage.print_memory_usage()
             taspc = time.time()
             if self.diagnostic_timing: print "Time to SetParametersAndCalculate",taspc-tacd
             #Have to write all interface stuff for this. Also not ready as it doesn't work out individual sheets.
             #cprim.build_beta_surface(self.molHnd,self.selHnd,self.obj,self.parameters.CParamsManager,self.atomColourVector)
           else:
             #print "RedrawPrimitives"
             self.conn_draw.RedrawPrimitives(self.obj,self.mode,self.parameters.CParamsManager,self.global_parameters.CParamsManager,nSelAtoms,self.atomColourVector,atomRad,"",bumpmap,self.stick_colour,self.side_to_ribbon,self.side_to_worm,self.external_bonds_mode)
             #Have to write all interface stuff for this. Also not ready as it doesn't work out individual sheets.
             #cprim.build_beta_surface(self.molHnd,self.selHnd,self.obj,self.parameters.CParamsManager,self.atomColourVector)
           t2 = time.time()
           if self.diagnostic_timing: print "Time to do build_tree_primitives",t2-t1
           if debug_memory:
             print "Memory build_primitives 8"
             memusage.print_memory_usage()
           if self.mode == cprim.SPHERES or self.mode == cprim.CYLINDERS or self.mode == cprim.BALLSTICK or self.mode == cprim.BONDS or self.mode == cprim.FATBONDS or self.mode == cprim.THINBONDS:
             if useVA: self.obj.SetUseVertexArrays(True)
             if useVBO:
               if sys.platform == 'win32' or sys.platform == 'linux2' or sys.platform == 'darwin':
                 self.obj.SetAnchored(True)
                 if useVA: self.obj.SetUseVBO(True)
        else:
           if [cprim.DRAW_ALL_BONDS,cprim.DRAW_INTERNAL_BONDS].count(self.external_bonds_mode):
             import mmut
             sys.stdout.flush()
             self.update_conn_atoms()

             theMode = self.mode

             def calcSpline():

               spline_accu = 4+self.global_parameters.get('solid_quality')*4
               if theMode == cprim.SPLINE or theMode == cprim.FATWORM :
                 t1 = time.time()
                 if theMode == cprim.SPLINE:
                   self.sinfo = mmut.GetSplineInfo(self.molHnd,self.selHnd, self.atomColourVector,spline_accu,-1,-1,self.parameters.get('flatten_beta'),self.parameters.get('flatten_loop'),0,self.parameters.get('trace_cutoff'),self.parameters.get('loop_frac'))
                 else:
                   self.sinfo = mmut.GetSplineInfo(self.molHnd,self.selHnd, self.atomColourVector,spline_accu,-1,-1,self.parameters.get('flatten_beta'),self.parameters.get('flatten_loop'),1,self.parameters.get('trace_cutoff'),self.parameters.get('loop_frac'))
                 t2 = time.time()
                 if self.diagnostic_timing: print "Time to do get spline",t2-t1
               elif theMode ==cprim.VARIABLEWORM:
                 t1 = time.time()
                 self.sinfo = mmut.GetSplineInfo(molHnd,selHnd, self.atomColourVector,spline_accu,-1,-1,0,self.parameters.get('flatten_loop'),0,self.parameters.get('trace_cutoff'),self.parameters.get('loop_frac'),self.customWidthUDD)
                 t2 = time.time()
                 if self.diagnostic_timing: print "Time to do get spline",t2-t1
               else:
                 t1 = time.time()
                 self.sinfo = mmut.GetSplineInfo(self.molHnd,self.selHnd, self.atomColourVector,spline_accu,-1,-1,0,self.parameters.get('flatten_loop'),0,self.parameters.get('trace_cutoff'),self.parameters.get('loop_frac'))
                 t2 = time.time()
                 if self.diagnostic_timing: print "Time to do get spline",t2-t1

             def drawSpline():
               #print "drawSpline"
               if hasattr(self,"sinfo") and self.sinfo != None:
                 t1 = time.time()
                 cprim.build_spline(self.sinfo,self.obj,theMode,self.parameters.CParamsManager,self.global_parameters.CParamsManager,"",bumpmap)
                 t2 = time.time()
                 if self.diagnostic_timing: print "Time to do draw spline",t2-t1
               self.sinfo = None
               if useVA: self.obj.SetUseVertexArrays(True)
               if useVBO:
                 if sys.platform == 'win32' or sys.platform == 'linux2' or sys.platform == 'darwin':
                   self.obj.SetAnchored(True)
                   if useVA: self.obj.SetUseVBO(True)

               if mainwin and hasattr(mainwin,"glWidget") and hasattr(mainwin.glWidget,"updateGL"):
                  mainwin.glWidget.updateGL()

             if False and (not sys.argv.count('-quit')) and sys.platform == 'linux2':
               while hasattr(self,"splineThread") and (self.splineThread.isRunning() or not self.splineThread.isFinished()):
                 mginterrupt.mginterrupt.SetStatus(1)
                 self.splineThread.wait()
               mginterrupt.mginterrupt.SetStatus(0)
               self.splineThread = UtilityThread.UtilityThread(calcSpline)
               mainwin.connect(self.splineThread,QtCore.SIGNAL("finished()"),drawSpline)
               self.sinfo = None
               self.splineThread.start()
             else:
               calcSpline()
               drawSpline()
               self.sinfo = None

           if useVA: self.obj.SetUseVertexArrays(True)
           if useVBO:
             if sys.platform == 'win32' or sys.platform == 'linux2' or sys.platform == 'darwin':
               self.obj.SetAnchored(True)
               if useVA: self.obj.SetUseVBO(True)

        tb = time.time()
        if debug_memory:
          print "Memory build_primitives 9"
          memusage.print_memory_usage()

        """
        Since primitives are by default non-transparent we set them all ot be transparent if
        the displayobject has the transparency flag set. This means we can change drawing style and
        maintain transparency.
        """
        if self.obj.get_transparent():
           self.obj.set_transparent(1)

        if self.diagnostic_timing: print "Time to build it all",tb-ta

      elif not style in ["LIPIDS","SURFACE","NUCLEICBASEBLOCKS","NUCLEICBASEPAIRS","ANISOU","CIRCLES"]:
        if style in model.MolDisp.custom_style_methods and not style.startswith(model.MolDisp.custom_spline_style_prefix):
           model.MolDisp.custom_style_methods[style](obj=self.obj,molHnd=self.molHnd,selHnd=self.selHnd,atomColourVector=self.atomColourVector,params=self.parameters.CParamsManager,global_params=self.global_parameters.CParamsManager)

   def do_update_surface(self,update_surface=1):
      self.update_surface = update_surface

   def change_style(self,style):
      """
      Request recalculation of an objects
      primitives based on new representation type.
      """
      self.style = style
      self.rebuild()

