orthonym.assembly.composition_tier#
Note
Internal API. Names and behaviour may change between releases.
Best-effort composition tier (slice 1).
When a producer builds an atom-short parent name on the best-effort tier, this module finishes it: it computes which heavy atoms the parent actually accounts for, isolates the uncovered remainder, and (in a later step) names that remainder as substituent prefixes and composes a whole-molecule name.
Design + provenance: docs/the workflow tooling/specs/2026-08-05-best-effort-composition-tier-design.md
and docs/the workflow tooling/plans/2026-08-05-best-effort-composition-slice1.md. The covered-atom
source was settled by the Task-1/2 trace: features.principal_chain ALONE undercounts (it misses
the -ol oxygen of propan-1-ol → 3/4), so coverage must also include the principal-group
atoms. Every function here is pure (no OPSIN, no I/O).
- orthonym.assembly.composition_tier.parent_covered_atoms(mol, features)#
Heavy-atom indices the parent name accounts for.
Coverage = the principal chain plus every heavy atom of the principal characteristic group (the suffix).
principal_group_atomsis a list of tuples, each tuple holding all atom indices of one group occurrence — e.g. carboxylic acid[(2, 3, 4)]= C,O,O, alcohol[(3, 2)]= O plus its attachment carbon. Both shapes are handled by taking every integer index in every tuple. The attachment carbon is often already in the chain; the set union de-duplicates it.⚠ This is what the parent NAME covers, not what perception saw — a dropped substituent is perceived (it lives in
features.substituents) but is NOT in this set, which is exactly how:func:uncovered_fragments finds the remainder.
- orthonym.assembly.composition_tier.uncovered_fragments(mol, covered)#
Heavy atoms not in
covered, split into connected components (by heavy-atom bonds).Each returned tuple is one connected uncovered fragment — a candidate substituent whose atoms the parent dropped. Order within a tuple is ascending atom index; the list is ordered by each fragment’s lowest atom index, so the result is deterministic.
- orthonym.assembly.composition_tier.fragment_attachment_atom(mol, fragment)#
The atom inside
fragmentbonded to an atom outside it (the free-valence / attach atom).name_substituentexpects a fragment-side attachment index. When a fragment has several external bonds (rare for a dropped substituent), the lowest such atom index is chosen for determinism; when it has none (a disconnected component — should not happen for a real substituent), the lowest atom index is returned.