schrodinger.structutils.assignbondorders module

A module to assign bond orders based on molecular geometry.

Assigns double and triple bonds to structures based on molecular geometry (bond length, bond angles, and dihedral angles). Useful when importing ligands from PDBs into Maestro. Please check the output structure for errors and compare it to the molecular formula. If this script assigns bond orders incorrectly to a reasonable structure, please email the maestro file of the structure to help@schrodinger.com.

There is a single public function:

assignbondorders.assign_st(input_st, atoms=None, neutralize=False,
                           problem_only=False, skip_assigned_residues=True,
                           _logger=None)

Assigns bond orders to atom list [atoms] of structure input_st and returns a list of bonds that were adjusted. Bond orders are assigned for all atoms if the atoms list is empty or not specified.

Copyright (c) Schrodinger, LLC. All rights reserved.

schrodinger.structutils.assignbondorders.debug(txt)

For general debug messages

schrodinger.structutils.assignbondorders.debuggroup(msg)

For debugging group bond assignments

schrodinger.structutils.assignbondorders.debugbonders(msg)

For debugging aromatic ring assignments

schrodinger.structutils.assignbondorders.debugbond(msg)

For debugging code that calculates bond “scores”

schrodinger.structutils.assignbondorders.warning(msg)
schrodinger.structutils.assignbondorders.get_single_bond_length(a1, a2)

Returns ideal length of a single-order bond between specified atoms. If either of the atoms is non-common, returns 0.0.

schrodinger.structutils.assignbondorders.get_neighbors(st, atom)

Returns a list of atoms that <atom> is bound to.

schrodinger.structutils.assignbondorders.calculate_average_angle(st, atom_num)

Calculates the average of all bond angles around the input atom. Returns 0 if the angle can not be calculated. Close to 109 degrees = tetrahedral Close to 120 degrees = planar Close to 180 degrees = linear

schrodinger.structutils.assignbondorders.calculate_dihedral(st, a1, a2)

Calculates the average dihedral angle of the bond between the specified atoms. Close to 0 (zero) is likely to be double bond.

schrodinger.structutils.assignbondorders.order_ring_or_chain(st, atoms)

This function orders the atoms in the ring or chain by bonding order.

schrodinger.structutils.assignbondorders.do_rings_share_atoms(r1, r2)
schrodinger.structutils.assignbondorders.get_rings_in_group(ring, rings_to_check)
class schrodinger.structutils.assignbondorders.CCDAtomMapper(use_chirality: bool)

Bases: schrodinger.comparison.atom_mapper.ConnectivityAtomMapper

Class for determining most ideal mapping of a CCD SMILES structure to a 3D ligand conformation.

score_mapping(ccd_st, st, atset)

This method is called to “score” a given mapping. Here, both input structures have been re-ordered to have the same atom ordering, and <atset> is a set of atoms that are “shared” between the 2 structures.

ATOM_TYPE = 's_m_custom_atom_type'
MAPPER_INDEX = 'i_m_atom_mapper_index'
__init__(use_chirality: bool)
Parameters

use_chirality – if True, in addition to element type use chirality (where defined) to equate atoms.

are_conformers(st1: schrodinger.structure._structure.Structure, atlist1: List[int], st2: schrodinger.structure._structure.Structure, atlist2: List[int]) bool

Determine if the two substructures, as defined by the atom lists, are conformers but do not explore isomorphisms.

Parameters
  • st1 – the first structure

  • atlist1 – list of atom indexes defining the first substructure

  • st2 – the second structure

  • atlist2 – list of atom indexes defining the second substructure

Returns

boolean indicating whether or not the two structures are conformers

are_consistently_ordered_conformers(st1: schrodinger.structure._structure.Structure, st2: schrodinger.structure._structure.Structure, atlist: List[int]) bool

Determine if two substructures are consistently ordered conformers. That is, they have the same atom numbering and bonding

Parameters
  • st1 – the first structure

  • st2 – the second structure

  • atlist – list of atom indexes defining the substructure

Returns

boolean indicating whether or not the two structures are ordered conformers

are_enantiomers(st1: schrodinger.structure._structure.Structure, atlist1: List[int], st2: schrodinger.structure._structure.Structure, atlist2: List[int]) bool

Determine if the two substructures, as defined by the atom lists, are enantiomers but do not explore isomorphisms.

Parameters
  • st1 – the first structure

  • atlist1 – list of atom indexes defining the first substructure

  • st2 – the second structure

  • atlist2 – list of atom indexes defining the second substructure

Returns

boolean indicating whether or not the two structures are conformers

comparator(d1: Dict, d2: Dict) bool

Comparison function to be used to determine if two nodes on graph are equivalent.

If this method is not used when constructing a GraphMatcher, node attributes will not be considered for the purpose of determining isomorphism.

Parameters
  • d1 (dict) – key=value dictionary from graph returned from st_to_graph which represents node 1

  • d1 – key=value dictionary from graph returned from st_to_graph which represents node 2

Returns

boolean indicating equilvalence

get_atom_type(at: schrodinger.structure._structure._StructureAtom) str

This value is used as an atom property

Parameters

at – atom we wish to obtain a type for

Returns

string which identifies atom type

initialize_atom_types(st: schrodinger.structure._structure.Structure, invert_stereocenters: bool = False)

Initialize the atom types

Parameters
  • st – structure containing atoms

  • invert_stereocenters – whether or not R/S labels should be flipped

invert_chirality(ch_list: List[str])

Invert the chirality (R/S) of an input list of chiralities.

Parameters

ch_list – list of chirality labels for a structure

isomeric_atom_sets(st1: schrodinger.structure._structure.Structure, atset1: Set[int], st2: schrodinger.structure._structure.Structure, atset2: Set[int]) bool

Check that the atom types in atset1 are the same as those in atset2. If not, the two structures cannot be conformers.

Parameters
  • st1 – the first structure

  • atset1 – set of atom indexes defining the first substructure

  • st2 – the second structure

  • atset2 – set of atom indexes defining the second substructure

Returns

a boolean indicating if these atom lists are isomeric

reorder_structures(st1: schrodinger.structure._structure.Structure, atlist1: List[int], st2: schrodinger.structure._structure.Structure, atlist2: List[int], invert_stereocenters: bool = False) Tuple[schrodinger.structure._structure.Structure, schrodinger.structure._structure.Structure]

Reorder the atoms in the two structures.

Parameters
  • st1 – the first structure

  • atlist1 – list of atom indexes defining the first substructure

  • st2 – the second structure

  • atlist2 – list of atom indexes defining the second substructure

  • invert_stereocenters – If True, flip all R<->S, used for are_enantiomers

Returns

the two structures with structure 2 having had atoms reordered

score_is_equivalent(score1: float, score2: float) bool

determines if score should be considered equivalent

Parameters
  • score1 – the first score

  • score2 – the second score

set_atom_type(at: schrodinger.structure._structure._StructureAtom, value: str)

Set the value of the atom type

Parameters
  • at – atom we wish to set type for

  • value – set the type of atom to this

st_to_graph(st: schrodinger.structure._structure.Structure, atset: Set[int]) networkx.classes.graph.Graph

Convert Structure instance to a networkx Graph using _StructureAtom instances as nodes and adding an atom type property

Parameters
  • st – the structure to convert

  • atset – a set of atoms to use to create the graph

Returns

networkx Graph

unique_job_name(base_name: str) str

Add an integer to the end of the base_name to get a unique name.

Parameters

base_name – base job name

Returns

unique name

class schrodinger.structutils.assignbondorders.AssignBondOrders(st, atoms, neutralize)

Bases: object

__init__(st, atoms, neutralize)

This is a private class; use assign_st() function instead.

assign()
assignTemplatedSubstructures()

Force assignment of known functional groups by SMARTS

isOnlySingleBonded(atom)

Returns False if atom has double or triple bonds.

getNeighbors(atom)

Returns a list of atoms that <atomnum> is bound to.

getNeighborsObj(atom)

Returns a list of atoms that <atomnum> is bound to.

getNumNeighbors(atom)

Returns a the number of atoms that <atom> is bound to. EXCLUDING zero-order bonds

getNumBondOrders(atom)
getElement(atomnum)
fixFormalCharge(atom)

Adjusts the formal charge so that it is valid for number of bonds and bond orders.

setFormalCharge(atom, charge)
setBondOrder(atom1, atom2, bond_order)

Sets the bond order between atom1 and atom2 to bond_order.

getAtomsRings(atom)

Return a list of rings that this atom is part of.

isAtomInRing(atom)
isAtomInSmallRing(atom_num)

Returns 1 if atom_num is a ring with 3, 4, or 5 members.

getExtracyclicAtom(ring, a)

Given an atom of a ring, return the extra-cyclic atom that is bound to this atom.

forEdgeInRing(ring)

Iterates over (atom1, atom2) in the given ring

calcBondScore(a1, a2, distance_weight=1.0, ring_angle_weight=0.0)

Calculates the probability that the two atoms are double bonded to each other.

getBestDoubleBond(a1, a2, a3)

Returns a list of two atoms that are the best candidates. Returns [] if neither bond is potential double bond.

sortFirstThreeOfGroup(atom_group)

This function sorts the atoms in the group so that the 3 (or 4) atoms that need to be worked on the first will be listed first.

resolveTriangularGroup(atoms)

Assign a double bond to “best” bond pair in the set. If any bond score is under the double bond threshold and is also “terminal”, remove it from further consideration for double bonding.

Input atom list must be sorted: the first atom in the list must be central, and the three next atoms are bonded to it in a star-like arrangement.

If all three neighbors have bonds scores above the threshold, the one with the highest score is turned into a double bond. Else, the one with the lowest score is removed from the set to avoid infinite recursion.

In case of symmetrical inputs, 2 or more bonds may have the same length, etc, and ties may happen. We need a non-geometrical criterion to resolve ties in a reproducible manner. For this reason, use atom indexes as a secondary criterion.

assignGroupDoubleBonds(atom_set)

Assigns double bonds where appropriate for the atoms in the supplied group.

identifyGroups()

Identifies groups and sets bond orders appropriately.

findRings()

Returns a list of all rings in the st within the atoms range.

isRingAromatic(ringatoms)

Returns a boolean - whether the specified ring is aromatic or not. Aromatic ring is defined in this context as a 5 or 6 membered ring that is likely, based on bond lengths and angles, etc. to be an aromatic ring.

ringatoms are assumed to be in connectivity order.

findAromaticRings()

Returns a list of aromatic rings in st within all_rings.

isAtomAromatic(atom)

Returns True if the given atom is part of an aromatic ring

areAtomsOrtho(ring, atom1, atom2)
isBondRingEdge(a1, a2, rings=None)
isAtomBetweenTwoRings(atom)

Returns True if this atom is bound to two rings, but is not part of a ring itself. Like this: Ring-X-Ring. Such an atom may get a double bond to one of the rings if needed.

isAtomBoundToAromaticRing(atom)

Returns True if at least one of atoms bound to it is a member of an aromatic ring.

assignAromaticBonders(ring, bonders)

Assigns bond orders for the supplied 5 or 6-membered aromatic ring. Returns True if successful, False if not.

<bonders> is a list of atoms that MUST get double-bonded.

determineAromaticAtomType(ring, a, ring_group_atoms)

Determines the type of the atom in the aromatic ring.

areCOsPara(ring, c1, c2)
determineAromaticAtomTypes(ring, ring_group_atoms)

Goes through every atom in the supplied aromatic ring, and determines what type of atom it is, then adds the atom to that category. It returns a dictionary (list) of atoms in different groups.

assignGroupTripleBonds(atom_group)

Assigns triple bonds as appripriateley to the atoms in the supplied group. Returns a list of atoms which now have assigned bond orders.

assignAromaticRing(ring, ring_group_atoms)

Returns ASSIGNED_AROMATIC if everything is okay. Returns NOT_AROMATIC if the ring is not aromatic. Returns NOT_ASSIGNED if this ring should be considered later.

findAromaticBonders(ring, ringatomtypes_dict)

Returns a list of suggested bonding atoms in the specified aromatic ring. Returns [] if no bonds should be made.

If “required_only” is set, return only the REQUIRED BONDERS and REQUIRED NON-BONDERS

Raises RuntimeError(“Not aromatic”) if the ring is not aromatic. Raises RuntimeError(“Not assigned”) if the ring could not be assigned.

groupAromaticRings()
getNeighboringRings(ring, rings)

Return a list of rings that share atoms with the specified ring.

isKetoneCarbon(atom)
assignAromaticRingGroup(group)

Assigns bond orders of aromatic rings (5 & 6 membered) which are arranged in a group (multi-cyclic systems).

assignAromaticRingOrders()

Assign all aromatic rings

fixKetones()

This function adds double bonds to ketones and aldehydes when necesary. It should be run only after ALL other bond orders have been assigned.

fix_N4s()

Sets the macromodel atom type of Positively Charged Nitrognes to N4(31/sp2) or N5(32/sp3).

sortBondableAtomsByGroups(potential_double_bond_atoms)

Takes the list of input atoms, and puts them into groups, and returns a list of those groups. Atoms are considerred in the same group if they are bonded together (in the same chain).

assignTripleBonds()
assignChainOrders()
findPotentialTripleBondAtoms()

Returns a list of atoms that can potentially triple-bond.

getPotentialDoubleBondAtoms()

Returns a list of atoms that can potentially double bond. Only bond angles are considered.

schrodinger.structutils.assignbondorders.get_ring_atom_coords(st, ring_atoms)

Get the coordinates of the ring atoms as a numpy array.

If st has periodic boundary conditions (PBC), the coordinates returned will all be in the frame of reference of the first atom in ring_atoms.

schrodinger.structutils.assignbondorders.get_edge_normals(ring_atom_coords)

Get vectors normal to the planes described by each ring-edge and the center of the ring.

Assumes that atoms are in order.

schrodinger.structutils.assignbondorders.calculate_planarity(st, ring_atoms)

Calculate the ring planarity.

Very planar rings have a planarity of < 1.

Assumes that atoms are in order.

exception schrodinger.structutils.assignbondorders.CCDStructureMismatchError

Bases: RuntimeError

raise this error when structure in CCD template doesn’t match HET

__init__(*args, **kwargs)
args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception schrodinger.structutils.assignbondorders.SmilesGenerateError

Bases: RuntimeError

raise this error when RDKit fails to generate SMILES

__init__(*args, **kwargs)
args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

schrodinger.structutils.assignbondorders.assign_st(st, atoms=None, neutralize=False, problem_only=False, skip_assigned_residues=True, use_ccd=False, _logger=None)

Perform the assign-bond-order algorithm on the supplied structure. If the atom list is specified, only those atoms are fixed.

Parameters
  • st (L{structure.Structure)) – Structure to assign bond orders in

  • atoms (list of ints) – List of atoms to assign. By default all atoms as assigned.

  • neutralize (bool) – Whether to protonate carboxylic acids.

  • problem_only (bool) – Whether to assign only to atoms with PDB convert problem of 4 (orange atoms). Not compatible with <atoms> argument.

  • skip_assigned_residues (bool) – If True, bond orders are not assigned to residues that have double or triple bonds, even if that residue’s atoms are in <atoms>. Not compatible with <problem_only> option.

  • use_ccd (bool) – Whether to use the Chemical Component Dictionary for hets that have records there. Not supported for covalent ligands. NOTE: if set to True, then all existing bond orders and charges (if present) will be overwritten (for residues with CCD entries). If False (or if residue can’t be assigned by CCD), formal charges are not adjusted, and existing bond orders will never be reduced.

  • _logger (logger) – logger to send messages to

Returns

List of (atom1, atom2, order) for every bond whose order was altered.

Return type

list of (int, int, int)

schrodinger.structutils.assignbondorders.read_ccd_structures(pdbres_iter: Iterable[str]) Dict[str, List[schrodinger.structure._structure.Structure]]

Read in CCD entries as structures. This is done in batch so we only need to touch the zip file once.

Returns

Dictionary that maps a pdbres to reference CCD structures

schrodinger.structutils.assignbondorders.build_ref_charges_and_bonds_cache(st: schrodinger.structure._structure.Structure)

Given a structure extract all CCD reference charges and bonds for each unique residue.

Populates the module level CCD_CHARGES_AND_BONDS_CACHE dict.

schrodinger.structutils.assignbondorders.determine_ccd_pdbres(res: schrodinger.structure._structure._Residue) str

Determine the CCD state that is consistent with the information present in the residue. For now only histidine is checked.

schrodinger.structutils.assignbondorders.determine_his_ccd_pdbres(his: schrodinger.structure._structure._Residue) str

Given a HIS residue, determine its protonation state based on PDB names and bond orders, and return the PDB residue name for the state.

schrodinger.structutils.assignbondorders.ccd_assign_by_names_and_bonds(res: schrodinger.structure._structure._Residue) Tuple[List[Tuple[int, int]], List[Tuple[int, int, int]]]

Assign bond orders and charges to residue based on CCD entry. A target residue matches with the reference if the atom names and all intra-residue bonds are a subset of the reference atom names and intra-residue bonds.

The CCD typically contains the most protonated form, which is not desirable for residues that are not handled by Epik, typically standard residues, e.g. it contains the neutral form of GLU. In that case the CCD is overwritten.

Returns

Tuple with list of atom indices and assigned charges, and list of assigned bond orders.

schrodinger.structutils.assignbondorders.attempt_ccd_assignment(res: schrodinger.structure._structure._Residue, res_assign_atoms: Optional[List[int]] = None, _logger: Optional[logging.Logger] = None) Tuple[List[Tuple[int, int]], List[Tuple[int, int, int]]]

Attempt to use the CCD record to assign the bond orders. Returns list of bonds that were assigned. Returns empty list if assignment was not successful.

Parameters
  • res – Residue for the het to assign orders to.

  • res_assign_atoms – List of atoms (substructure from the residue) to assign bond orders to. By default all residue atoms are assigned.

  • _logger – Logger

Returns

List of assigned charges and bonds

schrodinger.structutils.assignbondorders.orders_assigned(st, atoms=None, all=False)

Returns True if all bond orders are OK in the specified structure. Can be given a list of atoms to check bond orders of. If not list is specified and all flag is set to True, all atoms are checked; otherwise only atoms with a PDB convert error (appear orange in Maestro) are checked. NOTE: atoms and all options are mutually exclusinve.