00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 import os, tempfile, ftplib, httplib
00020
00021 from _ost_io import *
00022 from ost import mol, geom, conop, seq
00023
00024 profiles=None
00025
00026 class IOProfiles:
00027 def __init__(self):
00028 self._dict={}
00029
00030 def __getitem__(self, key):
00031 return IOProfileRegistry.Instance().Get(key)
00032
00033 def __setitem__(self, key, value):
00034 if isinstance(value, str):
00035 value=self[value].Copy()
00036 IOProfileRegistry.Instance().Set(key, value)
00037 self._dict[key]=value
00038
00039 def __len__(self):
00040 return len(self._dict)
00041
00042 def __iter__(self):
00043 return self._dict.__iter__()
00044
00045 if not profiles:
00046 profiles=IOProfiles()
00047 if conop.GetDefaultLib():
00048 processor = conop.RuleBasedProcessor(conop.GetDefaultLib())
00049 else:
00050 processor = conop.HeuristicProcessor()
00051 profiles['STRICT']=IOProfile(dialect='PDB', fault_tolerant=False,
00052 quack_mode=False, processor=processor.Copy())
00053 profiles['SLOPPY']=IOProfile(dialect='PDB', fault_tolerant=True,
00054 quack_mode=True, processor=processor.Copy())
00055 profiles['CHARMM']=IOProfile(dialect='CHARMM', fault_tolerant=True,
00056 quack_mode=False, processor=processor.Copy())
00057 profiles['DEFAULT']='STRICT'
00058
00059 def _override(val1, val2):
00060 if val2!=None:
00061 return val2
00062 else:
00063 return val1
00064
00065 def LoadPDB(filename, restrict_chains="", no_hetatms=None,
00066 fault_tolerant=None, load_multi=False, quack_mode=None,
00067 join_spread_atom_records=None, calpha_only=None,
00068 profile='DEFAULT', remote=False, dialect=None,
00069 seqres=False, bond_feasibility_check=None):
00070 """
00071 Load PDB file from disk and return one or more entities. Several options
00072 allow to customize the exact behaviour of the PDB import. For more information
00073 on these options, see :doc:`profile`.
00074
00075 Residues are flagged as ligand if they are mentioned in a HET record.
00076
00077 :param restrict_chains: If not an empty string, only chains listed in the
00078 string will be imported.
00079
00080 :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
00081 the value of :attr:`IOProfile.fault_tolerant`.
00082
00083 :param no_hetatms: If set to True, HETATM records will be ignored. Overrides
00084 the value of :attr:`IOProfile.no_hetatms`
00085
00086 :param load_multi: If set to True, a list of entities will be returned instead
00087 of only the first. This is useful when dealing with multi-PDB files.
00088
00089 :param join_spread_atom_records: If set, overrides the value of
00090 :attr:`IOProfile.join_spread_atom_records`.
00091
00092 :param remote: If set to True, the method tries to load the pdb from the
00093 remote pdb repository www.pdb.org. The filename is then interpreted as the
00094 pdb id.
00095
00096 :rtype: :class:`~ost.mol.EntityHandle` or a list thereof if `load_multi` is
00097 True.
00098
00099 :param dialect: Specifies the particular dialect to use. If set, overrides
00100 the value of :attr:`IOProfile.dialect`
00101
00102 :param seqres: Whether to read SEQRES records. If set to True, the loaded
00103 entity and seqres entry will be returned as a tuple.
00104
00105 :type dialect: :class:`str`
00106
00107
00108 :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous or
00109 inexistent file
00110 """
00111 def _override(val1, val2):
00112 if val2!=None:
00113 return val2
00114 else:
00115 return val1
00116 if isinstance(profile, str):
00117 prof=profiles[profile].Copy()
00118 elif isinstance(profile, IOProfile):
00119 prof=profile.Copy()
00120 else:
00121 raise TypeError('profile must be of type string or IOProfile, '+\
00122 'instead of %s'%type(profile))
00123 if dialect not in (None, 'PDB', 'CHARMM',):
00124 raise ValueError('dialect must be PDB or CHARMM')
00125 prof.calpha_only=_override(prof.calpha_only, calpha_only)
00126 prof.no_hetatms=_override(prof.no_hetatms, no_hetatms)
00127 prof.dialect=_override(prof.dialect, dialect)
00128 prof.quack_mode=_override(prof.quack_mode, quack_mode)
00129 if prof.processor:
00130 prof.processor.check_bond_feasibility=_override(prof.processor.check_bond_feasibility,
00131 bond_feasibility_check)
00132 prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
00133 prof.join_spread_atom_records=_override(prof.join_spread_atom_records,
00134 join_spread_atom_records)
00135
00136 tmp_file = None
00137 if remote:
00138 from ost.io.remote import RemoteGet
00139 tmp_file =RemoteGet(filename)
00140 filename = tmp_file.name
00141
00142 conop_inst=conop.Conopology.Instance()
00143 if prof.processor:
00144 if prof.dialect=='PDB':
00145 prof.processor.dialect=conop.PDB_DIALECT
00146 elif prof.dialect=='CHARMM':
00147 prof.processor.dialect=conop.CHARMM_DIALECT
00148 reader=PDBReader(filename, prof)
00149 reader.read_seqres=seqres
00150 try:
00151 if load_multi:
00152 ent_list=[]
00153 while reader.HasNext():
00154 ent=mol.CreateEntity()
00155 reader.Import(ent, restrict_chains)
00156 if prof.processor:
00157 prof.processor.Process(ent)
00158 ent_list.append(ent)
00159 if len(ent_list)==0:
00160 raise IOError("File '%s' doesn't contain any entities" % filename)
00161 return ent_list
00162 else:
00163 ent=mol.CreateEntity()
00164 if reader.HasNext():
00165 reader.Import(ent, restrict_chains)
00166 if prof.processor:
00167 prof.processor.Process(ent)
00168 else:
00169 raise IOError("File '%s' doesn't contain any entities" % filename)
00170 if seqres:
00171 return ent, reader.seqres
00172 return ent
00173 except:
00174 raise
00175
00176 def SavePDB(models, filename, dialect=None, pqr=False, profile='DEFAULT'):
00177 """
00178 Save entity or list of entities to disk. If a list of entities is supplied
00179 the PDB file will be saved as a multi PDB file. Each of the entities is
00180 wrapped into a MODEL/ENDMDL pair.
00181
00182 If the atom number exceeds 99999, '*****' is used.
00183
00184 :param models: The entity or list of entities (handles or views) to be saved
00185 :param filename: The filename
00186 :type filename: string
00187 """
00188 if not getattr(models, '__len__', None):
00189 models=[models]
00190 if isinstance(profile, str):
00191 profile=profiles[profile].Copy()
00192 elif isinstance(profile, IOProfile):
00193 profile.Copy()
00194 else:
00195 raise TypeError('profile must be of type string or IOProfile, '+\
00196 'instead of %s'%type(profile))
00197 profile.dialect=_override(profile.dialect, dialect)
00198 writer=PDBWriter(filename, profile)
00199 writer.SetIsPQR(pqr)
00200 if len(models)>1:
00201 writer.write_multi_model=True
00202 for model in models:
00203 writer.Write(model)
00204
00205 try:
00206 from ost import img
00207 LoadMap = LoadImage
00208 SaveMap = SaveImage
00209 except ImportError:
00210 pass
00211
00212
00213
00214 def LoadImageList (files):
00215 image_list=img.ImageList()
00216 for file in files:
00217 image=LoadImage(file)
00218 image_list.append(image)
00219 return image_list
00220
00221 LoadMapList=LoadImageList
00222
00223 def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
00224 lazy_load=False, stride=1,
00225 dialect=None, detect_swap=True,swap_bytes=False):
00226 """
00227 Load CHARMM trajectory file.
00228
00229 :param crd: EntityHandle or filename of the (PDB) file containing the
00230 structure. The structure must have the same number of atoms as the
00231 trajectory
00232 :param dcd_file: The filename of the DCD file. If not set, and crd is a
00233 string, the filename is set to the <crd>.dcd
00234 :param layz_load: Whether the trajectory should be loaded on demand. Instead
00235 of loading the complete trajectory into memory, the trajectory frames are
00236 loaded from disk when requested.
00237 :param stride: The spacing of the frames to load. When set to 2, for example,
00238 every second frame is loaded from the trajectory. By default, every frame
00239 is loaded.
00240 :param dialect: The dialect for the PDB file to use. See :func:`LoadPDB`. If
00241 set, overrides the value of the profile
00242 :param profile: The IO profile to use for loading the PDB file. See
00243 :doc:`profile`.
00244 :param detect_swap: if True (the default), then automatic detection of endianess
00245 is attempted, otherwise the swap_bytes parameter is used
00246 :param swap_bytes: is detect_swap is False, this flag determines whether bytes
00247 are swapped upon loading or not
00248 """
00249 if not isinstance(crd, mol.EntityHandle):
00250 if dcd_file==None:
00251 dcd_file='%s.dcd' % os.path.splitext(crd)[0]
00252 crd=LoadPDB(crd, profile=profile, dialect=dialect)
00253
00254 else:
00255 if not dcd_file:
00256 raise ValueError("No DCD filename given")
00257 return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load, detect_swap, swap_bytes)
00258
00259 def LoadMMCIF(filename, fault_tolerant=None, calpha_only=None, profile='DEFAULT', remote=False, seqres=False, info=False):
00260 """
00261 Load MMCIF file from disk and return one or more entities. Several options
00262 allow to customize the exact behaviour of the MMCIF import. For more
00263 information on these options, see :doc:`profile`.
00264
00265 Residues are flagged as ligand if they are mentioned in a HET record.
00266
00267 :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
00268 the value of :attr:`IOProfile.fault_tolerant`.
00269
00270 :param remote: If set to True, the method tries to load the pdb from the
00271 remote pdb repository www.pdb.org. The filename is then interpreted as the
00272 pdb id.
00273
00274 :rtype: :class:`~ost.mol.EntityHandle`.
00275
00276 :param seqres: Whether to read SEQRES records. If set to True, the loaded
00277 entity and seqres entry will be returned as second item.
00278
00279 :param info: Whether to return an info container with the other output.
00280 Returns a :class:`MMCifInfo` object as last item.
00281
00282 :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous
00283 or non-existent file.
00284 """
00285 def _override(val1, val2):
00286 if val2!=None:
00287 return val2
00288 else:
00289 return val1
00290 if isinstance(profile, str):
00291 prof = profiles[profile].Copy()
00292 else:
00293 prof = profile.Copy()
00294
00295 prof.calpha_only=_override(prof.calpha_only, calpha_only)
00296 prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
00297
00298 if remote:
00299 from ost.io.remote import RemoteGet
00300 tmp_file = RemoteGet(filename, from_repo='cif')
00301 filename = tmp_file.name
00302
00303 try:
00304 ent = mol.CreateEntity()
00305 reader = MMCifReader(filename, ent, prof)
00306 reader.read_seqres = seqres
00307
00308
00309
00310
00311
00312
00313 reader.Parse()
00314 if prof.processor:
00315 prof.processor.Process(ent)
00316
00317
00318 if seqres and info:
00319 return ent, reader.seqres, reader.info
00320 if seqres:
00321 return ent, reader.seqres
00322 if info:
00323 return ent, reader.info
00324 return ent
00325 except:
00326 raise
00327
00328
00329
00330
00331
00332
00333
00334 def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
00335 transformation=False):
00336 pdbizer = mol.alg.PDBize(min_polymer_size=min_polymer_size)
00337
00338 chains = biounit.GetChainList()
00339 c_intvls = biounit.GetChainIntervalList()
00340 o_intvls = biounit.GetOperationsIntervalList()
00341 ss = seqres
00342 if not ss:
00343 ss = seq.CreateSequenceList()
00344
00345
00346
00347
00348 operations = biounit.GetOperations()
00349 for i in range(0,len(c_intvls)):
00350 trans_matrices = geom.Mat4List()
00351 l_operations = operations[o_intvls[i][0]:o_intvls[i][1]]
00352 if len(l_operations) > 0:
00353 for op in l_operations[0]:
00354 rot = geom.Mat4()
00355 rot.PasteRotation(op.rotation)
00356 trans = geom.Mat4()
00357 trans.PasteTranslation(op.translation)
00358 tr = geom.Mat4()
00359 tr = trans * rot
00360 trans_matrices.append(tr)
00361 for op_n in range(1, len(l_operations)):
00362 tmp_ops = geom.Mat4List()
00363 for o in l_operations[op_n]:
00364 rot = geom.Mat4()
00365 rot.PasteRotation(o.rotation)
00366 trans = geom.Mat4()
00367 trans.PasteTranslation(o.translation)
00368 tr = geom.Mat4()
00369 tr = trans * rot
00370 for t_o in trans_matrices:
00371 tp = t_o * tr
00372 tmp_ops.append(tp)
00373 trans_matrices = tmp_ops
00374
00375 assu = asu.Select('cname='+','.join(chains[c_intvls[i][0]:c_intvls[i][1]]))
00376 pdbizer.Add(assu, trans_matrices, ss)
00377 pdb_bu = pdbizer.Finish(transformation)
00378 if transformation:
00379 return pdb_bu, pdb_bu.GetTransformationMatrix()
00380 return pdb_bu
00381
00382 MMCifInfoBioUnit.PDBize = _PDBize