Skip to content

Commit 81d44ed

Browse files
committed
Merge branch 'feature/street' of https://github.com/mapswipe/python-mapswipe-workers into feature/street
2 parents 8593a3c + 9f2ac81 commit 81d44ed

File tree

3 files changed

+71
-39
lines changed

3 files changed

+71
-39
lines changed

mapswipe_workers/mapswipe_workers/project_types/street/project.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
build_multipolygon_from_layer_geometries,
2222
check_if_layer_has_too_many_geometries,
2323
save_geojson_to_file,
24-
multipolygon_to_wkt
24+
multipolygon_to_wkt,
2525
)
2626
from mapswipe_workers.project_types.project import BaseProject, BaseTask, BaseGroup
2727
from mapswipe_workers.utils.process_mapillary import get_image_metadata
@@ -56,7 +56,6 @@ def __init__(self, project_draft):
5656
sampling_threshold=project_draft.get("samplingThreshold", None),
5757
)
5858

59-
6059
self.imageIds = ImageMetadata["ids"]
6160
self.imageGeometries = ImageMetadata["geometries"]
6261

@@ -83,7 +82,9 @@ def validate_geometries(self):
8382
self.inputGeometriesFileName = save_geojson_to_file(
8483
self.projectId, self.geometry
8584
)
86-
layer, datasource = load_geojson_to_ogr(self.projectId, self.inputGeometriesFileName)
85+
layer, datasource = load_geojson_to_ogr(
86+
self.projectId, self.inputGeometriesFileName
87+
)
8788

8889
# check if inputs fit constraints
8990
check_if_layer_is_empty(self.projectId, layer)
@@ -97,7 +98,9 @@ def validate_geometries(self):
9798
del datasource
9899
del layer
99100

100-
logger.info(f"{self.projectId}" f" - validate geometry - " f"input geometry is correct.")
101+
logger.info(
102+
f"{self.projectId}" f" - validate geometry - " f"input geometry is correct."
103+
)
101104
wkt_geometry = multipolygon_to_wkt(multi_polygon)
102105
return wkt_geometry
103106

mapswipe_workers/mapswipe_workers/utils/process_mapillary.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,26 @@ def coordinate_download(
127127
return pd.DataFrame(downloaded_metadata)
128128

129129
target_columns = [
130-
"id", "geometry", "captured_at", "is_pano", "compass_angle", "sequence", "organization_id"
130+
"id",
131+
"geometry",
132+
"captured_at",
133+
"is_pano",
134+
"compass_angle",
135+
"sequence",
136+
"organization_id",
131137
]
132138
for col in target_columns:
133139
if col not in downloaded_metadata.columns:
134140
downloaded_metadata[col] = None
135141

136-
if downloaded_metadata.isna().all().all() == False or downloaded_metadata.empty == True:
142+
if (
143+
downloaded_metadata.isna().all().all() == False
144+
or downloaded_metadata.empty == True
145+
):
137146
downloaded_metadata = downloaded_metadata[
138-
downloaded_metadata['geometry'].apply(lambda point: point.within(polygon))
147+
downloaded_metadata["geometry"].apply(
148+
lambda point: point.within(polygon)
149+
)
139150
]
140151

141152
return downloaded_metadata
@@ -187,9 +198,7 @@ def filter_results(
187198
df = results_df.copy()
188199
if is_pano is not None:
189200
if df["is_pano"].isna().all():
190-
logger.exception(
191-
"No Mapillary Feature in the AoI has a 'is_pano' value."
192-
)
201+
logger.exception("No Mapillary Feature in the AoI has a 'is_pano' value.")
193202
return None
194203
df = df[df["is_pano"] == is_pano]
195204

@@ -220,25 +229,28 @@ def get_image_metadata(
220229
organization_id: str = None,
221230
start_time: str = None,
222231
end_time: str = None,
223-
sampling_threshold = None,
232+
sampling_threshold=None,
224233
):
225234
aoi_polygon = geojson_to_polygon(aoi_geojson)
226-
downloaded_metadata = coordinate_download(
227-
aoi_polygon, level, attempt_limit
228-
)
235+
downloaded_metadata = coordinate_download(aoi_polygon, level, attempt_limit)
229236
downloaded_metadata = downloaded_metadata[
230-
downloaded_metadata['geometry'].apply(lambda geom: isinstance(geom, Point))
237+
downloaded_metadata["geometry"].apply(lambda geom: isinstance(geom, Point))
231238
]
232239

233240
downloaded_metadata = filter_results(
234241
downloaded_metadata, is_pano, organization_id, start_time, end_time
235242
)
236243
if sampling_threshold is not None:
237244
downloaded_metadata = spatial_sampling(downloaded_metadata, sampling_threshold)
238-
if downloaded_metadata.isna().all().all() == False or downloaded_metadata.empty == False:
245+
if (
246+
downloaded_metadata.isna().all().all() == False
247+
or downloaded_metadata.empty == False
248+
):
239249
if len(downloaded_metadata) > 100000:
240-
err = (f"Too many Images with selected filter "
241-
f"options for the AoI: {len(downloaded_metadata)}")
250+
err = (
251+
f"Too many Images with selected filter "
252+
f"options for the AoI: {len(downloaded_metadata)}"
253+
)
242254
raise ValueError(err)
243255
else:
244256
return {

mapswipe_workers/mapswipe_workers/utils/spatial_sampling.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from shapely import wkt
44
from shapely.geometry import Point
55

6+
67
def distance_on_sphere(p1, p2):
78
"""
89
p1 and p2 are two lists that have two elements. They are numpy arrays of the long and lat
@@ -30,13 +31,19 @@ def distance_on_sphere(p1, p2):
3031
delta_lat = p2[1] - p1[1]
3132
delta_long = p2[0] - p1[0]
3233

33-
a = np.sin(delta_lat / 2) ** 2 + np.cos(p1[1]) * np.cos(p2[1]) * np.sin(delta_long / 2) ** 2
34+
a = (
35+
np.sin(delta_lat / 2) ** 2
36+
+ np.cos(p1[1]) * np.cos(p2[1]) * np.sin(delta_long / 2) ** 2
37+
)
3438
c = 2 * np.arcsin(np.sqrt(a))
3539

3640
distances = earth_radius * c
3741
return distances
3842

43+
3944
"""-----------------------------------Filtering Points------------------------------------------------"""
45+
46+
4047
def filter_points(df, threshold_distance):
4148
"""
4249
Filter points from a DataFrame based on a threshold distance.
@@ -61,31 +68,37 @@ def filter_points(df, threshold_distance):
6168
lat = df["lat"].to_numpy()
6269
long = df["long"].to_numpy()
6370

64-
65-
distances = distance_on_sphere([long[1:],lat[1:]],
66-
[long[:-1],lat[:-1]])
71+
distances = distance_on_sphere([long[1:], lat[1:]], [long[:-1], lat[:-1]])
6772
road_length = np.sum(distances)
6873

69-
#save the last point if the road segment is relavitely small (< 2*road_length)
74+
# save the last point if the road segment is relavitely small (< 2*road_length)
7075
if threshold_distance <= road_length < 2 * threshold_distance:
7176
mask[-1] = True
7277

7378
accumulated_distance = 0
7479
for i, distance in enumerate(distances):
7580
accumulated_distance += distance
7681
if accumulated_distance >= threshold_distance:
77-
mask[i+1] = True
82+
mask[i + 1] = True
7883
accumulated_distance = 0 # Reset accumulated distance
7984

8085
to_be_returned_df = df[mask]
8186
# since the last point has to be omitted in the vectorized distance calculation, it is being checked manually
8287
p2 = to_be_returned_df.iloc[0]
83-
distance = distance_on_sphere([float(p2["long"]),float(p2["lat"])],[long[-1],lat[-1]])
84-
85-
#last point will be added if it suffices the length condition
86-
#last point will be added in case there is only one point returned
87-
if distance >= threshold_distance or len(to_be_returned_df) ==1:
88-
to_be_returned_df = pd.concat([to_be_returned_df,pd.DataFrame(df.iloc[-1],columns=to_be_returned_df.columns)],axis=0)
88+
distance = distance_on_sphere(
89+
[float(p2["long"]), float(p2["lat"])], [long[-1], lat[-1]]
90+
)
91+
92+
# last point will be added if it suffices the length condition
93+
# last point will be added in case there is only one point returned
94+
if distance >= threshold_distance or len(to_be_returned_df) == 1:
95+
to_be_returned_df = pd.concat(
96+
[
97+
to_be_returned_df,
98+
pd.DataFrame(df.iloc[-1], columns=to_be_returned_df.columns),
99+
],
100+
axis=0,
101+
)
89102
return to_be_returned_df
90103

91104

@@ -109,19 +122,23 @@ def spatial_sampling(df, interval_length):
109122
if len(df) == 1:
110123
return df
111124

112-
df['long'] = df['geometry'].apply(lambda geom: geom.x if geom.geom_type == 'Point' else None)
113-
df['lat'] = df['geometry'].apply(lambda geom: geom.y if geom.geom_type == 'Point' else None)
114-
sorted_df = df.sort_values(by=['captured_at'])
125+
df["long"] = df["geometry"].apply(
126+
lambda geom: geom.x if geom.geom_type == "Point" else None
127+
)
128+
df["lat"] = df["geometry"].apply(
129+
lambda geom: geom.y if geom.geom_type == "Point" else None
130+
)
131+
sorted_df = df.sort_values(by=["captured_at"])
115132

116133
sampled_sequence_df = pd.DataFrame()
117134

118135
# loop through each sequence
119-
for sequence in sorted_df['sequence_id'].unique():
120-
sequence_df = sorted_df[sorted_df['sequence_id'] == sequence]
121-
122-
filtered_sorted_sub_df = filter_points(sequence_df,interval_length)
123-
sampled_sequence_df = pd.concat([sampled_sequence_df,filtered_sorted_sub_df],axis=0)
124-
136+
for sequence in sorted_df["sequence_id"].unique():
137+
sequence_df = sorted_df[sorted_df["sequence_id"] == sequence]
125138

139+
filtered_sorted_sub_df = filter_points(sequence_df, interval_length)
140+
sampled_sequence_df = pd.concat(
141+
[sampled_sequence_df, filtered_sorted_sub_df], axis=0
142+
)
126143

127144
return sampled_sequence_df

0 commit comments

Comments
 (0)