Exemplo n.º 1
0
def add_dummy_entry(lmpdat):
    """
    Add dummy entries to the lammps data file.

    Parameters
    ----------
    lmpdat : str
        name of the lammps data file

    """
    md_sys = aglmp.read_lmpdat(lmpdat)
    if md_sys.bnd_types != {}:
        ntypes = len(md_sys.bnd_types)
        if md_sys.bnd_types[ntypes - 1].prm1 > 0:
            md_sys.bnd_types[ntypes] = mds.Bond(
                bnd_key=ntypes,
                prm1=0.0,
                prm2=0.0,
                comment=" dummy bond for force field fitting")

    if md_sys.ang_types != {}:
        ntypes = len(md_sys.ang_types)
        if md_sys.ang_types[ntypes - 1].prm1 > 0:
            md_sys.ang_types[ntypes] = mds.Angle(
                ang_key=ntypes,
                prm1=0.0,
                prm2=0.0,
                comment=" dummy bond for force field fitting")

    if md_sys.dih_types != {}:
        ntypes = len(md_sys.dih_types)
        if md_sys.dih_types[ntypes - 1].prm_k > 0:
            md_sys.dih_types[ntypes] = mds.Dihedral(
                dih_key=ntypes,
                prm_k=0.0,
                prm_n=1,
                prm_d=0,
                weigh_factor=0,
                comment=" dummy angle for force field fitting")

    md_sys.change_indices(incr=1, mode="increase")
    md_sys.write_lmpdat(lmpdat, frame_id=-1, title="Default Title", cgcmm=True)
    return True
Exemplo n.º 2
0
def relocate_parsed(sect_bad_iwh, container, key, dict_key_old_new,
                    dict_atm_id_old_new):
    """
    Sort the parsed data from the sections:
        > bonds (inc/without hydrogen) or
        > angles (inc/without hydrogen) or
        > dihedrals (inc/without hydrogen)
    to their respective containers (bonds, angles, dihedrals; see class Universe
    for more information).
    'bad' = b(onds), a(ngles), d(ihedrals)
    sect_bad_iwh:  list; section inclusive hydrogens or section without hydrogens
    key:           "bonds", "angles", "dihedrals"
    """
    #lc = len(container)  # number of elements in container

    # bonds with hydrogens
    for ientry in sect_bad_iwh:
        # transform amber-numbered atom-ids to their original ids
        ientry_0 = true_atm_id(ientry[0])
        ientry_0 = dict_atm_id_old_new[ientry_0]

        ientry_1 = true_atm_id(ientry[1])
        ientry_1 = dict_atm_id_old_new[ientry_1]

        if len(ientry) > 3:  # angles or dihedrals
            ientry_2 = true_atm_id(ientry[2])
            ientry_2 = dict_atm_id_old_new[ientry_2]

        if len(ientry) > 4:  # dihedrals
            ientry_3 = true_atm_id(ientry[3])
            ientry_3 = dict_atm_id_old_new[ientry_3]

        if key == "bonds":
            container.append(
                mds.Bond(bnd_id=len(container),
                         atm_id1=ientry_0,
                         atm_id2=ientry_1,
                         bnd_key=dict_key_old_new[ientry[2]]))
        elif key == "angles":
            container.append(
                mds.Angle(ang_id=len(container),
                          atm_id1=ientry_0,
                          atm_id2=ientry_1,
                          atm_id3=ientry_2,
                          ang_key=dict_key_old_new[ientry[3]]))
        elif key == "dihedrals":
            # only append non-impropers, which are dihedrals
            if ientry[3] > 0:
                container.append(
                    mds.Dihedral(dih_id=len(container),
                                 atm_id1=ientry_0,
                                 atm_id2=ientry_1,
                                 atm_id3=ientry_2,
                                 atm_id4=ientry_3,
                                 dih_key=dict_key_old_new[ientry[4]]))
        elif key == "impropers":
            #print(ientry_0, ientry_1, ientry_2, ientry_3, ientry[4])
            # if third int of each subcontainer is < 0, amber assumes it is an improper
            if ientry[3] < 0:
                container.append(
                    mds.Improper(imp_id=len(container),
                                 atm_id1=ientry_0,
                                 atm_id2=ientry_1,
                                 atm_id3=ientry_2,
                                 atm_id4=ientry_3,
                                 imp_key=dict_key_old_new[ientry[4]]))
        else:
            raise RuntimeError(
                "key must be 'bonds', 'angles', 'dihedrals' or 'impropers'!")

    return container
Exemplo n.º 3
0
    def read_gau(self, gauin, overwrite=False):
        """
        """
        print("***Gau-Info: Reading  Gaussian-Input-File!")

        (chk, nproc, mem, job_type, method, basis_set, geom, charge,
         multiplicity) = [None for _ in range(9)]
        cframe = []

        with open(gauin, "r") as gau_in:
            for line in gau_in:
                if "%chk" in line:
                    if not hasattr(self, "chk"):
                        self.chk = line.split("=")[1].strip("\n")
                elif "%nproc" in line:
                    if not hasattr(self, "nproc"):
                        self.nproc = int(line.split("=")[1].strip("\n"))
                elif "%mem" in line:
                    if not hasattr(self, "mem"):
                        mem = line.split("=")[1].strip("\n")
                        self.mem = int(re.findall(r'^\d+', mem)[0])
                elif line.startswith("#"):
                    # job settings direction
                    job_settings = line.split()

                    # classify job settings
                    for setting in job_settings:
                        # remove # e.g. #SP
                        if setting.startswith("#"):
                            setting = setting.strip("#")

                        if setting in self.job_types:
                            if not hasattr(self, "job_type"):
                                self.job_type = setting
                        elif "geom" in setting:
                            if not hasattr(self, "geom"):
                                self.geom = setting.split("=")[1]
                        elif "EmpiricalDispersion" in setting:
                            if not hasattr(self, "dispersion"):
                                self.dispersion = setting.split("=")[1]
                        elif "/" in setting:
                            setting = setting.split("/")
                            if not hasattr(self, "method"):
                                self.method = setting[0]
                            if not hasattr(self, "basis_set"):
                                self.basis_set = setting[1]
                        else:
                            pass

                elif re.findall(r'^-?\d+ \d$', line):
                    line = line.split()

                    if not hasattr(self, "charge"):
                        self.charge = int(line[0])

                    if not hasattr(self, "multiplicity"):
                        self.multiplicity = int(line[1])

                    read_coords_section = True

                    while read_coords_section is True:

                        # read info
                        try:
                            line = next(gau_in)
                        except StopIteration:
                            # last line of document reached
                            break

                        # quit reading section when empty line occurs
                        if line == "\n":
                            read_coords_section = False
                            break

                        line = line.split()
                        csitnam = line[0]
                        ccoords = np.array([float(i) for i in line[1:]])

                        # store info
                        cur_atom = mds.Atom(sitnam=csitnam)
                        self.atoms.append(cur_atom)
                        cframe.append(ccoords)

                    self.ts_coords.append(cframe)

                elif hasattr(self, "geom") and self.geom == "connectivity":
                    # section with bonds-information
                    if bool(re.search(r'(^\d+ \d+ \d+.\d+)|(^\d+\n$)',
                                      line)) is True:
                        line = line.split()

                        # get rest of the bond-entries
                        read_connectivity_section = True

                        while read_connectivity_section is True:

                            # stop reading current entry if line is empty
                            if line == []:
                                break

                            # only process line if it really has bond information
                            if len(line) > 1:
                                # get atm-id 1 (always the same for current line)
                                catm_id1 = int(line[0])

                                for idx, cur_subentry in enumerate(line[1:]):

                                    # get atm-id 2
                                    if idx % 2 == 0:
                                        catm_id2 = int(cur_subentry)
                                        # decrease indices by 1 since internally
                                        # atom-indices start with 0
                                        cbnd = mds.Bond(atm_id1=catm_id1 - 1,
                                                        atm_id2=catm_id2 - 1)
                                    else:
                                        cbnd_order = float(cur_subentry)
                                        cbnd.bnd_order = cbnd_order
                                        self.bonds.append(cbnd)

                            # if there is only one empty line at file bottom
                            try:
                                line = gau_in.next().split()
                            except StopIteration:
                                break

                else:
                    pass
Exemplo n.º 4
0
    def read_gau(self,
                 gauin,
                 coordinate_style="cartesian",
                 overwrite=False,
                 debug=False):
        """
        """
        self.coordinate_style = coordinate_style

        print("***Gau-Info: Reading  Gaussian-Input-File!")
        cframe = []
        reading = True

        with open(gauin, "r") as gau_in:
            line = gau_in.readline()

            if debug is True:
                print("Parsing link 0 and route section")

            # line != "" -> just to be safe this will eventually finish when
            # loading a wrong file by accident
            while line != "":

                # // LINK 0 SECTION
                if "%oldchk" in line:
                    if not hasattr(self, "oldchk") or overwrite is True:
                        self.oldchk = line.split("=")[1].strip("\n")

                elif "%chk" in line:
                    if not hasattr(self, "chk") or overwrite is True:
                        self.chk = line.split("=")[1].strip("\n")

                elif "%nproc" in line:
                    if not hasattr(self, "nproc") or overwrite is True:
                        self.nproc = int(line.split("=")[1].strip("\n"))

                elif "%mem" in line:
                    if not hasattr(self, "mem") or overwrite is True:
                        self.mem = line.split("=")[1].strip("\n")

                # TBD
                elif "%rwf" in line:
                    if not hasattr(self, "rwf") or overwrite is True:
                        self.rwf = line.split("=")[1].strip("\n")

                #// ROUTE SECTION (may be scattered over several files)
                elif line.startswith("#"):
                    #pdb.set_trace()

                    # keep reading until empty line is reached, end loop
                    # when it is
                    while line != "\n":
                        if self.job_settings == "" or overwrite is True:
                            self.job_settings += line.rstrip("\n") + " "
                        line = gau_in.readline()

                        # eof reached
                        if line == "":
                            break

                    else:
                        break

                else:
                    pass

                line = gau_in.readline()

            #// TITLE SECTION
            if debug is True:
                print("Title section")

            # skip all empty lines until title line is reached
            while line == "\n":
                line = gau_in.readline()
            else:
                title_line = line
                line = gau_in.readline()

            #// MOLECULE SPECIFICATION SECTION
            if debug is True:
                print("Molecule specification section")

            while line == "\n":
                line = gau_in.readline()
            else:
                charge_mutliplicity_line = re.findall(r'[\w]+', line)

                if self.gaussian_charges == [] or overwrite is True:
                    self.gaussian_charges = [
                        int(i)
                        for idx, i in enumerate(charge_mutliplicity_line)
                        if idx % 2 == 0
                    ]

                if self.gaussian_multiplicities == [] or overwrite is True:
                    self.gaussian_multiplicities = [
                        int(i)
                        for idx, i in enumerate(charge_mutliplicity_line[1:])
                        if idx % 2 == 0
                    ]

                line = gau_in.readline()

            #// COORDINATES SECTION
            if debug is True:
                print("Coordinates section")

            g_atoms = []
            g_frame = []  # gaussian coordinates
            # counter to substitute given atoms or complement their attributes
            atom_index = 0

            while line != "\n":
                line = line.split()
                columns_coordinates_section_atomic = len(line)

                # element parameters section
                if "Fragment=" in line[0]:
                    fragment_id = re.search(r"Fragment=\d+", line[0]).group(0)
                    fragment_id = int(re.search(r"\d+", fragment_id).group(0))
                    csitnam = line[0].split("(")[0]
                else:
                    fragment_id = None
                    csitnam = line[0]

                # translate atomic number to its element
                if csitnam.isdigit():
                    csitnam = int(csitnam)
                    csitnam = mde.atomicnumber_element[csitnam]

                if "Iso=" in line[0]:
                    print("Iso not implemented yet")

                if "Spin=" in line[0]:
                    print("Iso not implemented yet")

                # element freeze section
                if len(line) > 4 and (line[-4] == "0" or line[-4] == "-1"):
                    cifrz = int(line[-4])
                else:
                    cifrz = None

                # store element info
                cur_atom = mds.Atom(sitnam=csitnam,
                                    atm_id=atom_index,
                                    ifrz=cifrz,
                                    grp_id=fragment_id)

                #g_atoms.append(cur_atom)

                try:
                    if overwrite is True:
                        self.atoms[atom_index] = cur_atom
                    else:
                        if not hasattr(self.atoms[atom_index], "sitnam"):
                            self.atoms[atom_index].sitnam = cur_atom.sitnam

                        # add ifrz to current atom if overwrite option is set or ifrz attribute has not been defined yet
                        if hasattr(cur_atom, "ifrz") and not hasattr(
                                self.atoms[atom_index], "ifrz"):
                            self.atoms[atom_index].ifrz = cur_atom.ifrz

                        if hasattr(cur_atom, "grp_id") and not hasattr(
                                self.atoms[atom_index], "grp_id"):
                            self.atoms[atom_index].grp_id = cur_atom.grp_id

                except IndexError:
                    # overwrite the whole entry if one index does not fit
                    self.atoms.append(cur_atom)

                # add coordinates
                if self.coordinate_style == "cartesian":
                    ccoords = np.array([float(i) for i in line[-3:]])
                    g_frame.append(ccoords)
                else:
                    print("Z-Matrix not implemented yet.")

                line = gau_in.readline()
                atom_index += 1

                if line == "":
                    break

            # overwrite or append frame (coordinates) to existing one(s)
            g_frame = np.array(g_frame)

            if self.ts_coords != [] and overwrite is True:
                self.ts_coords[-1] = g_frame
            else:
                self.ts_coords.append(g_frame)

            # skip all empty lines until title line is reached
            while line == "\n":
                line = gau_in.readline()  # first bond line

                # just to be sure this will end
                if line == "":
                    break

            # BOND SECTION
            if debug is True:
                print("Bonds Section")

            if "CONNECTIVITY" in self.job_settings.upper() and bool(
                    re.search(r'(^\d+ \d+ \d+.\d+)|(^\d+\n$)', line)) is True:
                gau_bonds = []

                while line != "\n":
                    line = line.split()

                    # only process line if it really has bond information
                    if len(line) > 1:
                        # get atm-id 1 (always the same for current line)
                        catm_id1 = int(line[0])
                        catm_id1 -= 1  # decrement atom index by 1
                        # read other further bond partners (if present)
                        catms_id2 = [
                            int(i) - 1 for idx, i in enumerate(line[1:])
                            if idx % 2 == 0
                        ]
                        # read bond orders (if present)
                        cbnd_orders = [
                            float(i) for idx, i in enumerate(line[2:])
                            if idx % 2 == 0
                        ]

                        # append bond to gaussian given bonds
                        for catm_id2, cbnd_order in zip(
                                catms_id2, cbnd_orders):
                            cbnd = mds.Bond(atm_id1=catm_id1,
                                            atm_id2=catm_id2,
                                            bnd_order=cbnd_order)
                            gau_bonds.append(cbnd)

                    # if there is only one empty line at file bottom
                    line = gau_in.readline()

                    if line == "":
                        break

                # complement attributes that do not exist or overwrite existing ones if wanted
                if len(gau_bonds) == len(self.bonds) and overwrite is False:
                    for idx, gau_bnd in enumerate(gau_bonds):
                        for universe_bnd in self.bonds:
                            if (universe_bnd.atm_id1 == gau_bnd.atm_id1 and
                                    universe_bnd.atm_id2 == gau_bnd.atm_id2):
                                # complement attribute or overwrite existing one
                                # if overwriting is active
                                if not hasattr(universe_bnd, "bnd_order"):
                                    universe_bnd.bnd_order = gau_bnd.bnd_order
                                break
                else:
                    self.bonds = gau_bonds

                # create molecules by bond information
                self.fetch_molecules_by_bonds()
Exemplo n.º 5
0
    def read_mae(self, maefile, overwrite_data=False):
        """
        Read Schroedinger Maestro's mae-files.
        """
        atm_id_old_new = {}

        with open(maefile, "r") as mae_in:
            for line in mae_in:

                # find header for atoms-section
                if "m_atom" in line:
                    cframe = []
                    num_atms = int(re.findall(r'\d+', line)[0])

                    # skip lines until coordinates section is reached
                    while ":::" not in line:
                        line = next(mae_in)

                    for iid in range(num_atms):
                        catm = mae_in.next().split()
                        atm_id_old_new[int(catm[0])] = iid
                        csitnam = catm[-1]
                        ccoords = np.array([float(i) for i in catm[2:5]])

                        # check if an instance of Atom with index iid already exists;
                        # overwrite info if it does or create a new one if it does not
                        try:
                            self.atoms[iid]

                            # overwrite data
                            if overwrite_data is True:
                                self.atoms[iid].atm_id = iid
                                self.atoms[iid].sitnam = csitnam
                            # complement data
                            else:

                                if not hasattr(self.atoms[iid], "atm_id"):
                                    self.atoms[iid].atm_id = iid

                                if not hasattr(self.atoms[iid], "sitnam"):
                                    self.atoms[iid].sitnam = csitnam

                        except IndexError:
                            catm = mds.Atom(atm_id=iid, sitnam=csitnam)
                            self.atoms.append(catm)

                        cframe.append(ccoords)
                    # append current frame
                    self.ts_coords.append(cframe)

                elif "m_bond" in line:
                    num_bnds = int(re.findall(r'\d+', line)[0])

                    # skip lines until coordinates section is reached
                    while ":::" not in line:
                        line = next(mae_in)

                    for iid in range(num_bnds):
                        cbnd = mae_in.next().split()

                        # store section
                        atm_1 = atm_id_old_new[int(cbnd[1])]
                        atm_2 = atm_id_old_new[int(cbnd[2])]
                        bnd_order = int(cbnd[3])

                        # check if an instance of Bond with index iid already exists;
                        # overwrite info if it does or create a new one if it does not
                        try:
                            self.bonds[iid]

                            # overwrite data
                            if overwrite_data is True:
                                self.bonds[iid].bnd_id = iid
                                self.bonds[iid].bnd_order = bnd_order
                            # complement data
                            else:

                                if not hasattr(self.bonds[iid], "bnd_id"):
                                    self.bonds[iid].bnd_id = iid

                                if not hasattr(self.bonds[iid], "atm_id1"):
                                    self.bonds[iid].atm_id1 = atm_1

                                if not hasattr(self.bonds[iid], "atm_id2"):
                                    self.bonds[iid].atm_id2 = atm_2

                                if not hasattr(self.bonds[iid], "bnd_order"):
                                    self.bonds[iid].bnd_order = bnd_order

                        except IndexError:
                            cbnd = mds.Bond(bnd_id=iid,
                                            atm_id1=atm_1,
                                            atm_id2=atm_2,
                                            bnd_order=bnd_order)
                            self.bonds.append(cbnd)
                else:
                    pass
Exemplo n.º 6
0
    def read_pdb(self, pdb, overwrite_data=False, debug=False):
        """
        Read a pdb file. Work in Progress!
        """
        with open(pdb, "r") as pdb_file:
            line = pdb_file.readline()
            atm_idx = 0
            bnd_idx = 0
            atm_id_old_new = {}
            all_pdb_coords = []
            tmp_bnds = []

            while line != '':
                if line.startswith("HETATM"):
                    atom_line = line.split()
                    atm_id = int(atom_line[1])
                    sitnam = atom_line[2]
                    coords = np.array([float(i) for i in atom_line[3:6]])
                    atm_id_old_new[atm_id] = atm_idx
                    cur_atm = mds.Atom(
                        atm_id=atm_idx,
                        sitnam=sitnam)
                    self.atoms.append(cur_atm)
                    all_pdb_coords.append(coords)
                    atm_idx += 1
                elif line.startswith("CONECT"):
                    bond_line = line.split()
                    # convert old indices to new ones
                    new_indices = [atm_id_old_new[int(i)] for i in bond_line[1:]]
                    for i, atom_index in enumerate(new_indices):

                        # only covalent bonds are of interest (columns 1-4)
                        if i != 0 and i < 5:
                            id_1 = new_indices[0]
                            id_2 = atom_index

                            # sort by id
                            if id_1 > id_2:
                                id_1, id_2 = atom_index, new_indices[0]

                            if [id_1, id_2] not in tmp_bnds:
                                tmp_bnds.append([id_1, id_2])
                                cbnd = mds.Bond(bnd_id=bnd_idx,
                                                atm_id1=id_1,
                                                atm_id2=id_2)
                                bnd_idx += 1
                                self.bonds.append(cbnd)
                elif line.startswith("CRYST1"):
                    a = float(line[7:16])
                    b = float(line[16:25])
                    c = float(line[25:34])
                    alpha = float(line[34:41])
                    beta = float(line[40:47])
                    gamma = float(line[48:55])
                    cbox = mdb.Box(
                        boxtype="lattice", ltc_a=a, ltc_b=b, ltc_c=c,
                        ltc_alpha=alpha, ltc_beta=beta, ltc_gamma=gamma)
                    self.ts_boxes.append(cbox)
                else:
                    pass

                line = pdb_file.readline()

            # append coordinates
            self.ts_coords.append(all_pdb_coords)

        self.fetch_molecules_by_bonds()
Exemplo n.º 7
0
    def read_prmtop(self, prmtop):
        """
        Read the contents of the amber prmtop-file. CHARMM-Entries will not be
        read!

        Input:
            >   mode        str; complement|overwrite|append;
                            complement (missing) data, overwrite given data
                            or append to given data
        """
        # /// parse file
        with open(prmtop, "r") as prmtop_in:
            prmtop_version = prmtop_in.readline()

            # parse sections
            for line in prmtop_in:

                if line.startswith("%FLAG TITLE"):
                    # section contains the title of the topology file
                    next(prmtop_in)  # line with formatting info
                    prmtop_title = next(prmtop_in)
                elif line.startswith("%FLAG POINTERS"):
                    # section which contains the information about how many
                    # parameters are present in all of the sections

                    next(prmtop_in)  # line with formatting info

                    line = next(prmtop_in).split()
                    (natom, ntypes, nbonh, mbona, ntheth, mtheta, nphih, mphia,
                     nhparm, nparm) = [int(i) for i in line]

                    line = next(prmtop_in).split()
                    (nnb, nres, nbona, ntheta, nphia, numbnd, numang, nptra,
                     natyp, nphb) = [int(i) for i in line]

                    line = next(prmtop_in).split()
                    (ifpert, nbper, ngper, ndper, mbper, mgper, mdper, ifbox,
                     nmxrs, ifcap) = [int(i) for i in line]

                    line = next(prmtop_in).split()
                    numextra = line[0]

                    try:
                        ncopy = line[1]  # entry "copy" need not to be given
                    except (IndexError):
                        pass

                elif line.startswith("%FLAG ATOM_NAME"):
                    # SECTION: ATOM_NAME
                    # section which contains the atom name for every atom in
                    # the prmtop
                    section_atom_name = agphf.parse_section(prmtop_in, natom)

                elif line.startswith("%FLAG CHARGE"):
                    # SECTION: CHARGE
                    # section which contains the charge for every atom in the prmtop
                    # prmtop-charges must be divided by 18.2223 (reasons unknown)
                    section_charge = agphf.parse_section(prmtop_in, natom)

                elif line.startswith("%FLAG ATOMIC NUMBER"):
                    pass
                elif line.startswith("%FLAG MASS"):
                    # SECTION: MASS
                    # section which  contains the atomic mass of every atom
                    # in g/mol.
                    section_mass = agphf.parse_section(prmtop_in, natom)

                elif line.startswith("%FLAG ATOM_TYPE_INDEX"):
                    # SECTION ATOM TYPE INDEX
                    # section which contains the Lennard-Jones atom type index.
                    # The Lennard-Jones potential contains parameters for every
                    # pair of atoms in the system. All atoms with the same
                    # sigma and epsilon parameters are assigned to the same type (regardless
                    # of whether they have the same AMBER ATOM TYPE).
                    section_atom_type_index = agphf.parse_section(prmtop_in,
                                                                  natom,
                                                                  itype="int")

                elif line.startswith("%FLAG NUMBER_EXCLUDED_ATOMS"):
                    # section which contains the number of atoms that need to be
                    # excluded from the non-bonded calculation loop for atom i
                    # because i is involved in a bond, angle, or torsion with those atoms
                    section_number_excluded_atoms = agphf.parse_section(
                        prmtop_in, natom, itype="int")

                elif line.startswith("%FLAG NONBONDED_PARM_INDEX"):
                    # section which contains the pointers for each pair of LJ
                    # atom types into the LENNARD JONES ACOEF and
                    # LENNARD JONES BCOEF arrays
                    section_nonbonded_parm_index = agphf.parse_section(
                        prmtop_in, ntypes * ntypes, itype="int")

                elif line.startswith("%FLAG RESIDUE_LABEL"):
                    # section which contains the residue name for every residue
                    # in the prmtop
                    section_residue_label = agphf.parse_section(
                        prmtop_in, nres)
                elif line.startswith("%FLAG RESIDUE_POINTER"):
                    section_residue_pointer = agphf.parse_section(prmtop_in,
                                                                  nres,
                                                                  itype="int")
                elif line.startswith("%FLAG BOND_FORCE_CONSTANT"):
                    # section which lists all of the bond force constants
                    # k in kcal/(mol*Angstrom**2) for each unique bond type
                    section_bond_force_constant = agphf.parse_section(
                        prmtop_in, numbnd)
                elif line.startswith("%FLAG BOND_EQUIL_VALUE"):
                    # section which lists all of the bond equilibrium distances
                    # in "Angstrom" for each unique bond type
                    section_bond_equil_value = agphf.parse_section(
                        prmtop_in, numbnd)
                elif line.startswith("%FLAG ANGLE_FORCE_CONSTANT"):
                    # section which contains all of the angle equilibrium angles
                    # in "radians"
                    section_angle_force_constant = agphf.parse_section(
                        prmtop_in, numang)
                elif line.startswith("%FLAG ANGLE_EQUIL_VALUE"):
                    # section which contains all of the angle equilibrium angles
                    # in "radians"
                    section_angle_equil_value = agphf.parse_section(
                        prmtop_in, numang)
                elif line.startswith("%FLAG DIHEDRAL_FORCE_CONSTANT"):
                    # section which lists the torsion force constants in kcal/mol
                    # for each unique torsion type
                    section_dihedral_force_constant = agphf.parse_section(
                        prmtop_in, nptra)
                elif line.startswith("%FLAG DIHEDRAL_PERIODICITY"):
                    # section which lists the periodicity n for each unique
                    # torsion type; only int
                    section_dihedral_periodicity = agphf.parse_section(
                        prmtop_in, nptra)
                elif line.startswith("%FLAG DIHEDRAL_PHASE"):
                    # section which lists the phase shift for each unique
                    # torsion type in "radians"
                    section_dihedral_phase = agphf.parse_section(
                        prmtop_in, nptra)
                elif line.startswith("%FLAG SCEE_SCALE_FACTOR"):
                    # section which lists the factor by which 1-4 electrostatic
                    # interactions are divided (i.e., the two atoms on either
                    # end of a torsion)
                    section_scee_scale_factor = agphf.parse_section(
                        prmtop_in, nptra)
                elif line.startswith("%FLAG SCNB_SCALE_FACTOR"):
                    # section which lists the factor by which 1-4 van der Waals
                    # interactions are divided (i.e., the two atoms on either
                    # end of a torsion)
                    section_scnb_scale_factor = agphf.parse_section(
                        prmtop_in, nptra)
                elif line.startswith("%FLAG SOLTY"):
                    # section which is unused
                    section_solty = agphf.parse_section(prmtop_in, natyp)
                elif line.startswith("%FLAG LENNARD_JONES_ACOEF"):
                    # section contains the LJ A-coefficients for all pairs of
                    # distinct LJ types
                    section_lennard_jones_acoef = agphf.parse_section(
                        prmtop_in,
                        ntypes * (ntypes + 1) / 2)
                elif line.startswith("%FLAG LENNARD_JONES_BCOEF"):
                    # section contains the LJ A-coefficients for all pairs of
                    # distinct LJ types
                    section_lennard_jones_bcoef = agphf.parse_section(
                        prmtop_in,
                        ntypes * (ntypes + 1) / 2)
                elif line.startswith("%FLAG BONDS_INC_HYDROGEN"):
                    # section which contains a list of every bond in the system
                    # in which at least one atom is Hydrogen
                    section_bonds_inc_hydrogen = agphf.parse_section(
                        prmtop_in, 3 * nbonh, chunksize=3, itype="int")
                elif line.startswith("%FLAG BONDS_WITHOUT_HYDROGEN"):
                    # section contains a list of every bond in the system in
                    # which neither atom is a Hydrogen
                    section_bonds_without_hydrogen = agphf.parse_section(
                        prmtop_in, 3 * nbona, chunksize=3, itype="int")
                elif line.startswith("%FLAG ANGLES_INC_HYDROGEN"):
                    # section contains a list of every angle in the system in
                    # which at least one atom is Hydrogen
                    section_angles_inc_hydrogen = agphf.parse_section(
                        prmtop_in, 4 * ntheth, chunksize=4, itype="int")
                elif line.startswith("%FLAG ANGLES_WITHOUT_HYDROGEN"):
                    # section which contains a list of every angle in the system
                    # in which no atom is Hydrogen
                    section_angles_without_hydrogen = agphf.parse_section(
                        prmtop_in, 4 * ntheta, chunksize=4, itype="int")
                elif line.startswith("%FLAG DIHEDRALS_INC_HYDROGEN"):
                    # section contains a list of every torsion in the system in
                    # which at least one atom is Hydrogen
                    section_dihedrals_inc_hydrogen = agphf.parse_section(
                        prmtop_in, 5 * nphih, chunksize=5, itype="int")
                elif line.startswith("%FLAG DIHEDRALS_WITHOUT_HYDROGEN"):
                    section_dihedrals_without_hydrogen = agphf.parse_section(
                        prmtop_in, 5 * nphia, chunksize=5, itype="int")
                elif line.startswith("%FLAG AMBER_ATOM_TYPE"):
                    section_amber_atom_type = agphf.parse_section(
                        prmtop_in, natom)
                elif line.startswith("%FLAG TREE_CHAIN_CLASSIFICATION"):
                    agphf.entry_not_read("TREE_CHAIN_CLASSIFICATION")
                elif line.startswith("%FLAG JOIN_ARRAY"):
                    agphf.entry_not_read("JOIN_ARRAY")
                elif line.startswith("%FLAG IROTAT"):
                    agphf.entry_not_read("IROTAT")
                elif line.startswith("%FLAG RADIUS_SET"):
                    agphf.entry_not_read("RADIUS_SET")
                elif line.startswith("%FLAG RADII"):
                    section_radii = agphf.parse_section(prmtop_in, natom)
                elif line.startswith("%FLAG SCREEN"):
                    agphf.entry_not_read("SCREEN")
                else:
                    pass

        # /// arrange data - force field section ///
        # /// atom-types
        #     (atoms with same epsilon and sigma (lj) have same type)

        # 1. get acoef/bcoef-ids for ii-interactions
        abcoef_ids = agphf.get_AB_ids(ntypes, section_nonbonded_parm_index)

        # 2. calculate sigma from coefs
        # dict to translate between internal and amber indices
        atm_key_old_new = {}

        for cidx, cid in enumerate(abcoef_ids):
            #cidx += 1
            cur_sig, cur_eps = agphf.sig_eps_from_AB(
                section_lennard_jones_acoef[cid],
                section_lennard_jones_bcoef[cid])

            # skip duplicates
            try:
                if self.atm_types[cidx]:
                    print("***Prmtop-Info: Skipping atom type {}".format(cid))
            except KeyError:
                self.atm_types[cidx] = mds.Atom(sigma=cur_sig,
                                                epsilon=cur_eps,
                                                energy_unit="kcal/mol")

            # add old key as key and new key as value
            atm_key_old_new[cidx + 1] = cidx

        # ityp:      atom type as number (= atom key)
        # imass:     mass of atom type
        # itypamb:   amber force field name of atom type
        # atypemass: dictionary with atom type masses and amber names assigned
        #            to atom-keys

        # type-id (key), mass, type-name
        atypemass = {}
        for ityp, imass, itypamb in zip(section_atom_type_index, section_mass,
                                        section_amber_atom_type):
            # iterate through names- and mass-list, overwrite duplicates
            # -> only single atom-types remain
            atypemass[ityp] = [imass, itypamb]

        for akey in atypemass:
            akey_new = atm_key_old_new[akey]  # translate old key
            self.atm_types[akey_new].weigh = atypemass[akey][0]
            self.atm_types[akey_new].sitnam = atypemass[akey][1]

        # /// bond-types
        bnd_key_old_new = {}
        for cbnd_id, (bnd_fconst, bnd_r0) in enumerate(
                zip(section_bond_force_constant, section_bond_equil_value)):
            self.bnd_types[cbnd_id] = mds.Bond(prm1=bnd_fconst,
                                               prm2=bnd_r0,
                                               energy_unit="kcal/mol")
            bnd_key_old_new[cbnd_id + 1] = cbnd_id

        # /// angle-types
        ang_key_old_new = {}
        for cang_id, (ang_fconst, ang_r0) in enumerate(
                zip(section_angle_force_constant, section_angle_equil_value)):
            self.ang_types[cang_id] = mds.Angle(prm1=ang_fconst,
                                                prm2=ang_r0,
                                                energy_unit="kcal/mol",
                                                angle_unit="rad")
            ang_key_old_new[cang_id + 1] = cang_id

        # /// dihedral- and improper-types
        #     assign dihedrals and impropers to "dih" and "imp"
        dih_imp_dict = agphf.unmask_imp(section_dihedrals_inc_hydrogen,
                                        section_dihedrals_without_hydrogen)

        # dicts where we can look up, which old dihedral-/improper-key points to the new key
        dih_old_new = {}
        imp_old_new = {}

        dih_cntr = 0  # dihedral key-counter, for consecutive numbering
        imp_cntr = 0  # improper key-counter, for consecutive numbering

        dih_key_old_new = {}
        #imp_key_old_new = {}
        for cdih_id, (dih_fconst, dih_prd, dih_phase) in enumerate(
                zip(section_dihedral_force_constant,
                    section_dihedral_periodicity, section_dihedral_phase)):
            cur_key = cdih_id + 1
            dih_prd = int(dih_prd)

            if dih_imp_dict[cur_key] == "dih":
                self.dih_types[dih_cntr] = mds.Dihedral(prm_k=dih_fconst,
                                                        prm_n=dih_prd,
                                                        prm_d=dih_phase,
                                                        energy_unit="kcal/mol",
                                                        angle_unit="rad")
                # pointer new-key -> old-key
                dih_old_new[cur_key] = dih_cntr
                dih_key_old_new[dih_cntr + 1] = dih_cntr
                dih_cntr += 1  # right enumeration for dih-key (starting at 1)

            elif dih_imp_dict[cur_key] == "imp":
                self.imp_types[imp_cntr] = mds.Improper(prm_k=dih_fconst,
                                                        prm_n=dih_prd,
                                                        prm_d=dih_phase,
                                                        energy_unit="kcal/mol",
                                                        angle_unit="rad")
                # check if prm_k and prm_n fulfill cvff convention (see lammps)
                agphf.check_cvff_compatibility(dih_phase, dih_prd)
                # pointer new-key -> old-key
                imp_old_new[cur_key] = imp_cntr
                #imp_key_old_new[imp_cntr+1] = imp_cntr
                imp_cntr += 1  # right enumeration for imp-key (starting at 1)
            else:
                raise RuntimeError(
                    "***Undefined dihedral! Something went totally wrong!")

        # /// arrange data - topology section ///
        # /// atoms
        atm_id_old_new = {}
        for iatmkey, (itype, ichge, isitnam) in enumerate(
                zip(section_atom_type_index, section_charge,
                    section_atom_name)):
            # since amber is/was based on fortran, increment atom-ids by 1
            self.atoms.append(
                mds.Atom(atm_id=iatmkey,
                         atm_key=atm_key_old_new[itype],
                         chge=ichge,
                         sitnam=isitnam,
                         grp_id=0))

            # save into the corresponding dictionary to translate amber-ids to internal ids
            #self.atm_idx_id[iatmkey] = iatmkey+1
            #self.atm_id_idx[iatmkey+1] = iatmkey
            atm_id_old_new[iatmkey + 1] = iatmkey

        # gather residue information
        for cur_atm_nr in range(nres):
            cur_res = section_residue_label[cur_atm_nr]  # residue name

            if cur_atm_nr == 0:  # first
                pptr = 0
            else:
                pptr = section_residue_pointer[
                    cur_atm_nr]  # present atom-pointer

            try:
                # atom-pointer after present atom-pointer
                iptr = section_residue_pointer[cur_atm_nr + 1]
            except (IndexError):
                iptr = None  # None, if no pointer after present pointer

            for iatm in self.atoms[pptr:iptr]:
                iatm.res = cur_res

        # /// bonds
        self.bonds = agphf.relocate_parsed(section_bonds_inc_hydrogen,
                                           self.bonds, "bonds",
                                           bnd_key_old_new, atm_id_old_new)

        self.bonds = agphf.relocate_parsed(section_bonds_without_hydrogen,
                                           self.bonds, "bonds",
                                           bnd_key_old_new, atm_id_old_new)

        # /// angles
        self.angles = agphf.relocate_parsed(section_angles_inc_hydrogen,
                                            self.angles, "angles",
                                            ang_key_old_new, atm_id_old_new)

        self.angles = agphf.relocate_parsed(section_angles_without_hydrogen,
                                            self.angles, "angles",
                                            ang_key_old_new, atm_id_old_new)

        # /// dihedrals
        self.dihedrals = agphf.relocate_parsed(section_dihedrals_inc_hydrogen,
                                               self.dihedrals, "dihedrals",
                                               dih_old_new, atm_id_old_new)

        self.dihedrals = agphf.relocate_parsed(
            section_dihedrals_without_hydrogen, self.dihedrals, "dihedrals",
            dih_old_new, atm_id_old_new)

        # /// impropers
        self.impropers = agphf.relocate_parsed(section_dihedrals_inc_hydrogen,
                                               self.impropers, "impropers",
                                               imp_old_new, atm_id_old_new)

        self.impropers = agphf.relocate_parsed(
            section_dihedrals_without_hydrogen, self.impropers, "impropers",
            imp_old_new, atm_id_old_new)

        # delete variables not needed (at the moment)
        del prmtop_version
        del prmtop_title
        del numextra

        # if no ncopy is specified
        try:
            del ncopy
        except UnboundLocalError:
            pass

        # delete unneeded variables (at least at the moment there is no need)
        try:
            del section_number_excluded_atoms
            del section_scee_scale_factor
            del section_scnb_scale_factor
            del section_solty
            del section_radii
        except UnboundLocalError:
            pass

        # convert amber charges to normal ones
        print("***Prmtop-Info: Converting prmtop-charges.")
        self._convert_prmtop_charges()

        # convert impropers to match cvff (i.e. cos of prm_d)
        print("***Prmtop-Info: Converting impropers to cvff-style.")
        self._amb_imp2cvff()

        # form molecules by given bonds
        self.fetch_molecules_by_bonds()