mirror of
https://github.com/run-llama/llama-hub.git
synced 2025-08-14 11:41:56 +00:00
127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
"""Simple reader that reads OSMmap data from overpass API"""
|
|
|
|
from typing import List,Optional,Literal
|
|
import random
|
|
import string
|
|
import warnings
|
|
from llama_index.readers.base import BaseReader
|
|
from llama_index.readers.schema.base import Document
|
|
warnings.filterwarnings('ignore')
|
|
|
|
|
|
|
|
|
|
class OpenMap(BaseReader):
|
|
"""OpenMap Reader.
|
|
|
|
Get the map Features from the overpass api(osm) for the given location/area
|
|
|
|
|
|
Args:
|
|
localarea(str) - Area or location you are seaching for
|
|
tag_values(str) - filter for the give area
|
|
search_tag(str) - Tag that you are looking for
|
|
|
|
if you not sure about the search_tag and tag_values visit https://taginfo.openstreetmap.org/tags
|
|
|
|
remove_keys(list) - list of keys that need to be removed from the response
|
|
by default following keys will be removed ['nodes','geometry','members']
|
|
|
|
"""
|
|
|
|
def __init__(self) -> None:
|
|
"""Initialize with parameters."""
|
|
super().__init__()
|
|
|
|
@staticmethod
|
|
def _get_user()->str:
|
|
# choose from all lowercase letter
|
|
letters = string.ascii_lowercase
|
|
result_str = ''.join(random.choice(letters) for i in range(10))
|
|
return result_str
|
|
|
|
@staticmethod
|
|
def _get_latlon(locarea:str,user_agent:str)->tuple:
|
|
try:
|
|
from geopy.geocoders import Nominatim
|
|
except:
|
|
raise ImportError('install geopy using `pip3 install geopy`')
|
|
|
|
geolocator = Nominatim(user_agent=user_agent)
|
|
location = geolocator.geocode(locarea)
|
|
return(location.latitude,location.longitude) if location else (None, None)
|
|
|
|
def load_data(
|
|
self,
|
|
localarea:str,
|
|
search_tag:Optional[str] = 'amenity',
|
|
remove_keys : Optional [List]= ['nodes','geometry','members'],
|
|
tag_only:Optional[bool]=True ,
|
|
tag_values:Optional[List]=[''],
|
|
local_area_buffer : Optional[int] = 2000,
|
|
) -> List[Document]:
|
|
|
|
"""
|
|
This loader will bring you the all the node values from the open street maps for the given location
|
|
|
|
Args:
|
|
|
|
localarea(str) - Area or location you are seaching for
|
|
search_tag(str) - Tag that you are looking for
|
|
if you not sure about the search_tag and tag_values visit https://taginfo.openstreetmap.org/tags
|
|
|
|
remove_keys(list) - list of keys that need to be removed from the response
|
|
by default it those keys will be removed ['nodes','geometry','members']
|
|
|
|
tag_only(bool) - if True it return the nodes which has tags if False returns all the nodes
|
|
tag_values(str) - filter for the give area
|
|
local_area_buffer(int) - range that you wish to cover (Default 2000(2km))
|
|
"""
|
|
try:
|
|
from osmxtract import overpass, location
|
|
from osmxtract.errors import OverpassBadRequest
|
|
except:
|
|
raise ImportError('install osmxtract using `pip3 install osmxtract`')
|
|
|
|
null_list=['','null','none',None]
|
|
extra_info={}
|
|
local_area=localarea
|
|
|
|
if (local_area.lower().strip() in null_list):
|
|
raise Exception('The Area should not be null')
|
|
|
|
user=self._get_user()
|
|
lat, lon = self._get_latlon(local_area,user)
|
|
try:
|
|
bounds = location.from_buffer(lat, lon, buffer_size=int(local_area_buffer))
|
|
except TypeError:
|
|
raise TypeError('Please give valid location name or check for spelling')
|
|
|
|
#overpass query generation and execution
|
|
tag_values=[str(i).lower().strip() for i in tag_values ]
|
|
query = overpass.ql_query(bounds, tag=search_tag.lower(), values=tag_values,timeout=500)
|
|
|
|
extra_info['overpass_query']=query
|
|
try:
|
|
response = overpass.request(query)
|
|
|
|
except OverpassBadRequest :
|
|
raise TypeError(f'Error while executing the Query {query} please check the Args')
|
|
|
|
res=response['elements']
|
|
|
|
_meta=response.copy()
|
|
del _meta['elements']
|
|
extra_info['overpass_meta']=str(_meta)
|
|
extra_info['lat']=lat
|
|
extra_info['lon']=lon
|
|
# filtering for only the tag values
|
|
filtered=[i for i in res if 'tags' in i.keys()] if tag_only else res
|
|
|
|
for key in remove_keys:
|
|
extras_poped =[i.pop(key,None) for i in filtered ]
|
|
if filtered:
|
|
return Document(str(filtered),extra_info=extra_info)
|
|
else:
|
|
return Document(str(res),extra_info=extra_info)
|