Skip to content

Commit

Permalink
Merge branch 'analyzer_tool'
Browse files Browse the repository at this point in the history
  • Loading branch information
Valdes-Tresanco-MS committed Feb 21, 2021
2 parents 6c7cd57 + 478db4f commit 634bed4
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 230 deletions.
4 changes: 2 additions & 2 deletions GMXMMPBSA/input_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ def Parse(self, filename):
['interval', int, 1, 'Number of frames between adjacent frames analyzed.'],
['ions_parameters', int, 1, 'Define ions parameters to build the Amber topology.'],
['keep_files', int, 2, 'How many files to keep after successful completion.'],
['ligand_mask', str, None, 'Amber mask of ligand atoms in complex prmtop.'],
# ['ligand_mask', str, None, 'Amber mask of ligand atoms in complex prmtop.'],
['ligand_forcefield', str, "leaprc.gaff", 'Define the force field to build Amber topology for '
'ligand (small molecule)'],
['netcdf', int, 0, 'Use NetCDF intermediate trajectories.'],
Expand All @@ -507,7 +507,7 @@ def Parse(self, filename):
['protein_forcefield', str, "oldff/leaprc.ff99SB", 'Define the force field to build Amber '
'topology for protein'],

['receptor_mask', str, None, 'Amber mask of receptor atoms in complex prmtop.'],
# ['receptor_mask', str, None, 'Amber mask of receptor atoms in complex prmtop.'],
# ['search_path', str, '', 'Look for intermediate programs in all of PATH'],
['solvated_trajectory', int, 1, 'Define if it is necessary to cleanup the trajectories'],
['startframe', int, 1, 'First frame to analyze.'],
Expand Down
14 changes: 1 addition & 13 deletions GMXMMPBSA/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,12 +587,12 @@ def loadcheck_prmtops(self):
self.external_progs = external_progs

# Make amber topologies

logging.info('Building AMBER Topologies from GROMACS files...')
maketop = CheckMakeTop(FILES, INPUT, self.external_progs)
(FILES.complex_prmtop, FILES.receptor_prmtop, FILES.ligand_prmtop, FILES.mutant_complex_prmtop,
FILES.mutant_receptor_prmtop, FILES.mutant_ligand_prmtop) = maketop.buildTopology()
logging.info('Building AMBER Topologies from GROMACS files...Done.\n')
INPUT['receptor_mask'], INPUT['ligand_mask'] = maketop.get_masks()

self.normal_system = MMPBSA_System(FILES.complex_prmtop, FILES.receptor_prmtop, FILES.ligand_prmtop)
self.using_chamber = self.normal_system.complex_prmtop.chamber
Expand All @@ -607,9 +607,6 @@ def loadcheck_prmtops(self):
FILES.mutant_ligand_prmtop = FILES.ligand_prmtop
self.mutant_system = MMPBSA_System(FILES.mutant_complex_prmtop, FILES.mutant_receptor_prmtop,
FILES.mutant_ligand_prmtop)
if self.using_chamber is not self.mutant_system.complex_prmtop.chamber:
GMXMMPBSA_ERROR('CHAMBER prmtops must be used for both mutant '
'and normal prmtops or neither!')
# If we have a chamber prmtop, force using sander
if self.using_chamber:
INPUT['use_sander'] = True
Expand All @@ -619,15 +616,6 @@ def loadcheck_prmtops(self):
GMXMMPBSA_ERROR('CHAMBER prmtops cannot be used with NMODE')
self.stdout.write('CHAMBER prmtops found. Forcing use of sander\n')

# Print warnings if we are overwriting any masks and get default masks
if (INPUT['ligand_mask'] is None and INPUT['receptor_mask'] is not None):
warnings.warn('receptor_mask overwritten with default\n')
INPUT['receptor_mask'] = None
if (INPUT['receptor_mask'] is None and INPUT['ligand_mask'] is not None):
warnings.warn('ligand_mask overwritten with default\n')
INPUT['ligand_mask'] = None
# Map the gmx_MMPBSA systems with the input masks, and get the default ones if
# the masks were not input
self.normal_system.Map(INPUT['receptor_mask'], INPUT['ligand_mask'])
self.normal_system.CheckConsistency()
if INPUT['alarun']:
Expand Down
150 changes: 81 additions & 69 deletions GMXMMPBSA/make_top.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def gmx2pdb(self):
self.complex_str = self.molstr(self.complex_str_file)
self.receptor_str = self.molstr(self.receptor_str_file)
self.ligand_str = self.molstr(self.ligand_str_file)
self.resi, self.resl, self.orderl = self.res2map(self.complex_str, self.receptor_str, self.ligand_str)
self.resi, self.resl, self.orderl = self.res2map()
self.fix_chains_IDs(self.complex_str, self.receptor_str, self.ligand_str, self.ref_str)

def gmxtop2prmtop(self):
Expand Down Expand Up @@ -499,19 +499,19 @@ def pdb2prmtop(self):

def reswithin(self):
# Get residue form receptor-ligand interface
if self.print_residues:
if self.print_residues and self.INPUT['decomprun']:
res_list = []
for i in self.resl['REC']:
if i in res_list:
continue
for j in self.resl['LIG']:
if j in res_list:
continue
for rat in self.complex_str.residues[i].atoms:
for rat in self.complex_str.residues[i - 1].atoms:
rat_coor = [rat.xx, rat.xy, rat.xz]
if i in res_list:
break
for lat in self.complex_str.residues[j].atoms:
for lat in self.complex_str.residues[j - 1].atoms:
lat_coor = [lat.xx, lat.xy, lat.xz]
if dist(rat_coor, lat_coor) <= self.within:
if i not in res_list:
Expand Down Expand Up @@ -554,74 +554,86 @@ def cleantop(self, top_file, temp_top_file):
temp_top.write(line)
temp_top.close()

@staticmethod
def res2map(com_str, rec_str, lig_str):
def get_masks(self):
rt = []
for r in self.resi['REC']:
if r[0] == r[1]: # only as precaution
rt.append(f'{r[0]}')
else:
rt.append(f'{r[0]}-{r[1]}')
rec_mask = ':' + ','.join(rt)
lt = []
for l in self.resi['LIG']:
if l[0] == l[1]:
lt.append(f'{l[0]}')
else:
lt.append(f'{l[0]}-{l[1]}')
lig_mask = ':' + ','.join(lt)
return rec_mask, lig_mask

def res2map(self):
"""
Obtains the indices of residues in the complex from the receptor and the ligand. This function allows indexing
of receptor and ligand residues even if they are mixed or discontinuous.
:param com_str: Complex structure
:param rec_str: Receptor structure
:param lig_str: Ligand structure
:return: a dictionary containing the ranges of the receptor and ligand indices
:param com_str:
:return:
"""
ref_map = {}
c_rec = 0
c_lig = 0
no_rec = True
lig = True
cpart = None
# read the index file
ndx = {}
with open(self.FILES.complex_index) as indexf:
header = None
for line in indexf:
if line.startswith('['):
header = line.strip('\n[] ')
ndx[header] = []
else:
ndx[header].extend(map(int, line.split()))
com_str = self.complex_str

start = 1
end = None
order_list = []
for i in range(len(com_str.residues)):
if no_rec and (com_str.residues[i].name == rec_str.residues[c_rec].name):
if not cpart or cpart != 'R':
cpart = 'R'
order_list.append('R')
ref_map[i] = 'R'
c_rec += 1
if c_rec == len(rec_str.residues):
no_rec = False
else:
if lig and com_str.residues[i].name == lig_str.residues[c_lig].name:
if not cpart or cpart != 'L':
cpart = 'L'
order_list.append('L')
ref_map[i] = 'L'
c_lig += 1
if c_lig == len(lig_str.residues):
lig = False
previous = None

masks = {'REC': [], 'LIG': []}
res_list = {'REC': [], 'LIG': []}

# Separate each element to its corresponding partner
for i in ref_map:
if ref_map[i] == 'R':
res_list['REC'].append(i)
else:
res_list['LIG'].append(i)

rec_s = res_list['REC'][0]
rec_e = rec_s
for i in range(1, len(res_list['REC'])):
if res_list['REC'][i] - res_list['REC'][i - 1] == 1:
rec_e += 1
else:
masks['REC'].append([rec_s, rec_e])
rec_s = res_list['REC'][i]
rec_e = res_list['REC'][i]
masks['REC'].append([rec_s, rec_e])

lig_s = res_list['LIG'][0]
lig_e = lig_s
for i in range(1, len(res_list['LIG'])):
if res_list['LIG'][i] - res_list['LIG'][i - 1] == 1:
lig_e += 1
com_ndx = ndx['GMXMMPBSA_REC_GMXMMPBSA_LIG']
com_len = len(ndx['GMXMMPBSA_REC_GMXMMPBSA_LIG'])
dif = 0
for i in range(com_len):
if i == 0:
dif = com_str.atoms[i].residue.number - 1 # AMBER mask must be start at 1
# We check who owns the residue corresponding to this atom
if com_ndx[i] in ndx['GMXMMPBSA_REC']:
current = 'R'
# save residue number in the rec list
resnum = com_str.atoms[i].residue.number - dif
if not resnum in res_list['REC']:
res_list['REC'].append(resnum)
else:
masks['LIG'].append([lig_s, lig_e])
lig_s = res_list['LIG'][i]
lig_e = res_list['LIG'][i]
masks['LIG'].append([lig_s, lig_e])

current = 'L'
# save residue number in the lig list
resnum = com_str.atoms[i].residue.number - dif
if not resnum in res_list['LIG']:
res_list['LIG'].append(resnum)
# check for end
if previous and current != previous:
end = com_str.atoms[i-1].residue.number - dif

# when i is the last index
if i == com_len - 1:
end = com_str.atoms[i].residue.number - dif
if end:
if previous == 'R':
masks['REC'].append([start, end])
else:
masks['LIG'].append([start, end])
# add current range identifier
order_list.append(previous)
# set the new start and reset end
start = end + 1
end = None
# we change previous to current once it is processed
previous = current
return masks, res_list, order_list

def fixparm2amber(self, structure, removeH=False):
Expand Down Expand Up @@ -879,7 +891,7 @@ def fix_chains_IDs(self, com_str, rec_str=None, lig_str=None, ref_str=None):
c = 0
for res in ref_str.residues:
res.chain = com_str.residues[c].chain
if c in self.resl['REC']:
if c + 1 in self.resl['REC']:
i = self.resl['REC'].index(c)
rec_str.residues[i].chain = res.chain
else:
Expand Down Expand Up @@ -917,7 +929,7 @@ def fix_chains_IDs(self, com_str, rec_str=None, lig_str=None, ref_str=None):
if not res.chain:
res.chain = curr_chain_id

if c in self.resl['REC']:
if c + 1 in self.resl['REC']:
i = self.resl['REC'].index(c)
rec_str.residues[i].chain = res.chain
else:
Expand Down Expand Up @@ -960,7 +972,7 @@ def fix_chains_IDs(self, com_str, rec_str=None, lig_str=None, ref_str=None):
curr_chain_id = chains_letters[chains_letters.index(chains_ids[-1]) + 1]
res.chain = curr_chain_id

if c in self.resl['REC']:
if c + 1 in self.resl['REC']:
i = self.resl['REC'].index(c)
rec_str.residues[i].chain = res.chain
else:
Expand All @@ -984,7 +996,7 @@ def fix_chains_IDs(self, com_str, rec_str=None, lig_str=None, ref_str=None):
def molstr(self, data):

if type(data) == str:
# data is a pdb file
# data is a pdb file
pdb_file = data
try:
with open(pdb_file) as fo:
Expand Down
Loading

0 comments on commit 634bed4

Please sign in to comment.