diff --git a/modules/bindings/pymod/tmtools.py b/modules/bindings/pymod/tmtools.py
index 522a2dd559e31fb6656dca3ad20dc9a42d360722..87a9e3616c937f5514c9bbc3ba8a444410b7cec9 100644
--- a/modules/bindings/pymod/tmtools.py
+++ b/modules/bindings/pymod/tmtools.py
@@ -68,7 +68,7 @@ def _ParseTmAlign(lines):
   alignment = seq.CreateAlignment()
   alignment.AddSequence(seq2)
   alignment.AddSequence(seq1)
-  return TMAlignResult(rmsd, tm_score, aln_length, tf, seq2, alignment)
+  return TMAlignResult(rmsd, aln_length, tm_score, tf, seq2, alignment)
 
 def _RunTmAlign(tmalign, tmp_dir):
   model1_filename=os.path.join(tmp_dir, 'model01.pdb')
@@ -86,6 +86,50 @@ def _RunTmAlign(tmalign, tmp_dir):
     raise RuntimeError("tmalign superposition failed")
   return _ParseTmAlign(lines)
 
+class MMAlignResult:
+  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
+    self.transform=transform
+    self.ref_sequence =ref_sequence
+    self.alignment=alignment
+
+def _ParseMmAlign(lines):
+  info_line=lines[10].split(',')
+  aln_length=float(info_line[0].split('=')[1].strip())
+  rmsd=float(info_line[1].split('=')[1].strip())  
+  tm_score=float(info_line[2].split('=')[1].strip())
+  tf1=[float(i.strip()) for i in lines[14].split()]
+  tf2=[float(i.strip()) for i in lines[15].split()]
+  tf3=[float(i.strip()) for i in lines[16].split()]
+  rot=geom.Mat3(tf1[2], tf1[3], tf1[4], tf2[2], tf2[3],
+                tf2[4], tf3[2], tf3[3], tf3[4])
+  tf=geom.Mat4(rot)
+  tf.PasteTranslation(geom.Vec3(tf1[1], tf2[1], tf3[1]))
+  seq1 = seq.CreateSequence("1",lines[19].strip())
+  seq2 = seq.CreateSequence("2",lines[21].strip())
+  alignment = seq.CreateAlignment()
+  alignment.AddSequence(seq2)
+  alignment.AddSequence(seq1)
+  return MMAlignResult(rmsd, aln_length, tm_score, tf, seq2, alignment)
+
+def _RunMmAlign(mmalign, tmp_dir):
+  model1_filename=os.path.join(tmp_dir, 'model01.pdb')
+  model2_filename=os.path.join(tmp_dir, 'model02.pdb')
+  if platform.system() == "Windows":
+    mmalign_path=settings.Locate('mmalign.exe', explicit_file_name=mmalign)
+    command="\"%s\" %s %s" %(os.path.normpath(mmalign_path), model1_filename, model2_filename)
+  else:
+    mmalign_path=settings.Locate('MMalign', explicit_file_name=mmalign)  
+    command="\"%s\" \"%s\" \"%s\"" %(mmalign_path, model1_filename, model2_filename)
+  ps=subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
+  ps.wait()
+  lines=ps.stdout.readlines()
+  if (len(lines))<22:
+    raise RuntimeError("mmalign superposition failed")
+  return _ParseMmAlign(lines)
+
 class TMScoreResult:
   def __init__(self, rmsd_common, tm_score, max_sub, 
                gdt_ts, gdt_ha, rmsd_below_five, transform):
@@ -114,7 +158,6 @@ def _ParseTmScore(lines):
                        tf)
   return result
 
-
 def _RunTmScore(tmscore, tmp_dir):
   model1_filename=os.path.join(tmp_dir, 'model01.pdb')
   model2_filename=os.path.join(tmp_dir, 'model02.pdb')  
@@ -133,6 +176,7 @@ def _RunTmScore(tmscore, tmp_dir):
     raise RuntimeError("tmscore superposition failed")
   return _ParseTmScore(lines)
 
+
 def TMAlign(model1, model2, tmalign=None):
   """
   Run tmalign on two protein structures
@@ -142,6 +186,17 @@ def TMAlign(model1, model2, tmalign=None):
   model1.handle.EditXCS().ApplyTransform(result.transform)
   _CleanupFiles(tmp_dir_name)
   return result
+
+def MMAlign(model1, model2, mmalign=None):
+  """
+  Run tmalign on two protein structures
+  """
+  tmp_dir_name=_SetupFiles((model1, model2))
+  result=_RunMmAlign(mmalign, tmp_dir_name)
+  model1.handle.EditXCS().ApplyTransform(result.transform)
+  _CleanupFiles(tmp_dir_name)
+  return result
+
 def TMScore(model1, model2, tmscore=None):
   """
   Run tmscore on two protein structures