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
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')