6 This module is for calculating MSMS surfaces as well as surface areas
7 (SESA, SASA) from OpenStructure using the external program MSMS.
9 How To Use This Module:
10 1. Import it (e.g. as "from ost.bindings import msms")
11 2. Use it (e.g. as "surfaces_list = msms.CalculateSurface(entity)"
12 "(sesa,sasa) = msms.CalculateSurfaceArea(entity)")
24 from ost
import settings
42 msms_executable = _GetExecutable(msms_exe, msms_env)
43 command =
"%s" % (msms_executable)
44 proc = subprocess.Popen(command, shell=
True, stdout=subprocess.PIPE)
45 stdout_value, stderr_value = proc.communicate()
48 for l
in stdout_value.splitlines():
50 version = l.split(
' ')[1]
53 LogWarning(
'Could not parse MSMS version string')
62 def _GetExecutable(msms_exe, msms_env):
63 return settings.Locate(
'msms', explicit_file_name=msms_exe,
72 def _SetupFiles(entity, selection):
74 tmp_dir_name=tempfile.mkdtemp()
77 entity_view=entity.Select(selection)
78 if not entity_view.IsValid():
79 raise RuntimeError,
"Could not create view for selection (%s)"%(selection)
82 tmp_file_name=os.path.join(tmp_dir_name,
"entity")
83 tmp_file_handle=open(tmp_file_name,
'w')
84 for a
in entity_view.GetAtomList():
86 tmp_file_handle.write(
'%8.3f %8.3f %8.3f %4.2f\n' % (position[0],
87 position[1], position[2], a.radius))
88 tmp_file_handle.close()
90 return (tmp_dir_name, tmp_file_name)
99 def _ParseAreaFile(entity,file, asa_prop, esa_prop):
101 area_lines = area_fh.readlines()
104 area_lines = area_lines[1:]
105 if entity.GetAtomCount() != len(area_lines):
106 raise RuntimeError,
"Atom count (%d) unequeal to number of atoms in area file (%d)" % (entity.GetAtomCount(), len(area_lines))
108 atom_no, sesa, sasa = l.split()
109 a = entity.atoms[int(atom_no)]
111 a.SetFloatProp(asa_prop, float(sasa))
113 a.SetFloatProp(esa_prop, float(sesa))
120 def __CleanupFiles(dir_name):
122 shutil.rmtree(dir_name)
131 def _RunMSMS(command):
132 proc = subprocess.Popen(command, shell=
True, stdout=subprocess.PIPE)
133 stdout_value, stderr_value = proc.communicate()
136 if proc.returncode!=0:
137 print "WARNING: msms error\n", stdout_value
166 no_hydrogens=
False, no_hetatoms=
False, no_waters=
False,
168 msms_exe=
None, msms_env=
None, keep_files=
False,
169 attach_asa=
None, attach_esa=
None):
173 msms_executable=_GetExecutable(msms_exe, msms_env)
184 selection+=
"ishetatm=False"
189 selection+=
"rname!=HOH"
192 (msms_data_dir, msms_data_file)=_SetupFiles(entity, selection)
195 command=
"%s -if %s -of %s -density %s -probe_radius %s -surface ases" % \
196 (msms_executable, msms_data_file, msms_data_file, density, radius)
199 if attach_asa !=
None:
200 command+=
" -af %s" % os.path.join(msms_data_dir,
"asa_atom")
202 stdout_value=_RunMSMS(command)
205 if attach_asa !=
None:
206 _ParseAreaFile(entity, os.path.join(msms_data_dir,
"asa_atom.area"),
207 attach_asa, attach_esa)
213 for line
in stdout_value.splitlines():
214 if re.match(
'MSMS terminated normally', line):
217 (ses_,sas_)=line.split()[5:7]
218 msms_ases.append(float(ses_))
219 msms_asas.append(float(sas_))
220 if re.match(
' Comp. probe_radius, reent, toric, contact SES SAS', line):
225 __CleanupFiles(msms_data_dir)
227 return (msms_ases, msms_asas)
250 no_hydrogens=
False, no_hetatoms=
False, no_waters=
False,
252 msms_exe=
None, msms_env=
None, keep_files=
False):
258 msms_executable=_GetExecutable(msms_exe, msms_env)
269 selection+=
"ishetatm=False"
274 selection+=
"rname!=HOH"
277 (msms_data_dir, msms_data_file)=_SetupFiles(entity, selection)
280 command=
"%s -if %s -of %s -density %s -probe_radius %s" % (msms_executable,
281 msms_data_file, msms_data_file, density, radius)
286 stdout_value=_RunMSMS(command)
290 for line
in stdout_value.splitlines():
291 if re.search(
'RS component [0-9]+ identified',line):
292 num_surf=int(line.split()[2])
296 msms_surfaces.append(io.LoadSurface(msms_data_file,
"msms"))
297 for n
in range(1,num_surf+1):
298 filename=msms_data_file+
'_'+str(n)
299 msms_surfaces.append(io.LoadSurface(filename,
"msms"))
303 __CleanupFiles(msms_data_dir)