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 __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 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 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 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 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 close(self): VRML.VRMLFile.close(self) if self.warning: Utility.warning('Some atoms are missing in the output file ' + \ 'because their positions are undefined.') self.warning = 0
def __init__(self, system, points, constraints = None): """ :param system: any chemical object (usually a molecule) :param points: a list of point/potential pairs (a vector for the evaluation point, a number for the potential), or a dictionary whose keys are Configuration objects and whose values are lists of point/potential pairs. The latter case permits combined fits for several conformations of the system. :param constraints: an optional list of constraint objects (:class:`~MMTK.ChargeFit.TotalChargeConstraint` and/or :class:`~MMTK.ChargeFit.EqualityConstraint` objects). If the constraints are inconsistent, a warning is printed and the result will satisfy the constraints only in a least-squares sense. """ self.atoms = system.atomList() if type(points) != type({}): points = {None: points} if constraints is not None: constraints = ChargeConstraintSet(self.atoms, constraints) npoints = sum([len(v) for v in points.values()]) natoms = len(self.atoms) if npoints < natoms: raise ValueError("Not enough data points for fit") m = N.zeros((npoints, natoms), N.Float) phi = N.zeros((npoints,), N.Float) i = 0 for conf, pointlist in points.items(): for r, p in pointlist: for j in range(natoms): m[i, j] = 1./(r-self.atoms[j].position(conf)).length() phi[i] = p i = i + 1 m = m*Units.electrostatic_energy m_test = m phi_test = phi if constraints is not None: phi -= N.dot(m, constraints.bi_c) m = N.dot(m, constraints.p) c_rank = constraints.rank else: c_rank = 0 u, s, vt = LA.singular_value_decomposition(m) s_test = s[:len(s)-c_rank] cutoff = 1.e-10*N.maximum.reduce(s_test) nonzero = N.repeat(s_test, N.not_equal(s_test, 0.)) self.rank = len(nonzero) self.condition = N.maximum.reduce(nonzero) / \ N.minimum.reduce(nonzero) self.effective_rank = N.add.reduce(N.greater(s, cutoff)) if self.effective_rank < self.rank: self.effective_condition = N.maximum.reduce(nonzero) / cutoff else: self.effective_condition = self.condition if self.effective_rank < natoms-c_rank: Utility.warning('Not all charges are uniquely determined' + ' by the available data') for i in range(natoms): if s[i] > cutoff: s[i] = 1./s[i] else: s[i] = 0. q = N.dot(N.transpose(vt), s*N.dot(N.transpose(u)[:natoms, :], phi)) if constraints is not None: q = constraints.bi_c + N.dot(constraints.p, q) deviation = N.dot(m_test, q)-phi_test self.rms_error = N.sqrt(N.dot(deviation, deviation)) deviation = N.fabs(deviation/phi_test) self.relative_rms_error = N.sqrt(N.dot(deviation, deviation)) self.charges = {} for i in range(natoms): self.charges[self.atoms[i]] = q[i]
def __init__(self, object, points, constraints=None): self.atoms = object.atomList() if type(points) != type({}): points = {None: points} if constraints is not None: constraints = ChargeConstraintSet(self.atoms, constraints) npoints = reduce(operator.add, map(len, points.values())) natoms = len(self.atoms) if npoints < natoms: raise ValueError("Not enough data points for fit") m = Numeric.zeros((npoints, natoms), Numeric.Float) phi = Numeric.zeros((npoints, ), Numeric.Float) i = 0 for conf, pointlist in points.items(): for r, p in pointlist: for j in range(natoms): m[i, j] = 1. / (r - self.atoms[j].position(conf)).length() phi[i] = p i = i + 1 m = m * Units.electrostatic_energy m_test = m phi_test = phi if constraints is not None: phi = phi - Numeric.dot(m, constraints.bi_c) m = Numeric.dot(m, constraints.p) c_rank = constraints.rank else: c_rank = 0 u, s, vt = LinearAlgebra.singular_value_decomposition(m) s_test = s[:len(s) - c_rank] cutoff = 1.e-10 * Numeric.maximum.reduce(s_test) nonzero = Numeric.repeat(s_test, Numeric.not_equal(s_test, 0.)) self.rank = len(nonzero) self.condition = Numeric.maximum.reduce(nonzero) / \ Numeric.minimum.reduce(nonzero) self.effective_rank = Numeric.add.reduce(Numeric.greater(s, cutoff)) if self.effective_rank < self.rank: self.effective_condition = Numeric.maximum.reduce(nonzero) / cutoff else: self.effective_condition = self.condition if self.effective_rank < natoms - c_rank: Utility.warning('Not all charges are uniquely determined' + ' by the available data') for i in range(natoms): if s[i] > cutoff: s[i] = 1. / s[i] else: s[i] = 0. q = Numeric.dot(Numeric.transpose(vt), s * Numeric.dot(Numeric.transpose(u)[:natoms, :], phi)) if constraints is not None: q = constraints.bi_c + Numeric.dot(constraints.p, q) deviation = Numeric.dot(m_test, q) - phi_test self.rms_error = Numeric.sqrt(Numeric.dot(deviation, deviation)) deviation = Numeric.fabs(deviation / phi_test) self.relative_rms_error = Numeric.sqrt( Numeric.dot(deviation, deviation)) self.charges = {} for i in range(natoms): self.charges[self.atoms[i]] = q[i]
def __init__(self, *items, **properties): """ :param items: either a sequence of peptide chain objects, or a string, which is interpreted as the name of a database definition for a protein. If that definition does not exist, the string is taken to be the name of a PDB file, from which all peptide chains are constructed and assembled into a protein. :keyword model: one of "all" (all-atom), "no_hydrogens" or "none" (no hydrogens),"polar_hydrogens" or "polar" (united-atom with only polar hydrogens), "polar_charmm" (like "polar", but defining polar hydrogens like in the CHARMM force field), "polar_opls" (like "polar", but defining polar hydrogens like in the latest OPLS force field), "calpha" (only the |C_alpha| atom of each residue). Default is "all". :type model: str :keyword position: the center-of-mass position of the protein :type position: Scientific.Geometry.Vector :keyword name: a name for the protein :type name: str """ 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] m._addSSBridges(bonds) else: numbers = sum((i._numbers for i in m[0]), []) m = ConnectedChains(m[0]) m._numbers = numbers m._addSSBridges(bonds) m._finalize() for c in m: c.parent = self 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 += 1 if undefined > 0 and undefined != len(self.atoms): Utility.warning('Some atoms in a protein ' + 'have undefined positions.')
def __init__(self, system, points, constraints=None): """ :param system: any chemical object (usually a molecule) :param points: a list of point/potential pairs (a vector for the evaluation point, a number for the potential), or a dictionary whose keys are Configuration objects and whose values are lists of point/potential pairs. The latter case permits combined fits for several conformations of the system. :param constraints: an optional list of constraint objects (:class:`~MMTK.ChargeFit.TotalChargeConstraint` and/or :class:`~MMTK.ChargeFit.EqualityConstraint` objects). If the constraints are inconsistent, a warning is printed and the result will satisfy the constraints only in a least-squares sense. """ self.atoms = system.atomList() if type(points) != type({}): points = {None: points} if constraints is not None: constraints = ChargeConstraintSet(self.atoms, constraints) npoints = sum([len(v) for v in points.values()]) natoms = len(self.atoms) if npoints < natoms: raise ValueError("Not enough data points for fit") m = N.zeros((npoints, natoms), N.Float) phi = N.zeros((npoints, ), N.Float) i = 0 for conf, pointlist in points.items(): for r, p in pointlist: for j in range(natoms): m[i, j] = 1. / (r - self.atoms[j].position(conf)).length() phi[i] = p i = i + 1 m = m * Units.electrostatic_energy m_test = m phi_test = phi if constraints is not None: phi -= N.dot(m, constraints.bi_c) m = N.dot(m, constraints.p) c_rank = constraints.rank else: c_rank = 0 u, s, vt = LA.singular_value_decomposition(m) s_test = s[:len(s) - c_rank] cutoff = 1.e-10 * N.maximum.reduce(s_test) nonzero = N.repeat(s_test, N.not_equal(s_test, 0.)) self.rank = len(nonzero) self.condition = N.maximum.reduce(nonzero) / \ N.minimum.reduce(nonzero) self.effective_rank = N.add.reduce(N.greater(s, cutoff)) if self.effective_rank < self.rank: self.effective_condition = N.maximum.reduce(nonzero) / cutoff else: self.effective_condition = self.condition if self.effective_rank < natoms - c_rank: Utility.warning('Not all charges are uniquely determined' + ' by the available data') for i in range(natoms): if s[i] > cutoff: s[i] = 1. / s[i] else: s[i] = 0. q = N.dot(N.transpose(vt), s * N.dot(N.transpose(u)[:natoms, :], phi)) if constraints is not None: q = constraints.bi_c + N.dot(constraints.p, q) deviation = N.dot(m_test, q) - phi_test self.rms_error = N.sqrt(N.dot(deviation, deviation)) deviation = N.fabs(deviation / phi_test) self.relative_rms_error = N.sqrt(N.dot(deviation, deviation)) self.charges = {} for i in range(natoms): self.charges[self.atoms[i]] = q[i]
def __init__(self, object, points, constraints = None): self.atoms = object.atomList() if type(points) != type({}): points = {None: points} if constraints is not None: constraints = ChargeConstraintSet(self.atoms, constraints) npoints = reduce(operator.add, map(len, points.values())) natoms = len(self.atoms) if npoints < natoms: raise ValueError("Not enough data points for fit") m = Numeric.zeros((npoints, natoms), Numeric.Float) phi = Numeric.zeros((npoints,), Numeric.Float) i = 0 for conf, pointlist in points.items(): for r, p in pointlist: for j in range(natoms): m[i, j] = 1./(r-self.atoms[j].position(conf)).length() phi[i] = p i = i + 1 m = m*Units.electrostatic_energy m_test = m phi_test = phi if constraints is not None: phi = phi-Numeric.dot(m, constraints.bi_c) m = Numeric.dot(m, constraints.p) c_rank = constraints.rank else: c_rank = 0 u, s, vt = LinearAlgebra.singular_value_decomposition(m) s_test = s[:len(s)-c_rank] cutoff = 1.e-10*Numeric.maximum.reduce(s_test) nonzero = Numeric.repeat(s_test, Numeric.not_equal(s_test, 0.)) self.rank = len(nonzero) self.condition = Numeric.maximum.reduce(nonzero) / \ Numeric.minimum.reduce(nonzero) self.effective_rank = Numeric.add.reduce(Numeric.greater(s, cutoff)) if self.effective_rank < self.rank: self.effective_condition = Numeric.maximum.reduce(nonzero) / cutoff else: self.effective_condition = self.condition if self.effective_rank < natoms-c_rank: Utility.warning('Not all charges are uniquely determined' + ' by the available data') for i in range(natoms): if s[i] > cutoff: s[i] = 1./s[i] else: s[i] = 0. q = Numeric.dot(Numeric.transpose(vt), s*Numeric.dot(Numeric.transpose(u)[:natoms, :], phi)) if constraints is not None: q = constraints.bi_c + Numeric.dot(constraints.p, q) deviation = Numeric.dot(m_test, q)-phi_test self.rms_error = Numeric.sqrt(Numeric.dot(deviation, deviation)) deviation = Numeric.fabs(deviation/phi_test) self.relative_rms_error = Numeric.sqrt(Numeric.dot(deviation, deviation)) self.charges = {} for i in range(natoms): self.charges[self.atoms[i]] = q[i]
# On Unix-like systems, give priority to a user-specified viewer. object.writeToFile(filename, configuration, format) if os.fork() == 0: pipe = os.popen(viewer[format][1] + ' ' + filename + \ ' 1> /dev/null 2>&1', 'w') pipe.close() os.unlink(filename) os._exit(0) elif running_on_macosx: object.writeToFile(filename, configuration, format) subprocess.call(["/usr/bin/open", filename]) elif running_on_linux: object.writeToFile(filename, configuration, format) subprocess.call(["xdg-open", filename]) else: Utility.warning('No viewer for %s defined.' % viewer_format) return def viewConfiguration(*args, **kwargs): pdbviewer, exec_path = viewer.get('pdb', (None, None)) function = {'vmd': viewConfigurationVMD, 'xmol': viewConfigurationXMol, 'imol': viewConfigurationIMol} \ .get(pdbviewer,genericViewConfiguration) function(*args, **kwargs) # # Normal mode and trajectory animation # def viewSequence(object, conf_list, periodic = False, label = None): """
# On Unix-like systems, give priority to a user-specified viewer. object.writeToFile(filename, configuration, format) if os.fork() == 0: pipe = os.popen(viewer[format][1] + ' ' + filename + \ ' 1> /dev/null 2>&1', 'w') pipe.close() os.unlink(filename) os._exit(0) elif running_on_macosx: object.writeToFile(filename, configuration, format) subprocess.call(["/usr/bin/open", filename]) elif running_on_linux: object.writeToFile(filename, configuration, format) subprocess.call(["xdg-open", filename]) else: Utility.warning('No viewer for %s defined.' % viewer_format) return def viewConfiguration(*args, **kwargs): pdbviewer, exec_path = viewer.get('pdb', (None, None)) function = {'vmd': viewConfigurationVMD, 'xmol': viewConfigurationXMol, 'imol': viewConfigurationIMol} \ .get(pdbviewer,genericViewConfiguration) function(*args, **kwargs) # # Normal mode and trajectory animation #