Exemplo n.º 1
0
    def write(self, atomdict):
        """
        Write an atom to the file.

        Args:
          atom (dict): a dictionary describing the atom.
        """
        from BigDFT.Atoms import Atom
        at = Atom(atomdict)
        self._handle.write(at.sym + " ")
        pos = at.get_position(self.units)
        self._handle.write(" ".join([str(x) for x in pos]))
        self._handle.write("\n")
Exemplo n.º 2
0
 def __init__(self, filename):
     from BigDFT.Atoms import Atom
     self.atoms = []
     symbol_lookup = []
     with open(filename, "r") as ifile:
         # Read the first line
         matinfo = next(ifile).split()
         self.matdim, natoms, ntypes = [int(x) for x in matinfo[:3]]
         # Units
         next(ifile)
         # skip geocode
         line = next(ifile)
         # skip shift?
         line = next(ifile)
         # get the symbol lookup information
         for i in range(0, ntypes):
             line = next(ifile).split()
             symbol_lookup.append(line[2])
         # Get the atom positions
         for i in range(0, natoms):
             line = next(ifile).split()
             adict = {}
             adict["sym"] = symbol_lookup[int(line[0]) - 1]
             adict["r"] = [float(x) for x in line[1:4]]
             # THIS IS BECAUSE THE METADATA FILE CURRENTLY PRINTS THE
             # WRONG UNITS!
             adict["units"] = "bohr"
             adict["indices"] = []
             self.atoms.append(Atom(adict))
         # Get the indices
         for i in range(0, self.matdim):
             line = next(ifile).split()
             self.atoms[int(line[0]) - 1]["indices"].append(i)
Exemplo n.º 3
0
    def update_positions_from_dict(self, posinp):
        """
        Update the atomic positions of a system from a posinp dictionary.

        This method only works if the order of atoms match.

        Args:
            posinp (dict): a posinp dictionary.
        """
        from BigDFT.Atoms import Atom
        units = posinp.get("units", "angstroem")
        i = 0
        for frag in self.values():
            for at in frag:
                at2 = Atom(posinp["positions"][i], units=units)
                at.set_position(at2.get_position())
                i += 1
def compute_system_forces(sys, forcefield="MMFF94", verbose=False):
    """
    Assign the forces of a system using an openbabel forcefield.

    Args:
      sys (BigDFT.Systems.System): the system to compute.
      forcefield (str): the type of forcefield to use.
      verbose (bool): whether to have openbabel run in verbose mode.

    Returns:
      (float): the energy of the system.
    """
    from openbabel.openbabel import OBForceField, OBFF_LOGLVL_LOW
    from BigDFT.Atoms import Atom, number_to_symbol, AU_to_A

    # Handle verbository.
    if verbose:
        ff.SetLogToStdOut()
        ff.SetLogLevel(OBFF_LOGLVL_LOW)

    # Setup the forcefield
    ff = OBForceField.FindForceField(forcefield)
    mol = convert_system_to_babel(sys)
    ff.Setup(mol)

    # Compute the forces.
    energy_out = ff.Energy() * _energy_conversion[ff.GetUnit()]
    gradients = []
    for idx in range(1, mol.NumAtoms() + 1):
        at = mol.GetAtom(idx)
        grad = ff.GetGradient(at)
        convgrad = [grad.GetX(), grad.GetY(), grad.GetZ()]
        convgrad = [
            x * _energy_conversion[ff.GetUnit()] / AU_to_A for x in convgrad
        ]
        gradients.append(convgrad)

    # Create the atom list for the compute matching procedure.
    atom_list = []
    for idx in range(1, mol.NumAtoms() + 1):
        obat = mol.GetAtom(idx)
        atnum = obat.GetAtomicNum()
        pos = [obat.GetX(), obat.GetY(), obat.GetZ()]
        atom_list.append(
            Atom({
                number_to_symbol(atnum): pos,
                "units": "angstroem"
            }))
    lookup = sys.compute_matching(atom_list)

    # Assign
    for fragid, frag in sys.items():
        for i, at in enumerate(frag):
            idx = lookup[fragid][i]
            at.set_force(gradients[idx])

    return energy_out
Exemplo n.º 5
0
 def __next__(self):
     from BigDFT.Atoms import Atom
     line = next(self._handle)
     if self.natoms == len(self.atoms_positions):
         raise StopIteration
     split = line.split()
     sym = split[0]
     position = [float(x) for x in split[1:4]]
     this_pos = Atom({'sym': sym, 'r': position, "units": self.units})
     self.atoms_positions.append(this_pos)
     return this_pos
Exemplo n.º 6
0
    def __init__(self,
                 atomlist=None,
                 xyzfile=None,
                 posinp=None,
                 astruct=None,
                 system=None):
        from BigDFT.Atoms import Atom
        self.atoms = []

        if system is not None:
            self._system_to_fragment(system)
            return

        # insert atoms.
        if atomlist:
            for atom in atomlist:
                self.append(Atom(atom))
        elif xyzfile:
            with xyzfile:
                for line in xyzfile:
                    self.append(Atom(line))
        elif posinp:
            units = posinp.get('units', 'angstroem')
            for atom in posinp['positions']:
                self.append(Atom(atom, units=units))
        elif astruct:
            units = astruct.get('units', 'angstroem')
            rshift = astruct.get('Rigid Shift Applied (AU)', [0.0, 0.0, 0.0])
            for atom in astruct["positions"]:
                self.append(Atom(atom, units=units))
            self.translate([-1.0 * x for x in rshift])

        # Values
        self.q1 = None
        self.q2 = None
        self.frozen = None
        self.conmat = None
Exemplo n.º 7
0
    def compute_matching(self, atlist, shift=None, check_matching=True):
        """
        Frequently we are passed a list of atom like objects from which we
        need to extract data and assign it to a system. However, a system
        can potentially store those atoms in any order, and may not have
        the same set of atoms. This helper routine creates a mapping between
        this list view, to the dictionary view of the system class.

        Args:
          atlist (list): a list of atom like objects.
          shift (list): if the positions in atlist are shifted by some constant
            vector you can specify that here.
          check_matching (bool): if set to True, this will raise an error
            if we can't match all of the atoms in the system.

        Returns:
          (dict): a mapping from a system to indices in the atom list. If
            an atom is not in the list, an index value of -1 is assigned.
        """
        from BigDFT.Atoms import Atom
        from numpy import array
        from scipy.spatial import KDTree

        # Convert everything to pure positions to avoid overhead.
        poslist = [
            array(Atom(x).get_position("bohr", cell=self.cell)) for x in atlist
        ]
        if shift is not None:
            poslist = [x - array(shift) for x in poslist]
        tree = KDTree(poslist)

        # Seach for the mapping values
        mapping = {}
        for fragid, frag in self.items():
            mapping[fragid] = []
            for at in frag:
                atpos = array(at.get_position("bohr", cell=self.cell))
                ndist, nearest = tree.query(atpos)
                if check_matching and ndist > 0.01:
                    raise ValueError("Unable to match atom" + str(dict(at)))
                mapping[fragid].append(nearest)

        return mapping
Exemplo n.º 8
0
def system_from_dict_positions(posinp, units='angstroem'):
    """
    Build a system from a set of positions from a dictionary whose yaml
    serialisation is compliant with the BigDFT yaml position format

    Args:
       posinp (list): list of the atomic specifications
    Returns:
       BigDFT.Systems.System: an instance of the system class.
          The employed fragment specification is specified in the file.
    """
    from BigDFT.Atoms import Atom
    from BigDFT.Fragments import Fragment
    sys = System()
    for iat, at in enumerate(posinp):
        frag = GetFragId(at, iat)
        if frag not in sys:
            sys[frag] = Fragment()
        sys[frag].append(Atom(at, units=units))
    return sys
Exemplo n.º 9
0
def _process_atom(line, include_chain=False):
    """
    This processes a line of a pdb file and extracts information about an atom.

    Returns:
      (BigDFT.Atoms.Atom, int, str): return the Atom on this line, its id in
      the pdb, and the fragment it belongs to. It may include the chain id.
    """
    from BigDFT.Atoms import Atom
    # Get the basic information about this atom
    sym = line[76:78].strip().capitalize()

    if "1-" in sym:
        sym = sym.replace("1-", "")
    if "1+" in sym:
        sym = sym.replace("1+", "")

    fullname = line[12:16]

    name = fullname.strip()

    xpos = float(line[30:38])
    ypos = float(line[38:46])
    zpos = float(line[46:54])

    at = Atom({"sym": sym, "r": [xpos, ypos, zpos], "name": name,
               "units": "angstroem"})

    # Get the atom id for building the lookup table
    atid = int(line[6:11])

    # Information about the residue
    resname = line[17:20]
    chain = line[20:22].strip()
    resid = str(int(line[22:26]))
    fragid = resname+":"+resid
    if include_chain:
        fragid = chain+'-'+fragid

    return at, atid, fragid
Exemplo n.º 10
0
 def __setitem__(self, index, value):
     from BigDFT.Atoms import Atom
     self.atoms.__setitem__(index, Atom(value))
Exemplo n.º 11
0
 def insert(self, index, value):
     from BigDFT.Atoms import Atom
     self.atoms.insert(index, Atom(value))
Exemplo n.º 12
0
def read_mol2(ifile, disable_warnings=False):
    """
    Read a system from a mol2 file.

    Args:
      ifile (TextIOBase): the file to read from.
      disable_warnings (bool): whether to print warnings about possible file
        issues.

    Returns:
      (BigDFT.Systems.System): the system file.
    """
    from BigDFT.Systems import System
    from BigDFT.Fragments import Fragment
    from BigDFT.Atoms import Atom
    from BigDFT.UnitCells import UnitCell
    from warnings import warn

    sys = System()

    # Just go ahead and read the whole file into a string.
    lines = [x for x in ifile]

    # First pass, read in the number of atoms.
    for start, line in enumerate(lines):
        if ("@<TRIPOS>MOLECULE" in line):
            break
    start += 1

    split = lines[start+1].split()
    natoms = int(split[0])
    nbonds = int(split[1])

    # Second pass read in the atoms.
    for start, line in enumerate(lines):
        if ("@<TRIPOS>ATOM" in line):
            break
    start += 1

    lookup = []
    for i in range(0, natoms):
        split = lines[start + i].split()
        pos = [float(x) for x in split[2:5]]
        name = split[5]
        sym = name.split(".")[0]
        fragid = split[7] + ":" + split[6]
        charge = [float(split[8])]

        # Add fragment
        if fragid not in sys:
            sys[fragid] = Fragment()
        at = Atom({sym: pos, "units": "angstroem", "q0":
                   charge, "name": name})
        sys[fragid] += [at]

        # Lookup table for connectivity
        lookup.append((fragid, len(sys[fragid]) - 1))

    # Third pass reads the connectivity.
    for start, line in enumerate(lines):
        if ("@<TRIPOS>BOND" in line):
            break
    start += 1

    if start < len(lines):
        sys.conmat = {}
        for fragid, frag in sys.items():
            sys.conmat[fragid] = []
            for i in range(0, len(frag)):
                sys.conmat[fragid].append({})

    bowarn = False
    for i in range(0, nbonds):
        split = lines[start + i].split()
        frag1, at1 = lookup[int(split[1])-1]
        frag2, at2 = lookup[int(split[2])-1]
        bo = split[3]
        try:
            bo = float(split[3])
        except ValueError:
            bowarn = True
            bo = 1
        sys.conmat[frag1][at1][(frag2, at2)] = bo

        # Since mol2 doesn't include the symmetric bonds.
        if frag1 != frag2 or at1 != at2:
            sys.conmat[frag2][at2][(frag1, at1)] = bo

    # Fourth path reads the unit cell.
    for start, line in enumerate(lines):
        if ("@<TRIPOS>CRYSIN" in line):
            break
    start += 1

    if start < len(lines):
        split = lines[start].split()
        a = float(split[0])
        b = float(split[1])
        c = float(split[2])
        alpha = float(split[3])
        beta = float(split[4])
        gamma = float(split[5])

        sys.cell = UnitCell([a, b, c], units="angstroem")

        if not disable_warnings:
            if (alpha != 90 or beta != 90 or gamma != 90):
                warn("Cell angles must be 90 degrees", UserWarning)

    if not disable_warnings:
        if sum([len(x) for x in sys.values()]) == 0:
            warn("Warning: zero atoms found", UserWarning)
        if bowarn:
            warn("Unsupported bond type had to be set to 1 (i.e. aromatic)",
                 UserWarning)

    return sys
def read_polaris_pdb(pdbfile, chain_as_letter=False, slefile=None):
    """
    Read coordinates in the PDB format of POLARIS

    Args:
       pdbfile (str): path of the input file
       chain_as_letter (bool): If True, the fifth column
           is assumed to contain a letter
       slefile (str): path of the file ``.sle`` of Polaris from which
           to extract the system's attributes.

    Warning:
       Assumes Free Boundary conditions for the molecule.
       Only accepts atoms that have one letter in the symbol.
       Switch representation if there is a single letter in the fifth column

    Returns:
       System: A system class
    """
    from BigDFT.Fragments import Fragment
    from BigDFT.Systems import System, GetFragId
    from BigDFT.Atoms import Atom
    sys = System()
    units = 'angstroem'
    with open(pdbfile) as ifile:
        for line in ifile:
            if 'ATOM' not in line:
                continue
            atomline = line.split()
            if chain_as_letter:
                iat, name, frag, lett, ifrag, x, y, z, sn = atomline[1:10]
                chain = lett
                segname = sn
            else:
                iat, name, frag, ifrag, x, y, z, chlett = atomline[1:9]
                chain = chlett[2]
                segname = chlett
            atdict = {
                str(name[:1]): map(float, [x, y, z]),
                'frag': [chain + '-' + frag, int(ifrag)],
                'name': name,
                'iat': int(iat),
                'segname': segname
            }
            fragid = GetFragId(atdict, iat)
            if fragid not in sys:
                sys[fragid] = Fragment()
            sys[fragid].append(Atom(atdict, units=units))
    if slefile is None:
        return sys
    attributes = read_polaris_sle(slefile)
    from BigDFT import Systems as S, Fragments as F, Atoms as A
    system = S.System()
    for name, frag in sys.items():
        refrag = F.Fragment()
        for at in frag:
            atdict = at.dict()
            att = attributes[atdict['iat'] - 1]
            assert att['name'] == atdict['name']
            atdict.update(att)
            refrag.append(A.Atom(atdict))
        system[name] = refrag
    return system