orthonym.rules.phosphorus#

Note

Internal API. Names and behaviour may change between releases.

Phosphorus compound naming rules per IUPAC 2013.

Handles: - Phosphines (R3P): substitutive naming with “phosphane” (PIN, not “phosphine”) - Phosphine oxides (R3P=O): functional class naming - Phosphonic acids (RP(O)(OH)2): suffix -phosphonic acid - Phosphinic acids (R2P(O)OH): suffix -phosphinic acid - Phosphate esters: functional class naming (methyl phosphate) - Phosphanyl prefix for P as substituent (e.g., diphenylphosphanyl)

orthonym.rules.phosphorus.name_phosphine(mol, phosphorus_idx)#

Name a phosphine using substitutive nomenclature.

IUPAC 2013 PIN: “phosphane” (not “phosphine”) - methylphosphane, dimethylphosphane, trimethylphosphane - triphenylphosphane, diphenylmethylphosphane

Parameters:
  • mol – RDKit Mol object

  • phosphorus_idx (int) – Index of phosphorus atom

Returns:

Substitutive name like “trimethylphosphane”, or None if not a simple phosphine

Return type:

str | None

orthonym.rules.phosphorus.name_phosphine_oxide(mol, phosphine_oxide_atoms)#

Name a phosphine oxide using substitutive nomenclature.

IUPAC: trimethylphosphane oxide (substitutive, preferred)

Parameters:
  • mol – RDKit Mol object

  • phosphine_oxide_atoms (Tuple[int, ...]) – Atom indices from SMARTS match

Returns:

Name like “trimethylphosphane oxide”, or None if not simple

Return type:

str | None

orthonym.rules.phosphorus.name_phosphonous_acid(mol, match_atoms)#

R-P(OH)2 -> phenylphosphonous acid substituent-prefix PIN).

orthonym.rules.phosphorus.name_phosphinous_acid(mol, match_atoms)#

R2P(OH) -> diphenylphosphinous acid substituent-prefix PIN).

orthonym.rules.phosphorus.name_arsonous_acid(mol, match_atoms)#

R-As(OH)2 -> phenylarsonous acid (BB L35413 preselected name).

orthonym.rules.phosphorus.name_arsinous_acid(mol, match_atoms)#

R2As(OH) -> diphenylarsinous acid (BB L35465 preselected PIN).

orthonym.rules.phosphorus.name_stibonous_acid(mol, match_atoms)#

R-Sb(OH)2 -> phenylstibonous acid (BB L35467 preselected PIN).

orthonym.rules.phosphorus.name_stibinous_acid(mol, match_atoms)#

R2Sb(OH) -> diphenylstibinous acid (BB L35435 preselected name).

orthonym.rules.phosphorus.name_arsonic_acid(mol, match_atoms)#

R-As(=O)(OH)2 -> methylarsonic acid (BB L36051 preselected name).

orthonym.rules.phosphorus.name_arsinic_acid(mol, match_atoms)#

R2As(=O)OH -> dimethylarsinic acid (BB L36052 preselected name).

orthonym.rules.phosphorus.name_stibonic_acid(mol, match_atoms)#

R-Sb(=O)(OH)2 -> methylstibonic acid (BB L36054 preselected name).

orthonym.rules.phosphorus.name_stibinic_acid(mol, match_atoms)#

R2Sb(=O)OH -> dimethylstibinic acid (BB L36054 preselected name).

orthonym.rules.phosphorus.name_phosphonic_acid(mol, phosphonic_atoms)#

Name an organyl phosphonic acid in substituent-prefix mode (IUPAC PIN).

R-P(=O)(OH)2 -> methylphosphonic acid / ethylphosphonic acid / phenylphosphonic acid. Phosphonic acid is a functional parent (HP(=O)(OH)2) whose central-atom H is substituted by the organyl group; the PIN is therefore {R-yl}phosphonic acid — NOT the parent-hydride-stem form {R-ane}phosphonic acid (ethanephosphonic), which the generic suffix assembler would otherwise emit (it correctly serves the genuine suffix acids like ethanesulfonic).

Mirrors:func:name_phosphinic_acid. Returns None (fail-closed) when the single organyl substituent is not a clean simple alkyl / aryl — the caller then defers to the generic path (no regression for complex parents).

Thin wrapper over the element-generic:func:_name_pnictogen_onic_acid, which the arsenic/antimony analogues share.

orthonym.rules.phosphorus.name_acyloxy_phosphonic_acid(mol)#

(BB L36999): a mixed acyl/phosphoric anhydride named SUBSTITUTIVELY as an (acyloxy)phosphonic acid (acid is senior to anhydride, so the substitutive acid name is the PIN, NOT the functional-class acetic phosphoric monoanhydride).

CH3-CO-O-P(O)(OH)2 -> (acetyloxy)phosphonic acid

Structural shape: exactly one NEUTRAL P of degree 4 bearing one P=O, two -OH and one -O-acyl (the bridging O joins P to a carbonyl carbon). The fourth position of phosphonic acid HP(=O)(OH)2 — normally the central-atom H (methylphosphonic) — is here substituted by the acyloxy group.

Fail-closed (returns None) off this shape: any C-P bond (genuine organophosphonic acid -> the suffix path), an -O-alkyl bridge (a phosphate ester, not an anhydride), fewer/more than two -OH, a charge, or an acyl group the acyloxy namer cannot spell. Pure: no mol mutation.

orthonym.rules.phosphorus.name_phosphane_carboxylic_acid(mol)#

(BB 39117): a carboxylic acid -C(=O)OH on a Group-15 P/As/Sb parent hydride is expressed as the added-carbon -carboxylic acid suffix on the phosphane/arsane/stibane parent hydride — NOT a phosphanyl prefix on methanoic acid (the generic acid namer’s non-PIN 1-phosphanylmethanoic acid):

H2P-COOH -> phosphanecarboxylic acid (PIN)

Exactly analogous to the added-carbon -carboxylic acid on carbocycles (cyclohexanecarboxylic acid) and to polyazane’s azane-1-carboxylic acid.

Scope (fail-closed graph classifier, NOT SMARTS): exactly ONE bare carboxyl carbon (=O + -OH + one pnictogen neighbour, degree 3) on a PURE homonuclear P/As/Sb chain (H-saturated, standard bonding number 3, neutral, acyclic). A P=O (phosphonic/phosphinic, retained acids), a lambda5 hydride, a ring, a second characteristic group, a stray heteroatom, a charge/radical, or an interior carboxyl attachment fails a guard and cascades onward. Pure: no mol mutation.

orthonym.rules.phosphorus.name_phosphinic_acid(mol, phosphinic_atoms)#

Name a phosphinic acid with dialkyl/aryl prefix and phosphinic acid suffix.

R2P(O)(OH) -> dialkylphosphinic acid, diphenylphosphinic acid

Parameters:
  • mol – RDKit Mol object

  • phosphinic_atoms (Tuple[int, ...]) – Atom indices from SMARTS match

Returns:

Name like “dimethylphosphinic acid”, or None if not simple

Return type:

str | None

Thin wrapper over the element-generic:func:_name_pnictogen_inic_acid, which the arsenic/antimony analogues share.

orthonym.rules.phosphorus.name_phosphate_ester(mol, phosphorus_idx)#

Functional-class name for an ester of a phosphorus oxo-acid.

Covers phosphoric-acid esters (mono/di/tri: methyl dihydrogen phosphate, dimethyl hydrogen phosphate, trimethyl phosphate), phosphonate esters (dimethyl methylphosphonate — one P-C bond), phosphinate esters (methyl dimethylphosphinate — two P-C bonds), and phosphite triesters (triethyl phosphite — trivalent P, no P=O). The acidic H that remains on a partial ester IS cited (hydrogen/dihydrogen, /; the older code dropped it and emitted the anion name dimethyl phosphate for a NEUTRAL diester — a wrong (charged) structure ‘s skeleton block does not catch. Fail-closed (None) off the clean neutral single-P shape, or if any owner / C-ligand is not spellable or the name would not cover every atom. Thio (P=S, P-S) is out of scope here -> None (honest defer).

orthonym.rules.phosphorus.name_phosphate_ester_anion(mol, phosphorus_idx)#

Functional-class name for the ANION of a P-oxoacid acid-ester.

Sibling of:func:name_phosphate_ester for the deprotonated form. The protonation word is derived IN PLACE from the surviving free -OH count (_HYDROGEN_MULT): the [O-] carry the charge and are NOT counted as hydrogens, so a monoester dianion (0 OH) -> dodecyl phosphate, a monoanion (1 OH) -> dodecyl hydrogen phosphate, a diester monoanion (0 OH, 2 owners) -> diethyl phosphate. Never neutralize-then-rename . Requires at least one terminal [O-] (else -> None, the NEUTRAL producer owns that shape) and that the molecule’s only charges are those [O-]. Fail-closed (None) off the clean single-P ester-anion shape (thio P=S/P-S, ring P, P-N, P-O-P bridge, no ester owner, unspellable owner, incomplete coverage).

orthonym.rules.phosphorus.get_phosphanyl_prefix(mol, phosphorus_idx, exclude_atoms=None)#

Generate IUPAC phosphanyl prefix string.

Used when phosphorus is a substituent on a parent chain/ring. Characterizes C/c neighbors of P (excluding parent attachment atoms) and builds the prefix.

Examples

-PPh2 -> “diphenylphosphanyl” -PMe2 -> “dimethylphosphanyl” -PMePhPh -> not typical, but “methyldiphenylphosphanyl” -PMe -> “methylphosphanyl”

Parameters:
  • mol – RDKit Mol object

  • phosphorus_idx (int) – Index of phosphorus atom

  • exclude_atoms (set) – Optional set of atom indices to exclude from substituent counting (typically the parent ring/chain atoms that P is bonded to).

Returns:

Prefix string like “diphenylphosphanyl”, or None if no valid substituents

Return type:

str | None

orthonym.rules.phosphorus.name_phosphanyl_substituent(mol, frag_atoms, attach_idx)#

: name a phosphorus-rooted substituent on an acyclic parent.

-PH2 -> phosphanyl; -PR2 -> dialkyl/diarylphosphanyl (via get_phosphanyl_prefix()). Wired into the chain/acid substituent path (name_substituent Tier 1.93) so a trivalent-P substituent on a carbon chain is cited as the phosphanyl prefix rather than dropped.

Fail-closed collision guard load-bearing case): fires ONLY when attach_idx is a NEUTRAL, radical-free phosphorus whose every in-fragment heavy neighbour is a single-bonded carbon (organyl) — so a phosphoryl / phosphonic P=O (bonding number 5, but with an O neighbour) is EXCLUDED and left to the oxoacid subsystem. Standard-valence (bonding number 3) only in this task; the λ5 hydride branch is added in Task 3.

Non-standard valence: only the all-H λ-hydride (-PH4) is named here as lambda5-phosphanyl /; house ASCII lambda5 with NO internal locant on a mononuclear prefix). Any other non-standard shape (organyl λ5, phosphoryl/phosphonic P=O) fails closed.

Returns None (caller falls through, fail-closed) for any non-P attachment, a P bearing a heteroatom / multiple bond, or an unrecognised organyl ligand.

orthonym.rules.phosphorus.name_acyl_prefix_substituent(mol, frag_atoms, attach_idx)#

: name a mononuclear P/As/Sb ACYL group carried as a SUBSTITUENT prefix on a senior parent, CONSUMING the shared acyl_prefix_for table (never re-spelling the acyl base).

The central atom (attach_idx) is a neutral, radical-free P/As/Sb that bears EXACTLY ONE terminal =E’ multiple bond – =O -> oxo, =S -> thio, =NH -> imido, |=N (triple) -> nitrido – and attaches to the parent by a SINGLE bond leaving the fragment (the yl-bond). The acyl base (-oryl / -onoyl / -inoyl, or its thio/imido/nitrido sibling) is chosen by the SKELETAL count = the number of in-fragment P-C(organyl) / P-H ligands (0 -> -oryl, 1 -> -onoyl, 2 -> -inoyl), exactly the R,R'-E(=E')OH acid skeleton of where R/R’ = H or organyl.

Those organyl ligands ARE the -inoyl base’s own defining substituents, so they are cited WITHOUT a P-locant (BB L36080 methyl(phenyl)arsinoyl, L39255 dimethylphosphinothioyl). Any remaining in-fragment heteroatom ligand (-OH -> hydroxy, -SH -> sulfanyl, -OR -> <R>oxy) is an acid-derived residual cited as a front prefix (BB L39242 hydroxyarsoryl).

Returns None (caller falls through, fail-closed) for a trivalent phosphanyl / arsanyl (no =E’), a multiplicative >P(=E)< bridge (>1 attachment, named by rules/multiplicative.py), an untabled cell, or a residual it cannot name. The top-level OPSIN round-trip gate voids any mis-spelling, so a wrong skeletal / residual guess degrades to an abstention, never a wrong structure.

orthonym.rules.phosphorus.name_phosphoanhydride_oxy_substituent(mol, o_idx, from_idx, _depth=0)#

method (1): name an -O-P(=O)(…)… phosphoanhydride subgraph as a recursive phosphoryl-oxy substituent prefix.

o_idx is the ester/bridging oxygen bonded to the parent atom from_idx; the oxygen’s other neighbour must be a phosphorus. Returns a substituent string ENDING in oxy — 'phosphonooxy' for a terminal -O-P(=O)(OH)2, or the nested '[<branches>phosphoryl]oxy' for a P-O-P(-O-P…) anhydride bridge — or None (fail-closed) for any P outside the neutral mono-oxo phosphoryl class (a P-C phosphonate, a no-oxo phosphite, a charged/oxido/radical P, etc.), which carry their own nomenclature.

This is the valid SYSTEMATIC form the Blue Book lists as alternative (1) under

(the Blue Book Blue Book); the PIN (method 2) uses the

…diphosphoxan-1-yl skeletal-replacement parent and is a future PIN-tier build. Emitted only on the best-effort path, where a valid systematic name is preferred over silence. 0-wrong is preserved by the top-level /OPSIN round-trip gate. Full record: internal notes.

orthonym.rules.phosphorus.name_phosphoxane_oxy_substituent(mol, o_idx, from_idx)#

method (2) — the PIN: name an -O-P(=O)(…)… phosphoanhydride bridge as the skeletal-replacement …phosphoxan-1-yl parent, returning '(<subs>[n]phosphoxan-1-yl)oxy'.

diphosphoxane/triphosphoxane/… are preselected parent hydrides, the Blue Book Blue Book,2971): a chain of n phosphorus atoms bridged by (n-1) oxygens, numbered P at the odd locants 1,3,5,…,(2n-1). Each P carries its =O (oxo), its -OH (hydroxy), any -O-R ester ({R}oxy), and a λ⁵ designator (all P are pentavalent). The attachment is at.

This is the PREFERRED form (method 2, the PIN) over the recursive-phosphoryl method-1 (name_phosphoanhydride_oxy_substituent()). Returns None (fail-closed) for any P outside the neutral mono-oxo phosphoryl anhydride class (P-C phosphonate, no-oxo phosphite, charged/oxido P, branched P-O-P), so the caller can fall back to method-1. RT-verified through OPSIN 2.9.0 for di/tri/ tetraphosphoxane. Record: internal notes.

orthonym.rules.phosphorus.get_phosphorus_prefix(fg_name)#

Get prefix form for phosphorus functional groups.

Returns:

Prefix string, or None if group uses functional class naming

Return type:

str | None

orthonym.rules.phosphorus.carbon_free_phospho_prefix(mol, sub_atoms, attach_idx)#

A CARBON-FREE -P(=O)(OH)2 / -P(=O)(O-)2 substituent fragment -> its RETAINED detachable prefix.

phosphono, the neutral di-hydroxy group) and phosphonato

preselected prefix for the -P(O)(O-)2 di-anion, BB:41213).

Why this exists: the recursive substituent path (name_substituent_fragment Step 4) names a fragment by round-tripping it through the WHOLE-molecule namer, but the bare P-oxo fragment O=P(O)O has NO carbon, so name_compound classifies it inorganic compound (not supported) and the fragment was DROPPED (substituent_recursion_depth_exceeded). The neutral prefix is exactly the one the FG-on-parent-chain path already emits via get_phosphorus_prefix('phosphonic_acid') -> 'phosphono'; this restores it for the fragment shape the whole-molecule reject cannot see.

Fail-closed (None) for anything that is not exactly this shape: attach atom is P; the fragment is carbon-free with a single P centre; that P carries exactly one =O and two single-bonded O; and the two single O are BOTH neutral hydroxyl (-> phosphono) or BOTH oxido anions (-> phosphonato). A mixed/partial charge, an extra H on P (phosphinic), or a second P (anhydride) declines here and falls through to the existing guards. The top-level /OPSIN validity gate voids any non-RT composed name, so 0-wrong holds regardless.