cwadayi commited on
Commit
e6a8aae
·
verified ·
1 Parent(s): 628e852

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -39
app.py CHANGED
@@ -1,25 +1,29 @@
1
  import sqlite3
2
  import pandas as pd
3
  import gradio as gr
 
 
 
4
 
5
- # 後端資料查詢函式,已更新以支援日期時間區間
6
- async def fetch_earthquake_data(
7
  start_date, start_time, end_date, end_time,
8
  lat_min, lat_max, lon_min, lon_max,
9
  depth_min, depth_max, ML_min, ML_max
10
  ):
11
  try:
12
- # 組合日期和時間,如果時間為空,則使用預設值
13
  start_datetime_str = f"{start_date.strip()} {start_time.strip() if start_time and start_time.strip() else '00:00:00'}"
14
  end_datetime_str = f"{end_date.strip()} {end_time.strip() if end_time and end_time.strip() else '23:59:59'}"
15
 
 
16
  conn = sqlite3.connect('earthquake_data.db')
17
 
18
- # 使用 SQLite 的 `date || ' ' || time` 來組合欄位進行比較
19
  query = "SELECT * FROM earthquakes WHERE (date || ' ' || time) BETWEEN ? AND ?"
20
  params = [start_datetime_str, end_datetime_str]
21
 
22
- # 處理其他數值範圍篩選條件
23
  filters = {
24
  "lat BETWEEN ? AND ?": (lat_min, lat_max),
25
  "lon BETWEEN ? AND ?": (lon_min, lon_max),
@@ -28,64 +32,90 @@ async def fetch_earthquake_data(
28
  }
29
 
30
  for condition, values in filters.items():
31
- # 確保兩個值都存在才加入篩選
32
  if values[0] is not None and values[1] is not None:
33
  query += f" AND {condition}"
34
  params.extend(values)
35
 
 
36
  df = pd.read_sql_query(query, conn, params=tuple(params))
37
  conn.close()
38
 
 
39
  if df.empty:
40
- return pd.DataFrame()
41
-
42
- return df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  except Exception as e:
44
- return pd.DataFrame({"Error": [str(e)]})
 
45
 
46
 
47
- # 建立 Gradio 使用者介面,已更新欄位和預設值
48
  with gr.Blocks() as demo:
49
  gr.Markdown("# Earthquake Data Explorer")
50
- gr.Markdown("Use the filters below to search the earthquake catalog.")
51
 
52
  with gr.Row():
53
- with gr.Column():
54
- gr.Markdown("### 起訖日期與時間")
55
- start_date_input = gr.Textbox(label="開始日期 (Start Date)", value="2024-01-01")
56
- start_time_input = gr.Textbox(label="開始時間 (Start Time, HH:MM:SS)", placeholder="00:00:00")
57
- with gr.Column():
58
- gr.Markdown("### (空白)") # 佔位,讓排版好看
59
- end_date_input = gr.Textbox(label="結束日期 (End Date)", value="2024-12-31")
60
- end_time_input = gr.Textbox(label="結束時間 (End Time, HH:MM:SS)", placeholder="23:59:59")
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  with gr.Row():
63
- gr.Markdown("### 經緯度、深度、規模")
64
- with gr.Row():
65
- lon_min_input = gr.Number(label="經度 (Longitude) From", value=119)
66
- lon_max_input = gr.Number(label="To", value=123)
67
- with gr.Row():
68
- lat_min_input = gr.Number(label="緯度 (Latitude) From", value=21)
69
- lat_max_input = gr.Number(label="To", value=26)
70
- with gr.Row():
71
- depth_min_input = gr.Number(label="深度 (Depth) From", value=0)
72
- depth_max_input = gr.Number(label="To", value=100)
73
- with gr.Row():
74
- ML_min_input = gr.Number(label="規模 (Magnitude) From", value=4.5)
75
- ML_max_input = gr.Number(label="To", value=8)
76
-
77
- filter_button = gr.Button("Filter Data")
78
-
79
- output_df = gr.DataFrame(label="Filtered Results")
80
 
81
  filter_button.click(
82
- fn=fetch_earthquake_data,
83
  inputs=[
84
  start_date_input, start_time_input, end_date_input, end_time_input,
85
  lat_min_input, lat_max_input, lon_min_input, lon_max_input,
86
  depth_min_input, depth_max_input, ML_min_input, ML_max_input
87
  ],
88
- outputs=output_df
89
  )
90
 
91
  # --- 主程式執行 ---
 
1
  import sqlite3
2
  import pandas as pd
3
  import gradio as gr
4
+ import matplotlib.pyplot as plt
5
+ import cartopy.crs as ccrs
6
+ import cartopy.feature as cfeature
7
 
8
+ # --- 後端資料查詢與繪圖函式 ---
9
+ async def fetch_and_plot_data(
10
  start_date, start_time, end_date, end_time,
11
  lat_min, lat_max, lon_min, lon_max,
12
  depth_min, depth_max, ML_min, ML_max
13
  ):
14
  try:
15
+ # 組合日期和時間
16
  start_datetime_str = f"{start_date.strip()} {start_time.strip() if start_time and start_time.strip() else '00:00:00'}"
17
  end_datetime_str = f"{end_date.strip()} {end_time.strip() if end_time and end_time.strip() else '23:59:59'}"
18
 
19
+ # 連接到資料庫
20
  conn = sqlite3.connect('earthquake_data.db')
21
 
22
+ # 建立查詢
23
  query = "SELECT * FROM earthquakes WHERE (date || ' ' || time) BETWEEN ? AND ?"
24
  params = [start_datetime_str, end_datetime_str]
25
 
26
+ # 處理其他篩選條件
27
  filters = {
28
  "lat BETWEEN ? AND ?": (lat_min, lat_max),
29
  "lon BETWEEN ? AND ?": (lon_min, lon_max),
 
32
  }
33
 
34
  for condition, values in filters.items():
 
35
  if values[0] is not None and values[1] is not None:
36
  query += f" AND {condition}"
37
  params.extend(values)
38
 
39
+ # 執行查詢
40
  df = pd.read_sql_query(query, conn, params=tuple(params))
41
  conn.close()
42
 
43
+ # 如果沒有資料,回傳空的 DataFrame 和 None
44
  if df.empty:
45
+ return pd.DataFrame({"Message": ["No data found for the selected filters."]}), None
46
+
47
+ # --- 繪圖 ---
48
+ fig = plt.figure(figsize=(10, 12))
49
+ ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
50
+ ax.set_extent([lon_min, lon_max, lat_min, lat_max], crs=ccrs.PlateCarree())
51
+
52
+ # 加入地圖特徵
53
+ ax.add_feature(cfeature.LAND, edgecolor='black')
54
+ ax.add_feature(cfeature.OCEAN)
55
+ ax.add_feature(cfeature.COASTLINE)
56
+ ax.add_feature(cfeature.BORDERS, linestyle=':')
57
+
58
+ # 繪製散點圖
59
+ scatter = ax.scatter(
60
+ df['lon'], df['lat'], c=df['ML'],
61
+ cmap='viridis', alpha=0.7, s=50,
62
+ transform=ccrs.PlateCarree()
63
+ )
64
+
65
+ # 加入顏色條和標題
66
+ plt.colorbar(scatter, ax=ax, orientation='vertical', label='Magnitude (ML)', shrink=0.6)
67
+ ax.set_title(f'Earthquake Distribution on Map\n({start_date} to {end_date})')
68
+
69
+ # 關閉圖形以避免在伺服器上顯示
70
+ plt.close(fig)
71
+
72
+ return df, fig
73
+
74
  except Exception as e:
75
+ # 回傳錯誤訊息和 None
76
+ return pd.DataFrame({"Error": [str(e)]}), None
77
 
78
 
79
+ # --- Gradio 使用者介面 ---
80
  with gr.Blocks() as demo:
81
  gr.Markdown("# Earthquake Data Explorer")
82
+ gr.Markdown("Use the filters below to search the earthquake catalog and visualize the distribution.")
83
 
84
  with gr.Row():
85
+ with gr.Column(scale=1):
86
+ gr.Markdown("### Date & Time Range")
87
+ start_date_input = gr.Textbox(label="Start Date", value="2024-01-01")
88
+ start_time_input = gr.Textbox(label="Start Time (HH:MM:SS)", placeholder="00:00:00")
89
+ end_date_input = gr.Textbox(label="End Date", value="2024-12-31")
90
+ end_time_input = gr.Textbox(label="End Time (HH:MM:SS)", placeholder="23:59:59")
91
+
92
+ with gr.Column(scale=1):
93
+ gr.Markdown("### Geographical & Physical Filters")
94
+ lon_min_input = gr.Number(label="Longitude From", value=119)
95
+ lon_max_input = gr.Number(label="To", value=123)
96
+ lat_min_input = gr.Number(label="Latitude From", value=21)
97
+ lat_max_input = gr.Number(label="To", value=26)
98
+ depth_min_input = gr.Number(label="Depth From", value=0)
99
+ depth_max_input = gr.Number(label="To", value=100)
100
+ ML_min_input = gr.Number(label="Magnitude From", value=4.5)
101
+ ML_max_input = gr.Number(label="To", value=8)
102
+
103
+ filter_button = gr.Button("Filter and Plot Data", variant="primary")
104
 
105
  with gr.Row():
106
+ with gr.Column(scale=2):
107
+ output_plot = gr.Plot(label="Earthquake Distribution Map")
108
+ with gr.Column(scale=3):
109
+ output_df = gr.DataFrame(label="Filtered Results")
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
  filter_button.click(
112
+ fn=fetch_and_plot_data,
113
  inputs=[
114
  start_date_input, start_time_input, end_date_input, end_time_input,
115
  lat_min_input, lat_max_input, lon_min_input, lon_max_input,
116
  depth_min_input, depth_max_input, ML_min_input, ML_max_input
117
  ],
118
+ outputs=[output_df, output_plot]
119
  )
120
 
121
  # --- 主程式執行 ---