From ba6feadfdea0b98fc44e4d4963a6fe8f136c84c3 Mon Sep 17 00:00:00 2001 From: Co Quach <43968221+daico007@users.noreply.github.com> Date: Tue, 25 Oct 2022 14:14:37 -0500 Subject: [PATCH] Add smiles string conversion using pybel backend (#1056) * add smiles string conversion using pybel backend * add unit test for several smiles string conversion scenarios * restrict python version, attempt to fix bleeding test --- environment-dev-win.yml | 2 +- environment-dev.yml | 2 +- environment.yml | 2 +- mbuild/compound.py | 16 ++++++++++++++++ mbuild/conversion.py | 29 +++++++++++++++++++++++++++++ mbuild/tests/test_compound.py | 16 ++++++++++++++++ 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/environment-dev-win.yml b/environment-dev-win.yml index be6d07a0f..88e6bdb0c 100644 --- a/environment-dev-win.yml +++ b/environment-dev-win.yml @@ -25,6 +25,6 @@ dependencies: - pycifrw - pytest - pytest-cov - - python + - python<3.10 - rdkit>=2021 - scipy diff --git a/environment-dev.yml b/environment-dev.yml index 13a004b96..c4cd43fff 100644 --- a/environment-dev.yml +++ b/environment-dev.yml @@ -27,6 +27,6 @@ dependencies: - pytest - pytest-azurepipelines - pytest-cov - - python + - python<3.10 - rdkit>=2021 - scipy diff --git a/environment.yml b/environment.yml index 04d27a7b4..883dad7d5 100644 --- a/environment.yml +++ b/environment.yml @@ -7,6 +7,6 @@ dependencies: - packmol>=18 - gmso>=0.9.0 - parmed>=3.4.3 - - python + - python<3.10 - rdkit>=2021 - scipy diff --git a/mbuild/compound.py b/mbuild/compound.py index beb9c8f90..fe5081f4d 100644 --- a/mbuild/compound.py +++ b/mbuild/compound.py @@ -2728,6 +2728,22 @@ def to_pybel( show_ports=show_ports, ) + def to_smiles(self, backend="pybel"): + """Create a SMILES string from an mbuild compound. + + Parameters + ---------- + compound : mb.Compound. + The mbuild compound to be converted. + backend : str, optional, default="pybel" + Backend used to do the conversion. + + Return + ------ + smiles_string : str + """ + return conversion.to_smiles(self, backend) + def from_pybel( self, pybel_mol, diff --git a/mbuild/conversion.py b/mbuild/conversion.py index 22011e8e5..85a035158 100644 --- a/mbuild/conversion.py +++ b/mbuild/conversion.py @@ -1564,6 +1564,35 @@ def to_pybel( return pybelmol +def to_smiles(compound, backend="pybel"): + """Create a SMILES string from an mbuild compound. + + Parameters + ---------- + compound : mb.Compound. + The mbuild compound to be converted. + backend : str, optional, default="pybel" + Backend used to do the conversion. + + Return + ------ + smiles_string : str + """ + if backend == "pybel": + mol = to_pybel(compound) + + warn( + "The bond orders will be guessed using pybel" + "OBMol.PerceviedBondOrders()" + ) + mol.OBMol.PerceiveBondOrders() + smiles_string = mol.write("smi").replace("\t", " ").split(" ")[0] + + return smiles_string + else: + raise NotImplementedError(f"Backend {backend} not implemented.") + + def to_networkx(compound, names_only=False): """Create a NetworkX graph representing the hierarchy of a Compound. diff --git a/mbuild/tests/test_compound.py b/mbuild/tests/test_compound.py index b284a1192..5e955e906 100644 --- a/mbuild/tests/test_compound.py +++ b/mbuild/tests/test_compound.py @@ -800,6 +800,22 @@ def test_reload(self): assert p3ht1.n_particles == 33 assert p3ht1.n_bonds == 33 + @pytest.mark.skipif( + not has_openbabel, reason="Open Bable package not installed" + ) + def test_to_smiles(self, ethane, benzene): + # Test predefined molecule + eth_smiles = "CC" + benzene_smiles = "c1ccccc1" + + assert ethane.to_smiles() == eth_smiles + assert benzene.to_smiles() == benzene_smiles + + # Test molecules loaded in with smiles string + for smiles in ["CCO", "CC(O)O", "Cc1ccccc1"]: + compound = mb.load(smiles, smiles=True) + assert compound.to_smiles() == smiles + @pytest.mark.parametrize( "extension", [(".xyz"), (".pdb"), (".mol2"), (".gro")] )