diff --git a/modules/bindings/pymod/CMakeLists.txt b/modules/bindings/pymod/CMakeLists.txt index 0e194a0ebe6b5480258d9fdff253f35be4685c63..5dd7a1cc99bf9d75386cdde85e5c2da2ebe07bcc 100644 --- a/modules/bindings/pymod/CMakeLists.txt +++ b/modules/bindings/pymod/CMakeLists.txt @@ -1 +1 @@ -pymod(NAME bindings PY __init__.py lga.py hbplus.py msms.py) +pymod(NAME bindings PY __init__.py lga.py hbplus.py msms.py tmtools.py) diff --git a/modules/bindings/pymod/tmtools.py b/modules/bindings/pymod/tmtools.py new file mode 100644 index 0000000000000000000000000000000000000000..76abc5324b89af06d0c0d917960b1efc55d0b9ea --- /dev/null +++ b/modules/bindings/pymod/tmtools.py @@ -0,0 +1,123 @@ +#------------------------------------------------------------------------------ +# This file is part of the OpenStructure project <www.openstructure.org> +# +# Copyright (C) 2008-2009 by the OpenStructure authors +# +# This library is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3.0 of the License, or (at your option) +# any later version. +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +#------------------------------------------------------------------------------ +""" +Wrappers for the tmalign and tmscore utilities. + +References: + +tmscore: Yang Zhang and Jeffrey Skolnick, Proteins 2004 57: 702-710 +tmalign: Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9 + + +Authors: Pascal Benkert, Marco Biasini +""" + +import subprocess, os, tempfile +from ost import settings, io, geom + +def _SetupFiles(models): + # create temporary directory + tmp_dir_name=tempfile.mkdtemp() + for index, model in enumerate(models): + io.SavePDB(model, os.path.join(tmp_dir_name, 'model%02d.pdb' % (index+1))) + return tmp_dir_name + +def _CleanupFiles(dir_name): + import shutil + shutil.rmtree(dir_name) + +def _ParseTmAlign(lines): + tf1=[float(i.strip()) for i in lines[15].split()] + tf2=[float(i.strip()) for i in lines[16].split()] + tf3=[float(i.strip()) for i in lines[17].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])) + return tf + +def _RunTmAlign(tmalign, tmp_dir): + tmalign_path=settings.Locate('tmalign', explicit_file_name=tmalign) + model1_filename=os.path.join(tmp_dir, 'model01.pdb') + model2_filename=os.path.join(tmp_dir, 'model02.pdb') + command="%s '%s' '%s'" %(tmalign_path, model1_filename, model2_filename) + ps=subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + lines=ps.stdout.readlines() + if (len(lines))<22: + raise RuntimeError("tmalign superposition failed") + return _ParseTmAlign(lines) + +class TMScoreResult: + def __init__(self, rmsd_common, tm_score, max_sub, + gdt_ts, gdt_ha, rmsd_below_five, transform): + self.rmsd_common=rmsd_common + self.tm_score=tm_score + self.max_sub=max_sub + self.gdt_ts=gdt_ts + self.gdt_ha=gdt_ha + self.rmsd_below_five=rmsd_below_five + self.transform=transform + +def _ParseTmScore(lines): + tf1=[float(i.strip()) for i in lines[23].split()] + tf2=[float(i.strip()) for i in lines[24].split()] + tf3=[float(i.strip()) for i in lines[25].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])) + result=TMScoreResult(float(lines[14].split()[-1].strip()), + float(lines[16].split()[2].strip()), + float(lines[17].split()[1].strip()), + float(lines[18].split()[1].strip()), + float(lines[19].split()[1].strip()), + float(lines[27].split()[-1].strip()), + tf) + return result + + +def _RunTmScore(tmscore, tmp_dir): + tmscore_path=settings.Locate('tmscore', explicit_file_name=tmscore) + model1_filename=os.path.join(tmp_dir, 'model01.pdb') + model2_filename=os.path.join(tmp_dir, 'model02.pdb') + command="%s '%s' '%s'" %(tmscore_path, model1_filename, model2_filename) + ps=subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + lines=ps.stdout.readlines() + if (len(lines))<22: + raise RuntimeError("tmscore superposition failed") + return _ParseTmScore(lines) + +def TMAlign(model1, model2, tmalign=None): + """ + Run tmalign on two protein structures + """ + tmp_dir_name=_SetupFiles((model1, model2)) + tf=_RunTmAlign(tmalign, tmp_dir_name) + model1.handle.RequestXCSEditor().ApplyTransform(tf) + _CleanupFiles(tmp_dir_name) + +def TMScore(model1, model2, tmscore=None): + """ + Run tmscore on two protein structures + """ + tmp_dir_name=_SetupFiles((model1, model2)) + result=_RunTmScore(tmscore, tmp_dir_name) + model1.handle.RequestXCSEditor().ApplyTransform(result.transform) + _CleanupFiles(tmp_dir_name) + return result \ No newline at end of file