Topology and visualization¶
Topology¶
ctopo.topology
¶
Ligand skeleton and topology transformations for dataset visualization.
This module provides two lightweight graph transformations for ligand analysis:
1) get_ligands_skeleton(G): Returns the ligand "skeleton" as a subgraph of the original ligand graph. The skeleton contains donor atoms and skeleton atoms (i.e., atoms on the union of shortest paths between donor pairs).
2) get_ligands_topology(G): Returns a simplified "topology" graph derived from the skeleton by suppressing linear linkers and removing triangle "bubbles", mirroring the provided RDKit reference algorithm with ignore_cycles=False.
Topology graph requirements (per spec): - contains only single bonds, - donor atoms retain their original node attributes, - all other remaining atoms are dummies with minimal attributes (only Z=0).
__all__ = ['get_ligands_skeleton', 'get_ligands_topology']
module-attribute
¶
AtomType
¶
Bases: IntEnum
Atom partition labels stored in graph node attribute atom_type.
_donor_nodes(G, atom_type_key='atom_type')
¶
_find_degree2_non_donor(G, donors, bubble)
¶
Find next removable node, mirroring RDKit's sequential scan behavior.
bubble=False: degree-2 non-donor whose neighbors are NOT bonded bubble=True: degree-2 non-donor whose neighbors ARE bonded
_neighbors_two(G, n)
¶
_normalize_edges_single(G)
¶
Normalize all edges to single bonds with minimal deterministic attributes.
_reduce_degree2(G, donors, bubble)
¶
Repeatedly remove degree-2 non-donor nodes under the chosen criterion.
_remove_degree2_node(G, n, bubble)
¶
Remove degree-2 node n; connect neighbors if not a bubble.
_skeleton_nodes_from_labels(G, atom_type_key='atom_type')
¶
Return skeleton-node set using AtomType labels if present.
Returns (keep_nodes, used_labels). If no labeled skeleton nodes exist, returns (empty_set, False).
get_ligands_skeleton(G, atom_type_key='atom_type')
¶
Return the ligand skeleton as an induced subgraph of the original graph.
Skeleton definition
- Prefer precomputed AtomType labels: keep atoms with type in {DONOR, SKELETON}.
- Otherwise compute skeleton as the union of nodes on all shortest paths between donor pairs (plus donors themselves).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
G
|
Graph
|
Original ligand graph (NetworkX Graph). |
required |
atom_type_key
|
str
|
Node attribute holding AtomType integer codes. |
'atom_type'
|
Returns:
| Type | Description |
|---|---|
Graph
|
A copy of the induced skeleton subgraph (same node ids as in G). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no donor atoms are present. |
get_ligands_topology(G, atom_type_key='atom_type')
¶
Return a simplified topology graph of the ligand (ignore_cycles=False behavior).
Algorithm (mirrors your RDKit reference): - start from ligand skeleton - remove linear linkers (degree-2 non-donors, neighbors not bonded) by contracting - remove bubbles (degree-2 non-donors, neighbors bonded) by deleting - remove remaining linear linkers again - finalize: * donors keep original node attributes * non-donors become dummy nodes with only {'Z': 0} * all edges become single bonds with minimal attrs
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
G
|
Graph
|
Original ligand graph (NetworkX Graph). |
required |
atom_type_key
|
str
|
Node attribute holding AtomType integer codes. |
'atom_type'
|
Returns:
| Type | Description |
|---|---|
Graph
|
A new NetworkX Graph representing the ligand topology. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no donor atoms are present. |
skeleton_from_donors(G, donor_atoms)
¶
Union of nodes on all shortest paths between all donor-atom pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
G
|
Graph
|
NetworkX graph where nodes are atom indices. |
required |
donor_atoms
|
Sequence[int]
|
Donor atom node indices. |
required |
Returns:
| Type | Description |
|---|---|
set[int]
|
Set of atom indices on shortest paths between donor pairs (may include donors). |
Raises:
| Type | Description |
|---|---|
NodeNotFound
|
If a donor index is not present in G. |
Visuals¶
ctopo.visuals
¶
RDKit-backed visualization and SMILES utilities for cTopo graphs.
The core cTopo objects are graph-based (NetworkX). For human-facing visualizations and canonical string representations (SMILES), RDKit is much better suited.
This module provides three high-level preparers:
- prepare_ligand_visual – ligand Mol with donor maps + highlighting.
- prepare_skeleton_visual – skeleton graph -> Mol with configurable restoration of elements/bonds.
- prepare_topology_visual – topology graph -> Mol, with donors shown as either original elements or as 'DA' labels.
All preparers return a PreparedMol bundle which contains
- the RDKit Mol
- optional atom-label overrides
- optional highlight information
Donor atoms can be marked by the same atom-map number (:1 by default), which helps group similar ligands by a stable SMILES key.
Color = Tuple[float, float, float]
module-attribute
¶
__all__ = ['PreparedMol', 'prepare_ligand_visual', 'prepare_skeleton_visual', 'prepare_topology_visual']
module-attribute
¶
AtomType
¶
Bases: IntEnum
Atom partition labels stored in graph node attribute atom_type.
Ligand(mol, G, donor_atoms, skeleton_atoms, substituent_atoms, smiles_settings=SmilesSettings(), svg_settings=SvgSettings())
dataclass
¶
Ligand represented as an RDKit molecule plus a NetworkX graph and atom partitions.
Attributes:
| Name | Type | Description |
|---|---|---|
mol |
Mol
|
RDKit molecule |
G |
Graph
|
NetworkX graph with node attributes |
donor_atoms |
FrozenSet[int]
|
Frozen set of donor atom indices |
skeleton_atoms |
FrozenSet[int]
|
Frozen set of skeleton atom indices (excluding donors) |
substituent_atoms |
FrozenSet[int]
|
Frozen set of substituent atom indices |
smiles_settings |
SmilesSettings
|
Default settings for SMILES generation in visualization helpers |
svg_settings |
SvgSettings
|
Default settings for SVG generation in visualization helpers |
Visualization
The methods visualize_ligand, visualize_skeleton, and visualize_topology
return (smiles, svg) pairs that are convenient for building dataset browsers.
Keyword arguments for visual style are forwarded to the corresponding functions
in ctopo.visuals:
- visualize_ligand -> ctopo.visuals.prepare_ligand_visual
- visualize_skeleton -> ctopo.visuals.prepare_skeleton_visual
- visualize_topology -> ctopo.visuals.prepare_topology_visual
See ctopo.visuals for the available options.
denticity
property
¶
Returns ligand's denticity
visualize_ligand(**kwargs)
¶
Return ligand visualization (SMILES with donor maps + chemical-like SVG).
Keyword arguments are forwarded to ctopo.visuals.prepare_ligand_visual.
See ctopo.visuals for available options.
visualize_skeleton(donors=True, skeleton=True, bonds=True, **kwargs)
¶
Return skeleton visualization (SMILES + SVG) for this ligand.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
donors
|
bool
|
If True, donor atoms are shown as original elements. If False, donors are dummies labeled 'DA'. |
True
|
skeleton
|
bool
|
If True, skeleton atoms are shown as original elements. If False, skeleton atoms are dummies with empty labels. |
True
|
bonds
|
bool
|
If True, keep original bond orders from the skeleton graph. If False, force all bonds to be single. |
True
|
Keyword arguments are forwarded to ctopo.visuals.prepare_skeleton_visual.
See ctopo.visuals for available options.
visualize_topology(donors=False, **kwargs)
¶
Return topology visualization (SMILES + SVG) for this ligand.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
donors
|
bool
|
If True, donor atoms are shown as original elements. If False, donors are dummies labeled 'DA'. Non-donor atoms are always dummies with empty labels in the topology depiction. |
False
|
Keyword arguments are forwarded to ctopo.visuals.prepare_topology_visual.
See ctopo.visuals for available options.
PreparedMol(mol, atom_labels=None, highlight_atoms=None, highlight_bonds=None, highlight_atom_colors=None, highlight_bond_colors=None, highlight_atom_radii=None)
dataclass
¶
_bond_type_from_graph_edge(attrs, force_single)
¶
Map cTopo edge attrs to an RDKit bond type.
_clear_all_atom_maps(mol)
¶
_copy_mol(mol)
¶
_ensure_2d(mol)
¶
Ensure the molecule has 2D coordinates for drawing.
_graph_to_mol(G, atom_Z, force_single_bonds, sanitize=False)
¶
Build an RDKit Mol from a NetworkX graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
G
|
Graph
|
NetworkX graph. |
required |
atom_Z
|
Mapping[int, int]
|
mapping node_id -> atomic number to use in the RDKit Mol. |
required |
force_single_bonds
|
bool
|
if True, all bonds will be SINGLE. |
required |
sanitize
|
bool
|
if True, attempts Chem.SanitizeMol(mol). Default False. |
False
|
Returns:
| Type | Description |
|---|---|
tuple[Mol, Dict[int, int]]
|
(mol, node_to_atomidx) |
_set_donor_atom_maps(mol, donor_atoms, map_num)
¶
get_ligands_skeleton(G, atom_type_key='atom_type')
¶
Return the ligand skeleton as an induced subgraph of the original graph.
Skeleton definition
- Prefer precomputed AtomType labels: keep atoms with type in {DONOR, SKELETON}.
- Otherwise compute skeleton as the union of nodes on all shortest paths between donor pairs (plus donors themselves).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
G
|
Graph
|
Original ligand graph (NetworkX Graph). |
required |
atom_type_key
|
str
|
Node attribute holding AtomType integer codes. |
'atom_type'
|
Returns:
| Type | Description |
|---|---|
Graph
|
A copy of the induced skeleton subgraph (same node ids as in G). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no donor atoms are present. |
prepare_ligand_visual(ligand, donor_map_num=1, donor_color=(1.0, 0.8, 0.45), skeleton_bond_color=(0.65, 0.8, 1.0), donor_radius=0.45, mark_donors_in_smiles=True, highlight_skeleton_bonds=True)
¶
Prepare an RDKit Mol of the ligand for drawing and SMILES generation.
Behavior
- starts from ligand.mol (source of truth)
- optionally sets the same atom-map number on all donor atoms
- highlights donor atoms and (optionally) skeleton bonds
Skeleton bonds are computed from the ligand graph partition.
prepare_skeleton_visual(G_skeleton, use_original_donor_atoms=True, use_original_skeleton_atoms=True, use_original_bonds=True, donor_map_num=1, mark_donors_in_smiles=True, donor_color=(1.0, 0.8, 0.45), donor_radius=0.45, donor_label='DA')
¶
Prepare an RDKit Mol for a ligand skeleton graph.
prepare_topology_visual(G_topology, use_original_donor_atoms=False, donor_map_num=1, mark_donors_in_smiles=True, donor_color=(1.0, 0.8, 0.45), donor_radius=0.45, donor_label='DA')
¶
Prepare an RDKit Mol for a ligand topology graph.