orthonym.validation.stereo_descriptors#
Note
Internal API. Names and behaviour may change between releases.
The descriptor check of a name for its input: is every CIP stereodescriptor right?
A name that OPSIN reads only without its stereodescriptors (a lowercase r/s, a
descriptor OPSIN 2.9.0 does not know) is shipped by the default tier’s stereo-layer carve-out
after the stereo-stripped parse proved the constitution , and the best-effort tier’s
cis/trans offer starts from the same name. Neither may ship a name whose descriptors are
wrong, so both ask:func:stereo_block_units for the reading by which the name describes the
input. orthonym.namer imports:func:stereo_block_units and
stereo_descriptors_verified() as _stereo_block_units and
_stereo_descriptors_verified; its callers resolve those names at call time.
- class orthonym.validation.stereo_descriptors.StereoBlockUnits(text, span, multiplicity, units)#
Bases:
objectOne descriptor block of a name and what the accepted reading of it binds (
stereo_block_units()).text: the block asrules.stereochemistry.strip_stereo_blocksreturns it ('(1r,4r)').span:(start, end)in the name, the block with its following hyphen (name[start:end] == '(1r,4r)-').multiplicity: how many copies of its group the name cites the block for (1 outside a multiplied group).units: the stereo units of the input the reading binds to the tokens of the block,multiplicityper token, as('a', atom_idx)(a stereocentre) or('b', bond_idx)(a double bond), in ascending order.- text: str#
- span: Tuple[int, int]#
- multiplicity: int#
- units: Tuple[Tuple[str, int], ...]#
- orthonym.validation.stereo_descriptors.stereo_block_units(name, smiles, reduced)#
The reading by which
namedescribes the stereo ofsmiles, orNonewhen there is none. One:class:StereoBlockUnits per descriptor block ofname, in the orderrules.stereochemistry.strip_stereo_blocksremoves them; the stereo-layer carve-out and the best-effort prefix-order fallback ask only whether the reading exists (stereo_descriptors_verified()), and a caller that rewrites a block reads its span and its atoms here, from the reading that was accepted.critic-1 / R63 (claims conformance, 2026-09-27): is every stereodescriptor of
nameright, for a name OPSIN rejects only for its stereo layer?The stereo-layer carve-out of the validity gate ships such a name after judged the stereo-STRIPPED parse (
reduced,rules.stereochemistry.strip_stereo), so the constitution is OPSIN-checked and the descriptors are not. They were shipped unchecked, and some were wrong: ‘(7R,8S)-7-chloro-1-(3,5-dihydroxyphenyl)-2- methylundecyl acetate’ for an input whose stereocentres are the name’s C1 and C2 (C7 is unspecified, C8 is a CH2), and ‘(2S,3R)-3-oxoestr-4-en-17β-yl 3-phenylpropanoate’, whose C2 is a CH2 and C3 the ketone carbon. “NAMING OF STEREOISOMERS” (the Blue Book): “They are preceded by a numerical or letter locant to describe the position of the stereogenic unit when such locants are present” – a descriptor asserts the configuration of the unit at its locant, so a descriptor on a CH2 is a wrong name, not a narrower OPSIN grammar.Generalises
namer._pseudoasymmetric_name_verified(r/s only) to every CIP descriptor. A reading exists iff, for some reading ofreducedonto the input:every descriptor block is a list of CIP code tokens (R, S, r, s, E, Z), each with its locant where the unit has one; anything else (
rel,cis,RS,R*) is not verifiable;every token lands on DISTINCT stereogenic units of the input whose CIP label (
perception.stereo.assign_stereochemistry, the centres engine) is that code – a stereocentre for R/S/r/s, a double bond at that atom for E/Z. A located token is read in OPSIN’s own numbering ofreduced(the$_AVatom labels of-o extendedsmi), so a locant on a CH2, a heteroatom or out of range finds no such unit; a locant-free token may be any unit with its code. A block cited under a multiplier (bis[...],tris[...]) is cited for every copy of its group: each of its tokens lands on as many distinct units as the multiplicity (_block_multiplicity()), one per copy;every stereo unit of the input that the CIP labelling labels (the units a token can name, as in 2.) is either one of those cited units or one that the OPSIN parse of
reducedalready specifies (the retained parent’s implied configuration, a 17β,…): a name that cites a block for fewer copies than the input holds leaves a labelled unit uncited and has no reading;the input with exactly the cited units made unspecified has the FULL InChIKey of
reduced’s OPSIN parse – so each unit the parse specifies is what the rest of the name says. A token that restates a unit the parent already fixes (tropane’s 1R,5S) is kept specified on both sides.
Conditions 2 and 3 fix every labelled unit of the input, and condition 4 the constitution, the parent’s units and any other stereo the InChI sees, so the cited codes fix the units they name and the name denotes the input. Condition 3 is stated on the units, not through the InChI of the reduced input: that InChI drops a lone ring centre whose partner is unspecified, so a leftover centre of a pair of ring centres would not show in the key. A tagged atom that carries no CIP label (one of the two ring centres of cis,trans-1,3,5-trimethylcyclohexane that are not the pseudoasymmetric one) is not a unit a descriptor can name, and is left to condition 4. Fails closed (
None) on anything it cannot establish.
- orthonym.validation.stereo_descriptors.stereo_descriptors_verified(name, smiles, reduced)#
Is every stereodescriptor of
nameright forsmiles,reducedbeing the name with its descriptor blocks stripped? True iff:func:stereo_block_units finds a reading; the conditions are stated there.