orthonym.validation.e1_certificate#

Note

Internal API. Names and behaviour may change between releases.

: E1 atom-coverage certificate.

Verifies a GeneralEngineResult’s atom->token partition: every heavy atom of the molecule is bound by EXACTLY ONE token, every token occurs in the emitted name, and (G1 scope) the molecule is neutral. Pure Python + RDKit – no Java, no OPSIN. This is the load-bearing “no silent atom drop” gate the legacy count-based validation/atom_coverage.py never was; that legacy module is untouched and unrelated.

class orthonym.validation.e1_certificate.E1Verdict(ok: 'bool', reason: 'str')#

Bases: object

ok: bool#
reason: str#
orthonym.validation.e1_certificate.verify_atom_coverage(mol, name, atom_id_groups, allow_charged=True)#

Producer-side atom-COVERAGE close (the task-W2 reusable template).

A thin wrapper over:func:_verify_partition for the recurring producer situation the W2 jar-absent-proper fix addresses: “here are the atom groups my emitted ``name`` accounts for — confirm together they cover EVERY heavy atom of ``mol``, else I must decline (fail-closed) rather than ship a name that silently dropped atoms.”

This is the OPSIN-free, jar-independent guard that catches an atom-drop at CONSTRUCTION (defense-in-depth: jar-present would also catch it, but only after a JVM round-trip; jar-absent nothing else does). It reuses the E1 partition primitive rather than duplicating a coverage check (a project rule: extend, don’t duplicate) and is deliberately scoped to the COVERAGE axis:

  • Groups are DEDUPLICATED before binding, so a benign double-listing of an atom never trips the partition’s bound twice refusal (a false void that would cost breadth — the fix must void ONLY genuine drops).

  • Each group is bound under the EMPTY token, so the token-in-name and element_soundness chemistry checks are SKIPPED here. Those two checks presuppose a GeneralEngineResult-style (token, atom_ids) stream whose token strings are reconstructable; a legacy composer producer building the partition from atom-index data alone cannot supply faithful token strings (locants/elision/enclosing-marks are added around morphemes at assembly time), and a mismatched token would false-void a CORRECT name. Coverage is the only axis this template owns.

  • allow_charged defaults True: this template checks atom coverage, not the G1 charge scope, so a legitimately-charged parent is never voided for a reason unrelated to an atom drop.

Parameters:
  • indices (* atom_id_groups -- iterable of iterables of heavy-atom) – name-piece the producer emitted (ring atoms, each named substituent’s atoms, suffix atoms,…). Their UNION is the accounted set.

  • per (one) – name-piece the producer emitted (ring atoms, each named substituent’s atoms, suffix atoms,…). Their UNION is the accounted set.

Returns an:class:E1Verdict; .ok is False (with an unbound heavy atoms reason) when any heavy atom is left unaccounted. Callers decline (return None / abstain) on a non-ok verdict.

orthonym.validation.e1_certificate.verify_certificate(mol, result, allow_charged=False)#

Atom-partition certificate for a GeneralEngineResult.

: allow_charged (set only under complete) lifts the net-formal-charge refusal – the charge is expressed as a -ylium/-ide/-uide/-ium suffix on an already-bound skeletal atom, so it introduces NO new atom and the partition is still complete. Default False -> byte-identical (the G1 neutral-scope guard still fires).

Thin object-shape wrapper over _verify_partition: unpacks each result.bindings element’s .token/.atom_ids into a (token, atom_ids) 2-tuple. Byte-identical logic to the historical body.