Skip to content

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

A bundle of an RDKit Mol and drawing metadata.

to_smiles(canonical=True, isomeric=True)

Generate a SMILES string from the stored RDKit Mol.

to_svg(size=(300, 220), line_width=2, add_atom_indices=False)

Render the prepared molecule as an SVG string.

_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.