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, restrict_chains="", 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 restrict_chains: If not an empty string, only chains listed in the
00268 string will be imported.
00269
00270 :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
00271 the value of :attr:`IOProfile.fault_tolerant`.
00272
00273 :param remote: If set to True, the method tries to load the pdb from the
00274 remote pdb repository www.pdb.org. The filename is then interpreted as the
00275 pdb id.
00276
00277 :rtype: :class:`~ost.mol.EntityHandle`.
00278
00279 :param seqres: Whether to read SEQRES records. If set to True, the loaded
00280 entity and seqres entry will be returned as second item.
00281
00282 :param info: Whether to return an info container with the other output.
00283 Returns a :class:`MMCifInfo` object as last item.
00284
00285 :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous
00286 or non-existent file.
00287 """
00288 def _override(val1, val2):
00289 if val2!=None:
00290 return val2
00291 else:
00292 return val1
00293 if isinstance(profile, str):
00294 prof = profiles[profile].Copy()
00295 else:
00296 prof = profile.Copy()
00297
00298 prof.calpha_only=_override(prof.calpha_only, calpha_only)
00299 prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
00300
00301 if remote:
00302 from ost.io.remote import RemoteGet
00303 tmp_file =RemoteGet(filename, from_repo='cif')
00304 filename = tmp_file.name
00305
00306 try:
00307 ent = mol.CreateEntity()
00308 reader = MMCifReader(filename, ent, prof)
00309 reader.read_seqres = seqres
00310
00311 reader.Parse()
00312 if prof.processor:
00313 prof.processor.Process(ent)
00314
00315
00316 if seqres and info:
00317 return ent, reader.seqres, reader.info
00318 if seqres:
00319 return ent, reader.seqres
00320 if info:
00321 return ent, reader.info
00322 return ent
00323 except:
00324 raise
00325
00326
00327
00328
00329
00330
00331
00332 def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
00333 transformation=False):
00334 pdbizer = mol.alg.PDBize(min_polymer_size=min_polymer_size)
00335
00336 chains = biounit.GetChainList()
00337 c_intvls = biounit.GetChainIntervalList()
00338 o_intvls = biounit.GetOperationsIntervalList()
00339 ss = seqres
00340 if not ss:
00341 ss = seq.CreateSequenceList()
00342
00343
00344
00345
00346 operations = biounit.GetOperations()
00347 for i in range(0,len(c_intvls)):
00348 trans_matrices = geom.Mat4List()
00349 l_operations = operations[o_intvls[i][0]:o_intvls[i][1]]
00350 if len(l_operations) > 0:
00351 for op in l_operations[0]:
00352 rot = geom.Mat4()
00353 rot.PasteRotation(op.rotation)
00354 trans = geom.Mat4()
00355 trans.PasteTranslation(op.translation)
00356 tr = geom.Mat4()
00357 tr = trans * rot
00358 trans_matrices.append(tr)
00359 for op_n in range(1, len(l_operations)):
00360 tmp_ops = geom.Mat4List()
00361 for o in l_operations[op_n]:
00362 rot = geom.Mat4()
00363 rot.PasteRotation(o.rotation)
00364 trans = geom.Mat4()
00365 trans.PasteTranslation(o.translation)
00366 tr = geom.Mat4()
00367 tr = trans * rot
00368 for t_o in trans_matrices:
00369 tp = t_o * tr
00370 tmp_ops.append(tp)
00371 trans_matrices = tmp_ops
00372
00373 assu = asu.Select('cname='+','.join(chains[c_intvls[i][0]:c_intvls[i][1]]))
00374 pdbizer.Add(assu, trans_matrices, ss)
00375 pdb_bu = pdbizer.Finish(transformation)
00376 if transformation:
00377 return pdb_bu, pdb_bu.GetTransformationMatrix()
00378 return pdb_bu
00379
00380 MMCifInfoBioUnit.PDBize = _PDBize