Source code for schrodinger.application.matsci.smartsutilsgui

"""
GUI elements for working with SMARTS patterns

Copyright Schrodinger, LLC. All rights reserved.
"""

import warnings

from schrodinger.application.matsci import atomicsymbolsgui as symbolsgui
from schrodinger.application.matsci import rdpattern
from schrodinger.infra import mm
from schrodinger.structutils import analyze


[docs]class SMARTSNameValidator(symbolsgui.AtomNameLabelValidator): """ Ensures that the line edit contains only valid SMARTS name characters """ VALID_LABEL_PUNCTUATION = '_-()[]'
[docs]def populate_smarts_edit(smarts_edit, maestro, warning, append=False, delim=' ', canvas_api=False, use_rdkit=False, fall_back=False, check_connectivity=True, allow_intermolecular=False): """ Populates the smarts edit with smarts pattern grabbed from WS. If append is true then the smarts pattern is appended to smarts_edit with delim (space as default) as delimiter else smarts_edit is replaced with the given smarts pattern. :param swidgets.SMARTSEdit smarts_edit: The smarts edit on which population of smarts pattern is to be done :param schrodinger.maestro.maestro maestro: maestro provides structure and selected atom index :param function warning: prints warning message :param bool append: If flag is true then smarts is appended to smarts_edit with delim as delimiter else smarts_edit is replaced with smarts :param str delim: The delimiter used when append is true. :param bool canvas_api: whether to use analyze.generate_smarts or analyze.generate_smarts_canvas :param bool use_rdkit: Whether to use rdkit :param bool fall_back: whether to fall back on using analyze.generate_smarts if canvas/rdkit fails, used only if canvas_api is True :param bool check_connectivity: If True, check for whether the atoms given are connected and raise a ValueError if they are not. SMARTS generation will give bogus results for unconnected atoms. :param bool allow_intermolecular: If check_connectivity is False this controls whether matches must be intramolecular or allowed to be intermolecular """ smarts = get_smarts_from_ws(maestro, warning, canvas_api=canvas_api, use_rdkit=use_rdkit, fall_back=fall_back, check_connectivity=check_connectivity, allow_intermolecular=allow_intermolecular) if not smarts: return if append: patterns = smarts_edit.getSMARTSPatterns() patterns.append(smarts) smarts_edit.setText(delim.join(patterns)) else: smarts_edit.setText(smarts)
[docs]def get_smarts_from_ws(maestro, warning, canvas_api=False, use_rdkit=False, fall_back=False, check_connectivity=True, allow_intermolecular=False): """ Get the SMARTS pattern for the selected atoms in the workspace and insert it into the SMARTS entry :type maestro: `schrodinger.maestro.maestro` :param maestro: maestro provides structure and selected atom index :type warning: function :param warning: prints warning message :type canvas_api: bool :param canvas_api: whether to use analyze.generate_smarts or analyze.generate_smarts_canvas :type canvas_api: bool :param bool use_rdkit: Whether to use rdkit :type fall_back: bool :param fall_back: whether to fall back on using analyze.generate_smarts if canvas/rdkit fails, used only if canvas_api is True :type check_connectivity: bool :param check_connectivity: If True, check for whether the atoms given are connected and raise a ValueError if they are not. SMARTS generation will give bogus results for unconnected atoms. :type allow_intermolecular: bool :param allow_intermolecular: if check_connectivity is False this controls whether matches must be intramolecular or allowed to be intermolecular :rtype: str or None :return: smarts pattern selected from workspace or None if any of the validation fails """ assert not (canvas_api and use_rdkit), ('Canvas and rdkit cannot be both ' 'requested.') selection = maestro.selected_atoms_get() if not selection: warning('No workspace atoms selected') return None try: struct = maestro.get_included_entry() except RuntimeError: warning("There has to be at least one and " "only one included entry in the Workspace.") return None if not check_connectivity and not allow_intermolecular: if len(set(struct.atom[i].molecule_number for i in selection)) > 1: warning('Selection includes atoms from different molecules.') return None use_default = not (canvas_api or use_rdkit) if canvas_api: try: smarts = analyze.generate_smarts_canvas( struct, atom_subset=selection, check_connectivity=check_connectivity) except (RuntimeError, ValueError) as msg: if not fall_back: warning(str(msg)) return None else: use_default = True elif use_rdkit: try: # generate_smarts as well as generate_smarts_canvas with defaults # don't return chiral smarts, thus set it to false here. Also note # that converting to rdkit including stereo can be very slow (RB 67298) include_stereo = False smarts = rdpattern.to_smarts(struct, include_stereo=include_stereo, atom_subset=selection, check_connectivity=check_connectivity) except ValueError as msg: if not fall_back: warning(str(msg)) return None else: use_default = True if use_default: try: # Changed default of generate_smarts_canvas to generate_smarts # due to CANVAS-5621 with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning, message="analyze.generate_smarts") smarts = analyze.generate_smarts( struct, atom_subset=selection, check_connectivity=check_connectivity) except ValueError as msg: warning(str(msg)) return None except mm.MmException: # Something went very wrong with obtaining the SMARTS pattern, but # we don't know what and the Exception message is not user # appropriate warning('Unable to obtain a SMARTS pattern for the selected atoms') return None return smarts