diff --git a/docs/pages/api.rst b/docs/pages/api.rst index d4d0e1458..b4a065870 100644 --- a/docs/pages/api.rst +++ b/docs/pages/api.rst @@ -18,8 +18,8 @@ The API for the historical weather data mainly consists of the following functio - calculates the close weather stations based on the coordinates for the requested data - either selected by rank (n stations) or by distance in km - - it returns a list of station ids that can be used to download the data plus the - distances + - it returns a DataFrame with meta data, distances [in km] and station ids that can be used to download the + data plus the - **DWDStationRequest:** - a class that can combine multiple periods/date ranges for any number of stations @@ -97,18 +97,21 @@ Now, we know an approximate location, where we cant to get data for the temperat .. code-block:: Python + from datetime import datetime from wetterdienst import Parameter, PeriodType, TimeResolution from wetterdienst import get_nearby_stations get_nearby_stations( - [50., 51.4], [8.9, 9.3], + 50., 8.9, + datetime(2020, 1, 1), + datetime(2020, 1, 20), Parameter.TEMPERATURE_AIR, TimeResolution.HOURLY, PeriodType.RECENT, num_stations_nearby=1 ) -The function returns us the station ids (and distances), that we can use to get our +The function returns a meta data DataFrame, where we can find weather station ids and distances to get our observation data. .. code-block:: Python diff --git a/tests/additionals/test_geo_location.py b/tests/additionals/test_geo_location.py index 3a780d1b0..514c70c08 100644 --- a/tests/additionals/test_geo_location.py +++ b/tests/additionals/test_geo_location.py @@ -27,8 +27,8 @@ def test_get_nearby_stations(): # Test for one nearest station nearest_station = get_nearby_stations( - [50.0, 51.4], - [8.9, 9.3], + 50.0, + 8.9, datetime(2020, 1, 1), datetime(2020, 1, 20), Parameter.TEMPERATURE_AIR, @@ -36,10 +36,10 @@ def test_get_nearby_stations(): PeriodType.RECENT, num_stations_nearby=1, ) - nearest_station[0] = nearest_station[0].drop("TO_DATE", axis="columns") + nearest_station = nearest_station.drop("TO_DATE", axis="columns") pd.testing.assert_frame_equal( - nearest_station[0], + nearest_station, pd.DataFrame( [ [ @@ -70,8 +70,8 @@ def test_get_nearby_stations(): ) nearest_station = get_nearby_stations( - [50.0, 51.4], - [8.9, 9.3], + 50.0, + 8.9, datetime(2020, 1, 1), datetime(2020, 1, 20), Parameter.TEMPERATURE_AIR, @@ -79,9 +79,9 @@ def test_get_nearby_stations(): PeriodType.RECENT, max_distance_in_km=20, ) - nearest_station[0] = nearest_station[0].drop("TO_DATE", axis="columns") + nearest_station = nearest_station.drop("TO_DATE", axis="columns") pd.testing.assert_frame_equal( - nearest_station[0], + nearest_station, pd.DataFrame( [ [ @@ -135,8 +135,8 @@ def test_get_nearby_stations(): with pytest.raises(ValueError): get_nearby_stations( - [50.0, 51.4], - [8.9, 9.3], + 50.0, + 8.9, datetime(2020, 1, 1), datetime(2020, 1, 20), Parameter.TEMPERATURE_AIR, @@ -148,8 +148,8 @@ def test_get_nearby_stations(): with pytest.raises(ValueError): get_nearby_stations( - [50.0, 51.4], - [8.9, 9.3], + 51.4, + 9.3, datetime(2020, 1, 1), datetime(2020, 1, 20), Parameter.TEMPERATURE_AIR, @@ -160,8 +160,8 @@ def test_get_nearby_stations(): with pytest.raises(InvalidParameterCombination): get_nearby_stations( - [50.0, 51.4], - [8.9, 9.3], + 51.4, + 9.3, datetime(2020, 1, 1), datetime(2020, 1, 20), Parameter.SOIL, diff --git a/wetterdienst/additionals/geo_location.py b/wetterdienst/additionals/geo_location.py index 308918102..3bb288cd5 100644 --- a/wetterdienst/additionals/geo_location.py +++ b/wetterdienst/additionals/geo_location.py @@ -4,6 +4,7 @@ import numpy as np import pandas as pd +import logging from scipy.spatial import cKDTree from wetterdienst.additionals.functions import ( @@ -22,10 +23,12 @@ KM_EARTH_RADIUS = 6371 +logger = logging.getLogger(__name__) + def get_nearby_stations( - latitudes: Union[List[float], np.array], - longitudes: Union[List[float], np.array], + latitude: float, + longitude: float, minimal_available_date: Union[datetime, str], maximal_available_date: Union[datetime, str], parameter: Union[Parameter, str], @@ -33,13 +36,13 @@ def get_nearby_stations( period_type: Union[PeriodType, str], num_stations_nearby: Optional[int] = None, max_distance_in_km: Optional[float] = None, -) -> List[pd.DataFrame]: +) -> pd.DataFrame: """ Provides a list of weather station ids for the requested data Args: - latitudes: latitudes of locations to search for nearest + latitude: latitude of location to search for nearest weather station - longitudes: longitudes of locations to search for nearest + longitude: longitude of location to search for nearest weather station minimal_available_date: Start date of timespan where measurements should be available @@ -53,7 +56,7 @@ def get_nearby_stations( distance to location in km Returns: - List of DataFrames with valid Stations in radius per requested location + DataFrames with valid Stations in radius per requested location """ if (num_stations_nearby and max_distance_in_km) and ( @@ -84,13 +87,7 @@ def get_nearby_stations( f"{period_type.value} is invalid." ) - if not isinstance(latitudes, list): - latitudes = np.array(latitudes) - - if not isinstance(longitudes, list): - latitudes = np.array(longitudes) - - coords = Coordinates(latitudes, longitudes) + coords = Coordinates(np.array(latitude), np.array(longitude)) metadata = metadata_for_climate_observations( parameter, time_resolution, period_type @@ -113,35 +110,26 @@ def get_nearby_stations( # Cast to np.array required for subset indices_nearest_neighbours = np.array(cast_to_list(indices_nearest_neighbours)) distances_km = np.array(distances * KM_EARTH_RADIUS) - nearest_station_list = [] - for distances_km_location, indices_nearest_neighbours_location in zip( - distances_km, indices_nearest_neighbours - ): - # Filter for distance based on calculated distances - if max_distance_in_km: - _in_max_distance_indices = np.where( - distances_km_location <= max_distance_in_km - )[0] - indices_nearest_neighbours_location = indices_nearest_neighbours_location[ - _in_max_distance_indices - ] - distances_km_location = distances_km_location[_in_max_distance_indices] - - metadata_location = metadata.loc[ - indices_nearest_neighbours_location - if isinstance(indices_nearest_neighbours_location, (list, np.ndarray)) - else [indices_nearest_neighbours_location], - :, + # Filter for distance based on calculated distances + if max_distance_in_km: + _in_max_distance_indices = np.where( + distances_km <= max_distance_in_km)[0] + indices_nearest_neighbours = indices_nearest_neighbours[ + _in_max_distance_indices ] - metadata_location["DISTANCE_TO_LOCATION"] = distances_km_location - nearest_station_list.append(metadata_location) + distances_km = distances_km[_in_max_distance_indices] + + metadata_location = metadata.loc[ + indices_nearest_neighbours + if isinstance(indices_nearest_neighbours, (list, np.ndarray)) + else [indices_nearest_neighbours], :] + metadata_location["DISTANCE_TO_LOCATION"] = distances_km - for _idx, _nearest_stations in enumerate(nearest_station_list): - if _nearest_stations.empty: - print(f"No weather station was found for {_idx+1}. location") + if metadata_location: + logger.warning(f"No weather station was found for {_idx+1}. location") - return nearest_station_list + return metadata_location def _derive_nearest_neighbours(