148 lines
4.4 KiB
Python
148 lines
4.4 KiB
Python
'''
|
|
Experimental MMTF (Macromolecular Transmission Format) support
|
|
'''
|
|
|
|
as_str = lambda s: s if isinstance(s, str) else s.decode("utf-8")
|
|
|
|
#####################################################################
|
|
|
|
ss_map = {
|
|
0: 'H', # pi helix
|
|
1: 'L', # bend
|
|
2: 'H', # alpha helix
|
|
3: 'S', # extended
|
|
4: 'H', # 3-10 helix
|
|
5: 'S', # bridge
|
|
6: 'L', # turn
|
|
7: 'L', # coil
|
|
}
|
|
|
|
#####################################################################
|
|
|
|
def _to_chempy(data, use_auth=True):
|
|
'''
|
|
Construct a "chempy" model (molecule) from decoded MMTF data.
|
|
'''
|
|
from itertools import islice, zip_longest
|
|
from chempy import models, Atom, Bond
|
|
|
|
def add_bond(i1, i2, order, offset=0):
|
|
bond = Bond()
|
|
bond.order = order
|
|
bond.index = [i1 + offset, i2 + offset]
|
|
model.add_bond(bond)
|
|
|
|
coord_iter = data.get_table_iter([
|
|
'xCoordList',
|
|
'yCoordList',
|
|
'zCoordList',
|
|
])
|
|
|
|
atom_iter = data.get_table_iter([
|
|
'bFactorList',
|
|
'occupancyList',
|
|
'altLocList',
|
|
'atomIdList',
|
|
], [0.0, 1.0, '', -1])
|
|
|
|
group_iter = data.get_table_iter([
|
|
'groupTypeList',
|
|
'sequenceIndexList',
|
|
'groupIdList',
|
|
'insCodeList',
|
|
'secStructList',
|
|
])
|
|
|
|
chain_list_iter = enumerate(data.get_table_iter([
|
|
'chainIdList',
|
|
'chainNameList',
|
|
'groupsPerChain',
|
|
]))
|
|
|
|
groupList = data.get('groupList')
|
|
|
|
symmetry = (
|
|
data.get('unitCell', None),
|
|
as_str(data.get('spaceGroup', '')),
|
|
)
|
|
|
|
model_output = []
|
|
|
|
for n_chains in data.get_iter('chainsPerModel'):
|
|
model = models.Indexed()
|
|
model_output.append(model)
|
|
|
|
if symmetry[0] is not None:
|
|
model.cell, model.spacegroup = symmetry
|
|
|
|
for (chain_idx, (segi, chain, n_groups)) in islice(chain_list_iter, n_chains):
|
|
for (groupType, label_seq_id, auth_seq_id, ins_code, ss_info) in \
|
|
islice(group_iter, n_groups):
|
|
|
|
group = groupList[groupType]
|
|
resn = as_str(group['groupName'])
|
|
|
|
bondAtomList_iter = iter(group.get('bondAtomList', ()))
|
|
group_bond_iter = zip_longest(
|
|
bondAtomList_iter,
|
|
bondAtomList_iter,
|
|
group.get('bondOrderList', ()),
|
|
)
|
|
|
|
offset = len(model.atom)
|
|
for (i1, i2, order) in group_bond_iter:
|
|
add_bond(i1, i2, order, offset)
|
|
|
|
group_atom_iter = zip(
|
|
group['atomNameList'],
|
|
group['elementList'],
|
|
group['formalChargeList'],
|
|
)
|
|
|
|
for (name, elem, formal_charge) in group_atom_iter:
|
|
atom = Atom()
|
|
|
|
(atom.b, atom.q, atom.alt, atom.id) = next(atom_iter)
|
|
|
|
atom.coord = next(coord_iter)
|
|
atom.symbol = as_str(elem)
|
|
atom.name = as_str(name)
|
|
atom.resn = resn
|
|
atom.hetatm = label_seq_id == -1
|
|
atom.formal_charge = formal_charge
|
|
atom.segi = segi
|
|
atom.chain = chain
|
|
atom.ss = ss_map.get(ss_info, '')
|
|
|
|
if use_auth or label_seq_id is None:
|
|
atom.resi = auth_seq_id
|
|
atom.ins_code = ins_code or ''
|
|
else:
|
|
atom.resi = label_seq_id + 1
|
|
|
|
model.add_atom(atom)
|
|
|
|
model_atom_max = 0
|
|
model_atom_min = 0
|
|
model_iter = iter(model_output)
|
|
bondAtomList_iter = data.get_iter('bondAtomList')
|
|
|
|
for i1, i2, order in zip_longest(bondAtomList_iter,
|
|
bondAtomList_iter,
|
|
data.get_iter('bondOrderList'),
|
|
fillvalue=1):
|
|
if i1 >= model_atom_max or i2 >= model_atom_max:
|
|
model = next(model_iter)
|
|
model_atom_min = model_atom_max
|
|
model_atom_max += len(model.atom)
|
|
add_bond(i1, i2, order, -model_atom_min)
|
|
|
|
return model_output
|
|
|
|
#####################################################################
|
|
|
|
from .io import MmtfReader
|
|
MmtfReader.to_chempy = _to_chempy
|
|
|
|
#####################################################################
|