def buildAllAtomModel(pymol_model): import ChemicalObjects, Collections, Proteins data = scanModel(pymol_model) all = Collections.Collection() peptide_chains = [] for seg_id, segment in data: amino_acids = [] nucleic_acids = [] for res_name, residue in segment: res_name = res_name.lower().strip() if res_name in amino_acid_names: amino_acids.append((res_name, residue)) elif res_name in nucleic_acid_names: nucleic_acids.append((res_name, residue)) elif res_name == 'hoh': if len(residue) == 3: m = ChemicalObjects.Molecule('water') for atom_name, atom_pos in residue: atom = getattr(m, atom_name) atom.setPosition(atom_pos) elif len(residue) == 1 and residue[0][0] == 'O': m = ChemicalObjects.Atom('O') m.setPosition(residue[0][1]) all.addObject(m) else: print "Skipping unknown residue", res_name if amino_acids: chain = Proteins.PeptideChain([item[0] for item in amino_acids]) for residue, res_data in zip(chain, amino_acids): pdbmap = residue.pdbmap[0][1] try: altmap = residue.pdb_alternative except AttributeError: altmap = {} pymol_atom_list = res_data[1] atom_list = residue.atomList() for atom_name, atom_pos in pymol_atom_list: try: atom_name = altmap[atom_name] except KeyError: pass try: atom = atom_list[pdbmap[atom_name].number] except KeyError: print "No atom named " + atom_name atom.setPosition(atom_pos) print atom_name, atom.name chain.findHydrogenPositions() peptide_chains.append(chain) if peptide_chains: all.addObject(Proteins.Protein(peptide_chains)) return all
def addObject(self, object): """Adds |object| to the collection. If |object| is another collection or a list, all of its elements are added.""" if ChemicalObjects.isChemicalObject(object): self.addChemicalObject(object) elif isCollection(object): self.addChemicalObjectList(object.objectList()) elif Utility.isSequenceObject(object): if object and ChemicalObjects.isChemicalObject(object[0]): self.addChemicalObjectList(list(object)) else: for o in object: self.addObject(o) else: raise TypeError, 'Wrong object type in collection'
def addObject(self, object): """Adds |object| to the collection. If |object| is another collection or a list, all of its elements are added.""" if ChemicalObjects.isChemicalObject(object): self.addChemicalObject(object) elif isCollection(object): self.addChemicalObjectList(object.objectList()) elif Utility.isSequenceObject(object): if object and ChemicalObjects.isChemicalObject(object[0]): self.addChemicalObjectList(list(object)) else: for o in object: self.addObject(o) else: raise TypeError('Wrong object type in collection')
def description(self, objects = None, index_map = None): if objects is None: objects = self attributes = {} for attr in dir(self): if attr[0] != '_': object = getattr(self, attr) if ChemicalObjects.isChemicalObject(object) \ or Environment.isEnvironmentObject(object): attributes[object] = attr items = [] for o in objects.objectList(): attr = attributes.get(o, None) if attr is not None: items.append(repr(attr)) items.append(o.description(index_map)) for o in self._environment: attr = attributes.get(o, None) if attr is not None: items.append(repr(attr)) items.append(o.description()) s = 'c(%s,[%s])' % \ (`self.__class__.__name__ + self._descriptionArguments()`, string.join(items, ',')) return s
def position(self, object, conf): if ChemicalObjects.isChemicalObject(object): return object.position(conf) elif isVector(object): return object else: return Vector(object)
def addObject(self, object): """Adds |object| to the universe. If |object| is a Collection, all elements of the Collection are added to the universe. An object can only be added to a universe if it is not already part of another universe.""" if ChemicalObjects.isChemicalObject(object): if object.parent is not None: if isUniverse(object.parent): raise ValueError, `object` + \ ' is already in another universe' else: raise ValueError, `object` + ' is part of another object' object.parent = self self._objects.addObject(object) self._changed(1) elif Environment.isEnvironmentObject(object): for o in self._environment: o.checkCompatibilityWith(object) self._environment.append(object) self._changed(0) elif Collection.isCollection(object) \ or Utility.isSequenceObject(object): for o in object: self.addObject(o) else: raise TypeError, repr(object) + ' cannot be added to a universe'
def map(self, function): """Applies |function| to all objects in the collection and returns the list of the results. If the results are chemical objects, a Collection object is returned instead of a list.""" list = map(function, self.objectList()) if list and ChemicalObjects.isChemicalObject(list[0]): return Collection(list) else: return list
def createMolecule(self, name=None): """Returns a Molecule object corresponding to the molecule in the PDB file. The parameter |name| specifies the molecule name as defined in the chemical database. It can be left out for known molecules (currently only water).""" if name is None: name = molecule_names[self.name] m = ChemicalObjects.Molecule(name) setConfiguration(m, [self]) return m
def createGroups(self, mapping): groups = [] for name in self.molecules.keys(): full_name = mapping.get(name, None) if full_name is not None: for molecule in self.molecules[name]: g = ChemicalObjects.Group(full_name) setConfiguration(g, [molecule], toplevel=0) groups.append(g) return groups
def write(self, object, configuration=None, tag=None): """Writes |object| to the file, using coordinates from |configuration| (defaults to the current configuration). The parameter |tag| is reserved for internal use.""" if not ChemicalObjects.isChemicalObject(object): for o in object: self.write(o, configuration) else: toplevel = tag is None if toplevel: tag = Utility.uniqueAttribute() if hasattr(object, 'pdbmap'): for residue in object.pdbmap: self.file.nextResidue(residue[0], ) sorted_atoms = residue[1].items() sorted_atoms.sort( lambda x, y: cmp(x[1].number, y[1].number)) for atom_name, atom in sorted_atoms: atom = object.getAtom(atom) p = atom.position(configuration) if Utility.isDefinedPosition(p): try: occ = atom.occupancy except AttributeError: occ = 0. try: temp = atom.temperature_factor except AttributeError: temp = 0. self.file.writeAtom(atom_name, p / Units.Ang, occ, temp, atom.type.symbol) self.atom_sequence.append(atom) else: self.warning = 1 setattr(atom, tag, None) else: if hasattr(object, 'is_protein'): for chain in object: self.write(chain, configuration, tag) elif hasattr(object, 'is_chain'): self.file.nextChain(None, object.name) for residue in object: self.write(residue, configuration, tag) self.file.terminateChain() elif hasattr(object, 'molecules'): for m in object.molecules: self.write(m, configuration, tag) elif hasattr(object, 'groups'): for g in object.groups: self.write(g, configuration, tag) if toplevel: for a in object.atomList(): if not hasattr(a, tag): self.write(a, configuration, tag) delattr(a, tag)
def removeObject(self, object): """Removes |object| from the collection. If |object| is a collection or a list, each of its elements is removed. The object to be removed must be an element of the collection.""" if ChemicalObjects.isChemicalObject(object): self.removeChemicalObject(object) elif isCollection(object) or Utility.isSequenceObject(object): for o in object: self.removeObject(o) else: raise ValueError('Object not in this collection')
def removeObject(self, object): """Removes |object| from the collection. If |object| is a collection or a list, each of its elements is removed. The object to be removed must be an element of the collection.""" if ChemicalObjects.isChemicalObject(object): self.removeChemicalObject(object) elif isCollection(object) or Utility.isSequenceObject(object): for o in object: self.removeObject(o) else: raise ValueError, 'Object not in this collection'
def numberOfSolventMolecules(universe, solvent, density): """Returns the number of solvent molecules of type |solvent| that must be added to |universe|, in addition to whatever it contains already, to obtain the specified solvent |density|.""" if type(solvent) == type(''): solvent = ChemicalObjects.Molecule(solvent) cell_volume = universe.cellVolume() if cell_volume is None: raise TypeError("universe volume is undefined") solute_volume = 0. for o in universe._objects: solute_volume = solute_volume + surfaceAndVolume(o)[1] return int(round(density*(cell_volume-solute_volume)/solvent.mass()))
def write(self, object, configuration = None, tag = None): """Writes |object| to the file, using coordinates from |configuration| (defaults to the current configuration). The parameter |tag| is reserved for internal use.""" if not ChemicalObjects.isChemicalObject(object): for o in object: self.write(o, configuration) else: toplevel = tag is None if toplevel: tag = Utility.uniqueAttribute() if hasattr(object, 'pdbmap'): for residue in object.pdbmap: self.file.nextResidue(residue[0], ) sorted_atoms = residue[1].items() sorted_atoms.sort(lambda x, y: cmp(x[1].number, y[1].number)) for atom_name, atom in sorted_atoms: atom = object.getAtom(atom) p = atom.position(configuration) if Utility.isDefinedPosition(p): try: occ = atom.occupancy except AttributeError: occ = 0. try: temp = atom.temperature_factor except AttributeError: temp = 0. self.file.writeAtom(atom_name, p/Units.Ang, occ, temp, atom.type.symbol) self.atom_sequence.append(atom) else: self.warning = 1 setattr(atom, tag, None) else: if hasattr(object, 'is_protein'): for chain in object: self.write(chain, configuration, tag) elif hasattr(object, 'is_chain'): self.file.nextChain(None, object.name) for residue in object: self.write(residue, configuration, tag) self.file.terminateChain() elif hasattr(object, 'molecules'): for m in object.molecules: self.write(m, configuration, tag) elif hasattr(object, 'groups'): for g in object.groups: self.write(g, configuration, tag) if toplevel: for a in object.atomList(): if not hasattr(a, tag): self.write(a, configuration, tag) delattr(a, tag)
def save(object, filename): """Writes |object| to a newly created file with the name |filename|, for later retrieval by 'load()'.""" import ChemicalObjects filename = os.path.expanduser(filename) file = open(filename, 'wb') if ChemicalObjects.isChemicalObject(object): parent = object.parent object.parent = None Pickler(file).dump(object) object.parent = parent else: Pickler(file).dump(object) file.close()
def contiguousObjectOffset(self, objects = None, conf = None, box_coordinates = 0): from MMTK_universe import contiguous_object_offset if objects is None: default = 1 objects = self._objects.objectList() pairs = self._bond_pairs else: default = 0 pairs = None if conf is None: conf = self.configuration() cell = conf.cell_parameters offset = ParticleProperties.ParticleVector(self) if pairs is None: pairs = [] for o in objects: new_object = 1 if ChemicalObjects.isChemicalObject(o): units = o.bondedUnits() elif Collection.isCollection(o) or isUniverse(o): included = {} for element in o: top = element.topLevelChemicalObject() for u in top.bondedUnits(): included[u] = 1 units = included.keys() else: raise ValueError, str(o) + " not a chemical object" for bu in units: mpairs = bu.traverseBondTree(lambda a: a.index) if len(mpairs) == 0: atoms = bu.atomList() first = atoms[0].index for a in atoms[1:]: mpairs.append((first, a.index)) if not new_object and len(pairs) > 0: pairs.append((pairs[-1][1], mpairs[0][0])) new_object = 0 pairs = pairs + mpairs pairs = Numeric.array(pairs) if default: self._bond_pairs = pairs if cell is None: contiguous_object_offset(self._spec, pairs, conf.array, offset.array, box_coordinates) else: contiguous_object_offset(self._spec, pairs, conf.array, offset.array, box_coordinates, cell) return offset
def write(self, object, configuration = None, distance = None): if distance is None: try: distance = object.universe().distanceVector except AttributeError: distance = Universe.InfiniteUniverse().distanceVector if not ChemicalObjects.isChemicalObject(object): for o in object: self.write(o, configuration, distance) else: for bu in object.bondedUnits(): for a in bu.atomList(): self.writeAtom(a, configuration) if hasattr(bu, 'bonds'): for b in bu.bonds: self.writeBond(b, configuration, distance)
def write(self, object, configuration=None, distance=None): if distance is None: try: distance = object.universe().distanceVector except AttributeError: distance = Universe.InfiniteUniverse().distanceVector if not ChemicalObjects.isChemicalObject(object): for o in object: self.write(o, configuration, distance) else: for bu in object.bondedUnits(): for a in bu.atomList(): self.writeAtom(a, configuration) if hasattr(bu, 'bonds'): for b in bu.bonds: self.writeBond(b, configuration, distance)
def addSolvent(universe, solvent, density, scale_factor=4.): """Scales up the universe by |scale_factor| and adds as many molecules of type |solvent| (a molecul object or a string) as are necessary to obtain the specified solvent |density|, taking account of the solute molecules that are already present in the universe. The molecules are placed at random positions in the scaled-up universe, but without overlaps between any two molecules.""" # Calculate number of solvent molecules and universe size if type(solvent) == type(''): solvent = ChemicalObjects.Molecule(solvent) cell_volume = universe.cellVolume() if cell_volume is None: raise TypeError("universe volume is undefined") solute = copy.copy(universe._objects) solute_volume = 0. excluded_regions = [] for o in solute: solute_volume = solute_volume + surfaceAndVolume(o)[1] excluded_regions.append(o.boundingSphere()) n_solvent = int(round(density*(cell_volume-solute_volume)/solvent.mass())) solvent_volume = n_solvent*solvent.mass()/density cell_volume = solvent_volume + solute_volume universe.translateBy(-solute.position()) universe.scaleSize((cell_volume/universe.cellVolume())**(1./3.)) # Scale up the universe and add solvent molecules at random positions universe.scaleSize(scale_factor) universe.scale_factor = scale_factor for i in range(n_solvent): m = copy.copy(solvent) m.translateTo(universe.randomPoint()) while 1: s = m.boundingSphere() collision = 0 for region in excluded_regions: if (s.center-region.center).length() < s.radius+region.radius: collision = 1 break if not collision: break m.translateTo(universe.randomPoint()) universe.addObject(m) excluded_regions.append(s)
def removeObject(self, object): """Removes |object| from the universe. If |object| is a Collection, each of its elements is removed. The object to be removed must be in the universe.""" if Collection.isCollection(object) or Utility.isSequenceObject(object): for o in object: self.removeObject(o) elif ChemicalObjects.isChemicalObject(object): if object.parent != self: raise ValueError, `object` + ' is not in this universe.' object.parent = None self._objects.removeObject(object) self._changed(1) elif Environment.isEnvironmentObject(object): self._environment.remove(object) self._changed(0) else: raise ValueError, `object` + ' is not in this universe.'
def createMolecules(self, names=None, permit_undefined=1): """Returns a collection of Molecule objects, one for each molecule in the PDB file. Each PDB residue not describing an amino acid or nucleotide residue is considered a molecule. The parameter |names| allows the selective construction of certain molecule types and the construction of unknown molecules. If its value is a list of molecule names (as defined in the chemical database) and/or PDB residue names, only molecules mentioned in this list will be constructed. If its value is a dictionary, it is used to map PDB residue names to molecule names. By default only water molecules are recognizes (under various common PDB residue names); for all other molecules a molecule name must be provided by the user. The parameter |permit_undefined| determines how PDB residues without a corresponding molecule name are handled. A value of 0 causes an exception to be raised. A value of 1 causes an AtomCluster object to be created for each unknown residue. """ collection = Collections.Collection() mol_dicts = [molecule_names] if type(names) == type({}): mol_dicts.append(names) names = None for name in self.molecules.keys(): full_name = None for dict in mol_dicts: full_name = dict.get(name, None) if names is None or name in names or full_name in names: if full_name is None and not permit_undefined: raise ValueError("no definition for molecule " + name) for molecule in self.molecules[name]: if full_name: m = ChemicalObjects.Molecule(full_name) setConfiguration(m, [molecule]) else: pdbdict = {} atoms = [] i = 0 for atom in molecule: aname = atom.name while aname[0] in string.digits: aname = aname[1:] + aname[0] try: element = atom['element'] a = ChemicalObjects.Atom(element, name=aname) except KeyError: try: a = ChemicalObjects.Atom(aname[:2], name=aname) except IOError: a = ChemicalObjects.Atom(aname[:1], name=aname) a.setPosition(atom.position) atoms.append(a) pdbdict[atom.name] = Database.AtomReference(i) i = i + 1 m = ChemicalObjects.AtomCluster(atoms, name=name) if len(pdbdict) == len(molecule): # pdbmap is correct only if the AtomCluster has # unique atom names m.pdbmap = [(name, pdbdict)] collection.addObject(m) return collection
def __init__(self, *items, **properties): if items == (None, ): return self.name = '' if len(items) == 1 and type(items[0]) == type(''): try: filename = Database.databasePath(items[0], 'Proteins') found = 1 except IOError: found = 0 if found: blueprint = Database.BlueprintProtein(items[0]) items = blueprint.chains for attr, value in vars(blueprint).items(): if attr not in ['type', 'chains']: setattr(self, attr, value) else: import PDB conf = PDB.PDBConfiguration(items[0]) model = properties.get('model', 'all') items = conf.createPeptideChains(model) molecules = [] for i in items: if ChemicalObjects.isChemicalObject(i): molecules.append(i) else: molecules = molecules + list(i) for m, i in zip(molecules, range(len(molecules))): m._numbers = [i] if not m.name: m.name = 'chain' + ` i ` ss = self._findSSBridges(molecules) new_mol = {} for m in molecules: new_mol[m] = ([m], []) for bond in ss: m1 = new_mol[bond[0].topLevelChemicalObject()] m2 = new_mol[bond[1].topLevelChemicalObject()] if m1 == m2: m1[1].append(bond) else: combined = (m1[0] + m2[0], m1[1] + m2[1] + [bond]) for m in combined[0]: new_mol[m] = combined self.molecules = [] while new_mol: m = new_mol.values()[0] for i in m[0]: del new_mol[i] bonds = m[1] if len(m[0]) == 1: m = m[0][0] else: numbers = reduce(operator.add, map(lambda i: i._numbers, m[0])) m = ConnectedChains(m[0]) m._numbers = numbers for c in m: c.parent = self m._addSSBridges(bonds) m.parent = self self.molecules.append(m) self.atoms = [] self.chains = [] for m in self.molecules: self.atoms.extend(m.atoms) if hasattr(m, 'is_connected_chains'): for c, name, i in zip(range(len(m)), m.chain_names, m._numbers): self.chains.append((m, c, name, i)) else: try: name = m.name except AttributeError: name = '' self.chains.append((m, None, name, m._numbers[0])) self.chains.sort(lambda c1, c2: cmp(c1[3], c2[3])) self.chains = map(lambda c: c[:3], self.chains) self.parent = None self.type = None self.configurations = {} try: self.name = properties['name'] del properties['name'] except KeyError: pass if properties.has_key('position'): self.translateTo(properties['position']) del properties['position'] self.addProperties(properties) undefined = 0 for a in self.atoms: if a.position() is None: undefined = undefined + 1 if undefined > 0 and undefined != len(self.atoms): Utility.warning('Some atoms in a protein ' + 'have undefined positions.')
def __init__(self, *items, **properties): if items == (None,): return self.name = '' if len(items) == 1 and type(items[0]) == type(''): try: filename = Database.databasePath(items[0], 'Proteins') found = 1 except IOError: found = 0 if found: blueprint = Database.BlueprintProtein(items[0]) items = blueprint.chains for attr, value in vars(blueprint).items(): if attr not in ['type', 'chains']: setattr(self, attr, value) else: import PDB conf = PDB.PDBConfiguration(items[0]) model = properties.get('model', 'all') items = conf.createPeptideChains(model) molecules = [] for i in items: if ChemicalObjects.isChemicalObject(i): molecules.append(i) else: molecules = molecules + list(i) for m, i in map(None, molecules, range(len(molecules))): m._numbers = [i] if not m.name: m.name = 'chain'+`i` ss = self._findSSBridges(molecules) new_mol = {} for m in molecules: new_mol[m] = ([m],[]) for bond in ss: m1 = new_mol[bond[0].topLevelChemicalObject()] m2 = new_mol[bond[1].topLevelChemicalObject()] if m1 == m2: m1[1].append(bond) else: combined = (m1[0] + m2[0], m1[1] + m2[1] + [bond]) for m in combined[0]: new_mol[m] = combined self.molecules = [] while new_mol: m = new_mol.values()[0] for i in m[0]: del new_mol[i] bonds = m[1] if len(m[0]) == 1: m = m[0][0] else: numbers = reduce(operator.add, map(lambda i: i._numbers, m[0])) m = ConnectedChains(m[0]) m._numbers = numbers m._addSSBridges(bonds) m.parent = self self.molecules.append(m) self.atoms = [] self.chains = [] for m in self.molecules: self.atoms = self.atoms + m.atoms if hasattr(m, 'is_connected_chains'): for c, name, i in map(None, range(len(m)), m.chain_names, m._numbers): self.chains.append((m, c, name, i)) else: try: name = m.name except AttributeError: name = '' self.chains.append((m, None, name, m._numbers[0])) self.chains.sort(lambda c1, c2: cmp(c1[3], c2[3])) self.chains = map(lambda c: c[:3], self.chains) self.parent = None self.type = None self.configurations = {} try: self.name = properties['name'] del properties['name'] except KeyError: pass if properties.has_key('position'): self.translateTo(properties['position']) del properties['position'] self.addProperties(properties) undefined = 0 for a in self.atoms: if a.position() is None: undefined = undefined + 1 if undefined > 0 and undefined != len(self.atoms): Utility.warning('Some atoms in a protein ' + 'have undefined positions.')
def __setattr__(self, attr, value): self.__dict__[attr] = value if attr[0] != '_' and (ChemicalObjects.isChemicalObject(value) or Environment.isEnvironmentObject(value)): self.addObject(value)
|partition_size| -- the edge length of the cubic cells |objects| -- a chemical object or a sequence of chemical objects that define the initial content of the collection. """ def __init__(*args): apply(PartitionedCollection.__init__, args) def addChemicalObject(self, object): for atom in object.atomList(): PartitionedCollection.addChemicalObject(self, atom) def removeChemicalObject(self, object): for atom in object.atomList(): PartitionedCollection.removeChemicalObject(self, atom) # # Test code # if __name__ == '__main__': from Random import randomPointInBox from copy import copy box = PartitionedCollection(1.) for i in xrange(100): x = randomPointInBox(4., 4., 4.) box.addObject(ChemicalObjects.Atom('c', position=x))