OpenStructure
__init__.py
Go to the documentation of this file.
1 #------------------------------------------------------------------------------
2 # This file is part of the OpenStructure project <www.openstructure.org>
3 #
4 # Copyright (C) 2008-2011 by the OpenStructure authors
5 #
6 # This library is free software; you can redistribute it and/or modify it under
7 # the terms of the GNU Lesser General Public License as published by the Free
8 # Software Foundation; either version 3.0 of the License, or (at your option)
9 # any later version.
10 # This library is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this library; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #------------------------------------------------------------------------------
19 import os, tempfile, ftplib, httplib
20 
21 from _io import *
22 from ost import mol, conop
23 
24 profiles=None
25 
26 class IOProfiles:
27  def __init__(self):
28  self._dict={}
29 
30  def __getitem__(self, key):
31  return IOProfileRegistry.Instance().Get(key)
32 
33  def __setitem__(self, key, value):
34  if isinstance(value, str):
35  value=self[value]
36  IOProfileRegistry.Instance().Set(key, value)
37  self._dict[key]=value
38 
39  def __len__(self):
40  return len(self._dict)
41 
42  def __iter__(self):
43  return self._dict.__iter__()
44 
45 if not profiles:
46  profiles=IOProfiles()
47  profiles['STRICT']=IOProfile(dialect='PDB', fault_tolerant=False,
48  strict_hydrogens=False, quack_mode=False)
49  profiles['SLOPPY']=IOProfile(dialect='PDB', fault_tolerant=True,
50  strict_hydrogens=False, quack_mode=True)
51  profiles['CHARMM']=IOProfile(dialect='CHARMM', fault_tolerant=True,
52  strict_hydrogens=False, quack_mode=False)
53  profiles['DEFAULT']='STRICT'
54 
55 def _override(val1, val2):
56  if val2!=None:
57  return val2
58  else:
59  return val1
60 
61 def __GetModelFromPDB(model_id, output_dir, file_pattern='pdb%s.ent.gz'):
62  file_name = file_pattern % model_id
63  file_path = os.path.join(output_dir,file_name)
64  try:
65  server="ftp.wwpdb.org"
66  ftp=ftplib.FTP(server,"anonymous","user@")
67  ftp.cwd("pub/pdb/data/structures/all/pdb")
68  ftp_retrfile=open(file_path,"wb")
69  ftp.retrbinary("RETR "+file_name,ftp_retrfile.write)
70  ftp_retrfile.close()
71  except:
72  conn=httplib.HTTPConnection('www.pdb.org')
73  conn.request('GET', '/pdb/files/%s.pdb.gz' % model_id )
74  response=conn.getresponse()
75  if response.status==200:
76  data=response.read()
77  f=open(os.path.join(output_dir, file_pattern % model_id), 'w+')
78  f.write(data)
79  f.close()
80  else:
81  conn.close()
82  return False
83  return os.path.getsize(file_path) > 0
84 
85 def LoadPDB(filename, restrict_chains="", no_hetatms=None,
86  fault_tolerant=None, load_multi=False, quack_mode=None,
87  join_spread_atom_records=None, calpha_only=None,
88  profile='DEFAULT', remote=False, dialect=None,
89  strict_hydrogens=None):
90  """
91  Load PDB file from disk and returns one or more entities. Several options
92  allow to customize the exact behaviour of the PDB import. For more information
93  on these options, see :doc:`profile`.
94 
95  Residues are flagged as ligand if they are mentioned in a HET record.
96 
97  :param restrict_chains: If not an empty string, only chains listed in the
98  string will be imported.
99 
100  :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
101  the value of :attr:`IOProfile.fault_tolerant`.
102 
103  :param no_hetatms: If set to True, HETATM records will be ignored. Overrides
104  the value of :attr:`IOProfile.no_hetatms`
105 
106  :param load_multi: If set to True, a list of entities will be returned instead
107  of only the first. This is useful when dealing with multi-PDB files.
108 
109  :param join_spread_atom_records: If set, overrides the value of
110  :attr:`IOProfile.join_spread_atom_records`.
111 
112  :param remote: If set to true, the method tries to load the pdb from the
113  remote pdb repository www.pdb.org. The filename is then interpreted as the
114  pdb id.
115 
116  :rtype: :class:`~ost.mol.EntityHandle` or a list thereof if `load_multi` is
117  True.
118 
119  :param dialect: Specifies the particular dialect to use. If set, overrides
120  the value of :attr:`IOProfile.dialect`
121 
122  :type dialect: :class:`str`
123 
124  :param strict_hydrogens: If set, overrides the value of
125  :attr:`IOProfile.strict_hydrogens`.
126 
127  :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous or
128  inexistent file
129  """
130  def _override(val1, val2):
131  if val2!=None:
132  return val2
133  else:
134  return val1
135  if isinstance(profile, str):
136  prof=profiles[profile].Copy()
137  else:
138  prof=profile.Copy()
139  if dialect not in (None, 'PDB', 'CHARMM',):
140  raise ValueError('dialect must be PDB or CHARMM')
141  prof.calpha_only=_override(prof.calpha_only, calpha_only)
142  prof.no_hetatms=_override(prof.no_hetatms, no_hetatms)
143  prof.dialect=_override(prof.dialect, dialect)
144  prof.quack_mode=_override(prof.quack_mode, quack_mode)
145  prof.strict_hydrogens=_override(prof.strict_hydrogens, strict_hydrogens)
146  prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
147  prof.join_spread_atom_records=_override(prof.join_spread_atom_records,
148  join_spread_atom_records)
149 
150  if remote:
151  output_dir = tempfile.gettempdir()
152  if __GetModelFromPDB(filename, output_dir):
153  filename = os.path.join(output_dir, 'pdb%s.ent.gz' % filename)
154  else:
155  raise IOError('Can not load PDB %s from www.pdb.org'%filename)
156 
157  conop_inst=conop.Conopology.Instance()
158  builder=conop_inst.GetBuilder("DEFAULT")
159  if prof.dialect=='PDB':
160  builder.dialect=conop.PDB_DIALECT
161  elif prof.dialect=='CHARMM':
162  builder.dialect=conop.CHARMM_DIALECT
163  builder.strict_hydrogens=prof.strict_hydrogens
164  reader=PDBReader(filename, prof)
165  try:
166  if load_multi:
167  ent_list=[]
168  while reader.HasNext():
169  ent=mol.CreateEntity()
170  reader.Import(ent, restrict_chains)
171  conop_inst.ConnectAll(builder, ent, 0)
172  ent_list.append(ent)
173  if len(ent_list)==0:
174  raise IOError("File doesn't contain any entities")
175  return ent_list
176  else:
177  ent=mol.CreateEntity()
178  if reader.HasNext():
179  reader.Import(ent, restrict_chains)
180  conop_inst.ConnectAll(builder, ent, 0)
181  else:
182  raise IOError("File doesn't contain any entities")
183  return ent
184  except:
185  raise
186 
187 def SavePDB(models, filename, dialect=None, pqr=False, profile='DEFAULT'):
188  """
189  Save entity or list of entities to disk. If a list of entities is supplied the
190  PDB file will be saved as a multi PDB file. Each of the entities is wrapped
191  into a MODEL/ENDMDL pair.
192 
193  :param models: The entity or list of entities (handles or views) to be saved
194  :param filename: The filename
195  :type filename: string
196  """
197  if not getattr(models, '__len__', None):
198  models=[models]
199  if isinstance(profile, str):
200  profile=profiles[profile].Copy()
201  else:
202  profile.Copy()
203  profile.dialect=_override(profile.dialect, dialect)
204  writer=PDBWriter(filename, profile)
205  writer.SetIsPQR(pqr)
206  if len(models)>1:
207  writer.write_multi_model=True
208  for model in models:
209  writer.Write(model)
210 
211 try:
212  from ost import img
213  LoadMap = LoadImage
214  SaveMap = SaveImage
215 except ImportError:
216  pass
217 
218  ## loads several images and puts them in an ImageList
219  # \sa \ref fft_li.py "View Fourier Transform Example"
220 def LoadImageList (files):
221  image_list=img.ImageList()
222  for file in files:
223  image=LoadImage(file)
224  image_list.append(image)
225  return image_list
226 
227 LoadMapList=LoadImageList
228 
229 def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
230  lazy_load=False, stride=1,
231  dialect=None):
232  """
233  Load CHARMM trajectory file.
234 
235  :param crd: EntityHandle or filename of the (PDB) file containing the
236  structure. The structure must have the same number of atoms as the
237  trajectory
238  :param dcd_file: The filename of the DCD file. If not set, and crd is a
239  string, the filename is set to the <crd>.dcd
240  :param layz_load: Whether the trajectory should be loaded on demand. Instead
241  of loading the complete trajectory into memory, the trajectory frames are
242  loaded from disk when requested.
243  :param stride: The spacing of the frames to load. When set to 2, for example,
244  every second frame is loaded from the trajectory. By default, every frame
245  is loaded.
246  :param dialect: The dialect for the PDB file to use. See :func:`LoadPDB`. If
247  set, overrides the value of the profile
248  :param profile: The IO profile to use for loading the PDB file. See
249  :doc:`profile`.
250  """
251  if not isinstance(crd, mol.EntityHandle):
252  if dcd_file==None:
253  dcd_file='%s.dcd' % os.path.splitext(crd)[0]
254  crd=LoadPDB(crd, profile=profile, dialect=dialect)
255 
256  else:
257  if not dcd_file:
258  raise ValueError("No DCD filename given")
259  return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load)
260 
261 ## \example fft_li.py
262 #
263 # This scripts loads one or more images and shows their Fourier Transforms on
264 # the screen. A viewer is opened for each loaded image. The Fourier Transform
265 # honors the origin of the reference system, which is assumed to be at the
266 # center of the image.
267 #
268 # Usage:
269 #
270 # \code giplt view_ft.py <image1> [<image2> <image3> .... ] \endcode
271 #
272 # <BR>
273 # <BR>