OpenStructure
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
superpositiondialog.py
Go to the documentation of this file.
1 #------------------------------------------------------------------------------
2 # This file is part of the OpenStructure project <www.openstructure.org>
3 #
4 # Copyright (C) 2008-2011 by the OpenStructure authors
5 #
6 # This library is free software; you can redistribute it and/or modify it under
7 # the terms of the GNU Lesser General Public License as published by the Free
8 # Software Foundation; either version 3.0 of the License, or (at your option)
9 # any later version.
10 # This library is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this library; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #------------------------------------------------------------------------------
19 #
20 # Authors: Stefan Bienert
21 #
22 from PyQt5 import QtCore, QtGui, QtWidgets
23 from ost.mol.alg import Superpose
24 from ost import mol
25 
26 class ChainComboBox(QtWidgets.QComboBox):
27  def __init__(self, ent, gfx, parent=None):
28  # class variables
29  self.all_chains = 'All'
30  QtWidgets.QComboBox.__init__(self, parent)
31  self.entity = ent
32  self.addItem(self.all_chains)
33  for chain in self.entity.chains:
34  self.addItem(chain.name)
35  if self.count()>0:
36  self.setCurrentIndex(0)
37  if gfx:
38  self.gfx = gfx
39  self.highlighted.connect(self._HighlightChain)
40  else:
41  self.gfx = None
42 
43  def focusOutEvent (self, event):
44  if self.gfx:
45  self.gfx.selection = None
46 
47  def SetItems(self, ent, gfx):
48  self.clear()
49  self.entity = ent
50  self.addItem(self.all_chains)
51  for chain in self.entity.chains:
52  self.addItem(chain.name)
53  if self.count()>0:
54  self.setCurrentIndex(0)
55  if gfx:
56  self.gfx = gfx
57 
58  def _HighlightChain(self, chain_idx):
59  chain = self.itemText(chain_idx)
60  if chain != 'All':
61  self.gfx.SetSelection(self.entity.Select('cname="%s"' % str(chain)))
62  else:
63  self.gfx.SetSelection(self.entity.Select(''))
64 
65  def _GetSelectedChain(self):
66  if self.currentIndex() == -1:
67  return mol.EntityHandle()
68  elif self.currentText() == self.all_chains:
69  return self.entity
70  return self.entity.Select('cname="%s"' % str(self.currentText()))
71 
72  def _SetSelectedChain(self, chain):
73  if hasattr(chain, 'name'):
74  name = chain.name
75  else:
76  name = str(chain)
77  for i in range(self.count()):
78  if self.itemText(i) == name:
79  self.setCurrentIndex(i)
80  break
81  selected_chain = property(_GetSelectedChain, _SetSelectedChain)
82 
83 class SuperpositionDialog(QtWidgets.QDialog):
84  """
85  Provides a graphical user interface to structurally superpose two entities.
86  Uses function :func:`~ost.mol.alg.Superpose`. The RMSD of two superposed
87  molecules will be stored in attribute ``rmsd``. An index for the selected
88  reference molecule will be stored in attribute ``reference``.
89 
90  :param ent_one: The first entity
91  :type ent_one: :class:`~ost.mol.EntityView`, :class:`~ost.mol.EntityHandle`
92  or :class:`~ost.gfx.Entity`
93  :param ent_two: The second entity
94  :type ent_two: :class:`~ost.mol.EntityView`, :class:`~ost.mol.EntityHandle`
95  or :class:`~ost.gfx.Entity`
96 
97  **Example Usage:**
98 
99  .. code-block:: python
100 
101  e1=io.LoadPDB('examples/code_fragments/entity/pdb1ake.ent')
102  e2=io.LoadPDB('examples/code_fragments/entity/pdb4ake.ent')
103 
104  sd = ost.gui.dng.superpositiondialog.SuperpositionDialog(e1, e2)
105 
106  g1=gfx.Entity('G1', e1)
107  g2=gfx.Entity('G2', e2)
108  scene.Add(g1)
109  scene.Add(g2)
110 
111  if sd.reference == 0:
112  scene.CenterOn(g1)
113  else:
114  scene.CenterOn(g2)
115 
116  if sd.rmsd != None:
117  LogScript('RMSD: %.3f'%sd.rmsd)
118  """
119 
120  def __init__(self, ent_one, ent_two, parent=None):
121  # class variables
123  self.rmsd = None
125  self._mmethod_dict = {'number': 'number',
126  'index': 'index',
127  'local alignment': 'local-aln',
128  'global alignment': 'global-aln'}
129  self.gfx_one = None
130  self.gfx_two = None
131  self.gfx_select_one = None
132  self.gfx_select_two = None
133  QtWidgets.QDialog.__init__(self, parent)
134  self.setWindowTitle('Superpose Structures')
135  if not isinstance(ent_one, mol.EntityHandle) and \
136  not isinstance(ent_one, mol.EntityView):
137  n_one = ent_one.GetName()
138  self.gfx_one = ent_one
139  self.gfx_select_one = self.gfx_one.GetSelection()
140  self.ent_one = ent_one.GetView()
141  else:
142  if isinstance(ent_one, mol.EntityHandle):
143  n_one = ent_one.GetName()
144  elif isinstance(ent_one, mol.EntityView):
145  n_one = ent_one.GetHandle().GetName()
146  self.ent_one = ent_one
147  if len(n_one) == 0:
148  n_one = '1'
149  if not isinstance(ent_two, mol.EntityHandle) and \
150  not isinstance(ent_two, mol.EntityView):
151  n_two = ent_two.GetName()
152  self.gfx_two = ent_two
153  self.gfx_select_two = self.gfx_two.GetSelection()
154  self.ent_two = ent_two.GetView()
155  else:
156  if isinstance(ent_two, mol.EntityHandle):
157  n_two = ent_two.GetName()
158  elif isinstance(ent_two, mol.EntityView):
159  n_two = ent_two.GetHandle().GetName()
160  self.ent_two = ent_two
161  if len(n_two) == 0:
162  n_two = '2'
163  if n_one == n_two:
164  n_one = n_one + ' 1'
165  n_two = n_two + ' 2'
166  layout = QtWidgets.QGridLayout(self)
167  # select reference molecule
168  self.reference = 0;
169  self._reference = self._ReferenceSelection(n_one, n_two)
170  grow = 0
171  layout.addWidget(QtWidgets.QLabel("reference"), grow, 0)
172  layout.addWidget(self._reference, grow, 1)
173  grow += 1
174  # chains
175  self._chain_one = ChainComboBox(self.ent_one, self.gfx_one, self)
176  self._chain_two = ChainComboBox(self.ent_two, self.gfx_two, self)
177  layout.addWidget(QtWidgets.QLabel("reference chain"), grow, 0)
178  layout.addWidget(self._chain_one, grow, 1)
179  grow += 1
180  layout.addWidget(QtWidgets.QLabel("chain"), grow, 0)
181  layout.addWidget(self._chain_two, grow, 1)
182  grow += 1
183  # link chain and reference selection
184  self._reference.currentIndexChanged.connect(self._ChangeChainSelection)
185  # match methods
186  self._methods = self._MatchMethods()
187  layout.addWidget(QtWidgets.QLabel('match residues by'), grow, 0)
188  grow += 1
189  layout.addWidget(self._methods)
190 
191  # iterative
192  self._iterative=None
193  self._it_box, self._it_in, self._dist_in = self._ItBox()
194  layout.addWidget(self._it_box, grow, 0)
195  # atoms
196  self._atoms = self._FetchAtoms(self._methods.size(),
197  self.ent_one,
198  self.ent_two)
199  self._atmselectbx, self._atmselectgrp = self._AtomSelectionBox()
200  layout.addWidget(self._atmselectbx, grow, 1)
201  grow += 1
202  # buttons
203  ok_button = QtWidgets.QPushButton("Superpose")
204  ok_button.clicked.connect(self.accept)
205  cancel_button = QtWidgets.QPushButton("Cancel")
206  hbox_layout = QtWidgets.QHBoxLayout()
207  hbox_layout.addStretch(1)
208  layout.addLayout(hbox_layout, grow, 0, 1, 2)
209  grow += 1
210  cancel_button.clicked.connect(self.reject)
211  self.accepted.connect(self._Superpose)
212  hbox_layout.addWidget(cancel_button, 0)
213  hbox_layout.addWidget(ok_button, 0)
214  ok_button.setDefault(True)
215  self.exec_()
216  # restore old selections
217  if self.gfx_one:
218  self.gfx_one.SetSelection(self.gfx_select_one)
219  if self.gfx_two:
220  self.gfx_two.SetSelection(self.gfx_select_two)
221 
222  def _Superpose(self):
223  view_one = self._chain_one.selected_chain
224  view_two = self._chain_two.selected_chain
225  atoms = self._GetAtomSelection()
226  sp = Superpose(view_two, view_one,
227  self._mmethod_dict[str(self._methods.currentText())],
228  atoms, iterative=self._iterative,
229  max_iterations=self._it_in.value(),
230  distance_threshold=self._dist_in.value())
231  self.rmsd = sp.rmsd
232  if self._iterative:
233  self.rmsd_superposed_atoms = sp.rmsd_superposed_atoms
234  self.fraction_superposed = sp.fraction_superposed
235 
236  def _toggle_atoms(self, checked):
237  if checked:
238  self._atoms.setEnabled(True)
239  else:
240  self._atoms.setEnabled(False)
241 
242  def _AtomSelectionBox(self):
243  bt1 = QtWidgets.QRadioButton('All')
244  bt2 = QtWidgets.QRadioButton('Backbone')
245  bt3 = QtWidgets.QRadioButton('CA')
246  self.cstmbtntxt = 'Custom'
247  custom_rbutton = QtWidgets.QRadioButton(self.cstmbtntxt)
248  group = QtWidgets.QButtonGroup()
249  group.addButton(bt1)
250  group.addButton(bt2)
251  group.addButton(bt3)
252  group.addButton(custom_rbutton)
253  bt1.setChecked(True)
254  vbox_layout = QtWidgets.QVBoxLayout()
255  vbox_layout.addWidget(bt1)
256  vbox_layout.addWidget(bt2)
257  vbox_layout.addWidget(bt3)
258  vbox_layout.addWidget(custom_rbutton)
259  vbox_layout.addWidget(self._atoms)
260  custom_rbutton.toggled.connect(self._toggle_atoms)
261  box = QtWidgets.QGroupBox("atom selection")
262  box.setLayout(vbox_layout)
263  return box, group
264 
265  def _GetAtomSelection(self):
266  checkedbtn = self._atmselectgrp.checkedButton()
267  if str(checkedbtn.text()) != self.cstmbtntxt:
268  return str(checkedbtn.text())
269  slctn_model = self._atoms.selectionModel()
270  dt_model = slctn_model.model()
271  atms = list()
272  for idx in slctn_model.selectedRows():
273  slctn = dt_model.data(idx, Qt.DisplayRole).toString()
274  atms.append(str(slctn))
275  return atms
276 
277  def _FetchAtoms(self, dim, ent_a, ent_b):
278  # fetch list of atoms: only those which are in both entities are considered
279  atm_dict = {}
280  for atm in ent_a.GetAtomList():
281  atm_dict[atm.name] = 0
282  for atm in ent_b.GetAtomList():
283  if atm.name in atm_dict:
284  atm_dict[atm.name] = 1
285  atmlst = list()
286  for atm in sorted(atm_dict.keys()):
287  if atm_dict[atm]:
288  atmlst.append(atm)
289  elems = QtCore.QStringListModel(atmlst)
290  atoms = QtWidgets.QListView(self)
291  dim.setHeight(3*dim.height())
292  atoms.setFixedSize(dim)
293  atoms.setModel(elems)
294  atoms.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
295  atoms.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
296  atoms.setEnabled(False)
297  return atoms
298 
299  def _ReferenceSelection(self, name_a, name_b):
300  cbox = QtWidgets.QComboBox()
301  cbox.addItem(name_a)
302  cbox.addItem(name_b)
303  if cbox.count() > 0:
304  cbox.setCurrentIndex(0)
305  return cbox
306 
307  def _toggle_iterative(self, checked):
308  if checked:
309  self._it_in.setEnabled(True)
310  self._dist_in.setEnabled(True)
311  self._iterative=True
312  else:
313  self._it_in.setEnabled(False)
314  self._dist_in.setEnabled(False)
315  self._iterative=False
316 
317  def _ItBox(self):
318  bt1 = QtWidgets.QRadioButton("On")
319  iteration_label=QtWidgets.QLabel("Max Iterations: ")
320  distance_label=QtWidgets.QLabel("Dist Thresh: ")
321  iteration_in=QtWidgets.QSpinBox()
322  iteration_in.setRange(1,30)
323  iteration_in.setValue(8)
324  distance_in=QtWidgets.QDoubleSpinBox()
325  distance_in.setRange(1.0,10.0)
326  distance_in.setValue(3.0)
327  distance_in.setDecimals(1)
328  distance_in.setSingleStep(0.5)
329  iteration_in.setEnabled(False)
330  distance_in.setEnabled(False)
331  bt1.setChecked(False)
332  self._iterative=False
333  vbox_layout = QtWidgets.QVBoxLayout()
334  vbox_layout.addWidget(bt1)
335  vbox_layout.addWidget(iteration_label)
336  vbox_layout.addWidget(iteration_in)
337  vbox_layout.addWidget(distance_label)
338  vbox_layout.addWidget(distance_in)
339  vbox_layout.addSpacing(50)
340  bt1.toggled.connect(self._toggle_iterative)
341  box = QtWidgets.QGroupBox("Iterative")
342  box.setLayout(vbox_layout)
343  return box,iteration_in, distance_in
344 
345  def _ChangeChainSelection(self, index):
346  if index == 0:
347  self._chain_one.SetItems(self.ent_one, self.gfx_one)
348  self._chain_two.SetItems(self.ent_two, self.gfx_two)
349  self.reference = 0;
350  elif index == 1:
351  self._chain_one.SetItems(self.ent_two, self.gfx_two)
352  self._chain_two.SetItems(self.ent_one, self.gfx_one)
353  self.reference = 1;
354 
355  def _MatchMethods(self):
356  methods=QtWidgets.QComboBox(self)
357  for method in sorted(self._mmethod_dict):
358  methods.addItem(method)
359  return methods
Protein or molecule.
definition of EntityView
Definition: entity_view.hh:86