1import math, numpy as np, onnxruntime as ort
2from huggingface_hub import hf_hub_download
3
4path = hf_hub_download("YuYu1015/YuYu1015-IntensityGMM-TW-45k-v1", "twn-intensity-gmm.onnx")
5sess = ort.InferenceSession(path)
6
7PGA_B = [0.8, 2.5, 8, 25, 80, 140, 250, 440, 800] # gal
8PGV_B = [0.2, 0.7, 1.9, 5.7, 15, 30, 50, 80, 140] # cm/s
9LEVELS = ["0", "1", "2", "3", "4", "5弱", "5強", "6弱", "6強", "7"]
10
11def _features(M, depth, ev_lat, ev_lon, t_lat, t_lon):
12 Re = 6371.0
13 p1, p2, dl = math.radians(ev_lat), math.radians(t_lat), math.radians(t_lon - ev_lon)
14 a = math.sin((p2 - p1) / 2) ** 2 + math.cos(p1) * math.cos(p2) * math.sin(dl / 2) ** 2
15 dist = 2 * Re * math.asin(math.sqrt(a))
16 lnR = math.log(max(math.hypot(dist, depth), 3.0))
17 az = math.atan2(math.sin(dl) * math.cos(p2),
18 math.cos(p1) * math.sin(p2) - math.sin(p1) * math.cos(p2) * math.cos(dl))
19 return [M, depth, dist, lnR, ev_lat, ev_lon, t_lat, t_lon, math.sin(az), math.cos(az)]
20
21def _classify(v, bounds):
22 return sum(1 for x in bounds if v >= x)
23
24def predict(M, depth, ev_lat, ev_lon, target_lat, target_lon):
25 x = np.array([_features(M, depth, ev_lat, ev_lon, target_lat, target_lon)], dtype=np.float32)
26 pga, pgv = sess.run(None, {"features": x})
27 pga, pgv = float(pga[0][0]), float(pgv[0][0])
28 level = max(_classify(pga, PGA_B), _classify(pgv, PGV_B))
29 return {"pga": round(pga, 2), "pgv": round(pgv, 3), "level": level, "name": LEVELS[level]}
30
31# 2024/04/03 Hualien M7.2 (epicenter 23.77, 121.67, depth 30 km)
32print(predict(7.2, 30, 23.77, 121.67, 25.03, 121.56)) # Taipei
33# {'pga': 72.4, 'pgv': 5.994, 'level': 4, 'name': '4'}
34print(predict(7.2, 30, 23.77, 121.67, 23.87, 121.51)) # Shoufeng
35# {'pga': 243.89, 'pgv': 31.902, 'level': 6, 'name': '5強'}