-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcity_test.py
More file actions
132 lines (111 loc) · 6.28 KB
/
city_test.py
File metadata and controls
132 lines (111 loc) · 6.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
cities = [
# {"name": "London", "country": "UK", "tz": "Europe/London", "lat": 51.5074, "lon": -0.1278, "create_dashboard": False},
# {"name": "New_York","country": "US", "tz": "America/New_York", "lat": 40.7128, "lon": -74.0060, "create_dashboard": False},
# {"name": "Tokyo", "country": "JP", "tz": "Asia/Tokyo", "lat": 35.6895, "lon": 139.6917, "create_dashboard": False},
# {"name": "Sydney", "country": "AU", "tz": "Australia/Sydney", "lat": -33.8688,"lon": 151.2093, "create_dashboard": False},
{"name": "Hong Kong", "country": "HK", "tz": "Asia/Hong_Kong", "lat": 22.3193, "lon": 114.1694, "create_dashboard": False},
{"name": "Reading", "country": "UK", "tz": "Europe/London", "lat": 51.4545, "lon": -0.9781, "create_dashboard": False},
# {"name": "Oxford", "country": "UK", "tz": "Europe/London", "lat": 51.7520, "lon": -1.2577, "create_dashboard": False},
{"name": "Cambridge", "country": "UK", "tz": "Europe/London", "lat": 52.2053, "lon": 0.1218, "create_dashboard": False},
]
# def run_tests():
# run_dt = datetime.datetime(2025, 11, 20, 12, 0, tzinfo=datetime.timezone.utc)
# current_utc = run_dt + datetime.timedelta(hours=22) #simulate current time at 10 UTC or 22 UTC
# cities = [
# {"name": "London", "country": "UK", "tz": "Europe/London", "lat": 51.5074, "lon": -0.1278},
# {"name": "New_York", "country": "US", "tz": "America/New_York", "lat": 40.7128, "lon": -74.0060},
# {"name": "Tokyo", "country": "JP", "tz": "Asia/Tokyo", "lat": 35.6895, "lon": 139.6917},
# {"name": "Sydney", "country": "AU", "tz": "Australia/Sydney", "lat": -33.8688, "lon": 151.2093},
# {"name": "Los_Angeles", "country": "US", "tz": "America/Los_Angeles", "lat": 34.0522, "lon": -118.2437},
# ]
# print("=== Real-city tests ===")
# for c in cities:
# city = LocationInfo(c["name"], c["country"], c["tz"], c["lat"], c["lon"])
# tz = pytz.timezone(c["tz"])
# # local date anchored to actual run-time (10Z) so we compute the coming events
# local_ref_date = current_utc.astimezone(tz).date()
# s_today = sun(city.observer, date=local_ref_date, tzinfo=tz)
# sunrise_today = s_today["sunrise"]
# sunset_today = s_today["sunset"]
# # also get tomorrow's events (coming) for completeness
# s_tom = sun(city.observer, date=local_ref_date + datetime.timedelta(days=1), tzinfo=tz)
# sunrise_tom = s_tom["sunrise"]
# sunset_tom = s_tom["sunset"]
# # choose which event datetimes to pass to determine_city_forecast_time_to_use:
# # pass the event datetimes for the coming local day (today & tomorrow)
# res = determine_city_forecast_time_to_use(city, sunrise_today, sunset_today, run_dt, time_threshold_h=15)
# print(c["name"], "local_ref_date:", local_ref_date, "->", res)
import datetime
from astral import LocationInfo
from city_test import cities # must be a module-level list as above
from calc_afterglow_realistic_path_lwc_global import process_city, latest_forecast_hours_run_to_download
from get_cds_global import get_cams_aod_lwc, get_cams_cloud_cover
from get_aifs import download_file
import requests
import logging
import os
import pandas as pd
import numpy as np
def main():
output_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'Afterglow', 'output'))
input_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'Afterglow', 'input'))
today = datetime.datetime(2026,3,29,23,3,0) # Simulate today as selected date for testing
today_str = today.strftime("%Y%m%d")
print("today_str:", today_str)
#run = "00".zfill(2) # Change this when simulating as well!
run_dt = latest_forecast_hours_run_to_download()
run = str(run_dt.hour).zfill(2)
# failed_count = 0
# for fcst_hour in range(0, 61, 6):
# try:
# if failed_count >= 5:
# print("Too many failed downloads, aborting.")
# quit()
# url = f"https://data.ecmwf.int/forecasts/{today_str}/{run}z/aifs-single/0p25/oper/{today_str}{run}0000-{fcst_hour}h-oper-fc.grib2"
# download_file(url, f"{input_path}/{today_str}{run}0000-{fcst_hour}h-oper-fc.grib2")
# except requests.HTTPError as e:
# logging.warning(f"HTTP error downloading hour {fcst_hour}: {e}")
# failed_count += 1
# except Exception as e:
# logging.exception(f"Unexpected error downloading hour {fcst_hour}")
# failed_count += 1
# Need global dataset for this - convert datetime to date
get_cams_aod_lwc(today.date(), run, today_str, input_path) # type: ignore
get_cams_cloud_cover(today.date(), run, today_str, input_path)
run_date_str = today_str # For test, use today_str as run_date_str (adjust if needed)
results = []
for c in cities:
try:
res = process_city(
c["name"],
c.get("country", ""),
float(c["lat"]),
float(c["lon"]),
c["tz"],
today,
run,
today_str,
run_date_str, # <-- add this argument
input_path,
output_path,
c.get("create_dashboard", False)
)
results.append(res)
print("OK:", c["name"], "->", res.get("sunset_time_tdy"))
except Exception as e:
print("ERROR:", c["name"], e)
results_df = pd.DataFrame(results)
# Round all numeric columns to 3 decimal places
numeric_cols = results_df.select_dtypes(include=[np.number]).columns
results_df[numeric_cols] = results_df[numeric_cols].round(3)
# Convert likelihood index columns to integers (they should be 0-100, not floats)
index_cols = [col for col in results_df.columns if 'likelihood_index' in col]
for col in index_cols:
results_df[col] = results_df[col].fillna(-1).astype(int).replace(-1, np.nan)
# Export to JSON with controlled precision
output_json_path = f'{output_path}/all_cities_summary_{today_str}.json'
results_df.to_json(output_json_path, orient='records', indent=2, date_format='iso', double_precision=3)
logging.info(f"Results saved to {output_json_path}")
return results_df
if __name__ == "__main__":
main()