Bond Utilities#
Utility functions for the detection, and creation, of bonds in a structure.
- atomworks.io.utils.bonds.LongBondPolicyType#
Type alias for long bond filtering policy options.
alias of
Literal[‘keep’, ‘filter’, ‘warn’, ‘raise’, ‘filter_nonstandard_only’, ‘warn_nonstandard_only’, ‘raise_nonstandard_only’]
- atomworks.io.utils.bonds.add_bonds_from_struct_conn(atom_array: AtomArray | AtomArrayStack, cif_block: CIFBlock, add_bond_types_from_struct_conn: tuple[str, ...] = ('covale',), struct_conn_distance_policy: Literal['keep', 'filter', 'warn', 'raise', 'filter_nonstandard_only', 'warn_nonstandard_only', 'raise_nonstandard_only'] = 'filter') AtomArray | AtomArrayStack[source]#
Convenience wrapper to add bonds to an AtomArray from a struct_conn CIF category.
See also
get_struct_conn_bonds()- For arguments and return types.
- atomworks.io.utils.bonds.build_bond_dict_for_atom_array(atom_array: AtomArray, custom_bond_dict: dict[str, dict[tuple[str, str], int]] | None = None, ccd_mirror_path: str | None = None) dict[str, dict[tuple[str, str], int]] | None[source]#
Build a complete bond dictionary for an AtomArray by merging CCD bonds with custom overrides.
Fetches CCD bonds for all residues as the baseline, then overlays
custom_bond_dicton top. This ensures that atoms added later (e.g., H atoms viaadd_missing_atoms) always have bonds available from CCD, while custom connectivity still takes precedence for the pairs it explicitly defines.- Parameters:
atom_array – Structure containing residues to get bonds for.
custom_bond_dict – Optional custom bonds (e.g., from CIF
chem_comp_bond). Maps residue names to{(atom1_name, atom2_name): bond_type_int}. These override the CCD entries for matching atom pairs.ccd_mirror_path – Path to local CCD mirror. Defaults to
CCD_MIRROR_PATH.
- Returns:
Complete bond dictionary with CCD bonds as baseline and custom bonds as overrides, or
Noneif no bonds could be found for any residue.
Example
>>> # Custom bonds for VER override CCD heavy-atom pairs; CCD still provides H bonds >>> custom_bonds = {"VER": {("C1", "C2"): 1, ("C2", "O1"): 2}} >>> bond_dict = build_bond_dict_for_atom_array(atom_array, custom_bond_dict=custom_bonds, ccd_mirror_path="/path/to/ccd") >>> # bond_dict contains VER bonds (CCD H-bonds + custom heavy-atom overrides) + ALA, GLY, etc. (CCD)
- atomworks.io.utils.bonds.correct_charged_amide_nitrogens(atom_array: AtomArray, to_update: ndarray | None = None) AtomArray[source]#
Neutralize charged nitrogens that are part of an amide pattern.
When a charged nitrogen (charge=+1) is bonded to a carbon that is also bonded to an oxygen (N-C=O / N-C-O amide pattern), the nitrogen should be neutral.
Example: PDB ID 1qfe Lysine NZ becomes a component of an amide bond to small molecule DHS, and should NOT be charged.
- Parameters:
atom_array – The AtomArray to fix.
to_update – Boolean mask of atoms to consider. If
None, defaults to atoms involved in inter-residue bonds.
- Returns:
The AtomArray with amide nitrogens corrected (modified in-place).
- atomworks.io.utils.bonds.correct_formal_charges_for_specified_atoms(atom_array: AtomArray, to_update: ndarray) AtomArray[source]#
Fix formal charges for atoms in an AtomArray based on valence rules and current bonding pattern.
- Parameters:
atom_array (AtomArray) – The AtomArray to fix.
to_update (np.ndarray) – A boolean mask of atoms whose formal charges should be fixed. These are normally the atoms for which bonds were manually added or modified (e.g., inter-residue bonds).
- Returns:
The AtomArray with fixed formal charges.
- Return type:
AtomArray
- atomworks.io.utils.bonds.filter_bonds_by_distance(atom_array: AtomArray, policy: Literal['keep', 'filter', 'warn', 'raise', 'filter_nonstandard_only', 'warn_nonstandard_only', 'raise_nonstandard_only'] = 'filter', chno_threshold: float = 1.7, chnops_threshold: float = 2.4, other_threshold: float = 3.6) AtomArray[source]#
Handle unphysical bonds based on element-dependent distance thresholds.
The thresholds are: 1. Bonds involving ONLY C, H, N, O: flagged if distance > chno_threshold 2. Bonds involving ONLY C, H, N, O, P, S: flagged if distance > chnops_threshold 3. Any other bonds (metals, etc.): flagged if distance > other_threshold
- Parameters:
atom_array – The AtomArray containing atoms and bonds to check.
policy –
How to handle long bonds. Options:
"keep": No checking, return atom_array unchanged."filter": Remove all bonds exceeding thresholds."warn": Log warning about all long bonds but keep them."raise": RaiseValueErrorif any long bonds detected."filter_nonstandard_only": Remove long bonds only in non-standard residues. Bonds where both atoms are in standard AA (20 canonical + UNK), RNA (A, C, G, U + N), or DNA (DA, DC, DG, DT + DN) are preserved."warn_nonstandard_only": Warn about long bonds in non-standard residues only."raise_nonstandard_only": Raise error if long bonds in non-standard residues.
Defaults to
"filter".chno_threshold – Maximum distance for bonds between only C, H, N, O atoms. Defaults to 1.8 Angstroms.
chnops_threshold – Maximum distance for bonds between only C, H, N, O, P, S atoms. Defaults to 2.4 Angstroms.
other_threshold – Maximum distance for bonds involving any other elements. Defaults to 3.6 Angstroms.
- Returns:
The input AtomArray, potentially with long bonds removed (if
policy="filter").- Raises:
ValueError – If
policy="raise"and long bonds are detected.
Note
Bonds involving atoms with NaN coordinates are preserved (not flagged).
- atomworks.io.utils.bonds.generate_inter_level_bond_hash(atom_array: AtomArray, lower_level_id: str, lower_level_entity: str | None = None, exclude_bond_types: set[BondType] | None = None) str[source]#
Generates a hash string representing the inter-level bonds within an AtomArray.
When computing entities IDs, we must consider inter-level bonds at the atom- and residue-level to avoid ambiguity.
- Parameters:
atom_array (AtomArray) – The array of atoms containing bond and annotation information.
lower_level_id (str) – The level which to find, and hash, the inter-level bonds. For example, when computing molecule entities, we’d consider the inter-PN Unit bonds.
lower_level_entity (str | None) – An additional entity annotation to use when computing the hash. Optional; if None, then only residue ID, residue name, and atom name are used.
- Returns:
A hash string representing the inter-level bonds.
- Return type:
str
- atomworks.io.utils.bonds.get_coarse_graph_as_nodes_and_edges(atom_array: AtomArray, annotations: str | tuple[str], exclude_bond_types: set[BondType] | None = None) tuple[ndarray, ndarray][source]#
Returns the coarse-grained nodes and edges at the given annotation level based on the atom array’s bond connectivity.
- Parameters:
atom_array (-) – The atom array containing atomic information and bonds.
annotations (-) – A single annotation or a tuple of annotations to be used for node identification.
exclude_bond_types (-) – Bond types to exclude from connectivity. For example, pass
{BondType.COORDINATION}to prevent metal-ligand bonds from merging components.
- Returns:
An array of unique nodes, each represented by a combination of annotations. - edges (np.ndarray): An array of edges, where each edge is a tuple of node indices representing a bond
between two nodes.
- Return type:
nodes (np.ndarray)
Example
>>> atom_array = cached_parse("5ocm")["atom_array"] >>> nodes, edges = get_coarse_graph(atom_array, ["chain_id", "transformation_id"]) >>> print(nodes) array([('A', '1'), ('F', '1'), ('G', '1'), ('H', '1'), ('I', '1'), ('W', '1'), ('X', '1'), ('Y', '1')], dtype=[('chain_id', '<U4'), ('transformation_id', '<U1')]) >>> print(edges) array([[0, 0], [1, 1], [2, 2], [3, 3], [5, 5], [6, 6]])
- atomworks.io.utils.bonds.get_connected_nodes(nodes: ndarray, edges: ndarray) list[list[Any]][source]#
Returns connected nodes as a mapped list given corresponding arrays of nodes and edges.
Example
>>> nodes = np.array([("A", "1"), ("B", "1"), ("C", "1"), ("D", "1")]) >>> edges = np.array([[0, 1], [0, 2], [1, 2]]) >>> connected_nodes = get_connected_nodes(nodes, edges) >>> print(connected_nodes) [[("A", "1"), ("B", "1"), ("C", "1")], [("D", "1")]]
- atomworks.io.utils.bonds.get_inter_pn_unit_bond_mask(atom_array: AtomArray) ndarray[source]#
Return a mask indicating which bonds are between two distinct PN units.
- atomworks.io.utils.bonds.get_struct_conn_bonds(atom_array: AtomArray, struct_conn_dict: dict[str, ndarray], add_bond_types: tuple[str, ...] = ('covale',), raise_on_failure: bool = False, distance_policy: Literal['keep', 'filter', 'warn', 'raise', 'filter_nonstandard_only', 'warn_nonstandard_only', 'raise_nonstandard_only'] = 'filter') BondList[source]#
Find inter-residue bonds from the CIF
struct_conncategory.Modified from biotite’s internal
_get_struct_conn_bonds.- Parameters:
atom_array – The atom array used to look up atom indices.
struct_conn_dict – The
struct_conncategory of a CIF block as a dict of numpy arrays. Required keys:conn_type_id,ptnr{1,2}_label_asym_id,ptnr{1,2}_label_comp_id,ptnr{1,2}_label_seq_id,ptnr{1,2}_label_atom_id.add_bond_types – Bond type IDs to include. Valid values are
"covale","disulf", and"metalc". Defaults to["covale"].raise_on_failure – If
True, raise on missing atoms or residues. Defaults toFalse.
- Returns:
A
biotite.structure.BondListready to merge into the atom array’s bond list.
- Reference:
- atomworks.io.utils.bonds.hash_atom_array(atom_array: AtomArray, annotations: tuple[str] = ('element', 'atom_name'), bond_order: bool = True, cast_aromatic_bonds_to_same_type: bool = False, use_md5: bool = False, md5_length: int | None = None) str[source]#
Computes a hash for an AtomArray based on the bond connectivity and the selected node annotations.
- Parameters:
atom_array (AtomArray) – The array of atoms to hash
annotations (tuple[str]) – The node annotations to include in the hash
bond_order (bool) – Whether to include bond order in the hash
cast_aromatic_bonds_to_same_type (bool) – Whether to treat all aromatic bonds as the same type
use_md5 (bool) – Whether to use MD5 hashing on the output
md5_length (int | None) – If using MD5, the number of characters to keep from the hash. If None, returns full hash.
- Returns:
The computed hash
- Return type:
str
- atomworks.io.utils.bonds.hash_graph(graph: Graph, node_attr: str | None = None, edge_attr: str | None = None, iterations: int = 3, digest_size: int = 16) str[source]#
Computes a hash for a given graph using the Weisfeiler-Lehman (WL) graph hashing algorithm and additionally adds a node and edge attribute hash, if specified, to deal with common edge cases where WL fails (e.g. disconnected graphs).
- Parameters:
graph (-) – The input graph to be hashed.
node_attr (-) – The node attribute to be used for hashing. If None, node attributes are ignored.
edge_attr (-) – The edge attribute to be used for hashing. If None, edge attributes are ignored.
iterations (-) – The number of iterations for the WL algorithm. Default is 3.
digest_size (-) – The size of the hash digest for WL. Default is 16.
- Returns:
The computed hash of the graph.
- Return type:
str
Example
>>> import networkx as nx >>> G = nx.gnm_random_graph(10, 15) >>> hash_graph(G) '504894f49dd84b17c391b163af69624b'
- atomworks.io.utils.bonds.remap_intra_residue_coordination_bonds(structure: AtomArray) AtomArray[source]#
Remap intra-residue COORDINATION bonds to SINGLE.
Biotite’s CIF writer routes intra-residue bonds to
chem_comp_bond, which cannot represent COORDINATION; inter-residue bonds go tostruct_conn(which can).