Atom

class Atom(atnum=0, symbol=None, coords=None, unit='angstrom', bonds=None, mol=None, **other)[source]

A class representing a single atom in three dimensional space.

An instance of this class has the following attributes:

  • atnum – atomic number (zero for “dummy atoms”)

  • coords – tuple of length 3 storing spatial coordinates

  • bonds – list of bonds (see Bond) this atom is a part of

  • molMolecule this atom belongs to

  • propertiesSettings instance storing all other information about this atom (initially it is populated with **other)

The above attributes can be accessed either directly or using one of the following properties:

  • x, y, z – allow to read or modify each coordinate separately

  • symbol – allows to read or write the atomic symbol directly. Atomic symbol is not stored as an attribute, instead of that the atomic number (atnum) indicates the type of atom. In fact, symbol this is just a wrapper around atnum that uses PeriodicTable as a translator:

    >>> a = Atom(atnum=8)
    >>> print(a.symbol)
    O
    >>> a.symbol = 'Ca'
    >>> print(a.atnum)
    20
    
  • mass – atomic mass, obtained from PeriodicTable, read only

  • radius – atomic radius, obtained from PeriodicTable, read only

  • connectors – number of connectors, obtained from PeriodicTable, read only

Note

When creating a new atom, its type can be chosen either by setting an atomic number or a symbol (atnum and symbol constructor arguments). The symbol argument takes precedence – if it is supplied, the atnum argument is ignored.

Values stored in coords tuple do not necessarily have to be numeric, you can also store any string there. This might come handy for programs that allow parametrization of coordinates in the input file (to enforce some geometry constraints for example):

>>> a = Atom(symbol='C', coords=(1,2,3))
>>> print(a)
         C       1.00000       2.00000       3.00000
>>> a.y = 'param1'
>>> print(a)
         C       1.00000        param1       3.00000

However, non-numerical coordinates cannot be used together with some methods (for example distance_to() or translate()). An attempt to do this raises an exception.

Internally, atomic coordinates are always expressed in angstroms. Most of methods that read or modify atomic coordinates accept a keyword argument unit allowing to choose unit in which results and/or arguments are expressed (see Units for details). Throughout the entire code angstrom is the default length unit. If you don’t specify unit parameter in any place of your script, all the automatic unit handling described above boils down to occasional multiplication/division by 1.0.

__init__(atnum=0, symbol=None, coords=None, unit='angstrom', bonds=None, mol=None, **other)[source]

Initialize self. See help(type(self)) for accurate signature.

str(symbol=True, suffix='', suffix_dict={}, unit='angstrom', space=14, decimal=6)[source]

Return a string representation of this atom.

Returned string is a single line (no newline characters) that always contains atomic coordinates (and maybe more). Each atomic coordinate is printed using space characters, with decimal characters reserved for decimal digits. Coordinates values are expressed in unit.

If symbol is True, atomic symbol is added at the beginning of the line. If symbol is a string, this exact string is printed there.

suffix is an arbitrary string that is appended at the end of returned line. It can contain identifiers in curly brackets (like for example f={fragment}) that will be replaced by values of corresponding keys from suffix_dict dictionary. See Format String Syntax for details.

Example:

>>> a = Atom(atnum=6, coords=(1,1.5,2))
>>> print(a.str())
         C      1.000000      1.500000      2.000000
>>> print(a.str(unit='bohr'))
         C      1.889726      2.834589      3.779452
>>> print(a.str(symbol=False))
      1.000000      1.500000      2.000000
>>> print(a.str(symbol='C2.13'))
     C2.13      1.000000      1.500000      2.000000
>>> print(a.str(suffix='protein1'))
         C      1.000000      1.500000      2.000000 protein1
>>> a.properties.info = 'membrane'
>>> print(a.str(suffix='subsystem={info}', suffix_dict=a.properties))
         C      1.000000      1.500000      2.000000 subsystem=membrane
__str__()[source]

Return a string representation of this atom. Simplified version of str() to work as a magic method.

__iter__()[source]

Iteration through atom yields coordinates. Thanks to that instances of Atom can be passed to any method requiring as an argument a point or a vector in 3D space.

translate(vector, unit='angstrom')[source]

Move this atom in space by vector, expressed in unit.

vector should be an iterable container of length 3 (usually tuple, list or numpy array). unit describes unit of values stored in vector.

This method requires all atomic coordinates to be numerical values, TypeError is raised otherwise.

move_to(point, unit='angstrom')[source]

Move this atom to a given point in space, expressed in unit.

point should be an iterable container of length 3 (for example: tuple, Atom, list, numpy array). unit describes unit of values stored in point.

This method requires all atomic coordinates to be numerical values, TypeError is raised otherwise.

distance_to(point, unit='angstrom', result_unit='angstrom')[source]

Measure the distance between this atom and point.

point should be an iterable container of length 3 (for example: tuple, Atom, list, numpy array). unit describes unit of values stored in point. Returned value is expressed in result_unit.

This method requires all atomic coordinates to be numerical values, TypeError is raised otherwise.

vector_to(point, unit='angstrom', result_unit='angstrom')[source]

Calculate a vector from this atom to point.

point should be an iterable container of length 3 (for example: tuple, Atom, list, numpy array). unit describes unit of values stored in point. Returned value is expressed in result_unit.

This method requires all atomic coordinates to be numerical values, TypeError is raised otherwise.

angle(point1, point2, point1unit='angstrom', point2unit='angstrom', result_unit='radian')[source]

Calculate an angle between vectors pointing from this atom to point1 and point2.

point1 and point2 should be iterable containers of length 3 (for example: tuple, Atom, list, numpy array). Values stored in them are expressed in, respectively, point1unit and point2unit. Returned value is expressed in result_unit.

This method requires all atomic coordinates to be numerical values, TypeError is raised otherwise.

rotate(matrix)[source]

Rotate this atom according to a rotation matrix.

matrix should be a container with 9 numerical values. It can be a list (tuple, numpy array etc.) listing matrix elements row-wise, either flat ([1,2,3,4,5,6,7,8,9]) or in two-level fashion ([[1,2,3],[4,5,6],[7,8,9]]).

Note

This method does not check if matrix is a proper rotation matrix.

neighbors()[source]

Return a list of neighbors of this atom within the molecule. The list follows the same order as the bonds attribute.

Bond

class Bond(atom1=None, atom2=None, order=1, mol=None, **other)[source]

A class representing a bond between two atoms.

An instance of this class has the following attributes:

  • atom1 and atom2 – two instances of Atom that form this bond

  • order – order of the bond. It is either an integer number or the floating point value stored in Bond.AR, indicating an aromatic bond

  • molMolecule this bond belongs to

  • propertiesSettings instance storing all other information about this bond (initially it is populated with **other)

Note

Newly created bond is not added to atom1.bonds or atom2.bonds. Storing information about Bond in Atom is relevant only in the context of the whole Molecule, so this information is updated by add_bond().

__init__(atom1=None, atom2=None, order=1, mol=None, **other)[source]

Initialize self. See help(type(self)) for accurate signature.

__str__()[source]

Return a string representation of this bond.

__iter__()[source]

Iterate over bonded atoms (atom1 first, then atom2).

is_aromatic()[source]

Check if this bond is aromatic.

length(unit='angstrom')[source]

Return bond length, expressed in unit.

as_vector(start=None, unit='angstrom')[source]

Return a vector between two atoms that form this bond. start can be used to indicate which atom should be the beginning of that vector. If not specified, self.atom1 is used. Returned value if a tuple of length 3, expressed in unit.

other_end(atom)[source]

Return the atom on the other end of this bond with respect to atom. atom has to be one of the atoms forming this bond, otherwise an exception is raised.

resize(moving_atom, length, unit='angstrom')[source]

Change the length of this bond to length expressed in unit by moving moving_atom.

moving_atom should be one of the atoms that form this bond. This atom is moved along the bond axis in such a way that new bond length equals length. If this bond is a part of a Molecule the whole part connected to moving_atom is moved.

Note

Calling this method on a bond that forms a ring within a molecule raises a MoleculeError.

rotate(moving_atom, angle, unit='radian')[source]

Rotate part of the molecule containing moving_atom along axis defined by this bond by an angle expressed in unit.

Calling this method makes sense only if this bond is a part of a Molecule. moving_atom should be one of the atoms that form this bond and it indicates which part of the molecule is rotated. A positive value of angle denotes counterclockwise rotation (when looking along the bond, from the stationary part of the molecule).

Note

Calling this method on a bond that forms a ring raises a MoleculeError.