def viewSequence(object, conf_list, periodic=False, label=None): """ Launches an animation using an external viewer. :param object: the object for which the animation is displayed. :type object: :class:`~MMTK.Collections.GroupOfAtoms` :param conf_list: a sequence of configurations that define the animation :type conf_list: sequence :param periodic: if True, turn animation into a loop :param label: an optional text string that some interfaces use to pass a description of the object to the visualization system. :type label: str """ pdbviewer, exec_path = viewer.get('pdb', (None, None)) function = { 'vmd': viewSequenceVMD, 'xmol': viewSequenceXMol, 'imol': viewSequenceIMol, None: None }[pdbviewer] if function is None: Utility.warning('No viewer with animation feature defined.') else: function(object, conf_list, periodic, label)
def __init__(self, atoms, constraints): self.atoms = atoms natoms = len(self.atoms) nconst = sum([len(c) for c in constraints]) b = N.zeros((nconst, natoms), N.Float) c = N.zeros((nconst, ), N.Float) i = 0 for cons in constraints: cons.setCoefficients(self.atoms, b, c, i) i = i + len(cons) u, s, vt = LA.singular_value_decomposition(b) self.rank = 0 for i in range(min(natoms, nconst)): if s[i] > 0.: self.rank = self.rank + 1 self.b = b self.bi = LA.generalized_inverse(b) self.p = N.identity(natoms) - N.dot(self.bi, self.b) self.c = c self.bi_c = N.dot(self.bi, c) c_test = N.dot(self.b, self.bi_c) if N.add.reduce((c_test - c)**2) / nconst > 1.e-12: Utility.warning("The charge constraints are inconsistent." " They will be applied as a least-squares" " condition.")
def __init__(self, atoms, constraints): self.atoms = atoms natoms = len(self.atoms) nconst = sum([len(c) for c in constraints]) b = N.zeros((nconst, natoms), N.Float) c = N.zeros((nconst,), N.Float) i = 0 for cons in constraints: cons.setCoefficients(self.atoms, b, c, i) i = i + len(cons) u, s, vt = LA.singular_value_decomposition(b) self.rank = 0 for i in range(min(natoms, nconst)): if s[i] > 0.: self.rank = self.rank + 1 self.b = b self.bi = LA.generalized_inverse(b) self.p = N.identity(natoms)-N.dot(self.bi, self.b) self.c = c self.bi_c = N.dot(self.bi, c) c_test = N.dot(self.b, self.bi_c) if N.add.reduce((c_test-c)**2)/nconst > 1.e-12: Utility.warning("The charge constraints are inconsistent." " They will be applied as a least-squares" " condition.")
def write(self, object, configuration = None, tag = None): """ Write an object to the file :param object: the object to be written :type object: :class:~MMTK.Collections.GroupOfAtoms :param configuration: the configuration from which the coordinates are taken (default: current configuration) :type configuration: :class:~MMTK.ParticleProperties.Configuration """ 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 = True 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 __init__(self, b1, b2, ca): self.b1 = b1 # bond 1 self.b2 = b2 # bond 2 self.ca = ca # common atom if Utility.uniqueID(self.b2) < Utility.uniqueID(self.b1): self.b1, self.b2 = self.b2, self.b1 self.a1 = b1.otherAtom(ca) self.a2 = b2.otherAtom(ca) Utility.uniqueID.registerObject(self)
def write(self, object, configuration = None, tag = None): """ Write an object to the file :param object: the object to be written :type object: :class:`~MMTK.Collections.GroupOfAtoms` :param configuration: the configuration from which the coordinates are taken (default: current configuration) :type configuration: :class:`~MMTK.ParticleProperties.Configuration` """ 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 = True 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 __init__(self, blueprint, memo=None): if type(blueprint) is type(()): self.a1 = blueprint[0] self.a2 = blueprint[1] else: self.a1 = Database.instantiate(blueprint.a1, memo) self.a2 = Database.instantiate(blueprint.a2, memo) if Utility.uniqueID(self.a2) < Utility.uniqueID(self.a1): self.a1, self.a2 = self.a2, self.a1 Utility.uniqueID.registerObject(self)
def __init__(self, blueprint, memo = None): if type(blueprint) is type(()): self.a1 = blueprint[0] self.a2 = blueprint[1] else: self.a1 = Database.instantiate(blueprint.a1, memo) self.a2 = Database.instantiate(blueprint.a2, memo) if Utility.uniqueID(self.a2) < Utility.uniqueID(self.a1): self.a1, self.a2 = self.a2, self.a1 Utility.uniqueID.registerObject(self)
def close(self): """ Closes the file. Must be called in order to prevent data loss. """ if self.model_number is not None: self.file.writeLine('ENDMDL', '') self.file.close() if self.warning: Utility.warning('Some atoms are missing in the output file ' + \ 'because their positions are undefined.') self.warning = False
def setConfiguration(object, pdb_residues, map = 'pdbmap', alt = 'pdb_alternative', atom_map = None, toplevel = True): defined = 0 if hasattr(object, 'is_protein'): i = 0 for chain in object: l = len(chain) defined += setConfiguration(chain, pdb_residues[i:i+l], map, alt, atom_map, False) i = i + l elif hasattr(object, 'is_chain'): for i in range(len(object)): defined += setConfiguration(object[i], pdb_residues[i:i+1], map, alt, atom_map, False) elif hasattr(object, map): pdbmap = getattr(object, map) try: altmap = getattr(object, alt) except AttributeError: altmap = {} nres = len(pdb_residues) if len(pdbmap) != nres: raise IOError('PDB configuration does not match object ' + object.fullName()) for i in range(nres): defined += setResidueConfiguration(object, pdb_residues[i], pdbmap[i], altmap, atom_map) elif Collections.isCollection(object): nres = len(pdb_residues) if len(object) != nres: raise IOError('PDB configuration does not match object ' + object.fullName()) for i in range(nres): defined += setConfiguration(object[i], [pdb_residues[i]], map, alt, atom_map, False) else: try: name = object.fullName() except AttributeError: try: name = object.name except AttributeError: name = '???' raise IOError('PDB configuration does not match object ' + name) if toplevel and defined < object.numberOfAtoms(): name = '[unnamed object]' try: name = object.fullName() except: pass if name: name = ' in ' + name Utility.warning(`object.numberOfAtoms()-defined` + ' atom(s)' + name + ' were not assigned (new) positions.') return defined
def setConfiguration(object, pdb_residues, map = 'pdbmap', alt = 'pdb_alternative', atom_map = None, toplevel = True): defined = 0 if hasattr(object, 'is_protein'): i = 0 for chain in object: l = len(chain) defined += setConfiguration(chain, pdb_residues[i:i+l], map, alt, atom_map, False) i = i + l elif hasattr(object, 'is_chain'): for i in range(len(object)): defined += setConfiguration(object[i], pdb_residues[i:i+1], map, alt, atom_map, False) elif hasattr(object, map): pdbmap = getattr(object, map) try: altmap = getattr(object, alt) except AttributeError: altmap = {} nres = len(pdb_residues) if len(pdbmap) != nres: raise IOError('PDB configuration does not match object ' + object.fullName()) for i in range(nres): defined += setResidueConfiguration(object, pdb_residues[i], pdbmap[i], altmap, atom_map) elif Collections.isCollection(object): nres = len(pdb_residues) if len(object) != nres: raise IOError('PDB configuration does not match object ' + object.fullName()) for i in range(nres): defined += setConfiguration(object[i], [pdb_residues[i]], map, alt, atom_map, False) else: try: name = object.fullName() except AttributeError: try: name = object.name except AttributeError: name = '???' raise IOError('PDB configuration does not match object ' + name) if toplevel and defined < object.numberOfAtoms(): name = '[unnamed object]' try: name = object.fullName() except: pass if name: name = ' in ' + name Utility.warning(object.numberOfAtoms()-defined + ' atom(s)' + name + ' were not assigned (new) positions.') return defined
def pairsWithinCutoff(self, cutoff): """ :param cutoff: a cutoff for pair distances :returns: a list containing all pairs of objects in the collection whose center-of-mass distance is less than the cutoff :rtype: list """ pairs = [] positions = {} for index, objects in self.partition.items(): pos = map(lambda o: o.position(), objects) positions[index] = pos for o1, o2 in Utility.pairs(zip(objects, pos)): if (o2[1]-o1[1]).length() <= cutoff: pairs.append((o1[0], o2[0])) partition_cutoff = int(N.floor((cutoff/self.partition_size)**2)) ones = N.array([1,1,1]) zeros = N.array([0,0,0]) keys = self.partition.keys() for i in range(len(keys)): p1 = keys[i] for j in range(i+1, len(keys)): p2 = keys[j] d = N.maximum(abs(N.array(p2)-N.array(p1)) - ones, zeros) if N.add.reduce(d*d) <= partition_cutoff: for o1, pos1 in zip(self.partition[p1], positions[p1]): for o2, pos2 in zip(self.partition[p2], positions[p2]): if (pos2-pos1).length() <= cutoff: pairs.append((o1, o2)) return pairs
def dihedralAngles(self): """ :returns: a list of all dihedral angles that can be formed from the bond angles in the list :rtype: :class:`~MMTK.Bonds.DihedralAngleList` """ # find all bonds that are involved in more than one bond angle angles = {} bond_list = [] for angle in self.data: try: al = angles[angle.b1] except KeyError: al = [] angles[angle.b1] = al bond_list.append(angle.b1) al.append(angle) try: al = angles[angle.b2] except KeyError: al = [] angles[angle.b2] = al bond_list.append(angle.b2) al.append(angle) dihedrals = [] for bond in bond_list: # each pair of bond angles with a common bond defines a dihedral for p in Utility.pairs(angles[bond]): d = DihedralAngle(p[0], p[1], bond) if d.normalized: dihedrals.append(d) return DihedralAngleList(dihedrals)
def bondAngles(self): """ :returns: a list of all bond angles that can be formed from the bonds in the list :rtype: :class:`~MMTK.Bonds.BondAngleList` """ if self.bond_angles is None: # find all atoms that are involved in more than one bond bonds = {} atom_list = [] for bond in self: try: bl = bonds[bond.a1] except KeyError: bl = [] bonds[bond.a1] = bl atom_list.append(bond.a1) bl.append(bond) try: bl = bonds[bond.a2] except KeyError: bl = [] bonds[bond.a2] = bl atom_list.append(bond.a2) bl.append(bond) angles = [] for atom in atom_list: # each pair of bonds at the same atom defines a bond angle for p in Utility.pairs(bonds[atom]): angles.append(BondAngle(p[0], p[1], atom)) self.bond_angles = BondAngleList(angles) return self.bond_angles
def pairsWithinCutoff(self, cutoff): """ :param cutoff: a cutoff for pair distances :returns: a list containing all pairs of objects in the collection whose center-of-mass distance is less than the cutoff :rtype: list """ pairs = [] positions = {} for index, objects in self.partition.items(): pos = map(lambda o: o.position(), objects) positions[index] = pos for o1, o2 in Utility.pairs(zip(objects, pos)): if (o2[1] - o1[1]).length() <= cutoff: pairs.append((o1[0], o2[0])) partition_cutoff = int(N.floor((cutoff / self.partition_size)**2)) ones = N.array([1, 1, 1]) zeros = N.array([0, 0, 0]) keys = self.partition.keys() for i in range(len(keys)): p1 = keys[i] for j in range(i + 1, len(keys)): p2 = keys[j] d = N.maximum(abs(N.array(p2) - N.array(p1)) - ones, zeros) if N.add.reduce(d * d) <= partition_cutoff: for o1, pos1 in zip(self.partition[p1], positions[p1]): for o2, pos2 in zip(self.partition[p2], positions[p2]): if (pos2 - pos1).length() <= cutoff: pairs.append((o1, o2)) return pairs
def forceConstantTest(universe, atoms = None, delta = 0.0001): """ Test force constants by comparing to the numerical derivatives of the gradients. :param universe: the universe on which the test is performed :type universe: :class:`~MMTK.Universe.Universe` :param atoms: the atoms of the universe for which the gradient is tested (default: all atoms) :type atoms: list :param delta: the step size used in calculating the numerical derivatives :type delta: float """ e0, grad0, fc = universe.energyGradientsAndForceConstants() if atoms is None: atoms = universe.atomList() for a1, a2 in itertools.chain(itertools.izip(atoms, atoms), Utility.pairs(atoms)): print a1, a2 print fc[a1, a2] num_fc = [] for v in [ex, ey, ez]: x = a1.position() a1.setPosition(x+delta*v) e_plus, grad_plus = universe.energyAndGradients() a1.setPosition(x-delta*v) e_minus, grad_minus = universe.energyAndGradients() a1.setPosition(x) num_fc.append(0.5*(grad_plus[a2]-grad_minus[a2])/delta) print N.array(map(lambda a: a.array, num_fc))
def forceConstantTest(universe, atoms=None, delta=0.0001): """ Test force constants by comparing to the numerical derivatives of the gradients. :param universe: the universe on which the test is performed :type universe: :class:`~MMTK.Universe.Universe` :param atoms: the atoms of the universe for which the gradient is tested (default: all atoms) :type atoms: list :param delta: the step size used in calculating the numerical derivatives :type delta: float """ e0, grad0, fc = universe.energyGradientsAndForceConstants() if atoms is None: atoms = universe.atomList() for a1, a2 in itertools.chain(itertools.izip(atoms, atoms), Utility.pairs(atoms)): print a1, a2 print fc[a1, a2] num_fc = [] for v in [ex, ey, ez]: x = a1.position() a1.setPosition(x + delta * v) e_plus, grad_plus = universe.energyAndGradients() a1.setPosition(x - delta * v) e_minus, grad_minus = universe.energyAndGradients() a1.setPosition(x) num_fc.append(0.5 * (grad_plus[a2] - grad_minus[a2]) / delta) print N.array(map(lambda a: a.array, num_fc))
def setReferences(self): atom_refs = [] for i in range(len(self.atoms)): atom_refs.append(AtomReference(i)) for attr in vars(self).items(): if attr[0] not in self.instance: setattr(self, attr[0], Utility.substitute(getattr(self, attr[0]), self.atoms, atom_refs))
def atomsWithDefinedPositions(self, conf = None): """ :param conf: a configuration object, or None for the current configuration :type conf: :class:`~MMTK.ParticleProperties.Configuration` or NoneType :returns: a collection of all atoms that have a position in the given configuration """ return Collection([a for a in self.atomIterator() if Utility.isDefinedPosition(a.position(conf))])
def addToForceConstants(total_fc, indices, small_fc): indices = zip(indices, range(len(indices))) for i1, i2 in itertools.chain(itertools.izip(indices, indices), Utility.pairs(indices)): ii1, jj1 = i1 ii2, jj2 = i2 if ii1 > ii2: ii1, ii2 = ii2, ii1 jj1, jj2 = jj2, jj1 jj1 = 3*jj1 jj2 = 3*jj2 total_fc[ii1,:,ii2,:] += small_fc[jj1:jj1+3, jj2:jj2+3]
def excludedPairs(self, subset1, subset2, global_data): if 'excluded_pairs' not in global_data.get('initialized'): excluded_pairs = set(global_data.get('excluded_pairs')) if subset1 is not None: set1 = set(a.index for a in subset1.atomList()) set2 = set(a.index for a in subset2.atomList()) excluded_pairs |= set(Utility.orderedPairs(list(set1 - set2))) excluded_pairs |= set(Utility.orderedPairs(list(set2 - set1))) atom_subset = list(set1 | set2) atom_subset.sort() else: atom_subset = None global_data.set('atom_subset', atom_subset) global_data.set('excluded_pairs', list(excluded_pairs)) one_four_pairs = set(global_data.get('1_4_pairs')) \ - excluded_pairs global_data.set('1_4_pairs', list(one_four_pairs)) global_data.add('initialized', 'excluded_pairs') return global_data.get('excluded_pairs'), \ global_data.get('1_4_pairs'), \ global_data.get('atom_subset')
def addToForceConstants(total_fc, indices, small_fc): indices = zip(indices, range(len(indices))) for i1, i2 in map(lambda i: (i, i), indices) + Utility.pairs(indices): ii1, jj1 = i1 ii2, jj2 = i2 if ii1 > ii2: ii1, ii2 = ii2, ii1 jj1, jj2 = jj2, jj1 jj1 = 3 * jj1 jj2 = 3 * jj2 total_fc[ii1,:,ii2,:] = total_fc[ii1,:,ii2,:] + \ small_fc[jj1:jj1+3, jj2:jj2+3]
def excludedPairs(self, subset1, subset2, global_data): if 'excluded_pairs' not in global_data.get('initialized'): excluded_pairs = set(global_data.get('excluded_pairs')) if subset1 is not None: set1 = set(a.index for a in subset1.atomList()) set2 = set(a.index for a in subset2.atomList()) excluded_pairs |= set(Utility.orderedPairs(list(set1-set2))) excluded_pairs |= set(Utility.orderedPairs(list(set2-set1))) atom_subset = list(set1 | set2) atom_subset.sort() else: atom_subset = None global_data.set('atom_subset', atom_subset) global_data.set('excluded_pairs', list(excluded_pairs)) one_four_pairs = set(global_data.get('1_4_pairs')) \ - excluded_pairs global_data.set('1_4_pairs', list(one_four_pairs)) global_data.add('initialized', 'excluded_pairs') return global_data.get('excluded_pairs'), \ global_data.get('1_4_pairs'), \ global_data.get('atom_subset')
def addToForceConstants(total_fc, indices, small_fc): indices = map(None, indices, range(len(indices))) for i1, i2 in map(lambda i: (i,i), indices) + Utility.pairs(indices): ii1, jj1 = i1 ii2, jj2 = i2 if ii1 > ii2: ii1, ii2 = ii2, ii1 jj1, jj2 = jj2, jj1 jj1 = 3*jj1 jj2 = 3*jj2 total_fc[ii1,:,ii2,:] = total_fc[ii1,:,ii2,:] + \ small_fc[jj1:jj1+3, jj2:jj2+3]
def __init__(self, ba1, ba2, cb): self.ba1 = ba1 # bond angle 1 self.ba2 = ba2 # bond angle 2 # cb is the common bond, i.e. the central bond for a proper dihedral if Utility.uniqueID(self.ba2) < Utility.uniqueID(self.ba1): self.ba1, self.ba2 = self.ba2, self.ba1 self.improper = (self.ba1.ca is self.ba2.ca) if self.improper: self.b1 = self.ba1.otherBond(cb) self.b2 = cb self.b3 = self.ba2.otherBond(cb) self.a1 = self.ba1.ca # central atom self.a2 = self.b1.otherAtom(self.ba1.ca) self.a3 = cb.otherAtom(self.ba1.ca) self.a4 = self.b3.otherAtom(self.ba2.ca) # each improper dihedral will come in three versions; # identify an arbitrary unique one for constructing the list self.normalized = Utility.uniqueID(cb) < Utility.uniqueID(self.b1)\ and Utility.uniqueID(cb) < \ Utility.uniqueID(self.b3) else: self.b1 = self.ba1.otherBond(cb) self.b2 = cb self.b3 = self.ba2.otherBond(cb) self.a1 = self.b1.otherAtom(self.ba1.ca) self.a2 = self.ba1.ca # these two are self.a3 = self.ba2.ca # on the common bond self.a4 = self.b3.otherAtom(self.ba2.ca) self.normalized = self.a1 is not self.a4
def databasePath(filename, directory, try_direct = False): if Utility.isURL(filename): return filename filename = os.path.expanduser(filename) if try_direct and os.path.exists(filename): return os.path.normcase(filename) entries = [] if os.path.split(filename)[0] == '': for p in path: if Utility.isURL(p): url = Utility.joinURL(p, directory+'/'+filename) if Utility.checkURL(url): entries.append(url) else: full_name = os.path.join(os.path.join(p, directory), filename) if os.path.exists(full_name): entries.append(os.path.normcase(full_name)) if len(entries) == 0: raise IOError("Database entry %s/%s not found" % (directory, filename)) else: if len(entries) > 1: Utility.warning("multiple database entries for %s/%s, using first one" % (directory, filename)) for e in entries: sys.stderr.write(e+'\n') return entries[0]
def databasePath(filename, directory, try_direct=False): if Utility.isURL(filename): return filename filename = os.path.expanduser(filename) if try_direct and os.path.exists(filename): return os.path.normcase(filename) entries = [] if os.path.split(filename)[0] == '': for p in path: if Utility.isURL(p): url = Utility.joinURL(p, directory + '/' + filename) if Utility.checkURL(url): entries.append(url) else: full_name = os.path.join(os.path.join(p, directory), filename) if os.path.exists(full_name): entries.append(os.path.normcase(full_name)) if len(entries) == 0: raise IOError("Database entry %s/%s not found" % (directory, filename)) else: if len(entries) > 1: Utility.warning( "multiple database entries for %s/%s, using first one" % (directory, filename)) for e in entries: sys.stderr.write(e + '\n') return entries[0]
def evaluatorTerms(self, universe, subset1, subset2, global_data): nothing = N.zeros((0, 2), N.Int) if subset1 is not None: set1 = set(a.index for a in subset1.atomList()) set2 = set(a.index for a in subset2.atomList()) excluded_pairs = set(Utility.orderedPairs(list(set1-set2))) \ | set(Utility.orderedPairs(list(set2-set1))) excluded_pairs = N.array(list(excluded_pairs)) atom_subset = list(set1 | set2) atom_subset.sort() atom_subset = N.array(atom_subset) else: atom_subset = N.array([], N.Int) excluded_pairs = nothing nbl = NonbondedList(excluded_pairs, nothing, atom_subset, universe._spec, self.cutoff) update = NonbondedListTerm(nbl) cutoff = self.cutoff if cutoff is None: cutoff = 0. ev = ANTerm(universe._spec, nbl, cutoff, self.scale_factor) return [update, ev]
def viewSequence(object, conf_list, periodic = False, label = None): """ Launches an animation using an external viewer. :param object: the object for which the animation is displayed. :type object: :class:`~MMTK.Collections.GroupOfAtoms` :param conf_list: a sequence of configurations that define the animation :type conf_list: sequence :param periodic: if True, turn animation into a loop :param label: an optional text string that some interfaces use to pass a description of the object to the visualization system. :type label: str """ pdbviewer, exec_path = viewer.get('pdb', (None, None)) function = {'vmd': viewSequenceVMD, 'xmol': viewSequenceXMol, 'imol': viewSequenceIMol, None: None}[pdbviewer] if function is None: Utility.warning('No viewer with animation feature defined.') else: function(object, conf_list, periodic, label)
def __init__(self, universe, rigid_bodies): """ :param universe: the universe for which the subspace is created :type universe: :class:`~MMTK.Universe.Universe` :param rigid_bodies: a list or set of rigid bodies with some common atoms """ ex_ey_ez = [Vector(1.,0.,0.), Vector(0.,1.,0.), Vector(0.,0.,1.)] # Constructs # 1) a list of vectors describing the rigid-body motions of each # rigid body as if it were independent. # 2) a list of pair-distance constraint vectors for all pairs of # atoms inside a rigid body. # The LRB subspace is constructed from the projections of the # first set of vectors onto the orthogonal complement of the # subspace generated by the second set of vectors. vectors = [] c_vectors = [] for rb in rigid_bodies: atoms = rb.atomList() for d in ex_ey_ez: v = ParticleProperties.ParticleVector(universe) for a in atoms: v[a] = d vectors.append(v) if len(atoms) > 1: center = rb.centerOfMass() iv = len(vectors)-3 for d in ex_ey_ez: v = ParticleProperties.ParticleVector(universe) for a in atoms: v[a] = d.cross(a.position()-center) for vt in vectors[iv:]: v -= v.dotProduct(vt)*vt if v.dotProduct(v) > 0.: vectors.append(v) for a1, a2 in Utility.pairs(atoms): distance = universe.distanceVector(a1.position(), a2.position()) v = ParticleProperties.ParticleVector(universe) v[a1] = distance v[a2] = -distance c_vectors.append(v) if c_vectors: constraints = Subspace(universe, c_vectors) vectors = [constraints.projectionComplementOf(v) for v in vectors] Subspace.__init__(self, universe, vectors)
def __init__(self, universe, rigid_bodies): """ :param universe: the universe for which the subspace is created :type universe: :class:~MMTK.Universe.Universe :param rigid_bodies: a list or set of rigid bodies with some common atoms """ ex_ey_ez = [Vector(1.,0.,0.), Vector(0.,1.,0.), Vector(0.,0.,1.)] # Constructs # 1) a list of vectors describing the rigid-body motions of each # rigid body as if it were independent. # 2) a list of pair-distance constraint vectors for all pairs of # atoms inside a rigid body. # The LRB subspace is constructed from the projections of the # first set of vectors onto the orthogonal complement of the # subspace generated by the second set of vectors. vectors = [] c_vectors = [] for rb in rigid_bodies: atoms = rb.atomList() for d in ex_ey_ez: v = ParticleProperties.ParticleVector(universe) for a in atoms: v[a] = d vectors.append(v) if len(atoms) > 1: center = rb.centerOfMass() iv = len(vectors)-3 for d in ex_ey_ez: v = ParticleProperties.ParticleVector(universe) for a in atoms: v[a] = d.cross(a.position()-center) for vt in vectors[iv:]: v -= v.dotProduct(vt)*vt if v.dotProduct(v) > 0.: vectors.append(v) for a1, a2 in Utility.pairs(atoms): distance = universe.distanceVector(a1.position(), a2.position()) v = ParticleProperties.ParticleVector(universe) v[a1] = distance v[a2] = -distance c_vectors.append(v) if c_vectors: constraints = Subspace(universe, c_vectors) vectors = [constraints.projectionComplementOf(v) for v in vectors] Subspace.__init__(self, universe, vectors)
def evaluatorParameters(self, universe, subset1, subset2, global_data): if universe.is_periodic and \ (len(self.atom_indices_1) > 1 or len(self.atom_indices_1) > 1): raise ValueError("Center-of-mass restraints not implemented" " for periodic universes") ok = False for s1, s2 in [(subset1, subset2), (subset2, subset1)]: if s1 is None and s1 is None: ok = True break s1 = set(a.index for a in s1.atomIterator()) diff1 = set(self.atom_indices_1).difference(s1) s2 = set(a.index for a in s2.atomIterator()) diff2 = set(self.atom_indices_2).difference(s2) if not diff1 and not diff2: # Each object is in one of the subsets ok = True break if (diff1 and len(diff1) != len(self.atom_indices_1)) \ or (diff2 and len(diff2) != len(self.atom_indices_2)): # The subset contains some but not all of the # restrained atoms. raise ValueError("Restrained atoms partially " "in a subset") global_data.add('initialized', self.__class__) if not ok: # The objects are not in the subsets, so there is no # contribution to the total energy. return {'harmonic_distance_cm': []} if self.nb_exclusion: assert len(self.atom_indices_1) == 1 assert len(self.atom_indices_2) == 1 i1 = self.atom_indices_1[0] i2 = self.atom_indices_2[0] global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) if len(self.atom_indices_1) == 1 and len(self.atom_indices_2) == 1: # Keep the old format for the single-atom case for best # compatibility with older MMTK versions. return { 'harmonic_distance_term': [(self.atom_indices_1[0], self.atom_indices_2[0], self.distance, self.force_constant)] } else: return { 'harmonic_distance_cm': [(self.atom_indices_1, self.atom_indices_2, self.distance, self.force_constant)] }
def addBondTerm(self, data, bond, object, global_data): a1 = bond.a1 a2 = bond.a2 i1 = a1.index i2 = a2.index global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] try: p = self.dataset.bondParameters(t1, t2) except KeyError: raise KeyError(('No parameters for bond %s (atom type %s)' + ' - %s (atom type %s)') % (str(a1), t1, str(a2), t2)) if p is not None and p[1] != 0.: data.add('bonds', (i1, i2, p[0], p[1]*self.scale_factor))
def addBondTerm(self, data, bond, object, global_data): a1 = bond.a1 a2 = bond.a2 i1 = a1.index i2 = a2.index global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] try: p = self.dataset.bondParameters(t1, t2) except KeyError: raise KeyError( ('No parameters for bond %s (atom type %s)' + ' - %s (atom type %s)') % (str(a1), t1, str(a2), t2)) if p is not None and p[1] != 0.: data.add('bonds', (i1, i2, p[0], p[1] * self.scale_factor))
def addBondTerm(self, data, bond, object, global_data): if not self.arguments[0]: return a1 = bond.a1 a2 = bond.a2 i1 = a1.index i2 = a2.index global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] try: p = self.dataset.bondParameters(t1, t2) except KeyError: raise KeyError('No parameters for bond ' + a1 + '--' + a2) if p is not None: d = data.get('universe').distance(a1, a2) data.add('bonds', (i1, i2, d, p[1]))
def forceConstantTest(universe, atoms = None, delta = 0.0001): e0, grad0, fc = universe.energyGradientsAndForceConstants() if atoms is None: atoms = universe.atomList() for a1, a2 in map(lambda a: (a,a), atoms) + Utility.pairs(atoms): print a1, a2 print fc[a1, a2] num_fc = [] for v in [VectorModule.ex, VectorModule.ey, VectorModule.ez]: x = a1.position() a1.setPosition(x+delta*v) e_plus, grad_plus = universe.energyAndGradients() a1.setPosition(x-delta*v) e_minus, grad_minus = universe.energyAndGradients() a1.setPosition(x) num_fc.append(0.5*(grad_plus[a2]-grad_minus[a2])/delta) print Numeric.array(map(lambda a: a.array, num_fc))
def addBondTerm(self, data, bond, object, global_data): if not self.arguments[0]: return a1 = bond.a1 a2 = bond.a2 i1 = a1.index i2 = a2.index global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] try: p = self.dataset.bondParameters(t1, t2) except KeyError: raise KeyError('No parameters for bond ' + `a1` + '--' + `a2`) if p is not None: d = data.get('universe').distance(a1, a2) data.add('bonds', (i1, i2, d, p[1]))
def forceConstantTest(universe, atoms=None, delta=0.0001): e0, grad0, fc = universe.energyGradientsAndForceConstants() if atoms is None: atoms = universe.atomList() for a1, a2 in map(lambda a: (a, a), atoms) + Utility.pairs(atoms): print a1, a2 print fc[a1, a2] num_fc = [] for v in [ex, ey, ez]: x = a1.position() a1.setPosition(x + delta * v) e_plus, grad_plus = universe.energyAndGradients() a1.setPosition(x - delta * v) e_minus, grad_minus = universe.energyAndGradients() a1.setPosition(x) num_fc.append(0.5 * (grad_plus[a2] - grad_minus[a2]) / delta) print Numeric.array(map(lambda a: a.array, num_fc))
def evaluatorParameters(self, universe, subset1, subset2, global_data): if universe.is_periodic and \ (len(self.atom_indices_1) > 1 or len(self.atom_indices_1) > 1): raise ValueError("Center-of-mass restraints not implemented" " for periodic universes") ok = False for s1, s2 in [(subset1, subset2), (subset2, subset1)]: if s1 is None and s1 is None: ok = True break s1 = set(a.index for a in s1.atomIterator()) diff1 = set(self.atom_indices_1).difference(s1) s2 = set(a.index for a in s2.atomIterator()) diff2 = set(self.atom_indices_2).difference(s2) if not diff1 and not diff2: # Each object is in one of the subsets ok = True break if (diff1 and len(diff1) != len(self.atom_indices_1)) \ or (diff2 and len(diff2) != len(self.atom_indices_2)): # The subset contains some but not all of the # restrained atoms. raise ValueError("Restrained atoms partially " "in a subset") global_data.add('initialized', self.__class__) if not ok: # The objects are not in the subsets, so there is no # contribution to the total energy. return {'harmonic_distance_cm': []} if self.nb_exclusion: assert len(self.atom_indices_1) == 1 assert len(self.atom_indices_2) == 1 i1 = self.atom_indices_1[0] i2 = self.atom_indices_2[0] global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) if len(self.atom_indices_1) == 1 and len(self.atom_indices_2) == 1: # Keep the old format for the single-atom case for best # compatibility with older MMTK versions. return {'harmonic_distance_term': [(self.atom_indices_1[0], self.atom_indices_2[0], self.distance, self.force_constant)]} else: return {'harmonic_distance_cm': [(self.atom_indices_1, self.atom_indices_2, self.distance, self.force_constant)]}
def removeObject(self, object): """ Remove an object or a list or collection of objects from the collection. The object(s) to be removed must be elements of the collection. :param object: the object to be removed, or a list or collection of objects whose elements are to be removed :raises ValueError: if the object is not an element of the collection """ from MMTK.ChemicalObjects import isChemicalObject if 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 addBondAngleTerm(self, data, angle, object, global_data): a1 = angle.a1 a2 = angle.a2 ca = angle.ca i1 = a1.index i2 = a2.index ic = ca.index global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] tc = global_data.atom_type[ca] try: p = self.dataset.bondAngleParameters(t1, tc, t2) except KeyError: raise KeyError(('No parameters for angle %s (atom type %s)' + ' - %s (atom type %s) - %s (atom type %s)') % (str(a1), t1, str(ca), tc, str(a2), t2)) if p is not None and p[1] != 0.: data.add('angles', (i1, ic, i2, p[0], p[1] * self.scale_factor))
def addBondAngleTerm(self, data, angle, object, global_data): a1 = angle.a1 a2 = angle.a2 ca = angle.ca i1 = a1.index i2 = a2.index ic = ca.index global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] tc = global_data.atom_type[ca] try: p = self.dataset.bondAngleParameters(t1, tc, t2) except KeyError: raise KeyError(('No parameters for angle %s (atom type %s)' + ' - %s (atom type %s) - %s (atom type %s)') % (str(a1), t1, str(ca), tc, str(a2), t2)) if p is not None and p[1] != 0.: data.add('angles', (i1, ic, i2, p[0], p[1]*self.scale_factor))
def addDihedralTerm(self, data, dihedral, object, global_data): a1 = dihedral.a1 a2 = dihedral.a2 a3 = dihedral.a3 a4 = dihedral.a4 i1 = a1.index i2 = a2.index i3 = a3.index i4 = a4.index global_data.add('1_4_pairs', Utility.normalizePair((i1, i4))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] t3 = global_data.atom_type[a3] t4 = global_data.atom_type[a4] terms = self.dataset.dihedralParameters(t1, t2, t3, t4) if terms is not None: for p in terms: if p[2] != 0.: data.add('dihedrals', (i1, i2, i3, i4, p[0], p[1], p[2]*self.scale_factor))
def addObject(self, object): """ Add objects to the collection. :param object: the object(s) to be added. If it is another collection or a list, all of its elements are added """ from MMTK.ChemicalObjects import isChemicalObject if isChemicalObject(object): self.addChemicalObject(object) elif isCollection(object): self.addChemicalObjectList(object.objectList()) elif Utility.isSequenceObject(object): if object and isChemicalObject(object[0]): self.addChemicalObjectList(list(object)) else: for o in object: self.addObject(o) else: raise TypeError('Wrong object type in collection')
def addDihedralTerm(self, data, dihedral, object, global_data): a1 = dihedral.a1 a2 = dihedral.a2 a3 = dihedral.a3 a4 = dihedral.a4 i1 = a1.index i2 = a2.index i3 = a3.index i4 = a4.index global_data.add('1_4_pairs', Utility.normalizePair((i1, i4))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] t3 = global_data.atom_type[a3] t4 = global_data.atom_type[a4] terms = self.dataset.dihedralParameters(t1, t2, t3, t4) if terms is not None: for p in terms: if p[2] != 0.: data.add( 'dihedrals', (i1, i2, i3, i4, p[0], p[1], p[2] * self.scale_factor))
def excludedPairs(self, subset1, subset2, global_data): if 'excluded_pairs' not in global_data.get('initialized'): excluded_pairs = global_data.get('excluded_pairs') if subset1 is not None: for s1, s2 in [(subset1, subset2), (subset2, subset1)]: set = {} for a in s1.atomList(): set[a.index] = None for a in s2.atomList(): try: del set[a.index] except KeyError: pass excluded_pairs = excluded_pairs + \ Utility.pairs(set.keys()) set = {} for a in subset1.atomList(): set[a.index] = None for a in subset2.atomList(): set[a.index] = None atom_subset = set.keys() atom_subset.sort() else: atom_subset = None global_data.set('atom_subset', atom_subset) excluded_pairs = map(_normalizePair, excluded_pairs) excluded_pairs.sort(_cmpPair) _makeUnique(excluded_pairs) global_data.set('excluded_pairs', excluded_pairs) one_four_pairs = map(_normalizePair, global_data.get('1_4_pairs')) one_four_pairs.sort(_cmpPair) _makeUnique(one_four_pairs) _eliminateExcluded(one_four_pairs, excluded_pairs) global_data.set('1_4_pairs', one_four_pairs) global_data.add('initialized', 'excluded_pairs') return global_data.get('excluded_pairs'), \ global_data.get('1_4_pairs'), \ global_data.get('atom_subset')
def __init__(self, filename, database_name, module, instancevars): self.filename = filename self.database_name = database_name file_text = Utility.readURL(filename) newvars = {} six.exec_(file_text, vars(module), newvars) for name, value in newvars.items(): setattr(self, name, value) self.parent = None if not hasattr(self, 'instance'): self.instance = [] for attr in instancevars + ('parent', ): if not hasattr(self, attr): setattr(self, attr, []) if attr not in self.instance: self.instance.append(attr) attributes = vars(self).items() attributes.sort(lambda a, b: cmp(a[0], b[0])) for name, object in attributes: if hasattr(object, 'is_instance_var'): if name not in self.instance: self.instance.append(name) object.parent = self object.name = name if hasattr(object, 'object_list'): getattr(self, object.object_list).append(object)
def addBondAngleTerm(self, data, angle, object, global_data): if not self.arguments[1]: return a1 = angle.a1 a2 = angle.a2 ca = angle.ca i1 = a1.index i2 = a2.index ic = ca.index global_data.add('excluded_pairs', Utility.normalizePair((i1, i2))) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] tc = global_data.atom_type[ca] try: p = self.dataset.bondAngleParameters(t1, tc, t2) except KeyError: raise KeyError('No parameters for angle ' + `a1` + '--' + `ca` + '--' + `a2`) if p is not None: v1 = a1.position()-ca.position() v2 = a2.position()-ca.position() angle = v1.angle(v2) data.add('angles', (i1, ic, i2, angle) + p[1:])