Skip to content

Commit

Permalink
Merge pull request Auto-Mech#603 from avcopan/dev
Browse files Browse the repository at this point in the history
Clean: Drop products argument for enumeration
  • Loading branch information
avcopan authored Jan 3, 2025
2 parents a6fbe94 + a10d7f8 commit e9c65c2
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 56 deletions.
2 changes: 1 addition & 1 deletion automol/geom/_2vib.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def vibrational_analysis(
bohr2m = qcc.conversion_factor("bohr", "meter")
sol = qcc.get("speed of light in vacuum") * 100 # in cm / s
to_inv_cm = numpy.sqrt(har2J / (amu2kg * bohr2m * bohr2m)) / (sol * 2 * numpy.pi)
freqs = numpy.sqrt(numpy.complex_(eig_vals)) * to_inv_cm
freqs = numpy.sqrt(numpy.complex128(eig_vals)) * to_inv_cm
freqs = tuple(map(float, numpy.real(freqs) - numpy.imag(freqs)))

return freqs, norm_coos
Expand Down
2 changes: 1 addition & 1 deletion automol/graph/base/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


# Reaction enumeration
class Smarts:
class ReactionSmarts:
"""SMARTS reaction templates for enumeration."""

elimination = "[H:5][C:1][C:2][O:3][OX1v1:4]>>[C:1]=[C:2].[OX1v1:3][O:4][H:5]"
Expand Down
60 changes: 16 additions & 44 deletions automol/reac/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,64 +8,51 @@


def from_smiles(
smarts: str,
rct_smis: Sequence[str] | Mapping[int, str],
prd_smis: Sequence[str | None] | Mapping[int, str | None] | None = None,
smarts: str, rct_smis: Sequence[str] | Mapping[int, str]
) -> list[Reaction]:
"""Enumerate reactions from SMILES.
Reagents can be given as lists or dictionaries by position in the SMARTS template.
Reactants can be given as lists or dictionaries by position in the SMARTS template.
:param smarts: Reaction SMARTS string
:param rct_chis: Reactant ChIs
:param prd_chis: Product ChIs
:return: List of Reaction objects
"""
rct_gras, prd_gras = reagents(smarts, rct_smis, prd_smis, conv_=smiles.graph)
return from_graphs(smarts, rct_gras, prd_gras)
rct_gras = reactants(smarts, rct_smis, conv_=smiles.graph)
return from_graphs(smarts, rct_gras)


def from_amchis(
smarts: str,
rct_chis: Sequence[str] | Mapping[int, str],
prd_chis: Sequence[str | None] | Mapping[int, str | None] | None = None,
smarts: str, rct_chis: Sequence[str] | Mapping[int, str]
) -> list[Reaction]:
"""Enumerate reactions from AMChIs.
Reagents can be given as lists or dictionaries by position in the SMARTS template.
Reactants can be given as lists or dictionaries by position in the SMARTS template.
:param rct_chis: Reactant ChIs
:param smarts: Reaction SMARTS string
:param prd_chis: Product ChIs
:return: List of Reaction objects
"""
rct_gras, prd_gras = reagents(smarts, rct_chis, prd_chis, conv_=amchi.graph)
return from_graphs(smarts, rct_gras, prd_gras)
rct_gras = reactants(smarts, rct_chis, conv_=amchi.graph)
return from_graphs(smarts, rct_gras)


def from_graphs(
smarts: str,
rct_gras: Sequence[object] | Mapping[int, object],
prd_gras: Sequence[object | None] | Mapping[int, object | None] | None = None,
smarts: str, rct_gras: Sequence[object] | Mapping[int, object]
) -> list[Reaction]:
"""Enumerate reactions from graphs.
Reagents can be given as lists or dictionaries by position in the SMARTS template.
Reactants can be given as lists or dictionaries by position in the SMARTS template.
:param smarts: SMARTS string
:param rct_gras: Reactant graphs
:param prd_gras: Product graphs
:return: List of Reaction objects
"""
# Prepare reactants graph
rct_gras, prd_gras = reagents(smarts, rct_gras, prd_gras, conv_=graph.explicit)
rct_gras = reactants(smarts, rct_gras, conv_=graph.explicit)
rct_gras, _ = graph.standard_keys_for_sequence(rct_gras)
rcts_gra = graph.union_from_sequence(rct_gras)

# Complain if product graphs are given
if any(g is not None for g in prd_gras):
raise NotImplementedError("Product graphs not yet suppported")

# Enumerate reactions
ts_gras = graph.enum.reactions(smarts, rcts_gra)

Expand All @@ -74,42 +61,27 @@ def from_graphs(
rxns = []
for ts_gra in ts_gras:
prds_gra = graph.ts.products_graph(ts_gra, stereo=False, dummy=False)
prd_gras_ = graph.connected_components(prds_gra)
prds_keys = list(map(sorted, map(graph.atom_keys, prd_gras_)))
prd_gras = graph.connected_components(prds_gra)
prds_keys = list(map(sorted, map(graph.atom_keys, prd_gras)))
rxns.append(from_data(ts_gra, rcts_keys, prds_keys))
return rxns


# helpers
def reagents(
def reactants(
smarts: str,
rct_vals: Sequence[object] | Mapping[int, object],
prd_vals: Sequence[object] | Mapping[int, object] | None = None,
conv_: Callable[[object], object] | None = None,
) -> tuple[list[object], list[object]]:
"""Get lists of reagent values for a SMARTS reaction template.
:param smarts: SMARTS string
:param rct_vals: Reagent values
:param prd_vals: Product values
:return: Lists of reactant and product values
"""
nrcts, nprds = smarts_.shape(smarts)
nrcts = smarts_.reactant_count(smarts)
rct_vals = dict(enumerate(rct_vals)) if isinstance(rct_vals, Sequence) else rct_vals
prd_vals = (
dict(enumerate(prd_vals))
if isinstance(prd_vals, Sequence)
else {} if prd_vals is None else prd_vals
)

assert isinstance(rct_vals, Mapping), f"rct_vals = {rct_vals}"
assert isinstance(prd_vals, Mapping), f"prd_vals = {prd_vals}"

rct_vals = list(map(rct_vals.get, range(nrcts)))
prd_vals = list(map(prd_vals.get, range(nprds)))

if conv_ is not None:
rct_vals = [v if v is None else conv_(v) for v in rct_vals]
prd_vals = [v if v is None else conv_(v) for v in prd_vals]

return rct_vals, prd_vals
return rct_vals
4 changes: 2 additions & 2 deletions automol/smarts/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""SMARTS functions."""

from . import rd
from ._core import shape
from ._core import product_count, reactant_count, shape

__all__ = ["rd", "shape"]
__all__ = ["rd", "shape", "reactant_count", "product_count"]
20 changes: 19 additions & 1 deletion automol/smarts/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,27 @@

# properties
def shape(smarts: str) -> tuple[list[int], list[int]]:
"""Get numbers of the reactants and products in SMARTS string.
"""Get numbers of reactants and products in SMARTS string.
:param smarts: SMARTS string
:return: Reaction shape
"""
return rd.shape(rd.from_smarts(smarts))


def reactant_count(smarts: str) -> tuple[list[int], list[int]]:
"""Get number of reactants in SMARTS string.
:param smarts: SMARTS string
:return: Reaction shape
"""
return rd.reactant_count(rd.from_smarts(smarts))


def product_count(smarts: str) -> tuple[list[int], list[int]]:
"""Get number of products in SMARTS string.
:param smarts: SMARTS string
:return: Reaction shape
"""
return rd.product_count(rd.from_smarts(smarts))
4 changes: 2 additions & 2 deletions automol/tests/test_graph_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@pytest.mark.parametrize(
"smarts, rcts_smi, nrxns",
[(graph.enum.Smarts.abstraction, "CCC.[OH]", 2)],
[(graph.enum.ReactionSmarts.abstraction, "CCC.[OH]", 2)],
)
def test__reactions(smarts, rcts_smi, nrxns):
"""Test reactions."""
Expand All @@ -16,4 +16,4 @@ def test__reactions(smarts, rcts_smi, nrxns):


if __name__ == "__main__":
test__reactions(graph.enum.ReactionTemplate.abstraction, "CCC.[OH]", 2)
test__reactions(graph.enum.ReactionSmarts.abstraction, "CCC.[OH]", 2)
10 changes: 5 additions & 5 deletions automol/tests/test_reac_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@


@pytest.mark.parametrize(
"smarts, rct_smis, prd_smis, nrxns",
"smarts, rct_smis, nrxns",
[
(graph.enum.Smarts.abstraction, ["C1=CCCC1", "[OH]"], None, 3),
(graph.enum.ReactionSmarts.abstraction, ["C1=CCCC1", "[OH]"], 3),
],
)
def test__from_smiles(smarts, rct_smis, prd_smis, nrxns):
def test__from_smiles(smarts, rct_smis, nrxns):
"""Test reac.from_smiles."""
rxns = reac.enum.from_smiles(smarts, rct_smis, prd_smis)
rxns = reac.enum.from_smiles(smarts, rct_smis)
assert len(rxns) == nrxns, f"\nrxns = {rxns}"


if __name__ == "__main__":
test__from_smiles(graph.enum.Smarts.abstraction, ["C1=CCCC1", "[OH]"], None, 3)
test__from_smiles(graph.enum.ReactionSmarts.abstraction, ["C1=CCCC1", "[OH]"], 3)

0 comments on commit e9c65c2

Please sign in to comment.