def nearby_number( self, latitude: float, longitude: float, num_stations_nearby: int, ) -> pd.DataFrame: """ Wrapper for get_nearby_stations_by_number using the given parameter set. Returns nearest stations defined by number. Args: latitude: latitude in degrees longitude: longitude in degrees num_stations_nearby: number of stations to be returned, greater 0 Returns: pandas.DataFrame with station information for the selected stations """ if num_stations_nearby <= 0: raise ValueError("'num_stations_nearby' has to be at least 1.") coords = Coordinates(np.array(latitude), np.array(longitude)) metadata = self.all() metadata = metadata.reset_index(drop=True) distances, indices_nearest_neighbours = derive_nearest_neighbours( metadata.LAT.values, metadata.LON.values, coords, num_stations_nearby ) distances = pd.Series(distances) indices_nearest_neighbours = pd.Series(indices_nearest_neighbours) # If num_stations_nearby is higher then the actual amount of stations # further indices and distances are added which have to be filtered out distances = distances[: min(metadata.shape[0], num_stations_nearby)] indices_nearest_neighbours = indices_nearest_neighbours[ : min(metadata.shape[0], num_stations_nearby) ] distances_km = np.array(distances * KM_EARTH_RADIUS) metadata_location = metadata.iloc[indices_nearest_neighbours, :].reset_index( drop=True ) metadata_location[DWDMetaColumns.DISTANCE_TO_LOCATION.value] = distances_km if metadata_location.empty: logger.warning( f"No weather stations were found for coordinate " f"{latitude}°N and {longitude}°E " ) return metadata_location
def filter_by_rank( self, latitude: float, longitude: float, rank: int, ) -> StationsResult: """ Wrapper for get_nearby_stations_by_number using the given parameter set. Returns nearest stations defined by number. :param latitude: latitude in degrees :param longitude: longitude in degrees :param rank: number of stations to be returned, greater 0 :return: pandas.DataFrame with station information for the selected stations """ rank = int(rank) if rank <= 0: raise ValueError("'num_stations_nearby' has to be at least 1.") coords = Coordinates(np.array(latitude), np.array(longitude)) df = self.all().df.reset_index(drop=True) distances, indices_nearest_neighbours = derive_nearest_neighbours( df[Columns.LATITUDE.value].values, df[Columns.LONGITUDE.value].values, coords, rank, ) distances = pd.Series(distances) indices_nearest_neighbours = pd.Series(indices_nearest_neighbours) # If num_stations_nearby is higher then the actual amount of stations # further indices and distances are added which have to be filtered out distances = distances[: min(df.shape[0], rank)] indices_nearest_neighbours = indices_nearest_neighbours[ : min(df.shape[0], rank) ] distances_km = np.array(distances * EARTH_RADIUS_KM) df = df.iloc[indices_nearest_neighbours, :].reset_index(drop=True) df[Columns.DISTANCE.value] = distances_km if df.empty: log.warning( f"No weather stations were found for coordinate " f"{latitude}°N and {longitude}°E and number {rank}" ) result = StationsResult(self, df.reset_index(drop=True)) return result
def test_derive_nearest_neighbours(): coords = Coordinates(np.array([50.0, 51.4]), np.array([8.9, 9.3])) metadata = pd.read_json(METADATA_FILE) distances, indices_nearest_neighbours = derive_nearest_neighbours( metadata.LAT.values, metadata.LON.values, coords) np.testing.assert_array_almost_equal(distances, np.array([0.00182907, 0.00227919])) np.testing.assert_array_almost_equal(indices_nearest_neighbours, np.array([432, 655]))
def filter_by_rank( self, latitude: float, longitude: float, rank: int, ) -> StationsResult: """ Wrapper for get_nearby_stations_by_number using the given parameter set. Returns nearest stations_result defined by number. :param latitude: latitude in degrees :param longitude: longitude in degrees :param rank: number of stations_result to be returned, greater 0 :return: pandas.DataFrame with station information for the selected stations_result """ rank = int(rank) if rank <= 0: raise ValueError("'num_stations_nearby' has to be at least 1.") coords = Coordinates(np.array(latitude), np.array(longitude)) df = self.all().df.reset_index(drop=True) distances, indices_nearest_neighbours = derive_nearest_neighbours( df[Columns.LATITUDE.value].values, df[Columns.LONGITUDE.value].values, coords, min(rank, df.shape[0]), ) df = df.iloc[indices_nearest_neighbours.flatten(), :].reset_index( drop=True) df[Columns.DISTANCE.value] = pd.Series(distances.flatten() * EARTH_RADIUS_KM, dtype=float) if df.empty: log.warning( f"No weather stations_result were found for coordinate " f"{latitude}°N and {longitude}°E and number {rank}") return StationsResult(self, df.reset_index(drop=True))
def test_derive_nearest_neighbours(): coords = Coordinates(np.array([50.0, 51.4]), np.array([8.9, 9.3])) metadata = pd.DataFrame({ "station_id": [4371, 4373, 4411, 13904, 13965, 15207], "latitude": [52.1042, 52.8568, 49.9195, 55.0, 48.2639, 51.2835], "longitude": [8.7521, 11.1319, 8.9671, 6.3333, 8.8134, 9.359], }) distances, indices_nearest_neighbours = derive_nearest_neighbours( latitudes=metadata["latitude"].values, longitudes=metadata["longitude"].values, coordinates=coords, number_nearby=1, ) np.testing.assert_array_almost_equal(distances, np.array([[0.001594], [0.002133]])) np.testing.assert_array_almost_equal(indices_nearest_neighbours, np.array([[2], [5]]))