Skip to content
Snippets Groups Projects
Commit a489bfa5 authored by Raphael Sturgis's avatar Raphael Sturgis
Browse files

Ais trajectory shifting

parent aac48af1
No related branches found
No related tags found
2 merge requests!12version 0.2a,!10Resolve "Image creation bugs with 0 size windows"
...@@ -3,3 +3,6 @@ build/ ...@@ -3,3 +3,6 @@ build/
skais.egg-info/ skais.egg-info/
*.coverage *.coverage
*__pycache__* *__pycache__*
venv/
local.*
\ No newline at end of file
import random
import pandas as pd import pandas as pd
import numpy as np import numpy as np
from numba import jit from numba import jit
from scipy.interpolate import interp1d from scipy.interpolate import interp1d
from skais.utils.geography import great_circle, position_from_distance
from skais.ais.ais_points import AISPoints from skais.ais.ais_points import AISPoints
...@@ -154,3 +157,53 @@ class AISTrajectory(AISPoints): ...@@ -154,3 +157,53 @@ class AISTrajectory(AISPoints):
index += i index += i
return result return result
def shift_trajectory_to_coordinates(self, target_coordinate=(0, 0), point_index=None, in_place=False):
if point_index is None:
point_index = random.randint(0, len(self.df.index) - 1)
df = self.df.copy()
new_df = df.copy()
new_df['latitude'].iat[point_index] = target_coordinate[0]
new_df['longitude'].iat[point_index] = target_coordinate[1]
new_point = target_coordinate
for i in range(point_index, 0, -1):
current_point = (df.iloc[i]['latitude'], df.iloc[i]['longitude'])
lat_dist = great_circle(current_point[0], df.iloc[i - 1]['latitude'], current_point[1], current_point[1])
long_dist = great_circle(current_point[0], current_point[0], current_point[1], df.iloc[i - 1]['longitude'])
if current_point[0] > df.iloc[i - 1]['latitude']:
lat_dist *= -1
if current_point[1] > df.iloc[i - 1]['longitude']:
long_dist *= -1
new_point = position_from_distance(new_point, (lat_dist, long_dist))
new_df['latitude'].iat[i - 1] = new_point[0]
new_df['longitude'].iat[i - 1] = new_point[1]
new_point = target_coordinate
for i in range(point_index, len(df.index) - 1):
current_point = (df.iloc[i]['latitude'], df.iloc[i]['longitude'])
lat_dist = great_circle(current_point[0], df.iloc[i + 1]['latitude'], current_point[1], current_point[1])
long_dist = great_circle(current_point[0], current_point[0], current_point[1], df.iloc[i + 1]['longitude'])
if current_point[0] > df.iloc[i + 1]['latitude']:
lat_dist *= -1
if current_point[1] > df.iloc[i + 1]['longitude']:
long_dist *= -1
new_point = position_from_distance(new_point, (lat_dist, long_dist))
new_df['latitude'].iat[i + 1] = new_point[0]
new_df['longitude'].iat[i + 1] = new_point[1]
if in_place:
self.df = new_df
return self
else:
return AISTrajectory(new_df, mmsi=self.mmsi)
...@@ -320,3 +320,41 @@ class TestAISTrajectory(unittest.TestCase): ...@@ -320,3 +320,41 @@ class TestAISTrajectory(unittest.TestCase):
def test_apply_func_on_window(self): def test_apply_func_on_window(self):
self.assertRaises(ValueError, apply_func_on_window,np.arange(10), 0, 0, 'not valid string') self.assertRaises(ValueError, apply_func_on_window,np.arange(10), 0, 0, 'not valid string')
def test_shift_trajectory_to_coordinates_no_change(self):
trajectory = AISTrajectory(
pd.DataFrame(
{
"latitude": [0, 90, 0, -90],
"longitude": [0, 90, 180, -90],
"ts_sec": [i for i in range(4)]
}
)
)
result = trajectory.shift_trajectory_to_coordinates(point_index=0)
pd.testing.assert_frame_equal(trajectory.df.reset_index(drop=True), result.df.reset_index(drop=True))
def test_shift_trajectory_to_coordinates_change_1(self):
trajectory = AISTrajectory(
pd.DataFrame(
{
"latitude": [1, 2, 3, 4],
"longitude": [1, 2, 3, 4],
"ts_sec": [i for i in range(4)]
}
)
)
result = trajectory.shift_trajectory_to_coordinates(point_index=0).df
expected = pd.DataFrame(
{
"latitude": [0, 2, 3, 4], # TBD
"longitude": [0, 1, 2, 3],
"ts_sec": [i for i in range(4)]
}
)
pd.testing.assert_frame_equal(expected.reset_index(drop=True), result.reset_index(drop=True))
\ No newline at end of file
import unittest
import numpy as np
from skais.utils.geography import position_from_distance
tol = 0.005
class TestGeography(unittest.TestCase):
def test_position_from_distance_1(self):
position = (0, 0)
distance = (10000, 10000)
expected = (0.09, 0.09)
result = position_from_distance(position, distance)
np.testing.assert_allclose(expected, result, tol)
def test_position_from_distance_2(self):
position = (10, 10)
distance = (10000, 10000)
expected = (10.0636111, 10.064722222222223)
result = position_from_distance(position, distance)
np.testing.assert_allclose(expected, result, tol)
def test_position_from_distance_3(self):
position = (75, 75)
distance = (10000, -10000)
expected = (75.0633333, 74.75333333333333)
result = position_from_distance(position, distance)
np.testing.assert_allclose(expected, result, tol)
if __name__ == '__main__':
unittest.main()
File deleted
File deleted
...@@ -2,6 +2,9 @@ from sklearn.metrics.pairwise import haversine_distances ...@@ -2,6 +2,9 @@ from sklearn.metrics.pairwise import haversine_distances
import numpy as np import numpy as np
from numba import jit from numba import jit
R = 6371000
@jit(nopython=True) @jit(nopython=True)
def great_circle(lat1, lat2, long1, long2): def great_circle(lat1, lat2, long1, long2):
x1 = np.radians(lat1) x1 = np.radians(lat1)
...@@ -9,8 +12,6 @@ def great_circle(lat1, lat2, long1, long2): ...@@ -9,8 +12,6 @@ def great_circle(lat1, lat2, long1, long2):
x2 = np.radians(lat2) x2 = np.radians(lat2)
y2 = np.radians(long2) y2 = np.radians(long2)
R = 6371000
delta_x = x2 - x1 delta_x = x2 - x1
delta_y = y2 - y1 delta_y = y2 - y1
...@@ -21,3 +22,16 @@ def great_circle(lat1, lat2, long1, long2): ...@@ -21,3 +22,16 @@ def great_circle(lat1, lat2, long1, long2):
d = R * c d = R * c
return d return d
def position_from_distance(position, distances):
lat = np.arcsin(
np.sin(np.radians(position[0])) * np.cos(distances[0] / R) + np.cos(np.radians(position[0])) * np.sin(
distances[0] / R))
long = np.radians(position[1]) + np.arctan2(
np.sin(distances[1] / R) * np.cos(np.radians(position[0])),
np.cos(distances[1] / R) - (np.sin(np.radians(position[1])) * np.sin(lat))
)
return np.degrees(lat), np.degrees(long)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment