@@ -760,7 +760,7 @@ def write_pdbfile(self,filename="Fragment"):
760
760
return f"{ filename } .pdb"
761
761
762
762
# Create new topology from scratch if none is defined (defined automatically when reading PDB-files by OpenMM)
763
- def define_topology (self , scale = 1.0 , tol = 0.1 ):
763
+ def define_topology (self , scale = 1.0 , tol = 0.1 , resname = "MOL" ):
764
764
try :
765
765
import openmm .app
766
766
except ImportError :
@@ -769,7 +769,7 @@ def define_topology(self, scale=1.0, tol=0.1):
769
769
print ("Defining new basic single-chain, single-residue topology" )
770
770
self .pdb_topology = openmm .app .Topology ()
771
771
chain = self .pdb_topology .addChain ()
772
- residue = self .pdb_topology .addResidue ("MOL" , chain )
772
+ residue = self .pdb_topology .addResidue (resname , chain )
773
773
774
774
# Defaultdictionary to keep track of unique element-atomnames
775
775
atomnames_dict = defaultdict (int )
@@ -788,7 +788,7 @@ def define_topology(self, scale=1.0, tol=0.1):
788
788
789
789
# Write PDB-file via OpenMM
790
790
def write_pdbfile_openmm (self ,filename = "Fragment" , calc_connectivity = False , pdb_topology = None ,
791
- skip_connectivity = False ):
791
+ skip_connectivity = False , resname = "MOL" ):
792
792
print ("write_pdbfile_openmm\n " )
793
793
try :
794
794
import openmm .app
@@ -807,7 +807,7 @@ def write_pdbfile_openmm(self,filename="Fragment", calc_connectivity=False, pdb_
807
807
print ("Warning: ASH Fragment has no PDB-file topology defined (required for PDB-file writing)" )
808
808
print ("Now defining new topology from scratch" )
809
809
if pdb_topology is None :
810
- self .define_topology () #Creates self.pdb_topology
810
+ self .define_topology (resname = resname ) #Creates self.pdb_topology
811
811
else :
812
812
print ("Using pdbtopology found in ASH fragment" )
813
813
@@ -4043,13 +4043,29 @@ def bounding_box_dimensions(coordinates,shift=0.0):
4043
4043
final_dims = dimensions + shift
4044
4044
return dimensions # Return the dimensions of the bounding box
4045
4045
4046
+ # Combien and place 2 fragments
4047
+ def combine_and_place_fragments (ref_frag , trans_frag ):
4048
+
4049
+ for displacement in [0.0 , 2.0 , 4.0 , 6.0 ,8.0 ,10.0 ,12.0 ,14.0 ]:
4050
+ #Translating 2nd frag by displacement in
4051
+ trans_frag .coords [:,- 1 ] += displacement
4052
+ members = get_molecule_members_loop_np2 (np .vstack ((ref_frag .coords ,trans_frag .coords )), ref_frag .elems + trans_frag .elems ,
4053
+ 10 , 1.0 , 0.4 , atomindex = 0 , membs = None )
4054
+ if len (members ) == ref_frag .numatoms :
4055
+ print ("Molecules are sufficiently far apart" )
4056
+ break
4057
+
4058
+ combined_solute = Fragment (elems = ref_frag .elems + trans_frag .elems , coords = np .vstack ((ref_frag .coords ,trans_frag .coords )),
4059
+ printlevel = 2 )
4060
+ return combined_solute
4061
+
4046
4062
4047
4063
#Simple function to combine 2 ASH fragments where one is assumed to be a solute (fewer atoms) and the other assumed to be
4048
4064
#some kind of solvent system (box,sphere etc.)
4049
4065
#Use tolerance (tol) e.g. to control how many solvent molecules around get deleted
4050
4066
#Currently using 0.4 as default based on threonine in acetonitrile example
4051
- def insert_solute_into_solvent (solute = None , solvent = None , scale = 1.0 , tol = 0.4 , write_pdb = False , write_solute_connectivity = True ,
4052
- solute_pdb = None , solvent_pdb = None , outputname = "solution.pdb" , write_PBC_info = True ):
4067
+ def insert_solute_into_solvent (solute = None , solute2 = None , solvent = None , scale = 1.0 , tol = 0.4 , write_pdb = False , write_solute_connectivity = True ,
4068
+ solute_pdb = None , solute2_pdb = None , solvent_pdb = None , outputname = "solution.pdb" , write_PBC_info = True ):
4053
4069
print ("\n insert_solute_into_solvent\n " )
4054
4070
#Early exits
4055
4071
if write_pdb :
@@ -4060,32 +4076,63 @@ def insert_solute_into_solvent(solute=None, solvent=None, scale=1.0, tol=0.4, wr
4060
4076
if solute is None and solute_pdb is not None :
4061
4077
print ("No solute fragment provided but solute_pdb is set. Reading solute fragment from PDB-file" )
4062
4078
solute = Fragment (pdbfile = solute_pdb )
4079
+ if solute2 is None and solute2_pdb is not None :
4080
+ print ("No solute2 fragment provided but solute2_pdb is set. Reading solute2 fragment from PDB-file" )
4081
+ solute2 = Fragment (pdbfile = solute2_pdb )
4063
4082
if solvent is None and solvent_pdb is not None :
4064
4083
print ("No solvent fragment provided but solvent_pdb is set. Reading solvent fragment from PDB-file" )
4065
4084
solvent = Fragment (pdbfile = solvent_pdb )
4066
4085
4067
4086
#Get centers
4068
4087
com_box = solvent .get_coordinate_center ()
4069
- com_solute = solute .get_coordinate_center ()
4070
4088
4071
- #Translating solute coords
4072
- trans_coord = np .array (com_box )- np .array (com_solute )
4073
- solute .coords = solute .coords + trans_coord
4089
+ if solute2 is None :
4090
+ com_solute = solute .get_coordinate_center ()
4091
+ #Translating solute coords
4092
+ trans_coord = np .array (com_box )- np .array (com_solute )
4093
+ solute .coords = solute .coords + trans_coord
4094
+ else :
4095
+ #Combine and Translate solute2 so that it is close to solute1
4096
+ combined_solute = combine_and_place_fragments (ref_frag = solute , trans_frag = solute2 )
4097
+
4098
+ #COM and trans
4099
+ com_solute = combined_solute .get_coordinate_center ()
4100
+ trans_coord = np .array (com_box )- np .array (com_solute )
4101
+ #Translate combined solute fragment
4102
+ combined_solute .coords = combined_solute .coords + trans_coord
4103
+
4074
4104
4075
4105
#New Fragment by combining element lists and coordinates
4076
- new_frag = Fragment (elems = solute .elems + solvent .elems , coords = np .vstack ((solute .coords ,solvent .coords )), printlevel = 2 )
4106
+ if solute2 is None :
4107
+ print ("Combining solute and solvent" )
4108
+ new_frag = Fragment (elems = solute .elems + solvent .elems , coords = np .vstack ((solute .coords ,solvent .coords )), printlevel = 2 )
4109
+ else :
4110
+ print ("Combining combined_solute and solvent" )
4111
+ new_frag = Fragment (elems = combined_solute .elems + solvent .elems , coords = np .vstack ((combined_solute .coords ,solvent .coords )), printlevel = 2 )
4077
4112
4078
4113
new_frag .write_xyzfile (xyzfilename = "solution-pre.xyz" )
4079
4114
#Trim by removing clashing atoms
4080
4115
new_frag .printlevel = 1
4116
+
4081
4117
#Find atoms connected to solute index 0. Uses scale and tol
4082
4118
membs = get_molecule_members_loop_np2 (new_frag .coords , new_frag .elems , 20 , scale , tol , atomindex = 0 , membs = None )
4083
- print ("Found clashing solvent atoms:" , membs )
4084
4119
delatoms = []
4085
4120
for i in membs :
4086
4121
if i >= solute .numatoms :
4087
4122
delatoms .append (i )
4123
+ print ("First delatoms:" , delatoms )
4124
+ if solute2 is not None :
4125
+ membs2 = get_molecule_members_loop_np2 (new_frag .coords , new_frag .elems , 20 , scale , tol , atomindex = solute .numatoms , membs = None )
4126
+ print ("membs2:" , membs2 )
4127
+ for j in membs2 :
4128
+ if j >= solute .numatoms + solute2 .numatoms :
4129
+ if j not in delatoms :
4130
+ delatoms .append (j )
4131
+ print ("Final delatoms:" , delatoms )
4132
+
4133
+ # Deleting
4088
4134
delatoms .sort (reverse = True )
4135
+ print ("Found clashing solvent atoms:" , delatoms )
4089
4136
for d in delatoms :
4090
4137
new_frag .delete_atom (d )
4091
4138
new_frag .printlevel = 2
@@ -4113,7 +4160,18 @@ def insert_solute_into_solvent(solute=None, solvent=None, scale=1.0, tol=0.4, wr
4113
4160
4114
4161
#Create modeller object
4115
4162
modeller = openmm .app .Modeller (pdb1 .topology , pdb1 .positions ) #Add pdbfile1
4163
+
4164
+ #solute2
4165
+ if solute2 is not None :
4166
+ print ("Adding solute2" )
4167
+ pdb_solute2 = openmm .app .PDBFile (solute2_pdb )
4168
+ solute2_resname = list (pdb_solute2 .topology .residues ())[0 ].name
4169
+ print ("solute2_resname:" , solute2_resname )
4170
+ modeller .add (pdb_solute2 .topology , pdb_solute2 .positions ) #Add pdbfile2
4171
+ print ("Adding solvent" )
4116
4172
modeller .add (pdb2 .topology , pdb2 .positions ) #Add pdbfile2
4173
+
4174
+
4117
4175
#Delete clashing atoms from topology
4118
4176
toDelete = [r for j ,r in enumerate (modeller .topology .atoms ()) if j in delatoms ]
4119
4177
modeller .delete (toDelete )
0 commit comments