Source code for schrodinger.application.jaguar.gui.tabs.solvation_tab

import warnings
from collections import OrderedDict

from schrodinger.infra import mm
from schrodinger.Qt import QtWidgets

from .. import ui
from ..utils import JaguarSettingWarning
from .base_tab import BaseTab


[docs]def different(value1, value2): """ Return True if the given float values are different from each other (tiny differences are not considered). """ return abs(value1 - value2) > 1e-10
[docs]class SolventTab(BaseTab): """ A base class for the Solvent tab (used in the pKa panel) and the standard Solvation tab. """ NAME = "Solvent" HELP_TOPIC = "JAGUAR_TOPIC_SOLVATION_FOLDER" def _warnAboutOtherSolventTypes(self, jag_input): """ Warn if any keywords for the "other" solvent type are set, since they will be ignored. :param jag_input: The Jaguar settings to check :type jag_input: `schrodinger.application.jaguar.input.JaguarInput` """ NON_ALLOWED_KEYS = (mm.MMJAG_RKEY_EPSOUT, mm.MMJAG_RKEY_RADPRB) bad_keys = [ key for key in NON_ALLOWED_KEYS if jag_input.isNonDefault(key) ] if bad_keys and jag_input[mm.MMJAG_SKEY_SOLVENT] != "other": plural_s = "s" if len(bad_keys) > 1 else "" msg = ( "Custom solvent keyword%s %s specified but solvent is not set " "to other (solvent != other). These keywords will be ignored." % (plural_s, " and ".join(bad_keys))) warnings.warn(JaguarSettingWarning(msg))
[docs]class SolventPkaTab(SolventTab): """ The Solvent tab for the Pka panel. """ SOLVENTS = {"Water": mm.MMJAG_SOLVENT_WATER, "DMSO": mm.MMJAG_SOLVENT_DMSO} UI_MODULES = (ui.solvent_pka_tab_ui,)
[docs] def setup(self): super().setup() self.ui.solvent_combo.addItemsFromDict(self.SOLVENTS)
[docs] def getMmJagKeywords(self): keywords = super().getMmJagKeywords() solv_type = self.ui.solvent_combo.currentData() keywords[mm.MMJAG_SKEY_SOLVENT] = solv_type ipka_solv_opt = mm.MMJAG_IPKA_SOLV_OPT_OFF if self.ui.use_solvation_cb.isChecked(): ipka_solv_opt = mm.MMJAG_IPKA_SOLV_OPT_ON keywords[mm.MMJAG_IKEY_IPKA_SOLV_OPT] = ipka_solv_opt # Explicitly clear any dielectric and probe radius settings, since # they're incompatible with the solvents selectable in this tab keywords[mm.MMJAG_RKEY_EPSOUT] = None keywords[mm.MMJAG_RKEY_RADPRB] = None return keywords
[docs] def loadSettings(self, jag_input): solv_type = jag_input[mm.MMJAG_SKEY_SOLVENT] solv_type = solv_type.replace('_', ' ') try: self.ui.solvent_combo.setCurrentData(solv_type) except ValueError: msg = "Unrecognized solvent type %s=%s" % (mm.MMJAG_SKEY_SOLVENT, solv_type) warnings.warn(JaguarSettingWarning(msg)) self._warnAboutOtherSolventTypes(jag_input) ipka_solv_opt = jag_input[mm.MMJAG_IKEY_IPKA_SOLV_OPT] ipka_solv_opt_bool = ipka_solv_opt == mm.MMJAG_IPKA_SOLV_OPT_ON self.ui.use_solvation_cb.setChecked(ipka_solv_opt_bool)
[docs]class SolvationTab(SolventTab): """ The Solvation tab, which includes solvent model and gas-phase reference energy """ NAME = "Solvation" UI_MODULES = (ui.solvent_tab_ui,) NO_SOLVENT_MODEL = "None" PBF_MODEL = "PBF" PCM_MODEL = "PCM" SM6_MODEL = "SM6" SM8_MODEL = "SM8" # SM6 and SM8 models are not available yet, so we will only show # the first two items at this time. NOTE - when they are implemented, # remove their special handling in the SolvationTabNoOptimized class. SOLVENT_MODELS = OrderedDict([ (NO_SOLVENT_MODEL, mm.MMJAG_ISOLV_OFF), (PBF_MODEL, mm.MMJAG_ISOLV_PBF), (PCM_MODEL, mm.MMJAG_ISOLV_PCM), #(SM6_MODEL, mm.MMJAG_ISOLV_SM6), #(SM8_MODEL, mm.MMJAG_ISOLV_SM8), ]) CPCM_PCM_MODEL = "CPCM" COSMO_PCM_MODEL = "COSMO" SSVPE_PCM_MODEL = "SS(v)PE" PCM_MODELS = OrderedDict([(CPCM_PCM_MODEL, mm.MMJAG_PCM_MODEL_CPCM), (COSMO_PCM_MODEL, mm.MMJAG_PCM_MODEL_COSMO), (SSVPE_PCM_MODEL, mm.MMJAG_PCM_MODEL_SSVPE)]) BONDI_PCM_RADII = "Bondi" UFF_PCM_RADII = "UFF" KLAMT_PCM_RADII = "Klamt" PCM_RADII = OrderedDict([(BONDI_PCM_RADII, mm.MMJAG_PCM_RADII_BONDI), (UFF_PCM_RADII, mm.MMJAG_PCM_RADII_UFF), (KLAMT_PCM_RADII, mm.MMJAG_PCM_RADII_KLAMT)])
[docs] def setup(self): super().setup() self.ui.solvent_model_combo.addItemsFromDict(self.SOLVENT_MODELS) self.ui.solvent_model_combo.currentIndexChanged.connect( self.solventModelChanged) self.ui.pcm_model_combo.addItemsFromDict(self.PCM_MODELS) self.ui.pcm_radii_combo.addItemsFromDict(self.PCM_RADII) self.gas_phase_group = QtWidgets.QButtonGroup(self) self.gas_phase_group.addButton(self.ui.optimized_structure_rb) self.gas_phase_group.addButton(self.ui.input_structure_rb) self.ui.solvent_chooser_btn.solventChanged.connect( self.ui.solvent_le.setText) self.solventModelChanged()
[docs] def solventModelChanged(self): """ Called when a new item is selected in the solvent model type menu. """ isolv = self.ui.solvent_model_combo.currentText() enable = isolv in (self.PBF_MODEL, self.PCM_MODEL, self.SM8_MODEL) self.ui.solvent_lbl.setEnabled(enable) self.ui.solvent_le.setEnabled(enable) self.ui.solvent_chooser_btn.setEnabled(enable) if not enable: self.ui.solvent_chooser_btn.setSolvent(mm.MMJAG_SOLVENT_WATER) visible = (isolv == self.PCM_MODEL) self.ui.pcm_frame.setVisible(visible) visible = isolv in (self.PBF_MODEL, self.PCM_MODEL) self.ui.gas_phase_frame.setVisible(visible)
[docs] def getMmJagKeywords(self): keywords = {} keywords.update(self._getSolventModelAndTypeKeyword()) keywords.update(self._getPCMKeywords()) keywords.update(self._getGasPhaseKeywords()) return keywords
def _getSolventModelAndTypeKeyword(self): """ Get the solvent model keyword :return: A dictionary of keywords :rtype: dict """ isolv = self.ui.solvent_model_combo.currentData() solvent_type = self.ui.solvent_chooser_btn.getSolvent() solvent_type = solvent_type.replace(' ', '_') return {mm.MMJAG_IKEY_ISOLV: isolv, mm.MMJAG_SKEY_SOLVENT: solvent_type} def _getPCMKeywords(self): """ Get PCM keywords when applicable. :return: A dictionary of keywords :rtype: dict """ keywords = {} isolv = self.ui.solvent_model_combo.currentText() if isolv != self.PCM_MODEL: keywords[mm.MMJAG_SKEY_PCM_MODEL] = None keywords[mm.MMJAG_SKEY_PCM_RADII] = None keywords[mm.MMJAG_IKEY_PBF_AFTER_PCM] = None return keywords pcm_model = self.ui.pcm_model_combo.currentData() keywords[mm.MMJAG_SKEY_PCM_MODEL] = pcm_model pcm_radii = self.ui.pcm_radii_combo.currentData() keywords[mm.MMJAG_SKEY_PCM_RADII] = pcm_radii pbf_after_pcm = mm.MMJAG_PBF_AFTER_PCM_OFF if self.ui.pbf_optimization_cb.isChecked(): pbf_after_pcm = mm.MMJAG_PBF_AFTER_PCM_ON keywords[mm.MMJAG_IKEY_PBF_AFTER_PCM] = pbf_after_pcm return keywords def _getGasPhaseKeywords(self): """ Get the gas phase reference energy keywords :return: A dictionary of keywords :rtype: dict """ keywords = {} isolv = self.ui.solvent_model_combo.currentText() if isolv not in (self.PBF_MODEL, self.PCM_MODEL): keywords[mm.MMJAG_IKEY_NOGAS] = None return keywords if self.ui.optimized_structure_rb.isChecked(): nogas = mm.MMJAG_NOGAS_OFF elif self.ui.input_structure_rb.isChecked(): nogas = mm.MMJAG_NOGAS_ZMAT keywords[mm.MMJAG_IKEY_NOGAS] = nogas return keywords
[docs] def loadSettings(self, jag_input): self._checkSolventSettings(jag_input) self._warnAboutOtherSolventTypes(jag_input) self._loadSolventModelAndTypeSettings(jag_input) self._loadPCMSettings(jag_input) self._loadGasPhaseSettings(jag_input)
def _checkSolventSettings(self, jag_input): """ Make sure that the solvent settings are consistent. Issue warnings for any inconsistencies. :param jag_input: The Jaguar settings to check :type jag_input: `schrodinger.application.jaguar.input.JaguarInput` """ SETTING_KEYS = (mm.MMJAG_RKEY_EPSOUT, mm.MMJAG_RKEY_RADPRB) SOLVENT_KEYS = ((mm.MMJAG_SKEY_SOLVENT, mm.MMJAG_IKEY_NOGAS) + SETTING_KEYS) if jag_input[mm.MMJAG_IKEY_ISOLV] not in (mm.MMJAG_ISOLV_PBF, mm.MMJAG_ISOLV_PCM, mm.MMJAG_ISOLV_SM8): bad_keys = [ key for key in SOLVENT_KEYS if jag_input.isNonDefault(key) ] if bad_keys: msg = ("Solvent settings specified but solvation not set to " "PBF, PCM, or SM8 (%s != %i, %i, or %i). The following " "keys will be ignored: %s." % (mm.MMJAG_IKEY_ISOLV, mm.MMJAG_ISOLV_PBF, mm.MMJAG_ISOLV_PCM, mm.MMJAG_ISOLV_SM8, ", ".join(bad_keys))) warnings.warn(JaguarSettingWarning(msg)) return if jag_input[mm.MMJAG_SKEY_SOLVENT] != "other": bad_keys = [ key for key in SETTING_KEYS if jag_input.isNonDefault(key) ] if bad_keys: msg = ("Solvent settings specified but solvent not set to " "other (%s != other). The following keys will be " "ignored: %s." % (mm.MMJAG_SKEY_SOLVENT, ", ".join(bad_keys))) warnings.warn(JaguarSettingWarning(msg)) def _loadSolventModelAndTypeSettings(self, jag_input): """ Load the solvent model and solvent type settings. If solvent model is not PBF, PCM, or SM8, then a solvent type of water is used regardless of the `jag_input` setting. :param jag_input: The Jaguar settings to load :type jag_input: `schrodinger.application.jaguar.input.JaguarInput` """ self.ui.solvent_model_combo.setCurrentMmJagData(jag_input, mm.MMJAG_IKEY_ISOLV, "solvent model") if jag_input[mm.MMJAG_IKEY_ISOLV] in (mm.MMJAG_ISOLV_PBF, mm.MMJAG_ISOLV_PCM, mm.MMJAG_ISOLV_SM8): solvent = jag_input[mm.MMJAG_SKEY_SOLVENT] solvent = solvent.replace('_', ' ') try: self.ui.solvent_chooser_btn.setSolvent(solvent) except ValueError: msg = ("Unrecognized solvent type " f"{mm.MMJAG_SKEY_SOLVENT}={solvent}") warnings.warn(JaguarSettingWarning(msg)) else: self.ui.solvent_chooser_btn.setSolvent(mm.MMJAG_SOLVENT_WATER) def _loadPCMSettings(self, jag_input): """ Load PCM settings. """ self.ui.pcm_model_combo.setCurrentMmJagData(jag_input, mm.MMJAG_SKEY_PCM_MODEL, "pcm model") self.ui.pcm_radii_combo.setCurrentMmJagData(jag_input, mm.MMJAG_SKEY_PCM_RADII, "pcm radii") pbf_after_pcm = jag_input[mm.MMJAG_IKEY_PBF_AFTER_PCM] self.ui.pbf_optimization_cb.setChecked( pbf_after_pcm == mm.MMJAG_PBF_AFTER_PCM_ON) def _loadGasPhaseSettings(self, jag_input): """ Load the gas phase reference energy settings :param jag_input: The Jaguar settings to load :type jag_input: `schrodinger.application.jaguar.input.JaguarInput` """ if (jag_input[mm.MMJAG_IKEY_ISOLV] != mm.MMJAG_ISOLV_PBF): return nogas = jag_input[mm.MMJAG_IKEY_NOGAS] # NOGAS_DEFAULT == -1, and NOGAS_OFF == 0, but the default behavior is # NOGAS_OFF. if nogas == mm.MMJAG_NOGAS_OFF or nogas == mm.MMJAG_NOGAS_DEFAULT: self.ui.optimized_structure_rb.setChecked(True) elif nogas == mm.MMJAG_NOGAS_ZMAT: self.ui.input_structure_rb.setChecked(True) else: msg = ("Gas-phase reference energy setting not recognized (%s=%f)" % (mm.MMJAG_IKEY_NOGAS, nogas)) warnings.warn(JaguarSettingWarning(msg))
[docs]class SolvationTabNoOptimized(SolvationTab): """ A solvation tab that doesn't allow "Optimized gas-phase structure". """
[docs] def setup(self): super(SolvationTabNoOptimized, self).setup() self.ui.optimized_structure_rb.setText("Input gas-phase structure") self.ui.input_structure_rb.hide() self.ui.pbf_optimization_cb.hide() # SM6 and SM8 models are only available for jobs without # optimization (SPE & Rigid CS), so add them here. self.ui.solvent_model_combo.addItem(self.SM6_MODEL, mm.MMJAG_ISOLV_SM6) self.ui.solvent_model_combo.addItem(self.SM8_MODEL, mm.MMJAG_ISOLV_SM8)
def _loadGasPhaseSettings(self, jag_input): if (jag_input[mm.MMJAG_IKEY_ISOLV] == mm.MMJAG_ISOLV_PBF and jag_input[mm.MMJAG_IKEY_NOGAS] == mm.MMJAG_NOGAS_ZMAT): msg = ("%s=%i not allowed for single point calculations." % (mm.MMJAG_IKEY_NOGAS, jag_input[mm.MMJAG_IKEY_NOGAS])) warnings.warn(JaguarSettingWarning(msg)) else: super(SolvationTabNoOptimized, self)._loadGasPhaseSettings(jag_input)