diff --git a/doc/conf/conf.py b/doc/conf/conf.py
index d3d1736f31af330ec5491d2bf6004d4a22ed7537..6de040bb6a3fdcb816eb79c7fe00f45eb0205bb9 100644
--- a/doc/conf/conf.py
+++ b/doc/conf/conf.py
@@ -79,7 +79,7 @@ exclude_trees = []
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+add_module_names = False
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
diff --git a/modules/bindings/doc/bindings.rst b/modules/bindings/doc/bindings.rst
new file mode 100644
index 0000000000000000000000000000000000000000..fc5357608c5a09becf40ba13b0ebed59fe634769
--- /dev/null
+++ b/modules/bindings/doc/bindings.rst
@@ -0,0 +1,19 @@
+:mod:`~ost.bindings` -- Interfacing external programs
+================================================================================
+
+.. module:: ost.bindings
+   :synopsis: Contains bindings for external programs
+
+The bindings module contains functions and classes that interface with command-line programs commonly used in bioinformatics.
+
+If you would like to write your own wrapper, consult :doc:`../external`.
+
+So far, the binding module includes:
+
+.. toctree::
+  :maxdepth: 1
+
+  dssp
+  blast
+  msms
+  tmtools
diff --git a/modules/bindings/doc/blast.rst b/modules/bindings/doc/blast.rst
new file mode 100644
index 0000000000000000000000000000000000000000..2154bddc6b74013bd320034aa56112c97a09c4dc
--- /dev/null
+++ b/modules/bindings/doc/blast.rst
@@ -0,0 +1,16 @@
+:mod:`~ost.bindings.blast` - Search related sequences in databases
+================================================================================
+
+.. module:: ost.bindings.blast
+  :synopsis: Search related sequences in databases
+
+
+.. autofunction:: ost.bindings.blast.Blast
+
+.. autofunction:: ost.bindings.blast.ParseBlastOutput
+
+.. autoclass:: ost.bindings.blast.AlignedPatch
+
+.. autoclass:: ost.bindings.blast.BlastHit
+
+.. autoclass:: ost.bindings.blast.BlastError
diff --git a/modules/bindings/doc/dssp.rst b/modules/bindings/doc/dssp.rst
new file mode 100644
index 0000000000000000000000000000000000000000..61de495e34f920e85bc801800feb24c4ca5a3305
--- /dev/null
+++ b/modules/bindings/doc/dssp.rst
@@ -0,0 +1,31 @@
+:mod:`~ost.bindings.dssp` - Secondary structure assignment
+================================================================================
+
+.. module:: ost.bindings.dssp
+  :synopsis: Interface to the DSSP commandline utility
+
+Introduction
+--------------------------------------------------------------------------------
+
+DSSP is a program developed by Wolfgang Kabsch and Chris Sander to assign secondary structure states to protein structures. The assignment is based on hydrogen bonding patterns and geometric features.
+
+The program can be downloaded from `<http://swift.cmbi.ru.nl/gv/dssp/>`_.
+
+Example
+--------------------------------------------------------------------------------
+
+The following example assigns secondary structure states to an entity by using the DSSP program.
+
+
+.. code-block:: python
+
+  from ost.bindings import dssp
+  ent=io.LoadPDB('1ake.pdb')
+  dssp.AssignDSSP(ent)
+
+DSSP bindings Usage
+--------------------------------------------------------------------------------
+
+.. autofunction:: ost.bindings.dssp.AssignDSSP
+
+.. autofunction:: ost.bindings.dssp.LoadDSSP
diff --git a/modules/bindings/doc/msms.rst b/modules/bindings/doc/msms.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0085571c0a063b15bb78e7ecb6dded7a89ad24ef
--- /dev/null
+++ b/modules/bindings/doc/msms.rst
@@ -0,0 +1,11 @@
+:mod:`~ost.bindings.msms` -- Calculating Molecular Surfaces
+================================================================================
+
+.. currentmodule:: ost.bindings.msms
+
+
+.. autoclass:: ost.bindings.msms.MsmsProcessError
+
+.. autofunction:: ost.bindings.msms.CalculateSurfaceArea
+
+.. autofunction:: ost.bindings.msms.CalculateSurface
diff --git a/modules/bindings/doc/tmtools.rst b/modules/bindings/doc/tmtools.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7192e730d99e39c9a408b3687cc69e06b9cc6942
--- /dev/null
+++ b/modules/bindings/doc/tmtools.rst
@@ -0,0 +1,69 @@
+:mod:`~ost.bindings.tmtools` - Structural superposition
+================================================================================
+
+.. module:: ost.bindings.tmtools
+  :synopsis: Sequence dependent and independent structure superposition
+
+The :mod:`~ost.bindings.tmtools` module provides access to the structural 
+superposition programs TMscore, Tmalign and MMalign developed by Y. Zhang 
+and J. Skolnick. These programs superpose a model onto a reference structure, 
+using the positions of the Calpha atoms only. While at their core, these 
+programs essentially use the same algorithm, they differ on how the Calphas are 
+paired. TMscore pairs the Calpha atom based on the residue number, TMalign 
+calculates an optimal pairing of Calpha atom based on heuristics.
+
+Citation:
+
+  Yang Zhang and Jeffrey Skolnick, Proteins 2004 57: 702-710
+  Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9
+
+Distance measures used by TMscore
+--------------------------------------------------------------------------------
+
+There are many different ways to describe the structural similarity of two 
+protein structures at the Calpha level. TMscore calculate several of these 
+measures. The most common is to describe the difference in terms of the root 
+mean square deviation of the Calpha positions, the RMSD. Despite its common use, 
+RMSD has several drawbacks when working with incomplete models. Since the RMSD 
+highly depends on the set of included atoms, it is relatively easy to obtain a 
+smaller RMSD by omitting flexible parts of a protein structure. This has lead to 
+the introduction of the global distance test (GDT). A model is compared to a 
+reference by calculating the fraction of Calpha atoms that can be superposed 
+below a certain cutoff, e.g. 1Å. The fractions of several such cutoffs are 
+combined into the GDT_TS (1, 2, 4 and 8Å) and GDT_HA (0.5, 1, 2, 4Å) and divided 
+by four to obtain the final measure. In contrast to RSMD, GDT is an agreement 
+measure. The higher the value, the more similar the two structures are. TM-score 
+(not to be confused by TMscore, the program), additionally adds a size 
+dependences to the GDT measure by taking the protein length into account. As 
+with GDT, the bigger the value, the more similar the two structures are.
+
+Common Usage
+--------------------------------------------------------------------------------
+
+The following example shows how to use TMscore to superpose two protein 
+structures and print the RMSD as well as the GDT_TS and GDT_HA similarity measures.
+
+.. code-block:: python
+
+  from ost.bindings import tmtools
+  
+  pdb1=io.LoadPDB('1ake.pdb', restrict_chains='A')
+  pdb2=io.LoadPDB('4ake.pdb', restrict_chains='A')
+  result=tmtools.TMScore(pdb1, pdb2)
+  print result.rmsd_below_five # 1.9
+  print result.gdt_ha # 0.41
+  print result.gdt_ts # 0.56
+
+Usage of TMalign
+--------------------------------------------------------------------------------
+
+.. autofunction:: ost.bindings.tmtools.TMAlign
+
+.. autoclass:: ost.bindings.tmtools.TMAlignResult
+
+Usage of TMscore
+--------------------------------------------------------------------------------
+
+.. autofunction:: ost.bindings.tmtools.TMScore
+
+.. autoclass:: ost.bindings.tmtools.TMScoreResult
diff --git a/modules/bindings/pymod/__init__.py b/modules/bindings/pymod/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..388a6054e165dc7fdd572892a11abb4f5f69ae62 100644
--- a/modules/bindings/pymod/__init__.py
+++ b/modules/bindings/pymod/__init__.py
@@ -0,0 +1,7 @@
+from ost.bindings import dssp
+from ost.bindings import msms
+from ost.bindings import blast
+from ost.bindings import tmtools
+from ost.bindings import naccess
+from ost.bindings import hbplus
+from ost.bindings import clustalw
\ No newline at end of file
diff --git a/modules/bindings/pymod/blast.py b/modules/bindings/pymod/blast.py
index 32e36e3bf37fd4860111b76425efea56c8547659..054bff58c0575848d08642a6f935c09c7912df98 100644
--- a/modules/bindings/pymod/blast.py
+++ b/modules/bindings/pymod/blast.py
@@ -5,7 +5,30 @@ from ost import io, seq
 import ost
 import re
 import os
+
 class AlignedPatch:
+  """
+  An aligned patch, aka. HSP
+
+  .. attribute:: aln
+
+    The local alignment. Sequence offset of both sequences in the alignment are
+    set to the starting position in the query and target sequence, respectively.
+
+    :type: :class:`~ost.seq.AlignmentHandle`
+
+  .. attribute:: bit_score
+
+    The bit score of the HSP
+
+  .. attribute:: score
+
+    The score of the HSP
+
+  .. attribute:: evalue
+
+    The E-value of the HSP
+  """
   def __init__(self, aln, bit_score, score, evalue):
     self.aln=aln
     self.bit_score=bit_score
@@ -16,16 +39,51 @@ class BlastHit:
   """
   A positive match found by BLAST.
   
-  Each blast hit consists of one or more aligned patches. 
+  Each blast hit consists of one or more HSPs, encoded by the
+  :class:`AlignedPatch` class.
   
+  .. attribute:: identifier
+
+    The identifier of the matching sequence
+
+  .. attribute:: aligned_patches
+
+    list of :class:`AlignedPatch` instances holding the actual HSPs.
   """
   def __init__(self, identifier, aligned_patches):
     self.identifier=identifier
     self.aligned_patches=aligned_patches
 
+class BlastError(RuntimeError):
+  """
+  Raised when something goes wrong during parsing/execution of the blast
+  executable.
+
+  .. attribute:: brief
+
+    Short explanation of the problem
+
+  .. attribute:: details
+
+    If set, explains in more detail what caused the error. Might be empty.
+  """
+  def __init__(self, brief, details):
+    self.brief=brief
+    self.details=details
+
+  def __str__(self):
+    if self.details:
+      return '%s\n%s' % (self.brief, self.details)
+    else:
+      return self.brief
+
 def ParseBlastOutput(string):
   """
-  Parses the blast output and returns a list of BlastHits
+  Parses the blast output and returns a list of :class:`BlastHit` instances.
+
+  :raises: :class:`BlastError` if the output could not be parsed.
+
+  This functions is only capable of dealing with the BLAST XML output.
   """
   def _GetText(node):
     rc=''
@@ -57,8 +115,7 @@ def ParseBlastOutput(string):
   try:
     doc=minidom.parseString(string)
   except Exception, e:
-    ost.LogError('Error while parsing BLAST output: %s' % str(e))
-    return None
+    raise BlastError('Error while parsing BLAST output: %s' % str(e), '')
   hits=[]
   query_id=_GetValue(doc, 'BlastOutput_query-def')
   for hit in doc.getElementsByTagName('Hit'):
@@ -69,18 +126,6 @@ def ParseBlastOutput(string):
   return hits
 
 
-
-class BlastError(RuntimeError):
-  def __init__(self, brief, details):
-    self.brief=brief
-    self.details=details
-
-  def __str__(self):
-    if self.details:
-      return '%s\n%s' % (self.brief, self.details)
-    else:
-      return self.brief
-
 def Blast(query, database, gap_open=11, gap_ext=1, matrix='BLOSUM62',
          blast_location=None):
   """
@@ -100,6 +145,12 @@ def Blast(query, database, gap_open=11, gap_ext=1, matrix='BLOSUM62',
   :param gap_ext: Gap extension penalty. Only a subset of gap extension 
      penalties are supported for each of the substitution matrices. Consult the 
      blast docs for more information.
+
+  :raises: :class:`~ost.settings.FileNotFound` if the BLAST executable could not 
+           be found
+  :raises: :class:`BlastError` if there was a problem during execution of BLAST.
+  :raises: :class:`ValueError` if the substitution matrix is invalid
+  :raises: :class:`IOError` if the database does not exist
   """
   subst_mats=('BLOSUM45', 'BLOSUM62', 'BLOSUM80', 'PAM30', 'PAM70',)
   if matrix not in subst_mats:
diff --git a/modules/bindings/pymod/dssp.py b/modules/bindings/pymod/dssp.py
index 234ba74067f1dd977f0b5018ab22984caf70d930..56f78bd059a60e73977ef918614c6945d030c989 100644
--- a/modules/bindings/pymod/dssp.py
+++ b/modules/bindings/pymod/dssp.py
@@ -38,16 +38,21 @@ def _SkipHeader(stream):
       line=stream.readline()
     return False
 
+def _Cleanup(pdb_path, temp_path, entity_saved):
+  if entity_saved and os.path.exists(pdb_path):
+    os.remove(pdb_path)
+  if os.path.exists(temp_path):
+    os.remove(temp_path)
 
 def _ExecuteDSSP(path, temp_dir=None):
   # use of mktemp is a safty problem (use mkstemp and provide file handle to 
   # subsequent process
   temp_dssp_path=tempfile.mktemp(suffix=".out",prefix="dssp", dir=temp_dir)
   dssp_abs_path=settings.Locate('dssp', env_name='DSSP_EXECUTABLE')
-  command=dssp_abs_path+" "+path+" "+temp_dssp_path
-  ps=subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
+  assert os.path.exists(path)
+  ps=subprocess.Popen([dssp_abs_path, path, temp_dssp_path], 
+                      stderr=subprocess.PIPE)
   err_lines=ps.stderr.readlines()
-
   return temp_dssp_path
 
 
@@ -55,7 +60,10 @@ def _CalcRelativeSA(residue_type, absolute_sa):
   solvent_max_list=[118,317,238,243,183,262,286,154,258,228,
                     243,278,260,271,204,234,206,300,303,216] #TODO: source?
   residue_indices = "ARNDCQEGHILKMFPSTWYV"
-  if residue_type.islower()==True:
+  # cysteine bridges are marked with lower-case letters by DSSP. We don't 
+  # really care which cysteines are forming covalent bonds, so let's set the 
+  # one-letter-code to "C".
+  if residue_type.islower():
     residue_type='C'
   if residue_indices.find(residue_type)==-1:
     raise RuntimeError('residue %s is a non-standard residue' %(residue_type))	
@@ -64,14 +72,30 @@ def _CalcRelativeSA(residue_type, absolute_sa):
   return rel
   
 
-def AssignDSSP(ent, pdb_path="", extract_burial_status_flag=0, tmp_dir=None):
-  entity_saved_flag = 0
+def AssignDSSP(ent, pdb_path="", extract_burial_status=False, tmp_dir=None):
+  """
+  Assign secondary structure states to peptide residues in the structure. This
+  function uses the DSSP command line program.
+
+  If you already have a DSSP output file and would like to assign the secondary 
+  structure states to an entity, use :func:`LoadDSSP`.
+  
+  :param ent: The entity for which the secondary structure should be calculated
+  :type ent: :class:`~ost.mol.EntityHandle` or :class:`~ost.mol.EntityView`
+  :param extract_burial_status: If true, also extract burial status
+  :param tmp_dir: If set, overrides the default tmp directory of the
+                  operating system
+
+  :raises: :class:`~ost.settings.FileNotFound` if the dssp executable is not 
+      in the path.
+  """
+  entity_saved = False
   # use of mktemp is a safty problem (use mkstemp and provide file handle to 
   # subsequent process
   pdb_path=tempfile.mktemp(suffix=".pdb",prefix="temp_entity", 
-			    dir=tmp_dir)
-  io.SaveEntity(ent, pdb_path)
-  entity_saved_flag = 1
+                           dir=tmp_dir)
+  io.SavePDB(ent, pdb_path)
+  entity_saved = True
 
   #TODO: exception handling (currently errors occuring here
   # are handled in the parser LoadDSSP)
@@ -79,30 +103,45 @@ def AssignDSSP(ent, pdb_path="", extract_burial_status_flag=0, tmp_dir=None):
 
   # assign DSSP to entity
   try:
-    LoadDSSP(temp_dssp_path, ent, extract_burial_status_flag, 
-             entity_saved_flag)
+    LoadDSSP(temp_dssp_path, ent, extract_burial_status,
+             entity_saved)
   except Exception, e:
     # clean up
     print "Exception in DSSP:", e
-    if entity_saved_flag == 1:
-      os.remove(pdb_path)
-    os.remove(temp_dssp_path)
+    _Cleanup(pdb_path, temp_dssp_path, entity_saved)
     raise RuntimeError(e)
 
   # clean up
   #print pdb_path, temp_dssp_path
-  if entity_saved_flag == 1:
-    os.remove(pdb_path)
-  os.remove(temp_dssp_path)
+  _Cleanup(pdb_path, temp_dssp_path, entity_saved)
 
   return ent
 
 
 
-def LoadDSSP(file_name, model, extract_burial_status_flag=0, 
-             entity_saved_flag=0, calculate_relative_sa=True):
-    if model.IsValid() == 0:
-      print "DSSP: model is not valid"
+def LoadDSSP(file_name, model, extract_burial_status=False,
+             entity_saved=False, calculate_relative_sa=True):
+    """
+    Loads DSSP output and assigns secondary structure states to the peptidic
+    residues.
+
+    If you would like to run dssp *and* assign the secondary structure,
+    use :func:`AssignDSSP` instead.
+
+    :param file_name: The filename of the DSSP output file
+    :param model: The entity to which the secondary structure states should be
+                  assigned
+    :param extract_burial_status: If true also calculates burial status of
+        residues and assigns it to the burial_status string property.
+    :param calculate_relative_sa: If true also relative solvent accessibility and
+        and assigns it to the relative_solvent_accessibility float property of
+        the residue.
+    :param entity_save: Whether the entity was saved.
+    """
+    if not model.IsValid():
+      raise ValueError('model entity is not valid')
+    if model.atom_count==0:
+      raise ValueError('model entity does not contain any atoms')
     stream=open(file_name)
     if not _SkipHeader(stream):
       stream.close()
@@ -135,24 +174,24 @@ def LoadDSSP(file_name, model, extract_burial_status_flag=0,
           residue=chain.FindResidue(mol.ResNum(int(num),ins_code))
 
         # set property "burial status:
-        if extract_burial_status_flag == 1:
-         #set default (dummy) burial status for incomplete residues:
-         residue.SetStringProp("burial_status", 'X')
-
-         #handle seleno-methionine appearing as amino acid 'X' in DSSP:
-         if residue.name=="MSE" and amino_acid=='X':
-           amino_acid='M'
-
-         residue.SetFloatProp("solvent_accessibility", 
-                                         solvent_accessibility)
-         if calculate_relative_sa:
-           relative_sa=_CalcRelativeSA(amino_acid,solvent_accessibility)
-           residue.SetFloatProp("relative_solvent_accessibility", 
-                                           relative_sa)
-           if relative_sa < 0.25:
-             residue.SetStringProp("burial_status", 'b')
-           else:
-             residue.SetStringProp("burial_status", 'e')
+        if extract_burial_status:
+          #set default (dummy) burial status for incomplete residues:
+          residue.SetStringProp("burial_status", 'X')
+
+          #handle seleno-methionine appearing as amino acid 'X' in DSSP:
+          if residue.name=="MSE" and amino_acid=='X':
+            amino_acid='M'
+
+          residue.SetFloatProp("solvent_accessibility",
+                                          solvent_accessibility)
+          if calculate_relative_sa:
+            relative_sa=_CalcRelativeSA(amino_acid,solvent_accessibility)
+            residue.SetFloatProp("relative_solvent_accessibility",
+                                            relative_sa)
+            if relative_sa < 0.25:
+              residue.SetStringProp("burial_status", 'b')
+            else:
+              residue.SetStringProp("burial_status", 'e')
       except Exception, e:
         print "ERROR:",e
         continue
@@ -174,7 +213,7 @@ def LoadDSSP(file_name, model, extract_burial_status_flag=0,
       elif rtype=='G':
         rt=mol.SecStructure.THREE_TEN_HELIX
       # for corrupted DSSP files. Catch in calling routine:
-      if residue.IsValid() == 0:
+      if not residue.IsValid():
         #Todo: if residues with occupancy 0 have been removed before
         #using a selection statement, they are missed here
         #IMPORTANT: asign DSSP before any selections
diff --git a/modules/bindings/pymod/msms.py b/modules/bindings/pymod/msms.py
index d928f6c57ae1ddcdd8abd0f1af3d3163e070eac0..92f9494cf836c149e5a4330e922c008c63ba9c2f 100644
--- a/modules/bindings/pymod/msms.py
+++ b/modules/bindings/pymod/msms.py
@@ -25,12 +25,11 @@ from ost import settings
 from ost import geom
 
 
-
-## \brief custom exception that substitutes CalledProcessError
-#
-# Python 2.4 does not include the CalledProcessError exception.
-# This one substitutes it 
 class MsmsProcessError(Exception):
+  """
+  Python 2.4 and older do not include the CalledProcessError exception. This
+  class substitutes it.
+  """
   def __init__(self, returncode,command):
     self.returncode = returncode
     self.command = command
@@ -39,6 +38,9 @@ class MsmsProcessError(Exception):
 
 
 def GetVersion(msms_exe=None, msms_env=None):
+  """
+  Get version of MSMS executable
+  """
   msms_executable = _GetExecutable(msms_exe, msms_env)
   command = "%s" % (msms_executable)
   proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
@@ -53,24 +55,32 @@ def GetVersion(msms_exe=None, msms_env=None):
     LogWarning('Could not parse MSMS version string')
     return
 
-## \brief Method to check if MSMS executable is present
-#
-# \param msms_exe Explicit path to msms executable
-# \param msms_env Environment variable pointing to msms executable
-# \return         Path to the executable
-# \exception      FileNotFound if executable is not found
+
 def _GetExecutable(msms_exe, msms_env):
+  """
+  Function to check if MSMS executable is present
+
+  :param msms_exe: Explicit path to msms executable
+  :param msms_env: Environment variable pointing to msms executable
+  :returns: Path to the executable
+  :raises:  :class:`~ost.FileNotFound` if executable is not found
+  """
   return settings.Locate('msms', explicit_file_name=msms_exe,
                          env_name=msms_env)
 
-## \brief Setup files for MSMS calculation in temporary directory
-#
-# \param entity      EntityHandle or EntityView to calculate surface
-# \param selection   Calculate surface for subset of entity 
-# \return            Touple containing temporary directory and msms input file
-# \exception         RuntimeError if selection is not valid
+
 def _SetupFiles(entity, selection):
-  # create temporary directory
+  """
+  Setup files for MSMS calculation in temporary directory
+
+  :param entity: The entity for which the surface is to be calculated
+  :type entity: :class:`~ost.mol.EntityHandle` or :class:`~ost.mol.EntityHandle`
+  :param selection:  Calculate surface for subset of entity
+  :type selection: :class:`str`
+  :returns: tuple containing temporary directory and msms input file
+  :raises:         :class:`RuntimeError` if selection is not valid
+  """
+  #   create temporary directory
   tmp_dir_name=tempfile.mkdtemp()
 
   # select only heavy atoms if no_hydrogens is true
@@ -89,46 +99,55 @@ def _SetupFiles(entity, selection):
   
   return (tmp_dir_name, tmp_file_name)
 
-## \brief Reads Area file (-af) and attach sasa and sesa per atom to an entitiy
-#
-# \param entity   EntityHandle or EntityView for attaching sasa and sesa on atom level
-# \param file     Filename of area file
-# \param asa_prop Name of the float property for SASA
-# \param esa_prop Name of the float property for SESA
-# \exception RuntimeError if number of atoms in file != number of atoms in entity 
+
 def _ParseAreaFile(entity,file, asa_prop, esa_prop):
-    area_fh = open(file)
-    area_lines = area_fh.readlines()
-    area_fh.close()
-    # shift first line
-    area_lines = area_lines[1:]
-    if entity.GetAtomCount() != len(area_lines):
-        raise RuntimeError, "Atom count (%d) unequeal to number of atoms in area file (%d)" % (entity.GetAtomCount(), len(area_lines))
-    for l in area_lines:
-        atom_no, sesa, sasa = l.split()
-        a = entity.atoms[int(atom_no)]
-        if asa_prop:
-          a.SetFloatProp(asa_prop, float(sasa))
-        if esa_prop:
-          a.SetFloatProp(esa_prop, float(sesa))
+  """
+   Reads Area file (-af) and attach sasa and sesa per atom to an entitiy
+
+  :param entity:   :class:`~ost.mol.EntityHandle` or :class:`~ost.mol.EntityView`
+                   for attaching sasa and sesa on atom level
+  :param file:     Filename of area file
+  :param asa_prop: Name of the float property for SASA
+  :param esa_prop: Name of the float property for SESA
+  :raises: :class:`RuntimeError` if number of atoms in file != number of atoms in entity
+  """
+  area_fh = open(file)
+  area_lines = area_fh.readlines()
+  area_fh.close()
+  # shift first line
+  area_lines = area_lines[1:]
+  if entity.GetAtomCount() != len(area_lines):
+      raise RuntimeError, "Atom count (%d) unequeal to number of atoms in area file (%d)" % (entity.GetAtomCount(), len(area_lines))
+  for l in area_lines:
+      atom_no, sesa, sasa = l.split()
+      a = entity.atoms[int(atom_no)]
+      if asa_prop:
+        a.SetFloatProp(asa_prop, float(sasa))
+      if esa_prop:
+        a.SetFloatProp(esa_prop, float(sesa))
     
     
-## \brief Method which recursively deletes a directory
-#
-# \warning This method removes also non-empty directories without asking, so
-#          be careful!
-def __CleanupFiles(dir_name):
+
+def _CleanupFiles(dir_name):
+  """
+  Function which recursively deletes a directory and all the files contained
+  in it. *Warning*: This method removes also non-empty directories without
+  asking, so be careful!
+  """
   import shutil
   shutil.rmtree(dir_name)
 
-## \brief Method to run the MSMS surface calculation
-#
-# This method starts the external MSMS executable and returns the stdout of MSMS
-#
-# \param command          Command to execute
-# \return                 stdout of MSMS
-# \exception              CalledProcessError for non-zero return value
 def _RunMSMS(command):
+  """
+  Run the MSMS surface calculation
+
+  This functions starts the external MSMS executable and returns the stdout of
+  MSMS.
+
+  :param command:          Command to execute
+  :returns:                 stdout of MSMS
+  :raises:              :class:`CalledProcessError` for non-zero return value
+  """
   proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
   stdout_value, stderr_value = proc.communicate()
 
@@ -140,33 +159,36 @@ def _RunMSMS(command):
   return stdout_value
   
 
-## \brief Calculates analytical solvent excluded and solvent accessible surface
-#  area by using the external MSMS program
-#
-# This method calculates the molecular surface areas by invoking the external
-# program MSMS. First, it is checked if the MSMS executable is present, then, 
-# the necessary files are prepared in a temporary directory and MSMS is
-# executed. The last step is to remove the temporary directory.
-# 
-#
-# \param entity        OST entity to calculate surface
-# \param density       Surface point density
-# \param radius        Surface probe radius
-# \param all_surf      Calculate surface area for all cavities (returns multiple
-#                      surfaces areas as a list)
-# \param no_hydrogens  Calculate surface only for hevy atoms
-# \param selection     Calculate surface for subset of entity
-# \param msms_exe      msms executable (full path to executable)
-# \param msms_env      msms environment variable
-# \param keep_files    Do not delete temporary files
-# \param attach_asa    Attaches per atom SASA to specified FloatProp at atom level
-# \param attach_esa    Attaches per atom SESA to specified FloatProp at atom level
-# \return              Touplet of lists for (SES, SAS)
+
 def CalculateSurfaceArea(entity, density=1.0, radius=1.5,  all_surf=False,
                          no_hydrogens=False, no_hetatoms=False, no_waters=False,
                          selection='',
                          msms_exe=None, msms_env=None, keep_files=False, 
                          attach_asa=None, attach_esa=None):
+  """
+  Calculates analytical solvent excluded and solvent accessible surface
+  area by using the external MSMS program.
+
+  This method calculates the molecular surface areas by invoking the external
+  program MSMS. First, it is checked if the MSMS executable is present, then,
+  the necessary files are prepared in a temporary directory and MSMS is
+  executed. The last step is to remove the temporary directory.
+
+
+  :param entity:        OST entity to calculate surface
+  :param density:       Surface point density
+  :param radius:       Surface probe radius
+  :param all_surf:      Calculate surface area for all cavities (returns multiple
+      surfaces areas as a list)
+  :param no_hydrogens:  Calculate surface only for hevy atoms
+  :param selection:     Calculate surface for subset of entity
+  :param msms_exe:      msms executable (full path to executable)
+  :param msms_env:      msms environment variable
+  :param keep_files:    Do not delete temporary files
+  :param attach_asa:    Attaches per atom SASA to specified FloatProp at atom level
+  :param attach_esa:    Attaches per atom SESA to specified FloatProp at atom level
+  :returns:             Tuple of lists for (SES, SAS)
+  """
   import re 
 
   # check if msms executable is specified
@@ -222,35 +244,38 @@ def CalculateSurfaceArea(entity, density=1.0, radius=1.5,  all_surf=False,
 
   # clean up
   if not keep_files:
-    __CleanupFiles(msms_data_dir)
+    _CleanupFiles(msms_data_dir)
 
   return (msms_ases, msms_asas)
   
 
-## \brief Calculates molecular surface by using the external MSMS program
-#
-# This method calculates a molecular surface by invoking the external program
-# MSMS. First, it is checked if the MSMS executable is present, then, the
-# necessary files are prepared in a temporary directory and MSMS is executed.
-# The last step is to remove the temporary directory.
-# 
-#
-# \param entity        OST entity to calculate surface
-# \param density       Surface point density
-# \param radius        Surface probe radius
-# \param all_surf      Calculate surface for all cavities (returns multiple
-#                      surfaces as a list)
-# \param no_hydrogens  Calculate surface only for hevy atoms
-# \param selection     Calculate surface for subset of entity
-# \param msms_exe      msms executable (full path to executable)
-# \param msms_env      msms environment variable
-# \param keep_files    Do not delete temporary files
-# \return list of OST SurfaceHandle objects
+
 def CalculateSurface(entity, density=1.0, radius=1.5, all_surf=False,
                      no_hydrogens=False, no_hetatoms=False, no_waters=False,
                      selection='',
                      msms_exe=None, msms_env=None, keep_files=False):
   
+  """
+  Calculates molecular surface by using the external MSMS program
+
+  This method calculates a molecular surface by invoking the external program
+  MSMS. First, it is checked if the MSMS executable is present, then, the
+  necessary files are prepared in a temporary directory and MSMS is executed.
+  The last step is to remove the temporary directory.
+
+
+  :param entity:        Entity for which the surface is to be calculated
+  :param density:       Surface point density
+  :param radius:        Surface probe radius
+  :param all_surf:      Calculate surface for all cavities (returns multiple
+                        surfaces as a list)
+  :param no_hydrogens:  Calculate surface only for hevy atoms
+  :param selection:     Calculate surface for subset of entity
+  :param msms_exe:      msms executable (full path to executable)
+  :param msms_env:      msms environment variable
+  :param keep_files:    Do not delete temporary files
+  :returns:             list of :class:`~ost.mol.SurfaceHandle` objects
+  """
   import os
   import re
 
@@ -300,7 +325,7 @@ def CalculateSurface(entity, density=1.0, radius=1.5, all_surf=False,
 
   # clean up
   if not keep_files:
-    __CleanupFiles(msms_data_dir)
+    _CleanupFiles(msms_data_dir)
 
   return msms_surfaces
 
diff --git a/modules/bindings/pymod/tmtools.py b/modules/bindings/pymod/tmtools.py
index df545b9c116e10ccca2a8d4ece559a2d5fc21f78..2b0c712149e3337de117812fa12b82af58917e46 100644
--- a/modules/bindings/pymod/tmtools.py
+++ b/modules/bindings/pymod/tmtools.py
@@ -43,7 +43,35 @@ def _CleanupFiles(dir_name):
   shutil.rmtree(dir_name)
 
 class TMAlignResult:
-  def __init__(self, rmsd, tm_score, aligned_length, transform, ref_sequence, alignment):
+  """
+  Holds the result of running TMalign
+  
+  .. attribute:: rmsd
+    
+    The RMSD of the common Calpha atoms of both structures
+  
+  .. attribute:: transform
+  
+    The transform that superposes the model onto the reference structure.
+    
+    :type: :class:`~ost.geom.Mat4`
+  
+  .. attribute:: alignment
+  
+    The alignment of the structures, that is the pairing of Calphas of both 
+    structures. Since the programs only read ATOM records, residues consisting 
+    of HETATMs (MSE) are not included in the alignment.
+    
+    :type: :class:`~ost.seq.AlignmentHandle`
+
+  .. attribute:: tm_score
+
+    The TM-score of the structural superposition
+
+  """
+  def __init__(self, rmsd, tm_score, aligned_length, transform, 
+               ref_sequence, alignment):
+    
     self.rmsd=rmsd
     self.tm_score=tm_score    
     self.aligned_length=aligned_length
@@ -133,6 +161,36 @@ def _RunMmAlign(mmalign, tmp_dir):
   return _ParseMmAlign(lines)
 
 class TMScoreResult:
+  """
+  Holds the result of running TMscore
+  
+  .. attribute:: rmsd_common
+    
+    The RMSD of the common Calpha atoms of both structures
+
+    .. attribute:: rmsd_below_five
+
+      The RMSD of all Calpha atoms that can be superposed below five Angstroem
+    
+  .. attribute:: tm_score
+  
+    The TM-score of the structural superposition
+  
+  .. attribute:: transform
+  
+    The transform that superposes the model onto the reference structure.
+    
+    :type: :class:`~ost.geom.Mat4`
+  
+  .. attribute:: gdt_ha
+  
+    The GDT_HA of the model to the reference structure.
+
+  .. attribute:: gdt_ts
+
+    The GDT_TS of the model to the reference structure.
+
+  """
   def __init__(self, rmsd_common, tm_score, max_sub, 
                gdt_ts, gdt_ha, rmsd_below_five, transform):
     self.rmsd_common=rmsd_common
@@ -182,7 +240,21 @@ def _RunTmScore(tmscore, tmp_dir):
 
 def TMAlign(model1, model2, tmalign=None):
   """
-  Run tmalign on two protein structures
+  Performs a sequence independent superposition of model1 onto model2, the 
+  reference.
+  
+
+  :param model1: The model structure. If the superposition is successful, will 
+                 be superposed onto the reference structure
+  :type model1: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
+  :param model2: The reference structure
+  :type model2: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
+  :param tmalign: If not None, the path to the tmalign executable.
+  :returns: The result of the tmscore superposition
+  :rtype: :class:`TMAlignResult`
+  
+  :raises: :class:`~ost.settings.FileNotFound` if tmalign could not be located.
+  :raises: :class:`RuntimeError` if the superposition failed
   """
   tmp_dir_name=_SetupFiles((model1, model2))
   result=_RunTmAlign(tmalign, tmp_dir_name)
@@ -202,7 +274,20 @@ def MMAlign(model1, model2, mmalign=None):
 
 def TMScore(model1, model2, tmscore=None):
   """
-  Run tmscore on two protein structures
+  Performs a sequence dependent superposition of model1 onto model2, 
+  the reference.
+
+  :param model1: The model structure. If the superposition is successful, will 
+                 be superposed onto the reference structure
+  :type model1: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
+  :param model2: The reference structure
+  :type model2: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
+  :param tmscore: If not None, the path to the tmscore executable.
+  :returns: The result of the tmscore superposition
+  :rtype: :class:`TMScoreResult`
+  
+  :raises: :class:`~ost.settings.FileNotFound` if tmalign could not be located.
+  :raises: :class:`RuntimeError` if the superposition failed
   """
   tmp_dir_name=_SetupFiles((model1, model2))
   result=_RunTmScore(tmscore, tmp_dir_name)
diff --git a/modules/index.rst b/modules/index.rst
index d44b3aaa9c303f3d9818a072afbfeddebe9a614a..05c38c4dc9b944734eefbcf037196fe2f788ebc2 100644
--- a/modules/index.rst
+++ b/modules/index.rst
@@ -18,6 +18,8 @@ OpenStructure documentation
   seq/base/seq
   seq/alg/seqalg
 
+  bindings/bindings
+
   io/io
   gfx/gfx
   gui/gui