Skip to content

Instantly share code, notes, and snippets.

@amupoti
Last active September 8, 2024 07:19
Show Gist options
  • Save amupoti/5284c389405fd36dfc3b7338f2c9efcb to your computer and use it in GitHub Desktop.
Save amupoti/5284c389405fd36dfc3b7338f2c9efcb to your computer and use it in GitHub Desktop.
Get total rain for a location given 3 different stations
import requests
from lxml import html
import re
from datetime import datetime, timedelta
from math import radians, sin, cos, sqrt, atan2
# Function to calculate distance between two GPS coordinates (Haversine formula)
def haversine(lat1, lon1, lat2, lon2):
R = 6371.0 # Earth radius in kilometers
lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
dlat = lat2 - lat1
dlon = lon2 - lon1
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
distance = R * c
return distance
# Function to get the precipitation value for a date and location
def get_precipitation(url):
response = requests.get(url)
if response.status_code == 200:
tree = html.fromstring(response.content)
precipitation_value = tree.xpath('//*[@id="resum-diari"]/div/table/tbody/tr[5]/td/text()')
if precipitation_value:
try:
# Extract and return the numeric value
return float(re.findall(r'\d+\.\d+', precipitation_value[0])[0])
except IndexError:
print(f"Error extracting value from URL: {url}")
return 0.0
else:
print(f"Error in GET request: {response.status_code} for URL: {url}")
return 0.0
# Coordinates of stations and El Catllar
stations = {
"Torredembarra": {"coords": (41.145, 1.402), "code": "DK"},
"Nulles": {"coords": (41.263, 1.327), "code": "VY"},
"Tarragona": {"coords": (41.118, 1.244), "code": "XE"}
}
el_catllar_coords = (41.222, 1.346)
# Generate URLs for each day of the last six weeks
url_base = "https://www.meteo.cat/observacions/xema/dades?codi="
num_weeks = 6
days_per_week = 7
# Function to generate URLs for a specific location
def generate_urls_for_location(code):
weeks = [[] for _ in range(num_weeks)]
for week in range(num_weeks):
for day in range(days_per_week):
date = (datetime.now() - timedelta(weeks=week, days=day)).strftime('%Y-%m-%dT00:00Z')
weeks[week].append(url_base + code + "&dia=" + date)
return weeks
# Get the accumulated precipitation per week for each station
for station_name, station_data in stations.items():
print(f"Processing station: {station_name}")
weeks = generate_urls_for_location(station_data["code"])
precipitation_per_week = []
for idx, week in enumerate(weeks):
precipitations = [get_precipitation(url) for url in week]
precipitation_per_week.append(precipitations)
station_data["precipitation_per_week"] = [sum(week) for week in precipitation_per_week]
# Calculate distances from El Catllar to each station
for station_name, station_data in stations.items():
lat, lon = station_data["coords"]
station_data["distance_to_catllar"] = haversine(el_catllar_coords[0], el_catllar_coords[1], lat, lon)
# Function to perform Inverse Distance Weighting (IDW)
def idw_precipitation(precipitation_values, distances):
inv_distances = [1 / d if d != 0 else 0 for d in distances]a
weighted_precipitations = [p * inv_d for p, inv_d in zip(precipitation_values, inv_distances)]
total_weight = sum(inv_distances)
return sum(weighted_precipitations) / total_weight if total_weight > 0 else 0
# Estimate precipitation in El Catllar using IDW
precipitation_catllar_per_week = []
for week_idx in range(num_weeks):
precipitations = [stations[station]["precipitation_per_week"][week_idx] for station in stations]
distances = [stations[station]["distance_to_catllar"] for station in stations]
estimated_precipitation = idw_precipitation(precipitations, distances)
precipitation_catllar_per_week.append(estimated_precipitation)
# Display the estimated rainfall for El Catllar
for week_idx, total_precipitation in enumerate(precipitation_catllar_per_week):
print(f"Estimated total precipitation {week_idx} week(s) ago for El Catllar: {total_precipitation:.2f} mm")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment