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  :raises: IOException if the restrictions of the PDB format are not satisfied
188  (with the exception of atom numbers, see above):
189 
190  * Chain names with more than one character
191  * Atom positions with coordinates outside range [-999.99, 9999.99]
192  * Residue names longer than three characters
193  * Atom names longer than four characters
194  * Numeric part of :class:`ost.mol.ResNum` outside range [-999, 9999]
195  * Alternative atom indicators longer than one character
196  """
197  if not getattr(models, '__len__', None):
198  models=[models]
199  if isinstance(profile, str):
200  profile=profiles[profile].Copy()
201  elif isinstance(profile, IOProfile):
202  profile.Copy()
203  else:
204  raise TypeError('profile must be of type string or IOProfile, '+\
205  'instead of %s'%type(profile))
206  profile.dialect=_override(profile.dialect, dialect)
207  writer=PDBWriter(filename, profile)
208  writer.SetIsPQR(pqr)
209  if len(models)>1:
210  writer.write_multi_model=True
211  for model in models:
212  writer.Write(model)
213 
214 try:
215  from ost import img
216  LoadMap = LoadImage
217  SaveMap = SaveImage
218 except ImportError:
219  pass
220 
221  ## loads several images and puts them in an ImageList
222  # \sa \example fft_li.py "View Fourier Transform Example"
223 def LoadImageList (files):
224  image_list=img.ImageList()
225  for file in files:
226  image=LoadImage(file)
227  image_list.append(image)
228  return image_list
229 
230 LoadMapList=LoadImageList
231 
232 def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
233  lazy_load=False, stride=1,
234  dialect=None, detect_swap=True,swap_bytes=False):
235  """
236  Load CHARMM trajectory file.
237 
238  :param crd: EntityHandle or filename of the (PDB) file containing the
239  structure. The structure must have the same number of atoms as the
240  trajectory
241  :param dcd_file: The filename of the DCD file. If not set, and crd is a
242  string, the filename is set to the <crd>.dcd
243  :param layz_load: Whether the trajectory should be loaded on demand. Instead
244  of loading the complete trajectory into memory, the trajectory frames are
245  loaded from disk when requested.
246  :param stride: The spacing of the frames to load. When set to 2, for example,
247  every second frame is loaded from the trajectory. By default, every frame
248  is loaded.
249  :param dialect: The dialect for the PDB file to use. See :func:`LoadPDB`. If
250  set, overrides the value of the profile
251  :param profile: The IO profile to use for loading the PDB file. See
252  :doc:`profile`.
253  :param detect_swap: if True (the default), then automatic detection of endianess
254  is attempted, otherwise the swap_bytes parameter is used
255  :param swap_bytes: is detect_swap is False, this flag determines whether bytes
256  are swapped upon loading or not
257  """
258  if not isinstance(crd, mol.EntityHandle):
259  if dcd_file==None:
260  dcd_file='%s.dcd' % os.path.splitext(crd)[0]
261  crd=LoadPDB(crd, profile=profile, dialect=dialect)
262 
263  else:
264  if not dcd_file:
265  raise ValueError("No DCD filename given")
266  return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load, detect_swap, swap_bytes)
267 
268 def LoadMMCIF(filename, fault_tolerant=None, calpha_only=None, profile='DEFAULT', remote=False, seqres=False, info=False):
269  """
270  Load MMCIF file from disk and return one or more entities. Several options
271  allow to customize the exact behaviour of the MMCIF import. For more
272  information on these options, see :doc:`profile`.
273 
274  Residues are flagged as ligand if they are mentioned in a HET record.
275 
276  :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
277  the value of :attr:`IOProfile.fault_tolerant`.
278 
279  :param remote: If set to True, the method tries to load the pdb from the
280  remote pdb repository www.pdb.org. The filename is then interpreted as the
281  pdb id.
282 
283  :rtype: :class:`~ost.mol.EntityHandle`.
284 
285  :param seqres: Whether to read SEQRES records. If set to True, the loaded
286  entity and seqres entry will be returned as second item.
287 
288  :param info: Whether to return an info container with the other output.
289  Returns a :class:`MMCifInfo` object as last item.
290 
291  :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous
292  or non-existent file.
293  """
294  def _override(val1, val2):
295  if val2!=None:
296  return val2
297  else:
298  return val1
299  if isinstance(profile, str):
300  prof = profiles[profile].Copy()
301  else:
302  prof = profile.Copy()
303 
304  prof.calpha_only=_override(prof.calpha_only, calpha_only)
305  prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
306 
307  if remote:
308  from ost.io.remote import RemoteGet
309  tmp_file = RemoteGet(filename, from_repo='cif')
310  filename = tmp_file.name
311 
312  try:
313  ent = mol.CreateEntity()
314  reader = MMCifReader(filename, ent, prof)
315  reader.read_seqres = seqres
316 
317  # NOTE: to speed up things, we could introduce a restrict_chains parameter
318  # similar to the one in LoadPDB. Here, it would have to be a list/set
319  # of chain-name-strings.
320 
321  #if reader.HasNext():
322  reader.Parse()
323  if prof.processor:
324  prof.processor.Process(ent)
325  #else:
326  # raise IOError("File doesn't contain any entities")
327  if seqres and info:
328  return ent, reader.seqres, reader.info
329  if seqres:
330  return ent, reader.seqres
331  if info:
332  return ent, reader.info
333  return ent
334  except:
335  raise
336 
337 # this function uses a dirty trick: should be a member of MMCifInfoBioUnit
338 # which is totally C++, but we want the method in Python... so we define it
339 # here (__init__) and add it as a member to the class. With this, the first
340 # arguement is the usual 'self'.
341 # documentation for this function was moved to mmcif.rst,
342 # MMCifInfoBioUnit.PDBize, since this function is not included in SPHINX.
343 def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
344  transformation=False):
345  pdbizer = mol.alg.PDBize(min_polymer_size=min_polymer_size)
346 
347  chains = biounit.GetChainList()
348  c_intvls = biounit.GetChainIntervalList()
349  o_intvls = biounit.GetOperationsIntervalList()
350  ss = seqres
351  if not ss:
352  ss = seq.CreateSequenceList()
353  # create list of operations
354  # for cartesian products, operations are stored in a list, multiplied with
355  # the next list of operations and re-stored... until all lists of operations
356  # are multiplied in an all-against-all manner.
357  operations = biounit.GetOperations()
358  for i in range(0,len(c_intvls)):
359  trans_matrices = geom.Mat4List()
360  l_operations = operations[o_intvls[i][0]:o_intvls[i][1]]
361  if len(l_operations) > 0:
362  for op in l_operations[0]:
363  rot = geom.Mat4()
364  rot.PasteRotation(op.rotation)
365  trans = geom.Mat4()
366  trans.PasteTranslation(op.translation)
367  tr = geom.Mat4()
368  tr = trans * rot
369  trans_matrices.append(tr)
370  for op_n in range(1, len(l_operations)):
371  tmp_ops = geom.Mat4List()
372  for o in l_operations[op_n]:
373  rot = geom.Mat4()
374  rot.PasteRotation(o.rotation)
375  trans = geom.Mat4()
376  trans.PasteTranslation(o.translation)
377  tr = geom.Mat4()
378  tr = trans * rot
379  for t_o in trans_matrices:
380  tp = t_o * tr
381  tmp_ops.append(tp)
382  trans_matrices = tmp_ops
383  # select chains into a view as basis for each transformation
384  assu = asu.Select('cname='+','.join(mol.QueryQuoteName(name) \
385  for name in \
386  chains[c_intvls[i][0]:c_intvls[i][1]]))
387  pdbizer.Add(assu, trans_matrices, ss)
388  pdb_bu = pdbizer.Finish(transformation)
389  if transformation:
390  return pdb_bu, pdb_bu.GetTransformationMatrix()
391  return pdb_bu
392 
393 MMCifInfoBioUnit.PDBize = _PDBize
def RemoteGet
Definition: remote.py:86
DLLEXPORT_OST_IO img::ImageHandle LoadImage(const boost::filesystem::path &loc)
Function that loads an image from a file.
Protein or molecule.
std::vector< Mat4 > Mat4List
Definition: mat4.hh:141
mol::CoordGroupHandle DLLEXPORT_OST_IO LoadCHARMMTraj(const mol::EntityHandle &ent, const String &trj_filename, unsigned int stride=1, bool lazy_load=false, bool detect_swap=true, bool byte_swap=false)
import a CHARMM trajectory in dcd format with an existing entity requires the existing entity and the...
def LoadImageList
Definition: __init__.py:223
def LoadMMCIF
Definition: __init__.py:268
reader for the mmcif file format
Definition: mmcif_reader.hh:59
Manages a collection of images.
Definition: image_list.hh:43
def SavePDB
Definition: __init__.py:176
def LoadPDB
Definition: __init__.py:69