linting
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 2m22s
Run linting on the backend code / Build (pull_request) Successful in 43s
Run testing on the backend code / Build (pull_request) Failing after 2m23s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 24s

This commit is contained in:
2025-01-16 12:22:36 +01:00
parent e5a4645f7a
commit 7027444602
12 changed files with 176 additions and 665 deletions

View File

@@ -1,3 +1,4 @@
"""Find clusters of interest to add more general areas of visit to the tour."""
import logging
from typing import Literal
@@ -38,11 +39,24 @@ class Cluster(BaseModel):
class ClusterManager:
"""
A manager responsible for clustering points of interest, such as shops or historic sites,
to identify areas worth visiting. It uses the DBSCAN algorithm to detect clusters
based on a set of points retrieved from OpenStreetMap (OSM).
Attributes:
logger (logging.Logger): Logger for capturing relevant events and errors.
valid (bool): Indicates whether clusters were successfully identified.
all_points (list): All points retrieved from OSM, representing locations of interest.
cluster_points (list): Points identified as part of a cluster.
cluster_labels (list): Labels corresponding to the clusters each point belongs to.
cluster_type (Literal['sightseeing', 'shopping']): Type of clustering, either for sightseeing
landmarks or shopping areas.
"""
logger = logging.getLogger(__name__)
# NOTE: all points are in (lat, lon) format
valid: bool # Ensure the manager is valid (ie there are some clusters to be found)
valid: bool # Ensure the manager is valid (ie there are some clusters to be found)
all_points: list
cluster_points: list
cluster_labels: list
@@ -65,8 +79,6 @@ class ClusterManager:
Args:
bbox: The bounding box coordinates (around:radius, center_lat, center_lon).
"""
# Initialize overpass and cache
self.overpass = Overpass()
CachingStrategy.use(JSON, cacheDir=OSM_CACHE_DIR)
@@ -96,7 +108,7 @@ class ClusterManager:
if len(result.elements()) == 0 :
self.valid = False
else :
points = []
for elem in result.elements() :
@@ -126,8 +138,8 @@ class ClusterManager:
self.filter_clusters() # ValueError here sometimes. I dont know why. # Filter the clusters to keep only the largest ones.
self.valid = True
else :
self.valid = False
else :
self.valid = False
def generate_clusters(self) -> list[Landmark]:
@@ -155,7 +167,7 @@ class ClusterManager:
# Extract points belonging to the current cluster
current_cluster = self.cluster_points[self.cluster_labels == label]
# Calculate the centroid as the mean of the points
centroid = np.mean(current_cluster, axis=0)
@@ -205,7 +217,7 @@ class ClusterManager:
selectors.append('"shop"="mall"')
new_name = 'Shopping Area'
t = 40
else :
else :
new_name = 'Neighborhood'
t = 15
@@ -214,7 +226,7 @@ class ClusterManager:
osm_id = 0
osm_type = 'node'
for sel in selectors :
for sel in selectors :
query = overpassQueryBuilder(
bbox = bbox,
elementType = ['node', 'way', 'relation'],
@@ -233,11 +245,11 @@ class ClusterManager:
location = (elem.centerLat(), elem.centerLon())
# Skip if element has neither name or location
if elem.tag('name') is None :
if elem.tag('name') is None :
continue
if location[0] is None :
if location[0] is None :
location = (elem.lat(), elem.lon())
if location[0] is None :
if location[0] is None :
continue
d = get_distance(cluster.centroid, location)
@@ -245,14 +257,14 @@ class ClusterManager:
min_dist = d
new_name = elem.tag('name')
osm_type = elem.type() # Add type: 'way' or 'relation'
osm_id = elem.id() # Add OSM id
osm_id = elem.id() # Add OSM id
# Add english name if it exists
try :
new_name_en = elem.tag('name:en')
except:
pass
except Exception:
pass
return Landmark(
name=new_name,
type=self.cluster_type,
@@ -290,4 +302,3 @@ class ClusterManager:
# update the cluster points and labels with the filtered data
self.cluster_points = np.vstack(filtered_cluster_points) # ValueError here
self.cluster_labels = np.concatenate(filtered_cluster_labels)