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

Merge branch '27-add-link-interpolation' into 'develop'

Resolve "Add link interpolation"

Closes #27

See merge request !22
parents cf60707b 1a1c63d9
No related branches found
No related tags found
2 merge requests!22Resolve "Add link interpolation",!13Draft: Develop
import numbers import numbers
import random import random
from copy import copy
import pandas as pd import pandas as pd
import numpy as np import numpy as np
...@@ -8,7 +9,7 @@ from scipy.interpolate import interp1d ...@@ -8,7 +9,7 @@ from scipy.interpolate import interp1d
from skais.utils.geography import great_circle, position_from_distance, get_coord from skais.utils.geography import great_circle, position_from_distance, get_coord
from skais.ais.ais_points import AISPoints from skais.ais.ais_points import AISPoints
from skais.utils.geometry import bresenham from skais.utils.geometry import bresenham, dist_on_grid
@jit(nopython=True) @jit(nopython=True)
...@@ -130,22 +131,9 @@ def generate_points(data, positions, height, width, node_size, lower_lat, upper_ ...@@ -130,22 +131,9 @@ def generate_points(data, positions, height, width, node_size, lower_lat, upper_
data[x, y] = [1] data[x, y] = [1]
@jit(nopython=True)
def generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon):
lon, lat = positions[0, 0], positions[0, 1]
for longitude, latitude in positions[1:]:
x_prv, y_prev = get_coord(lat, lon, height, width, lower_lat, upper_lat, lower_lon, upper_lon)
x_nxt, y_nxt = get_coord(latitude, longitude, height, width, lower_lat, upper_lat, lower_lon,
upper_lon)
lon, lat = longitude, latitude
for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt):
data[x, y] = [1]
@jit(nopython=True) @jit(nopython=True)
def generate_points_with_features(data, positions, features_vectors, bounds, node_size, height, width, def generate_points_with_features(data, positions, features_vectors, bounds, node_size, height, width,
lower_lat, upper_lat, lower_lon, upper_lon, link): lower_lat, upper_lat, lower_lon, upper_lon):
for pos, f in zip(positions, features_vectors): for pos, f in zip(positions, features_vectors):
latitude = pos[1] latitude = pos[1]
longitude = pos[0] longitude = pos[0]
...@@ -162,21 +150,46 @@ def generate_points_with_features(data, positions, features_vectors, bounds, nod ...@@ -162,21 +150,46 @@ def generate_points_with_features(data, positions, features_vectors, bounds, nod
for y in range(y_lower_bound, y_upper_bound + 1): for y in range(y_lower_bound, y_upper_bound + 1):
for i, v in enumerate(value): for i, v in enumerate(value):
data[x, y, i] = v data[x, y, i] = v
if link:
lon, lat = positions[0, 0], positions[0, 1]
@jit(nopython=True)
value = __get_image_value__(features_vectors[0], bounds) def generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon, values, interpolate=None):
for pos, f in zip(positions[1:], features_vectors[1:]): lon, lat = positions[0, 0], positions[0, 1]
latitude = pos[1]
longitude = pos[0] current_value = values[0]
x_prv, y_prev = get_coord(lat, lon, height, width, lower_lat, upper_lat, lower_lon, upper_lon) for pos, nxt_value in zip(positions[1:], values[1:]):
x_nxt, y_nxt = get_coord(latitude, longitude, height, width, lower_lat, upper_lat, lower_lon, latitude = pos[1]
upper_lon) longitude = pos[0]
lon, lat = longitude, latitude x_prv, y_prev = get_coord(lat, lon, height, width, lower_lat, upper_lat, lower_lon, upper_lon)
x_nxt, y_nxt = get_coord(latitude, longitude, height, width, lower_lat, upper_lat, lower_lon,
upper_lon)
lon, lat = longitude, latitude
if interpolate is not None and nxt_value != current_value:
dist = dist_on_grid(x_prv, y_prev, x_nxt, y_nxt)
for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt): for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt):
for i, v in enumerate(value): dist_prev = dist_on_grid(x_prv, y_prev, x, y)
data[x, y, i] = v dist_next = dist_on_grid(x, y, x_nxt, y_nxt)
value = __get_image_value__(f, bounds)
pixel_color = current_value * (1-dist_prev/dist) + nxt_value * (1-dist_next/dist)
for i in range(len(pixel_color)):
data[x, y, i] = pixel_color[i]
else:
for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt):
for i in range(len(current_value)):
data[x, y, i] = current_value[i]
current_value = nxt_value
@jit(nopython=True)
def generate_values(features_vectors, bounds):
result = np.zeros(features_vectors.shape)
for i in range(len(features_vectors)):
features = features_vectors[i]
value = __get_image_value__(features, bounds)
for j in range(len(value)):
v = value[j]
result[i, j] = v
return result
class AISTrajectory(AISPoints): class AISTrajectory(AISPoints):
...@@ -346,7 +359,7 @@ class AISTrajectory(AISPoints): ...@@ -346,7 +359,7 @@ class AISTrajectory(AISPoints):
return result return result
def generate_array_from_positions(self, height=256, width=256, link=True, bounding_box='fit', ref_index=-1, def generate_array_from_positions(self, height=256, width=256, link=True, bounding_box='fit', ref_index=-1,
features=None, node_size=0): features=None, node_size=0, interpolation=None):
positions = self.df[['longitude', 'latitude']].to_numpy() positions = self.df[['longitude', 'latitude']].to_numpy()
...@@ -371,18 +384,23 @@ class AISTrajectory(AISPoints): ...@@ -371,18 +384,23 @@ class AISTrajectory(AISPoints):
if features_vectors is not None: if features_vectors is not None:
nb_channels = len(features_vectors.T) nb_channels = len(features_vectors.T)
bounds = np.array(bounds)
else: else:
nb_channels = 1 nb_channels = 1
data = np.zeros((height, width, nb_channels), dtype=np.float) data = np.zeros((height, width, nb_channels), dtype=float)
if features_vectors is None: if features_vectors is None:
generate_points(data, positions, height, width, node_size, lower_lat, upper_lat, lower_lon, upper_lon) generate_points(data, positions, height, width, node_size, lower_lat, upper_lat, lower_lon, upper_lon)
if link: if link:
generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon) generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon,
np.ones((len(positions), 1)))
else: else:
generate_points_with_features(data, positions, features_vectors, np.array(bounds), node_size, height, width, generate_points_with_features(data, positions, features_vectors, np.array(bounds), node_size, height, width,
lower_lat, upper_lat, lower_lon, upper_lon, link) lower_lat, upper_lat, lower_lon, upper_lon, )
if link:
generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon,
generate_values(features_vectors, bounds), interpolation)
return data return data
...@@ -651,4 +651,32 @@ class TestAISTrajectoryImageGeneration(unittest.TestCase): ...@@ -651,4 +651,32 @@ class TestAISTrajectoryImageGeneration(unittest.TestCase):
[[0.25, 1], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [[0.25, 1], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0.25, 0.5], [0.5, 0.25]]]) [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0.25, 0.5], [0.5, 0.25]]])
np.testing.assert_array_equal(result, expected) np.testing.assert_array_equal(result, expected)
\ No newline at end of file
def test_generate_array_interpolate_links(self):
trajectory = AISTrajectory(
pd.DataFrame(
{
"latitude": [0, 10, 0, 20],
"longitude": [0, 10, 20, 20],
"ts_sec": [i for i in range(4)],
"sog": [10, 10, 20, 40]
}
)
)
result = trajectory.generate_array_from_positions(height=9, width=18, link=True, bounding_box='fit',
features={"sog": (0, 80)}, node_size=0,
interpolation='linear').reshape((9, 18))
print(result)
expected = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.46875],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4375],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.40625],
[0, 0, 0, 0, 0, 0, 0, 0.125, 0.125, 0.13526987, 0, 0, 0, 0, 0, 0, 0, 0.375],
[0, 0, 0, 0, 0, 0.125, 0.125, 0, 0, 0, 0.15330406, 0.16458619, 0, 0, 0, 0, 0, 0.34375],
[0, 0, 0, 0.125, 0.125, 0, 0, 0, 0, 0, 0, 0, 0.18154526, 0.19313327, 0, 0, 0, 0.3125],
[0, 0.125, 0.125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20959047, 0.22158235, 0, 0.28125],
[0.125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.23609719, 0.25]])
np.testing.assert_array_almost_equal(result, expected)
import numpy as np
from numba import jit from numba import jit
@jit(nopython=True)
def dist_on_grid(x1, y1, x2, y2):
dx = int(x2 - x1)
dy = int(y2 - y1)
return np.sqrt(dx ** 2 + dy ** 2)
@jit(nopython=True) @jit(nopython=True)
def bresenham(x1, y1, x2, y2): def bresenham(x1, y1, x2, y2):
...@@ -12,9 +19,8 @@ def bresenham(x1, y1, x2, y2): ...@@ -12,9 +19,8 @@ def bresenham(x1, y1, x2, y2):
if dy < 0: if dy < 0:
sy = -1 sy = -1
pixels = [] pixels = []
if abs(dx) > abs(dy): # slope < 1 if abs(dx) > abs(dy): # slope < 1
if x1 > x2: if x1 > x2:
tmp = x2 tmp = x2
x2 = x1 x2 = x1
...@@ -28,7 +34,7 @@ def bresenham(x1, y1, x2, y2): ...@@ -28,7 +34,7 @@ def bresenham(x1, y1, x2, y2):
y = y1 y = y1
p = (2 * abs(dy)) - abs(dx) p = (2 * abs(dy)) - abs(dx)
pixels.append((x1, y1)) pixels.append((x1, y1))
for x in range(x1 + 1, x2 + 1): for x in range(x1 + 1, x2 + 1):
if p < 0: if p < 0:
p += 2 * abs(dy) p += 2 * abs(dy)
...@@ -36,7 +42,7 @@ def bresenham(x1, y1, x2, y2): ...@@ -36,7 +42,7 @@ def bresenham(x1, y1, x2, y2):
y += sy y += sy
p += (2 * abs(dy)) - (2 * abs(dx)) p += (2 * abs(dy)) - (2 * abs(dx))
pixels.append((x, y)) pixels.append((x, y))
else: # slope >= 1 else: # slope >= 1
if y1 > y2: if y1 > y2:
tmp = x2 tmp = x2
x2 = x1 x2 = x1
...@@ -59,4 +65,3 @@ def bresenham(x1, y1, x2, y2): ...@@ -59,4 +65,3 @@ def bresenham(x1, y1, x2, y2):
pixels.append((x, y)) pixels.append((x, y))
return pixels return pixels
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment