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 \example 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, 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 fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
268  the value of :attr:`IOProfile.fault_tolerant`.
269 
270  :param remote: If set to True, the method tries to load the pdb from the
271  remote pdb repository www.pdb.org. The filename is then interpreted as the
272  pdb id.
273 
274  :rtype: :class:`~ost.mol.EntityHandle`.
275 
276  :param seqres: Whether to read SEQRES records. If set to True, the loaded
277  entity and seqres entry will be returned as second item.
278 
279  :param info: Whether to return an info container with the other output.
280  Returns a :class:`MMCifInfo` object as last item.
281 
282  :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous
283  or non-existent file.
284  """
285  def _override(val1, val2):
286  if val2!=None:
287  return val2
288  else:
289  return val1
290  if isinstance(profile, str):
291  prof = profiles[profile].Copy()
292  else:
293  prof = profile.Copy()
294 
295  prof.calpha_only=_override(prof.calpha_only, calpha_only)
296  prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
297 
298  if remote:
299  from ost.io.remote import RemoteGet
300  tmp_file = RemoteGet(filename, from_repo='cif')
301  filename = tmp_file.name
302 
303  try:
304  ent = mol.CreateEntity()
305  reader = MMCifReader(filename, ent, prof)
306  reader.read_seqres = seqres
307 
308  # NOTE: to speed up things, we could introduce a restrict_chains parameter
309  # similar to the one in LoadPDB. Here, it would have to be a list/set
310  # of chain-name-strings.
311 
312  #if reader.HasNext():
313  reader.Parse()
314  if prof.processor:
315  prof.processor.Process(ent)
316  #else:
317  # raise IOError("File doesn't contain any entities")
318  if seqres and info:
319  return ent, reader.seqres, reader.info
320  if seqres:
321  return ent, reader.seqres
322  if info:
323  return ent, reader.info
324  return ent
325  except:
326  raise
327 
328 # this function uses a dirty trick: should be a member of MMCifInfoBioUnit
329 # which is totally C++, but we want the method in Python... so we define it
330 # here (__init__) and add it as a member to the class. With this, the first
331 # arguement is the usual 'self'.
332 # documentation for this function was moved to mmcif.rst,
333 # MMCifInfoBioUnit.PDBize, since this function is not included in SPHINX.
334 def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
335  transformation=False):
336  pdbizer = mol.alg.PDBize(min_polymer_size=min_polymer_size)
337 
338  chains = biounit.GetChainList()
339  c_intvls = biounit.GetChainIntervalList()
340  o_intvls = biounit.GetOperationsIntervalList()
341  ss = seqres
342  if not ss:
343  ss = seq.CreateSequenceList()
344  # create list of operations
345  # for cartesian products, operations are stored in a list, multiplied with
346  # the next list of operations and re-stored... until all lists of operations
347  # are multiplied in an all-against-all manner.
348  operations = biounit.GetOperations()
349  for i in range(0,len(c_intvls)):
350  trans_matrices = geom.Mat4List()
351  l_operations = operations[o_intvls[i][0]:o_intvls[i][1]]
352  if len(l_operations) > 0:
353  for op in l_operations[0]:
354  rot = geom.Mat4()
355  rot.PasteRotation(op.rotation)
356  trans = geom.Mat4()
357  trans.PasteTranslation(op.translation)
358  tr = geom.Mat4()
359  tr = trans * rot
360  trans_matrices.append(tr)
361  for op_n in range(1, len(l_operations)):
362  tmp_ops = geom.Mat4List()
363  for o in l_operations[op_n]:
364  rot = geom.Mat4()
365  rot.PasteRotation(o.rotation)
366  trans = geom.Mat4()
367  trans.PasteTranslation(o.translation)
368  tr = geom.Mat4()
369  tr = trans * rot
370  for t_o in trans_matrices:
371  tp = t_o * tr
372  tmp_ops.append(tp)
373  trans_matrices = tmp_ops
374  # select chains into a view as basis for each transformation
375  assu = asu.Select('cname='+','.join(chains[c_intvls[i][0]:c_intvls[i][1]]))
376  pdbizer.Add(assu, trans_matrices, ss)
377  pdb_bu = pdbizer.Finish(transformation)
378  if transformation:
379  return pdb_bu, pdb_bu.GetTransformationMatrix()
380  return pdb_bu
381 
382 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:140
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:214
def LoadMMCIF
Definition: __init__.py:259
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