Skip to content

Commit

Permalink
Allow just one location to search for nearby stations
Browse files Browse the repository at this point in the history
  • Loading branch information
d.lassahn committed Sep 3, 2020
1 parent 7821f73 commit e7a7277
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 56 deletions.
11 changes: 7 additions & 4 deletions docs/pages/api.rst
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
28 changes: 14 additions & 14 deletions tests/additionals/test_geo_location.py
Expand Up @@ -27,19 +27,19 @@
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,
TimeResolution.HOURLY,
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(
[
[
Expand Down Expand Up @@ -70,18 +70,18 @@ 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,
TimeResolution.HOURLY,
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(
[
[
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
64 changes: 26 additions & 38 deletions wetterdienst/additionals/geo_location.py
Expand Up @@ -4,6 +4,7 @@

import numpy as np
import pandas as pd
import logging
from scipy.spatial import cKDTree

from wetterdienst.additionals.functions import (
Expand All @@ -22,24 +23,26 @@

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],
time_resolution: Union[TimeResolution, str],
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
Expand All @@ -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 (
Expand Down Expand Up @@ -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
Expand All @@ -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(
Expand Down

0 comments on commit e7a7277

Please sign in to comment.