/usr/share/pyshared/MMTK/CCPNDataModel.py is in python-mmtk 2.7.9-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | # Interface to the CCPN Data Model
#
# Warning: this is a first draft and thus likely to change!
# At the moment, it is a one-way interface that creates MMTK objects
# from CCPN MolSystems and MolStructures.
#
# Written by Konrad Hinsen
#
"""Interface to the CCPN Data Model
The CCPN Data Model was created to facilitate exchange between programs
working with macromolecules and related experimental data. For more information,
see http://www.ccpn.ac.uk/datamodel/datamodel.html
Both the CCPN Data Model and MMTK's internal data model are
object-oriented representations of molecular systems and they share many
common features. However, there are important differences in terminology
that can easily create confusion. Here is a rough comparison chart between
the central classes in both models. The equivalences are of course not perfect.
CCPN MMTK
==== ====
Molecule MoleculeType
MolResidue BlueprintGroup
ChemCompVar GroupType
MolSystem set of Molecules without coordinates
MolSystem.Chain Molecule without coordinates
MolStructure set of Molecules with coordinates
MolStructure.CoordChain Molecule with coordinates
An important difference is that in the CCPN model, all molecules are chains of
residues. Non-polymeric molecules are represented as chains containing a single
residue.
"""
from MMTK.MoleculeFactory import MoleculeFactory
from MMTK import Units, Vector, Collection
from ccp.api.molecule.MolSystem import MolSystem, MolStructure
import sys
class CCPNMoleculeFactory(MoleculeFactory):
"""A MoleculeFactory built from the contents of a CCPN MolSystem.
"""
def __init__(self, mol_system):
MoleculeFactory.__init__(self)
self.mol_system = mol_system
self.group_name_mapping = {}
self.peptide_chains = {}
self.makeAllGroups()
def retrieveMoleculeForChain(self, mol_system_chain):
group_name = self.group_name_mapping[mol_system_chain]
if self.peptide_chains.has_key(group_name):
return self.retrievePeptideChain(self.peptide_chains[group_name],
mol_system_chain)
else:
return self.retrieveMolecule(group_name)
def retrievePeptideChain(self, sequence, mol_system_chain):
from MMTK.Proteins import PeptideChain, Residue
chain = PeptideChain(None)
n_terminus = \
mol_system_chain.residues[0].molResidue.chemCompVar.linking == "start"
c_terminus = \
mol_system_chain.residues[-1].molResidue.chemCompVar.linking == "end"
chain.version_spec = {'n_terminus': n_terminus,
'c_terminus': c_terminus,
'model': 'all',
'circular': False}
numbers = [r.seqId for r in mol_system_chain.residues]
chain.groups = []
n = 0
for residue, number in zip(sequence, numbers):
n = n + 1
r = Residue(residue, 'all')
r.name = r.symbol + str(number)
r.sequence_number = n
r.parent = chain
chain.groups.append(r)
chain._setupChain(False, {}, None)
return chain
def makeAllGroups(self):
for chain in self.mol_system.chains:
if chain.molecule.molType == "protein":
self.registerPeptideSequence(chain)
else:
residues = chain.residues
for residue in residues:
chem_comp_var = residue.molResidue.chemCompVar
self.makeGroupFromChemCompVar(chem_comp_var)
mol_type = chain.molecule.molType
if len(residues) > 1:
self.makeGroupFromChain(chain)
self.group_name_mapping[chain] = chain.molecule.name
else:
group_name = self.groupNameFromChemCompVar(chem_comp_var)
self.group_name_mapping[chain] = group_name
def registerPeptideSequence(self, chain):
chain_name = chain.molecule.name
self.group_name_mapping[chain] = chain_name
sequence = []
for residue in chain.residues:
chem_comp_var = residue.molResidue.chemCompVar
rd, pd, sd = self.processDescriptor(chem_comp_var.descriptor)
# The first branch is a quick hack for testing the rest of the
# code without having to create a project with realistic
# protonation states.
if False:
pd = ''
res_name = self.peptide_mapping.get(chem_comp_var.chemComp.ccpCode,
None)
if isinstance(res_name, dict):
for name in res_name.values():
if name is not None:
res_name = name
break
else:
res_name = self.peptide_mapping.get(chem_comp_var.chemComp.ccpCode,
None)
if isinstance(res_name, dict):
if rd and sd:
label = ';'.join((rd, sd))
elif rd:
label = rd
else:
label = sd
res_name = res_name.get(label, None)
if res_name is None \
or pd: # MMTK has no variants of the peptide group
raise ValueError("Unknown residue %s %s" %
(chem_comp_var.chemComp.ccpCode,
chem_comp_var.descriptor))
try:
res_name = res_name + \
self.peptide_linking[chem_comp_var.linking]
except KeyError:
raise ValueError("Unknown linking %s" % chem_comp_var.linking)
sequence.append(res_name)
self.peptide_chains[chain_name] = sequence
def processDescriptor(self, descriptor):
residue = []
peptide = []
sidechain = []
for part in descriptor.split(';'):
if ':' not in part:
residue.append(part)
else:
label, atoms = part.split(':')
atoms = atoms.split(',')
for atom in atoms:
if len(atom) > 1 and atom[1] in 'BGDEZH':
sidechain.append(label[0] + atom)
else:
peptide.append(label[0] + atom)
residue.sort()
peptide.sort()
sidechain.sort()
return ','.join(residue), ','.join(peptide), ','.join(sidechain)
peptide_mapping = {
'ALA': 'alanine',
'ARG': {'pHH12': 'arginine',
'dHH12': None},
'ASN': {'neutral': 'asparagine',
'lND2': None},
'ASP': {'pHD2': 'aspartic_acid_neutral',
'dHD2': 'aspartic_acid'},
'CYS': {'pHG': 'cysteine',
'dHG': 'cysteine_with_negative_charge',
'lSG': 'cystine_ss'},
'GLN': 'glutamine',
'GLU': {'pHE2': 'glutamic_acid_neutral',
'dHE2': 'glutamic_acid'},
'GLY': 'glycine',
'HIS': {'pHD1,pHE2': 'histidine_plus',
'dHD1,pHE2': 'histidine_epsilonh',
'dHE1,pHD1': 'histidine_deltah'},
'ILE': 'isoleucine',
'LEU': 'leucine',
'LYS': {'pHZ3': 'lysine',
'dHZ3': 'lysine_neutral'},
'MET': 'methionine',
'PHE': 'phenylalanine',
'PRO': 'proline',
'SER': {'pHG': 'serine',
'dHG': None},
'THR': {'pHG1': 'threonine',
'dHG1': None},
'TRP': {'pHE1': 'tryptophan',
'dHE1': None},
'TYR': {'pHH': 'tyrosine',
'dHH': None,},
'VAL': 'valine',
}
peptide_linking = {
'start': '_nt',
'middle': '',
'end': '_ct',
}
def groupNameFromChemCompVar(self, chem_comp_var):
group_name = chem_comp_var.name
descriptor = chem_comp_var.descriptor
if descriptor != "neutral":
group_name = group_name + '/' + descriptor
linking = chem_comp_var.linking
if linking != "none":
group_name = group_name + '/' + linking
return group_name
def makeGroupFromChemCompVar(self, chem_comp_var):
group_name = self.groupNameFromChemCompVar(chem_comp_var)
if self.groups.has_key(group_name):
return
self.createGroup(group_name)
for atom in chem_comp_var.findAllChemAtoms(className="ChemAtom"):
self.addAtom(group_name, atom.name, atom.elementSymbol)
for bond in chem_comp_var.chemBonds:
atoms = bond.findAllChemAtoms(className="ChemAtom")
if len(atoms) < 2:
continue
atom1 = atoms[0].name
atom2 = atoms[1].name
self.addBond(group_name, atom1, atom2)
def makeGroupFromChain(self, chain):
group_name = chain.molecule.name
if self.groups.has_key(group_name):
return
self.createGroup(group_name)
residue_ids = []
for residue in chain.residues:
chem_comp_var = residue.molResidue.chemCompVar
residue_name = self.groupNameFromChemCompVar(chem_comp_var)
residue_id = residue.ccpCode + str(residue.seqId)
self.addSubgroup(group_name, residue_id, residue_name)
residue_ids.append(residue_id)
for link in chain.molecule.molResLinks:
le1, le2 = link.molResLinkEnds
la1 = le1.linkEnd.boundChemAtom
la2 = le2.linkEnd.boundChemAtom
s1 = le1.parent.serial
s2 = le2.parent.serial
self.addBond(group_name,
"%s.%s" % (residue_ids[s1-1], la1.name),
"%s.%s" % (residue_ids[s2-1], la2.name))
class CoordMapping(dict):
"""Mapoing from MolSystem.Atom objects to tuples of MolStructure.Coord
objects taken from a corresponding MolStructure.
"""
def __init__(self, mol_structure):
for chain in mol_structure.coordChains:
for residue in chain.residues:
for atom in residue.atoms:
self[atom.atom] = atom.coords
def __getitem__(self, key):
return self.get(key, ())
class CCPNMolSystemAdapter(object):
"""Interface between a CCPN MolSystem and corresponding MMTK
objects. At the moment, this is one-way only (MMTK objects
can be generated from CCPN MolSystems), but ultimately it will
be two-way.
"""
def __init__(self, mol_system):
self.mol_system = mol_system
self.mol_structures = mol_system.molStructures
self.factory = CCPNMoleculeFactory(self.mol_system)
self.coord_mappings = [CoordMapping(ms) for ms in self.mol_structures]
self.ccpn_to_mmtk_atom_map = {}
self.mmtk_to_ccpn_atom_map = {}
self.ccpn_to_mmtk_molecule_map = {}
self.mmtk_to_ccpn_molecule_map = {}
def makeMolecule(self, ccpn_chain):
molecule = self.factory.retrieveMoleculeForChain(ccpn_chain)
self.ccpn_to_mmtk_molecule_map[ccpn_chain] = molecule
self.mmtk_to_ccpn_molecule_map[molecule] = ccpn_chain
residues = ccpn_chain.residues
if ccpn_chain.molecule.molType == "protein":
for i in range(len(residues)):
residue = residues[i]
my_residue = molecule[i]
self.makeAtomMaps(residue, my_residue)
else:
for residue in residues:
if len(residues) == 1:
my_residue = molecule
else:
residue_id = residue.ccpCode + str(residue.seqId)
my_residue = getattr(molecule, residue_id)
for atom in residue.atoms:
my_atom = getattr(my_residue, atom.name)
self.ccpn_to_mmtk_atom_map[atom] = my_atom
self.mmtk_to_ccpn_atom_map[my_atom] = atom
if len(self.coord_mappings) == 1:
self.assignPositions([molecule])
return molecule
def makeAtomMaps(self, ccpn_residue, my_residue):
pdbmap = my_residue.pdbmap
altmap = my_residue.pdb_alternative
for atom in ccpn_residue.atoms:
name = atom.name
name = altmap.get(name, name)
atom_ref = pdbmap[0][1][name]
my_atom = my_residue.atoms[atom_ref.number]
self.ccpn_to_mmtk_atom_map[atom] = my_atom
self.mmtk_to_ccpn_atom_map[my_atom] = atom
def makeAllMolecules(self):
molecules = Collection()
for ccpn_chain in self.mol_system.chains:
molecules.addObject(self.makeMolecule(ccpn_chain))
return molecules
def assignPositions(self, molecules, mol_structure_index=0):
mapping = self.coord_mappings[mol_structure_index]
for molecule in molecules:
for atom in molecule.atomList():
try:
coords = mapping[self.mmtk_to_ccpn_atom_map[atom]]
except KeyError:
coords = None
if coords:
position = Vector(coords[0].x, coords[0].y, coords[0].z)
atom.setPosition(position*Units.Ang)
|