feat(numbering): publish canonical numbering API

Add a public numbering module and route fragmenting, validation,
and scaffold preparation through the canonical numbering entry.

Rewrite the repository entry docs around the fixed numbering
contract, add MkDocs landing pages, and document the mirror
mapping used for medicinal-chemistry comparisons.

Also refresh the validation analysis reports to explain the
canonical-versus-mirrored numbering relationship.
This commit is contained in:
2026-03-20 15:14:31 +08:00
parent 8071a141ee
commit 3e07402f4e
22 changed files with 529 additions and 444 deletions

View File

@@ -0,0 +1,52 @@
from __future__ import annotations
from macro_lactone_toolkit import (
MacrolactoneFragmenter,
mirror_macrolactone_position,
mirror_macrolactone_positions,
number_macrolactone,
)
from macro_lactone_toolkit.splicing.scaffold_prep import prepare_macrolactone_scaffold
from .helpers import build_macrolactone
def test_number_macrolactone_matches_fragmenter_numbering() -> None:
built = build_macrolactone(16, {5: "methyl"})
api_result = number_macrolactone(built.smiles, ring_size=16)
fragmenter_result = MacrolactoneFragmenter(ring_size=16).number_molecule(built.smiles)
assert api_result.position_to_atom == fragmenter_result.position_to_atom
assert api_result.atom_to_position == fragmenter_result.atom_to_position
def test_mirror_macrolactone_position_for_ring16() -> None:
assert mirror_macrolactone_position(6, 16) == 13
assert mirror_macrolactone_position(7, 16) == 12
assert mirror_macrolactone_position(15, 16) == 4
assert mirror_macrolactone_position(16, 16) == 3
def test_mirror_macrolactone_positions_returns_stable_mapping() -> None:
assert mirror_macrolactone_positions([6, 7, 15, 16], 16) == {
6: 13,
7: 12,
15: 4,
16: 3,
}
def test_prepare_scaffold_keeps_requested_position_label() -> None:
built = build_macrolactone(16, {5: "ethyl"})
scaffold, dummy_map = prepare_macrolactone_scaffold(
built.mol,
positions=[5],
ring_size=16,
)
numbering = number_macrolactone(built.mol, ring_size=16)
assert 5 in dummy_map
assert numbering.position_to_atom[5] == built.position_to_atom[5]
assert numbering.position_to_atom[5] == scaffold.GetAtomWithIdx(dummy_map[5]).GetNeighbors()[0].GetIdx()