def fromGroFile(self, a_destinationFilePath, a_grofileName):
        '''
        Tolopogy.fromGroFile takes the a_destinationFilePath, a_topolfileName,
        and a_atomtypesH.
        a) a_grofileName is the name of the grofile for the given system
        b) a_destinationFilePath is where the file a_topolfileName is located
        The return of this function are the lines_in_grofile and number_molecs
        present inf the grofile.
        '''
        # -------------------------------------
        # Verifying the input format is correct
        # -------------------------------------
        FileUtil.CheckFuncInput(a_destinationFilePath, str, 'Topology.fromGroFile')
        FileUtil.CheckFuncInput(a_grofileName, str, 'Topology.fromGroFile')

        # -------------------------------------
        # Reading the GRO file
        # -------------------------------------
        groFileOb = FileUtil.FileReader(a_destinationFilePath, a_grofileName)
        grofile = groFileOb.file[2:-1]
        lines_in_grofile = [] # taking the index of the lines from the GRofile that correspond to the molecule described in the itp file.

        for index, line in enumerate(grofile):
            residue = line[5:10].strip()

            if residue == self.residue:
                lines_in_grofile.append(index)

        self.lines_in_grofile = lines_in_grofile
        self.number_molecs = int(len(self.lines_in_grofile) / self.atoms_per_molec) # number of molecules in the GROfile that correspond to the topology given.

        return None
def run_multiprocessing(a_grofileName):

    # --------------------------------------------------------------------
    # Getting topology for molec0 and molec1
    # --------------------------------------------------------------------
    itpmolec0 = Topology.fromItpFile(workdir, molec0_ipt, Hydros0)
    itpmolec0.fromGroFile(workdir, a_grofileName)

    itpmolec1 = Topology.fromItpFile(workdir, molec1_itp, Hydros1)
    itpmolec1.fromGroFile(workdir, a_grofileName)

    # --------------------------------------------------------------------
    # Getting the molecules0 and molecules1 corresponding to the itpmolec0 and itpmolec1, respectvely
    # --------------------------------------------------------------------
    grofile = FileUtil.FileReader(workdir, a_grofileName).file

    print('\nGetting all molec0 molecules present in grofile: {}\n'.format(a_grofileName))
    molecs0_dict = add.get_molecules(itpmolec0, grofile)

    print('\nGetting all molec1 molecules present in grofile: {}\n'.format(a_grofileName))
    molecs1_dict = add.get_molecules(itpmolec1, grofile)

    # --------------------------------------------------------------------
    # Getting h-bonds interactions
    # --------------------------------------------------------------------

    # h-bonds interactions between molec0 and molec1. Where in molec0 we get X-H bond and in molec 1 we get Y
    # ------------------------------
    print('\nThe hydrogen bonds found between X-H from molec0 and Y from molec1 present in grofile {} are:\n'.format(a_grofileName))
    hbonds0_list = add.get_bonded_interactions(molecs0_dict, itpmolec0, molecs1_dict, Hydros1, Alkali1, dist_thres, angle_thres)

    if not hbonds0_list:
        print('\nNo hydrogen bonds found between X-H from molec0 and Y from molec1 present in grofile {}\n'.format(a_grofileName))
    else:
        print('\nA total of {} hydrogen bonds found between X-H from molec0 and Y from molec1 present in grofile {}\n'.format(str(len(hbonds0_list)), a_grofileName))

    # h-bonds interactions between molec0 and molec1. Where in molec0 we get X-H bond and in molec 1 we get Y
    # ------------------------------
    print('\nThe hydrogen bonds found between X-H from molec1 and Y from molec0 present in grofile {} are:\n'.format(a_grofileName))
    hbonds1_list = add.get_bonded_interactions(molecs1_dict, itpmolec1, molecs0_dict, Hydros0, Alkali0, dist_thres, angle_thres)

    if not hbonds1_list:
        print('\nNo hydrogen bonds found between X-H from molec1 and Y from molec0 present in grofile {}\n'.format(a_grofileName))
    else:
        print('\nA total of {} hydrogen bonds found between X-H from molec1 and Y from molec0 present in grofile {}\n'.format(str(len(hbonds1_list)), a_grofileName))

    # adding both list
    # ------------------------------
    hbond_list = hbonds0_list + hbonds1_list # we just add them

    del(itpmolec0, itpmolec1, grofile, molecs0_dict, molecs1_dict, hbonds0_list, hbonds1_list) # delete things to free space in case we run out of memory during the multiprocessing

    return hbond_list
Ejemplo n.º 3
0
    def fromList(cls, a_indexesList, a_grofileList):
        '''
        Molecule.fromList is the class constructor. It only takes the a_grofileList.
        a_grofileList is a piece from the grofile that corresponds to the
        molecule.
        This method is to about the molecules in the grofile.
        a_indexesList are the indexes to be selected from the supplied grofile (a_grofileList)
        '''
        # -------------------------------------
        # Verifying the input format is correct
        # -------------------------------------
        FileUtil.CheckFuncInput(a_grofileList, list, 'Topology.fromFileUtil')

        # -------------------------------------
        # splitting the line into the desired components
        # -------------------------------------
        residNum = []
        residType = []
        atomName = []
        atomNum = []
        xCoord = []
        yCoord = []
        zCoord = []

        for line in a_indexesList:
            residNum.append(
                int(a_grofileList[line]
                    [Gro.RESNUM_S.value:Gro.RESNUM_E.value].strip()))
            residType.append(a_grofileList[line]
                             [Gro.RESTYPE_S.value:Gro.RESTYPE_E.value].strip())
            atomName.append(a_grofileList[line]
                            [Gro.ATONAME_S.value:Gro.ATONAME_E.value].strip())
            atomNum.append(
                int(a_grofileList[line]
                    [Gro.ATONUM_S.value:Gro.ATONUM_E.value].strip()))
            xCoord.append(
                float(a_grofileList[line]
                      [Gro.XCOORD_S.value:Gro.XCOORD_E.value].strip()))
            yCoord.append(
                float(a_grofileList[line]
                      [Gro.YCOORD_S.value:Gro.YCOORD_E.value].strip()))
            zCoord.append(
                float(a_grofileList[line]
                      [Gro.ZCOORD_S.value:Gro.ZCOORD_E.value].strip()))

        return cls(residNum, residType, atomName, atomNum, xCoord, yCoord,
                   zCoord)
    def from_XVGfile(cls, a_destinationFilePath, a_fileName):
        '''
        XvgPlotter.from_XVGfile is a class constructor that takes the 2 arguments:
        a_destinationFilePath: the location where the xvg file is located.
        a_fileName: the name of the xvg file.
        '''

        file = FileUtil.FileReader(a_destinationFilePath, a_fileName).file
        legends = []

        for line in file:
            if line.find('title') >= 0: # Getting the title
                title = line.split('"')[1]
            elif line.find('xaxis') >= 0: # getting x-axis label
                xlabel = line.split('"')[1]
            elif line.find('yaxis') >= 0: # getting y-axis label
                ylabel = line.split('"')[1]
            elif line.find('@ s') >= 0: # getting the legends
                legends.append(line.split('"')[1])

        # Getting the dats to plot
        #-------------------------
        data = [line for line in file if (line.find('#') < 0 and line.find('@') < 0)]
        line_count = len(data)
        feature_num = len(data[0].split()) - 1  # number of features variables (x-axis is the first column so we deduct 1 unit)
        x_values = np.zeros(line_count, dtype=float)
        features = np.zeros((feature_num, line_count), dtype=float).T

        for index, line in enumerate(data):
            parts = line.split()
            x_values[index] = round(float(parts[0]), 4)

            for var in range(feature_num):
                new_part = var + 1 # we start from 1 beacause zero is x_values
                features[index][var] = round(float(parts[new_part]), 4)

        features = features.T
        plot_filename = a_fileName.split('.')[0] + '.png'

        return cls(x_values, features, title, xlabel, legends, ylabel, plot_filename)
    def get_gmx_index_density_files(a_destinationFilePath, a_all_hbonds,
                                    a_molec0_residue, a_molec1_residue,
                                    a_zBoxLen, a_gmx_call, a_grofileName,
                                    a_xtc_filename, a_tpr_filename,
                                    a_outdens_xvg):
        '''
        AdditionalFunctions.get_gmx_index_density_files is a method that call AdditionalFunctions.for_gmx_index
        and AdditionalFunctions.for_gmx_density.
        '''

        # Getting the index.ndx file using gmx make_ndx
        # ------------------------------

        columns_in_ndxFile = 15  # index files from gromacs has by default 15 columns
        ndx_gmx_format = '%6d'  # every digit in the column must comply wih this format (see gromacs manual)

        # Getting ready the atomnums in the all_hbonds to be added to the gmx index.ndx file
        # ------------------------------

        atom_nrs = [
        ]  # to save all the atomnums that are present in the H_bond objects
        for hbonds in a_all_hbonds:  # hbonds is a list of H_bond objects
            for hbondObj in hbonds:
                atom_nrs.extend([
                    hbondObj.H_atomNum, hbondObj.X_atomNum, hbondObj.Y_atomNum
                ])

        atom_nrs = list(
            AdditionalFunctions.chunks(atom_nrs, columns_in_ndxFile)
        )  # atom_nrs list must be divided into chunks of 15 numbers to comply with the index format for gmx
        # Example: atom_nrs = [x,x,x,x,x,x,x,x,x,x, ...........]
        # after using the chunk function, atom_nrs = [[15 x numbers here], [15 x numbers here], [15 x numbers here], ....]
        # where all x are different numbers

        # Now that the atomnums are in chucks of 15 numbers, the gmx index format must be applied to all numbers
        # ------------------------------

        hbond_atomnums = [
        ]  # list to save the atomnums from h_binds that will be added to the index.ndx gromacs file
        for element in atom_nrs:
            formatted = ''.join(ndx_gmx_format % n for n in element) + '\n'
            hbond_atomnums.append(formatted)

        hbond_atomnums = [
            '[ h_bond_atoms ]\n'
        ] + hbond_atomnums  # additing the tittle for this new group in the index file (see gromacs manual for more info).

        # Getting the final index.ndx file
        # ------------------------------

        index_out_filename = AdditionalFunctions.for_gmx_index(
            a_gmx_call, a_grofileName
        )  # creating the index.ndx file using gmx make_ndx and the name of the stderr and stdout

        ndx_fileObj = FileUtil.FileReader(
            a_destinationFilePath, 'index.ndx'
        )  # reading the index.ndx file created in the previous code
        ndx_fileObj.file = ndx_fileObj.file + hbond_atomnums  # adding the h_bonds atomnum to the index file (all this is required to calculate the density)
        ndx_fileObj.FileWriter(a_destinationFilePath,
                               'index.ndx')  # priting the new index.ndx file
        del (ndx_fileObj)

        print(
            '\nThe atom_nrs that are involved in the hydrogen bonds were added at the end of the index.ndx file \n'
        )

        # The stderr and stdout from gmx make_ndx is needed to get the indexes for gmx density input
        # ------------------------------

        # There is a bug very well known in gromacs. regards index files. Sometimes the residues are repeated.
        # When that happens, the residue name cannot be used for gmx density. To avoid problem, the index referred to the
        # residues wil be used instead.
        out_indexfile = FileUtil.FileReader(
            a_destinationFilePath, index_out_filename
        ).file  # reading the stderr and stdout file of gmx make_ndx

        molec0_index = [
        ]  # if the residue0 is repeated we wil need to append it to get the first index
        molec1_index = [
        ]  # if the residue1 is repeated we wil need to append it to get the first index

        for i, line in enumerate(out_indexfile):
            if line.find(a_molec0_residue) >= 0:
                molec0_index.append(line)
            if line.find(a_molec1_residue) >= 0:
                molec1_index.append(line)

        molec0_index = molec0_index[0].split()[
            0]  # taking the first index for residue0
        molec1_index = molec1_index[0].split()[
            0]  # taking the first index for residue1
        h_bond_index = 'h_bond_atoms'  # this was the same name used in the line 274 and it is at the end of the new index.ndx file

        # -------------------------------------------------------------------------------------------------
        # Getting the density file using gmx density
        # -------------------------------------------------------------------------------------------------

        zBoxLen = int(
            a_zBoxLen * 10
        )  # a_zBoxLen must be multiplied by 10 to be more slices and it must an integer (see gromacs manual)
        AdditionalFunctions.for_gmx_density(a_gmx_call, a_grofileName,
                                            a_xtc_filename, a_tpr_filename,
                                            a_outdens_xvg, zBoxLen,
                                            molec0_index, molec1_index,
                                            h_bond_index)

        return None
    def fromItpFile(cls, a_destinationFilePath, a_itpfileName, a_atomtypesH):
        '''
        This is the class constructor. It only takes the a_itpfile and a_atomtypesH.
        a) a_itpfile is the name of the gromacs itp file for a given molecule
        b) a_atomtypesH is a list of H atoms in the itp file
        c) a_destinationFilePath is where the file a_itpfileName is located
        '''
        # -------------------------------------
        # Verifying the input format is correct
        # -------------------------------------
        FileUtil.CheckFuncInput(a_destinationFilePath, str, 'Topology.fromItpFile')
        FileUtil.CheckFuncInput(a_itpfileName, str, 'Topology.fromItpFile')
        FileUtil.CheckFuncInput(a_atomtypesH, list, 'Topology.fromItpFile')

        # -------------------------------------
        # Reading the itp file
        # -------------------------------------
        itpFileOb = FileUtil.FileReader(a_destinationFilePath, a_itpfileName)
        itpfile = itpFileOb.file

        # -------------------------------------
        # Getting atoms from the itpfile
        # -------------------------------------
        # [ moleculetype ], [ atoms ], [ bonds ], and [ pairs ] are part of itp file format in Gromacs
        for index, line in enumerate(itpfile):
            if line.find('[ moleculetype ]') >= 0:
                molname_index = index + 2
            if line.find('[ atoms ]') >= 0:
                atoms_index_top = index + 2
            if line.find('[ bonds ]') >= 0 or line.find('[ pairs ]') >= 0:
                atoms_index_bottom = index - 1
                break

        moleculetype = itpfile[molname_index].split()[0]
        atoms_section = itpfile[atoms_index_top : atoms_index_bottom]
        atoms_per_molec = len(atoms_section)
        residue = atoms_section[0].split()[3]

        atomtype_atomNum_dict = {}
        atomTypeList = []

        for line in atoms_section:
            parts = line.split()
            key_atomtype = parts[1].strip()
            atomTypeList.append(key_atomtype)
            atom_nr = int(parts[0])

            if key_atomtype not in atomtype_atomNum_dict.keys():
                atomtype_atomNum_dict[key_atomtype] = []
                atomtype_atomNum_dict[key_atomtype].append(atom_nr)
            else:
                atomtype_atomNum_dict[key_atomtype].append(atom_nr)

        # -------------------------------------
        # Getting index of atoms bonded to Hydrogens from the itpfile
        # -------------------------------------
        # specifically looking in the bonds section
        # H is the hydrogen atom
        # X is the atom chemically bonded to the H atom
        for index, line in enumerate(itpfile):
            if line.find('[ bonds ]') >= 0:
                bonds_index_top = index + 2
            if line.find('[ angles ]') >= 0:
                bonds_index_bottom = index - 1
                break


        bonds_section = itpfile[bonds_index_top : bonds_index_bottom]
        atomsH_nrL = []

        for key_atomH in a_atomtypesH:
            atomsH_nrL.extend(atomtype_atomNum_dict[key_atomH])

        atomsH_nrL = sorted(atomsH_nrL)
        bonds = []

        for atomH_nr in atomsH_nrL:
            atomH_line = atoms_section[atomH_nr - 1]
            partsH = atomH_line.split()
            atyomtypeH = partsH[1]
            atomH = partsH[4]

            for line in bonds_section:
                # bonds sections is a list where each line has two number. Those are atomnumbers that corresponds to two atoms that are bonded.
                # the H atom can be any of those numbers, thus we need to check both.
                parts = line.split()
                atomnum1 = int(parts[0])
                atomnum2 = int(parts[1])
                bond_info = {}

                if atomnum1 == atomH_nr: # if the hydrogen is atomnum1
                    bond_info['atomNumH'] = atomnum1
                    bond_info['atomTypeH'] = atyomtypeH
                    bond_info['atomH'] = atomH

                    # Getting AtomX
                    # -------------
                    atomX_line = atoms_section[atomnum2 - 1] # atomnums start from 1 and python is starting from 0. Thus we take one unit.
                    partsX = atomX_line.split()
                    atyomtypeX = partsX[1]
                    atomX = partsX[4]
                    bond_info['atomNumX'] = atomnum2
                    bond_info['atomTypeX'] = atyomtypeX
                    bond_info['atomX'] = atomX
                    bonds.append(bond_info)

                if atomnum2 == atomH_nr: # if the hydrogen is atomnum2
                    bond_info['atomNumH'] = atomnum2
                    bond_info['atomTypeH'] = atyomtypeH
                    bond_info['atomH'] = atomH

                    # Getting AtomX
                    # -------------
                    atomX_line = atoms_section[atomnum1 - 1] # atomnums start from 1 and python is starting from 0. Thus we take one unit.
                    partsX = atomX_line.split()
                    atyomtypeX = partsX[1]
                    atomX = partsX[4]
                    bond_info['atomNumX'] = atomnum1
                    bond_info['atomTypeX'] = atyomtypeX
                    bond_info['atomX'] = atomX
                    bonds.append(bond_info)

                if atomnum1 > atomH_nr and atomnum2 > atomH_nr: # if both atomnum are higher that atomH_nr, then there is no need to continue the search for that H atom.
                    break

        return cls(moleculetype, residue, atoms_per_molec, atomtype_atomNum_dict, bonds, atomTypeList) # these 5 variable are basic data from a ipt file
print('\nFinished all plots!\n')

# -------------------------------------------------------------------------------------------------
# Getting the density profile using gmx density
# -------------------------------------------------------------------------------------------------

# Getting the residue name for molec0 and molec1 (see Topology.py for more info)
# ------------------------------

molec0_residue= Topology.fromItpFile(workdir, molec0_ipt, Hydros0).residue
molec1_residue = Topology.fromItpFile(workdir, molec1_itp, Hydros1).residue

# Getting the z-axis length of the grofile (any grofile can be used)
# ------------------------------

zBoxLen = float(FileUtil.FileReader(workdir, grofiles[-1]).file[-1].split()[2]) # Any grofile can be used. The last was selected.

# Getting the density file file
# ------------------------------

add.get_gmx_index_density_files(workdir, all_hbonds, molec0_residue, molec1_residue,
                            zBoxLen, gmx_call, grofiles[-1], xtc_filename,
                            tpr_filename, outdens_xvg)

print('\nDensity profile was calculated sucessfully!\n')

# -------------------------------------------------------------------------------------------------
# Doing the density profile plot
# -------------------------------------------------------------------------------------------------

print('\nPlotting the density profile!\n')