-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: Add Historical Weather Data Comparison #152
Changes from all commits
b04cd6f
934d174
d1ebbfb
ef293d1
8d01d4c
d734495
5e947b7
8a8e206
62f2d2f
3bc2791
ff8bebb
ec2320a
8ef8ab7
9f2a0ea
54230b1
8e735bc
1bc944a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ | |||||
Functions that make API calls stored here | ||||||
""" | ||||||
|
||||||
from datetime import datetime, timedelta | ||||||
from http import HTTPStatus | ||||||
|
||||||
import numpy as np | ||||||
|
@@ -14,6 +15,8 @@ | |||||
|
||||||
from src import helper | ||||||
|
||||||
testing = 1 | ||||||
|
||||||
|
||||||
def get_coordinates(args): | ||||||
""" | ||||||
|
@@ -90,6 +93,76 @@ | |||||
return current_uv_index | ||||||
|
||||||
|
||||||
def get_uv_history(lat, long, decimal, unit="imperial"): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Extract common API setup and error handling logic into a shared utility function There's significant duplication in API setup and error handling between get_uv_history and ocean_information_history. Consider creating a shared utility function to handle these common operations. |
||||||
""" | ||||||
Retrieve the UV index from one year ago for specified coordinates. | ||||||
|
||||||
This function accesses the Open-Meteo API to fetch the hourly UV index | ||||||
for the given latitude and longitude. It formats the result based on the | ||||||
specified decimal precision. | ||||||
|
||||||
Args: | ||||||
lat (float): Latitude of the location. | ||||||
long (float): Longitude of the location. | ||||||
decimal (int): Number of decimal places to round the output. | ||||||
unit (str): Unit of measurement ('imperial' or 'metric'). | ||||||
Defaults to 'imperial'. | ||||||
|
||||||
Returns: | ||||||
str: The historical UV index rounded to the specified decimal places, | ||||||
or an error message if no data is found. | ||||||
|
||||||
API Documentation: | ||||||
https://open-meteo.com/en/docs/air-quality-api | ||||||
""" | ||||||
# Set up the Open-Meteo API client with caching and retry on error | ||||||
cache_session = requests_cache.CachedSession(".cache", expire_after=3600) | ||||||
retry_session = retry(cache_session, retries=5, backoff_factor=0.2) | ||||||
openmeteo = openmeteo_requests.Client(session=retry_session) | ||||||
|
||||||
# Calculate the date one year ago and the current hour | ||||||
one_year_ago = datetime.now() - timedelta(days=365) | ||||||
formatted_date_one_year_ago = one_year_ago.strftime("%Y-%m-%d") | ||||||
current_hour = one_year_ago.hour | ||||||
|
||||||
# Define the API request parameters | ||||||
url = "https://air-quality-api.open-meteo.com/v1/air-quality" | ||||||
params = { | ||||||
"latitude": lat, | ||||||
"longitude": long, | ||||||
"length_unit": unit, | ||||||
"hourly": ["uv_index"], | ||||||
"start_date": formatted_date_one_year_ago, | ||||||
"end_date": formatted_date_one_year_ago, | ||||||
"timezone": "auto", | ||||||
} | ||||||
|
||||||
# For testing purposes if testing equals 1 it will continue | ||||||
if testing == 1: | ||||||
# Attempt to fetch the UV index data from the API | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (typo): Fix misleading comment in ocean_information_history This comment incorrectly refers to UV index data when the function is actually fetching ocean data. |
||||||
try: | ||||||
responses = openmeteo.weather_api(url, params=params) | ||||||
|
||||||
except ValueError: | ||||||
return "No data" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Implement consistent error handling across functions Different functions return different types on error ('No data' string vs list). Consider implementing a consistent error handling strategy that maintains return type consistency.
Suggested change
|
||||||
|
||||||
# Process the first response (assuming a single location) | ||||||
response = responses[0] | ||||||
|
||||||
# Extract hourly UV index values | ||||||
hourly = response.Hourly() | ||||||
hourly_uv_index = hourly.Variables(0).ValuesAsNumpy() | ||||||
|
||||||
else: | ||||||
hourly_uv_index = [0.5678] * 24 | ||||||
|
||||||
# Retrieve the UV index for the current hour from one year ago | ||||||
historical_uv_index = hourly_uv_index[current_hour] | ||||||
|
||||||
# Format the result to the specified decimal precision | ||||||
return f"{historical_uv_index:.{decimal}f}" | ||||||
|
||||||
|
||||||
def ocean_information(lat, long, decimal, unit="imperial"): | ||||||
""" | ||||||
Get Ocean Data at coordinates | ||||||
|
@@ -129,6 +202,84 @@ | |||||
return [current_wave_height, current_wave_direction, current_wave_period] | ||||||
|
||||||
|
||||||
def ocean_information_history(lat, long, decimal, unit="imperial"): | ||||||
""" | ||||||
Retrieve ocean data from one year ago for specified coordinates. | ||||||
|
||||||
This function accesses the Open-Meteo API to fetch | ||||||
hourly ocean data including wave height, | ||||||
direction, and period for the specified latitude | ||||||
and longitude. It formats the results based on the | ||||||
specified decimal precision. | ||||||
|
||||||
Args: | ||||||
lat (float): Latitude of the location. | ||||||
long (float): Longitude of the location. | ||||||
decimal (int): Number of decimal places to round the output. | ||||||
unit (str): Unit of measurement ('imperial' or 'metric'). | ||||||
Defaults to 'imperial'. | ||||||
|
||||||
Returns: | ||||||
list: A list containing the wave height, direction, and period rounded | ||||||
to the specified decimal places, | ||||||
or an error message if no data is found. | ||||||
|
||||||
API Documentation: | ||||||
https://open-meteo.com/en/docs/marine-weather-api | ||||||
""" | ||||||
# Set up the Open-Meteo API client with caching and retry on error | ||||||
cache_session = requests_cache.CachedSession(".cache", expire_after=3600) | ||||||
retry_session = retry(cache_session, retries=5, backoff_factor=0.2) | ||||||
openmeteo = openmeteo_requests.Client(session=retry_session) | ||||||
|
||||||
# Calculate the date and current hour one year ago | ||||||
one_year_ago = datetime.now() - timedelta(days=365) | ||||||
formatted_date_one_year_ago = one_year_ago.strftime("%Y-%m-%d") | ||||||
current_hour = one_year_ago.hour # Combined calculation here | ||||||
|
||||||
# Define the API request parameters | ||||||
url = "https://marine-api.open-meteo.com/v1/marine" | ||||||
params = { | ||||||
"latitude": lat, | ||||||
"longitude": long, | ||||||
"hourly": ["wave_height", "wave_direction", "wave_period"], | ||||||
"length_unit": unit, | ||||||
"timezone": "auto", | ||||||
"start_date": formatted_date_one_year_ago, | ||||||
"end_date": formatted_date_one_year_ago, | ||||||
} | ||||||
|
||||||
# For testing purposes if testing equals 1 it will continue | ||||||
if testing == 1: | ||||||
# Attempt to fetch the UV index data from the API | ||||||
try: | ||||||
responses = openmeteo.weather_api(url, params=params) | ||||||
|
||||||
except ValueError: | ||||||
return "No data" | ||||||
|
||||||
# Process the first response (assuming a single location) | ||||||
response = responses[0] | ||||||
|
||||||
# Extract hourly values for the specified metrics | ||||||
hourly = response.Hourly() | ||||||
hourly_wave_height = hourly.Variables(0).ValuesAsNumpy() | ||||||
hourly_wave_direction = hourly.Variables(1).ValuesAsNumpy() | ||||||
hourly_wave_period = hourly.Variables(2).ValuesAsNumpy() | ||||||
|
||||||
else: | ||||||
hourly_wave_height = [0.5678] * 24 | ||||||
hourly_wave_direction = [0.5678] * 24 | ||||||
hourly_wave_period = [0.5678] * 24 | ||||||
|
||||||
# Retrieve data for the current hour from one year ago | ||||||
return [ | ||||||
f"{hourly_wave_height[current_hour]:.{decimal}f}", | ||||||
f"{hourly_wave_direction[current_hour]:.{decimal}f}", | ||||||
f"{hourly_wave_period[current_hour]:.{decimal}f}", | ||||||
] | ||||||
|
||||||
|
||||||
def current_wind_temp(lat, long, decimal, temp_unit="fahrenheit"): | ||||||
""" | ||||||
Gathers the wind and temperature data | ||||||
|
@@ -364,6 +515,7 @@ | |||||
ocean_data = ocean_information( | ||||||
lat, long, arguments["decimal"], arguments["unit"] | ||||||
) | ||||||
|
||||||
uv_index = get_uv(lat, long, arguments["decimal"], arguments["unit"]) | ||||||
|
||||||
wind_temp = current_wind_temp(lat, long, arguments["decimal"]) | ||||||
|
@@ -385,9 +537,27 @@ | |||||
"Long": long, | ||||||
"Location": arguments["city"], | ||||||
"Height": ocean_data[0], | ||||||
"Height one year ago": ( | ||||||
ocean_information_history( | ||||||
lat, long, arguments["decimal"], arguments["unit"] | ||||||
)[0] | ||||||
), | ||||||
"Swell Direction": ocean_data[1], | ||||||
"Swell Direction one year ago": ( | ||||||
ocean_information_history( | ||||||
lat, long, arguments["decimal"], arguments["unit"] | ||||||
)[1] | ||||||
), | ||||||
"Period": ocean_data[2], | ||||||
"Period one year ago": ( | ||||||
ocean_information_history( | ||||||
lat, long, arguments["decimal"], arguments["unit"] | ||||||
)[2] | ||||||
), | ||||||
"UV Index": uv_index, | ||||||
"UV Index one year ago": ( | ||||||
get_uv_history(lat, long, arguments["decimal"], arguments["unit"]) | ||||||
), | ||||||
"Air Temperature": air_temp, | ||||||
"Wind Speed": wind_speed, | ||||||
"Wind Direction": wind_dir, | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Consider replacing the global testing flag with dependency injection or a configuration object
Global variables for testing make code harder to maintain and test. Consider passing this as a parameter or using a configuration object that can be injected into the functions.