OpenStructure
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
__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 _ost_io import *
22 from ost import mol, geom, conop, seq
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].Copy()
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  if conop.GetDefaultLib():
48  processor = conop.RuleBasedProcessor(conop.GetDefaultLib())
49  else:
50  processor = conop.HeuristicProcessor()
51  profiles['STRICT']=IOProfile(dialect='PDB', fault_tolerant=False,
52  quack_mode=False, processor=processor.Copy())
53  profiles['SLOPPY']=IOProfile(dialect='PDB', fault_tolerant=True,
54  quack_mode=True, processor=processor.Copy())
55  profiles['CHARMM']=IOProfile(dialect='CHARMM', fault_tolerant=True,
56  quack_mode=False, processor=processor.Copy())
57  profiles['DEFAULT']='STRICT'
58 
59 def _override(val1, val2):
60  if val2!=None:
61  return val2
62  else:
63  return val1
64 
65 def LoadPDB(filename, restrict_chains="", no_hetatms=None,
66  fault_tolerant=None, load_multi=False, quack_mode=None,
67  join_spread_atom_records=None, calpha_only=None,
68  profile='DEFAULT', remote=False, dialect=None,
69  seqres=False, bond_feasibility_check=None):
70  """
71  Load PDB file from disk and return one or more entities. Several options
72  allow to customize the exact behaviour of the PDB import. For more information
73  on these options, see :doc:`profile`.
74 
75  Residues are flagged as ligand if they are mentioned in a HET record.
76 
77  :param restrict_chains: If not an empty string, only chains listed in the
78  string will be imported.
79 
80  :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
81  the value of :attr:`IOProfile.fault_tolerant`.
82 
83  :param no_hetatms: If set to True, HETATM records will be ignored. Overrides
84  the value of :attr:`IOProfile.no_hetatms`
85 
86  :param load_multi: If set to True, a list of entities will be returned instead
87  of only the first. This is useful when dealing with multi-PDB files.
88 
89  :param join_spread_atom_records: If set, overrides the value of
90  :attr:`IOProfile.join_spread_atom_records`.
91 
92  :param remote: If set to True, the method tries to load the pdb from the
93  remote pdb repository www.pdb.org. The filename is then interpreted as the
94  pdb id.
95 
96  :rtype: :class:`~ost.mol.EntityHandle` or a list thereof if `load_multi` is
97  True.
98 
99  :param dialect: Specifies the particular dialect to use. If set, overrides
100  the value of :attr:`IOProfile.dialect`
101 
102  :param seqres: Whether to read SEQRES records. If set to True, the loaded
103  entity and seqres entry will be returned as a tuple.
104 
105  :type dialect: :class:`str`
106 
107 
108  :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous or
109  inexistent file
110  """
111  def _override(val1, val2):
112  if val2!=None:
113  return val2
114  else:
115  return val1
116  if isinstance(profile, str):
117  prof=profiles[profile].Copy()
118  elif isinstance(profile, IOProfile):
119  prof=profile.Copy()
120  else:
121  raise TypeError('profile must be of type string or IOProfile, '+\
122  'instead of %s'%type(profile))
123  if dialect not in (None, 'PDB', 'CHARMM',):
124  raise ValueError('dialect must be PDB or CHARMM')
125  prof.calpha_only=_override(prof.calpha_only, calpha_only)
126  prof.no_hetatms=_override(prof.no_hetatms, no_hetatms)
127  prof.dialect=_override(prof.dialect, dialect)
128  prof.quack_mode=_override(prof.quack_mode, quack_mode)
129  if prof.processor:
130  prof.processor.check_bond_feasibility=_override(prof.processor.check_bond_feasibility,
131  bond_feasibility_check)
132  prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
133  prof.join_spread_atom_records=_override(prof.join_spread_atom_records,
134  join_spread_atom_records)
135 
136  tmp_file = None # avoid getting out of scope
137  if remote:
138  from ost.io.remote import RemoteGet
139  tmp_file =RemoteGet(filename)
140  filename = tmp_file.name
141 
142  conop_inst=conop.Conopology.Instance()
143  if prof.processor:
144  if prof.dialect=='PDB':
145  prof.processor.dialect=conop.PDB_DIALECT
146  elif prof.dialect=='CHARMM':
147  prof.processor.dialect=conop.CHARMM_DIALECT
148  reader=PDBReader(filename, prof)
149  reader.read_seqres=seqres
150  try:
151  if load_multi:
152  ent_list=[]
153  while reader.HasNext():
154  ent=mol.CreateEntity()
155  reader.Import(ent, restrict_chains)
156  if prof.processor:
157  prof.processor.Process(ent)
158  ent_list.append(ent)
159  if len(ent_list)==0:
160  raise IOError("File '%s' doesn't contain any entities" % filename)
161  return ent_list
162  else:
163  ent=mol.CreateEntity()
164  if reader.HasNext():
165  reader.Import(ent, restrict_chains)
166  if prof.processor:
167  prof.processor.Process(ent)
168  else:
169  raise IOError("File '%s' doesn't contain any entities" % filename)
170  if seqres:
171  return ent, reader.seqres
172  return ent
173  except:
174  raise
175 
176 def SavePDB(models, filename, dialect=None, pqr=False, profile='DEFAULT'):
177  """
178  Save entity or list of entities to disk. If a list of entities is supplied
179  the PDB file will be saved as a multi PDB file. Each of the entities is
180  wrapped into a MODEL/ENDMDL pair.
181 
182  If the atom number exceeds 99999, '*****' is used.
183 
184  :param models: The entity or list of entities (handles or views) to be saved
185  :param filename: The filename
186  :type filename: string
187  """
188  if not getattr(models, '__len__', None):
189  models=[models]
190  if isinstance(profile, str):
191  profile=profiles[profile].Copy()
192  elif isinstance(profile, IOProfile):
193  profile.Copy()
194  else:
195  raise TypeError('profile must be of type string or IOProfile, '+\
196  'instead of %s'%type(profile))
197  profile.dialect=_override(profile.dialect, dialect)
198  writer=PDBWriter(filename, profile)
199  writer.SetIsPQR(pqr)
200  if len(models)>1:
201  writer.write_multi_model=True
202  for model in models:
203  writer.Write(model)
204 
205 try:
206  from ost import img
207  LoadMap = LoadImage
208  SaveMap = SaveImage
209 except ImportError:
210  pass
211 
212  ## loads several images and puts them in an ImageList
213  # \sa \ref fft_li.py "View Fourier Transform Example"
214 def LoadImageList (files):
215  image_list=img.ImageList()
216  for file in files:
217  image=LoadImage(file)
218  image_list.append(image)
219  return image_list
220 
221 LoadMapList=LoadImageList
222 
223 def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
224  lazy_load=False, stride=1,
225  dialect=None, detect_swap=True,swap_bytes=False):
226  """
227  Load CHARMM trajectory file.
228 
229  :param crd: EntityHandle or filename of the (PDB) file containing the
230  structure. The structure must have the same number of atoms as the
231  trajectory
232  :param dcd_file: The filename of the DCD file. If not set, and crd is a
233  string, the filename is set to the <crd>.dcd
234  :param layz_load: Whether the trajectory should be loaded on demand. Instead
235  of loading the complete trajectory into memory, the trajectory frames are
236  loaded from disk when requested.
237  :param stride: The spacing of the frames to load. When set to 2, for example,
238  every second frame is loaded from the trajectory. By default, every frame
239  is loaded.
240  :param dialect: The dialect for the PDB file to use. See :func:`LoadPDB`. If
241  set, overrides the value of the profile
242  :param profile: The IO profile to use for loading the PDB file. See
243  :doc:`profile`.
244  :param detect_swap: if True (the default), then automatic detection of endianess
245  is attempted, otherwise the swap_bytes parameter is used
246  :param swap_bytes: is detect_swap is False, this flag determines whether bytes
247  are swapped upon loading or not
248  """
249  if not isinstance(crd, mol.EntityHandle):
250  if dcd_file==None:
251  dcd_file='%s.dcd' % os.path.splitext(crd)[0]
252  crd=LoadPDB(crd, profile=profile, dialect=dialect)
253 
254  else:
255  if not dcd_file:
256  raise ValueError("No DCD filename given")
257  return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load, detect_swap, swap_bytes)
258 
259 def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=None, profile='DEFAULT', remote=False, seqres=False, info=False):
260  """
261  Load MMCIF file from disk and return one or more entities. Several options
262  allow to customize the exact behaviour of the MMCIF import. For more
263  information on these options, see :doc:`profile`.
264 
265  Residues are flagged as ligand if they are mentioned in a HET record.
266 
267  :param restrict_chains: If not an empty string, only chains listed in the
268  string will be imported.
269 
270  :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
271  the value of :attr:`IOProfile.fault_tolerant`.
272 
273  :param remote: If set to True, the method tries to load the pdb from the
274  remote pdb repository www.pdb.org. The filename is then interpreted as the
275  pdb id.
276 
277  :rtype: :class:`~ost.mol.EntityHandle`.
278 
279  :param seqres: Whether to read SEQRES records. If set to True, the loaded
280  entity and seqres entry will be returned as second item.
281 
282  :param info: Whether to return an info container with the other output.
283  Returns a :class:`MMCifInfo` object as last item.
284 
285  :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous
286  or non-existent file.
287  """
288  def _override(val1, val2):
289  if val2!=None:
290  return val2
291  else:
292  return val1
293  if isinstance(profile, str):
294  prof = profiles[profile].Copy()
295  else:
296  prof = profile.Copy()
297 
298  prof.calpha_only=_override(prof.calpha_only, calpha_only)
299  prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
300 
301  if remote:
302  from ost.io.remote import RemoteGet
303  tmp_file =RemoteGet(filename, from_repo='cif')
304  filename = tmp_file.name
305 
306  try:
307  ent = mol.CreateEntity()
308  reader = MMCifReader(filename, ent, prof)
309  reader.read_seqres = seqres
310  #if reader.HasNext():
311  reader.Parse()
312  if prof.processor:
313  prof.processor.Process(ent)
314  #else:
315  # raise IOError("File doesn't contain any entities")
316  if seqres and info:
317  return ent, reader.seqres, reader.info
318  if seqres:
319  return ent, reader.seqres
320  if info:
321  return ent, reader.info
322  return ent
323  except:
324  raise
325 
326 # this function uses a dirty trick: should be a member of MMCifInfoBioUnit
327 # which is totally C++, but we want the method in Python... so we define it
328 # here (__init__) and add it as a member to the class. With this, the first
329 # arguement is the usual 'self'.
330 # documentation for this function was moved to mmcif.rst,
331 # MMCifInfoBioUnit.PDBize, since this function is not included in SPHINX.
332 def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
333  transformation=False):
334  pdbizer = mol.alg.PDBize(min_polymer_size=min_polymer_size)
335 
336  chains = biounit.GetChainList()
337  c_intvls = biounit.GetChainIntervalList()
338  o_intvls = biounit.GetOperationsIntervalList()
339  ss = seqres
340  if not ss:
341  ss = seq.CreateSequenceList()
342  # create list of operations
343  # for cartesian products, operations are stored in a list, multiplied with
344  # the next list of operations and re-stored... until all lists of operations
345  # are multiplied in an all-against-all manner.
346  operations = biounit.GetOperations()
347  for i in range(0,len(c_intvls)):
348  trans_matrices = geom.Mat4List()
349  l_operations = operations[o_intvls[i][0]:o_intvls[i][1]]
350  if len(l_operations) > 0:
351  for op in l_operations[0]:
352  rot = geom.Mat4()
353  rot.PasteRotation(op.rotation)
354  trans = geom.Mat4()
355  trans.PasteTranslation(op.translation)
356  tr = geom.Mat4()
357  tr = trans * rot
358  trans_matrices.append(tr)
359  for op_n in range(1, len(l_operations)):
360  tmp_ops = geom.Mat4List()
361  for o in l_operations[op_n]:
362  rot = geom.Mat4()
363  rot.PasteRotation(o.rotation)
364  trans = geom.Mat4()
365  trans.PasteTranslation(o.translation)
366  tr = geom.Mat4()
367  tr = trans * rot
368  for t_o in trans_matrices:
369  tp = t_o * tr
370  tmp_ops.append(tp)
371  trans_matrices = tmp_ops
372  # select chains into a view as basis for each transformation
373  assu = asu.Select('cname='+','.join(chains[c_intvls[i][0]:c_intvls[i][1]]))
374  pdbizer.Add(assu, trans_matrices, ss)
375  pdb_bu = pdbizer.Finish(transformation)
376  if transformation:
377  return pdb_bu, pdb_bu.GetTransformationMatrix()
378  return pdb_bu
379 
380 MMCifInfoBioUnit.PDBize = _PDBize