Source code for luna.wrappers.obabel

from subprocess import Popen, PIPE, TimeoutExpired

from openbabel.pybel import informats, outformats

from luna.util.exceptions import FileNotCreated, InvalidFileFormat
from luna.util.default_values import OPENBABEL
from luna.util.file import is_file_valid, validate_file, get_file_format

import logging
logger = logging.getLogger()


def _prep_opts(opts, prefix=""):
    opt_list = []
    if opts is not None:
        for key in opts:
            if len(key) > 1:
                opt_list.append("--%s%s" % (prefix, key))
            else:
                opt_list.append("-%s%s" % (prefix, key))

            if opts[key] is not None:
                opt_list.append(str(opts[key]))
    return opt_list


[docs]def mol_to_svg(infile, output, opts=None): """Depict a molecule as SVG using Open Babel. Parameters ---------- infile : str The pathname of a molecular file. output : str Save the SVG to this file. opts : dict A set of depiction options. Check `Open Babel <http://openbabel.org/docs/dev/FileFormats/SVG_depiction.html>`_ \ to discover which options are available. Examples -------- In this example, we will depict the molecule ZINC000007786517 as SVG. The following options will be used: * C: do not draw terminal C (and attached H) explicitly; * d: do not display the molecule name; * P: image size in pixels. >>> from luna.util.default_values import LUNA_PATH >>> from luna.wrappers.obabel import mol_to_svg >>> mol_to_svg(infile=f"{LUNA_PATH}/tutorial/inputs/ZINC000007786517.mol", ... output="example.svg", ... opts={"C": None, "d": None, "P": 500}) """ logger.debug("Trying to generate a 2D diagram to the file '%s'." % infile) try: validate_file(infile) opt_list = _prep_opts(opts, "x") args = ["obabel", infile, "-O", output] + opt_list p = Popen(args, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() svg_created = stderr.decode().strip() == "1 molecule converted" if not is_file_valid(output) or not svg_created: raise FileNotCreated("SVG diagram for '%s' not created." % infile) else: logger.debug("SVG diagram for '%s' created." % infile) except Exception as e: logger.exception(e) raise
[docs]def convert_molecule(infile, output, infile_format=None, output_format=None, opts=None, openbabel=OPENBABEL): """Convert a molecular file to another format using Open Babel. Parameters ---------- infile : str The pathname of the molecular file to be converted. output : str Save the converted molecule to this file. infile_format : str, optional The molecular format of ``infile``. If not provided, the format will be defined by the file extension. output_format : str, optional The molecular format of ``output``. If not provided, the format will be defined by the file extension. opts : dict A set of convertion options. Check `Open Babel <https://openbabel.org/docs/dev/Command-line_tools/babel.html>`_ to discover which options are available. openbabel : str, optional The Open Babel binary location. If not provided, the default binary ('obabel') will be used. Raises ------ InvalidFileFormat If the provided molecular formats are not accepted by Open Babel. Examples -------- In this example, we will convert the molecule ZINC000007786517 from the format MOL to MOL2 and add hydrogens to it considering a pH of 7 (option "p"). >>> from luna.util.default_values import LUNA_PATH >>> from luna.wrappers.obabel import convert_molecule >>> convert_molecule(infile=f"{LUNA_PATH}/tutorial/inputs/ZINC000007786517.mol", ... output="example.mol2", ... opts={"p": 7}) """ logger.debug("Trying to convert the file '%s' to '%s'." % (infile, output)) try: # It raises an error if it is not valid. validate_file(infile) if infile_format is None: logger.debug("Input file format not defined. It will assume the format from the file extension.") infile_format = get_file_format(infile) if infile_format not in informats: raise InvalidFileFormat("Infile format '%s' does not exist." % infile_format) logger.debug("Input format: %s" % infile_format) if output_format is None: logger.debug("Output file format not defined. It will assume the format by the file extension.") output_format = get_file_format(output, 1) if output_format not in outformats: raise InvalidFileFormat("Infile format '%s' does not exist." % output_format) logger.debug("Output format: %s" % output_format) opt_list = _prep_opts(opts) args = [openbabel, "-i", infile_format, infile, "-o", output_format, "-O", output] + opt_list p = Popen(args, stdout=PIPE, stderr=PIPE) try: stdout, stderr = p.communicate(timeout=30) except TimeoutExpired: p.kill() raise output_lines = stderr.decode().strip().split("\n") is_mol_converted = output_lines[-1] != "0 molecule converted" if not is_file_valid(output) or not is_mol_converted: raise FileNotCreated("File '%s' not converted to '%s'." % (infile, output)) else: logger.debug("File '%s' converted to '%s'." % (infile, output)) except Exception: raise