Source code for schrodinger.application.msv.gui.homology_modeling.ligand_dialog
from schrodinger.application.msv.gui.homology_modeling import hm_models
from schrodinger.application.msv.gui.homology_modeling import ligand_dialog_ui
from schrodinger.Qt import QtCore
from schrodinger.Qt import QtWidgets
from schrodinger.Qt.QtCore import Qt
from schrodinger.ui.qt import basewidgets
from schrodinger.ui.qt.mapperwidgets import plptable
from schrodinger.ui.qt.widgetmixins import panelmixins
INFO_MSG = """
Choose Binding Site
annotation squares to add
the corresponding residues
to this list. These residues
will be kept in proximity to
their ligand.
"""
INFO_TEXT_EDIT_STYLE = 'color:grey;'
[docs]class LigandCofactorDialog(panelmixins.CleanStateMixin, basewidgets.Panel):
SHOW_AS_WINDOW = True
model_class = hm_models.LigandDialogModel
ui_module = ligand_dialog_ui
energyBasedModelingRequested = QtCore.pyqtSignal()
removeConstraintsRequested = QtCore.pyqtSignal()
[docs] def initSetOptions(self):
super().initSetOptions()
self.setWindowTitle("Choose Ligands and Cofactors")
self.std_btn_specs = {
self.StdBtn.Ok: None,
self.StdBtn.Cancel: self.discardChanges,
}
self.help_topic = "MSV_CHOOSE_LIGANDS_AND_COFACTORS"
[docs] def initSetUp(self):
super().initSetUp()
self.ligand_table = self._initLigandTable()
self.ui.clear_ligands_btn.clicked.connect(self._clearAll)
self.ui.select_all_ligands_btn.clicked.connect(self._selectAll)
self.lig_constraint_table = self._initLigConstraintTable()
self.ui.remove_constraints_btn.clicked.connect(
self.removeConstraintsRequested)
self.info_text_edit = QtWidgets.QTextEdit(f'<i>{INFO_MSG}</i>',
readOnly=True)
self.info_text_edit.setStyleSheet(INFO_TEXT_EDIT_STYLE)
self.ui.constrain_residues_info_btn.setToolTip(INFO_MSG)
[docs] def initLayOut(self):
super().initLayOut()
self.ui.ligand_table_layout.addWidget(self.ligand_table)
self.ui.constrain_residues_table_layout.addWidget(
self.lig_constraint_table)
self.ui.constrain_residues_table_layout.addWidget(self.info_text_edit)
[docs] def defineMappings(self):
M = self.model_class
return [
(self.ligand_table, M.ligands),
(self.ligand_table.selection_target, M.selected_ligands),
(self._updateSelectButtons, (M.ligands, M.selected_ligands)),
(self.ui.constrain_residues_cb, M.constrain_ligand),
(self._onConstrainResiduesToggled, M.constrain_ligand),
(self.lig_constraint_table, M.ligand_constraints),
(self._updateRemoveConstraintButton, M.ligand_constraints),
(self._updateInfoMessage, M.ligand_constraints),
(self._updateWatersCb, M.has_waters),
(self.ui.keep_waters_cb, M.include_waters),
(self.ui.pick_constraints_btn, M.pick_ligand),
] # yapf: disable
def _initLigandTable(self):
table = plptable.PLPTableWidget(spec=LigandSpec())
table.view.setShowGrid(False)
table.view.setWordWrap(False)
table.view.verticalHeader().hide()
hheader = table.view.horizontalHeader()
hheader.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
hheader.hide()
return table
def _initLigConstraintTable(self):
table = plptable.PLPTableWidget(spec=LigandConstraintSpec())
table.view.setShowGrid(False)
hheader = table.view.horizontalHeader()
hheader.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
hheader.hide()
return table
def _updateSelectButtons(self):
ligands = self.model.ligands
selected_ligands = self.model.selected_ligands
num_selected = len(selected_ligands)
self.ui.clear_ligands_btn.setEnabled(bool(num_selected))
can_select_all = bool(ligands) and num_selected < len(ligands)
self.ui.select_all_ligands_btn.setEnabled(can_select_all)
def _updateRemoveConstraintButton(self):
has_constraints = bool(self.model.ligand_constraints)
self.ui.remove_constraints_btn.setEnabled(has_constraints)
def _updateInfoMessage(self):
"""
When there is no constrained ligand show a text editor with a message in
the place of the lig_constraint_table.
"""
has_constraints = bool(self.model.ligand_constraints)
enable_info_label = self.model.constrain_ligand and not has_constraints
enable_table = self.model.constrain_ligand and has_constraints
self.info_text_edit.setVisible(enable_info_label)
self.lig_constraint_table.setVisible(enable_table)
self.update()
def _updateWatersCb(self):
has_waters = self.model.has_waters
self.ui.keep_waters_cb.setEnabled(bool(has_waters))
def _clearAll(self):
self.model.selected_ligands.clear()
def _selectAll(self):
self.model.selected_ligands = self.model.ligands
[docs] def show(self):
# Fit the column width to the content and adjust the dialog size.
# This is done to avoid showing the panel too wide, when
# self.lig_constraint_table is hidden.
self.ligand_table.view.resizeColumnsToContents()
super().show()
self.adjustSize()
def _onConstrainResiduesToggled(self):
checked = self.model.constrain_ligand
for wdg in (self.ui.constrain_lbl, self.ui.constrain_residues_info_btn,
self.ui.pick_constraints_btn,
self.ui.remove_constraints_btn, self.lig_constraint_table,
self.info_text_edit):
wdg.setVisible(checked)
if checked:
self.energyBasedModelingRequested.emit()
note = "<font color='#ab692c'>(Energy-based modeling will be used)</font>"
else:
note = "(requires Energy-based modeling)"
text = f"<qt><em>{note}</em></qt>"
self.ui.constrain_residues_cb_lbl.setText(text)
self._updateInfoMessage()
[docs]class LigandSpec(plptable.TableSpec):
@plptable.FieldColumn(hm_models.LigandMolecule, sample_data='A HEM 1203')
def lig_name(self, ligand):
src_ligands = ligand.source_ligands
if src_ligands:
chain_name = src_ligands[0].chain
lig_names = [
f'{lig.pdbres.strip()} {lig.resnum:d}' for lig in src_ligands
]
return f'{chain_name}: {", ".join(lig_names)}'
structure_name = plptable.FieldColumn(
hm_models.LigandMolecule.structure_name, sample_data="1CMY")
[docs]class LigandConstraintSpec(plptable.TableSpec):
@plptable.ParamColumn(sample_data="GLY403 - A HEM 1203")
def constraint(self, lig_constraint):
res = lig_constraint.res
resname = f"{res.long_code}{res.rescode}"
return f"{resname} - {lig_constraint.ligname}"