Yanisse Graïne
Yanisse Graïne

Reputation: 1

Jump angle computation in Python

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.
jump angles

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

Answers (1)

lastchance
lastchance

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

Related Questions