orthonym.rules.fusion_descriptors#
Note
Internal API. Names and behaviour may change between releases.
Fusion descriptor generation for systematic fusion names.
Generates IUPAC fusion descriptors for naming fused ring systems when no retained name exists. Used for systematic names like benzo[a]anthracene, naphtho[2,1-b]furan, etc.
IUPAC 2013 Fusion Descriptor Rules: - Letter locants (a, b, c…) designate edges of the PARENT ring - Edge ‘a’ is between atoms 1-2, edge ‘b’ is between 2-3, etc. - Numerical locants indicate which atoms of the CHILD ring are fused - Format: child[child_locants-letter]parent (e.g., benzo[a]anthracene) - IUPAC 2013: ‘o’ in fusion prefix is NOT elided before vowels
Reference: IUPAC 2013 Blue Book, Section (Fused Ring Systems)
- orthonym.rules.fusion_descriptors.get_fusion_edge(parent_ring, atom1, atom2)#
Find which edge (bond) in the parent ring is shared.
An edge is defined by two adjacent atoms in the ring. Edge numbering follows ring atom order: edge 0 is between atoms at positions 0-1, edge 1 is between positions 1-2, etc.
- Parameters:
parent_ring (List[int]) – List of atom indices in the parent ring (ordered)
atom1 (int) – First shared atom index
atom2 (int) – Second shared atom index
- Returns:
0-indexed edge number, or -1 if atoms are not adjacent in ring
- Return type:
int
Examples
>>> get_fusion_edge([0, 1, 2, 3, 4, 5], 0, 1) 0 >>> get_fusion_edge([0, 1, 2, 3, 4, 5], 1, 2) 1 >>> get_fusion_edge([0, 1, 2, 3, 4, 5], 5, 0) # wraparound 5
- orthonym.rules.fusion_descriptors.get_fusion_letter(parent_ring, shared_atoms)#
Get the fusion letter locant for the parent ring edge.
Converts edge index to letter: edge 0 -> ‘a’, edge 1 -> ‘b’, etc.
- Parameters:
parent_ring (List[int]) – List of atom indices in the parent ring
shared_atoms (Tuple[int, int]) – Tuple of (atom1, atom2) shared between rings
- Returns:
Fusion letter (‘a’, ‘b’, etc.) or empty string if edge not found
- Return type:
str
Examples
>>> get_fusion_letter([0, 1, 2, 3, 4, 5], (0, 1)) 'a' >>> get_fusion_letter([0, 1, 2, 3, 4, 5], (3, 4)) 'd'
- orthonym.rules.fusion_descriptors.get_child_locants(child_ring, shared_atoms)#
Find positions of shared atoms in child ring numbering.
Returns positions as 1-indexed locants (IUPAC convention).
- Parameters:
child_ring (List[int]) – List of atom indices in the child ring
shared_atoms (Tuple[int, int]) – Tuple of (atom1, atom2) shared between rings
- Returns:
Tuple of (lower_locant, higher_locant), 1-indexed Returns (0, 0) if atoms not found
- Return type:
Tuple[int, int]
Examples
>>> get_child_locants([0, 1, 2, 3, 4], (3, 4)) (4, 5) >>> get_child_locants([6, 7, 8, 9, 10], (6, 7)) (1, 2)
- orthonym.rules.fusion_descriptors.generate_fusion_descriptor(parent_ring, child_ring, shared_atoms, child_is_benzene=False)#
Generate the fusion descriptor [num,num-letter] format.
Child locants are ordered according to IUPAC convention: the child position bonded to the lower-numbered parent edge atom is listed first, then the child position bonded to the higher-numbered parent edge atom. This can produce ascending [2,3-b] or descending [3,2-b] depending on the relative orientation of parent and child numbering.
For benzene as child (all positions equivalent), child locants are omitted and only the edge letter is used: [b] instead of [1,2-b].
- Parameters:
parent_ring (List[int]) – List of atom indices in the parent ring (IUPAC order)
child_ring (List[int]) – List of atom indices in the child ring (IUPAC order)
shared_atoms (Set[int]) – Set of atom indices shared between rings
child_is_benzene (bool) – If True, omit child locants (all equivalent)
- Returns:
Fusion descriptor string like “[3,2-b]” or “[b]” for benzene child Returns empty string if descriptor cannot be generated
- Return type:
str
Examples
>>> generate_fusion_descriptor([0,1,2,3,4,5], [6,7,8,9,10], {0,1}) '[1,2-a]'
- orthonym.rules.fusion_descriptors.get_fusion_prefix(ring_name)#
Convert ring name to its fusion prefix form.
Uses lookup table for known rings, then applies general rules for unknown rings.
- Parameters:
ring_name (str) – The name of the ring (e.g., ‘benzene’, ‘furan’)
- Returns:
Fusion prefix form (e.g., ‘benzo’, ‘furo’)
- Return type:
str
Examples
>>> get_fusion_prefix('benzene') 'benzo' >>> get_fusion_prefix('naphthalene') 'naphtho' >>> get_fusion_prefix('furan') 'furo' >>> get_fusion_prefix('pyrrole') 'pyrrolo'
- orthonym.rules.fusion_descriptors.build_systematic_fusion_name(parent_name, child_name, descriptor)#
Assemble the systematic fusion name from components.
Format: {fusion_prefix}{descriptor}{parent}
IUPAC 2013 Note: The ‘o’ in fusion prefixes (benzo, naphtho) is NOT elided before vowels (unlike some older conventions).
- Parameters:
parent_name (str) – Name of the parent ring system
child_name (str) – Name of the child (fused) ring
descriptor (str) – Fusion descriptor (e.g., ‘[a]’, ‘[2,1-b]’)
- Returns:
Complete systematic fusion name
- Return type:
str
Examples
>>> build_systematic_fusion_name('anthracene', 'benzene', '[a]') 'benzo[a]anthracene' >>> build_systematic_fusion_name('furan', 'naphthalene', '[2,1-b]') 'naphtho[2,1-b]furan'
- orthonym.rules.fusion_descriptors.identify_parent_and_child(mol, ring_a, ring_b)#
Determine which ring is parent and which is child for fusion naming.
Parent selection follows IUPAC 2013 seniority: 1. Heterocyclic ring is senior to carbocyclic (regardless of size) 2. Among heterocyclic: nitrogen-containing > oxygen > sulfur 3. Among same heteroatom type: larger ring > smaller ring 4. Among same size/heteroatom: more heteroatoms > fewer
The MORE SENIOR ring is the parent (base component, appears last in name). The LESS SENIOR ring is the child (becomes the fusion prefix).
- Parameters:
mol – RDKit Mol object
ring_a (Set[int]) – Set of atom indices in first ring
ring_b (Set[int]) – Set of atom indices in second ring
- Returns:
Tuple of (parent_name, child_name, parent_ring_list, child_ring_list) Returns (‘’, ‘’, , ) if rings cannot be identified
- Return type:
Tuple[str, str, List[int], List[int]]
- orthonym.rules.fusion_descriptors.identify_fusion_edges(mol, parent_atoms, child_atoms)#
Find which edges of parent ring are involved in fusion with child ring.
Identifies all edges (bonds) shared between the parent and child rings. An edge is defined by two adjacent atoms that appear in both rings.
- Parameters:
mol – RDKit Mol object
parent_atoms (List[int]) – List of atom indices in the parent ring (ordered)
child_atoms (List[int]) – List of atom indices in the child ring
- Returns:
List of (edge_start, edge_end) atom index pairs for shared edges Empty list if no shared edges found
- Return type:
List[Tuple[int, int]]
Examples
>>> # For benzene fused to anthracene at edge 'a' (atoms 0-1) >>> identify_fusion_edges(mol, [0,1,2,3,4,5,6,7,8,9], [0,1,10,11,12,13]) [(0, 1)]
- orthonym.rules.fusion_descriptors.edge_position_to_letter(parent_ring, edge)#
Convert an edge position in a parent ring to its IUPAC letter designator.
Edge ‘a’ is between atoms at positions 0-1 (IUPAC atoms 1-2), edge ‘b’ is between positions 1-2 (IUPAC atoms 2-3), etc.
- Parameters:
parent_ring (List[int]) – List of atom indices in the parent ring (ordered)
edge (Tuple[int, int]) – Tuple of (atom1, atom2) defining the edge
- Returns:
Letter designator (‘a’, ‘b’, ‘c’,…) or empty string if not found
- Return type:
str
Examples
>>> edge_position_to_letter([0,1,2,3,4,5], (0, 1)) 'a' >>> edge_position_to_letter([0,1,2,3,4,5], (2, 3)) 'c'
- orthonym.rules.fusion_descriptors.handle_duplicate_edge_fusion(edge_letters)#
Apply primed notation when same edge letter appears multiple times.
IUPAC uses primed notation (a’, a’’, b’, etc.) when the same edge letter is used for multiple fusion points. Letters are sorted alphabetically with unprimed before primed variants.
- Parameters:
edge_letters (List[str]) – List of edge letters (may have duplicates)
- Returns:
List of letters with primes applied where needed, sorted canonically Order: a, b, c,… a’, b’,… a’’, b’’,…
- Return type:
List[str]
Examples
>>> handle_duplicate_edge_fusion(['a', 'c']) ['a', 'c'] >>> handle_duplicate_edge_fusion(['a', 'a']) ['a', "a'"] >>> handle_duplicate_edge_fusion(['a', 'b', 'a']) ['a', 'b', "a'"] >>> handle_duplicate_edge_fusion(['a', 'a', 'a']) ['a', "a'", "a''"]
- orthonym.rules.fusion_descriptors.format_complex_fusion(child_locants, parent_letter, multi_component=None, multi_edge=None)#
Format fusion descriptor for various complexity levels.
Handles three types of fusion descriptors: 1. Standard: [2,3-b] - single fusion with child locants and parent letter 2. Multi-component: [a,c] - multiple same-type rings fused to parent 3. Multi-edge: [1,2-a:4,5-b’] - complex fusions with multiple edges
- Parameters:
child_locants (Tuple[int, int] | None) – Tuple of (loc1, loc2) child ring locants, or None
parent_letter (str | None) – Parent edge letter (‘a’, ‘b’, etc.), or None
multi_component (List[str] | None) – List of edge letters for multi-component fusion
multi_edge (List[Tuple[Tuple[int, int], str]] | None) – List of ((loc1, loc2), letter) for multi-edge fusion
- Returns:
Formatted fusion descriptor string
- Return type:
str
Examples
>>> format_complex_fusion((2, 3), 'b') '[2,3-b]' >>> format_complex_fusion(None, None, multi_component=['a', 'c']) '[a,c]' >>> format_complex_fusion(None, None, multi_edge=[((1, 2), 'a'), ((4, 5), "b'")]) "[1,2-a:4,5-b']"
- orthonym.rules.fusion_descriptors.generate_multi_fusion_descriptor(parent_ring_name, fused_components)#
Generate fusion descriptor for multi-component fusions.
For compounds like dibenzo[a,c]anthracene where multiple rings of the same type are fused to a parent ring.
- Parameters:
parent_ring_name (str) – Name of the parent ring (e.g., ‘anthracene’)
fused_components (List[Tuple[str, List[int], Set[int]]]) – List of (child_name, parent_ring_atoms, shared_atoms) tuples where each tuple describes one fused component
- Returns:
Multi-component descriptor like ‘[a,c]’ for dibenzo Returns empty string if descriptor cannot be generated
- Return type:
str
Examples
>>> # dibenzo[a,c]anthracene: two benzene rings at edges a and c >>> generate_multi_fusion_descriptor('anthracene', [ ... ('benzene', [0,1,2,3,4,5,6,7,8,9,10,11,12,13], {0, 1}), ... ('benzene', [0,1,2,3,4,5,6,7,8,9,10,11,12,13], {4, 5}) ... ]) '[a,c]'
- orthonym.rules.fusion_descriptors.build_multi_component_name(parent_name, child_name, count, descriptor)#
Build name for multi-component fusion (dibenzo, dinaphtho, etc.).
- Parameters:
parent_name (str) – Name of parent ring (e.g., ‘anthracene’)
child_name (str) – Name of fused ring type (e.g., ‘benzene’)
count (int) – Number of fused rings of this type (2 for di-, 3 for tri-)
descriptor (str) – Fusion descriptor (e.g., ‘[a,c]’)
- Returns:
Complete multi-component name like ‘dibenzo[a,c]anthracene’
- Return type:
str
Examples
>>> build_multi_component_name('anthracene', 'benzene', 2, '[a,c]') 'dibenzo[a,c]anthracene' >>> build_multi_component_name('anthracene', 'naphthalene', 2, '[a,h]') 'dinaphtho[a,h]anthracene'
- orthonym.rules.fusion_descriptors.generate_systematic_name_for_fused_pair(mol, ring1, ring2, shared_atoms, allow_skeleton_match=False)#
Generate systematic fusion name for a pair of fused rings.
This is the main entry point for generating fusion names when no retained name exists. Uses IUPAC-numbered ring ordering for correct edge letters and child locants.
- Parameters:
mol – RDKit Mol object
ring1 (List[int]) – List of atom indices in first ring
ring2 (List[int]) – List of atom indices in second ring
shared_atoms (Set[int]) – Set of atom indices shared between rings
- Returns:
Systematic fusion name, or None if name cannot be generated
- Return type:
str | None
Examples
>>> mol = Chem.MolFromSmiles('c1ccc2cc3ccccc3cc2c1') # anthracene >>> ri = mol.GetRingInfo >>> # Would generate 'benzo[a]naphthalene' for benzene fused to naphthalene
- orthonym.rules.fusion_descriptors.generate_multi_fusion_name(mol, parent_ring, parent_name, fused_rings)#
Generate systematic name for multiple rings fused to a parent.
Handles complex fusion scenarios like dibenzo[a,c]anthracene where multiple rings of the same type are fused at different edges.
- Parameters:
mol – RDKit Mol object
parent_ring (List[int]) – List of atom indices in the parent ring
parent_name (str) – Name of the parent ring (e.g., ‘anthracene’)
fused_rings (List[Tuple[List[int], Set[int]]]) – List of (child_ring_atoms, shared_atoms) for each fusion
- Returns:
Complete systematic fusion name, or None if cannot be generated
- Return type:
str | None
Examples
>>> # For dibenzo[a,c]anthracene >>> generate_multi_fusion_name(mol, anthracene_atoms, 'anthracene', ... [(benzene1_atoms, {0,1}), (benzene2_atoms, {4,5})]) 'dibenzo[a,c]anthracene'