Skip to content

Commit

Permalink
Make bond check optional
Browse files Browse the repository at this point in the history
  • Loading branch information
brennanaba committed Mar 7, 2023
1 parent 4b324ff commit fa14229
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 37 deletions.
18 changes: 10 additions & 8 deletions ImmuneBuilder/ABodyBuilder2.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def save_single_unrefined(self, filename, index=0):
file.write(unrefined)


def save_all(self, dirname=None, filename=None):
def save_all(self, dirname=None, filename=None, check_for_strained_bonds=True):
if dirname is None:
dirname="ABodyBuilder2_output"
if filename is None:
Expand All @@ -60,22 +60,22 @@ def save_all(self, dirname=None, filename=None):

np.save(os.path.join(dirname,"error_estimates"), self.error_estimates.mean(0).cpu().numpy())
final_filename = os.path.join(dirname, filename)
refine(os.path.join(dirname,"rank0_unrefined.pdb"), final_filename)
refine(os.path.join(dirname,"rank0_unrefined.pdb"), final_filename, check_for_strained_bonds=check_for_strained_bonds)
add_errors_as_bfactors(final_filename, self.error_estimates.mean(0).sqrt().cpu().numpy(), header=[header])


def save(self, filename=None):
def save(self, filename=None,check_for_strained_bonds=True):
if filename is None:
filename = "ABodyBuilder2_output.pdb"

for i in range(len(self.atoms)):
self.save_single_unrefined(filename, index=self.ranking.index(i))
success = refine(filename, filename)
success = refine(filename, filename, check_for_strained_bonds=check_for_strained_bonds)
if success:
break
else:
self.save_single_unrefined(filename, index=self.ranking.index(i))
success = refine(filename, filename)
success = refine(filename, filename, check_for_strained_bonds=check_for_strained_bonds)
if success:
break

Expand Down Expand Up @@ -147,8 +147,8 @@ def command_line_interface():
parser.add_argument("--to_directory", help="Save all unrefined models and the top ranked refined model to a directory. "
"If this flag is set the output argument will be assumed to be a directory", default=False, action="store_true")
parser.add_argument("-n", "--numbering_scheme", help="The scheme used to number output antibody structures. Available numbering schemes are: imgt, chothia, kabat, aho, wolfguy, martin and raw. Default is imgt.", default='imgt')
parser.add_argument("-u", "--no_sidechain_bond_check", help="Don't check for strained bonds. This is a bit faster but will rarely generate unphysical side chains", default=False, action="store_true")
parser.add_argument("-v", "--verbose", help="Verbose output", default=False, action="store_true")

args = parser.parse_args()

if (args.heavy_sequence is not None) and (args.light_sequence is not None):
Expand All @@ -158,6 +158,8 @@ def command_line_interface():
else:
raise ValueError("Missing input sequences")

check_for_strained_bonds = not args.no_sidechain_bond_check

if args.verbose:
print(description, flush=True)
print(f"Sequences loaded succesfully.\nHeavy and light chains are:", flush=True)
Expand All @@ -174,11 +176,11 @@ def command_line_interface():
print("Antibody modelled succesfully, starting refinement.", flush=True)

if args.to_directory:
antibody.save_all(args.output)
antibody.save_all(args.output,check_for_strained_bonds)
if args.verbose:
print("Refinement finished. Saving all outputs to directory", flush=True)
else:
antibody.save(args.output)
antibody.save(args.output,check_for_strained_bonds)
if args.verbose:
outfile = "ABodyBuilder2_output.pdb" if args.output is None else args.output
print(f"Refinement finished. Saving final structure to {outfile}", flush=True)
18 changes: 10 additions & 8 deletions ImmuneBuilder/NanoBodyBuilder2.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def save_single_unrefined(self, filename, index=0):
file.write(unrefined)


def save_all(self, dirname=None, filename=None):
def save_all(self, dirname=None, filename=None, check_for_strained_bonds=True):
if dirname is None:
dirname="NanoBodyBuilder2_output"
if filename is None:
Expand All @@ -60,22 +60,22 @@ def save_all(self, dirname=None, filename=None):

np.save(os.path.join(dirname,"error_estimates"), self.error_estimates.mean(0).cpu().numpy())
final_filename = os.path.join(dirname, filename)
refine(os.path.join(dirname,"rank0_unrefined.pdb"), final_filename)
refine(os.path.join(dirname,"rank0_unrefined.pdb"), final_filename, check_for_strained_bonds=check_for_strained_bonds)
add_errors_as_bfactors(final_filename, self.error_estimates.mean(0).sqrt().cpu().numpy(), header=[header])


def save(self, filename=None):
def save(self, filename=None, check_for_strained_bonds=True):
if filename is None:
filename = "NanoBodyBuilder2_output.pdb"

for i in range(len(self.atoms)):
self.save_single_unrefined(filename, index=self.ranking.index(i))
success = refine(filename, filename)
success = refine(filename, filename, check_for_strained_bonds=check_for_strained_bonds)
if success:
break
else:
self.save_single_unrefined(filename, index=self.ranking.index(i))
success = refine(filename, filename)
success = refine(filename, filename, check_for_strained_bonds=check_for_strained_bonds)
if success:
break

Expand Down Expand Up @@ -150,7 +150,7 @@ def command_line_interface():
parser.add_argument("--to_directory", help="Save all unrefined models and the top ranked refined model to a directory. "
"If this flag is set the output argument will be assumed to be a directory", default=False, action="store_true")
parser.add_argument("-n", "--numbering_scheme", help="The scheme used to number output nanobody structures. Available numbering schemes are: imgt, chothia, kabat, aho, wolfguy, martin and raw. Default is imgt.", default='imgt')

parser.add_argument("-u", "--no_sidechain_bond_check", help="Don't check for strained bonds. This is a bit faster but will rarely generate unphysical side chains", default=False, action="store_true")
parser.add_argument("-v", "--verbose", help="Verbose output", default=False, action="store_true")

args = parser.parse_args()
Expand All @@ -162,6 +162,8 @@ def command_line_interface():
else:
raise ValueError("Missing input sequences")

check_for_strained_bonds = not args.no_sidechain_bond_check

if args.verbose:
print(description, flush=True)
print(f"Sequence loaded succesfully.\nHeavy chain is:", flush=True)
Expand All @@ -178,11 +180,11 @@ def command_line_interface():
print("Nanobody modelled succesfully, starting refinement.", flush=True)

if args.to_directory:
antibody.save_all(args.output)
antibody.save_all(args.output,check_for_strained_bonds)
if args.verbose:
print("Refinement finished. Saving all outputs to directory", flush=True)
else:
antibody.save(args.output)
antibody.save(args.output,check_for_strained_bonds)
if args.verbose:
outfile = "NanoBodyBuilder2_output.pdb" if args.output is None else args.output
print(f"Refinement finished. Saving final structure to {outfile}", flush=True)
17 changes: 10 additions & 7 deletions ImmuneBuilder/TCRBuilder2.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def save_single_unrefined(self, filename, index=0):
file.write(unrefined)


def save_all(self, dirname=None, filename=None):
def save_all(self, dirname=None, filename=None, check_for_strained_bonds=True):
if dirname is None:
dirname="TCRBuilder2_output"
if filename is None:
Expand All @@ -60,22 +60,22 @@ def save_all(self, dirname=None, filename=None):

np.save(os.path.join(dirname,"error_estimates"), self.error_estimates.mean(0).cpu().numpy())
final_filename = os.path.join(dirname, filename)
refine(os.path.join(dirname,"rank0_unrefined.pdb"), final_filename)
refine(os.path.join(dirname,"rank0_unrefined.pdb"), final_filename, check_for_strained_bonds=check_for_strained_bonds)
add_errors_as_bfactors(final_filename, self.error_estimates.mean(0).sqrt().cpu().numpy(), header=[header])


def save(self, filename=None):
def save(self, filename=None, check_for_strained_bonds=True):
if filename is None:
filename = "TCRBuilder2_output.pdb"

for i in range(len(self.atoms)):
self.save_single_unrefined(filename, index=self.ranking.index(i))
success = refine(filename, filename)
success = refine(filename, filename, check_for_strained_bonds=check_for_strained_bonds)
if success:
break
else:
self.save_single_unrefined(filename, index=self.ranking.index(i))
success = refine(filename, filename)
success = refine(filename, filename, check_for_strained_bonds=check_for_strained_bonds)
if success:
break

Expand Down Expand Up @@ -147,6 +147,7 @@ def command_line_interface():
parser.add_argument("-o", "--output", help="Path to where the output model should be saved. Defaults to the same directory as input file.", default=None)
parser.add_argument("--to_directory", help="Save all unrefined models and the top ranked refined model to a directory. "
"If this flag is set the output argument will be assumed to be a directory", default=False, action="store_true")
parser.add_argument("-u", "--no_sidechain_bond_check", help="Don't check for strained bonds. This is a bit faster but will rarely generate unphysical side chains", default=False, action="store_true")
parser.add_argument("-v", "--verbose", help="Verbose output", default=False, action="store_true")

args = parser.parse_args()
Expand All @@ -158,6 +159,8 @@ def command_line_interface():
else:
raise ValueError("Missing input sequences")

check_for_strained_bonds = not args.no_sidechain_bond_check

if args.verbose:
print(description, flush=True)
print(f"Sequences loaded succesfully.\nAlpha and Beta chains are:", flush=True)
Expand All @@ -174,11 +177,11 @@ def command_line_interface():
print("TCR modelled succesfully, starting refinement.", flush=True)

if args.to_directory:
tcr.save_all(args.output)
tcr.save_all(args.output,check_for_strained_bonds)
if args.verbose:
print("Refinement finished. Saving all outputs to directory", flush=True)
else:
tcr.save(args.output)
tcr.save(args.output,check_for_strained_bonds)
if args.verbose:
outfile = "TCRBuilder2_output.pdb" if args.output is None else args.output
print(f"Refinement finished. Saving final structure to {outfile}", flush=True)
31 changes: 17 additions & 14 deletions ImmuneBuilder/refine.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@
forcefield = app.ForceField("amber14/protein.ff14SB.xml")


def refine(input_file, output_file, tries=3, n=6):
def refine(input_file, output_file, check_for_strained_bonds=True, tries=3, n=6):
for i in range(tries):
if refine_once(input_file, output_file, n=n):
if refine_once(input_file, output_file, check_for_strained_bonds=check_for_strained_bonds, n=n):
return True
return False


def refine_once(input_file, output_file, n=6):
def refine_once(input_file, output_file, check_for_strained_bonds=True, n=6):
k1s = [2.5,1,0.5,0.25,0.1,0.001]
k2s = [2.5,5,7.5,15,25,50]
success = False
Expand Down Expand Up @@ -81,17 +81,20 @@ def refine_once(input_file, output_file, n=6):
topology, positions = fixer.topology, fixer.positions
continue

# If all other checks pass, check and fix strained sidechain bonds:
try:
strained_bonds = strained_sidechain_bonds_check(topology, positions)
if len(strained_bonds) > 0:
needs_recheck = True
topology, positions = strained_sidechain_bonds_fixer(strained_bonds, topology, positions)
else:
needs_recheck = False
except OpenMMException as e:
topology, positions = fixer.topology, fixer.positions
continue
if check_for_strained_bonds:
# If all other checks pass, check and fix strained sidechain bonds:
try:
strained_bonds = strained_sidechain_bonds_check(topology, positions)
if len(strained_bonds) > 0:
needs_recheck = True
topology, positions = strained_sidechain_bonds_fixer(strained_bonds, topology, positions)
else:
needs_recheck = False
except OpenMMException as e:
topology, positions = fixer.topology, fixer.positions
continue
else:
needs_recheck = False

# If it passes all the tests, we are done
tests = bond_check(topology, positions) and cis_check(topology, positions)
Expand Down

0 comments on commit fa14229

Please sign in to comment.