""" qtgui/modelUtils.py: CCP4MG Molecular Graphics Program Copyright (C) 2009 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 PyQt4 import QtGui,QtCore from global_definitions import * import guiUtils import MGSimpleDialog,mgWidgets import model import functools #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class ModelSecStrEditor(MGSimpleDialog.MGSimpleDialog): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent,MolData=''): #------------------------------------------------------------------- MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.MolData = MolData #print "ModelColourEditor.__init__ MolData",self.MolData,self.parent self.setWindowTitle('Edit secondary structure for '+MolData) layout = QtGui.QVBoxLayout() widget = QtGui.QLabel('Override automatic secondary structure assignment',self) layout.addWidget(widget) #edit_frame = QtGui.QFrame() #edit_frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) #edit_layout = QtGui.QVBoxLayout() self.exFrame = mgWidgets.extendingFrame(self,widget=ModelSecStrLine,ifClose=1,ifClear=1,width=0) self.exFrame.show() layout.addWidget(self.exFrame) #edit_frame.setLayout(edit_layout) #layout.addWidget(edit_frame) self.setLayout(layout) self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.apply) self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close) self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu) self.loadFromModelInfo() #---------------------------------------------------------------------- def loadFromModelInfo(self): #---------------------------------------------------------------------- status,data = MODELINFO().get_info( set=self.MolData,info= 'edit_secstr') #print 'ModelSecStrEditor from MODELINFO',status,data if not status and data.has_key('secstr') and data.has_key('selection_command'): self.setParams(selection_command=data['selection_command'],secstr=data['secstr']) #---------------------------------------------------------------------- def apply(self): #---------------------------------------------------------------------- params = self.getParams() if params.has_key('selection_command') and params['selection_command']: secstr= [] for item in params['secstr']: secstr.append(model.MolData.secstr_alias[model.MolData.secstr_menu.index(item)]) #print 'ModelSecStrEditor.apply',secstr MODELINFO().add_info(set=self.MolData,info='edit_secstr',key='secstr',value=secstr) MODELINFO().add_info(set=self.MolData,info='edit_secstr',key='selection_command',value=params['selection_command']) target = data(self.MolData) if target: target.apply_edit_secstr(apply=1) target.redraw_all_objects() UPDATEDISPLAY() #---------------------------------------------------------------------- def atomPickMenu(self,pickevent=None): #---------------------------------------------------------------------- #print 'ModelSecStrEditor.atomPickMenu',pickevent if not self.isVisible(): return dobj = pickevent.getDataObj() menu = pickevent.getContextMenu() if not dobj or not menu or (not dobj.name == self.MolData): return name = str(self.objectName()) guiUtils.populateMenu(self,menu,[['Set secondary structure for this',name+'range_2',name+'residue',name+'range_1']],self.getActionDef,info = { 'pickevent' : pickevent } ) #---------------------------------------------------------------------- def getActionDef(self,name,**info): #---------------------------------------------------------------------- #print "ModelColourEditor.getActionDef",name,info name = name[len(str(self.objectName())):] pickevent=info.get('pickevent','') if not pickevent: return args = [name,pickevent.getLabel(format='full')] if name == 'residue': return dict ( text = 'Residue', tip = 'Colour the selected residue', slot = [self.editPickedResidue,args], deleteLater = 1, ) if name == 'range_1': return dict ( text = 'Start range', tip = 'Select first residue in a range', slot = [self.editPickedResidue,args], deleteLater = 1, ) if name == 'range_2': if not hasattr(self,'pickedRangeStart'): return {} return dict ( text = 'Range from '+self.pickedRangeStart, tip = 'Select end residue in a range', slot = [self.editPickedResidue,args], deleteLater = 1, ) else: return {} #---------------------------------------------------------------------- def editPickedResidue(self,args=[]): #---------------------------------------------------------------------- #print "ModelSecstrEditor.editPickedResidue",args name,atom_id = args if ['residue','range_1'].count(name): selection= data(self.MolData).convertAtomID (out = 'residue', atomID =atom_id ) elif name == 'range_2': res2 = data(self.MolData).convertAtomID (out = 'residue', atomID =atom_id ) selection = data(self.MolData).interpretRanges(self.pickedRangeStart,atom_id)[1] del self.pickedRangeStart #print "editPickedAtom selection",selection if name == 'range_1': self.pickedRangeStart = selection return else: self.exFrame.addLine() self.exFrame.setParams(params = { 'selection_command': [ selection] }, index=self.exFrame.getNofLines()-1) def getParams(self): params = self.exFrame.getParams({'selection_command':[],'secstr':[]}) #print 'ModelSecStrEditor.getParams',params return params def setParams(self,params={},**kw): params.update(kw) #print 'ModelSecStrEditor.setParams',params if params.has_key('selection_command') and params.has_key('secstr'): secstr= [] for item in params['secstr']: if model.MolData.secstr_alias.count(item): secstr.append(model.MolData.secstr_menu[model.MolData.secstr_alias.index(item)]) else: secstr.append(item) params['secstr'] = secstr self.exFrame.setParams(params) #----------------------------------------------------------------------- #----------------------------------------------------------------------- #----------------------------------------------------------------------- class ModelSecStrLine(QtGui.QWidget): #----------------------------------------------------------------------- #----------------------------------------------------------------------- #----------------------------------------------------------------------- def __init__(self,parent=None): QtGui.QWidget.__init__(self,parent) #print "ColourBlendLine parent",parent,parent.parent() layout = QtGui.QHBoxLayout() layout.setContentsMargins(0,0,0,0) layout.setSpacing(0) abstractModel = data(self.window().MolData).treeModel self.seleCombo = mgWidgets.mgSelectionCombo(self,abstractModel,modelGroups=['peptide'],selectionWidgets=[]) self.seleCombo.setToolTip('Select residue or range of residues') self.seleCombo.setObjectName('selection_command') layout.addWidget(self.seleCombo) # There must be better way of doing this! self.secstrCombo = QtGui.QComboBox(self) for item in model.MolData.secstr_menu: self.secstrCombo.addItem(item) self.secstrCombo.setToolTip('Secondary structure assignment for residue(s)') self.secstrCombo.setObjectName('secstr') layout.addWidget(self.secstrCombo) self.setLayout(layout) #----------------------------------------------------------------------- def setDefault(self): #----------------------------------------------------------------------- self.seleCombo.clear() self.secstrCombo.setCurrentIndex(0) ''' #----------------------------------------------------------------------- def getParams(self): #----------------------------------------------------------------------- pars = {} pars['secstr'] = model.MolData.secstr_alias[self.secstrCombo.currentIndex()] pars['selection_command'] = self.seleCombo.text() return pars #----------------------------------------------------------------------- def setParams(self,params={},**kw): #----------------------------------------------------------------------- params.update(kw) print 'ModelSecStrLine.setParams',params if params.has_key('secstr'): if model.MolData.secstr_alias.count(params['secstr']): self.secstrCombo.setCurrentIndex(model.MolData.secstr_alias.index(params['secstr'])) elif model.MolData.secstr_menu.count(params['secstr']): self.secstrCombo.setCurrentIndex(model.MolData.secstr_menu.index(params['secstr'])) if params.has_key('selection_command'): self.seleCombo.setText(params['selection_command']) ''' class editCIFFilesGui(MGSimpleDialog.MGSimpleDialog): def __init__(self,parent=None,MolData=''): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.MolData_name = MolData self.setWindowTitle('Edit residue types for '+self.MolData_name) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) layout = QtGui.QVBoxLayout() layout.addWidget(QtGui.QLabel('For residue types not recognised by the monomer library enter the name',self)) layout.addWidget(QtGui.QLabel('of residue and the cif file that goes with it.',self)) self.exFrame = mgWidgets.extendingFrame(self,widget=editCIFFilesLine,ifClose=1,width=0) layout.addWidget(self.exFrame) self.setLayout(layout) self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply) self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close) self.loadData() def Apply(self): params = self.getParams() target = data(self.MolData_name) if target and hasattr(target,"setCustomResCIFFiles"): target.setCustomResCIFFiles(params) target.GetMolBonds() target.redraw_all_objects() def getParams(self): params = self.exFrame.getParams({'resname':[],'dict':[]}) p = {} for key,val in zip(params['resname'],params['dict']): p[key] = val return p def loadData(self): target = data(self.MolData_name) if target: keys = [] vals = [] for key,val in target.customResCIFFiles.items(): keys.append(key) vals.append(val) params = {} params['resname'] = keys params['dict'] = vals self.exFrame.setParams(params) class editCIFFilesLine(QtGui.QWidget): def __init__(self,parent): QtGui.QWidget.__init__(self,parent) layout = QtGui.QHBoxLayout() layout.setContentsMargins(0,0,0,0) layout.setSpacing(0) widget = QtGui.QLineEdit(self) widget.setToolTip('Residue name (usually 3-letter code)') widget.setObjectName('resname') layout.addWidget(widget) ciffilewidget = QtGui.QLineEdit(self) ciffilewidget.setToolTip('CIF dictionary file') ciffilewidget.setObjectName('dict') layout.addWidget(ciffilewidget) widget = QtGui.QPushButton("Browse",self) widget.setAutoDefault(False) widget.setToolTip('Pick a CIF dictionary file on your computer') layout.addWidget(widget) def getFile(dum=True): w = QtGui.QFileDialog() w.setFileMode(QtGui.QFileDialog.ExistingFile) w.setOption(QtGui.QFileDialog.DontUseNativeDialog,True) f = w.exec_() if f: ciffilewidget.setText(w.selectedFiles()[0]) widget.clicked.connect(getFile) self.setLayout(layout) def setDefault(self): self.findChild(QtGui.QWidget,'resname').setText('') self.findChild(QtGui.QWidget,'dict').setText('') #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class editRestypesGui(MGSimpleDialog.MGSimpleDialog): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent=None,MolData=''): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.MolData_name = MolData self.setWindowTitle('Edit residue types for '+self.MolData_name) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) layout = QtGui.QVBoxLayout() layout.addWidget(QtGui.QLabel('For residue types not recognised by the monomer library enter the name',self)) layout.addWidget(QtGui.QLabel('of residue and either the equivalent library name and/or the residue type',self)) self.exFrame = mgWidgets.extendingFrame(self,widget=editRestypesLine,ifClose=1,width=0) self.exFrame.show() layout.addWidget(self.exFrame) self.setLayout(layout) self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply) self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close) self.loadData() #------------------------------------------------------------------- def Apply(self): #------------------------------------------------------------------- params = self.getParams() # Set up selection_protocols dictionary with items for the # 'standard' residue types # sel_prot[type]['ORDER'] is a list for each residue type (eg protein/monomer/etc) of # of the residue names (eg 'ALA'/'NAD') that are that type sel_prot = {} # Load sel_prot with the residue type info from the GUI for ii in range(len(params['resname'])): if not sel_prot.has_key(params['restype'][ii]): sel_prot[params['restype'][ii]]= { 'ORDER' : [] } if not sel_prot[params['restype'][ii]]['ORDER'].count(params['resname'][ii]): sel_prot[params['restype'][ii]]['ORDER'].append(params['resname'][ii]) #print 'editRestypesGui.Apply',sel_prot # For each 'standard' type either add or delete from ModelInfo # dependent on whether there is an info in the sel_prot item for type in model.MolData.restype_alias: if sel_prot.has_key(type): ret = MODELINFO().add_info(set=self.MolData_name, info='selection_protocols',key=type,value=sel_prot[type]) else: MODELINFO().delete_info(set=self.MolData_name, info='selection_protocols',key=type) # Clear out any saved residue aliases MODELINFO().delete_info(set=self.MolData_name,info='residue_aliases',key='*') # Save the residue name alias info for ii in range(len(params['resname'])): if params['resname'][ii] and params['alias'][ii]: ret = MODELINFO().add_info(set=self.MolData_name,info='residue_aliases', key=params['resname'][ii],value=params['alias'][ii]) MODELINFO().save(set=self.MolData_name) target = data(self.MolData_name) if target: target.updateCustomResTypes() target.analyse_restypes() target.GetMolBonds() target.redraw_all_objects() UPDATEDISPLAY() #------------------------------------------------------------------- def loadData(self): #------------------------------------------------------------------- import types restype_type = [] restype_res = [] restype_alias = [] #Get the residue name aliases status,alias= MODELINFO().get_info(set=self.MolData_name,info='residue_aliases') #print "status,alias",status,alias if not status: for key,value in alias.items(): restype_res.append(key) restype_alias.append(value) restype_type.append('') status,sel_prot= MODELINFO().get_info(set=self.MolData_name,info='selection_protocols') #print 'editRestypesGui.loadData',self.MolData_name,status,sel_prot for type in model.MolData.restype_alias: if sel_prot.has_key(type) and sel_prot[type].has_key('ORDER'): for item in sel_prot[type]['ORDER']: if restype_res.count(item): ii = restype_res.index(item) restype_type[ii] = type else: restype_type.append(type) restype_res.append(item) restype_alias.append('') #print 'editRestypesGui.loadData',restype_res,restype_alias,restype_type self.setParams( { 'resname' : restype_res, 'alias' : restype_alias, 'restype' : restype_type } ) #------------------------------------------------------------------- def getParams(self): #------------------------------------------------------------------- params = self.exFrame.getParams({'resname':[],'alias':[],'restype':[]}) restype = [] for item in params['restype']: if model.MolData.restype_menu.count(item): restype.append(model.MolData.restype_alias[model.MolData.restype_menu.index(item)]) else: restype.append(item) params['restype'] = restype #print 'editRestypesGui.getParams',params return params #------------------------------------------------------------------- def setParams(self,params={},**kw): #------------------------------------------------------------------- params.update(kw) #print 'editRestypesGui.setParams',params for item in ['resname','alias','restype']: if not params.has_key(item): return restype = [] for item in params['restype']: if model.MolData.restype_alias.count(item): restype.append(model.MolData.restype_menu[model.MolData.restype_alias.index(item)]) else: restype.append(item) params['restype'] = restype self.exFrame.setParams(params) #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class editRestypesLine(QtGui.QWidget): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent): QtGui.QWidget.__init__(self,parent) layout = QtGui.QHBoxLayout() layout.setContentsMargins(0,0,0,0) layout.setSpacing(0) widget = QtGui.QLineEdit(self) widget.setToolTip('Residue name (usually 3-letter code)') widget.setObjectName('resname') layout.addWidget(widget) widget = QtGui.QLineEdit(self) widget.setToolTip('Alternative residue name used in the monomer library') widget.setObjectName('alias') layout.addWidget(widget) widget = QtGui.QComboBox(self) widget.setToolTip('Assign residue to chemical type to help atom selection') widget.setObjectName('restype') for item in model.MolData.restype_menu: widget.addItem(item) layout.addWidget(widget) self.setLayout(layout) def setDefault(self): self.findChild(QtGui.QWidget,'resname').setText('') self.findChild(QtGui.QWidget,'alias').setText('') self.findChild(QtGui.QWidget,'restype').setCurrentIndex(0) #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class editBondsGui(MGSimpleDialog.MGSimpleDialog): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent=None,MolData=''): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.MolData_name = MolData self.setWindowTitle('Edit bonds for '+self.MolData_name) layout = QtGui.QVBoxLayout() layout.addWidget(QtGui.QLabel('Add or remove bonds in the structure',self)) self.exFrame = mgWidgets.extendingFrame(self,widget=editBondsLine,ifClose=1,width=0) self.exFrame.show() layout.addWidget(self.exFrame) self.setLayout(layout) self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply) self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close) self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu) self.loadData() #------------------------------------------------------------------- def Apply(self): #------------------------------------------------------------------- params = self.getParams() edit_bonds = [] for i in range(len(params['first_atom'])): if params['first_atom'][i] and params['second_atom'][i]: edit_bonds.append([params['first_atom'][i],params['second_atom'][i],params['action'][i]]) MODELINFO().add_info(set=self.MolData_name,info='edit_bonds',key='edit_bonds',value=edit_bonds) #print "editBondsGui",edit_bonds data(self.MolData_name).apply_edit_bonds() import rebuild rebuild.UpdateDisplay() #------------------------------------------------------------------- def Close(self): #------------------------------------------------------------------- self.disconnect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu) MGSimpleDialog.MGSimpleDialog.Close(self) #------------------------------------------------------------------- def loadData(self): #------------------------------------------------------------------- first_atom = [] second_atom = [] action = [] status,edit_bonds = MODELINFO().get_info( set=self.MolData_name,info= 'edit_bonds',key='edit_bonds') if edit_bonds.has_key('edit_bonds'): for item in edit_bonds['edit_bonds']: first_atom.append(item[0]) second_atom.append(item[1]) action.append(item[2]) self.setParams( { 'first_atom' : first_atom, 'second_atom' : second_atom, 'action' : action } ) #------------------------------------------------------------------- def getParams(self): #------------------------------------------------------------------- params = self.exFrame.getParams({'first_atom':[],'second_atom':[],'action':[]}) return params #------------------------------------------------------------------- def setParams(self,params={},**kw): #------------------------------------------------------------------- params.update(kw) self.exFrame.setParams(params) #---------------------------------------------------------------------- def atomPickMenu(self,pickevent=None): #---------------------------------------------------------------------- dobj = pickevent.getDataObj() if not self.isVisible() or not dobj or not dobj.name == self.MolData_name: return menu = pickevent.getContextMenu() if not menu: return name = str(self.objectName()) guiUtils.populateMenu(self,menu,[['Add/delete bond',name+'atom_2',name+'atom_1']],self.getActionDef,info = { 'pickevent' : pickevent } ) #---------------------------------------------------------------------- def getActionDef(self,name,**info): #---------------------------------------------------------------------- #print "ModelColourEditor.getActionDef",name,info name = name[len(str(self.objectName())):] pickevent=info.get('pickevent','') if not pickevent: return args = [name,pickevent.getLabel(format='full')] if name == 'atom_1': return dict ( text = 'First atom', tip = 'Select first atom in bond', slot = [self.handlePickedAtom,args], deleteLater = 1, ) if name == 'atom_2': if not hasattr(self,'firstPickedAtom'): return {} return dict ( text = 'Bond from '+self.firstPickedAtom, tip = 'Select second atom for bond', slot = [self.handlePickedAtom,args], deleteLater = 1, ) else: return {} #---------------------------------------------------------------------- def handlePickedAtom(self,args=[]): #---------------------------------------------------------------------- #print "ModelColourEditor.colourPickedAtom",args name,atom_id = args if ['atom_1'].count(name): self.firstPickedAtom = atom_id elif name == 'atom_2': self.exFrame.addLine() self.exFrame.setParams(params = { 'first_atom': [self.firstPickedAtom ], 'second_atom' : [ atom_id ] }, index=self.exFrame.getNofLines()-1) del self.firstPickedAtom self.Apply() #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class editBondsLine(QtGui.QWidget): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent): QtGui.QWidget.__init__(self,parent) layout = QtGui.QHBoxLayout() layout.setContentsMargins(0,0,0,0) layout.setSpacing(0) widget = QtGui.QComboBox(self) widget.setToolTip('Add or delete bond') widget.setObjectName('action') for item in ['add', 'delete']: widget.addItem(item) layout.addWidget(widget) widget = mgWidgets.mgAtomPicker(self,MolData_name=self.window().MolData_name) widget.setToolTip('First atom of bond') widget.setObjectName('first_atom') layout.addWidget(widget) widget = mgWidgets.mgAtomPicker(self,MolData_name=self.window().MolData_name) widget.setToolTip('Second atom of bond') widget.setObjectName('second_atom') layout.addWidget(widget) self.setLayout(layout) def setDefault(self): self.findChild(QtGui.QWidget,'first_atom').reset() self.findChild(QtGui.QWidget,'second_atom').reset() self.findChild(QtGui.QWidget,'action').setCurrentIndex(0) #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class editLinksGui(MGSimpleDialog.MGSimpleDialog): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent=None,MolData=''): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.MolData_name = MolData self.setWindowTitle('Edit links for '+self.MolData_name) layout = QtGui.QVBoxLayout() layout.addWidget(QtGui.QLabel('Define intra-residue links',self)) self.exFrame = mgWidgets.extendingFrame(self,widget=editLinksLine,ifClose=1,width=0) self.exFrame.show() layout.addWidget(self.exFrame) self.setLayout(layout) self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply) self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.close) #self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu) self.loadData() #------------------------------------------------------------------- def Apply(self): #------------------------------------------------------------------- params = self.getParams() edit_links = [] for i in range(len(params['first_atom'])): if params['first_atom'][i] and params['second_atom'][i] and \ params['first_res'][i] and params['second_res'][i] : edit_links.append([ params['first_res'][i],params['first_atom'][i],params['second_res'][i],params['second_atom'][i]]) MODELINFO().add_info(set=self.MolData_name,info='edit_links',key='edit_links',value=edit_links) #print "editBondsGui",edit_bonds data(self.MolData_name).apply_edit_links() import rebuild rebuild.UpdateDisplay() #------------------------------------------------------------------- def Close(self): #------------------------------------------------------------------- #self.disconnect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu) MGSimpleDialog.MGSimpleDialog.Close(self) #------------------------------------------------------------------- def loadData(self): #------------------------------------------------------------------- first_atom = [] second_atom = [] first_res = [] second_res = [] status,edit_links = MODELINFO().get_info( set=self.MolData_name,info= 'edit_links',key='edit_links') if edit_links.has_key('edit_links'): for item in edit_links['edit_links']: first_res.append(item[0]) first_atom.append(item[1]) second_res.append(item[2]) second_atom.append(item[3]) self.setParams( { 'first_atom' : first_atom, 'second_atom' : second_atom, 'first_res' : first_res, 'second_res' : second_res } ) #------------------------------------------------------------------- def getParams(self): #------------------------------------------------------------------- params = self.exFrame.getParams({'first_atom':[],'second_atom':[], 'first_res':[],'second_res':[]}) return params #------------------------------------------------------------------- def setParams(self,params={},**kw): #------------------------------------------------------------------- params.update(kw) self.exFrame.setParams(params) #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class editLinksLine(QtGui.QWidget): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent): QtGui.QWidget.__init__(self,parent) layout = QtGui.QHBoxLayout() layout.setContentsMargins(0,0,0,0) layout.setSpacing(0) widget = QtGui.QLineEdit(self) widget.setToolTip('Add first residue name (usually 3-letter code) ') widget.setObjectName('first_res') layout.addWidget(widget) widget = QtGui.QLineEdit(self) widget.setToolTip('Add first atom name') widget.setObjectName('first_atom') layout.addWidget(widget) widget = QtGui.QLineEdit(self) widget.setToolTip('Add second residue name (usually 3-letter code) ') widget.setObjectName('second_res') layout.addWidget(widget) widget = QtGui.QLineEdit(self) widget.setToolTip('Add second atom name') widget.setObjectName('second_atom') layout.addWidget(widget) self.setLayout(layout) def setDefault(self): self.findChild(QtGui.QWidget,'first_atom').setText('') self.findChild(QtGui.QWidget,'second_atom').setText('') self.findChild(QtGui.QWidget,'first_res').setText('') self.findChild(QtGui.QWidget,'second_res').setText('') #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class SymmetryMatesGui(MGSimpleDialog.MGSimpleDialog): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- def __init__(self,parent=None,MolData=''): MGSimpleDialog.MGSimpleDialog.__init__(self,parent) self.MolData_name = MolData self.setWindowTitle('Show symmetry mates for '+self.MolData_name) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) layout = QtGui.QVBoxLayout() layout.setContentsMargins(2,2,2,2) layout.setSpacing(2) frame = QtGui.QFrame() frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) frame_layout = QtGui.QVBoxLayout() frame_layout.addWidget(QtGui.QLabel('Automatic search for symmetry mates contacting the model',self)) line_layout = QtGui.QHBoxLayout() #line_layout.addWidget(QtGui.QLabel('Search over',self)) #self.nCells = QtGui.QComboBox(self) #for item in ['1','2','3','4']: self.nCells.addItem(item) #line_layout.addWidget(self.nCells) line_layout.addWidget(QtGui.QLabel('Search for symmetry mates within',self)) self.radius = QtGui.QDoubleSpinBox(self) self.radius.setRange(0.5,10.0) self.radius.setSingleStep(0.5) line_layout.addWidget(self.radius) line_layout.addWidget(QtGui.QLabel('A of',self)) frame_layout.addLayout(line_layout) line_layout = QtGui.QHBoxLayout() line_layout.addWidget(QtGui.QLabel('Contact area of model',self)) abstractModel = data(self.MolData_name).treeModel self.seleCombo = mgWidgets.mgSelectionCombo(self,abstractModel,selectionWidgets=[]) self.seleCombo.setToolTip('Optionally select limited contact area of model') line_layout.addWidget(self.seleCombo) frame_layout.addLayout(line_layout) line_layout = QtGui.QHBoxLayout() line_layout.addStretch(5) widget = QtGui.QPushButton('Search for contacting symmetry mates',self) widget.setAutoDefault(0) self.connect(widget,QtCore.SIGNAL('clicked()'),self.autoSearch) line_layout.addWidget(widget) frame_layout.addLayout(line_layout) frame.setLayout(frame_layout) layout.addWidget(frame) MolDisp_selection_menu = data(self.MolData_name).model_symmetry.MolDisp_selection_menu frame = QtGui.QFrame() frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) frame_layout = QtGui.QVBoxLayout() line_layout = QtGui.QHBoxLayout() self.MolDisp_visible = QtGui.QCheckBox('Show',self) line_layout.addWidget(self.MolDisp_visible) self.MolDisp_selection = QtGui.QComboBox(self) for item in MolDisp_selection_menu: self.MolDisp_selection.addItem(item) line_layout.addWidget(self.MolDisp_selection) line_layout.addWidget(QtGui.QLabel('of symmetry mates in separate display object',self)) line_layout.addStretch(5) frame_layout.addLayout(line_layout) frame.setLayout(frame_layout) layout.addWidget(frame) self.MolDisp_visible.setChecked(data(self.MolData_name).model_symmetry.MolDisp_visible) sele = data(self.MolData_name).model_symmetry.MolDisp_selection if MolDisp_selection_menu.count(sele): self.MolDisp_selection.setCurrentIndex(MolDisp_selection_menu.index(sele)) self.connect(self.MolDisp_visible,QtCore.SIGNAL('toggled(bool)'),self.handleMolDisp) self.connect(self.MolDisp_selection,QtCore.SIGNAL('currentIndexChanged(int)'),self.handleMolDisp) layout.addWidget(QtGui.QLabel('Enter transformations',self)) self.exFrame = mgWidgets.extendingFrame(self,widget=symmetryMatesLine,ifClose=1,ifClear=1,width=0) self.connect(self.exFrame,QtCore.SIGNAL('cleared'),functools.partial(self.Apply,"clear")) self.connect(self.exFrame,QtCore.SIGNAL('lineAdded(int)'),self.handleNewLine) self.exFrame.show() layout.addWidget(self.exFrame) self.setLayout(layout) self.connect(self.exFrame,QtCore.SIGNAL('accepted()'),self.Apply) self.connect(self.exFrame,QtCore.SIGNAL('close()'),self.Close) self.radius.setValue(5.0) #self.nCells.setCurrentIndex(self.nCells.findText('2')) self.seleCombo.setText('all') self.loadData() self.connect(self.parent(),QtCore.SIGNAL('symmetryMatesChanged'),self.loadData) self.connect(MAINWINDOW(),QtCore.SIGNAL('atomContextMenu'),self.atomPickMenu) #------------------------------------------------------------------- def atomPickMenu(self,pickevent): #------------------------------------------------------------------- if not self.isVisible(): return dobj = pickevent.getDataObj() menu = pickevent.getContextMenu() atomlist = pickevent.getPickedAtoms() #print 'SymmetryMatesGui.atomPickMenu',dobj,atomlist,menu,dobj.name if not dobj or not menu or not atomlist or (not dobj.name == self.MolData_name): return # Is pick of an atom in symmetry mate model? model = atomlist[0].GetModelNum() model_symmetry = data(self.MolData_name).model_symmetry if not model_symmetry or model < model_symmetry.firstSymModel: return symop = model_symmetry.modelSymop(model) name = str(self.objectName()) guiUtils.populateMenu(self,menu,[['For symmetry mate '+symop,name+'delete',name+'hide']],self.getActionDef,info = { 'pickevent' : pickevent } ) #------------------------------------------------------------------- def getActionDef(self,name,**info): #------------------------------------------------------------------- name = name[len(str(self.objectName())):] pickevent=info.get('pickevent','') if not pickevent: return atomlist = pickevent.getPickedAtoms() model = atomlist[0].GetModelNum() args = [model] if name == 'delete': return dict ( text = 'Delete', tip = 'Delete the symmetry mate', slot = [self.deleteSymmMate,args], deleteLater = 1 ) if name == 'hide': return dict ( text = 'Hide', tip = 'Hide the symmetry mate', slot = [self.hideSymmMate,args], deleteLater = 1 ) #------------------------------------------------------------------- def deleteSymmMate(self,args): #------------------------------------------------------------------- model = args[0] params = self.exFrame.getParams(params={'model_num':[]}) if params['model_num'].count(model): self.exFrame.deleteLine(line=params['model_num'].index(model)) self.Apply() #------------------------------------------------------------------- def hideSymmMate(self,args): #------------------------------------------------------------------- model = args[0] params = self.exFrame.getParams(params={'model_num':[]}) if params['model_num'].count(model): sym_widget = self.exFrame.getLine(params['model_num'].index(model)) sym_widget.visible.setChecked(0) sym_widget.handleVisibility() #------------------------------------------------------------------- def autoSearch(self): #------------------------------------------------------------------- import string selection = self.seleCombo.text() if string.strip(selection) == '': selection = 'all' radius = self.radius.value() #xtl_limit = int(self.nCells.currentText()) xtl_limit = 2 sym_obj = data(self.MolData_name).model_symmetry sym_obj.delete_MolDisp() sym_obj.setSymmetryMates([]) models = sym_obj.get_symmetry_models() print "This should be empty",models rv = sym_obj.findSymmetryNeighbours(selection=selection,radius=radius,xtl_limit=xtl_limit) #print 'SymmetryMatesGui.autoSearch',rv if not rv[0]: sym_obj.setSymmetryMates(rv[1]) sym_obj.showSymmetryMates() self.redraw() params = data(self.MolData_name).model_symmetry.getGuiParams() #print 'autoSearch params',params self.setParams( params ) #------------------------------------------------------------------- def Apply(self,args=None): #------------------------------------------------------------------- params = self.getParams() sym_obj = data(self.MolData_name).model_symmetry molData = data(self.MolData_name) for obj in get_dispobj(object_type='MolDisp'): obj.clearPickedAtoms() sym_obj.setGuiParams(params,append=0) if args != "clear": sym_obj.showSymmetryMates() else: sym_obj.delete_MolDisp() models = sym_obj.get_symmetry_models() print models if models: self.exFrame.setParams( { 'model_num' : models, 'visible' : sym_obj.symmetry_visible, 'colour' :sym_obj.symmetry_colours } ) self.redraw() #------------------------------------------------------------------- def Close(self): #------------------------------------------------------------------- #data(self.MolData_name).model_symmetry.hideSymmetryMates() MGSimpleDialog.MGSimpleDialog.Close(self) #------------------------------------------------------------------- def handleNewLine(self,index): #------------------------------------------------------------------- widget = self.exFrame.getLine(index) #print 'handleNewLine',index,widget widget.colour.set_colour(data(self.MolData_name).model_symmetry.nextColour()) #------------------------------------------------------------------- def handleMolDisp(self,**kw): #------------------------------------------------------------------- #print 'handleMolDisp',kw target = data(self.MolData_name) if not target: return redraw = target.model_symmetry.setMolDisp(visible = int(self.MolDisp_visible.isChecked()), selection = str(self.MolDisp_selection.currentText()) ) if redraw: UPDATEDISPLAY(controllingWidget=self) #------------------------------------------------------------------- def loadData(self): #------------------------------------------------------------------- params = data(self.MolData_name).model_symmetry.getGuiParams() #print 'SymmetryMatesGui.loadData',params self.setParams( params ) #------------------------------------------------------------------- def redraw(self): #------------------------------------------------------------------- sym_obj = data(self.MolData_name).model_symmetry import rebuild rebuild.UpdateDisplay(controllingWidget=self) self.emit(QtCore.SIGNAL('nofModelsChanged')) #------------------------------------------------------------------- def getParams(self): #------------------------------------------------------------------- params = self.exFrame.getParams({'symop':[],'tran_a':[],'tran_b':[], 'tran_c': [], 'visible' : [], 'colour' : [] }) return params #------------------------------------------------------------------- def setParams(self,params={},**kw): #------------------------------------------------------------------- params.update(kw) self.exFrame.blockSignals(True) self.exFrame.setParams(params) self.exFrame.blockSignals(False) #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- class symmetryMatesLine(mgWidgets.frameLine): #------------------------------------------------------------------- #------------------------------------------------------------------- #------------------------------------------------------------------- TRAN_MENU = ['-5','-4','-3','-2','-1','0','1','2','3','4','5'] def __init__(self,parent): #QtGui.QWidget.__init__(self,parent) mgWidgets.frameLine.__init__(self,parent) target = data(self.window().MolData_name) if not target: return layout = QtGui.QHBoxLayout() layout.setContentsMargins(0,0,0,0) layout.setSpacing(0) self.model_num = QtGui.QLabel('/1',self) layout.addWidget(self.model_num) self.model_num.setObjectName('model_num') self.model_num.setToolTip('Model number for use in atom selection') layout.addWidget( QtGui.QLabel(' ',self)) self.symop = QtGui.QComboBox(self) self.symop.setObjectName('symop') self.symop.setToolTip('Symmetry operation') for item in target.model_symmetry.symops_titles: self.symop.addItem(item) self.connect(self.symop,QtCore.SIGNAL('currentIndexChanged(int)'),self.updateSymid) layout.addWidget(self.symop) for dirn in ['a','b','c']: name = 'tran_'+dirn widget = QtGui.QComboBox(self) widget.setObjectName(name) setattr(self,name,widget) widget.setToolTip('Unit cell translation in '+dirn+' direction') for item in symmetryMatesLine.TRAN_MENU: widget.addItem(item) widget.setCurrentIndex(5) self.connect(widget,QtCore.SIGNAL('currentIndexChanged(int)'),self.updateSymid) layout.addWidget(widget) layout.addStretch(1) self.symid = QtGui.QLabel('1_555',self) layout.addWidget(self.symid) layout.addStretch(1) self.symid.setToolTip('Symmetry id which can be used in atom selection') self.visible = QtGui.QCheckBox(self) self.visible.setToolTip("Model shown the 'symmetry' display object") self.visible.setChecked(1) self.visible.setObjectName('visible') self.connect(self.visible,QtCore.SIGNAL('toggled(bool)'),self.handleVisibility) layout.addWidget(self.visible) self.colour = mgWidgets.mgColourCombo(self) self.colour.setObjectName('colour') self.colour.setToolTip("Colour of model in the 'symmetry' object") self.connect(self.colour,QtCore.SIGNAL('currentIndexChanged(const QString)'),self.handleColour) layout.addWidget(self.colour) self.setLayout(layout) #------------------------------------------------------------------- def setDefault(self): #------------------------------------------------------------------- self.symop.setCurrentIndex(0) for dirn in ['a','b','c']: widget = getattr(self,'tran_',dirn) widget.setCurrentIndex(widget.findText('0')) self.visible.setChecked(1) #self.colour.setCurrentIndex(0) #------------------------------------------------------------------- def getParams(self): #------------------------------------------------------------------- pars = { 'model_num' : int(str(self.model_num.text())[1:]), 'symop' : str(self.symop.currentText()), 'tran_a' : str(self.tran_a.currentText()), 'tran_b' : str(self.tran_b.currentText()), 'tran_c' : str(self.tran_c.currentText()), 'visible' : int(self.visible.isChecked()), 'colour' : self.colour.get_colour() } #print 'symmetryMatesLine.getParams',pars return pars #------------------------------------------------------------------- def setParams(self,params): #------------------------------------------------------------------- #print 'symmetryMatesLine setParams',params symop = params.get('symop','') if symop: self.symop.setCurrentIndex(self.symop.findText(symop)) model_num = params.get('model_num','') if model_num: self.model_num.setText(model_num) for dirn in ['a','b','c']: tran = str(params.get('tran_'+dirn,'')) if tran and symmetryMatesLine.TRAN_MENU.count(tran): widget = getattr(self,'tran_'+dirn) widget.setCurrentIndex(symmetryMatesLine.TRAN_MENU.index(tran)) if params.has_key('visible'): self.visible.setChecked(params['visible']) if params.has_key('colour'): self.colour.set_colour(params['colour']) #------------------------------------------------------------------- def updateSymid(self,junk): #------------------------------------------------------------------- idx = str(self.symop.currentIndex()+1)+'_'+ \ str(int(self.tran_a.currentText())+5) + \ str(int(self.tran_b.currentText())+5) + \ str(int(self.tran_c.currentText())+5) self.symid.setText(idx) #------------------------------------------------------------------- def handleVisibility(self,state=-1): #------------------------------------------------------------------- target = data(self.window().MolData_name) #print 'symmetryMatesLine.handleVisibility',target,state if not target: return model = int(str(self.model_num.text()).strip('/')) target.model_symmetry.setVisibility(model,int(self.visible.isChecked())) target.model_symmetry.select_MolDisp() UPDATEDISPLAY(controllingWidget=self) #------------------------------------------------------------------- def handleColour(self,colour): #------------------------------------------------------------------- target = data(self.window().MolData_name) #print 'symmetryMatesLine.handleVisibility',target,state if not target: return model = int(str(self.model_num.text()).strip('/')) target.model_symmetry.setColour(model,self.colour.get_colour()) target.model_symmetry.colour_MolDisp() UPDATEDISPLAY(controllingWidget=self) #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- class DispObjTree( QtGui.QTreeWidget ): #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- def __init__(self,parent=None,dataobj_list=[],object_types=['MolDisp'],exclude=[]): #---------------------------------------------------------------------- QtGui.QTreeWidget.__init__(self,parent) self.headerItem().setHidden(1) self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.object_types = object_types self.exclude = exclude self.dataobj_list = dataobj_list self.populate() self.connect(DISPLAYTABLE(),QtCore.SIGNAL("addDataObj"),self.populate) self.connect(DISPLAYTABLE(),QtCore.SIGNAL("loadAllDataObj"),self.populate) self.connect(DISPLAYTABLE(),QtCore.SIGNAL("update"),self.populate) self.connect(DISPLAYTABLE(),QtCore.SIGNAL("removeDataObj"),self.populate) self.connect(DISPLAYTABLE(),QtCore.SIGNAL("deleteDataObj"),self.populate) #---------------------------------------------------------------------- def populate(self): #---------------------------------------------------------------------- root = self.invisibleRootItem() status = {} if root and self.invisibleRootItem().childCount(): for i in range(0,self.invisibleRootItem().childCount()): item = root.child(i) status[str(item.text(0))] = item.isExpanded() #print "populate status",status self.clear() self.disp_list = [] if self.dataobj_list: dataobj_list = [] for item in self.dataobj_list: dataobj_list.append(data(name=item)) else: dataobj_list = get_dataobj(object_type='MolData') #print ' DispObjTree.populate',self.dataobj_list,dataobj_list for object_type in self.object_types: for dataobj in dataobj_list: top = QtGui.QTreeWidgetItem ( [dataobj.name] ) top.setText(0,dataobj.name) top.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.ShowIndicator) #print "ModelInfoTree.populate top",set self.addTopLevelItem(top) dispobj_list = dataobj.get_dispobj(object_type=object_type) for item in dispobj_list: if not self.exclude.count(item.name): line = QtGui.QTreeWidgetItem ([item.get_selection_label()] ) top.addChild(line) line.setToolTip(0,item.name) if status.has_key(top): top.setExpanded(status[top]) else: top.setExpanded(1) #---------------------------------------------------------------------- def getCurrentDispObj(self): #---------------------------------------------------------------------- item = self.currentItem() #print 'DispObjTree.getCurrentDispObj',item if not item or not item.parent(): return '' return str(item.toolTip(0)) #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- class AsDispObjGui(QtGui.QDialog): #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- def __init__(self,parent=None,dataobj_list=[],exclude=[],object_types=['MolData']): QtGui.QDialog.__init__(self,parent) layout = QtGui.QVBoxLayout() self.tree = DispObjTree(dataobj_list=dataobj_list,exclude=exclude,object_types=object_types) layout.addWidget(self.tree ) buttons = QtGui.QDialogButtonBox(self) but = buttons.addButton('OK',QtGui.QDialogButtonBox.AcceptRole) self.connect(but,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.emitApply,1)) self.connect(but,QtCore.SIGNAL('clicked()'),self.close) but = buttons.addButton('Apply',QtGui.QDialogButtonBox.ApplyRole) self.connect(but,QtCore.SIGNAL('clicked()'),self.emitApply) but = buttons.addButton('Close',QtGui.QDialogButtonBox.RejectRole) self.connect(but,QtCore.SIGNAL('clicked()'),self.close) layout.addWidget(buttons ) self.setLayout(layout) return def emitApply(self,close=0): self.emit(QtCore.SIGNAL('apply'),(QtCore.QVariant(self.objectName()),QtCore.QVariant(self.getCurrentDispObj()))) if close: self.close() def populate(self): self.tree.populate() def getCurrentDispObj(self): return self.tree.getCurrentDispObj() #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- class AsDataObjGui(QtGui.QDialog): #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- def __init__(self,parent=None,exclude_list=[],object_type='MolData'): QtGui.QDialog.__init__(self,parent) layout = QtGui.QVBoxLayout() line = QtGui.QHBoxLayout() self.clear = QtGui.QCheckBox('Clear existing display objects',self) self.clear.setChecked(1) line.addWidget(self.clear) layout.addLayout(line) self.dataCombo = mgWidgets.mgDataObjCombo(object_type=object_type) if exclude_list: self.dataCombo.setExcludeDataObjList(exclude_list) layout.addWidget(self.dataCombo ) buttons = QtGui.QDialogButtonBox(self) but = buttons.addButton('OK',QtGui.QDialogButtonBox.AcceptRole) self.connect(but,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.emitApply,1)) self.connect(but,QtCore.SIGNAL('clicked()'),self.close) but = buttons.addButton('Apply',QtGui.QDialogButtonBox.ApplyRole) self.connect(but,QtCore.SIGNAL('clicked()'),self.emitApply) but = buttons.addButton('Close',QtGui.QDialogButtonBox.RejectRole) self.connect(but,QtCore.SIGNAL('clicked()'),self.close) layout.addWidget(buttons ) self.setLayout(layout) return def emitApply(self,close=0): if close: self.close() if self.getCurrentDataObj(): self.emit(QtCore.SIGNAL('apply'),(QtCore.QVariant(self.objectName()),QtCore.QVariant(self.getCurrentDataObj().name),QtCore.QVariant(self.clear.isChecked()))) def populate(self): self.dataCombo.populateMenu() def getCurrentDataObj(self): return self.dataCombo.getCurrentDataObj()