orthonym.rules.ring_unsaturation#
Note
Internal API. Names and behaviour may change between releases.
Ring-unsaturation locant rendering for von Baeyer / spiro parents.
One producer for BOTH bond orders, replacing two inline blocks that disagreed.
Why this module exists#
vonbaeyer_universal.analyze_cage_universal recomputed the double-bond locants
into the von-Baeyer COMPOUND form – f"{lo}({hi})" when the bond’s two atoms
are not consecutively numbered, e.g. octalin’s 1(6) – but left the
triple-bond locants exactly as polycyclic.get_polycyclic_unsaturation produced
them: min(loc1, loc2), a bare lower locant with no compound form and no
guard. A cage carrying a non-consecutively-numbered triple bond would therefore
have emitted a -yne locant denoting a DIFFERENT bond than the one present.
The spiro sibling refused that case; the cage path was silent. Same computation,
two implementations, one of them unsound – so it becomes one function used by
both.
polycyclic.get_polycyclic_unsaturation is deliberately NOT changed: it is
shared with the PIN von-Baeyer stack, whose emitted strings are gold-locked, and
that stack consumes bare ints. The soundness fix belongs where the general tier
consumes the locants.
The compound locant is a DOUBLE-BOND rule (1))#
(1) is worded for double bonds only: “A compound locant is used for a
double bond if the locants of the atoms at each end of the bond do not differ by
a value of one. When a compound locant is required, the higher locant is cited in
parentheses.” The same double-bond-only wording appears in (3) and
. Every -yne example in the Blue Book carries a PLAIN locant –
bicyclo[14.3.1]icosa-11,13,18-trien-2-yne,
bicyclo[11.3.1]heptadec-2-en-11-yne – with the parentheses in those very
names appearing only on the -ene component. So the bare lower locant is
CORRECT for a triple bond on every structure the Blue Book covers, and there is
no sanctioned x(y) form to fall back on.
Why the non-consecutive branch refuses instead of citing the bare locant#
A non-consecutively-numbered triple bond is provably unreachable for standard bonding numbers: (a bridge connects two bridgeheads) makes von Baeyer numbering a concatenation of runs each ending at a bridgehead, so every non-consecutively-numbered bond is incident to a bridgehead; defines a bridgehead as having >= 3 skeletal neighbours; a C(triple)C carbon has exactly 2 sigma bonds. A bridgehead therefore can never be a triple-bond terminus.
Reaching that state consequently means the UPSTREAM NUMBERING is wrong – and
emitting the bare lower locant there would be a genuine wrong-structure emission,
because a reader parses -8-yne as the 8-9 bond. So the branch fails closed:
it is an assertion against a numbering bug, not a nomenclature fallback. The
structural claim is tested (test_ring_unsaturation.py) rather than assumed.
One documented, NOT ESTABLISHED hole: a lambda-n heteroatom could in principle be
3-connected AND triply bonded, which would make a non-consecutive yne structurally
possible. The Blue Book gives no rule for citing that bond, so the fail-closed
branch is what covers it – correctly, by abstaining. _YNE_COMPOSITE_ALLOWED
is the one-line flip should such a rule ever be cited; it must stay False
until then, since no compound -yne locant exists in the literature.
- class orthonym.rules.ring_unsaturation.RingUnsaturation(double_pairs, triple_pairs, double_locants, triple_locants)#
Bases:
objectRing double/triple bonds as both raw locant pairs and display strings.
double_pairs/triple_pairssorted
(low, high)locant pairs. The general engine’s oxo/ene valence guard consumes the double pairs in exactly this form: both endpoints of a ring double bond are termini a=O/=Ncannot share.double_locants/triple_locantsdisplay strings in the same order –
str(lo)whenhi == lo + 1, else the compoundf"{lo}({hi})".triple_locantsis always plain: a non-consecutive triple bond refuses before this is built.
- double_pairs: Tuple[Tuple[int, int], ...]#
- triple_pairs: Tuple[Tuple[int, int], ...]#
- double_locants: Tuple[str, ...]#
- triple_locants: Tuple[str, ...]#
- orthonym.rules.ring_unsaturation.render_ring_unsaturation(mol, numbering)#
Render every ring multiple bond of
molon the locants innumbering.Only bonds whose BOTH atoms carry a locant are considered – an exocyclic or substituent multiple bond is not ring unsaturation and is expressed elsewhere.
- Parameters:
mol – RDKit Mol, already kekulized if the ring system is mancude (an aromatic bond is neither DOUBLE nor TRIPLE and would be skipped).
numbering (Dict[int, int]) – atom index -> ring locant (1-based).
- Returns:
RingUnsaturation, orNoneto refuse – currently only for a non-consecutively-numbered triple bond (see the module docstring).- Return type:
RingUnsaturation | None