orthonym.rules.organometallics#
Note
Internal API. Names and behaviour may change between releases.
IUPAC organometallic seniority + naming rules (a phase).
- This module defines ORGM-specific seniority cascade SEPARATE from the
carbon-organic seniority in src/orthonym/rules/seniority.py per
internal notes hard invariant (ZERO edits to seniority.py).
The two cascades NEVER share data structures; the only common file is src/orthonym/data/organometallics.py (NEW; ORGM-exclusive).
Anti-patterns to avoid (PATTERNS lines 256-259): - forbids any import path pointing at rules/seniority (relative
..rules dot-seniority or absolute orthonym dot rules dot seniority); this enforces ZERO cross-contamination with the carbon-organic seniority cascade. The grep gate in Plan-02 task 02-03 asserts neither import line exists in this module.
NEVER add ORGM entries to the existing SENIORITY_ORDER list in seniority.py — define a NEW ORGM_LIGAND_ORDER in this file instead.
NEVER call name_compound(…) recursively from assemble_organometallic_name(…) — recursion path is OUTER CFR → handler → rules → data; no upward call.
a phase (first scope-expansion phase per -07).
- orthonym.rules.organometallics.select_ligand_naming(ligand_group, hapticity, style='pin')#
Generate the IUPAC name for a single ligand with η-notation.
STUB BODY (Plan-02): returns empty string. Plan-03 implements per RESEARCH + AUDIT SMARTS catalog.
Algorithm (Plan-03 implementation): 1. Look up ligand_group.ligand_canonical_smiles in LIGAND_NAMES. 2. If hapticity > 1 OR ligand in LIGAND_ETA_DEFAULTS: prefix η<N>-. 3. Apply multiplicative prefix (bis-, tris-, etc.) per outer caller.
- orthonym.rules.organometallics.assemble_organometallic_name(metal_complex, mol, style='pin')#
Assemble systematic IUPAC name for a metal complex per Salzer 1999
Plan-03 implementation: Tier-1 Cp2 metallocene branch (commit 03-01). Subsequent commits 03-02/03/04 add Tier-3/2/4 branches.
Returns: (full_name, metal_name_part, ligand_tree_nodes) per RESEARCH lines 799-815. The handler wraps this in NameTreeNode.
Returns None to signal cascade-continuation when: - metal_complex.is_multimetal (a phase deferred per Risk R-08) - Stock-notation lookup fails for the (metal, ligand_class) tuple - The compound’s topology doesn’t match any tier branch yet
- orthonym.rules.organometallics.organometallic_charge_conserved(full_name, mol)#
0-wrong charge-conservation veto for an assembled organometallic name.
True iff what the name states about charge holds for the WHOLE input. A name that OPSIN reads states the formal charge of the structure OPSIN builds from it (
_opsin_read_net_charge), whether the charge sits in a closing number, a suffix (‘-ate’) or a prefix (‘sulfonato’): it must equal the formal charge of the input. A name OPSIN cannot read (the eta / additive names) states its charge by its closing word (stated_charge): a stated net charge equals the formal charge of the input; a Stock number equals the formal charge of the metal (the complex’s charge is then that number plus the charges of the ligands as drawn, so it follows); a name with neither describes a neutral compound and the input must be neutral. A Stock number is a statement about the metal alone, so it is always checked against the metal. The formula veto_organometallic_conservesproves the pi-ligand atoms; it cannot see charge. A dot-separated input such as[Fe].c1cc[cH-]c1.c1cc[cH-]c1(net -2) or[Cr+].c1ccccc1.c1ccccc1(net +1) has the same ligand atoms as the neutral complex, so the additive names ‘bis(eta5-cyclopentadienyl)iron’ / ‘bis(eta6-benzene)chromium’ passed every other check and described a different species (and the systematic style’s default Stock number ‘iron(II)’ states a metal charge the input does not have). The pin tier ships these names past OPSIN (namer._ORGANOMETALLIC_ADDITIVE_PIN_RE), so this predicate is the only certificate of the charge. The first version read only the closing number and so declined a correct name whose ligand states the charge, ‘(4-sulfonatophenyl)mercury chloride’ for the sulfonate anion.The test is on the charge, NOT on whether the metal-ligand bonds are drawn: dot-separated pi-ligands are the SMILES convention for sandwich complexes and the balanced forms (‘[Fe+2].c1cc[cH-]c1.c1cc[cH-]c1’ = ferrocene, ‘c1ccccc1.[Cl-].[Cl-].[Fe+2]’, net 0; ‘[Fe+3].Cp-.Cp-’ = ‘bis(eta5-cyclopentadienyl) iron(III)’, the ferrocenium cation) name correctly and keep their names.
Governing rule: (organometallics) is out of scope, so the rule is the project’s core principle 2 (never emit a wrong structure). The Blue Book states a charged complex with a charge number: ‘Compounds with at least one metal-carbon single bond’ (the Blue Book), example ‘pentaammine(ethanido) osmium(1+) chloride’; (:39799), example ‘tricarbonyl(eta7- cycloheptatrienylium)molybdenum(1+)’. An anion or a cation of an organic ligand states its charge with a suffix: ‘Anions derived from acids’ (the Blue Book, ‘benzoate’, ‘sulfonate’) and ‘Cationic centers on characteristic groups’ (:41413); an OPSIN reading counts it.
- orthonym.rules.organometallics.stated_charge(full_name)#
What the assembled organometallic name states about charge, as
(kind, n):('net', n)the charge of the whole complex (its Ewens-Bassett number;n= 0 for a name without one, which describes a neutral compound) or('oxidation', n)the oxidation number of the metal (its Stock number).