6 This module is for calculating surface areas
7 from OpenStructure using the external program naccess
9 How To Use This Module:
10 1. Import it (e.g. as "from ost.bindings import naccess")
11 2. Use it (e.g. as "sasa = naccess.CalculateSurfaceArea(entity)")
23 from ost
import settings
31 def _GetExecutable(naccess_exe):
32 return settings.Locate(
'naccess', explicit_file_name=naccess_exe)
42 def _SetupFiles(entity, selection, scratch_dir, max_number_of_atoms):
46 tmp_dir_name=tempfile.mkdtemp(dir=scratch_dir)
48 tmp_dir_name=tempfile.mkdtemp()
51 entity_view=entity.Select(selection)
52 if len(entity_view.atoms) > max_number_of_atoms:
53 raise RuntimeError,
"Too much atoms for NACCESS (> %s)" % max_number_of_atoms
54 if not entity_view.IsValid():
55 raise RuntimeError,
"Could not create view for selection (%s)"%(selection)
58 tmp_file_name=os.path.join(tmp_dir_name,
"entity.pdb")
59 tmp_file_base = os.path.join(tmp_dir_name,
"entity")
60 io.SavePDB(entity_view, tmp_file_name)
61 return (tmp_dir_name, tmp_file_name, tmp_file_base)
70 def _ParseAsaFile(entity, file, asa_atom):
73 asa_lines = asa_fh.readlines()
77 if l.startswith(
"ATOM"):
83 atom_name = atom_name.strip()
85 res_number = res_number.strip()
88 m=re.match(
r'(?P<num>-?\d+)(?P<ins>\w)?', res_number)
96 a = entity.FindAtom(chain_id, resNum, atom_name)
98 a.SetFloatProp(asa_atom, float(asa))
100 print chain_id, resNum, atom_name
110 def _ParseRsaFile(enti,file, asa_abs, asa_rel):
112 area_lines = area_fh.readlines()
115 area_lines = area_lines[4:]
119 if l.startswith(
"RES"):
120 p = re.compile(
r'\s+')
124 res_name = res_name.strip()
127 res_number= res_number.strip()
129 abs_all, rel_all =l[15:28].strip().split()
130 m=re.match(
r'(?P<num>-?\d+)(?P<ins>\w)?', res_number)
132 if di[
"ins"] ==
None:
135 resNum =
mol.ResNum(int(di[
"num"]), di[
"ins"])
137 res = enti.handle.FindResidue(chain_id, resNum)
140 if res_name == res.name:
141 res.SetFloatProp(asa_rel, float(rel_all) )
142 res.SetFloatProp(asa_abs, float(abs_all) )
144 raise RuntimeError,
"Residue Names are not the same for ResNumb: %s (%s vs %s)" % (res_number, res.name, res_name)
150 def __CleanupFiles(dir_name):
152 shutil.rmtree(dir_name)
161 def _RunNACCESS(command, temp_dir):
162 proc = subprocess.Popen(command, shell=
True, stdout=subprocess.PIPE, cwd = temp_dir)
163 stdout_value, stderr_value = proc.communicate()
166 if proc.returncode!=0:
167 print "WARNING: naccess error\n", stdout_value
168 raise subprocess.CalledProcessError(proc.returncode, command)
198 include_hydrogens=
False, include_hetatm =
False,
199 include_water =
False, selection=
"",
200 naccess_exe=
None, keep_files=
False , asa_abs=
"asaAbs", asa_rel=
"asaRel", asa_atom=
"asaAtom", scratch_dir =
None, max_number_of_atoms=50000):
204 naccess_executable=_GetExecutable(naccess_exe)
208 (naccess_data_dir, naccess_data_file,naccess_data_base )=_SetupFiles(entity, selection, scratch_dir)
211 command=
"%s %s -p %f " % \
212 (naccess_executable, naccess_data_file, radius)
213 if include_hydrogens:
214 command =
"%s -w" % command
216 command =
"%s -y" % command
218 command =
"%s -h" % command
220 stdout_value=_RunNACCESS(command, naccess_data_dir)
222 new_asa= os.path.join(naccess_data_dir,
"%s.asa" % naccess_data_base)
223 _ParseAsaFile(entity, new_asa, asa_atom)
225 new_rsa = os.path.join(naccess_data_dir,
"%s.rsa" % naccess_data_base)
226 _ParseRsaFile(entity, new_rsa, asa_abs, asa_rel)
230 for a
in entity.atoms:
231 sasa += a.GetFloatProp(asa_atom, 0.0)
240 __CleanupFiles(naccess_data_dir)