Reputation: 1
I have issues to understand how to exactly compute in Python what I call a "jump angle". So basically, I have a map tracking of several tracks (of transcription factors) composed of the positions (x and y, so in 2D), and I am interested in finding the jump angle between two consecutive segments of the track (see the following figure). Edit: I changed the image, and so the representation I actually want.
I tried many things including using atan2, but this leads to wrong angle representation, at least the way I did it. So, I tried to compute it by hand, but this is not really given any good representation either. You will find just below how I compute it
def calculate_jump_angles(x_coords, y_coords):
"""Calculate the jump angles between consecutive segments in a track."""
angles = []
for i in range(len(x_coords) - 2):
vec1 = (x_coords[i+1] - x_coords[i], y_coords[i+1] - y_coords[i])
vec2 = (x_coords[i+2] - x_coords[i+1], y_coords[i+2] - y_coords[i+1])
dot_product = vec1[0] * vec2[0] + vec1[1] * vec2[1]
mag1 = np.sqrt(vec1[0]**2 + vec1[1]**2)
mag2 = np.sqrt(vec2[0]**2 + vec2[1]**2)
cos_theta = dot_product / (mag1 * mag2)
cos_theta = np.clip(cos_theta, -1.0, 1.0)
angle = np.arccos(cos_theta)
cross_product = vec1[0] * vec2[1] - vec1[1] * vec2[0]
angle = angle if cross_product >= 0 else -angle
angles.append(angle)
return angles
where x_coords
and y_coords
are respectively the x, and y coordinates of one track.
Upvotes: 0
Views: 82
Reputation: 6600
If you just want the angle between 0 and 180 deg (as suggested by your diagram) then the following gives the angle between the forward directions of successive segments. If you wish to assign a sign for the sense of the angle (clockwise or anticlockwise) then you need to define your requirements. The following code uses estimates of coordinates from your most recent diagram and has been vectorised rather than using a loop.
import numpy as np
def calculate_jump_angles(x_coords, y_coords):
dx = x_coords[1:] - x_coords[0:-1]
dy = y_coords[1:] - y_coords[0:-1]
firstx = dx[0:-1]; secondx = dx[1:]
firsty = dy[0:-1]; secondy = dy[1:]
costheta = ( firstx * secondx + firsty * secondy ) / np.sqrt( ( firstx ** 2 + firsty ** 2 ) * ( secondx ** 2 + secondy ** 2 ) )
costheta = np.clip( costheta, -1.0, 1.0 )
angles = np.arccos( costheta )
return angles
x = np.array( [ 0.0, 2.0, 3.5, 5.5, 4.0, 3.5, 5.5 ] )
y = np.array( [ 0.0, 0.0, 1.0, 0.0,-1.5,-2.7,-2.0 ] )
A = calculate_jump_angles( x, y ) * 180.0 / np.pi
print( "Angles (deg) = ", A )
Output:
Angles (deg) = [ 33.69006753 60.2551187 108.43494882 22.38013505 131.90991117]
Upvotes: 1