Skip to content

Commit

Permalink
Fix #271
Browse files Browse the repository at this point in the history
  • Loading branch information
2320sharon committed Jul 10, 2024
1 parent 14be0da commit 4c7d053
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 11 deletions.
16 changes: 6 additions & 10 deletions src/coastseg/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,7 @@ def export_dataframe_as_geojson(data:pd.DataFrame, output_file_path:str, x_col:s
def create_complete_line_string(points):
"""
Create a complete LineString from a list of points.
If there is only a single point in the list, a Point object is returned instead of a LineString.
Args:
points (numpy.ndarray): An array of points representing the coordinates.
Expand Down Expand Up @@ -1653,6 +1654,9 @@ def create_complete_line_string(points):
current_point = nearest_point

# Convert the sorted list of points to a LineString
if len(sorted_points) < 2:
return Point(sorted_points[0])

return LineString(sorted_points)

def order_linestrings_gdf(gdf,dates, output_crs='epsg:4326'):
Expand Down Expand Up @@ -1682,6 +1686,7 @@ def order_linestrings_gdf(gdf,dates, output_crs='epsg:4326'):
lines.append(line_string)

gdf = gpd.GeoDataFrame({'geometry': lines,'date': dates},crs=output_crs)

return gdf


Expand Down Expand Up @@ -1731,9 +1736,7 @@ def add_shore_points_to_timeseries(timeseries_data: pd.DataFrame,
shore_y_utm = first[1]+distances*np.sin(angle)
# points_utm = [shapely.Point(xy) for xy in zip(shore_x_utm, shore_y_utm)]

# #conversion from utm to wgs84, put them in the transect_timeseries csv and utm gdf
# dummy_gdf_utm = gpd.GeoDataFrame({'geometry':points_utm},
# crs=utm_crs)
#conversion from utm to wgs84, put them in the transect_timeseries csv and utm gdf
points_utm = gpd.GeoDataFrame({'geometry': [Point(x, y) for x, y in zip(shore_x_utm, shore_y_utm)]}, crs=utm_crs)
# Convert shore points to WGS84
points_wgs84 = points_utm.to_crs(org_crs)
Expand All @@ -1743,13 +1746,6 @@ def add_shore_points_to_timeseries(timeseries_data: pd.DataFrame,
# Update timeseries data with shore_x and shore_y
timeseries_data.loc[idx, 'shore_x'] = coords_wgs84[:, 0]
timeseries_data.loc[idx, 'shore_y'] = coords_wgs84[:, 1]
# points_wgs84 = [shapely.get_coordinates(p) for p in dummy_gdf_wgs84.geometry]
# points_wgs84 = np.array(points_wgs84)
# points_wgs84 = points_wgs84.reshape(len(points_wgs84),2)
# x_wgs84 = points_wgs84[:,0]
# y_wgs84 = points_wgs84[:,1]
# timeseries_data.loc[idxes,'shore_x'] = x_wgs84
# timeseries_data.loc[idxes,'shore_y'] = y_wgs84

return timeseries_data

Expand Down
101 changes: 100 additions & 1 deletion tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,87 @@
from typing import Dict, List, Union
from unittest.mock import patch

def test_order_linestrings_gdf_empty():
gdf = gpd.GeoDataFrame({'geometry': []})
dates = []
result = common.order_linestrings_gdf(gdf, dates)
assert result.empty, "Expected an empty GeoDataFrame for empty input"

def test_order_linestrings_gdf_single_linestring():
points = np.array([[0, 0], [1, 1]])
gdf = gpd.GeoDataFrame({'geometry': [LineString(points)]}, crs='epsg:4326')
dates = ['2023-01-01']
result = common.order_linestrings_gdf(gdf, dates)
expected_line = common.create_complete_line_string(points)
assert len(result) == 1, "Expected one linestring in the result"
assert result.iloc[0].geometry.equals(expected_line), "The geometry of the linestring is incorrect"
assert result.iloc[0].date == '2023-01-01', "The date is incorrect"

def test_order_linestrings_gdf_multiple_linestrings():
points1 = np.array([[0, 0], [1, 1]])
points2 = np.array([[1, 1], [2, 2]])
gdf = gpd.GeoDataFrame({'geometry': [LineString(points1), LineString(points2)]}, crs='epsg:4326')
dates = ['2023-01-01', '2023-01-02']
result = common.order_linestrings_gdf(gdf, dates)
expected_line1 = common.create_complete_line_string(points1)
expected_line2 = common.create_complete_line_string(points2)
assert len(result) == 2, "Expected two linestrings in the result"
assert result.iloc[0].geometry.equals(expected_line1), "The geometry of the first linestring is incorrect"
assert result.iloc[1].geometry.equals(expected_line2), "The geometry of the second linestring is incorrect"
assert result.iloc[0].date == '2023-01-01', "The first date is incorrect"
assert result.iloc[1].date == '2023-01-02', "The second date is incorrect"

# def test_order_linestrings_gdf_crs_conversion():
# points = np.array([[0, 0], [1, 1]])
# gdf = gpd.GeoDataFrame({'geometry': [LineString(points)]}, crs='epsg:3857')
# dates = ['2023-01-01']
# result = common.order_linestrings_gdf(gdf, dates, output_crs='epsg:4326')
# assert result.crs.to_string() == 'epsg:4326', "The CRS is not converted to 'epsg:4326'"

def test_order_linestrings_gdf_duplicate_points():
points = np.array([[0, 0], [1, 1], [1, 1], [2, 2]])
gdf = gpd.GeoDataFrame({'geometry': [LineString(points)]}, crs='epsg:4326')
dates = ['2023-01-01']
result = common.order_linestrings_gdf(gdf, dates)
expected_line = common.create_complete_line_string(points)
assert len(result) == 1, "Expected one linestring in the result"
assert result.iloc[0].geometry.equals(expected_line), "The geometry of the linestring is incorrect"
assert result.iloc[0].date == '2023-01-01', "The date is incorrect"


def test_no_points():
points = np.array([])
result = common.create_complete_line_string(points)
assert result is None, "Expected None for no points"

def test_single_point():
points = np.array([[1, 1]])
result = common.create_complete_line_string(points)
assert isinstance(result, Point), "Expected Point for a single point"
assert result.x == 1 and result.y == 1, "Expected Point with coordinates (1,1)"

def test_multiple_points_straight_line():
points = np.array([[0, 0], [1, 1], [2, 2]])
result = common.create_complete_line_string(points)
assert isinstance(result, LineString), "Expected LineString for multiple points"
expected_coords = [(0, 0), (1, 1), (2, 2)]
assert list(result.coords) == expected_coords, "Expected coordinates to be in a straight line"

def test_multiple_points_non_straight_line():
points = np.array([[0, 0], [2, 2], [1, 1], [3, 3]])
result = common.create_complete_line_string(points)
assert isinstance(result, LineString), "Expected LineString for multiple points"
expected_coords = [(0, 0), (1, 1), (2, 2), (3, 3)]
assert list(result.coords) == expected_coords, "Expected coordinates to be in a sorted line"

def test_duplicate_points():
points = np.array([[0, 0], [1, 1], [1, 1], [2, 2]])
result = common.create_complete_line_string(points)
assert isinstance(result, LineString), "Expected LineString for multiple points"
expected_coords = [(0, 0), (1, 1), (2, 2)]
assert list(result.coords) == expected_coords, "Expected coordinates to be unique and sorted"


def test_get_missing_roi_dirs():
roi_settings = {
"mgm8": {
Expand Down Expand Up @@ -2236,4 +2317,22 @@ def test_convert_points_to_linestrings_not_enough_pts():
linestrings_gdf = convert_points_to_linestrings(gdf, output_crs=output_crs)

# Check the result
assert len(linestrings_gdf) == 0
assert len(linestrings_gdf) == 0

def test_convert_points_to_linestrings_single_point_per_date():
# Create a GeoDataFrame with points
points = [Point(0, 0), Point(1, 1)]
gdf = gpd.GeoDataFrame(geometry=points,)
# this should cause the last point to be filtered out because it doesn't have a another points with a matching date
gdf['date'] = ['1/1/2020','1/1/2020']


# Set an initial CRS
gdf.crs = "EPSG:4326"

# Convert points to LineStrings with a different CRS
output_crs = "EPSG:3857"
linestrings_gdf = convert_points_to_linestrings(gdf, output_crs=output_crs)

# Check the result
assert len(linestrings_gdf) == 1

0 comments on commit 4c7d053

Please sign in to comment.