"""
     python/ui/picture_definition.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.
"""
from global_definitions import *
from picture_definition_classes import ParamsManager
import utils
import version

reqRunAfterModelLoad = []

class picture_definition:
  insts = ''
  preferences = {}
  preferences['content'] = {
                'create_DispObj' : 1,
                'keep_current' : 0 }
  preferences['order'] = ['keep_current','create_DispObj']
  preferences['export'] = 1

  def __init__(self):
    picture_definition.insts = self
    self.colour_export_objects = {'COLOUR' : 1 }
    self.pm_all = 0
    self.save_visible = 0
  

    
#---------------------------------------------------------------------------
  def save_picture_definition(self,filename='',DIR_filename='',
            limited_save=1,save_visible = '',
            save_list=['view','colours','display','params'],
            style='method',**keywords):
#---------------------------------------------------------------------------

    if filename:
    
      import pprint,sys,dataobj,time
      import services
      
      filename = utils.get_filename(DIR_filename,filename)

      active_colour_schemes = []
      header = '''# CCP4mg picture definition file
# See http://www.ysbl.york.ac.uk/~ccp4mg/ccp4mg_help/picture_definition.html
# or your local copy of CCP4mg documentation.
# CCP4mg version '''+  version.ccp4mg_version +'''
# Created ''' + str(time.asctime(time.localtime())) + '\n\n\n'
      choices_stream = 'CHOICES = [\n'
      stream = ''
      pretty_print = pprint.PrettyPrinter()

      all = not int(limited_save)
      if save_visible: self.save_visible = int(save_visible)

      #if picture_definition.preferences['export']:
      #    stream = stream + utils.picture_defn_item('preferences',picture_definition.preferences['content'],pretty_print,indent=0,dict_order=picture_definition.preferences['order'])

      for item in save_list:
        if item == 'view':
          style = 'method'
          indent = 5
          # Save the view
          view_params = MAINWINDOW().getViewParams()
          stream = 'view = View ('
          stream = stream+utils.picture_defn_item('orientation',view_params['quat'],pretty_print,style=style,indent=indent)
          stream = stream+utils.picture_defn_item('centre_xyz',view_params['pos'],pretty_print,style=style,indent=indent)
          stream = stream+utils.picture_defn_item('scale',view_params['scale'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('fog_enabled',view_params['fog_enabled'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('fog_near',view_params['fog_near'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('fog_far',view_params['fog_far'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('slab_enabled',view_params['slab_enabled'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('slab_width',view_params['slab_width'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('slab_offset',view_params['slab_offset'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('clip_cap',view_params['clip_cap'],pretty_print,style=style,indent=indent) 
          stream = stream+utils.picture_defn_item('customClipPlanes',view_params['customClipPlanes'],pretty_print,style=style,indent=indent) 
          stream = stream + '          )\n\n'

        elif item == 'colours':
          #Save colours
          if  self.colour_export_objects.has_key('COLOUR'):
            stream = stream + MGCOLOUR().save_picture_definition(pretty_print=pretty_print,all=self.pm_all)

        elif item == 'display':
          label_num = ['second','third','fourth']
          choices_stream = '#SECTION CHOICES\n\nCHOICES = [\n'
          ntype = {}

          # Save any generic user selection/colour schemes that are currently used
          generic_schemes = []
          for obj in get_dataobj(object_type='MolData'):
            scms = obj.get_open_schemes()
            for item in scms:
              if not generic_schemes.count(item): generic_schemes.append(item)
          #print "picture_definition generic_schemes",generic_schemes

          if generic_schemes: stream = stream + MODELINFO().save_picture_definition(pretty_print=pretty_print,set='generic',info='user_selection',keys=generic_schemes)

          generic_schemes = []
          for obj in get_dataobj(object_type='MolData'):
            scms = obj.get_open_schemes(info="user_colour_schemes")
            for item in scms:
              if not generic_schemes.count(item): generic_schemes.append(item)
          if generic_schemes: stream = stream + MODELINFO().save_picture_definition(pretty_print=pretty_print,set='generic',info='user_colour_schemes',keys=generic_schemes)

          for object_type in dataobj.DATAOBJ_TYPES:
            for obj in dataobj.get_dataobj(object_type=object_type):
              if (not self.save_visible) or obj.visible:
                shadowobj = dataobj.DataObjShadow()
                rv = shadowobj.save(obj,all=all)
                if rv:
                  del shadowobj
                else:
                  stream = stream + shadowobj.save_picture_definition(pretty_print=pretty_print,style=style)
                                    # Add .ccp4mg file info for MolData objects
                  if object_type == 'MolData':
                    stream = stream + MODELINFO().save_picture_definition(pretty_print=pretty_print,set=obj.name_label,info='user_selection')
                    stream = stream + MODELINFO().save_picture_definition(pretty_print=pretty_print,set=obj.name_label,info='user_colour_schemes')
                  # Add an element to the CHOICES list
                  label = ''
                  if ntype.has_key(object_type):
                    ntype[object_type] = ntype[object_type]+1
                    if ntype<=4: label=label_num[ntype-1]
                  else:
                    ntype[object_type] = 1
                  if object_type != 'MolData':
                    label = label + object_type[0:-4]
                  else:
                    label = label + 'model'
                  name = object_type+str(ntype[object_type])
                  choices_stream = choices_stream + \
                    "    { 'name' : '"+name+"', " + \
                    "'type' : '"+object_type+"', " + \
                    "'label' : 'Select "+label+"', " + \
                    "'multi' : 0 },\n"                                                                                       
                  if style != 'mgpic': name=''
                  for disp in shadowobj.objinsts:
                    if (not self.save_visible) or disp.visible:
                      if not style == 'mgpic' or not ['Crystal','Legend','Image'].count(disp.object_type):
                        stream = stream + disp.save_picture_definition(pretty_print=pretty_print,style='method',parent=name)
                        if hasattr(disp,'colparams'):
                          if services.ColourSchemeManager.colour_pref_alias.count(disp.colparams.get('colour_mode','')):
                            active_colour_schemes.append(disp.colparams.get('colour_mode',''))
                          
                 
                  choices_stream = choices_stream[0:-2]+ '\n      ]\n\n'
        elif item == 'params':
          # Save ParamsManagers etc
          for pm in PM('all'):
            if pm.picture_definition>0: stream = stream + pm.save_picture_definition(pretty_print=pretty_print,all=self.pm_all)
          #print "active_colour_schemes",active_colour_schemes
          for pm in active_colour_schemes:
            obj = PM(name=pm)
            if obj: stream = stream + obj.save_picture_definition(pretty_print=pretty_print,all=self.pm_all)

	  stream = stream + 'ParamsManager(\n'
	  stream = stream + "          name = 'gui_params',\n"
	  stream = stream + "          show_axes = " + str(MAINWINDOW().glWidget.getAxes()) + ",\n"
	  stream = stream + "          background_colour = " + str(MAINWINDOW().glWidget.getBackground()) + "\n"
	  stream = stream + ')\n'

	  lights = MAINWINDOW().glWidget.getLights()
	  import opengl
	  ls = {}
	  nlights = 0
	  for i,light in zip(range(len(lights)),lights):
		  l = {}
		  if light and light.has_key("depth") and light.has_key("pos"):
		  	l['position'] = [light["pos"].x(),light["pos"].y(),light["depth"]]
			l['ambient'] = light['params'][opengl.GL_AMBIENT]
			l['specular'] = light['params'][opengl.GL_SPECULAR]
			l['diffuse'] = light['params'][opengl.GL_DIFFUSE]
			l['on'] = 1
			ls[str(i)] = l
			nlights = nlights + 1
	  stream = stream + '\nParamsManager(\n'
	  stream = stream + "     name = 'light_params',\n"
          stream = stream + utils.picture_defn_item('lights',ls,pretty_print,style='method',indent=indent) 
	  stream = stream + '\n     nLights = ' + str(nlights) + '\n'
	  stream = stream + ')\n'

          for object_type in dataobj.PLUGIN_DATAOBJ_TYPES:
            for obj in dataobj.get_dataobj(object_type=object_type):
                stream = stream + obj.save_picture_definition(pretty_print=pretty_print,style=style)

          for plug in MAINWINDOW().plugins:
            if hasattr(plug,"save_picture_definition") and callable(plug.save_picture_definition):
              try:
                stream = stream + plug.save_picture_definition(pretty_print=pretty_print,style=style)
              except:
                print "call of",plug,"save_picture_definition failed"
                pass


      if style == 'mgpic':
        stream = header + "#SECTION TITLE\n\n#SECTION NOTES\n\n" + choices_stream + "#SECTION SCRIPT\n\n\nglobal ERROR_MESSAGE\n\n" + stream
      else:       
        stream = header + stream
      utils.saveFile(filename,text=stream)
      #print stream
      return 0

  def loadShadowPlugins(self):
      import os, glob
      pluginpaths=os.path.join(os.environ["CCP4MG"],os.path.join('qtgui','plugins'))
      plugins =  glob.glob(os.path.join(pluginpaths,'*'))
      modules = []
      modules.extend(glob.glob(os.path.normpath(os.path.join(pluginpaths,'*_Shadow.py'))))
      for pluginpath in plugins:
        modules.extend(glob.glob(os.path.normpath(os.path.join(pluginpath,'*_Shadow.py'))))
      return modules

#---------------------------------------------------------------------------
  def read_picture_definition(self,filename='',trap_errors=-1,default_dir=''):
#---------------------------------------------------------------------------
    import re
    import os,exceptions,pprint
    if trap_errors<0: trap_errors = 1-DEVELOPER()
    
    message = ''
    globs = {}
    #print "Setting globs['default_dir']",default_dir
    globs['default_dir'] = default_dir
    locs = {}
    try:
      execfile(os.path.join(os.environ["CCP4MG"],'python','ui','picture_definition_classes.py'),globs)
      plugs = self.loadShadowPlugins()
      for plug in plugs:
        execfile(plug,globs)
    except  StandardError, e:
      message = message + 'Error loading picture_definition_classes.py'
      print e.args
    if trap_errors:
      try:
        execfile(filename,globs,locs)
      except StandardError, e:
        message = message + 'Error reading '+filename
          
        if isinstance(e,exceptions.SyntaxError) and e.offset:
          spaces=''
          for i in range(0,e.offset): spaces = spaces+' '
          message = message + 'Invalid syntax in line '+ str(e.lineno)+ \
                       ':\n\n'+ re.sub('\n','',e.text) +'\n' + \
                       spaces + '*\n\n' + \
                       '(Hint: also check preceeding line)\n'
        else:
          pp = pprint.PrettyPrinter()
          message = message + pp.pformat(e.args)

        # Keep this diagnostic to go to log file
        print "Error reading ",filename,e.args
    else:
      # Let it crash
      execfile(filename,globs,locs)
    #print 'locs',locs
    return [message,globs,locs]
      
#---------------------------------------------------------------------------
  def restore_picture_definition(self,filename='',DIR_filename='',trap_errors=-1,test=0,keep_current=0,override_visible=1,restore_list=['view','colours','display','params'],delay_delete=0,default_dir='',**keywords):
#---------------------------------------------------------------------------

    if trap_errors<0: trap_errors = 1-DEVELOPER()
    if not filename: return [1,'']
      
    import dataobj,os,exceptions,re,pprint,picture_definition_classes
    
    #Delete existing loaded data?
    delete_list = []
    if not keep_current:
      for obj in dataobj.DataObj.dataobj_insts: delete_list.append(obj)
      if not delay_delete:
        for obj in delete_list: obj.delete()
      else:
        # NEED TO ENSURE OBJECTS REDRAW NOT TRIGGERED BY CHANGED PARAMETERS
        pass


    if default_dir == '':
       default_dir = os.path.dirname(filename)

    filename = utils.get_filename(DIR_filename,filename)
    if not os.path.exists(filename): return [1,'']

    ccp4mg_version_str = version.ccp4mg_version
    print "restore_picture_definition",filename
    try:
      f = open(filename)
      lines = f.readlines()
      for l in lines:
        if l.startswith("# CCP4mg version "):
          ccp4mg_version_str = l[len('# CCP4mg version '):].rstrip()
          break
      f.close()
    except:
      ccp4mg_version_str = version.ccp4mg_version

    old_colours=False
    MGCOLOUR().usingOldColours = False
    ccp4mg_version = utils.parseVersion(ccp4mg_version_str)
    print 'Reading status file from version',ccp4mg_version
    if ccp4mg_version[0] >= 2 and ccp4mg_version[1] <= 5 and ccp4mg_version[2] < 3:
      #print "Need to use old colours"
      old_colours=True

    if old_colours:
        MGCOLOUR().rgbreps = []
        MGCOLOUR().n_standard_rgbreps = 0
        MGCOLOUR().RGBReps.clear()
        MGCOLOUR().usingOldColours = True
        MGCOLOUR().load_old_default()
    else:
        MGCOLOUR().rgbreps = []
        MGCOLOUR().n_standard_rgbreps = 0
        MGCOLOUR().RGBReps.clear()
        MGCOLOUR().load_default()
    MGCOLOUR().initialiseRGBReps()

    message,globs,locs = self.read_picture_definition(filename,trap_errors,default_dir=default_dir)

    #Everything OK?
    if message:
      MGGUI().WarningMessage(message,help='picture_definition',target='errors')
      return [1,message]
    elif  globs['ERROR_MESSAGE']:
      message = 'Error interpreting '+filename +'\n\n'
      for line in globs['ERROR_MESSAGE']:
        message = message + line + '\n'
      MGGUI().WarningMessage(message,help='picture_definition',target='errors')
      return [1,message]
      

    if restore_list.count('colours') and globs['Colours'].insts:
      #print "Setting (picdef)",globs['Colours'].insts[0].params
      for key,value in globs['Colours'].insts[0].params:
        indx = MGCOLOUR().index(key,safe=0)
        if indx>=0:
          MGCOLOUR().reset(name=key,newrgb=value)
        else:
          MGCOLOUR().new(newname=key,newrgb=value)

    
    #Sort out preferences
    preferences = {
      'create_DispObj' : 1 }
    if locs.has_key('preferences'): preferences.update(locs['preferences'])
    for key in preferences.keys():
     if keywords.has_key(key): preferences[key] = int(keywords[key])

    if restore_list.count('display'):
      if globs['CrystalList']:
        xtl=dataobj.DataObjShadow(name='CrystalData',object_type='CrystalData',objinsts=globs['CrystalList'])

      if globs['twoDList']:        
        twoD=dataobj.DataObjShadow(name='GL2dScreen',object_type='GL2dScreen',objinsts=globs['twoDList'])
        
      #Everything OK?
      if message:
        MGGUI().WarningMessage(message,help='picture_definition',target='errors')
        return [1,message]
      if test: return [0,'']
        
    # Try restoring ParamsManagers first
    PM_remaining = []
    pm = None
    if restore_list.count('params'):
      import picture_definition_classes
      for obj in globs['ParamsManager'].insts:
        pm = PM(obj.name)
        if pm:
          pm.restore_picture_definition(params=obj.params)
        else:
          import services
          if obj.name.startswith('HBond_drawing_style'):
            import HBonds
            pm = HBonds.createDrawingStylePM(name=obj.name)
            pm.setparams(obj.params)
          PM_remaining.append(obj)
      globs['ParamsManager'].insts = []
      #print "PM_remaining",PM_remaining

      # Load any colour scheme managers
      for obj in globs['ColourSchemeManager'].insts:
        pm = PM(obj.name)
        if pm:
          pm.restore_picture_definition(params=obj.params)
      globs['ColourSchemeManager'].insts = []

      
    override_visible=int(override_visible)
    if restore_list.count('display'):

      #Unpack any inline data
      for obj in globs['InlineList']:
        rv = obj.unpack()
        if rv[0]:  message = message + rv[1] + '\n'
      del  globs['InlineList']

      #Restore any generic SelectionSchemes
      import model_selection
      SelParser = None
      for scheme in globs['SelectionSchemeList']:
        if scheme.parent_obj == 'generic':
          #print "restoring generic SelectionScheme",scheme.name
          if not SelParser: SelParser=model_selection.SelectionParser()
          stat,sel =SelParser .command_to_list(scheme.selection)
          if stat:
            message = message+"Can not interpret SelectionScheme "+scheme.name+'\n'
          else:
            rv = MODELINFO().add_info(set='generic',info='user_selection',
              key=utils.oneWord(scheme.name),value=sel)
            
      for scheme in globs['ColourSchemeList']:
        if scheme.parent_obj == 'generic':
          #print "restoring generic ColourScheme",scheme.name
          com2list = []
          for col,sel in scheme.colours:
            if not SelParser: SelParser=model_selection.SelectionParser()
            stat,listsel = SelParser.command_to_list(sel)
            if not stat: com2list.append([col,listsel,{}])
          #print "restoring  ColourScheme",scheme.name,com2list
          if not com2list:
            message = message+"Can not interpret ColourScheme "+scheme.name+'\n'
          else:
            #print "user_colour_schemes",scheme.name,com2list
            stat = MODELINFO().add_info( \
                set='generic',info='user_colour_schemes',
                key=utils.oneWord(scheme.name),value=com2list)

      data_old_colours = False
      for obj in globs['DataList']:
        
        if hasattr(obj,"dataparams"):
          if not obj.dataparams.has_key("ccp4mg_creator_version"):
             obj.dataparams["ccp4mg_creator_version"] = ccp4mg_version_str
          ccp4mg_creator_version = utils.parseVersion(obj.dataparams["ccp4mg_creator_version"])
          if ccp4mg_creator_version[0] >= 2 and ccp4mg_creator_version[1] <= 5 and ccp4mg_creator_version[2] < 3:
            #print "Need to use old colours because object needs them."
            data_old_colours = True
          print ccp4mg_creator_version
          if data_old_colours and not old_colours:
            MGCOLOUR().rgbreps = []
            MGCOLOUR().n_standard_rgbreps = 0
            MGCOLOUR().RGBReps.clear()
            MGCOLOUR().usingOldColours = True
            MGCOLOUR().load_old_default()
            MGCOLOUR().initialiseRGBReps()
            old_colours = True
            if restore_list.count('colours') and globs['Colours'].insts:
              #print "Setting (picdef)",globs['Colours'].insts[0].params
              for key,value in globs['Colours'].insts[0].params:
                indx = MGCOLOUR().index(key,safe=0)
                if indx>=0:
                  MGCOLOUR().reset(name=key,newrgb=value)
                else:
                  MGCOLOUR().new(newname=key,newrgb=value)

        print "restoring from",filename
        rv = obj.restore(default_dir=default_dir)
        if rv[1]: message = message+rv[1]+'\n'
        
        if not rv[0]:
          for scheme in globs['SelectionSchemeList']:
            if  scheme.parent_obj == obj:
              stat,sel = obj.dataobj.command_to_list(scheme.selection)
              #print "saving  SelectionScheme",scheme.name,obj.dataobj.name
              if stat:
                message = message+"Can not interpret SelectionScheme "+scheme.name+'\n'
              else:
                stat = MODELINFO().add_info( \
                  set=obj.dataobj.name,info='user_selection',
                  key=utils.oneWord(scheme.name),value=sel)

          for scheme in globs['ColourSchemeList']:
            if  scheme.parent_obj == obj:
              com2list = []
              for col,sel in scheme.colours:
                stat,listsel = obj.dataobj.command_to_list(sel)
                if not stat: com2list.append([col,listsel,{}])
              #print "restoring  ColourScheme",scheme.name,obj.dataobj.name,com2list
              if not com2list:
                message = message+"Can not interpret ColourScheme "+scheme.name+'\n'
              else:
                #print "user_colour_schemes",scheme.name,com2list
                stat = MODELINFO().add_info( \
                  set=obj.dataobj.name,info='user_colour_schemes',
                  key=utils.oneWord(scheme.name),value=com2list)
        
          rv =  obj.restore_display_objects(override_visible=override_visible)
          if rv[1]: message = message+rv[1]+'\n'

    
      if globs['twoDList']:
        if not keep_current or not get_dataobj('Legends&Images'):
          rv = twoD.restore()
          if rv[1]: message = message+rv[1]+'\n'
        else:
          twoD.set_dataobj(get_dataobj('Legends&Images')[0])
        rv =  twoD.restore_display_objects(override_visible=override_visible)
        if rv[1]: message = message+rv[1]+'\n'
      
      if globs['CrystalList']:
        if not keep_current or not get_dataobj('CrystalData'):
          rv = xtl.restore()
          if rv[1]: message = message+rv[1]+'\n'
        else:
          xtl.set_dataobj(get_dataobj('CrystalData')[0])
        rv =  xtl.restore_display_objects(override_visible=override_visible)
        if rv[1]: message = message+rv[1]+'\n'
  

    # Try restoring any remaining PMs - they may have been
    # associated with a DataObj or DispObj
    for obj in  PM_remaining:
      if obj.name == "gui_params":
        MAINWINDOW().setParams(params=obj.params)
      elif obj.name == "light_params":
        import copy
        ps = copy.deepcopy(obj.params)
        if hasattr(ps,'has_key') and ps.has_key('lights') and ps.has_key('nLights'):
          ps2 = ps['lights']
	  # Fudge to deal with the fact that keys may be
	  # strings rather than ints in pic def file.
	  ps3 = copy.deepcopy(ps2)
	  for key in ps2: ps3[int(key)] = ps3[key]
          ps3['nLights'] = ps['nLights']
          MAINWINDOW().setLightParams(ps3)
      else:
        pm = PM(obj.name)
        if pm:
          pm.setparams(obj.params)
          #pm.restore_picture_definition(params=obj.params)
        else:
          message = message + "Can not restore the ParamsManager: "+obj.name+'\n'
    del PM_remaining

    if restore_list.count('view') and globs['View'].insts:
      MAINWINDOW().setViewParams(params= globs['View'].insts[0].params)

    for p in reqRunAfterModelLoad:
      if hasattr(p,"runAfterModelLoad") and callable(p.runAfterModelLoad):
         p.runAfterModelLoad()

    if delay_delete:
      import rebuild,time
      rebuild.UpdateDisplay()
      time.sleep(1.0)     
      for item in delete_list: item.delete()
      del delete_list      
      
    print message
    if message:
      MGGUI().WarningMessage(message,help='picture_definition',target='errors')
      return [1,message]

    del locs,globs

    return [0,'']

  
#----------------------------------------------------------------------
  def loadInlinePDB(self,filename,mode='mman',name=''):
#----------------------------------------------------------------------
    message,globs,locs=self.read_picture_definition(filename)
    #print 'picture_definition.loadInlinePDB',message
    if message:
       return [1,'Error extracting data from file\n'+filename]

    #Unpack any inline data to a pdb file
    if not  globs['InlineList']:
      return [1,'No inline data in file\n'+filename]
    import os
    pdbfile = os.path.splitext(filename)[0]+'.pdb'
    #print 'picture_definition.loadInlinePDB',pdbfile
    rv = globs['InlineList'][0].unpack(pdbfile)
    if rv[0]:
       return [1,'No extracting inline data from file\n'+filename]

    if mode == 'MolData':
      import model
      m = model.MolData (filename=pdbfile,name=name)
      rv = m.loaddata(warnings=1)
      if rv[0]==1:
         m.delete()
         return [1,'Error loading file: '+filename+'\n'+rv[1]]
      return [0,m]
    else:
      import mmut
      import mmdb2 as mmdb
      if mode == 'mman':
        molHnd = mmut.CMMANManager(RESOURCES().SRS,RESOURCES().CMolBondParams)
      else:
        # Make MMDBManager of the PDB
        molHnd = mmdb.Manager()
        
      molHnd.SetFlag(mmdb.MMDBF_IgnoreRemarks)
      molHnd.SetFlag(mmdb.MMDBF_IgnoreBlankLines)
      molHnd.SetFlag(mmdb.MMDBF_IgnoreHash)
      #molHnd.SetFlag(mmdb.MMDBF_EnforceUniqueChainID)
      #molHnd.ReadCoorFile(pdbfile)
      utils.ReadCoorFile(molHnd,pdbfile)
      return [0,molHnd]
    
