@@ -118,7 +118,7 @@ def get_residue_axes(self, data_container, index: int, residue=None):
118118
119119 uas = residue .select_atoms ("mass 2 to 999" )
120120 ua_masses = self .get_UA_masses (residue )
121-
121+ print ( f"The edge atoms: { edge_atom_set } " )
122122 if len (edge_atom_set ) == 0 :
123123 # No UAS are bonded to other residues
124124 # Use a custom principal axes, from a MOI tensor that uses positions of
@@ -132,7 +132,7 @@ def get_residue_axes(self, data_container, index: int, residue=None):
132132 )
133133 rot_axes , moment_of_inertia = self .get_custom_principal_axes (moi_tensor )
134134 trans_axes = rot_axes # per original convention
135- center = np .array (residue .center_of_mass ())
135+ rot_center = np .array (residue .center_of_mass ())
136136 else :
137137 # If bonded to other residues, use local axes.
138138 make_whole (data_container .atoms )
@@ -169,17 +169,20 @@ def get_residue_axes(self, data_container, index: int, residue=None):
169169 backbone = self .get_chain (residue , edge_atom_set [0 ], edge_atom_set [1 ])
170170 # get edge atoms of the residue
171171 # for terminal residues, this will include the C/N terminus
172- center = np .array (backbone .center_of_mass ())
173- rot_axes = self .get_residue_custom_axes (edges , center )
172+ backbone_center = np .zeros (3 )
173+ for heavy_atom in backbone :
174+ backbone_center += heavy_atom .position
175+ backbone_center = backbone_center / len (backbone )
176+ rot_center , rot_axes = self .get_residue_custom_axes (edges , backbone_center )
174177
175178 moment_of_inertia = self .get_custom_residue_moment_of_inertia (
176- center_of_mass = center ,
179+ center_of_mass = rot_center ,
177180 positions = uas .positions ,
178181 masses = ua_masses ,
179182 custom_rot_axes = rot_axes ,
180183 dimensions = data_container .dimensions [:3 ],
181184 )
182- return trans_axes , rot_axes , center , moment_of_inertia
185+ return trans_axes , rot_axes , rot_center , moment_of_inertia
183186
184187 def get_UA_axes (self , data_container , index : int , res_position ):
185188 """Compute united-atom-level translational and rotational axes.
@@ -287,8 +290,13 @@ def get_UA_axes(self, data_container, index: int, res_position):
287290 edges = [first_edge .atoms [0 ], last ]
288291 backbone = self .get_chain (residue , first_edge .atoms [0 ], last )
289292
290- trans_center = np .array (backbone .center_of_mass ())
291- trans_axes = self .get_residue_custom_axes (edges , trans_center )
293+ backbone_center = np .zeros (3 )
294+ for heavy_atom in backbone :
295+ backbone_center += heavy_atom .position
296+ backbone_center = backbone_center / len (backbone )
297+ trans_center , trans_axes = self .get_residue_custom_axes (
298+ edges , backbone_center
299+ )
292300
293301 residue_heavy_atoms = residue .atoms .select_atoms ("mass 2 to 999" )
294302 # look for heavy atoms in residue of interest
@@ -338,49 +346,45 @@ def get_residue_custom_axes(self, edges, center):
338346 """
339347 Compute rotation axes at the residue level, given
340348 two edge atoms of the residue (E1+E2),
341- and the rotation centre (O).
349+ and the centre of geometry of backbone atoms
350+ that are not edges (C).
342351 - x axis is O-E1
343- - y axis is O-Q (perpendicular to O-E1 in the
352+ - y axis is O-C (perpendicular to O-E1 in the
344353 same plane as E2)
345354 - z axis is perpendicular to the two other axes
346355
347- Q --- E2
348- | |
349- | |
350- E1 ---- O --- P
356+ C
357+ |
358+ |
359+ E1 ---- O --- E2
351360 Args:
352361 edges: (2,3) positions of two edge atoms
353- center: (3,) coordinates of the rotation centre
362+ center: (3,) coordinates of the inner backbone
363+ centre of geometry
354364 Returns:
365+ rot_center: (3,) rotation centre --
366+ it lies on the E1-E2 vector
355367 rot_axes: (3,3) rotation axes of residue
356368 """
357369 # x axis is O-E1
358- E1O_vector = center - edges [0 ].position
359- x_axis = - E1O_vector
360- # y axis is perpendicular to x
361- # in the same plane as E2
362- # look for projection of E1-E2 on E1-O (E1-P)
370+ E1C_vector = center - edges [0 ].position
371+ # look for projection of E1-O onto E1-E2 (E1-C)
363372 E1E2_vector = edges [1 ].position - edges [0 ].position
364- projection = (
365- np .dot (E1O_vector , E1E2_vector ) / (np .linalg .norm (E1O_vector ) ** 2 )
366- ) * E1O_vector
367- # get the perpendicular onto E1-O (P-E2)
368- # P-E2 = P-E1 + E1-E2
369- perpendicular = E1E2_vector - projection
370- # get the perpendicular through O (Q-O)
371- # first get P-Q diagonal through paralellogram rule
372- # P- Q = P-E2 + P-O
373- diagonal = - (projection - E1O_vector ) + perpendicular
374- # get the parallel of P-E2 through O
375- # OQ = OP + PQ
376- y_axis = (projection - E1O_vector ) + diagonal
373+ E1O_vector = (
374+ np .dot (E1E2_vector , E1C_vector ) / (np .linalg .norm (E1E2_vector ) ** 2 )
375+ ) * E1E2_vector
376+ x_axis = - E1O_vector
377+ # O-C = O-E1 + E1-C
378+ OC_vector = - E1O_vector + E1C_vector
379+ y_axis = OC_vector
377380 z_axis = np .cross (x_axis , y_axis )
378381 x_axis /= np .linalg .norm (x_axis )
379382 y_axis /= np .linalg .norm (y_axis )
380383 z_axis /= np .linalg .norm (z_axis )
381384 rot_axes = np .array ([x_axis , y_axis , z_axis ])
385+ rot_center = E1O_vector - edges [0 ].position
382386
383- return rot_axes
387+ return rot_center , rot_axes
384388
385389 def get_bonded_axes (self , system , atom , dimensions : np .ndarray ):
386390 """Compute UA rotational axes from bonded topology around a heavy atom.
@@ -906,6 +910,8 @@ def get_chain(self, residue, first, last):
906910 chain .append (current )
907911 chain_indices .append (current .index - residue .atoms .indices [0 ])
908912 chain_indices = np .flip (chain_indices )
913+ # only get in between residues
914+ chain_indices = chain_indices [1 :- 1 ]
909915 # accout for in-residue index
910916 chain_AtomGroup = residue .atoms [chain_indices ]
911917 chain = chain_AtomGroup .atoms .select_atoms ("all" )
0 commit comments