00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 from PyQt4.QtCore import *
00023 from PyQt4.QtGui import *
00024 from ost.mol.alg import Superpose
00025 from ost import mol
00026
00027 class ChainComboBox(QComboBox):
00028 def __init__(self, ent, gfx, parent=None):
00029
00030 self.all_chains = 'All'
00031 QComboBox.__init__(self, parent)
00032 self.entity = ent
00033 self.addItem(self.all_chains)
00034 for chain in self.entity.chains:
00035 self.addItem(chain.name)
00036 if self.count()>0:
00037 self.setCurrentIndex(0)
00038 if gfx:
00039 self.gfx = gfx
00040 QObject.connect(self,
00041 SIGNAL('highlighted (const QString&)'),
00042 self._HighlightChain)
00043 else:
00044 self.gfx = None
00045
00046 def focusOutEvent (self, event):
00047 if self.gfx:
00048 self.gfx.selection = None
00049
00050 def SetItems(self, ent, gfx):
00051 self.clear()
00052 self.entity = ent
00053 self.addItem(self.all_chains)
00054 for chain in self.entity.chains:
00055 self.addItem(chain.name)
00056 if self.count()>0:
00057 self.setCurrentIndex(0)
00058 if gfx:
00059 self.gfx = gfx
00060
00061 def _HighlightChain(self, chain):
00062 if str(chain) != 'All':
00063 self.gfx.SetSelection(self.entity.Select('cname="%s"' % str(chain)))
00064 else:
00065 self.gfx.SetSelection(self.entity.Select(''))
00066
00067 def _GetSelectedChain(self):
00068 if self.currentIndex() == -1:
00069 return mol.EntityHandle()
00070 elif self.currentText() == self.all_chains:
00071 return self.entity
00072 return self.entity.Select('cname="%s"' % str(self.currentText()))
00073
00074 def _SetSelectedChain(self, chain):
00075 if hasattr(chain, 'name'):
00076 name = chain.name
00077 else:
00078 name = str(chain)
00079 for i in range(self.count()):
00080 if self.itemText(i) == name:
00081 self.setCurrentIndex(i)
00082 break
00083 selected_chain = property(_GetSelectedChain, _SetSelectedChain)
00084
00085 class SuperpositionDialog(QDialog):
00086 """
00087 Provides a graphical user interface to structurally superpose two entities.
00088 Uses function :func:`~ost.mol.alg.Superpose`. The RMSD of two superposed
00089 molecules will be stored in attribute ``rmsd``. An index for the selected
00090 reference molecule will be stored in attribute ``reference``.
00091
00092 :param ent_one: The first entity
00093 :type ent_one: :class:`~ost.mol.EntityView`, :class:`~ost.mol.EntityHandle`
00094 or :class:`~ost.gfx.Entity`
00095 :param ent_two: The second entity
00096 :type ent_two: :class:`~ost.mol.EntityView`, :class:`~ost.mol.EntityHandle`
00097 or :class:`~ost.gfx.Entity`
00098
00099 **Example Usage:**
00100
00101 .. code-block:: python
00102
00103 e1=io.LoadPDB('examples/code_fragments/entity/pdb1ake.ent')
00104 e2=io.LoadPDB('examples/code_fragments/entity/pdb4ake.ent')
00105
00106 sd = ost.gui.dng.superpositiondialog.SuperpositionDialog(e1, e2)
00107
00108 g1=gfx.Entity('G1', e1)
00109 g2=gfx.Entity('G2', e2)
00110 scene.Add(g1)
00111 scene.Add(g2)
00112
00113 if sd.reference == 0:
00114 scene.CenterOn(g1)
00115 else:
00116 scene.CenterOn(g2)
00117
00118 if sd.rmsd != None:
00119 LogScript('RMSD: %.3f'%sd.rmsd)
00120 """
00121
00122 def __init__(self, ent_one, ent_two, parent=None):
00123
00124 self.rmsd_superposed_atoms = None
00125 self.rmsd = None
00126 self.fraction_superposed = None
00127 self._mmethod_dict = {'number': 'number',
00128 'index': 'index',
00129 'local alignment': 'local-aln',
00130 'global alignment': 'global-aln'}
00131 self.gfx_one = None
00132 self.gfx_two = None
00133 self.gfx_select_one = None
00134 self.gfx_select_two = None
00135 QDialog.__init__(self, parent)
00136 self.setWindowTitle('Superpose structures')
00137 if not isinstance(ent_one, mol.EntityHandle) and \
00138 not isinstance(ent_one, mol.EntityView):
00139 n_one = ent_one.GetName()
00140 self.gfx_one = ent_one
00141 self.gfx_select_one = self.gfx_one.GetSelection()
00142 self.ent_one = ent_one.GetView()
00143 else:
00144 if isinstance(ent_one, mol.EntityHandle):
00145 n_one = ent_one.GetName()
00146 elif isinstance(ent_one, mol.EntityView):
00147 n_one = ent_one.GetHandle().GetName()
00148 self.ent_one = ent_one
00149 if len(n_one) == 0:
00150 n_one = '1'
00151 if not isinstance(ent_two, mol.EntityHandle) and \
00152 not isinstance(ent_two, mol.EntityView):
00153 n_two = ent_two.GetName()
00154 self.gfx_two = ent_two
00155 self.gfx_select_two = self.gfx_two.GetSelection()
00156 self.ent_two = ent_two.GetView()
00157 else:
00158 if isinstance(ent_two, mol.EntityHandle):
00159 n_two = ent_two.GetName()
00160 elif isinstance(ent_two, mol.EntityView):
00161 n_two = ent_two.GetHandle().GetName()
00162 self.ent_two = ent_two
00163 if len(n_two) == 0:
00164 n_two = '2'
00165 if n_one == n_two:
00166 n_one = n_one + ' 1'
00167 n_two = n_two + ' 2'
00168 layout = QGridLayout(self)
00169
00170 self.reference = 0;
00171 self._reference = self._ReferenceSelection(n_one, n_two)
00172 grow = 0
00173 layout.addWidget(QLabel("reference"), grow, 0)
00174 layout.addWidget(self._reference, grow, 1)
00175 grow += 1
00176
00177 self._chain_one = ChainComboBox(self.ent_one, self.gfx_one, self)
00178 self._chain_two = ChainComboBox(self.ent_two, self.gfx_two, self)
00179 layout.addWidget(QLabel("reference chain"), grow, 0)
00180 layout.addWidget(self._chain_one, grow, 1)
00181 grow += 1
00182 layout.addWidget(QLabel("chain"), grow, 0)
00183 layout.addWidget(self._chain_two, grow, 1)
00184 grow += 1
00185
00186 QObject.connect(self._reference,
00187 SIGNAL('currentIndexChanged(int)'),
00188 self._ChangeChainSelection)
00189
00190 self._methods = self._MatchMethods()
00191 layout.addWidget(QLabel('match residues by'), grow, 0)
00192 grow += 1
00193 layout.addWidget(self._methods)
00194
00195
00196 self._iterative=None
00197 self._it_box, self._it_in, self._dist_in = self._ItBox()
00198 layout.addWidget(self._it_box, grow, 0)
00199
00200 self._atoms = self._FetchAtoms(self._methods.size(),
00201 self.ent_one,
00202 self.ent_two)
00203 self._atmselectbx, self._atmselectgrp = self._AtomSelectionBox()
00204 layout.addWidget(self._atmselectbx, grow, 1)
00205 grow += 1
00206
00207 ok_button = QPushButton("Superpose")
00208 QObject.connect(ok_button, SIGNAL('clicked()'), self.accept)
00209 cancel_button = QPushButton("Cancel")
00210 hbox_layout = QHBoxLayout()
00211 hbox_layout.addStretch(1)
00212 layout.addLayout(hbox_layout, grow, 0, 1, 2)
00213 grow += 1
00214 QObject.connect(cancel_button, SIGNAL('clicked()'), self.reject)
00215 QObject.connect(self, SIGNAL('accepted()'), self._Superpose)
00216 hbox_layout.addWidget(cancel_button, 0)
00217 hbox_layout.addWidget(ok_button, 0)
00218 ok_button.setDefault(True)
00219 self.exec_()
00220
00221 if self.gfx_one:
00222 self.gfx_one.SetSelection(self.gfx_select_one)
00223 if self.gfx_two:
00224 self.gfx_two.SetSelection(self.gfx_select_two)
00225
00226 def _Superpose(self):
00227 view_one = self._chain_one.selected_chain
00228 view_two = self._chain_two.selected_chain
00229 atoms = self._GetAtomSelection()
00230 sp = Superpose(view_two, view_one,
00231 self._mmethod_dict[str(self._methods.currentText())],
00232 atoms, iterative=self._iterative,
00233 max_iterations=self._it_in.value(), distance_threshold=self._dist_in.value())
00234 self.rmsd = sp.rmsd
00235 if self._iterative:
00236 self.rmsd_superposed_atoms = sp.rmsd_superposed_atoms
00237 self.fraction_superposed = sp.fraction_superposed
00238
00239 def _toggle_atoms(self, checked):
00240 if checked:
00241 self._atoms.setEnabled(True)
00242 else:
00243 self._atoms.setEnabled(False)
00244
00245 def _AtomSelectionBox(self):
00246 bt1 = QRadioButton('All')
00247 bt2 = QRadioButton('Backbone')
00248 bt3 = QRadioButton('CA')
00249 self.cstmbtntxt = 'Custom'
00250 custom_rbutton = QRadioButton(self.cstmbtntxt)
00251 group = QButtonGroup()
00252 group.addButton(bt1)
00253 group.addButton(bt2)
00254 group.addButton(bt3)
00255 group.addButton(custom_rbutton)
00256 bt1.setChecked(True)
00257 vbox_layout = QVBoxLayout()
00258 vbox_layout.addWidget(bt1)
00259 vbox_layout.addWidget(bt2)
00260 vbox_layout.addWidget(bt3)
00261 vbox_layout.addWidget(custom_rbutton)
00262 vbox_layout.addWidget(self._atoms)
00263 QObject.connect(custom_rbutton, SIGNAL('toggled(bool)'), self._toggle_atoms)
00264 box = QGroupBox("atom selection")
00265 box.setLayout(vbox_layout)
00266 return box, group
00267
00268 def _GetAtomSelection(self):
00269 checkedbtn = self._atmselectgrp.checkedButton()
00270 if str(checkedbtn.text()) != self.cstmbtntxt:
00271 return str(checkedbtn.text())
00272 slctn_model = self._atoms.selectionModel()
00273 dt_model = slctn_model.model()
00274 atms = list()
00275 for idx in slctn_model.selectedRows():
00276 slctn = dt_model.data(idx, Qt.DisplayRole).toString()
00277 atms.append(str(slctn))
00278 return atms
00279
00280 def _FetchAtoms(self, dim, ent_a, ent_b):
00281
00282 atm_dict = {}
00283 for atm in ent_a.GetAtomList():
00284 atm_dict[atm.name] = 0
00285 for atm in ent_b.GetAtomList():
00286 if atm.name in atm_dict:
00287 atm_dict[atm.name] = 1
00288 atmlst = QStringList()
00289 for atm in sorted(atm_dict.keys()):
00290 if atm_dict[atm]:
00291 atmlst.append(atm)
00292 elems = QStringListModel(atmlst)
00293 atoms = QListView(self)
00294 dim.setHeight(3*dim.height())
00295 atoms.setFixedSize(dim)
00296 atoms.setModel(elems)
00297 atoms.setSelectionMode(QAbstractItemView.MultiSelection)
00298 atoms.setEditTriggers(QAbstractItemView.NoEditTriggers)
00299 atoms.setEnabled(False)
00300 return atoms
00301
00302 def _ReferenceSelection(self, name_a, name_b):
00303 cbox = QComboBox()
00304 cbox.addItem(name_a)
00305 cbox.addItem(name_b)
00306 if cbox.count() > 0:
00307 cbox.setCurrentIndex(0)
00308 return cbox
00309
00310 def _toggle_iterative(self, checked):
00311 if checked:
00312 self._it_in.setEnabled(True)
00313 self._dist_in.setEnabled(True)
00314 self._iterative=True
00315 else:
00316 self._it_in.setEnabled(False)
00317 self._dist_in.setEnabled(False)
00318 self._iterative=False
00319
00320 def _ItBox(self):
00321 bt1 = QRadioButton("On")
00322 iteration_label=QLabel("Max Iterations: ")
00323 distance_label=QLabel("Dist Thresh: ")
00324 iteration_in=QSpinBox()
00325 iteration_in.setRange(1,30)
00326 iteration_in.setValue(8)
00327 distance_in=QDoubleSpinBox()
00328 distance_in.setRange(1.0,10.0)
00329 distance_in.setValue(3.0)
00330 distance_in.setDecimals(1)
00331 distance_in.setSingleStep(0.5)
00332 iteration_in.setEnabled(False)
00333 distance_in.setEnabled(False)
00334 bt1.setChecked(False)
00335 self._iterative=False
00336 vbox_layout = QVBoxLayout()
00337 vbox_layout.addWidget(bt1)
00338 vbox_layout.addWidget(iteration_label)
00339 vbox_layout.addWidget(iteration_in)
00340 vbox_layout.addWidget(distance_label)
00341 vbox_layout.addWidget(distance_in)
00342 vbox_layout.addSpacing(50)
00343 QObject.connect(bt1, SIGNAL('toggled(bool)'), self._toggle_iterative)
00344 box = QGroupBox("Iterative")
00345 box.setLayout(vbox_layout)
00346 return box,iteration_in, distance_in
00347
00348 def _ChangeChainSelection(self, index):
00349 if index == 0:
00350 self._chain_one.SetItems(self.ent_one, self.gfx_one)
00351 self._chain_two.SetItems(self.ent_two, self.gfx_two)
00352 self.reference = 0;
00353 elif index == 1:
00354 self._chain_one.SetItems(self.ent_two, self.gfx_two)
00355 self._chain_two.SetItems(self.ent_one, self.gfx_one)
00356 self.reference = 1;
00357
00358 def _MatchMethods(self):
00359 methods=QComboBox(self)
00360 for method in sorted(self._mmethod_dict):
00361 methods.addItem(method)
00362 return methods