Ejemplo n.º 1
0
    def _initializeMolObj(self, mol, force_reading, ignore_errors):
        """
        Read the input and tries to convert it into a rdkit.Chem.rdchem.Mol obj

        Parameters
        ----------
        mol: str or rdkit.Chem.rdchem.Mol or moleculekit.smallmol.smallmol.SmallMol
            i) rdkit.Chem.rdchem.Mol ii) The path to the pdb/mol2 to load iii) The smile string iv) SmallMol object
            v) moleculekit.molecule.nolecule.Molecule
        force_reading: bool
        If the mol provided is not accepted, the molecule will be initially converted into sdf

        Returns
        -------
        _mol: rdkit.Chem.Molecule object
            The rdkit molecule
        smallMol: moleculekit.smallmol.smallmol.SmallMol
            The smallMol object if SmallMol was passed
        """
        from moleculekit.molecule import Molecule

        _mol = None
        if isinstance(mol, Chem.Mol):
            _mol = mol
        elif isinstance(mol, Molecule):
            _mol = self._fromMolecule(mol)
        elif isinstance(mol, str):
            if os.path.isfile(mol):
                name_suffix = os.path.splitext(mol)[-1]
                # load mol2 file
                if name_suffix == ".mol2":
                    _mol = Chem.MolFromMol2File(mol, removeHs=False)
                # load pdb file
                elif name_suffix == ".pdb":
                    _mol = Chem.MolFromPDBFile(mol, removeHs=False)
                # if the file failed to be loaded and 'force_reading' = True, file convert to sdf and than loaded
                if _mol is None and force_reading:
                    logger.warning(
                        'Reading {} with force_reading procedure'.format(mol))
                    sdf = openbabelConvert(mol, name_suffix, 'sdf')
                    _mol = Chem.SDMolSupplier(sdf, removeHs=False)[0]
                    os.remove(sdf)
            # assuming is a smile
            # TODO validate it. Implement smarts recognition
            else:
                # try with smiles
                psmile = Chem.SmilesParserParams()
                psmile.removeHs = False
                _mol = Chem.MolFromSmiles(mol, psmile)

        if _mol is None and not ignore_errors:
            if isinstance(mol, str):
                frerr = ' Try by setting the force_reading option as True.' if not force_reading else ''
                raise ValueError('Failed to read file {}.{}'.format(
                    mol, frerr))
            if isinstance(mol, Molecule):
                raise ValueError('Failed convering Molecule to SmallMol')
        return _mol
Ejemplo n.º 2
0
    def _initializeMolObj(self, mol, force_reading, ignore_errors, verbose=True):
        """
        Read the input and tries to convert it into a rdkit.Chem.rdchem.Mol obj

        Parameters
        ----------
        mol: str or rdkit.Chem.rdchem.Mol or moleculekit.smallmol.smallmol.SmallMol
            i) rdkit.Chem.rdchem.Mol ii) The path to the pdb/mol2 to load iii) The smile string iv) SmallMol object
            v) moleculekit.molecule.nolecule.Molecule
        force_reading: bool
        If the mol provided is not accepted, the molecule will be initially converted into sdf

        Returns
        -------
        _mol: rdkit.Chem.Molecule object
            The rdkit molecule
        smallMol: moleculekit.smallmol.smallmol.SmallMol
            The smallMol object if SmallMol was passed
        """
        from moleculekit.molecule import Molecule

        message = None

        # If we are converting a Molecule object to a SmallMol object
        remove = False
        natoms = None
        if isinstance(mol, Molecule):
            natoms = mol.numAtoms
            mol = self._fromMolecule(mol)  # Returns a temp filename
            remove = True

        _mol = None
        if isinstance(mol, Chem.Mol):
            _mol = mol
        elif isinstance(mol, str):
            if os.path.isfile(mol):
                name_suffix = os.path.splitext(mol)[-1]
                # load mol2 file
                if name_suffix == ".mol2":
                    _mol = Chem.MolFromMol2File(mol, removeHs=False)
                # load pdb file
                elif name_suffix == ".pdb":
                    _mol = Chem.MolFromPDBFile(mol, removeHs=False)
                # load single-molecule sdf file
                elif name_suffix == ".sdf":
                    sms = Chem.SDMolSupplier(mol, removeHs=False)
                    if len(sms) != 1:
                        logger.warning(f"More than one molecules found in {mol}. SmallMol will only read the first. If you want to read them all use the SmallMolLib class.")
                    _mol = sms[0]
                # if the file failed to be loaded and 'force_reading' = True, file convert to sdf and than loaded
                if _mol is None and force_reading:
                    logger.warning('Reading {} with force_reading procedure'.format(mol))
                    sdf = openbabelConvert(mol, name_suffix, 'sdf')
                    _mol = Chem.SDMolSupplier(sdf, removeHs=False)[0]
                    os.remove(sdf)
            else:
                # assuming it is a smile
                psmile = Chem.SmilesParserParams()
                psmile.removeHs = False
                _mol = Chem.MolFromSmiles(mol, psmile)

        if remove:  # Remove temp file
            os.remove(mol)

        if _mol is None and not ignore_errors:
            if isinstance(mol, str):
                frerr = ' Try by setting the force_reading option as True.' if not force_reading else ''
                raise ValueError(f'Failed to read file {mol}.{frerr}')
            elif isinstance(mol, Molecule):
                raise ValueError('Failed converting Molecule to SmallMol')
            else:
                raise RuntimeError(f"Failed reading molecule {mol}.")

        if natoms is not None and natoms != _mol.GetNumAtoms():
            raise RuntimeError("Number of atoms changed while converting to rdkit molecule")

        return _mol
Ejemplo n.º 3
0
    def _initializeMolObj(self,
                          mol,
                          force_reading,
                          ignore_errors,
                          verbose=True):
        """
        Read the input and tries to convert it into a rdkit.Chem.rdchem.Mol obj

        Parameters
        ----------
        mol: str or rdkit.Chem.rdchem.Mol or moleculekit.smallmol.smallmol.SmallMol
            i) rdkit.Chem.rdchem.Mol ii) The path to the pdb/mol2 to load iii) The smile string iv) SmallMol object
            v) moleculekit.molecule.nolecule.Molecule
        force_reading: bool
        If the mol provided is not accepted, the molecule will be initially converted into sdf

        Returns
        -------
        _mol: rdkit.Chem.Molecule object
            The rdkit molecule
        smallMol: moleculekit.smallmol.smallmol.SmallMol
            The smallMol object if SmallMol was passed
        """
        from moleculekit.molecule import Molecule

        message = None

        # If we are converting a Molecule object to a SmallMol object
        remove = False
        natoms = None
        if isinstance(mol, Molecule):
            natoms = mol.numAtoms
            mol = self._fromMolecule(mol)  # Returns a temp filename
            remove = True

        _mol = None
        if isinstance(mol, Chem.Mol):
            _mol = mol
        elif isinstance(mol, str):
            if os.path.isfile(mol):
                name_suffix = os.path.splitext(mol)[-1]

                with tempfile.TemporaryFile(mode='w+') as stderr:
                    # Redirect stderr to a file
                    temp_fileno = os.dup(sys.stderr.fileno())
                    os.dup2(stderr.fileno(),
                            sys.stderr.fileno())  # Change process stderr
                    sys.stderr = stderr  # Change Python stderr

                    # load mol2 file
                    if name_suffix == ".mol2":
                        _mol = Chem.MolFromMol2File(mol, removeHs=False)
                    # load pdb file
                    elif name_suffix == ".pdb":
                        _mol = Chem.MolFromPDBFile(mol, removeHs=False)
                    # if the file failed to be loaded and 'force_reading' = True, file convert to sdf and than loaded
                    if _mol is None and force_reading:
                        logger.warning(
                            'Reading {} with force_reading procedure'.format(
                                mol))
                        sdf = openbabelConvert(mol, name_suffix, 'sdf')
                        _mol = Chem.SDMolSupplier(sdf, removeHs=False)[0]
                        os.remove(sdf)

                    # Reset stderr
                    os.dup2(temp_fileno, sys.__stderr__.fileno())
                    os.close(temp_fileno)
                    sys.stderr = sys.__stderr__

                    # Read RDKit warnings
                    stderr.flush()
                    stderr.seek(0)
                    message = stderr.read()

                if verbose:
                    logger.warning(message)
            else:
                # assuming it is a smile
                psmile = Chem.SmilesParserParams()
                psmile.removeHs = False
                _mol = Chem.MolFromSmiles(mol, psmile)

        if remove:  # Remove temp file
            os.remove(mol)

        if _mol is None and not ignore_errors:
            if message is not None and not verbose:
                # Print it anyway if there was an error
                logger.warning(message)
            if isinstance(mol, str):
                frerr = ' Try by setting the force_reading option as True.' if not force_reading else ''
                raise ValueError(f'Failed to read file {mol}.{frerr}')
            elif isinstance(mol, Molecule):
                raise ValueError('Failed converting Molecule to SmallMol')
            else:
                raise RuntimeError(f"Failed reading molecule {mol}.")

        if natoms is not None and natoms != _mol.GetNumAtoms():
            raise RuntimeError(
                "Number of atoms changed while converting to rdkit molecule")

        return _mol