20250727
import numpy as np
import pandas as pd
import datetime
import math
import random
from scipy.integrate import odeint
from geopy.geocoders import Nominatim
import folium
from folium.plugins import HeatMapWithTime
import os
import webbrowser
# SIRV 모델 정의
def sirv_model_unique(y, t, N, beta_func, gamma, reinfection_rate, vaccination_schedule):
U, S, I, R, C = y
beta = beta_func(t)
vac_effect = 0
for start_day, rate in vaccination_schedule:
if t >= start_day:
vac_effect += rate
new_infections = beta * S * I / N
first_infections = new_infections * (U / S if S > 0 else 0)
dUdt = -first_infections
dSdt = -new_infections + reinfection_rate * R - vac_effect * S
dIdt = new_infections - gamma * I
dRdt = gamma * I - reinfection_rate * R + vac_effect * S
dCdt = first_infections
return dUdt, dSdt, dIdt, dRdt, dCdt
def beta_time_dependent(t):
gamma = 1/14
if t <= 365:
R0 = 2.5
elif t <= 600:
R0 = 1.2
elif t <= 800:
R0 = 4.0
elif t <= 1000:
R0 = 1.5
elif t <= 1200:
R0 = 5.0
else:
R0 = 1.0
return R0 * gamma
def run_sirv_simulation():
N = 50_000_000
I0, R0, C0 = 10, 0, 10
S0 = N - I0 - R0
U0 = N - I0
gamma = 1/14
reinfection_rate = 1/180
vaccination_schedule = [(500, 0.002), (900, 0.003)]
start_date = pd.to_datetime('2020-01-01')
end_date = pd.to_datetime('2024-06-30')
total_days = (end_date - start_date).days
t = np.linspace(0, total_days, total_days + 1)
y0 = U0, S0, I0, R0, C0
ret = odeint(sirv_model_unique, y0, t, args=(N, beta_time_dependent, gamma, reinfection_rate, vaccination_schedule))
U, S, I, R, C = ret.T
dates = start_date + pd.to_timedelta(t, unit='D')
return dates, I, C
def random_point_in_circle(lat_center, lon_center, radius_km):
r = radius_km * math.sqrt(random.random())
theta = random.uniform(0, 2 * math.pi)
delta_lat = r * math.cos(theta) / 111
delta_lon = r * math.sin(theta) / (111 * math.cos(math.radians(lat_center)))
lat = lat_center + delta_lat
lon = lon_center + delta_lon
return [lat, lon] # HeatMap은 (lat, lon)
def create_heatmap_simulation(country_name="South Korea"):
dates, I_vals, C_vals = run_sirv_simulation()
geolocator = Nominatim(user_agent="covid_sim")
location = geolocator.geocode(country_name)
if location is None:
raise ValueError(f"{country_name} 좌표를 찾을 수 없습니다.")
center_lat, center_lon = location.latitude, location.longitude
# 주 단위(7일)만 사용해서 속도 개선
step = 7
heat_data = []
time_index = []
for idx in range(0, len(dates), step):
current_I = I_vals[idx]
current_C = C_vals[idx]
date = dates[idx]
num_points = max(int(current_I / 20000), 5)
spread_radius = max(10, math.sqrt(current_C) / 50)
points = [random_point_in_circle(center_lat, center_lon, spread_radius)
for _ in range(num_points)]
heat_data.append(points)
time_index.append(date.strftime("%Y-%m-%d"))
m = folium.Map(location=[center_lat, center_lon], zoom_start=5, tiles='cartodbpositron')
HeatMapWithTime(
data=heat_data,
index=time_index,
auto_play=True,
max_opacity=0.8,
radius=10,
gradient={0.2: 'blue', 0.4: 'lime', 0.6: 'orange', 0.8: 'red'}
).add_to(m)
output_file = "covid_heatmap_simulation.html"
m.save(output_file)
file_path = os.path.abspath(output_file)
print(f"Heatmap 시뮬레이션 저장 완료: {file_path}")
webbrowser.open(f"file://{file_path}")
if __name__ == "__main__":
create_heatmap_simulation()




