orthonym.rules.polycyclic_bridged#

Note

Internal API. Names and behaviour may change between releases.

Bridged polycyclic system detection and classification.

Handles classification and analysis of bridged polycyclic systems beyond simple bicyclics: - Tricyclo (3 rings) - Tetracyclo (4 rings) - Pentacyclo+ (5+ rings)

IUPAC Reference: Blue Book 2013, (Tricyclic and polycyclic ring systems)

The von Baeyer system uses: - Prefix: bicyclo-, tricyclo-, tetracyclo-, etc. - Descriptor: [main branches.main bridge.secondary bridges^locants] - Parent alkane name based on total carbons

Examples: - Adamantane: tricyclo[3.3.1.1³⁷]decane - Twistane: tricyclo[4.4.0.0³⁸]decane

class orthonym.rules.polycyclic_bridged.BridgeInfo(atoms, length, start_bh, end_bh)#

Bases: NamedTuple

Information about a single bridge in a polycyclic system.

atoms: List[int]#

Alias for field number 0

length: int#

Alias for field number 1

start_bh: int#

Alias for field number 2

end_bh: int#

Alias for field number 3

class orthonym.rules.polycyclic_bridged.PolycyclicInfo(system_type, ring_count, bridgeheads, main_ring, main_bridge, secondary_bridges, all_ring_atoms)#

Bases: NamedTuple

Complete information about a polycyclic bridged system.

system_type: str#

Alias for field number 0

ring_count: int#

Alias for field number 1

bridgeheads: Set[int]#

Alias for field number 2

main_ring: List[int]#

Alias for field number 3

main_bridge: BridgeInfo#

Alias for field number 4

secondary_bridges: List[BridgeInfo]#

Alias for field number 5

all_ring_atoms: Set[int]#

Alias for field number 6

orthonym.rules.polycyclic_bridged.get_ring_count(mol)#

Calculate the number of independent rings using the cycle rank formula.

For a connected molecule: rings = bonds - atoms + 1 This equals the number of cuts needed to convert to an acyclic structure.

Parameters:

mol – RDKit Mol object

Returns:

Number of rings (cycle rank)

Return type:

int

Examples

>>> mol = Chem.MolFromSmiles('C1CC2CCC1C2') # norbornane
>>> get_ring_count(mol)
2
>>> mol = Chem.MolFromSmiles('C1C2CC3CC1CC(C2)C3') # adamantane
>>> get_ring_count(mol)
3
orthonym.rules.polycyclic_bridged.count_cuts_to_open(mol)#

Count how many bonds must be cut to make the ring system acyclic.

This is equivalent to the ring count (cycle rank).

Parameters:

mol – RDKit Mol object

Returns:

Number of cuts needed

Return type:

int

orthonym.rules.polycyclic_bridged.classify_bridged_system(mol)#

Classify a bridged polycyclic system by its ring count.

Classification: - bicyclo: 2 rings - tricyclo: 3 rings - tetracyclo: 4 rings - pentacyclo: 5 rings - hexacyclo: 6 rings - heptacyclo: 7 rings

Parameters:

mol – RDKit Mol object

Returns:

Classification string, or None if not a bridged polycyclic

Return type:

str | None

Examples

>>> mol = Chem.MolFromSmiles('C1CC2CCC1C2') # norbornane
>>> classify_bridged_system(mol)
'bicyclo'
>>> mol = Chem.MolFromSmiles('C1C2CC3CC1CC(C2)C3') # adamantane
>>> classify_bridged_system(mol)
'tricyclo'
orthonym.rules.polycyclic_bridged.is_tricyclo_system(mol)#

Check if molecule is a tricyclo (3-ring bridged) system.

Parameters:

mol – RDKit Mol object

Returns:

True if molecule has exactly 3 rings in bridged configuration

Return type:

bool

Examples

>>> mol = Chem.MolFromSmiles('C1C2CC3CC1CC(C2)C3') # adamantane
>>> is_tricyclo_system(mol)
True
orthonym.rules.polycyclic_bridged.is_tetracyclo_system(mol)#

Check if molecule is a tetracyclo (4-ring bridged) system.

Parameters:

mol – RDKit Mol object

Returns:

True if molecule has exactly 4 rings in bridged configuration

Return type:

bool

orthonym.rules.polycyclic_bridged.is_pentacyclo_or_higher(mol)#

Check if molecule is pentacyclo or higher (5+ rings).

Parameters:

mol – RDKit Mol object

Returns:

True if molecule has 5 or more rings

Return type:

bool

orthonym.rules.polycyclic_bridged.find_all_bridgeheads(mol)#

Find all bridgehead atoms in a polycyclic system.

A bridgehead atom is: 1. In 2 or more rings 2. Has 3+ neighbors all within the ring system

This extends the bicyclo bridgehead detection to handle systems with more than 2 bridgeheads.

Parameters:

mol – RDKit Mol object

Returns:

Set of atom indices that are bridgeheads

Return type:

Set[int]

Examples

>>> mol = Chem.MolFromSmiles('C1CC2CCC1C2') # norbornane
>>> len(find_all_bridgeheads(mol))
2
>>> mol = Chem.MolFromSmiles('C1C2CC3CC1CC(C2)C3') # adamantane
>>> len(find_all_bridgeheads(mol))
4
orthonym.rules.polycyclic_bridged.get_ring_atoms(mol)#

Get all atoms that are part of the ring system.

Parameters:

mol – RDKit Mol object

Returns:

Set of atom indices in any ring

Return type:

Set[int]

orthonym.rules.polycyclic_bridged.find_all_bridge_paths(mol, bridgeheads)#

Find all bridges between any pair of bridgehead atoms.

A bridge is a path between two bridgeheads that doesn’t pass through any other bridgehead.

Parameters:
  • mol – RDKit Mol object

  • bridgeheads (Set[int]) – Set of bridgehead atom indices

Returns:

List of BridgeInfo objects for each bridge

Return type:

List[BridgeInfo]

orthonym.rules.polycyclic_bridged.find_main_ring(mol, bridgeheads)#

Find the main ring for IUPAC numbering purposes.

The main ring is defined as: 1. The largest ring containing exactly 2 bridgeheads 2. If tie, the ring with the most atoms

Parameters:
  • mol – RDKit Mol object

  • bridgeheads (Set[int]) – Set of bridgehead atom indices

Returns:

List of atom indices in the main ring, in order, or None

Return type:

List[int] | None

orthonym.rules.polycyclic_bridged.identify_main_bridgeheads(mol, bridgeheads)#

Identify the two main bridgeheads for the primary bicyclic skeleton.

These are the bridgeheads in the main ring that will be numbered 1 and n.

Parameters:
  • mol – RDKit Mol object

  • bridgeheads (Set[int]) – Set of all bridgehead atom indices

Returns:

Tuple of (primary_bh, secondary_bh) or None

Return type:

Tuple[int, int] | None

orthonym.rules.polycyclic_bridged.analyze_polycyclic_system(mol)#

Perform complete analysis of a bridged polycyclic system.

Returns all information needed for IUPAC naming: - System classification - Bridgehead positions - Main ring - All bridges with lengths

Parameters:

mol – RDKit Mol object

Returns:

PolycyclicInfo namedtuple or None if not a valid polycyclic

Return type:

PolycyclicInfo | None

Examples

>>> mol = Chem.MolFromSmiles('C1C2CC3CC1CC(C2)C3') # adamantane
>>> info = analyze_polycyclic_system(mol)
>>> info.system_type
'tricyclo'
>>> info.ring_count
3
orthonym.rules.polycyclic_bridged.get_ring_heteroatoms(mol, ring_atoms)#

Find heteroatoms (non-carbon) in the ring system.

Parameters:
  • mol – RDKit Mol object

  • ring_atoms (Set[int]) – Set of atom indices in the ring system

Returns:

List of (atom_idx, element_symbol) for each heteroatom

Return type:

List[Tuple[int, str]]

orthonym.rules.polycyclic_bridged.get_heteroatom_prefix(symbol)#

Get the Table-1.5 skeletal replacement (‘a’) prefix for a heteroatom.

Returns None for any element the table does not carry. Callers must fail closed on ``None`` – never substitute a derived string.

Why there is no fallback#

This function used to end return prefixes.get(symbol, symbol.lower+'a') over a local 7-entry dict, i.e. it generated a prefix for every element it did not know. The Blue Book’s ‘a’-prefix set is a CLOSED list: “Those related to these recommendations are listed in Table 1.5”), not a derivation rule, so a generated prefix is fabricated nomenclature. It is not even close for the elements that matter: the fallback spelled asa, sba, bia, sna, pba, gea, tea where the Blue Book has arsa, stiba, bisma, stanna, plumba, germa, tellura, and ala for aluminium (alumina in Table 1.5). That shipped 2-alaspiro[5.5]undecane – a plausible-looking wrong name rather than an honest refusal.

The table itself is not duplicated here: it is ring_replacement.HETEROATOM_PREFIXES, the single Table-1.5 source. The retired local dict (O N S Se P Si B) was a strict subset of it with identical spellings, so this is byte-identical for those seven elements and correctly spells the seven it was missing (Te As Sb Bi Ge Sn Pb) instead of inventing them.

This is the von Baeyer / spiro (Table 1.5) context. Hantzsch-Widman monocycles use Table 2.4, which deliberately differs for Al and In (aluma/indiga vs alumina/inda); see data/hw_heteroatoms. Do not merge the two.

param symbol:

Element symbol (O, N, S,…)

returns:

The IUPAC replacement prefix (oxa, aza, thia,…), or None when the element is off-table and the caller must refuse.