00001 import platform
00002
00003 from PyQt4 import QtCore, QtGui
00004
00005 import sip
00006
00007 from ost import geom, gfx, gui, seq
00008 from ost import settings
00009 from ost import LogError, mol
00010 from ost.bindings import tmtools
00011 from ost.bindings import msms
00012 from ost.seq import alg
00013 import ost
00014 from ost.gui.scene.query_editor import QueryEditorWidget,QueryDialog
00015
00016 class SelectRefDialog(QtGui.QDialog):
00017 def __init__(self, ent_list, parent=None):
00018 QtGui.QDialog.__init__(self, parent)
00019 self.ent_list_ = ent_list
00020 vb = QtGui.QVBoxLayout()
00021 self.setLayout(vb)
00022 self.setWindowTitle("Select Reference Object")
00023 self.label = QtGui.QLabel("Please Select the Reference Object")
00024 self.list = QtGui.QTableWidget(self)
00025 self.list.horizontalHeader().setStretchLastSection(True)
00026 self.list.setColumnCount(2)
00027 self.list.verticalHeader().setVisible(False)
00028 self.list.horizontalHeader().setVisible(False)
00029 self.list.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
00030 self.list.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
00031 vb.addWidget(self.label)
00032 vb.addWidget(self.list)
00033 self.show_scores = QtGui.QCheckBox(self)
00034 self.show_scores.setText("Show Scores")
00035 self.show_scores.setChecked(True)
00036 vb.addWidget(self.show_scores)
00037 self.show_alignment = QtGui.QCheckBox(self)
00038 self.show_alignment.setText("Display Alignment")
00039 self.show_alignment.setChecked(False)
00040 vb.addWidget(self.show_alignment)
00041 hb = QtGui.QHBoxLayout()
00042 hb.setDirection(QtGui.QBoxLayout.LeftToRight)
00043 cancel_btn = QtGui.QPushButton("Cancel", self)
00044 load_btn = QtGui.QPushButton("Select", self)
00045 hb.addStretch(1)
00046 hb.addWidget(cancel_btn)
00047 hb.addWidget(load_btn)
00048 vb.addItem(hb)
00049 load_btn.setDefault(True)
00050 QtCore.QObject.connect(load_btn, QtCore.SIGNAL("clicked()"), self.Select)
00051 QtCore.QObject.connect(cancel_btn, QtCore.SIGNAL("clicked()"), self.reject)
00052
00053 row = 0
00054 for ent in self.ent_list_:
00055 variant = QtCore.QVariant(ent)
00056 self.list.insertRow(row)
00057 new_item = QtGui.QTableWidgetItem("%i"%(row+1))
00058 new_item.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
00059 new_item.setData(QtCore.Qt.UserRole,variant)
00060 self.list.setItem(row, 0, new_item)
00061 new_item = QtGui.QTableWidgetItem(ent.GetName())
00062 new_item.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
00063 self.list.setItem(row, 1, new_item)
00064 row += 1
00065
00066 self.list.resizeColumnsToContents()
00067
00068 def Select(self):
00069 items = self.list.selectedItems()
00070 for item in items:
00071 if(item.column()==0):
00072 ent = item.data(QtCore.Qt.UserRole).toPyObject()
00073 self.ent_list_.remove(ent)
00074 self.ent_list_.insert(0,ent)
00075 self.accept()
00076
00077 def GetShowScores(self):
00078 return self.show_scores.isChecked()
00079
00080 def GetDisplayAlignment(self):
00081 return self.show_alignment.isChecked()
00082
00083 def GetEntities(self):
00084 return self.ent_list_
00085
00086 class ShowResultDialog(QtGui.QDialog):
00087 def __init__(self, ent_list, res_list, parent=None):
00088 QtGui.QDialog.__init__(self, parent)
00089 self.ent_list_ = ent_list
00090 vb = QtGui.QVBoxLayout()
00091 self.setLayout(vb)
00092 self.setWindowTitle("Alignment result")
00093 self.label = QtGui.QLabel("Alignment results with %s as reference"%ent_list[0].GetName())
00094 self.list = QtGui.QTableWidget(self)
00095 self.list.horizontalHeader().setStretchLastSection(True)
00096 self.list.setColumnCount(4)
00097 self.list.verticalHeader().setVisible(False)
00098 self.list.setHorizontalHeaderLabels (["Name","RMSD","TMScore",""])
00099 self.list.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
00100 vb.addWidget(self.label)
00101 vb.addWidget(self.list)
00102 hb = QtGui.QHBoxLayout()
00103 hb.setDirection(QtGui.QBoxLayout.LeftToRight)
00104 ok_btn = QtGui.QPushButton("OK", self)
00105 hb.addStretch(1)
00106 hb.addWidget(ok_btn)
00107 vb.addItem(hb)
00108 ok_btn.setDefault(True)
00109 QtCore.QObject.connect(ok_btn, QtCore.SIGNAL("clicked()"), self.accept)
00110
00111 for i in range(0, len(res_list)):
00112 self.list.insertRow(i)
00113 new_item = QtGui.QTableWidgetItem(ent_list[i+1].GetName())
00114 new_item.setFlags(QtCore.Qt.ItemIsEnabled)
00115 self.list.setItem(i, 0, new_item)
00116 new_item = QtGui.QTableWidgetItem("%.2f"%res_list[i].rmsd)
00117 new_item.setFlags(QtCore.Qt.ItemIsEnabled)
00118 self.list.setItem(i, 1, new_item)
00119 new_item = QtGui.QTableWidgetItem("%i"%res_list[i].tm_score)
00120 new_item.setFlags(QtCore.Qt.ItemIsEnabled)
00121 self.list.setItem(i, 2, new_item)
00122 new_item = QtGui.QTableWidgetItem()
00123 new_item.setFlags(QtCore.Qt.ItemIsEnabled)
00124 self.list.setItem(i, 3, new_item)
00125
00126 self.list.resizeColumnsToContents()
00127
00128 class CalculateSurfaceSettingsDialog(QtGui.QDialog):
00129 def __init__(self, executable, parent=None):
00130 QtGui.QDialog.__init__(self, parent)
00131 vb = QtGui.QGridLayout()
00132 self.setLayout(vb)
00133 self.setWindowTitle("MSMS Surface Settings")
00134 msmsexe_label=QtGui.QLabel("executable")
00135 self.msmsexe_field=QtGui.QLineEdit()
00136 self.msmsexe_field.setText(executable)
00137 msmsexe_browsebutton=QtGui.QPushButton("Browse")
00138 vb.addWidget(msmsexe_label, 0, 0)
00139 vb.addWidget(self.msmsexe_field, 0, 1)
00140 vb.addWidget(msmsexe_browsebutton, 0, 2)
00141 surfname_label=QtGui.QLabel("surface name")
00142 self.surfname_field=QtGui.QLineEdit()
00143 self.surfname_field.setText("surface")
00144 vb.addWidget(surfname_label, 1, 0)
00145 vb.addWidget(self.surfname_field, 1, 1, 1, 2)
00146 density_label=QtGui.QLabel("density")
00147 self.density_spinbox=QtGui.QSpinBox()
00148 self.density_spinbox.setRange(1, 10)
00149 self.density_spinbox.setValue(4)
00150 vb.addWidget(density_label, 2, 0)
00151 vb.addWidget(self.density_spinbox, 2, 1, 1, 2)
00152 probe_label=QtGui.QLabel("probe radius")
00153 self.probe_spinbox=QtGui.QDoubleSpinBox()
00154 self.probe_spinbox.setDecimals(1)
00155 self.probe_spinbox.setSingleStep(0.1)
00156 self.probe_spinbox.setRange(0.3, 5.0)
00157 self.probe_spinbox.setValue(1.4)
00158 vb.addWidget(probe_label, 3, 0)
00159 vb.addWidget(self.probe_spinbox, 3, 1, 1, 2)
00160 selection_label=QtGui.QLabel("selection")
00161 self.selection_field=QtGui.QLineEdit()
00162 self.selection_field.setText("")
00163 vb.addWidget(selection_label, 4, 0)
00164 vb.addWidget(self.selection_field, 4, 1, 1, 2)
00165 self.noh_box=QtGui.QCheckBox("no hydrogens")
00166 vb.addWidget(self.noh_box, 5, 0)
00167 self.nohet_box=QtGui.QCheckBox("no hetatoms")
00168 vb.addWidget(self.nohet_box, 5, 1)
00169 self.nowat_box=QtGui.QCheckBox("no waters")
00170 vb.addWidget(self.nowat_box, 5, 2)
00171
00172 cancel_btn = QtGui.QPushButton("Cancel", self)
00173 ok_btn = QtGui.QPushButton("OK", self)
00174 vb.addWidget(cancel_btn, 6, 1)
00175 vb.addWidget(ok_btn, 6, 2)
00176
00177 QtCore.QObject.connect(msmsexe_browsebutton, QtCore.SIGNAL("clicked()"), self.GetPath)
00178 QtCore.QObject.connect(ok_btn, QtCore.SIGNAL("clicked()"), self.accept)
00179 QtCore.QObject.connect(cancel_btn, QtCore.SIGNAL("clicked()"), self.reject)
00180
00181 def GetPath(self):
00182 path=QtGui.QFileDialog().getOpenFileName(self, "Choose MSMS Executable")
00183 if path!='':
00184 self.msmsexe_field.setText(path)
00185
00186 class SurfaceContextMenu(QtCore.QObject):
00187 def __init__(self, context_menu):
00188 try:
00189 settings_name="msms"
00190 self.executable=settings.Locate(settings_name)
00191 except settings.FileNotFound:
00192 self.executable=""
00193 QtCore.QObject.__init__(self, context_menu.qobject)
00194 self.action = QtGui.QAction("Calculate Surface", self)
00195 QtCore.QObject.connect(self.action, QtCore.SIGNAL("triggered()"),
00196 self.CalculateSurface)
00197 context_menu.AddAction(self.action, gui.ContextActionType.ENTITY)
00198
00199 def CalculateSurface(self):
00200 scene_selection = gui.SceneSelection.Instance()
00201 ent_list = list()
00202 for i in range(0,scene_selection.GetActiveNodeCount()):
00203 ent_list.append(scene_selection.GetActiveNode(i))
00204 cssd = CalculateSurfaceSettingsDialog(self.executable)
00205 if(cssd.exec_()):
00206 self.__CalculateSurface(ent_list,
00207 str(cssd.surfname_field.text()),
00208 str(cssd.msmsexe_field.text()),
00209 cssd.density_spinbox.value(),
00210 cssd.probe_spinbox.value(),
00211 str(cssd.selection_field.text()),
00212 cssd.noh_box.isChecked(),
00213 cssd.nohet_box.isChecked(),
00214 cssd.nowat_box.isChecked())
00215
00216 def __CalculateSurface(self,ent_list,name,msms_exe,density,
00217 radius,selection,noh,nohet,nowat):
00218 for entity in ent_list:
00219 if isinstance(entity, gfx.Entity):
00220 try:
00221 s=msms.CalculateSurface(entity.view,
00222 msms_exe=msms_exe,
00223 density=density,
00224 radius=radius,
00225 selection=selection,
00226 no_hydrogens=noh,
00227 no_hetatoms=nohet,
00228 no_waters=nowat)[0]
00229 gfx.Scene().Add(gfx.Surface("%s_%s"%(entity.GetName(),name),s))
00230 except (RuntimeError, msms.MsmsProcessError):
00231 LogError("WARNING: Surface could not be calculated")
00232 return
00233 except UserWarning:
00234 LogError("WARNING: Entry with the same name already present in scene")
00235 return
00236
00237 class AlignmentContextMenu(QtCore.QObject):
00238
00239 def __init__(self, context_menu):
00240 try:
00241 try:
00242 if platform.system() == "Windows":
00243 settings_name="tmalign.exe"
00244 else:
00245 settings_name="tmalign"
00246 except IOError:
00247
00248
00249 settings_name="tmalign"
00250
00251 settings.Locate(settings_name)
00252 QtCore.QObject.__init__(self, context_menu.qobject)
00253
00254 self.action = QtGui.QAction("Align", self)
00255 QtCore.QObject.connect(self.action,QtCore.SIGNAL("triggered()"), self.Align)
00256 context_menu.AddAction(self.action, gui.ContextActionType.ENTITY | gui.ContextActionType.MULTI)
00257 self.seq_viewer = None
00258 except settings.FileNotFound:
00259 return
00260
00261 def Align(self):
00262 scene_selection = gui.SceneSelection.Instance()
00263 ent_list = list()
00264 for i in range(0,scene_selection.GetActiveNodeCount()):
00265 ent_list.append(scene_selection.GetActiveNode(i))
00266 sd = SelectRefDialog(ent_list)
00267 if(sd.exec_()):
00268 self.__Align(sd.GetEntities(),sd.GetShowScores(), sd.GetDisplayAlignment())
00269
00270 def __Align(self, ent_list,show_scores=True, display_alignment=False):
00271 node = ent_list[0]
00272 res_list = list()
00273 if isinstance(node, gfx.Entity):
00274 ref = node.view.handle
00275 for i in range(1,len(ent_list)):
00276 node = ent_list[i]
00277 if isinstance(node, gfx.Entity):
00278 res_list.append(tmtools.TMAlign(node.view.handle, ref))
00279 node.UpdatePositions()
00280 if show_scores:
00281 self.__ShowScore(ent_list, res_list)
00282 if display_alignment:
00283 self.__DisplayAlignment(ent_list, res_list)
00284
00285 def __ShowScore(self, ent_list, res_list):
00286 if(len(res_list)==1):
00287 res = res_list[0]
00288 string = "RMSD: %.2f, TMScore: %i"%(res.rmsd, res.tm_score)
00289 gui.GostyApp.Instance().perspective.StatusMessage(string)
00290 elif(len(res_list)>1):
00291 ShowResultDialog(ent_list, res_list).exec_()
00292
00293 def __DisplayAlignment(self, ent_list, res_list):
00294 if(len(res_list)>0):
00295 ref_seq = seq.CreateSequence("%s (ref)"%ent_list[0].GetName(),res_list[0].ref_sequence.GetGaplessString())
00296 aln_list = seq.AlignmentList()
00297 if(ref_seq.IsValid()):
00298 for i in range(0, len(res_list)):
00299 res_list[i].alignment.SetSequenceName(1,ent_list[i+1].GetName())
00300 aln_list.append(res_list[i].alignment)
00301 alignment = alg.MergePairwiseAlignments(aln_list, ref_seq)
00302 gosty = gui.GostyApp.Instance()
00303 main_area = gosty.perspective.GetMainArea()
00304 if self.seq_viewer:
00305 self.seq_viewer.qobject.close()
00306 self.seq_viewer = gui.SequenceViewer(True)
00307 self.seq_viewer.AddAlignment(alignment)
00308 self.seq_viewer.ChangeDisplayMode("Highlight conservation 1")
00309 self.seq_viewer.Show()
00310
00311 class SelectMenuPoints(QtCore.QObject):
00312 def __init__(self, context_menu):
00313 QtCore.QObject.__init__(self, context_menu.qobject)
00314 action=QtGui.QAction("Select...", self)
00315 QtCore.QObject.connect(action, QtCore.SIGNAL('triggered()'),
00316 self._Select)
00317 context_menu.AddAction(action, gui.ENTITY)
00318 action=QtGui.QAction("Copy Selection...", self)
00319 QtCore.QObject.connect(action, QtCore.SIGNAL('triggered()'),
00320 self._CopyViews)
00321 context_menu.AddAction(action, gui.ENTITY)
00322 action=QtGui.QAction('Select...', self)
00323 QtCore.QObject.connect(action, QtCore.SIGNAL('triggered()'),
00324 self._SelectViewsSameEntity)
00325 context_menu.AddAction(action, gui.ENTITY_VIEW|gui.VIEWS_SAME_OBJECT)
00326 def _Select(self):
00327 scene_selection=gui.SceneSelection.Instance()
00328 ent=scene_selection.GetActiveNode(0)
00329 dialog=QueryDialog('Select...')
00330 if dialog.exec_():
00331 q=mol.Query(dialog.query)
00332 if q.IsValid():
00333 ent.selection=ent.view.Select(dialog.query, dialog.query_flags)
00334 else:
00335 ost.LogError("invalid query: %s" % q.error)
00336
00337 def _UniqueName(self, ent):
00338 """
00339 Returns a name based on ent that is unique within the scene
00340 """
00341 ent_name=ent.GetName()
00342 num=2
00343 while True:
00344 candidate_name='%s-%d' % (ent_name, num)
00345 if not gfx.Scene().HasNode(candidate_name):
00346 return candidate_name
00347 num+=1
00348
00349 def _SelectViewsSameEntity(self):
00350
00351 union=gui.SceneSelection.Instance().GetViewUnion()
00352 dialog=QueryDialog('Select...')
00353 if dialog.exec_():
00354 q=mol.Query(dialog.query)
00355 if q.IsValid():
00356 ve=gui.SceneSelection.Instance().GetViewEntity()
00357 ve.selection=union.Select(q, dialog.query_flags)
00358 else:
00359 ost.LogError("invalid query: %s" % q.error)
00360
00361 def _CopyViews(self):
00362 views_to_add=[]
00363 scene_selection=gui.SceneSelection.Instance()
00364 ent=scene_selection.GetActiveNode(0)
00365 dialog=QueryDialog('Select...')
00366 if dialog.exec_():
00367 q=mol.Query(dialog.query)
00368 if q.IsValid():
00369 for i in range(scene_selection.GetActiveNodeCount()):
00370 ent=scene_selection.GetActiveNode(i)
00371 selected=ent.view.Select(q, dialog.query_flags)
00372 gfx_ent=gfx.Entity(self._UniqueName(ent),selected)
00373 gfx.Scene().Add(gfx_ent)
00374 else:
00375 ost.LogError("invalid query: %s" % q.error)
00376
00377 def _InitContextMenu(app):
00378 _InitContextMenu.cm=app.scene_win.GetContextMenu()
00379 _InitContextMenu.am=AlignmentContextMenu(_InitContextMenu.cm)
00380 _InitContextMenu.sc=SurfaceContextMenu(_InitContextMenu.cm)
00381 _InitContextMenu.sm=SelectMenuPoints(_InitContextMenu.cm)