1
1
import numpy as np
2
2
3
3
from luna .mol .interaction .math import atom_coordinates , centroid
4
+ from luna .util .default_values import PYMOL_INTERACTION_COLOR_AS_RGB
5
+ from luna .util import rgb2hex
6
+
7
+
8
+ NUCLEOPHILE_INTERS = ["Orthogonal multipolar" , "Parallel multipolar" , "Antiparallel multipolar" , "Tilted multipolar" , "Multipolar" ,
9
+ "Cation-nucleophile" , "Unfavorable anion-nucleophile" , "Unfavorable nucleophile-nucleophile" ]
10
+
11
+ ELECTROPHILE_INTERS = ["Orthogonal multipolar" , "Parallel multipolar" , "Antiparallel multipolar" , "Tilted multipolar" , "Multipolar" ,
12
+ "Anion-electrophile" , "Unfavorable cation-electrophile" , "Unfavorable electrophile-electrophile" ]
13
+
14
+ UNFAVORABLE_INTERS = ["Repulsive" , "Unfavorable anion-nucleophile" , "Unfavorable cation-electrophile" ,
15
+ "Unfavorable nucleophile-nucleophile" , "Unfavorable electrophile-electrophile" ]
4
16
5
17
6
18
class InteractionType ():
@@ -66,7 +78,21 @@ def src_centroid(self):
66
78
if self ._src_interacting_atms :
67
79
self ._src_centroid = centroid (atom_coordinates (self ._src_interacting_atms ))
68
80
else :
69
- self ._src_centroid = self ._src_grp .centroid
81
+ src_centroid = self ._src_grp .centroid
82
+ # Define the centroid in a nucleophile with two atoms as the position of its more electronegative atom.
83
+ # Remember that the position in the interaction object matters. We have defined that the first group is always
84
+ # the nucleophile for both dipole-dipole and ion-dipole interactions.
85
+ if self .type in NUCLEOPHILE_INTERS and len (self .src_grp .atoms ) == 2 :
86
+ dipole_atm = self .src_grp .atoms [0 ] if (self .src_grp .atoms [0 ].electronegativity
87
+ > self .src_grp .atoms [1 ].electronegativity ) else self .src_grp .atoms [1 ]
88
+ src_centroid = dipole_atm .coord
89
+ # For unfavorable multipolar interactions, it may happen that the first atom group is an electrophile as well.
90
+ elif self .type == "Unfavorable electrophile-electrophile" and len (self .src_grp .atoms ) == 2 :
91
+ dipole_atm = self .src_grp .atoms [0 ] if (self .src_grp .atoms [0 ].electronegativity
92
+ < self .src_grp .atoms [1 ].electronegativity ) else self .src_grp .atoms [1 ]
93
+ src_centroid = dipole_atm .coord
94
+
95
+ self ._src_centroid = src_centroid
70
96
return self ._src_centroid
71
97
72
98
@src_centroid .setter
@@ -82,7 +108,22 @@ def trgt_centroid(self):
82
108
if self ._trgt_interacting_atms :
83
109
self ._trgt_centroid = centroid (atom_coordinates (self ._trgt_interacting_atms ))
84
110
else :
85
- self ._trgt_centroid = self ._trgt_grp .centroid
111
+ trgt_centroid = self ._trgt_grp .centroid
112
+
113
+ # Define the centroid in an electrophile with two atoms as the position of its less electronegative atom.
114
+ # Remember that the position in the interaction object matters. We have defined that the second group is always
115
+ # the electrophile for both dipole-dipole and ion-dipole interactions.
116
+ if self .type in ELECTROPHILE_INTERS and len (self .trgt_grp .atoms ) == 2 :
117
+ dipole_atm = self .trgt_grp .atoms [0 ] if (self .trgt_grp .atoms [0 ].electronegativity
118
+ < self .trgt_grp .atoms [1 ].electronegativity ) else self .trgt_grp .atoms [1 ]
119
+ trgt_centroid = dipole_atm .coord
120
+ # For unfavorable multipolar interactions, it may happen that the second atom group is a nucleophile as well.
121
+ elif self .type == "Unfavorable nucleophile-nucleophile" and len (self .trgt_grp .atoms ) == 2 :
122
+ dipole_atm = self .trgt_grp .atoms [0 ] if (self .trgt_grp .atoms [0 ].electronegativity
123
+ > self .trgt_grp .atoms [1 ].electronegativity ) else self .trgt_grp .atoms [1 ]
124
+ trgt_centroid = dipole_atm .coord
125
+
126
+ self ._trgt_centroid = trgt_centroid
86
127
return self ._trgt_centroid
87
128
88
129
@trgt_centroid .setter
@@ -133,6 +174,34 @@ def is_intramol_interaction(self):
133
174
def is_intermol_interaction (self ):
134
175
return not self .is_intramol_interaction ()
135
176
177
+ def show_src_centroid (self ):
178
+ show_centroid = True
179
+
180
+ # Define the centroid in a nucleophile with two atoms as the position of its more electronegative atom.
181
+ # Remember that the position in the interaction object matters. We have defined that the first group is always
182
+ # the nucleophile for both dipole-dipole and ion-dipole interactions.
183
+ if self .type in NUCLEOPHILE_INTERS and len (self .src_grp .atoms ) == 2 :
184
+ show_centroid = False
185
+ # For unfavorable multipolar interactions, it may happen that the first atom group is an electrophile as well.
186
+ elif self .type == "Unfavorable electrophile-electrophile" and len (self .src_grp .atoms ) == 2 :
187
+ show_centroid = False
188
+
189
+ return show_centroid
190
+
191
+ def show_trgt_centroid (self ):
192
+ show_centroid = True
193
+
194
+ # Define the centroid in an electrophile with two atoms as the position of its less electronegative atom.
195
+ # Remember that the position in the interaction object matters. We have defined that the second group is always
196
+ # the electrophile for both dipole-dipole and ion-dipole interactions.
197
+ if self .type in ELECTROPHILE_INTERS and len (self .trgt_grp .atoms ) == 2 :
198
+ show_centroid = False
199
+ # For unfavorable multipolar interactions, it may happen that the second atom group is a nucleophile as well.
200
+ elif self .type == "Unfavorable nucleophile-nucleophile" and len (self .trgt_grp .atoms ) == 2 :
201
+ show_centroid = False
202
+
203
+ return show_centroid
204
+
136
205
def apply_refs (self ):
137
206
self .src_grp .add_interactions ([self ])
138
207
self .trgt_grp .add_interactions ([self ])
@@ -145,11 +214,45 @@ def _expand_dict(self):
145
214
for key in self ._params :
146
215
self .__dict__ [key ] = self ._params [key ]
147
216
217
+ def as_json (self ):
218
+ inter_obj = {}
219
+ inter_obj ["type" ] = self .type
220
+
221
+ inter_obj ["color" ] = rgb2hex (* PYMOL_INTERACTION_COLOR_AS_RGB .get_unnormalized_color (self .type ))
222
+ inter_obj ["is_directional" ] = self .is_directional ()
223
+ inter_obj ["is_intramol_interaction" ] = self .is_intramol_interaction ()
224
+ inter_obj ["is_intermol_interaction" ] = self .is_intermol_interaction ()
225
+
226
+ src_grp_obj = self .src_grp .as_json ()
227
+ src_grp_obj ["add_pseudo_group" ] = len (self .src_grp .atoms ) > 1
228
+ src_grp_obj ["centroid" ] = self .src_centroid .tolist ()
229
+ src_grp_obj ["show_centroid" ] = self .show_src_centroid ()
230
+
231
+ if src_grp_obj ["add_pseudo_group" ]:
232
+ src_grp_obj ["pseudo_group_name" ] = "+" .join ([a .name for a in sorted (self .src_grp .atoms )])
233
+
234
+ inter_obj ["src_grp" ] = src_grp_obj
235
+
236
+ #
237
+ # Target atom group
238
+ #
239
+ trgt_grp_obj = self .trgt_grp .as_json ()
240
+ trgt_grp_obj ["add_pseudo_group" ] = len (self .trgt_grp .atoms ) > 1
241
+ trgt_grp_obj ["centroid" ] = self .trgt_centroid .tolist ()
242
+ trgt_grp_obj ["show_centroid" ] = self .show_trgt_centroid ()
243
+
244
+ if trgt_grp_obj ["add_pseudo_group" ]:
245
+ trgt_grp_obj ["pseudo_group_name" ] = "+" .join ([a .name for a in sorted (self .trgt_grp .atoms )])
246
+
247
+ inter_obj ["trgt_grp" ] = trgt_grp_obj
248
+
249
+ return inter_obj
250
+
148
251
def __eq__ (self , other ):
149
252
"""Overrides the default implementation"""
150
253
if isinstance (self , other .__class__ ):
151
- is_equal_compounds = ((self .src_grp == other .src_grp and self .trgt_grp == other .trgt_grp ) or
152
- (self .src_grp == other .trgt_grp and self .trgt_grp == other .src_grp ))
254
+ is_equal_compounds = ((self .src_grp == other .src_grp and self .trgt_grp == other .trgt_grp )
255
+ or (self .src_grp == other .trgt_grp and self .trgt_grp == other .src_grp ))
153
256
154
257
is_equal_interactions = self .type == other .type
155
258
has_equal_params = self .params == other .params
0 commit comments