Ejemplo n.º 1
0
def addSolvent(universe, solvent, density, scale_factor=4.):
    """
    Scales up the universe and adds as many solvent molecules
    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.

    :param universe: a finite universe
    :type universe: :class:~MMTK.Universe.Universe
    :param solvent: a molecule, or the name of a molecule in the database
    :type solvent: :class:~MMTK.ChemicalObjects.Molecule or str
    :param density: the density of the solvent (amu/nm**3)
    :type density: float
    :param scale_factor: the factor by which the initial universe is
                         expanded before adding the solvent molecules
    :type scale_factor: float
    """

    # Calculate number of solvent molecules and universe size
    if isinstance(solvent, basestring):
        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 True:
            s = m.boundingSphere()
            collision = False
            for region in excluded_regions:
                if (s.center -
                        region.center).length() < s.radius + region.radius:
                    collision = True
                    break
            if not collision:
                break
            m.translateTo(universe.randomPoint())
        universe.addObject(m)
        excluded_regions.append(s)
Ejemplo n.º 2
0
 def createMolecule(self, name=None):
     """
     :returns: a :class:~MMTK.ChemicalObjects.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).
     :rtype: :class:~MMTK.ChemicalObjects.Molecule
     """
     if name is None:
         name = molecule_names[self.name]
     m = ChemicalObjects.Molecule(name)
     setConfiguration(m, [self])
     return m
Ejemplo n.º 3
0
 def makeChemicalObjects(self, template, top_level):
     self.groups[template.name].locked = True
     if top_level:
         if template.attributes.has_key('sequence'):
             object = ChemicalObjects.ChainMolecule(None)
         else:
             object = ChemicalObjects.Molecule(None)
     else:
         object = ChemicalObjects.Group(None)
     object.atoms = []
     object.bonds = Bonds.BondList([])
     object.groups = []
     object.type = self.groups[template.name]
     object.parent = None
     child_objects = []
     for child in template.children:
         if isinstance(child, GroupTemplate):
             group = self.makeChemicalObjects(child, False)
             object.groups.append(group)
             object.atoms.extend(group.atoms)
             object.bonds.extend(group.bonds)
             group.parent = object
             child_objects.append(group)
         else:
             atom = ChemicalObjects.Atom(child.element)
             object.atoms.append(atom)
             atom.parent = object
             child_objects.append(atom)
     for name, index in template.names.items():
         setattr(object, name, child_objects[index])
         child_objects[index].name = name
     for name, value in template.attributes.items():
         path = name.split('.')
         setattr(self.namePath(object, path[:-1]), path[-1], value)
     for atom1, atom2 in template.bonds:
         atom1 = self.namePath(object, atom1)
         atom2 = self.namePath(object, atom2)
         object.bonds.append(Bonds.Bond((atom1, atom2)))
     for name, vector in template.positions.items():
         path = name.split('.')
         self.namePath(object, path).setPosition(vector)
     return object
Ejemplo n.º 4
0
def numberOfSolventMolecules(universe, solvent, density):
    """
    :param universe: a finite universe
    :type universe: :class:`~MMTK.Universe.Universe`
    :param solvent: a molecule, or the name of a molecule in the database
    :type solvent: :class:`~MMTK.ChemicalObjects.Molecule` or str
    :param density: the density of the solvent (amu/nm**3)
    :type density: float
    :returns: the number of solvent molecules that must be added to the
              universe, in addition to whatever it already contains,
              to obtain the given solvent density.
    :rtype: int
    """
    if isinstance(solvent, basestring):
	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()))
Ejemplo n.º 5
0
 def createMolecules(self, names = None, permit_undefined=True):
     """
     :param names: If 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 a dictionary, it is used to map
                   PDB residue names to molecule names. With the
                   default (None), only water molecules are
                   built.
     :type names: list
     :param permit_undefined: If False, an exception is raised
                              when a PDB residue is encountered for
                              which no molecule name is supplied
                              in names. If True, an AtomCluster
                              object is constructed for each unknown
                              molecule.
     :returns: a collection of :class:~MMTK.ChemicalObjects.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.
     :rtype: :class:~MMTK.Collections.Collection
     """
     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'].strip()
                             a = ChemicalObjects.Atom(element, name = aname)
                         except KeyError:
                             try:
                                 a = ChemicalObjects.Atom(aname[:2].strip(),
                                                          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 += 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)]
                     setConfiguration(m, [molecule])
                 collection.addObject(m)
     return collection