orthonym.perception.ions#

Note

Internal API. Names and behaviour may change between releases.

Ion and radical detection for IUPAC nomenclature.

This module provides functions to detect and classify charged and radical species. Detection happens early in the naming pipeline to route molecules to the correct naming path (neutral, ion, zwitterion, salt, or radical).

IUPAC 2013 rules: - Cations: named with suffix -ium or -ylium - Anions: named with suffix -ide, -ate, or -uide - Radicals: named with suffix -yl - Salts: named as “cation anion” (e.g., sodium acetate) - Zwitterions: named as neutral compounds with +/- indicated

orthonym.perception.ions.detect_species_type(mol)#

Memoising front of:func:_detect_species_type_impl (perf lever A7, 2026-09-13).

The dispatch predicates (_is_salt, _is_zwitterion, _is_organometallic, _is_cation_quaternary,…) and _perceive call this about 13 times per pipeline pass on the SAME Mol (30,038 calls per 300 molecules, 3.5 s). The value depends on the atoms’ formal charges and radical electrons, which can be edited in place on a Chem.Mol, so that live signature is part of the memo key; connectivity cannot change without an RWMol, which molcache never caches. Outside a naming scope this is a plain call.

orthonym.perception.ions.get_ion_sites(mol, exclude_internal=True)#

Get all charged atom sites in a molecule.

Parameters:
  • mol – RDKit Mol object

  • exclude_internal – If True (default), exclude atoms whose formal charges are bonding features of prefix-only groups (nitro, N-oxide, azide, diazo) per IUPAC

Returns:

Dictionary with ‘cations’ and ‘anions’ lists. Each entry contains: - atom_idx: int - atom index in molecule - charge: int - formal charge (+1, -1, +2, etc.) - element: str - element symbol (N, O, C, etc.) - hybridization: str - hybridization state (SP3, SP2, etc.) - n_hydrogens: int - number of attached hydrogens

Return type:

Dict[str, List[Dict[str, Any]]]

Example

>>> mol = Chem.MolFromSmiles('[NH4+]')
>>> sites = get_ion_sites(mol)
>>> sites['cations'][0]['element']
'N'
>>> sites['cations'][0]['charge']
1
orthonym.perception.ions.get_radical_sites(mol)#

Get all radical centers in a molecule.

Parameters:

mol – RDKit Mol object

Returns:

List of radical site dictionaries, each containing –

  • atom_idx: int - atom index in molecule

  • n_electrons: int - number of unpaired electrons (1, 2, 3)

  • element: str - element symbol

  • radical_type: str - ‘monovalent’ (1), ‘divalent’ (2), ‘trivalent’ (3)

  • hybridization: str - hybridization state

Return type:

List[Dict[str, Any]]

Example

>>> mol = Chem.MolFromSmiles('[CH3]')
>>> sites = get_radical_sites(mol)
>>> sites[0]['element']
'C'
>>> sites[0]['radical_type']
'monovalent'
orthonym.perception.ions.parse_salt_fragments(mol)#

Parse a salt into its cation and anion fragments.

For multi-component salts (dot-separated SMILES), this separates the positively and negatively charged fragments.

Parameters:

mol – RDKit Mol object (may contain multiple fragments)

Returns:

Dictionary with ‘cations’, ‘anions’, and ‘neutrals’ lists. Each entry contains: - mol: RDKit Mol object for the fragment - charge: int - net charge of the fragment - smiles: str - canonical SMILES of the fragment

Return type:

Dict[str, List[Dict[str, Any]]]

Example

>>> mol = Chem.MolFromSmiles('[Na+].[O-]C(C)=O')
>>> frags = parse_salt_fragments(mol)
>>> len(frags['cations'])
1
>>> len(frags['anions'])
1
>>> frags['cations'][0]['smiles']
'[Na+]'