diff --git a/src/rxn/chemutils/miscellaneous.py b/src/rxn/chemutils/miscellaneous.py index f2b1fd3..a86f751 100644 --- a/src/rxn/chemutils/miscellaneous.py +++ b/src/rxn/chemutils/miscellaneous.py @@ -317,3 +317,28 @@ def merge_reactions(*reactions: ReactionEquation) -> ReactionEquation: agents.extend(reaction.agents) products.extend(reaction.products) return ReactionEquation(reactants=reactants, agents=agents, products=products) + + +def mol_has_atom_mapping(mol: Mol) -> bool: + """ + Whether at least one atom of an RDKit Mol contains an atom map number. + + Args: + mol: RDKit Mol. + """ + atom: Atom + for atom in mol.GetAtoms(): + if atom.GetAtomMapNum() != 0: + return True + return False + + +def smiles_has_atom_mapping(smiles: str) -> bool: + """ + Whether at least one atom of a compound SMILES contains an atom map number. + + Args: + smiles: compound SMILES. + """ + mol = smiles_to_mol(smiles, sanitize=False) + return mol_has_atom_mapping(mol) diff --git a/tests/test_miscellaneous.py b/tests/test_miscellaneous.py index 3a31795..1fff191 100644 --- a/tests/test_miscellaneous.py +++ b/tests/test_miscellaneous.py @@ -15,6 +15,7 @@ merge_reactions, remove_chiral_centers, remove_double_bond_stereochemistry, + smiles_has_atom_mapping, sort_any, ) from rxn.chemutils.reaction_equation import ReactionEquation @@ -260,3 +261,20 @@ def test_merge_reactions() -> None: assert merge_reactions(r1, r2, r3, r4) == ReactionEquation( ["A", "B", "F"], ["C", "G", "H"], ["D", "I"] ) + + +def test_smiles_has_atom_mapping() -> None: + assert smiles_has_atom_mapping("[CH3:9][CH:8]([CH3:10])c1ccccc1") + assert smiles_has_atom_mapping("CCO[CH3:9]") + assert smiles_has_atom_mapping("C[CH3:9].O") + + assert not smiles_has_atom_mapping("CC") + assert not smiles_has_atom_mapping("C[CH3]") + assert not smiles_has_atom_mapping("C[12CH3]") + + # Note: does not care about valence, but SMILES must be valid + # invalid valence -> call succeeds: + assert smiles_has_atom_mapping("CF(C)CC[C:9]") + # invalid SMILES -> call raises: + with pytest.raises(InvalidSmiles): + _ = canonicalize_any("[CH3:9]C(")