Skip to content

Commit ead4092

Browse files
authored
Merge pull request #471 from OpenBioSim/fix_470
Fix for ATM centre of mass restraints
2 parents 1c1aded + a901746 commit ead4092

2 files changed

Lines changed: 103 additions & 6 deletions

File tree

python/BioSimSpace/FreeEnergy/_atm.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@ def prepare(
525525
self._setLig2ComAtoms(ligand_free_com_atoms)
526526

527527
self._findAtomIndices()
528+
self._setLig1ProteinDisplacement()
529+
self._setLig2ProteinDisplacement()
528530
self._makeData()
529531
serialisable_disp = [
530532
self._displacement.x(),
@@ -555,6 +557,8 @@ def prepare(
555557
self._setLig1ComAtoms(ligand_bound_com_atoms)
556558
self._setLig2ComAtoms(ligand_free_com_atoms)
557559
self._findAtomIndices()
560+
self._setLig1ProteinDisplacement()
561+
self._setLig2ProteinDisplacement()
558562
self._makeData()
559563
serialisable_disp = [
560564
self._displacement.x(),
@@ -878,6 +882,79 @@ def _setLig2ComAtoms(self, lig2_com_atoms):
878882
for a in ligand_free._sire_object[f"atoms within 11 angstrom of {com}"]
879883
]
880884

885+
@staticmethod
886+
def _find_separation(com1, com2):
887+
"""
888+
Finds the separation vector between two sets of coordinates.
889+
890+
Parameters
891+
----------
892+
com1 : Coordinates
893+
The coordinates of the first molecule of interest.
894+
com2 : Coordinates
895+
The coordinates of the second molecule of interest.
896+
897+
Returns
898+
-------
899+
list
900+
A list of floats representing the separation vector between the two molecules.
901+
"""
902+
separation_vector = com2 - com1
903+
separation = [i.value() for i in separation_vector]
904+
return separation
905+
906+
def _getLig1ProteinDisplacement(self):
907+
"""
908+
Get the calculated displacement between ligand 1 and the protein.
909+
910+
Returns
911+
-------
912+
list
913+
A list of floats representing the displacement between ligand 1 and the protein.
914+
"""
915+
return self._lig1_protein_displacement
916+
917+
def _setLig1ProteinDisplacement(self):
918+
"""
919+
Set the calculated displacement between ligand 1 and the protein.
920+
Must be called after MakeSystemFromThree and setting of indices.
921+
"""
922+
# find the ligand atoms that define its center of mass
923+
lig1 = self._system[self._ligand_bound_index]
924+
lig1_com_coords = lig1._sire_object.atoms()[self._lig1_com_atoms].coordinates()
925+
# protein com coords (assumes that the first index in protein_index is representative of the whole protein)
926+
prot = self._system[self.protein_index[0]]
927+
prot_com_coords = prot._sire_object.atoms()[self._mol1_com_atoms].coordinates()
928+
self._lig1_protein_displacement = self._find_separation(
929+
prot_com_coords, lig1_com_coords
930+
)
931+
932+
def _getLig2ProteinDisplacement(self):
933+
"""
934+
Get the calculated displacement between ligand 2 and the protein.
935+
936+
Returns
937+
-------
938+
list
939+
A list of floats representing the displacement between ligand 2 and the protein.
940+
"""
941+
return self._lig2_protein_displacement
942+
943+
def _setLig2ProteinDisplacement(self):
944+
"""
945+
Set the calculated displacement between ligand 2 and the protein.
946+
Must be called after MakeSystemFromThree and setting of indices.
947+
"""
948+
# find the ligand atoms that define its center of mass
949+
lig2 = self._system[self._ligand_free_index]
950+
lig2_com_coords = lig2._sire_object.atoms()[self._lig2_com_atoms].coordinates()
951+
# protein com coords (assumes that the first index in protein_index is representative of the whole protein)
952+
prot = self._system[self.protein_index[0]]
953+
prot_com_coords = prot._sire_object.atoms()[self._mol1_com_atoms].coordinates()
954+
self._lig2_protein_displacement = self._find_separation(
955+
prot_com_coords, lig2_com_coords
956+
)
957+
881958
def _makeData(self):
882959
"""
883960
Make the data dictionary for the ATM system
@@ -901,6 +978,8 @@ def _makeData(self):
901978
self.data["protein_com_atoms"] = self._mol1_com_atoms
902979
self.data["ligand_bound_com_atoms"] = self._lig1_com_atoms
903980
self.data["ligand_free_com_atoms"] = self._lig2_com_atoms
981+
self.data["lig1_protein_displacement"] = self._lig1_protein_displacement
982+
self.data["lig2_protein_displacement"] = self._lig2_protein_displacement
904983

905984
@staticmethod
906985
def viewRigidCores(

python/BioSimSpace/Process/_atm_utils.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ def findAbsoluteCOMAtoms(self):
7272
self.lig2_first_atomnum, self.data["ligand_free_com_atoms"]
7373
).tolist()
7474

75+
def findLigProtDisplacements(self):
76+
self.lig1_protein_displacement = self.data["lig1_protein_displacement"]
77+
self.lig2_protein_displacement = self.data["lig2_protein_displacement"]
78+
7579
def getATMForceConstants(self, index=None):
7680
from .. import Protocol as _Protocol
7781

@@ -404,6 +408,7 @@ def createCOMRestraint(self, force_group=None):
404408
"""
405409

406410
self.findAbsoluteCOMAtoms()
411+
self.findLigProtDisplacements()
407412
# Groups contained within the constraint
408413
protein_com = self.protein_com_atoms
409414
lig1_com = self.lig1_com_atoms
@@ -416,6 +421,19 @@ def createCOMRestraint(self, force_group=None):
416421
output += "protein_com = {}\n".format(protein_com)
417422
output += "lig1_com = {}\n".format(lig1_com)
418423
output += "lig2_com = {}\n".format(lig2_com)
424+
425+
output += "# Displacement values for protein-ligand COM restraint\n"
426+
# round to 3 decimal places for clarity
427+
output += "displacement_bound = {}\n".format(
428+
[round(x, 3) for x in self.lig1_protein_displacement]
429+
)
430+
output += "displacement_free = {}\n".format(
431+
[round(x, 3) for x in self.lig2_protein_displacement]
432+
)
433+
output += "# Convert displacement to nm from angstrom\n"
434+
output += "displacement_bound = [x * 0.1 for x in displacement_bound]\n"
435+
output += "displacement_free = [x * 0.1 for x in displacement_free]\n"
436+
419437
output += "# Constants for the CM-CM force in their input units\n"
420438
output += "kfcm = {} * kilocalorie_per_mole / angstrom**2\n".format(kf_cm)
421439
output += "tolcm = {} * angstrom \n".format(tol_cm)
@@ -434,9 +452,9 @@ def createCOMRestraint(self, force_group=None):
434452
output += """parameters_bound = (
435453
kfcm.value_in_unit(kilojoules_per_mole / nanometer**2),
436454
tolcm.value_in_unit(nanometer),
437-
0.0 * nanometer,
438-
0.0 * nanometer,
439-
0.0 * nanometer,
455+
displacement_bound[0] * nanometer,
456+
displacement_bound[1] * nanometer,
457+
displacement_bound[2] * nanometer,
440458
)\n"""
441459
output += "force_CMCM.addBond((1,0), parameters_bound)\n"
442460
output += "numgroups = force_CMCM.getNumGroups()\n"
@@ -446,9 +464,9 @@ def createCOMRestraint(self, force_group=None):
446464
output += """parameters_free = (
447465
kfcm.value_in_unit(kilojoules_per_mole / nanometer**2),
448466
tolcm.value_in_unit(nanometer),
449-
displacement[0] * nanometer,
450-
displacement[1] * nanometer,
451-
displacement[2] * nanometer,
467+
displacement_free[0] * nanometer,
468+
displacement_free[1] * nanometer,
469+
displacement_free[2] * nanometer,
452470
)\n"""
453471

454472
output += "force_CMCM.addBond((numgroups+1,numgroups+0), parameters_free)\n"

0 commit comments

Comments
 (0)