molify 0.2.7__tar.gz → 0.2.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {molify-0.2.7 → molify-0.2.8}/PKG-INFO +1 -1
- {molify-0.2.7 → molify-0.2.8}/docs/source/index.rst +0 -1
- {molify-0.2.7 → molify-0.2.8}/src/molify/_version.py +2 -2
- {molify-0.2.7 → molify-0.2.8}/src/molify/cli.py +11 -1
- {molify-0.2.7 → molify-0.2.8}/src/molify/rdkit2x.py +16 -3
- {molify-0.2.7 → molify-0.2.8}/src/molify/smiles2x.py +17 -14
- {molify-0.2.7 → molify-0.2.8}/src/molify/utils.py +49 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_cli.py +7 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_rdkit2ase.py +14 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_smiles2conformers.py +29 -5
- {molify-0.2.7 → molify-0.2.8}/.github/workflows/build-wheels.yaml +0 -0
- {molify-0.2.7 → molify-0.2.8}/.github/workflows/pages.yaml +0 -0
- {molify-0.2.7 → molify-0.2.8}/.github/workflows/pytest.yaml +0 -0
- {molify-0.2.7 → molify-0.2.8}/.gitignore +0 -0
- {molify-0.2.7 → molify-0.2.8}/.pre-commit-config.yaml +0 -0
- {molify-0.2.7 → molify-0.2.8}/.python-version +0 -0
- {molify-0.2.7 → molify-0.2.8}/CITATION.cff +0 -0
- {molify-0.2.7 → molify-0.2.8}/CONTRIBUTING.md +0 -0
- {molify-0.2.7 → molify-0.2.8}/LICENSE +0 -0
- {molify-0.2.7 → molify-0.2.8}/README.md +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/Makefile +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/make.bat +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/source/ase_tools.ipynb +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/source/atom_selection.ipynb +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/source/conf.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/source/modules.rst +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/source/networkx_tools.ipynb +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/source/packmol_tools.ipynb +0 -0
- {molify-0.2.7 → molify-0.2.8}/docs/source/rdkit_tools.ipynb +0 -0
- {molify-0.2.7 → molify-0.2.8}/paper/.gitignore +0 -0
- {molify-0.2.7 → molify-0.2.8}/paper/bibliography.bib +0 -0
- {molify-0.2.7 → molify-0.2.8}/paper/build.sh +0 -0
- {molify-0.2.7 → molify-0.2.8}/paper/paper.md +0 -0
- {molify-0.2.7 → molify-0.2.8}/paper/zndraw_rdkit.svg +0 -0
- {molify-0.2.7 → molify-0.2.8}/pyproject.toml +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/__init__.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/__main__.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/ase2x.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/bond_order.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/com.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/compress.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/constants.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/networkx2x.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/pack.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/repeat.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/src/molify/substructure.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/conftest.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/data/ec_emc.xyz +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/integration/test_ase2x.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/integration/test_networkx2x.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/integration/test_rdkit2x.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_com.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_compress.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_connectivity.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_edgecases.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_examples.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_repeat.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_solvate.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_substructure.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/tests/test_utils.py +0 -0
- {molify-0.2.7 → molify-0.2.8}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: molify
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Molecular Structure Interface with RDKit, ASE, Packmol and NetworkX
|
|
5
5
|
Project-URL: Repository, https://github.com/zincware/molify
|
|
6
6
|
Project-URL: Releases, https://github.com/zincware/molify/releases
|
|
@@ -124,7 +124,6 @@ For example, molify provides helper functions to generate 3D conformers directly
|
|
|
124
124
|
# Generate 10 different 3D conformers of water
|
|
125
125
|
water = molify.smiles2conformers("O", numConfs=10)
|
|
126
126
|
|
|
127
|
-
|
|
128
127
|
**Molecular System Building**
|
|
129
128
|
|
|
130
129
|
For many applications, it is useful to solvate molecules or create mixtures.
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
21
|
+
__version__ = version = '0.2.8'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 8)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -86,13 +86,23 @@ def smiles2atoms(
|
|
|
86
86
|
seed: Annotated[
|
|
87
87
|
int, typer.Option(help="Random seed for conformer generation.")
|
|
88
88
|
] = 42,
|
|
89
|
+
random_coords: Annotated[
|
|
90
|
+
bool,
|
|
91
|
+
typer.Option(
|
|
92
|
+
"--random-coords",
|
|
93
|
+
help=(
|
|
94
|
+
"Start the embedding from random coordinates, which long chains"
|
|
95
|
+
" such as n-alkanes from about C56 on often need."
|
|
96
|
+
),
|
|
97
|
+
),
|
|
98
|
+
] = False,
|
|
89
99
|
) -> None:
|
|
90
100
|
"""Convert a SMILES string into a single 3D structure on standard output.
|
|
91
101
|
|
|
92
102
|
Example: molify smiles2atoms CCO --format XYZ > etoh.xyz
|
|
93
103
|
"""
|
|
94
104
|
try:
|
|
95
|
-
atoms = _smiles2atoms(smiles, seed=seed)
|
|
105
|
+
atoms = _smiles2atoms(smiles, seed=seed, useRandomCoords=random_coords)
|
|
96
106
|
except ValueError as err:
|
|
97
107
|
raise typer.BadParameter(str(err), param_hint=["smiles"]) from err
|
|
98
108
|
with io.StringIO() as handle:
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import ase
|
|
2
2
|
import networkx as nx
|
|
3
3
|
from rdkit import Chem
|
|
4
|
-
from rdkit.Chem import AllChem
|
|
5
4
|
|
|
6
5
|
from molify.constants import EdgeAttr, GraphAttr, NodeAttr
|
|
6
|
+
from molify.utils import embed_conformers
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def rdkit2ase(
|
|
9
|
+
def rdkit2ase(
|
|
10
|
+
mol: Chem.Mol,
|
|
11
|
+
seed: int = 42,
|
|
12
|
+
useRandomCoords: bool = False, # noqa N803
|
|
13
|
+
) -> ase.Atoms:
|
|
10
14
|
"""Convert an RDKit molecule to an ASE Atoms object.
|
|
11
15
|
|
|
12
16
|
Parameters
|
|
@@ -15,6 +19,10 @@ def rdkit2ase(mol: Chem.Mol, seed: int = 42) -> ase.Atoms:
|
|
|
15
19
|
RDKit molecule to convert
|
|
16
20
|
seed : int, optional
|
|
17
21
|
Random seed for conformer generation (default is 42)
|
|
22
|
+
useRandomCoords : bool, optional
|
|
23
|
+
Start the embedding from random coordinates instead of the eigenvectors
|
|
24
|
+
of the distance matrix (default is False). Long chains, such as
|
|
25
|
+
n-alkanes from about C56 on, often embed only this way.
|
|
18
26
|
|
|
19
27
|
Returns
|
|
20
28
|
-------
|
|
@@ -26,6 +34,11 @@ def rdkit2ase(mol: Chem.Mol, seed: int = 42) -> ase.Atoms:
|
|
|
26
34
|
- Formal charges if present
|
|
27
35
|
- SMILES string in atoms.info
|
|
28
36
|
|
|
37
|
+
Raises
|
|
38
|
+
------
|
|
39
|
+
ValueError
|
|
40
|
+
If RDKit fails to embed ``mol``.
|
|
41
|
+
|
|
29
42
|
Examples
|
|
30
43
|
--------
|
|
31
44
|
>>> from rdkit import Chem
|
|
@@ -41,7 +54,7 @@ def rdkit2ase(mol: Chem.Mol, seed: int = 42) -> ase.Atoms:
|
|
|
41
54
|
smiles = Chem.MolToSmiles(mol)
|
|
42
55
|
mol = Chem.AddHs(mol)
|
|
43
56
|
charges = [atom.GetFormalCharge() for atom in mol.GetAtoms()]
|
|
44
|
-
|
|
57
|
+
embed_conformers(mol, smiles, 1, seed, 0, useRandomCoords)
|
|
45
58
|
|
|
46
59
|
atoms = ase.Atoms(
|
|
47
60
|
positions=mol.GetConformer().GetPositions(),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import ase
|
|
2
2
|
import numpy as np
|
|
3
3
|
from rdkit import Chem
|
|
4
|
-
from rdkit.Chem import rdDistGeom
|
|
5
4
|
|
|
6
5
|
from molify.constants import GraphAttr
|
|
6
|
+
from molify.utils import embed_conformers
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def get_pf6() -> ase.Atoms:
|
|
@@ -32,7 +32,11 @@ def get_pf6() -> ase.Atoms:
|
|
|
32
32
|
return atoms
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def smiles2atoms(
|
|
35
|
+
def smiles2atoms(
|
|
36
|
+
smiles: str,
|
|
37
|
+
seed: int = 42,
|
|
38
|
+
useRandomCoords: bool = False, # noqa N803
|
|
39
|
+
) -> ase.Atoms:
|
|
36
40
|
"""Convert a SMILES string to an ASE Atoms object.
|
|
37
41
|
|
|
38
42
|
Parameters
|
|
@@ -41,6 +45,10 @@ def smiles2atoms(smiles: str, seed: int = 42) -> ase.Atoms:
|
|
|
41
45
|
The SMILES string to convert.
|
|
42
46
|
seed : int, optional
|
|
43
47
|
Random seed for conformer generation (default is 42).
|
|
48
|
+
useRandomCoords : bool, optional
|
|
49
|
+
Start the embedding from random coordinates instead of the eigenvectors
|
|
50
|
+
of the distance matrix (default is False). Long chains, such as
|
|
51
|
+
n-alkanes from about C56 on, often embed only this way.
|
|
44
52
|
|
|
45
53
|
Returns
|
|
46
54
|
-------
|
|
@@ -65,7 +73,7 @@ def smiles2atoms(smiles: str, seed: int = 42) -> ase.Atoms:
|
|
|
65
73
|
>>> isinstance(atoms, ase.Atoms)
|
|
66
74
|
True
|
|
67
75
|
"""
|
|
68
|
-
return smiles2conformers(smiles, 1, seed)[0]
|
|
76
|
+
return smiles2conformers(smiles, 1, seed, useRandomCoords=useRandomCoords)[0]
|
|
69
77
|
|
|
70
78
|
|
|
71
79
|
def smiles2conformers(
|
|
@@ -73,6 +81,7 @@ def smiles2conformers(
|
|
|
73
81
|
numConfs: int, # noqa N803
|
|
74
82
|
randomSeed: int = 42, # noqa N803
|
|
75
83
|
maxAttempts: int = 1000, # noqa N803
|
|
84
|
+
useRandomCoords: bool = False, # noqa N803
|
|
76
85
|
) -> list[ase.Atoms]:
|
|
77
86
|
"""Generate multiple molecular conformers from a SMILES string.
|
|
78
87
|
|
|
@@ -86,6 +95,10 @@ def smiles2conformers(
|
|
|
86
95
|
Random seed for conformer generation (default is 42).
|
|
87
96
|
maxAttempts : int, optional
|
|
88
97
|
Maximum number of embedding attempts (default is 1000).
|
|
98
|
+
useRandomCoords : bool, optional
|
|
99
|
+
Start each embedding from random coordinates instead of the
|
|
100
|
+
eigenvectors of the distance matrix (default is False). Long chains,
|
|
101
|
+
such as n-alkanes from about C56 on, often embed only this way.
|
|
89
102
|
|
|
90
103
|
Returns
|
|
91
104
|
-------
|
|
@@ -127,17 +140,7 @@ def smiles2conformers(
|
|
|
127
140
|
return [get_pf6()] * numConfs
|
|
128
141
|
|
|
129
142
|
mol = Chem.AddHs(mol)
|
|
130
|
-
|
|
131
|
-
mol,
|
|
132
|
-
numConfs=numConfs,
|
|
133
|
-
randomSeed=randomSeed,
|
|
134
|
-
maxAttempts=maxAttempts,
|
|
135
|
-
)
|
|
136
|
-
if len(conformer_ids) < numConfs:
|
|
137
|
-
raise ValueError(
|
|
138
|
-
f"rdkit embedded {len(conformer_ids)} of {numConfs} conformers"
|
|
139
|
-
f" of {smiles!r}"
|
|
140
|
-
)
|
|
143
|
+
embed_conformers(mol, smiles, numConfs, randomSeed, maxAttempts, useRandomCoords)
|
|
141
144
|
|
|
142
145
|
images: list[ase.Atoms] = []
|
|
143
146
|
charges = [atom.GetFormalCharge() for atom in mol.GetAtoms()]
|
|
@@ -14,11 +14,60 @@ from ase.data.colors import jmol_colors
|
|
|
14
14
|
from matplotlib.axes import Axes
|
|
15
15
|
from matplotlib.figure import Figure
|
|
16
16
|
from rdkit import Chem
|
|
17
|
+
from rdkit.Chem import rdDistGeom
|
|
17
18
|
from typing_extensions import deprecated
|
|
18
19
|
|
|
19
20
|
from molify.constants import GraphAttr
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
def embed_conformers(
|
|
24
|
+
mol: Chem.Mol,
|
|
25
|
+
smiles: str,
|
|
26
|
+
numConfs: int, # noqa N803
|
|
27
|
+
randomSeed: int, # noqa N803
|
|
28
|
+
maxAttempts: int, # noqa N803
|
|
29
|
+
useRandomCoords: bool, # noqa N803
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Embed conformers into ``mol`` in place.
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
mol : rdkit.Chem.Mol
|
|
36
|
+
Molecule with explicit hydrogens.
|
|
37
|
+
smiles : str
|
|
38
|
+
SMILES string named in the error message.
|
|
39
|
+
numConfs : int
|
|
40
|
+
Number of conformers to embed.
|
|
41
|
+
randomSeed : int
|
|
42
|
+
Random seed for the embedding.
|
|
43
|
+
maxAttempts : int
|
|
44
|
+
Maximum number of embedding attempts per conformer, 0 for RDKit's
|
|
45
|
+
default.
|
|
46
|
+
useRandomCoords : bool
|
|
47
|
+
Start each embedding from random coordinates instead of the
|
|
48
|
+
eigenvectors of the distance matrix.
|
|
49
|
+
|
|
50
|
+
Raises
|
|
51
|
+
------
|
|
52
|
+
ValueError
|
|
53
|
+
If RDKit embeds fewer than ``numConfs`` conformers.
|
|
54
|
+
"""
|
|
55
|
+
embedded = len(
|
|
56
|
+
rdDistGeom.EmbedMultipleConfs(
|
|
57
|
+
mol,
|
|
58
|
+
numConfs=numConfs,
|
|
59
|
+
randomSeed=randomSeed,
|
|
60
|
+
maxAttempts=maxAttempts,
|
|
61
|
+
useRandomCoords=useRandomCoords,
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
if embedded < numConfs:
|
|
65
|
+
message = f"rdkit embedded {embedded} of {numConfs} conformers of {smiles!r}"
|
|
66
|
+
if not useRandomCoords:
|
|
67
|
+
message += "; random starting coordinates often embed large molecules"
|
|
68
|
+
raise ValueError(message)
|
|
69
|
+
|
|
70
|
+
|
|
22
71
|
def _is_atom_index(value) -> bool:
|
|
23
72
|
return (
|
|
24
73
|
isinstance(value, numbers.Real)
|
|
@@ -76,3 +76,10 @@ def test_smiles2atoms_reports_unparseable_smiles():
|
|
|
76
76
|
assert (
|
|
77
77
|
"Invalid value for 'smiles': rdkit cannot parse SMILES 'C1CC'" in result.output
|
|
78
78
|
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_smiles2atoms_random_coords_embeds_long_chains():
|
|
82
|
+
result = runner.invoke(app, ["smiles2atoms", "C" * 56, "--random-coords"])
|
|
83
|
+
assert result.exit_code == 0, result.output
|
|
84
|
+
atoms = ase.io.read(io.StringIO(result.output), format="extxyz")
|
|
85
|
+
assert atoms.get_chemical_formula() == "C56H114"
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
1
3
|
import ase
|
|
2
4
|
import numpy as np
|
|
3
5
|
import numpy.testing as npt
|
|
@@ -203,3 +205,15 @@ class TestRdkit2NetworkxOriginalIndex:
|
|
|
203
205
|
|
|
204
206
|
for node_id, attributes in graph.nodes(data=True):
|
|
205
207
|
assert attributes[NodeAttr.ORIGINAL_INDEX] == node_id
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def test_rdkit2ase_embeds_long_chains_from_random_coords():
|
|
211
|
+
atoms = rdkit2ase(Chem.MolFromSmiles("C" * 56), seed=42, useRandomCoords=True)
|
|
212
|
+
assert atoms.get_chemical_formula() == "C56H114"
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_rdkit2ase_rejects_unembeddable_mol():
|
|
216
|
+
mol = Chem.MolFromSmiles("[Fe](C)(C)(C)(C)(C)(C)(C)(C)")
|
|
217
|
+
message = f"rdkit embedded 0 of 1 conformers of {Chem.MolToSmiles(mol)!r}"
|
|
218
|
+
with pytest.raises(ValueError, match=re.escape(message)):
|
|
219
|
+
rdkit2ase(mol)
|
|
@@ -81,22 +81,46 @@ def test_smiles2conformers_rejects_unparseable_smiles(smiles):
|
|
|
81
81
|
smiles2conformers(smiles, numConfs=3)
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
RANDOM_COORDS_HINT = "; random starting coordinates often embed large molecules"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.mark.parametrize(
|
|
88
|
+
("use_random_coords", "hint"),
|
|
89
|
+
[(False, RANDOM_COORDS_HINT), (True, "")],
|
|
90
|
+
ids=["eigenvector-coords", "random-coords"],
|
|
91
|
+
)
|
|
84
92
|
@pytest.mark.parametrize(
|
|
85
93
|
("convert", "num_confs"),
|
|
86
94
|
[(partial(smiles2conformers, numConfs=3), 3), (smiles2atoms, 1)],
|
|
87
95
|
ids=["smiles2conformers", "smiles2atoms"],
|
|
88
96
|
)
|
|
89
|
-
def test_rejects_unembeddable_smiles(convert, num_confs):
|
|
97
|
+
def test_rejects_unembeddable_smiles(convert, num_confs, use_random_coords, hint):
|
|
90
98
|
smiles = "[Fe](C)(C)(C)(C)(C)(C)(C)(C)"
|
|
91
|
-
message = f"rdkit embedded 0 of {num_confs} conformers of {smiles!r}"
|
|
92
|
-
with pytest.raises(ValueError, match=re.escape(message)):
|
|
93
|
-
convert(smiles)
|
|
99
|
+
message = f"rdkit embedded 0 of {num_confs} conformers of {smiles!r}{hint}"
|
|
100
|
+
with pytest.raises(ValueError, match=f"^{re.escape(message)}$"):
|
|
101
|
+
convert(smiles, useRandomCoords=use_random_coords)
|
|
94
102
|
|
|
95
103
|
|
|
96
104
|
def test_smiles2conformers_rejects_partial_embedding():
|
|
97
105
|
smiles = "C1CC2CCC1C2"
|
|
98
106
|
assert len(smiles2conformers(smiles, numConfs=10)) == 10
|
|
99
107
|
with pytest.raises(
|
|
100
|
-
ValueError,
|
|
108
|
+
ValueError,
|
|
109
|
+
match=(
|
|
110
|
+
r"^rdkit embedded [1-9] of 10 conformers of 'C1CC2CCC1C2'"
|
|
111
|
+
f"{re.escape(RANDOM_COORDS_HINT)}$"
|
|
112
|
+
),
|
|
101
113
|
):
|
|
102
114
|
smiles2conformers(smiles, numConfs=10, maxAttempts=1)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@pytest.mark.parametrize("n_carbons", [56, 64])
|
|
118
|
+
def test_smiles2atoms_embeds_long_chains_from_random_coords(n_carbons):
|
|
119
|
+
atoms = smiles2atoms("C" * n_carbons, seed=42, useRandomCoords=True)
|
|
120
|
+
assert atoms.get_chemical_formula() == f"C{n_carbons}H{2 * n_carbons + 2}"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_smiles2conformers_embeds_long_chains_from_random_coords():
|
|
124
|
+
frames = smiles2conformers("C" * 56, numConfs=2, useRandomCoords=True)
|
|
125
|
+
assert [atoms.get_chemical_formula() for atoms in frames] == ["C56H114"] * 2
|
|
126
|
+
assert not np.allclose(frames[0].positions, frames[1].positions)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|