""" python/ui/Superpose.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 sys from mgapp import * from mmut import * import mmut from dataobj import * from Application import * from global_definitions import * import cprim import copy import os import tempfile import subprocess import pygl_coord ''' Methods ssm - Secondary structure (SSM) close - Close atoms lsq - least square fit of seletected range(s) of residues interactive - least square fit of interactivelt seelcted atoms/residues/ranges/ligands ''' class Superpose(Application): insts = None initialisation = { 'method': 'ssm', 'fixed' : '', 'show_equiv_mol' : '', 'show_equivalents': 0, 'show_distances' : 1, 'show_mask' : 0, 'close_atoms_central_atom' : ' CA ', 'close_atoms_res_cutoff' : 2.0, 'close_atoms_cutoff' : 1.0, 'close_atoms_initial_global' : 0, 'monomer_keep_matches' : 0, 'selected_atoms_mode' : 'catrace', 'selected_atoms_selection' : ['CA','CB'], 'apply_interactive_all' : 0, 'conn_colour' : 'black', 'fixed_mask_colour' : 'yellow', 'moving_mask_colour' : 'magenta' } #selected_atoms_mode_menu = ['CA','main chain',"nucleic P,C1'",'user defined','all equivalent'] #selected_atoms_mode_alias = ['catrace','main','nucleic','user','all'] selected_atoms_mode_menu = ['CA','main chain',"nucleic P,C1'",'all equivalent','user defined'] selected_atoms_mode_alias = ['catrace','main','nucleic','all','user'] #------------------------------------------------------------------------- def __init__(self,params={},**keywords): #------------------------------------------------------------------------- Superpose.insts = self self.supModel = {} for key,value in Superpose.initialisation.items(): setattr(self,key,value) Application.__init__(self,'Superpose') if not ['ssm','close','interactive'].count(self.method): self.setparams({'method':'ssm'}) self.setparams({'submethod':'ssm'}) self.gesamt_out = "" self.initiallise_status() #------------------------------------------------------------------------ def initiallise_status(self): #------------------------------------------------------------------------ self.set_default_fixed() # Are current supModel still loaded? for model,supModel in self.supModel.items(): molobj = data(model) if not molobj: supModel.delete() del self.supModel[model] for molobj in get_dataobj(object_type='MolData'): self.add_MolData(molobj.name) self.set_show_equiv_mol() #------------------------------------------------------------------------ def add_MolData(self,mol): #------------------------------------------------------------------------ import model molobj =data(mol) #print "Superpose.add_MolData molobj",mol,molobj if not molobj or molobj.object_type != 'MolData': return 1 if not self.supModel.has_key(mol): self.supModel[mol] = SuperposeModel(self,mol,self.fixed,1) self.add_dependency(molobj,['delete'],[self.handle_delete_MolData]) self.add_dependency(molobj,['rename'],[self.handle_rename_MolData]) self.add_dependency(molobj,['transform'],[self.handle_transform_MolData]) return 0 def GetSuperposeModel(self,name): return self.supModel.get(name,None) def GetSuperposeModelMatch(self,name,imatch): sm = self.supModel.get(name,None) if sm: if imatch>=0 and imatch<len(sm.matches): return sm.matches[imatch] return None #------------------------------------------------------------------------- def close(self): #------------------------------------------------------------------------- #print 'Superpose.close' for model,supModel in self.supModel.items(): supModel.handle_close_application() self.draw() Application.close(self) #------------------------------------------------------------------------- def unclose(self): #------------------------------------------------------------------------- #print 'Superpose.unclose' self.set_show_equivalents(self.show_equivalents) self.set_show_mask(self.show_mask) for model,supModel in self.supModel.items(): supModel.handle_unclose_application() self.draw() #---------------------------------------------------------------------------- def Exit(self): #---------------------------------------------------------------------------- for model,supModel in self.supModel.items(): supModel.save_matches() #---------------------------------------------------------------------------- def delete(self): #---------------------------------------------------------------------------- for model,supModel in self.supModel.items(): supModel.delete() Superpose.insts = [] Application.delete(self) self.delete_graphobj() #----------------------------------------------------------------------- def getparams(self): #----------------------------------------------------------------------- import types pars = {} for key in Superpose.initialisation.keys(): pars[key] = getattr(self,key) pars['superposeModels'] = {} for model,supModel in self.supModel.items(): pars['superposeModels'][model] = supModel.getparams() #print 'Superpose.getparams',pars return pars #------------------------------------------------------------------------- def set_default_fixed(self): #------------------------------------------------------------------------- objlist = get_dataobj(object_type='MolData') namelist = [] for obj in objlist: namelist.append(obj.name) if namelist.count(self.fixed): namelist.remove(self.fixed) else: self.fixed = '' if namelist.count(self.show_equiv_mol): namelist.remove(self.show_equiv_mol) else: self.show_equiv_mol = '' if not self.fixed and len(namelist)>0: self.fixed = namelist[0] namelist.remove(self.fixed) if not self.show_equiv_mol and len(namelist)>0: self.show_equiv_mol = namelist[0] #print 'Superpose.set_default_fixed',self.fixed,self.show_equiv_mol #------------------------------------------------------------------------- def set_fixed(self,fixed): #------------------------------------------------------------------------- # Save the current matches to MODELINFO for model,supModel in self.supModel.items(): if model != self.fixed: supModel.save_matches() if fixed and fixed != self.fixed: self.fixed = fixed self.set_default_fixed() for model,supModel in self.supModel.items(): supModel.set_fixed(self.fixed) self.do_redraw = 1 #------------------------------------------------------------------------- def set_show_equiv_mol(self,show_equiv_mol=''): #------------------------------------------------------------------------- if show_equiv_mol: if show_equiv_mol == self.fixed: return 1 self.show_equiv_mol = show_equiv_mol for model,supModel in self.supModel.items(): supModel.set_show_connectivity(int(self.show_equivalents and (model == self.show_equiv_mol))) supModel.set_show_mask(int(self.show_mask and [self.fixed,self.show_equiv_mol].count(model))) supModel.do_redraw = 1 #------------------------------------------------------------------------- def set_show_equivalents(self,show_equivalents): #------------------------------------------------------------------------- #if show_equivalents == self.show_equivalents: return self.show_equivalents = show_equivalents if self.show_equiv_mol: self.supModel[self.show_equiv_mol].set_show_connectivity(self.show_equivalents) self.supModel[self.show_equiv_mol].do_redraw =1 #------------------------------------------------------------------------- def set_show_mask(self,show_mask): #------------------------------------------------------------------------- #if show_mask == self.show_mask: return self.show_mask = show_mask for model in (self.show_equiv_mol,self.fixed): if model: self.supModel[model].set_show_mask(show_mask) #------------------------------------------------------------------------- def set_colour(self,mode='',colour=''): #------------------------------------------------------------------------- setattr(self,mode,colour) #print 'Superpose.set_colour',mode,colour if self.show_equiv_mol: self.supModel[self.show_equiv_mol].do_redraw =1 #------------------------------------------------------------------------- def setparams(self,params={},**kw): #------------------------------------------------------------------------- params.update(kw) print "Superpose.setparams",params for key,value in params.items(): if ['fixed','show_equiv_mol'].count(key): if data(value): setattr(self,key,value) for key,value in params.items(): if key == 'superposeModels': for model,pars in params['superposeModels'].items(): # Test that the MolData object is loaded #print 'Superpose.setparams',model,pars molobj = data(model) if molobj: if not self.supModel.has_key(model): self.supModel[model] = SuperposeModel(self,model,self.fixed,1) self.supModel[model].setparams(pars) #if self.method == 'interactive': self.supModel[model].update_Connectivity2() elif key == 'method' and value != self.method: if self.method == 'interactive': for model,supModel in self.supModel.items(): supModel.clear_Connectivity2() self.method = value if self.method == 'interactive': for model,supModel in self.supModel.items(): supModel.update_Connectivity2() elif key == 'selected_atoms_selection': # make sure selected_atoms_selection is a list - confusion from pre 1.113 # and handle the text value sent by the gui import types if isinstance(value,types.StringType): self.set_user_selected_atoms(value) else: setattr(self,key,value) elif key == 'close_atoms_central_atom': # Needs to have correct format for mmdb atom name atnam = value.strip()[0:3] if len(atnam)==3: atnam = ' '+atnam elif len(atnam)==2: atnam = ' '+atnam + ' ' elif len(atnam)==1: atnam = ' '+atnam + ' ' elif len(atnam)==0: atnam = ' CA ' else: print "set",key,value setattr(self,key,value) if ['selected_atoms_selection','selected_atoms_mode'].count(key) and self.method == 'interactive': for model,supModel in self.supModel.items(): #supModel.update_Connectivity2() supModel.do_redraw = 1 #------------------------------------------------------------------------- def handle_rename_MolData(self,master='',**keywords): #------------------------------------------------------------------------- if not self.supModel.has_key(master): return pass #------------------------------------------------------------------------- def handle_delete_MolData(self,master='',**keywords): #------------------------------------------------------------------------- # Delete data structure for this mol if self.supModel.has_key(master): self.supModel[master].delete() del self.supModel[master] if [self.fixed,self.show_equiv_mol].count(master): self.set_default_fixed() #-------------------------------------------------------------------------- def handle_transform_MolData(self,master='',mol1='',mol2='',hide=0,**keywords): #-------------------------------------------------------------------------- #print "in handle_transform_MolData",mol1,mol2 if self.supModel.has_key(self.show_equiv_mol): self.supModel[self.show_equiv_mol].do_redraw = 1 #------------------------------------------------------------------------- def handle_saved_files(self,saved_list=[]): #------------------------------------------------------------------------- #print "Superpose saved_list",saved_list,self.matches,self.MGAlign pass #------------------------------------------------------------------------- def gesamt_multi(self): #------------------------------------------------------------------------- import pygl_coord rv = 0 output_text = "Done nothing!" if len(self.supModel) == 0: return [rv,output_text] models = [] selections = [] files = [] MolData_names = [] for model,supModel in self.supModel.items()[0:1]: if not supModel.on: continue mol0 = data(supModel.fixed_MolData_name) models.append(mol0) mask_selHnd0 = supModel.parent.supModel[supModel.fixed_MolData_name].get_selHnd() MolData_names.append(supModel.fixed_MolData_name) gesamt_d0 = mol0.molHnd.SelectionToSCOP(mask_selHnd0) if len(gesamt_d0) == 0: gesamt_d0 = '*' selections.append(gesamt_d0) f = mol0.filename[2] files.append(f) for model,supModel in self.supModel.items()[:]: if not supModel.on: continue mol = data(supModel.MolData_name) f = mol.filename[2] if f in files: continue files.append(f) models.append(mol) mask_selHnd = supModel.parent.supModel[supModel.MolData_name].get_selHnd() MolData_names.append(supModel.MolData_name) gesamt_d = mol.molHnd.SelectionToSCOP(mask_selHnd) if len(gesamt_d) == 0: gesamt_d = '*' selections.append(gesamt_d) """ print models print selections print files """ command = ["gesamt"] for i in range(len(files)): command.append(files[i]) command.append("-d") command.append(selections[i]) #print command env = copy.deepcopy(os.environ) gesamt_txt_output = tempfile.NamedTemporaryFile(suffix="_gesamt_out.txt",prefix="ccp4mg"+str(os.getpid()),delete=False) proc = subprocess.Popen(command,stdout=gesamt_txt_output,universal_newlines=True,stderr=subprocess.STDOUT,env=env,shell=False) self.retval = None import time t1 = time.time() while self.retval == None: self.retval = proc.poll() outname = gesamt_txt_output.name gesamt_txt_output.close() fo = open(outname) progout = fo.readlines() fo.close() print "time for gesamt",time.time()-t1 #print progout mats = [] rmsds = [] for isup in range(len(self.supModel)): rmsds.append("99.999") self.gesamt_out = "" nalign = 0 if len(files)==2: # Gesamt pairwise results for il,l in zip(range(len(progout)),progout[:]): if l.startswith(" Transformation matrix for Target:"): mat = [] mat.extend([float(x) for x in progout[il+3].split()]) mat.extend([float(x) for x in progout[il+4].split()]) mat.extend([float(x) for x in progout[il+5].split()]) mat.extend([0.0,0.0,0.0,1.0]) mats.append(mat) print mat if l.startswith(" Aligned residues :"): nalign = int(l[len(" Aligned residues :"):].strip()) if l.startswith(" RMSD :"): rmsd = float(l[len(" RMSD :"):].strip()) for model,supModel in self.supModel.items(): if supModel.on: supModel.last_rms = '%.2f/%i'%(rmsd,nalign) else: # Gesamt multi results for il,l in zip(range(len(progout)),progout[:]): #print l.rstrip("\n") self.gesamt_out += l if l.startswith(" Nalign: "): nalign = int(l.strip().split()[1]) if l.startswith(" (o) For structure S"): mat = [] mat.extend([float(x) for x in progout[il+3].split()]) mat.extend([float(x) for x in progout[il+4].split()]) mat.extend([float(x) for x in progout[il+5].split()]) mat.extend([0.0,0.0,0.0,1.0]) mats.append(mat) if l.startswith(" (o) pairwise r.m.s.d. (consensus r.m.s.d. on diagonal):"): isup = 0 for model,supModel in self.supModel.items()[:]: rmsds[isup] = progout[il+4+isup].split()[isup+1] isup += 1 for model,supModel in self.supModel.items()[:]: #supModel.last_rms = rmsds[0] mol = supModel.MolData_name for imat in range(len(MolData_names)): if mol == MolData_names[imat] and imat < len(rmsds): supModel.last_rms = '%.2f/%i'%(float(rmsds[imat]),nalign) break if len(files)==2: mat = mats[0] mat = pygl_coord.matrix(4,4,mat) models[1].molHnd.SetTransform(mat,True) models[1].update_dependents('transform') self.emitUpdateSignal(MolData_names[1]) else: for imat in range(len(mats)): mat = mats[imat] mat = pygl_coord.matrix(4,4,mat) """ print files[imat] print models[imat] mat.Print() print """ models[imat].molHnd.SetTransform(mat,True) models[imat].update_dependents('transform') self.emitUpdateSignal(MolData_names[imat]) self.do_redraw = 1 #print "Written",self.gesamt_output_file #print "Moving",self.MolData_name return [rv,output_text] #------------------------------------------------------------------------- def apply(self,**kw): #------------------------------------------------------------------------- if not self.fixed: MGGUI().WarningMessage("Need to select a fixed model") return 1 self.gesamt_out = "" nMoved = 0 output_text = '' rv = 0 if self.method == 'ssm': if self.submethod == "gesamt": self.gesamt_multi() else: for model,supModel in self.supModel.items(): if model != self.fixed and supModel.on: if self.submethod == "gesamt": supModel.superpose_Gesamt() rc = [0,'OK'] # FIXME Need to get a return code in here somehow. else: rc = supModel.superpose_SSM() if rc[0] == 0: nMoved = nMoved + 1 else: rv = rv = 1 output_text = output_text + rc[1] + '\n' elif self.method == 'close': for model,supModel in self.supModel.items(): if model != self.fixed and supModel.on: rc = supModel.superpose_Close() if rc[0] == 0: nMoved = nMoved + 1 else: rv = rv + 1 output_text = output_text + rc[1] + '\n' elif self.method == 'interactive': movingSupModel = self.supModel.get(self.show_equiv_mol,None) if not movingSupModel: return if self.apply_interactive_all: matches = movingSupModel.get_matches() for model,supModel in self.supModel.items(): if model != self.fixed and supModel.on: if model != self.show_equiv_mol: supModel.set_matches(matches) rc = supModel.superpose_Matched() if rc[0] == 0: nMoved = nMoved + 1 else: rv = rv + 1 output_text = output_text + rc[1] + '\n' else: rc = movingSupModel.superpose_Matched() if rc[0] == 0: nMoved = nMoved + 1 else: rv = rv + 1 output_text = output_text + rc[1] + '\n' return [rv,output_text] #------------------------------------------------------------------------- def undo(self,mol=''): #------------------------------------------------------------------------- self.gesamt_matches = "" # Undo any pre-existing transformation if mol: mollist = [mol] else: mollist = self.supModel.keys() for mol in mollist: self.supModel[mol].superpose_undo() #------------------------------------------------------------------------- def handle_change_match(self,mol='',value=''): #------------------------------------------------------------------------- # has user changed which match they want displayed? import model #print "handle_change_match",mol,value if not self.supModel.has_key(mol): return if value == 'undo': self.supModel[mol].superpose_undo() else: if value == 'best': value = self.supModel[mol].best_match self.supModel[mol].superpose_SSM(match=int(value)) #------------------------------------------------------------------------ def getRMS(self,mol): #------------------------------------------------------------------------ if not self.supModel.has_key(mol): return '' return self.supModel[mol].getRMS() #------------------------------------------------------------------------- def get_data(self,**keywords): #------------------------------------------------------------------------- results = [] if ['ssm','close'].count(self.method): for model,supModel in self.supModel.items(): if model != self.fixed and supModel.on and data(model): fixed_MolData = data(supModel.fixed_MolData_name) moving_MolData = data(supModel.MolData_name) thisResult = {'fixed':supModel.fixed_MolData_name,'moving':supModel.MolData_name,'matrix':moving_MolData.molHnd.GetTransformString()} if fixed_MolData.molHnd.GetIsTransformed(): thisResult['fixMatrix'] = fixed_MolData.molHnd.GetTransformString() else: thisResult['fixMatrix'] = None results.append(thisResult) return results elif self.method == 'interactive': for model,supModel in self.supModel.items(): if model != self.fixed and supModel.on and data(model): fixed_MolData = data(supModel.fixed_MolData_name) moving_MolData = data(supModel.MolData_name) thisResult = {'fixed':supModel.fixed_MolData_name,'moving':supModel.MolData_name,'matrix':moving_MolData.molHnd.GetTransformString()} mat = thisResult['matrix'].split() matvals = [] for val in mat: matvals.append(float(val)) import pygl_coord m = pygl_coord.matrix(4,4,matvals) tm = pygl_coord.matrix(4,4,[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]) if (m*tm - tm).isNull(): continue if fixed_MolData.molHnd.GetIsTransformed(): thisResult['fixMatrix'] = fixed_MolData.molHnd.GetTransformString() else: thisResult['fixMatrix'] = None results.append(thisResult) return results #------------------------------------------------------------------------- def list_data(self,**keywords): #------------------------------------------------------------------------- # Recreate list_data with current status text = '' if ['ssm','close'].count(self.method): for model,supModel in self.supModel.items(): if model != self.fixed and supModel.on and data(model): text = text + supModel.Print() elif self.method == 'interactive': supModel_list = [] if self.apply_interactive_all: for model,supModel in self.supModel.items(): if model != self.fixed and supModel.on and data(model): supModel_list.append(supModel) elif self.show_equiv_mol: supModel_list.append(self.supModel.get(self.show_equiv_mol)) for supModel in supModel_list: supModel.conn2.UpdateCoordinates(True) #print 'list_data',supModel.MolData_name,supModel.conn2.GetNofConnections() spaces=' ' fxd = data(self.fixed).name_label[0:20] mov = data(self.show_equiv_mol).name_label[0:20] text = text + 'Fixed model Moving model Distance\n' + fxd + spaces[0:21-len(fxd)] +mov + spaces[0:21-len(mov)] + supModel.getRMS()+ '\n\n' text = text + supModel.conn2.Print() # Append transform matrix text = text +"\n\nTransformation applied to the moving model\n"+ data(supModel.MolData_name).molHnd.GetTransformString() if data(self.fixed).molHnd.GetIsTransformed(): text = text + "NOTE: The fixed model is also transformed by\n"+data(self.fixed).molHnd.GetTransformString() if self.gesamt_out: text = text + "\n\n" + self.gesamt_out return text #------------------------------------------------------------------------ def get_unmatched_menu(self,molobj): #------------------------------------------------------------------------ MP = self.supModel.get(self.show_equiv_mol) if not MP: return [] else: return MP.get_unmatched_menu(molobj=molobj) #------------------------------------------------------------------------ def get_unfinished_range(self,molobj): #------------------------------------------------------------------------ MP = self.supModel.get(self.show_equiv_mol) if not MP: return [] else: return MP.get_unfinished_range(molobj=molobj) #---------------------------------------------------------------------- def get_user_selected_atoms(self): #---------------------------------------------------------------------- # Return selected_atoms_selectino as a text string if not self.selected_atoms_selection: return '' txt = self.selected_atoms_selection[0] for item in self.selected_atoms_selection[1:]: txt = txt + ','+item #print 'get_user_selected_atoms',txt return txt #---------------------------------------------------------------------- def set_user_selected_atoms(self,selection_text=''): #---------------------------------------------------------------------- sele_list0 = selection_text.split(',') sele_list = [] for item in sele_list0: sele_list.extend(item.split()) self.selected_atoms_selection = sele_list #print 'set__user_selected_atoms',self.selected_atoms_selection #---------------------------------------------------------------------- def handle_atom_popup(self,select='',match=-1,end_range='',mode='', undo='',clear_unmatched =0,clear_all=0, undo_last='', MolData_name='',atomID='',**keywords): #---------------------------------------------------------------------- imatch = -1 if MolData_name: molobj = data(MolData_name) else: molobj = None if molobj and atomID: atomptr = molobj.interpretAtomID(mol=molobj,atom_name=atomID,force_one_atom=1) else: atomptr = None #print 'handle_atom_popup',select,'match',match,MolData_name,atomID,molobj,atomptr MP=self.supModel.get(self.show_equiv_mol) if not MP: return update_conn = 0 if end_range: imatch = end_range if imatch>=0: MP.end_range(match=imatch,atomptr=atomptr,molobj=molobj) elif select: imatch = MP.new_match(molobj=molobj,atomptr=atomptr,mode=select) #print 'handle_atom_popup add_selection rv',rv if imatch>=0: update_conn = 1 if match>=0: #print "match",match imatch = MP.add_match(molobj=molobj,atomptr=atomptr,match=match,mode=mode) if imatch>=0: update_conn = 1 if undo: rv = MP.undo(item=undo,molobj=molobj,atomptr=atomptr) if not rv: update_conn = 1 if clear_unmatched: if hasattr(self,'select_range'): del self.select_range MP.clear_unmatched() self.do_redraw = 1 if clear_all: if hasattr(self,'select_range'): del self.select_range MP.clear_all() update_conn = 1 if undo_last: #print "undo last" MP.stack(restore=1) update_conn = 1 if update_conn: MP.update_Connectivity2() return imatch #----------------------------------------------------------------------- def draw(self): #----------------------------------------------------------------------- import cprim #print 'Superpose.draw' for model,supModel in self.supModel.items(): supModel.draw() #-------------------------------------------------------------------- def import_matches(self,filename=''): #-------------------------------------------------------------------- import mmdb2 as mmdb if not os.path.exists(filename): return [1,'No vector file specified'] CIF = mmdb.Data() RC = CIF.ReadMMCIFData ( filename ) if RC: err = GetErrorDescription(RC) print "Error reading vectors CIF",RC,err return [1,"Error reading file: "+err] # Read if any model files are required to be loaded molobj_list = [] RC_ptr = inta(1) Loop = CIF.GetLoop ( "_model" ); if Loop: maxV = Loop.GetLoopLength() row = 0 while row < maxV: id = '' filn = '' id = Loop.GetString( "id",row,RC_ptr) filn = Loop.GetString( "filename",row,RC_ptr) molobj = get_dataobj(object_type='MolData',name=id) if molobj: molobj_list.append(molobj[0]) else: return [1,'Vectors in file for: '+id+ ' does not correspond to currently loaded model'] row = row + 1 del Loop ''' Problem here is that the current fixed model might not correspond to one of the models in the file ''' Loop = CIF.GetLoop ( "_vector" ); if not Loop: return [1,'No vectors defined in file'] maxV = Loop.GetLoopLength() #print 'Reading',maxV,'vectors from file',filename row = 0 failed_interpretAtomID = [] while row < maxV: start_atom = '' end_atom = '' # Get atoms - or if there are none the point or displacement start_atom = Loop.GetString( "start_atom",row,RC_ptr) if not RC_ptr[0]: mol1 = Loop.GetString( "start_model_id",row,RC_ptr) molobj1 = get_dataobj(object_type='MolData',name=mol1) end_atom = Loop.GetString( "end_atom",row,RC_ptr) if not RC_ptr[0]: mol2 = Loop.GetString( "end_model_id",row,RC_ptr) molobj2 = get_dataobj(object_type='MolData',name=mol2) if molobj1 and molobj2: pAtom1 = molobj1[0].interpretAtomID(mol=molobj1[0],atom_name=start_atom) pAtom2 = molobj2[0].interpretAtomID(mol=molobj2[0],atom_name=end_atom) #print "pAtom1,pAtom2",start_atom,end_atom,pAtom1,pAtom2 if self.method == 'interactive': MP=self.get_MolPair( mol1,mol2,create=1) if MP and pAtom1 and pAtom2: if mol1==MP.mol1.name : MP.Connectivity2.AddConnection(pAtom1,pAtom2) else: MP.Connectivity2.AddConnection(pAtom2,pAtom1) else: failed_interpretAtomID.append([start_atom,end_atom]) else: pass row=row + 1 return [0,''] #----------------------------------------------------------------------- def emitUpdateSignal(self,MolData_name): #----------------------------------------------------------------------- ''' The model MolData_name has been transformed and we need to ensure gui for that model is updated. Superpose is not a QtObject so can not emit signal so call method in GMolData''' obj = DISPLAYTABLE().getDataObj(MolData_name) if not obj: return obj.updateGuiAfterTransformation() #----------------------------------------------------------------------- def checkForMultiModels(self): #----------------------------------------------------------------------- multiModels = [] for model,supModel in self.supModel.items(): if supModel.on and supModel.nofModelsSelected()>1: multiModels.append(model) # ..and make sure we have checked the fixed model if self.supModel.get(self.fixed,'') and not self.supModel[self.fixed].on and \ self.supModel[self.fixed].nofModelsSelected()>1: multiModels.append(self.fixed) return multiModels #----------------------------------------------------------------------- #----------------------------------------------------------------------- #----------------------------------------------------------------------- class SuperposeModel: #----------------------------------------------------------------------- #----------------------------------------------------------------------- #----------------------------------------------------------------------- def __init__(self,parent=None,MolData_name='',fixed_MolData_name='',on=1,params={},**kw): import mmut,VectorsDispobj,model self.parent=parent self.MolData_name = MolData_name self.fixed_MolData_name = fixed_MolData_name self.selection = 'all' self.on = on self.show_conn = 0 self.show_mask = 0 # Save and display matched atoms v. a fixed model self.conn2 = mmut.Connectivity2(mmut.CONN_ATOM_ATOM,0,1) self.graphobj = VectorsDispobj.Vectorsgraphicsmodel() BUILD().append(self.graphobj) #'Temporary' display of unmatched atoms in interactive mode # or of mask in other modes self.MolDisp = None self.do_redraw = 1 params.update(kw) # Lists of manually selected matched atoms self.matches = [] self.restore_matches() # Handling SSM self.MGAlign = None self.nof_matches = 0 self.best_match = -1 self.displayed_match = -1 # note the match number returned by CMGAlign::GetMatchNumber is 0-n-1 # but here we use 1-n self.last_rms = '' self.list_stack = [] self.gesamt_matches = "" #----------------------------------------------------------------------- def delete(self): #----------------------------------------------------------------------- self.save_matches() del self.conn2 if self.graphobj: MAINWINDOW().removeGLDisplayObject(self.graphobj) BUILD().deletemod(self.graphobj) if self.MolDisp: self.MolDisp.delete() self.MolDisp = None #----------------------------------------------------------------------- def set_fixed(self,fixed): #----------------------------------------------------------------------- if fixed == self.fixed_MolData_name: return #print 'set_fixed',self.MolData_name,self.fixed_MolData_name,'fixed:',fixed self.fixed_MolData_name = copy.deepcopy(fixed) self.conn2.Clear() self.clear_all() self.restore_matches() self.do_redraw = 1 #----------------------------------------------------------------------- def handle_close_application(self): #----------------------------------------------------------------------- self.set_show_connectivity(0) self.set_show_mask(0) #----------------------------------------------------------------------- def handle_unclose_application(self): #----------------------------------------------------------------------- self.do_redraw = 1 #----------------------------------------------------------------------- def save_matches(self): #----------------------------------------------------------------------- #print 'save_matches',self.MolData_name,self.get_matches(),self.get_matches(swap_selections=1) if self.fixed_MolData_name != self.MolData_name: MODELINFO().add_info(set=self.MolData_name,info='superpose_matches', key=self.fixed_MolData_name,value=self.get_matches(),save=1) MODELINFO().add_info(set=self.fixed_MolData_name,info='superpose_matches', key=self.MolData_name,value=self.get_matches(swap_selections=1),save=1) #----------------------------------------------------------------------- def restore_matches(self): #----------------------------------------------------------------------- if self.fixed_MolData_name != self.MolData_name: status,info = MODELINFO().get_info(set=self.MolData_name,info='superpose_matches', key=self.fixed_MolData_name) if not status and info.has_key(self.fixed_MolData_name): self.set_matches(info[self.fixed_MolData_name]) status,info = MODELINFO().get_info(set=self.fixed_MolData_name,info='superpose_matches', key=self.MolData_name) if not status and info.has_key(self.MolData_name): self.set_matches(info[self.MolData_name],append=1,swap_selections=1) #----------------------------------------------------------------------- def get_matches(self,swap_selections=0): #----------------------------------------------------------------------- match_info = [] for match in self.matches: match_info.append(match.getparams(swap_selections=swap_selections)) #print 'get_matches',self.MolData_name,self.fixed_MolData_name,swap_selections,match_info return match_info #---------------------------------------------------------------------- def set_matches(self,match_info=[],append=0,swap_selections=0): #----------------------------------------------------------------------- if not append: self.matches = [] #print 'set_matches',self.MolData_name,self.fixed_MolData_name,match_info,append,swap_selections for info in match_info: new_match = SuperposeMatch() if swap_selections: sele1 = info.get('sele1','') info['sele1'] = info.get('sele2','') info['sele2'] = sele1 new_match.setparams(info) same = 0 if self.matches: for old_match in self.matches: same = same + old_match.isSame(new_match) if not same : self.matches.append(new_match) #else: # print 'set_matches deleting repeat',info #----------------------------------------------------------------------- def getparams(self): #----------------------------------------------------------------------- pars= { 'MolData_name' : self.MolData_name, 'fixed_MolData_name' : self.fixed_MolData_name, 'on' : self.on, 'selection' : self.selection, 'matches' : self. get_matches() } return pars #----------------------------------------------------------------------- def setparams(self,params={},**kw): #----------------------------------------------------------------------- #print 'SuperposeModel.setparams',self.MolData_name,params params.update(kw) if params.has_key('on'): self.on = params.get('on') if params.has_key('selection'): self.selection = params.get('selection') self.do_redraw = 1 if params.has_key('matches'): self.set_matches(params['matches']) #----------------------------------------------------------------------- def nofMatches(self): #----------------------------------------------------------------------- return len(self.matches) def getRMS(self): return self.last_rms #----------------------------------------------------------------------- def getmatchesinfo(self): #----------------------------------------------------------------------- return { 'nof_matches' : getattr(self,'nof_matches'), 'best_match' : getattr(self,'best_match'), 'displayed_match' : getattr(self,'displayed_match'), 'rms' : getattr(self,'last_rms') } #----------------------------------------------------------------------- def set_show_connectivity(self,show_conn): #----------------------------------------------------------------------- if show_conn != self.show_conn: self.do_redraw = 1 self.show_conn = show_conn self.do_redraw = 1 #----------------------------------------------------------------------- def set_show_mask(self,show_mask): #----------------------------------------------------------------------- if show_mask != self.show_mask: self.do_redraw = 1 self.show_mask = show_mask self.do_redraw = 1 #----------------------------------------------------------------------- def extract_unmatched(self,model=2): #----------------------------------------------------------------------- ''' Extract any selection on either this model (=2) or the fixed model (=1) that is not matched ''' unmatched = [] for match in self.matches: info = match.getUnmatched(model) #print 'extract_unmatched',match,info if info: unmatched.append(info) #print 'extract_unmatched',model,unmatched return unmatched #----------------------------------------------------------------------- def get_unmatched_selection_command(self,unmatched_list): #----------------------------------------------------------------------- ''' Convert a list of unmatched groups into a parseable selection command This method is independent of the MolData object ''' #print "draw_unmatched",self.parent.selected_atoms_mode selected_atoms_mode = self.parent.selected_atoms_mode selected_atoms_selection = self.parent.selected_atoms_selection import string sele = '' for unmatched in unmatched_list: if ['atom','residue','monomer'].count(unmatched[0]): sele = sele + unmatched[1] + ' or ' elif ['main','side','base','backbone'].count(unmatched[0]): sele = sele + "{ "+unmatched[0]+" and "+unmatched[1] + ' } or ' elif ['range'].count(unmatched[0]): if selected_atoms_mode == 'all' or (selected_atoms_mode=='user' and selected_atoms_selection==''): sele = sele + unmatched[1] + ' or ' elif selected_atoms_mode == 'user': sele = sele + "{ /1/*/*,*/" for atm in selected_atoms_selection: sele = sele + atm +',' sele = sele[0:-1] + " and "+unmatched[1] + ' } or ' else: sele = sele + "{ "+selected_atoms_mode+" and "+unmatched[1] + ' } or ' #print "draw_unmatched sele",sele if len(sele)>4 and sele[-3:] == 'or ': sele = sele[0:-3] return sele #----------------------------------------------------------------------- def draw_unmatched(self,command,colour=''): #----------------------------------------------------------------------- rv = data(self.MolData_name).parse_selection(command=command,test=1) if (not rv[0]) and rv[1]: #print 'draw_unmatched parse_selection',command,rv,self.MolDisp if not self.MolDisp: self.create_MolDisp() if not getattr(self.MolDisp,'SelHandle'): return self.MolDisp.SelHandle.setCommand(command) if colour: self.MolDisp.set_colour(colour) self.MolDisp.do_redraw = 1 self.MolDisp.set_visibility(visibility=1) self.MolDisp.reapply_selection = 1 else: if self.MolDisp: self.MolDisp.set_visibility(visibility=0) #----------------------------------------------------------------------- def draw_mask(self,colour=''): #----------------------------------------------------------------------- #print 'superposeModel.draw_mask',self.MolData_name,colour if ['','all'].count(self.selection.strip()): if self.MolDisp: self.MolDisp.set_visibility(visibility=0) else: if not self.MolDisp: self.create_MolDisp() self.MolDisp.SelHandle.setCommand(self.selection) if colour: self.MolDisp.set_colour(colour) self.MolDisp.do_redraw = 1 self.MolDisp.set_visibility(visibility=1) self.MolDisp.reapply_selection = 1 #----------------------------------------------------------------------- def draw(self,force=0): #----------------------------------------------------------------------- #print "SuperposeModel do_redraw",self.MolData_name,self.do_redraw,self.show_mask if not self.do_redraw and not force: return self.draw_matched() fixed = self.parent.supModel.get(self.fixed_MolData_name,None) if self.show_mask: #if not self.MolDisp: self.create_MolDisp() #self.MolDisp.set_visibility(visibility=1) if self.parent.method == 'interactive': # Draw pyramids on the selected but unmatched groups unmatched_list = self.extract_unmatched(2) #print 'draw unmatched_list',unmatched_list command = self.get_unmatched_selection_command(unmatched_list) #print 'draw command',command,self.parent.moving_mask_colour self.draw_unmatched(command,colour=self.parent.moving_mask_colour) # Draw the unmatched on the 'fixed' model if fixed: unmatched_list = self.extract_unmatched(1) #print 'draw fixed unmatched_list',unmatched_list command = self.get_unmatched_selection_command(unmatched_list) #print 'draw fixed command',command,self.parent.fixed_mask_colour if fixed: fixed.draw_unmatched(command,colour=self.parent.fixed_mask_colour) else: self.draw_mask(colour=self.parent.moving_mask_colour) if fixed: fixed.draw_mask(colour=self.parent.fixed_mask_colour) elif self.MolDisp: self.MolDisp.set_visibility(visibility=0) self.MolDisp.draw() if fixed and fixed.MolDisp: fixed.MolDisp.set_visibility(visibility=0) fixed.MolDisp.draw() self.do_redraw = 0 #----------------------------------------------------------------------- def draw_matched(self): #---------------------------------------------------------------------- nconn=self.conn2.GetNofConnections() #print "SuperposeModel.draw_matched nconn",nconn,self.show_conn self.graphobj.obj.clear_prims(); self.graphobj.obj.DeleteText(); if nconn>0 and self.show_conn: self.conn2.UpdateCoordinates(True) import VectorsDispobj, pygl_coord, cprim col = MGCOLOUR().RGB(self.parent.conn_colour) colv = pygl_coord.DoubleVector(col) #print "SuperposeModel col,colv",col,colv if self.parent.show_distances: label_mode = cprim.LABELLEDCENTRE else: label_mode = cprim.NOTLABELLED cprim.DrawSimpleConnection(self.graphobj.obj,self.conn2.connected,colv, cprim.DASHLINE,VectorsDispobj.VectorsDispobj.line_width,label_mode,self.parent.conn_colour) font = FONTMANAGER().getFont('atom_label') self.graphobj.obj.SetTextFont( str(font['family']), str(font['weight']), str(font['slant']),font['size'],font['underline']) self.graphobj.rebuild() MAINWINDOW().rebuildGLDisplayObject(self.graphobj) def get_match_menu(self,iMatch=-1): menu = [] if iMatch>=0 and iMatch<len(self.matches): rng = [iMatch] else: rng = range(len(self.matches)) for ii in rng: menu.append([self.matches[ii].on,'%-8s %-12s %-12s'%(self.matches[ii].mode,self.matches[ii].sele2,self.matches[ii].sele1)]) return menu #----------------------------------------------------------------------- def get_unmatched_menu(self,molobj=''): #----------------------------------------------------------------------- ''' Return a menu of the unmatched items in the match list ''' menu = [] # If user has picked the fixed model then we want a list of the unmatched # items in the moving model (and visa versa) if molobj.name == self.MolData_name: model = 1 else: model = 2 for ii in range(len(self.matches)): menu_item_list = self.matches[ii].getUnmatchedMenu(model=model) #print 'get_unmatched_menu menu_item_list',ii,menu_item_list for menu_item in menu_item_list: menu.append( [ii,menu_item[0],menu_item[1]] ) return menu #----------------------------------------------------------------------- def get_unfinished_range(self,molobj=''): #----------------------------------------------------------------------- ''' Return a menu of the unfinished ranges in the match list ''' menu = [] if molobj.name == self.MolData_name: model = 2 else: model = 1 for ii in range(len(self.matches)): menu_item_list = self.matches[ii].getUnmatchedMenu(model=model,start=1) for menu_item in menu_item_list: menu.append( [ii,menu_item] ) return menu #----------------------------------------------------------------------- def set_close(self): #----------------------------------------------------------------------- for ii in range(0,len(self.list2)): if self.list2[ii]=='' and ['rang','residue','main','side'].count(self.list1[ii][0:4]): self.list2[ii]='close' for ii in range(0,len(self.list1)): if self.list1[ii]=='' and ['rang','residue','main','side'].count(self.list2[ii][0:4]): self.list1[ii]='close' #----------------------------------------------------------------------- def clear_unmatched(self): #----------------------------------------------------------------------- matches = [] for match in self.matches: if match.get('sele1') and match.get('sele2'): matches.append(match) self.matches = matches self.do_redraw = 1 #----------------------------------------------------------------------- def clear_all(self): #----------------------------------------------------------------------- self.matches = [] self.do_redraw = 1 #print 'MP.clear_all' #----------------------------------------------------------------------- def delete_match(self,match): #----------------------------------------------------------------------- if match>=0 and match<len(self.matches): del self.matches[match] #----------------------------------------------------------------------- def new_match(self,molobj=None,atomptr=None,mode='atom',match_closest=0): #----------------------------------------------------------------------- if molobj and atomptr: label=self.label(mode=mode,molobj=molobj,atomptr=atomptr) if not label: return -1 self.stack() if ['range','start'].count(mode): mode = 'range' qualifier = 'first' else: qualifier = '' if molobj.name == self.fixed_MolData_name: self.matches.append(SuperposeMatch( mode = mode, sele1 = label,qualifier=qualifier )) else: self.matches.append(SuperposeMatch( mode = mode, sele2 = label,qualifier=qualifier )) else: self.matches.append(SuperposeMatch()) #print 'SuperposeMatch.new_match',len(self.matches)-1,self.matches[-1].getparams() return len(self.matches)-1 #----------------------------------------------------------------------- def end_range(self,molobj=None,atomptr=None,match=-1): #----------------------------------------------------------------------- if match<0 or match>len(self.matches): #print 'End range: invalid match number',match return -1 if molobj.name == self.fixed_MolData_name: start_res = self.matches[match].get('sele1') model = 1 else: start_res = self.matches[match].get('sele2') model = 2 label=self.rangelabel(start_res=start_res,molobj=molobj,atomptr=atomptr) #print 'end_range rangelabel',start_res,label if not label: return -1 self.stack() if model == 1: self.matches[match].set('sele1',label) self.matches[match].set('qualifier','') else: self.matches[match].set('sele2',label) self.matches[match].set('qualifier','') #print 'end_range',match,self.matches[match].getparams() return match #----------------------------------------------------------------------- def add_match(self,molobj=None,atomptr=None,match=-1,mode=''): #----------------------------------------------------------------------- #print "add_match match",match,mode import string ''' if match[0:4]=='rang': label = self.label(mode='start',molobj=molobj,atomptr=atomptr) if string.find(match,'start')>0: sele='start '+label match=match[0:-6] elif string.find(match,'end')>0: sele='end '+label match=match[0:-4] else: label = self.label(mode=match,molobj=molobj,atomptr=atomptr) sele=string.split(match)[0]+' '+label print "add_match match,sele",molobj,match,'*',sele ''' if match<0 or match>len(self.matches): #print 'Add match: invalid match number',match return -1 if molobj.name == self.fixed_MolData_name: model = 1 elif molobj.name == self.MolData_name: model = 2 label = self.label(mode=mode,molobj=molobj,atomptr=atomptr) #print 'add_match',model,label if not label: return -1 self.stack() if model == 1: self.matches[ match].set('sele1',label) else: self.matches[ match].set('sele2',label) if ['start','end'].count(mode): if self.matches[match].get('qualifier')!='first': rv = self.matches[match].setEndOfRange(mode,self.fixed_MolData_name,self.MolData_name) if rv[0]: #print rv[1] self.matches[match].set('qualifier',mode) else: self.matches[match].set('qualifier','') else: self.matches[match].set('qualifier','') #print 'add_match',match,self.matches[match].getparams() self.do_redraw = 1 return match #----------------------------------------------------------------------- def undo(self,item,molobj=None,atomptr=None): #----------------------------------------------------------------------- if ['atom','residue'].count(item): pass else: import utils item=utils.safeInt(item,-1) if item>=0 and item<=len(self.list1): self.stack() self.list1.pop(item) self.list2.pop(item) self.do_redraw = 1 return 0 else: return 1 #if mode == 'atom': # self.conn2.RemoveConnection(atomptr ,0 ) #elif mode == 'residue': # import mmdb # resAtoms = mmdb.newPPCAtom() # p = intp() # atomptr.GetResidue().GetAtomTable(resAtoms,p) # for i in range(p.value()): # self.conn2.RemoveConnection(CAtomPtr(getPCAtom(resAtoms,i)),0 ) #elif mode == 'all': # self.conn2.DeleteConnections() #----------------------------------------------------------------------- def get_listitem(self,molobj=None,atomptr=None): #----------------------------------------------------------------------- # try to find a list item which includes the atom atomptr if molobj.name==self.fixed_MolData_name: list = self.list1 elif molobj.name==self.MolDaa_name: list = self.list2 ii=-1 label = self.label(mode='atom',molobj=molobj,atomptr=atomptr) if list.count('atom '+label): ii=list.index('atom '+label) else: label = self.label(mode='residue',molobj=molobj,atomptr=atomptr) for mode in ['residue','main','side','backbone','base']: if list.count(mode+' '+label): ii=list.index(mode+' '+label) if ii<0: label = self.label(mode='start',molobj=molobj,atomptr=atomptr) if list.count('start '+label): ii=list.index('start '+label) if ii<0: import mmdb2 as mmdb selHnd=molobj.molHnd.GetSelection() for jj in range(0,len(list)): if list[jj][0:4]=='rang': molobj.molHnd.Select(selHnd,mmdb.STYPE_ATOM,list[jj][6:],mmdb.SKEY_NEW) if atomptr.isInSelection(selHnd): ii=jj break molobj.molHnd.DeleteSelection(selHnd) if ii>=0: return list[ii] else: return '' #----------------------------------------------------------------------- def clear_Connectivity2(self): #----------------------------------------------------------------------- self.do_redraw = 1 self.conn2.DeleteConnections([],True) #----------------------------------------------------------------------- def update_Connectivity2(self,match=-1): #----------------------------------------------------------------------- if not self.fixed_MolData_name: return import string,selection_protocols if match<0 or match>=(self.matches): mrng = range(0,len(self.matches)) self.conn2.DeleteConnections([],True) else: mrng = [match] self.conn2.DeleteConnections(mrng,True) ''' print '-------------------------------' print "update_Connectivity2",len(self.matches),mrng import inspect stack = inspect.stack() for item in stack[1:]: print item print '-------------------------------' ''' atnam_list = [] centralAtom = 'CA' if self.parent.selected_atoms_mode == 'main': atnam_list = ['CA','N','O','C'] centralAtom = 'CA' elif self.parent.selected_atoms_mode =='catrace': atnam_list = ['CA'] centralAtom = 'CA' elif self.parent.selected_atoms_mode == 'nucleic': atnam_list = ['P',"C1'",'C1*'] centralAtom = "C1',C1*" elif self.parent.selected_atoms_mode == 'user': atnam_list = self.parent.selected_atoms_selection centralAtom = atnam_list[0] #print "update_Connectivity2 atnam_list",atnam_list,centralAtom self.do_redraw = 1 mol1 = data(self.fixed_MolData_name) mol2 = data(self.MolData_name) for ii in mrng: on = self.matches[ii].get('on') if on: sele1 = self.matches[ii].get('sele1') sele2 = self.matches[ii].get('sele2') mode = self.matches[ii].get('mode') close = self.matches[ii].get('close') #print 'update_Connectivity2',mode,sele1,sele2 qualifier = self.matches[ii].get('qualifier') ''' elif mode2 == 'close': pending_res = self.get_respointers(range=sele1,molobj=mol1) if len(pending_res)==1: pending_res.append(pending_res[0]) #print "pending_res",pending_res if len(pending_res)==2: nc = self.conn2.AddCloseRangeConnections(1, \ pending_res[0],pending_res[1],mol2.molHnd, self.parent.close_atoms_res_cutoff,self.parent.close_atoms_cutoff,atnam_list,centralAtom,ii) #print "close nc",nc elif mode1 == 'close': pending_res = self.get_respointers(range=sele2,molobj=mol2) if len(pending_res)==1: pending_res.append(pending_res[0]) #print "pending_res",pending_res if len(pending_res)==2: nc = self.conn2.AddCloseRangeConnections(2, \ pending_res[0],pending_res[1],mol1.molHnd, self.parent.close_atoms_res_cutoff,self.parent.close_atoms_cutoff,atnam_list,centralAtom,ii) #print "close nc",nc ''' if mode == 'atom': if sele1 and sele2: pAtom1 = mol1.interpretAtomID(mol1,sele1,force_one_atom=1) pAtom2 = mol2.interpretAtomID(mol2,sele2,force_one_atom=1) if pAtom1 and pAtom2: self.conn2.AddConnection(pAtom1,pAtom2,'',ii) elif ['monomer'].count(mode): if sele1 and sele2 and sele1.split('/')[1] != '' and sele2.split('/')[1] != '': nr1,pRes1 = mol1.interpretResidueID(sele1) nr2,pRes2 = mol2.interpretResidueID(sele2) #print 'update_Connectivity2 monomer',sele1,sele2,nr1,nr2 if nr1 and nr2 and pRes1 and pRes2: self.conn2.MatchGraphs(pRes1,"",pRes2,"",1,ii,0.9,bool(self.parent.monomer_keep_matches)) elif ['residue','side','main','backbone','base'].count(mode): if ['backbone','base'].count(mode): main_chain = selection_protocols.backbone_atoms['ORDER'] else: main_chain =selection_protocols.main_chain['ORDER'] nr1,pRes1 = mol1.interpretResidueID(sele1) nr2,pRes2 = mol2.interpretResidueID(sele2) if (nr1==1 and nr2==1): import mmdb2 as mmdb sele = [[1,1],[1,0],[0,1],[1,0],[0,1]][['residue','side','main','base','backbone'].index(mode)] resAtoms1 = mmdb.newPPCAtom() p1 = intp() resAtoms2 = mmdb.newPPCAtom() p2 = intp() #pRes1.GetAtomTable(resAtoms1,p1) #pRes2.GetAtomTable(resAtoms2,p2) resAtoms1 = mmut.GetAtomTable(pRes1,p1) resAtoms2 = mmut.GetAtomTable(pRes2,p2) for i in range(p1.value()): atomptr1 = getPCAtom(resAtoms1,i) #print "atomptr1",atomptr1.name, main_chain.count(string.strip(atomptr1.name)) if sele[main_chain.count(string.strip(atomptr1.name))]: for j in range(p2.value()): atomptr2 = getPCAtom(resAtoms2,j) if atomptr1.name == atomptr2.name: self.conn2.AddConnection(atomptr1,atomptr2,'',ii) elif mode == 'range': pres1=self.matches[ii].getResPointers(sele1,self.fixed_MolData_name) pres2=self.matches[ii].getResPointers(sele2,self.MolData_name) if len(pres1)==2 and len(pres2)==2: nc = self.conn2.AddRangeConnections(pres1[0],pres1[1],pres2[0],pres2[1],atnam_list,ii) #print 'update_Connectivity2',self.list1,self.list2,self.conn2.GetNofConnections() elif close and len(pres1)==2 and len(pres2)==0: nc = self.conn2.AddCloseRangeConnections(1,pres1[0],pres1[1],data(self.MolData_name).molHnd, self.parent.close_atoms_res_cutoff,self.parent.close_atoms_cutoff,atnam_list,centralAtom,ii) elif close and len(pres1)==0 and len(pres2)==2: nc = self.conn2.AddCloseRangeConnections(2,pres2[0],pres2[1],data(self.fixed_MolData_name).molHnd, self.parent.close_atoms_res_cutoff,self.parent.close_atoms_cutoff,atnam_list,centralAtom,ii) elif mode == 'range_same_seqid': import mmdb2 as mmdb selHnd1 = mol1.molHnd.NewSelection() mol1.molHnd.Select ( selHnd1, mmdb.STYPE_RESIDUE, sele1, mmdb.SKEY_NEW) selHnd2 = mol2.molHnd.NewSelection() mol2.molHnd.Select ( selHnd2, mmdb.STYPE_RESIDUE, sele2, mmdb.SKEY_NEW) nc = self.conn2.AddRangeWithSameIdConnections( mol1.molHnd, selHnd1, mol2.molHnd,selHnd2,atnam_list , ii) elif ['selection','selection_close'].count(mode): selHnd1 = -1 selHnd2 = -1 if sele1: rv1 = data(self.fixed_MolData_name).parse_selection(command=sele1) #print 'update_Connectivity2 selection rv1',rv1 if not rv1[0]: selHnd1 = rv1[1] if sele2: rv2 = data(self.MolData_name).parse_selection(command=sele2) #print 'update_Connectivity2 selection rv2',rv2 if not rv2[0]: selHnd2 = rv2[1] if mode == 'selection_close' and (selHnd1>0 or selHnd2>0): nClose=self.conn2.AddCloseAtoms(data(self.fixed_MolData_name).molHnd, selHnd1, data(self.MolData_name).molHnd, selHnd2, self.parent.close_atoms_res_cutoff, self.parent.close_atoms_cutoff , self.parent.close_atoms_central_atom, 0) #print 'update_Connectivity2 selection_close',sele1,sele2,selHnd1,selHnd2,nClose elif mode == 'selection' and selHnd1>0 and selHnd2>0: self.conn2.AddContactFromSelHandle(data(self.fixed_MolData_name).molHnd,selHnd1, data(self.MolData_name).molHnd, selHnd2) if selHnd1>0: data(self.fixed_MolData_name).molHnd.DeleteSelection(selHnd1) if selHnd2>0: data(self.MolData_name).molHnd.DeleteSelection(selHnd2) def label(self,mode='atom',molobj=None,atomptr=None): # 0 Molecule # 1 Model # 2 Chain Id # 3 Sequence number # 4 Insertion code # 5 Residue name # 6 Atom id # 7 Alternate position # 8 Element mask = inta(9) if ['resi','side','main','mono','back','base'].count(mode[0:4]): py_mask = [0,1,1,1,1,1,0,0,0] elif ['star'].count(mode[0:4]): py_mask = [0,1,1,1,1,0,0,0,0] elif mode[0:4]=='rang': py_mask = [0,0,0,1,1,0,0,0,0] else: py_mask = [0,1,1,1,1,1,1,1,0] for i in range(0,9): mask[i]=py_mask[i] return molobj.molHnd.AtomLabel_mask(atomptr,mask) def rangelabel(self,start_res='',molobj=None,atomptr=None): reverse = 0 pres1 = molobj.interpretResidueID(start_res) #print 'Superpose rangelabel',atomptr,pres1 if pres1[0]==1 and pres1[1].GetResidueNo()< atomptr.GetResidueNo(): label = start_res + '-' + \ self.label(mode='range',molobj=molobj,atomptr=atomptr) else: import string label = self.label(mode='start',molobj=molobj,atomptr=atomptr) \ + '-' + string.split(start_res,'/')[-1] reverse=1 return label def stack(self,restore=0): if not restore: match_params_list = [] for match in self.matches: match_params_list.append(match.getparams()) self.list_stack.append(match_params_list) else: if len(self.list_stack)>0: #Remove the current status match_params_list=self.list_stack.pop() self.matches = [] for params in match_params_list: self.matches.append(SuperposeMatch(params=params)) def superpose_undo(self): self.gesamt_matches = "" molobj = data(self.MolData_name) molobj.molHnd.UnSetTransform(True) molobj.update_dependents('transform') self.parent.emitUpdateSignal(self.MolData_name) self.best_match = 0 self.last_rms = '' self.do_redraw = 1 self.displayed_match = -1 def parseGesamtOutput(self,lines): """ Parse gesamt (output as list of lines) to get matrix, rmsd and matches. """ rmsd = 0.0 match_start = -1 match_end = -1 mat = [] for il,l in zip(range(len(lines)),lines[:]): #if l.startswith(" Rx Ry Rz T") and (il+6)<len(lines): if l.startswith(" Rx Ry Rz T") and (il+6)<len(lines) and len(mat)==0: mat.extend([float(x) for x in lines[il+1].split()]) mat.extend([float(x) for x in lines[il+2].split()]) mat.extend([float(x) for x in lines[il+3].split()]) mat.extend([0.0,0.0,0.0,1.0]) if l.startswith(' at RMSD ='): rmsd = float(l[len(' at RMSD ='):].split()[0]) if l.startswith(' r.m.s.d:'): rmsd = float(l[len(' r.m.s.d:'):].split()[0]) if l.startswith(' RMSD'): rmsd = float(l.split(":")[1].strip()) if l.startswith(' RESIDUE ALIGNMENT'): match_start = il+7 if l.startswith(' Residue alignment:'): match_start = il+6 if l.startswith('$TEXT:Residue alignment:'): match_start = il+5 if (l.startswith('`-------------') or l.startswith(' `-------------')) and match_start>-1: match_end = il matches = [] if match_start >-1 and match_end > match_start: for il in range(match_start,match_end): q,d,t = lines[il].split("|")[1:4] if not len(d.strip())==0: i1 = "" i2 = "" r1a = q.strip()[-4:].strip() r2a = t.strip()[-4:].strip() if r1a[-1].isalpha(): i1 = r1a[-1] r1a = r1a[:-1] if r2a[-1].isalpha(): i2 = r2a[-1] r2a = r2a[:-1] r1,dist,r2 = int(r1a),float(d.strip()[3:-3]),int(r2a) c1 = q[3] c2 = t[3] rn1 = q[5:8] rn2 = t[5:8] matches.append((r1,r2,c1,c2,dist,rn1,rn2,i1,i2)) return {'transform':mat,'rmsd':rmsd,'matches':matches } def runGesamt(self): import pygl_coord command = ["gesamt",self.gesamt_file1,'-d',self.gesamt_d1,self.gesamt_file2,'-d',self.gesamt_d2,'-o',self.gesamt_output_file] print command env = copy.deepcopy(os.environ) gesamt_txt_output = tempfile.NamedTemporaryFile(suffix="_gesamt_out.txt",prefix="ccp4mg"+str(os.getpid()),delete=False) proc = subprocess.Popen(command,stdout=gesamt_txt_output,universal_newlines=True,stderr=subprocess.STDOUT,env=env,shell=False) self.retval = None import time t1 = time.time() while self.retval == None: self.retval = proc.poll() outname = gesamt_txt_output.name gesamt_txt_output.close() fo = open(outname) progout = fo.readlines() fo.close() print "time for gesamt",time.time()-t1 print "Written",self.gesamt_output_file print "Moving",self.MolData_name mol2 = data(self.MolData_name) mol1 = data(self.fixed_MolData_name) # These 4 lines are a way of checking that gesamt run Ok. Probably a better way. fcheck = open(self.gesamt_output_file) outlines = fcheck.readlines() fcheck.close() if len(outlines)>3: pgo = self.parseGesamtOutput(progout) mat = pygl_coord.matrix(4,4,pgo['transform']) mat = mat.Inverse() mol2.molHnd.SetTransform(mat,True) mol2.update_dependents('transform') self.parent.emitUpdateSignal(self.MolData_name) self.do_redraw = 1 m1 = [] m2 = [] c1 = [] c2 = [] i1 = [] i2 = [] labels = [] # Now need to convert the indices in pgo["matches"] to carts for self.conn2 for match in pgo["matches"]: m1.append(match[0]) # Query, moving m2.append(match[1]) # Target, fixed c1.append(match[2]) c2.append(match[3]) i1.append(match[7]) i2.append(match[8]) labels.append(str(match[4])) self.conn2.Clear() self.conn2.AddConnectionsFromMatches(mol2.molHnd,mol1.molHnd,m1,m2,c1,c2,i1,i2,labels) self.gesamt_matches = "\n== Moving == Fixed == Distance ==\n" for match in pgo["matches"]: self.gesamt_matches += "%4d(%3s)%4d(%3s)%12.3f\n" % (match[0], match[5], match[1], match[6], match[4]) self.last_rms = '%.2f/%i'%(pgo["rmsd"],self.conn2.GetNofConnections()) def superpose_Gesamt(self): mol2 = data(self.fixed_MolData_name) mol1 = data(self.MolData_name) #print dir(mol1) f1 = mol1.filename[2] f2 = mol2.filename[2] if os.path.isfile(f1) and os.path.isfile(f2): self.gesamt_file1 = f1 self.gesamt_file2 = f2 gesamt_output = tempfile.NamedTemporaryFile(suffix="_gesamt_out.pdb",prefix="ccp4mg"+str(os.getpid()),delete=False) self.gesamt_output_file = gesamt_output.name gesamt_output.close() mask_selHnd1 = self.get_selHnd() mask_selHnd2 = self.parent.supModel[self.fixed_MolData_name].get_selHnd() self.gesamt_d1 = mol1.molHnd.SelectionToSCOP(mask_selHnd1) self.gesamt_d2 = mol2.molHnd.SelectionToSCOP(mask_selHnd2) if len(self.gesamt_d1) == 0: self.gesamt_d1 = '*' if len(self.gesamt_d2) == 0: self.gesamt_d2 = '*' self.runGesamt() def superpose_SSM(self,match=0,undo=0,best=0): # NEEDS to handle the undo/best options #print 'superpose_SSM',self.MolData_name,self.fixed_MolData_name if not self.fixed_MolData_name: return [1,'Error with fixed model'] mol1 = data(self.fixed_MolData_name) mol2 = data(self.MolData_name) if not mol1 or not mol2: return [1,'Error - possibly model deleted?'] mask_selHnd2 = self.get_selHnd() mask_selHnd1 = self.parent.supModel[self.fixed_MolData_name].get_selHnd() if mask_selHnd2<0: return [1,'Error selecting mask for moving model'] if mask_selHnd1<0:return [1,'Error selecting mask for fixed model'] new_MGAlign = CMGAlign() current_transform = mol2.molHnd.GetTransform() mol2.molHnd.UnSetTransform(True) RC = new_MGAlign.MGAlign( mol2.molHnd, mol1.molHnd,3,1, mask_selHnd2,mask_selHnd1,match-1,self.conn2 ) print "Superpose status (0=success)",mol2.name_label,RC if RC==0: self.MGAlign = new_MGAlign if match>0: self.displayed_match = copy.deepcopy(match) else: self.displayed_match = self.MGAlign.GetMatchNumber()+1 self.nof_matches = self.MGAlign.GetNumberofSSEMatches() self.best_match = self.MGAlign.GetMatchNumber()+1 self.last_rms = '%.2f/%i'%(self.MGAlign.GetRMSD(),self.conn2.GetNofConnections()) #print 'from GetRMSD',self.last_rms; sys.stdout.flush() mol2.update_dependents('transform') self.parent.emitUpdateSignal(self.MolData_name) self.do_redraw = 1 return [0,''] else : import pygl_coord # Thus getInvMatrix is potentially wrong: 8/2/2010 changes for quat bug. rotmat = pygl_coord.Quat(pygl_coord.matrix(4,4,current_transform)).getInvMatrix() mol2.molHnd.SetTransform(rotmat,True) return [1,self.ssm_error_message(RC)] #----------------------------------------------------------------------- def ssm_error_message(self,RC): #----------------------------------------------------------------------- import model moving_MolData = data(self.MolData_name) fixed_MolData = data(self.fixed_MolData_name) output_text = 'Superposing '+moving_MolData.name+ \ ' onto '+fixed_MolData.name + ' FAILED error code='+str(RC)+'\n\n' if RC == SPSN_noVertices: output_text = output_text + 'No secondary structure elements in the selection for '+moving_MolData.name+'\n\n' elif RC == SPSN_noVertices2: output_text = output_text + 'No secondary structure elements in the selection for '+fixed_MolData.name+'\n\n' elif RC == SPSN_noHits: output_text = output_text + 'No matching secondary structures found for '+moving_MolData.name+'\n\n' elif RC == SPSN_noSPSN: output_text = output_text +'Can not superpose the apparently matching SSEs for '+moving_MolData.name+'\n\n' elif [SPSN_noGraph,SPSN_noGraph2].count(RC): output_text = output_text +'Failed to create graphs.\nPossibly model does not have secondary structure.\nPossibly program error.\nContact ccp4mg@ccp4.ac.uk\n' print "Superpose error:",output_text return output_text #----------------------------------------------------------------------------- def superpose_LSQ (self, fixed_selHnd=-1,moving_selHnd=-1): #----------------------------------------------------------------------------- import mmdb2 as mmdb #print 'superpose_LSQ',fixed.name_label, fixed_selHnd, moving.name_label , moving_selHnd #***Limitations*** # Amino acids # Does not handle not sequence-order matching if self.parent.selected_atoms_mode == 'main': central_atom = 'CA,N,O,C' res_type = 'amino_acid' elif self.parent.selected_atoms_mode =='catrace': central_atom = 'CA' res_type = 'amino_acid' elif self.parent.selected_atoms_mode == 'nucleic': central_atom = "P,C1',C1*" res_type = 'nucleic_acid' elif self.parent.selected_atoms_mode == 'all': res_type = 'amino_acid' central_atom = central_atom = "*" elif self.parent.selected_atoms_mode == 'user': res_type = '' central_atom = self.parent.get_user_selected_atoms() # Get all the CA in amino acids fixed_molobj = data(self.fixed_MolData_name) if not fixed_molobj: return [-1,'Error with fixed model'] fixedHnd = fixed_molobj.molHnd.NewSelection() if res_type: fx_amino_acid = MODELINFO().get_names_string( key=res_type, set=fixed_molobj.name_label) else: fx_amino_acid = '*' fixed_olobj.molHnd.Select(fixedHnd ,mmdb.STYPE_ATOM,0,'*', \ mmdb.ANY_RES,'*',mmdb.ANY_RES,'*',fx_amino_acid,central_atom,'*','*',SKEY_NEW) if fixed_selHnd >0: fixed_molobj.molHnd.Select(fixedHnd,mmdb.STYPE_ATOM,fixed_selHnd,mmdb.SKEY_AND) selindexp = intp() fixed_atom = newPPCAtom() #fixed_nat = fixed_molobj.molHnd.GetSelIndex(fixedHnd,fixed_atom) fixed_atom = mmut.GetAtomSelIndex(fixed_molobj.molHnd,fixedHnd,selindexp) fixed_nat = selindexp.value() if ( fixed_nat < 3 ) : fixed_molobj.molHnd.DeleteSelection(fixedHnd) return [1,'Less than three residues containing '+central_atom+' selected for '+fixed_molobj.name_label] moving_molobj = data(self.MolData_name) movingHnd = moving_molobj.molHnd.NewSelection() moving_atom = newPPCAtom() #moving_nat = moving_molobj.molHnd.GetSelIndex(moving_selHnd,moving_atom) moving_atom = mmut.GetAtomSelIndex(moving_molobj.molHnd,moving_selHnd,selindexp) moving_nat = selindexp.value() #print 'superpose_LSQ moving_selHnd nat',moving_nat if res_type: mv_amino_acid = MODELINFO().get_names_string(key=res_type, set=moving_molobj.name_label) else: mv_amino_acid = '*' #print 'superpose mv_amino_acid',mv_amino_acid,central_atom moving_molobj.molHnd.Select(movingHnd ,mmdb.STYPE_ATOM,0,'*', \ mmdb.ANY_RES,'*',mmdb.ANY_RES,'*',mv_amino_acid,central_atom,'*','*',SKEY_NEW) if moving_selHnd > 0: moving_molobj.molHnd.Select(movingHnd,mmdb.STYPE_ATOM,moving_selHnd,mmdb.SKEY_AND) #moving_nat = moving_molobj.molHnd.GetSelIndex(movingHnd,moving_atom) moving_atom = mmut.GetAtomSelIndex(moving_molobj.molHnd,movingHnd,selindexp) moving_nat = selindexp.value() if ( moving_nat < 3 ) : fixed_molobj.molHnd.DeleteSelection(fixedHnd) moving_molobj.molHnd.DeleteSelection(movingHnd) return [1,'Less than three residues containing '+central_atom+' selected for '+moving.name_label] #print 'superpose_LSQ moving_nat',moving_nat,fixed_nat if ( moving_nat != fixed_nat ): fixed_molobj.molHnd.DeleteSelection(fixedHnd) moving_molobj.molHnd.DeleteSelection(movingHnd) return [1,'Different number of residues selected for models\n' + \ fixed_molobj.name_label+" has "+str(fixed_nat)+ '\n' + \ moving_molobj.name_label+" has "+str(moving_nat)] #rv = mmdb.SuperposeAtoms (TMatrix , moving_atom, moving_nat,fixed_atom,fixed_nat ) rv = moving_molobj.molHnd.TransformToSuperposeAtoms ( moving_atom, moving_nat,fixed_atom ) rms = moving_molobj.molHnd.AtomicRMSDistance(moving_atom, moving_nat,fixed_atom) #print "superpose_LSQ rv,rms",rv,rms self.last_rms = '%.2f/%i'%(rms,moving_nat) moving_molobj.update_dependents('transform') self.parent.emitUpdateSignal(self.MolData_name) self.displayed_match = 0 fixed_molobj.molHnd.DeleteSelection(fixedHnd) moving_molobj.molHnd.DeleteSelection(movingHnd) return [0,''] #----------------------------------------------------------------------------- def superpose_Close (self): #----------------------------------------------------------------------------- import mmdb2 as mmdb #print 'superpose_close',self.close_atoms_res_cutoff, self.close_atoms_cutoff fixed = data(self.fixed_MolData_name) moving = data(self.MolData_name) if not fixed or not moving: return [-1,'Fixed model not defined'] # Find the close atoms between the two models but use the selection masks moving_selHnd = self.get_selHnd() if moving_selHnd<0: return [-2,'Error selecting atoms for '+moving.name_label] fixed_selHnd = self.parent.supModel[self.fixed_MolData_name].get_selHnd() if fixed_selHnd<0: return [-2,'Error selecting atoms for '+fixed.name_label] self.conn2.Clear() nClose=self.conn2.AddCloseAtoms(fixed.molHnd, fixed_selHnd, moving.molHnd, moving_selHnd, self.parent.close_atoms_res_cutoff, self.parent.close_atoms_cutoff ,self.parent.close_atoms_central_atom, 0 ) #print 'superpose_Close',self.MolData_name,nClose if nClose<0: return [-1,'Error serching for close atoms'] elif nClose<3: return [-2,'Less than three close atoms found'] self.conn2.Superpose(1) rms = self.conn2.GetRMSD() moving_nat = self.conn2.GetNofConnections() self.last_rms = '%.2f/%i'%(rms,moving_nat) moving.update_dependents('transform') self.parent.emitUpdateSignal(self.MolData_name) self.displayed_match = 0 self.do_redraw = 1 return [0,''] #----------------------------------------------------------------------- def superpose_Matched(self): #----------------------------------------------------------------------- self.update_Connectivity2() #print 'superpose_Matched',self.MolData_name,self.conn2.GetNofConnections() if self.conn2.GetNofConnections()<3: return [-1,'Less than three matched atoms'] self.conn2.Superpose(1) rms = self.conn2.GetRMSD() self.last_rms = '%.2f/%i'%(rms,self.conn2.GetNofConnections()) #print ' superpose_Matched last_rms',self.last_rms #self.update_Connectivity2() self.parent.emitUpdateSignal(self.MolData_name) data(self.MolData_name).update_dependents('transform') return [0,''] #----------------------------------------------------------------------- def get_selHnd (self): #----------------------------------------------------------------------- self.selection = self.selection.strip() if self.selection: sele = self.selection else: sele = 'all' rv = data(self.MolData_name).parse_selection(command=sele) #print 'Superpose get_selHnd',self.MolData_name,sele,rv if not rv[0]: return rv[1] return -1 #----------------------------------------------------------------------- def nofModelsSelected(self): #----------------------------------------------------------------------- # Return the number of symmetry/NMR models in current selection # If this is >1 the gui will query user to continue molobj = data(self.MolData_name) if molobj.nmr_models <=1 and \ len(molobj.model_symmetry.get_symmetry_models())<=0: return 1 selHnd = self.get_selHnd() if selHnd<0: return 1 import mmdb2 as mmdb selindexp = intp() model_selHnd = molobj.molHnd.NewSelection() molobj.molHnd.Select(model_selHnd,mmdb.STYPE_MODEL,selHnd,mmdb.SKEY_NEW) pModels = newPPCModel() #nModels = molobj.molHnd.GetSelIndex(model_selHnd,pModels) pModels = mmut.GetModelSelIndex(molobj.molHnd,model_selHnd,selindexp) nModels = selindexp.value() #print 'nofModelsSelected',self.MolData_name,nModels molobj.molHnd.DeleteSelection(model_selHnd) return nModels #------------------------------------------------------------------------- def create_MolDisp(self): #------------------------------------------------------------------------- import model molobj =data(self.MolData_name) if not self.MolDisp: self.MolDisp = model.MolDisp(parent=molobj, name=self.MolData_name+'_superpose',master_application=self.parent) self.MolDisp.set_style(style_mode='PYRAMIDS') self.MolDisp.set_colour(self.parent.moving_mask_colour) #print 'create_MolDisp',mol,self.last_MolDisp_colour if not ['all','',' '].count(self.selection): #print 'Superpose.create_MolDisp',mol,self.status[mol]['selection'] self.MolDisp.set_selection(self.selection) self.MolDisp.SelHandle.mergeSelection(command='one_atom',op='and') #------------------------------------------------------------------------- def Print(self): #------------------------------------------------------------------------- moving_MolData = data(self.MolData_name) fixed_MolData = data(self.fixed_MolData_name) if not fixed_MolData: return 'Fixed model not set for: '+self.MolData_name if self.parent.method == 'close': output_text = 'Superposing '+moving_MolData.name_label + ' (atoms close to those selected for fixed model)\n' else: output_text = 'Moving: '+moving_MolData.name_label + ' (' + self.selection + ')\n' output_text= output_text+ 'Fixed: '+fixed_MolData.name_label + ' (' + self.parent.supModel[self.fixed_MolData_name].selection +')\n' if self.last_rms: output_text = output_text + '\nRMS of selected atoms: '+str(self.last_rms)+'\n\n' if self.MGAlign and self.parent.submethod == "ssm": output_text = output_text + \ '\n\n'+'Match number '+str(self.displayed_match)+ \ ' of '+str(self.nof_matches)+ \ ' (best result is number '+str(self.best_match)+')\n\n'+ \ self.MGAlign.Print(self.MolData_name,self.fixed_MolData_name )+'\n\n\n' if self.gesamt_matches and self.parent.submethod == "gesamt": output_text = '\n\n' + output_text + self.gesamt_matches +'\n\n' output_text = output_text +"\n\nTransformation applied to the moving model\n"+ moving_MolData.molHnd.GetTransformString() if fixed_MolData.molHnd.GetIsTransformed(): output_text = output_text + "NOTE: The fixed model is also transformed by\n"+fixed_MolData.molHnd.GetTransformString() return output_text #----------------------------------------------------------------- def export_matches(self,filename='',all=0,comments=[]): #----------------------------------------------------------------- import time if (not self.conn2) and self.conn2.GetNofConnections()<0: return [1,'No matches defined'] self.conn2.UpdateCoordinates(True) text='''loop_ _vector.start_model_id _vector.start_atom _vector.end_model_id _vector.end_atom _vector.label\n''' nV= self.conn2.GetNofConnections() #print "export_matches nV",nV for iV in range(0,nV): atom1 = self.conn2.GetAtomID(iV,1) atom2 = self.conn2.GetAtomID(iV,2) if atom1 and atom2: text=text+'"'+self.fixed_MolData_name+'" "'+atom1+'" ' \ +'"'+self.MolData_name+'" "'+atom2+'" ' \ +'"'+self.conn2.GetLabel(iV)+'" \n' # Create header head = '#Definition of vectors for display with CCP4mg\n'+ \ '# Matched atoms in Superposition\n' + \ '#Created on '+time.asctime(time.localtime(time.time()))+"\n" head = head+'\ndata_VECTORS\n' for item in comments: head = head+"# "+item+"\n" head = head+"\n\n" head = head+'''loop_ _model.id _model.filename\n''' head = head + self.fixed_MolData_name + ' ' + data(self.fixed_MolData_name).getFilename() + '\n' head = head + self.MolData_name + ' ' + data(self.MolData_name).getFilename() + '\n' if self.parent.show_distances == cprim.LABELLEDCENTRE: labmo = '"label centre"' else: labmo = '"no label"' head = head+'''\n\nloop_ _display_objects.line_colour _display_objects.line_style _display_objects.line_width _display_objects.label_mode _display_objects.label_colour "complement" "dashed" 2 '''+ labmo + ' "complement"\n\n' text = head + "\n" + text if filename: import utils utils.saveFile(filename=filename,text=text) return [0,text] #----------------------------------------------------------- #----------------------------------------------------------- #----------------------------------------------------------- class SuperposeMatch: #----------------------------------------------------------- #----------------------------------------------------------- #----------------------------------------------------------- initialise = { 'mode' : 'range', 'close' : 0, 'on' : 1, 'sele1' : '', 'sele2' : '', 'qualifier' : '' } def __init__(self,params={},mode='range',close=0,sele1='',sele2='',qualifier='',on=1): self.mode = mode self.close = close self.on = on self.sele1= sele1 self.sele2 = sele2 self.qualifier = qualifier self.setparams(params) def set(self,key,value): setattr(self,key,value) def get(self,key): return getattr(self,key,'') def isSame(self,other): if self.mode != other.mode or self.close != other.close or self.qualifier != other.qualifier: return 0 if self.sele1 == other.sele1 and self.sele2 == other.sele2: return 1 elif self.sele1 == other.sele2 and self.sele2 == other.sele1: return -1 else: return 0 def getparams(self,swap_selections=0): pars = {} for key in SuperposeMatch.initialise: pars[key] = getattr(self,key,'') if swap_selections: pars['sele1'] = getattr(self,'sele2','') pars['sele2'] = getattr(self,'sele1','') return pars def setparams(self,params): for key,value in params.items(): setattr(self,key,value) def getUnmatched(self,model=1): if model == 1 and not self.sele2: return [self.mode,self.sele1] elif model == 2 and not self.sele1: return [self.mode,self.sele2] else: return [] def getUnmatchedMenu(self,model=1,start=0): conversions = { } if start: if self.mode=='range'and self.qualifier=='first' : if model == 1 and self.sele1: return ['End range from ' + self.sele1] elif model == 2 and self.sele2: return ['End range from ' + self.sele2] else: return [] else: return [] else: unmatched = self.getUnmatched(model) if unmatched: if unmatched[0]=='range': menu_item_list = [ ['start','Start of range ' + unmatched[1]] ] if self.qualifier != 'first': menu_item_list.append(['end','End of range ' + unmatched[1]]) return menu_item_list elif conversions.has_key(unmatched[0]): return [ [conversions[unmatched[0]],conversions[unmatched[0]] + ' '+unmatched[1] ] ] else: return [ [ unmatched[0],unmatched[0]+' '+unmatched[1] ] ] else: return [] ''' else: for ii in range(0,len(list1)): if ['close',''].count(list2[ii]): if list1[ii][0:4]=='rang': menu.append(list1[ii]+' start') menu.append(list1[ii]+' end') else: menu.append(list1[ii]) ''' #----------------------------------------------------------------------- def setEndOfRange(self,mode='start',fixed_MolData_name='',MolData_name=''): #----------------------------------------------------------------------- #print 'setEndOfRange',mode,fixed_MolData_name,MolData_name if mode == 'end': direction = -1 else: direction = 1 pres1=self.getResPointers(self.sele1,fixed_MolData_name) pres2=self.getResPointers(self.sele2,MolData_name) pr1 = 0 pr2 = 0 irdif1 = 0 irdif2 = 0 if len(pres1)==2: if (pres1[0].GetChain().GetChainID() != pres1[1].GetChain().GetChainID()): return [1,'The selected residues in the fixed model are not in the same chain'] irdif1 = pres1[1].GetResidueNo() - pres1[0].GetResidueNo() if len(pres2)==2: if (pres2[0].GetChain().GetChainID() != pres2[1].GetChain().GetChainID()): return [1,'The selected residues in the moving model are not in the same chain'] irdif2 = pres2[1].GetResidueNo() - pres2[0].GetResidueNo() #print 'setEndOfRange irdif',irdif1,irdif2 if irdif1 and irdif2: if irdif1 != irdif2: return [1,'The selected ranges have different numbers of residues'] else: return [0,''] elif (not irdif1) and (not irdif2): return [2,'No range selected yet'] elif irdif1: if len(pres2): pr2 = pres2[0].GetChain().GetResidue( pres2[0].GetResidueNo()+(direction*irdif1) ) #print 'setEndOfRange',irdif1,'pr2',pr2 if not pr2: return [1,'The selected range in the fixed model can not be matched in the moving model'] if direction<0: rv = data(MolData_name).getResidueID(pr2,pres2[0]) else: rv = data(MolData_name).getResidueID(pres2[0],pr2) self.sele2 = rv[0] elif irdif2: if len(pres1): pr1 = pres1[0].GetChain().GetResidue(pres1[0].GetResidueNo()+(direction*irdif2)) #print 'setEndOfRange',irdif2,'pr1',pr1 if not pr1: return [1,'The selected range in the moving model can not be matched in the fixed model'] if direction<0: rv = data(fixed_MolData_name).getResidueID(pr1,pres1[0]) else: rv = data(fixed_MolData_name).getResidueID(pres1[0],pr1) self.sele1 = rv[0] #print 'setEndOfRange',self.sele1,self.sele2 return [0,''] #----------------------------------------------------------------------- def getResPointers(self,sele='',MolData_name=''): #----------------------------------------------------------------------- molobj = data(MolData_name) import string pslash = sele.rfind('/') if pslash<0: return [] pdash = sele.rfind('-') #print 'getResPointers',sele, pslash, pdash rv = [] if pdash<0: r1 = molobj.interpretResidueID(sele) if r1[0]==1: rv.append(r1[1]) else: r1 = molobj.interpretResidueID(sele[0:pdash]) r2 = molobj.interpretResidueID(sele[0:pslash+1]+sele[pdash+1:]) if r1[0]==1: rv.append(r1[1]) if r2[0]==1: rv.append(r2[1]) return rv