orthonym.rules.parent_correctness#
Note
Internal API. Names and behaviour may change between releases.
Parent-correctness scorer for a phase.
Scaffolds the 5th confidence factor (parent_correctness) in the candidate scoring pipeline. a phase wires this into FACTOR_WEIGHTS with weight 0.0 so the factor is computed and logged but does NOT influence selection (byte-identical safe by IEEE 754 + Python 3.7+ dict-order). a phase raises the weight after 80/20 train/test calibration to activate it.
- REFERENCE SOURCE (, locked in 145.1-internal notes):
OPSIN round-trip of the reference name. The only non-circular option: - Option A (chosen): OPSIN parses the reference name -> reference SMILES.
OPSIN is the inverse of Orthonym; reference names from ChEBI / PubChem / OPSIN self-test are external ground truth when they parse.
Option B (rejected – a phase’s work): a separate rule-based selector would pre-empt a phase.
Option C (rejected – too narrow): hand-curated parent map covers only the 500-compound opsin_selftest corpus.
- EXTRACTION PIPELINE (, – locked from RESEARCH):
- E1: regex parent-token + OPSIN re-parse + RDKit substructure match +
canonical-rank tiebreak. Pure Python + subprocess + RDKit; no Java<->Python bridge dependency. Verified on 6/9 test cases; remaining 3 fall back to 0.5 (no-decision = safe).
- THREAD-LOCAL I/O (, locked):
Module-level _pc_context = threading.local mirrors the established coverage_scoring._confidence_store pattern at coverage_scoring.py:404. Benchmark runners call set_reference_name(name) BEFORE orthonym.name(smiles). Production callers (no reference set) immediately return 0.5 with zero OPSIN cost.
- INVARIANT (security threat T-145.1-01 mitigation):
Production code path NEVER invokes OPSIN subprocess. Scorer.score short-circuits to 0.5 when _pc_context.reference_name is None (the production default). OPSIN is invoked ONLY in benchmark mode when set_reference_name has been explicitly called by the benchmark runner.
- FAILURE MODES (RESEARCH – all return 0.5 no-decision):
OPSIN can’t parse reference name
Parent token regex returns empty
OPSIN parses parent token to invalid SMILES
Substructure match returns 0 hits (ChEBI noise)
Substructure match returns >1 hits -> canonical-rank tiebreak
OPSIN CLI subprocess timeout (caught)
_pc_context.reference_name is None (production path)
candidate.parent_atom_indices is None (handler didn’t report)
- orthonym.rules.parent_correctness.set_reference_name(name)#
Set the reference IUPAC name for the current naming call.
Call BEFORE orthonym.name(smiles) in benchmark runs. Pass None to clear. Production callers (orthonym.name in REPL/library use) MUST NOT call this – leaving _pc_context.reference_name unset preserves byte-identical confidence values and avoids OPSIN subprocess cost.
- orthonym.rules.parent_correctness.clear_reference_name()#
Clear the thread-local reference name (idempotent).
- orthonym.rules.parent_correctness.opsin_reference_mol(ref_name)#
OPSIN-parse the FULL reference name once -> reference RDKit mol.
a phase SCORE-03 (A1 strategy, internal notes §A1 OPSIN-Cost Prototype): the per-node scorer parses the reference name ONCE per compound, then does RDKit fragment-submol matching per node (NOT one OPSIN call per node). Returns None on any OPSIN/parse failure (mirrors _opsin_to_smi’s caught-exception contract at:135-137). Reference names come from trusted corpora; OPSIN runs on STDIN (no shell), OPSIN_TIMEOUT=10.0.
- orthonym.rules.parent_correctness.match_token_atoms_in_mol(token, input_mol)#
OPSIN-parse a parent-stem/fragment token and substructure-match it into input_mol, returning the matched atom-index set (or None).
a phase SCORE-03: the reusable per-node generalization of the atom-alignment step (extracted verbatim from the old inline body of _extract_reference_parent_atoms). 0 hits -> None; >1 hits -> CanonicalRankAtoms(breakTies=True) deterministic tiebreak (load-bearing per RESEARCH Pitfall 4 — set-order non-determinism caused a real a phase byte-diff); any failure -> None. OPSIN runs on STDIN via _opsin_to_smi (no shell, OPSIN_TIMEOUT=10.0).
- class orthonym.rules.parent_correctness.ParentCorrectnessScorer#
Bases:
objectComputes the parent_correctness factor for a candidate name.
- Returns:
1.0 if candidate’s parent atoms match OPSIN-extracted reference parent 0.0 if mismatch 0.5 on no-decision (any failure mode – see module docstring)
Production callers (no _pc_context.reference_name set) immediately return 0.5 with zero OPSIN cost. Benchmark runners that have called set_reference_name pay one OPSIN parse per scored candidate.
- static score(candidate, mol)#
Score a single candidate against the thread-local reference.