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