Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -62,7 +62,7 @@ def normalize_drive_url(url: str) -> str:
|
|
| 62 |
# -----------------------------
|
| 63 |
# Demo / Data loading with dynamic update
|
| 64 |
# -----------------------------
|
| 65 |
-
def make_demo_dataframe(last_time=None) -> pd.DataFrame:
|
| 66 |
"""隨機示範資料:含經緯度 + pid,模擬實時更新"""
|
| 67 |
if last_time is None:
|
| 68 |
last_time = datetime.now(tz=TAIPEI) - timedelta(minutes=60)
|
|
@@ -477,9 +477,9 @@ def pipeline(source, file, sheet_url, series_choice, dual_axis, rolling_window,
|
|
| 477 |
demo_csv_path = f.name
|
| 478 |
|
| 479 |
return (
|
| 480 |
-
fig1, fig2,
|
| 481 |
dash_json_str, json_path, df_with_roll,
|
| 482 |
-
|
| 483 |
gr.Dropdown(choices=point_choices, value=default_choice),
|
| 484 |
detail_df,
|
| 485 |
"", # 錯誤訊息清空
|
|
@@ -592,8 +592,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 592 |
|
| 593 |
# 初次載入
|
| 594 |
demo.load(
|
| 595 |
-
lambda: pipeline("drive", None, DRIVE_PRESETS[0], [], False, "5", "viridis", "OpenStreetMap", "", "", False),
|
| 596 |
-
inputs=None,
|
| 597 |
outputs=[
|
| 598 |
plot1, plot2, plot3, plot4, map_out,
|
| 599 |
json_box, json_file, df_view,
|
|
@@ -606,7 +605,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 606 |
|
| 607 |
# 產生 / 重新產生 / 動態更新
|
| 608 |
run_btn.click(
|
| 609 |
-
pipeline,
|
| 610 |
inputs=[source_radio, file_in, preset_dd, series_multiselect, dual_axis_chk, rolling_dd, cmap_dd, tiles_dd, start_time_in, end_time_in, heatmap_chk, gr.State(value=None)],
|
| 611 |
outputs=[
|
| 612 |
plot1, plot2, plot3, plot4, map_out,
|
|
@@ -614,12 +613,12 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 614 |
demo_csv_file,
|
| 615 |
point_selector, detail_view,
|
| 616 |
error_msg,
|
| 617 |
-
gr.State(
|
| 618 |
]
|
| 619 |
)
|
| 620 |
|
| 621 |
update_btn.click(
|
| 622 |
-
pipeline,
|
| 623 |
inputs=[source_radio, file_in, preset_dd, series_multiselect, dual_axis_chk, rolling_dd, cmap_dd, tiles_dd, start_time_in, end_time_in, heatmap_chk, gr.State()],
|
| 624 |
outputs=[
|
| 625 |
plot1, plot2, plot3, plot4, map_out,
|
|
@@ -631,31 +630,37 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 631 |
]
|
| 632 |
)
|
| 633 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 634 |
interval.change(
|
| 635 |
-
fn=
|
| 636 |
inputs=[interval],
|
| 637 |
-
outputs=[]
|
| 638 |
)
|
| 639 |
|
| 640 |
-
demo.
|
| 641 |
-
|
| 642 |
-
|
| 643 |
-
()
|
| 644 |
-
|
| 645 |
-
|
| 646 |
-
|
| 647 |
-
|
| 648 |
-
}, interval * 1000);
|
| 649 |
-
}
|
| 650 |
-
const interval = """ + str(10) + """; // 初始間隔
|
| 651 |
-
update();
|
| 652 |
}
|
| 653 |
-
|
| 654 |
-
|
| 655 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 656 |
|
| 657 |
point_selector.change(
|
| 658 |
-
update_detail,
|
| 659 |
inputs=[df_view, point_selector],
|
| 660 |
outputs=[detail_view]
|
| 661 |
)
|
|
|
|
| 62 |
# -----------------------------
|
| 63 |
# Demo / Data loading with dynamic update
|
| 64 |
# -----------------------------
|
| 65 |
+
def make_demo_dataframe(last_time=None) -> tuple[pd.DataFrame, datetime]:
|
| 66 |
"""隨機示範資料:含經緯度 + pid,模擬實時更新"""
|
| 67 |
if last_time is None:
|
| 68 |
last_time = datetime.now(tz=TAIPEI) - timedelta(minutes=60)
|
|
|
|
| 477 |
demo_csv_path = f.name
|
| 478 |
|
| 479 |
return (
|
| 480 |
+
fig1, fig2, plot3, plot4, map_out,
|
| 481 |
dash_json_str, json_path, df_with_roll,
|
| 482 |
+
demo_csv_file,
|
| 483 |
gr.Dropdown(choices=point_choices, value=default_choice),
|
| 484 |
detail_df,
|
| 485 |
"", # 錯誤訊息清空
|
|
|
|
| 592 |
|
| 593 |
# 初次載入
|
| 594 |
demo.load(
|
| 595 |
+
fn=lambda: pipeline("drive", None, DRIVE_PRESETS[0], [], False, "5", "viridis", "OpenStreetMap", "", "", False),
|
|
|
|
| 596 |
outputs=[
|
| 597 |
plot1, plot2, plot3, plot4, map_out,
|
| 598 |
json_box, json_file, df_view,
|
|
|
|
| 605 |
|
| 606 |
# 產生 / 重新產生 / 動態更新
|
| 607 |
run_btn.click(
|
| 608 |
+
fn=pipeline,
|
| 609 |
inputs=[source_radio, file_in, preset_dd, series_multiselect, dual_axis_chk, rolling_dd, cmap_dd, tiles_dd, start_time_in, end_time_in, heatmap_chk, gr.State(value=None)],
|
| 610 |
outputs=[
|
| 611 |
plot1, plot2, plot3, plot4, map_out,
|
|
|
|
| 613 |
demo_csv_file,
|
| 614 |
point_selector, detail_view,
|
| 615 |
error_msg,
|
| 616 |
+
gr.State()
|
| 617 |
]
|
| 618 |
)
|
| 619 |
|
| 620 |
update_btn.click(
|
| 621 |
+
fn=pipeline,
|
| 622 |
inputs=[source_radio, file_in, preset_dd, series_multiselect, dual_axis_chk, rolling_dd, cmap_dd, tiles_dd, start_time_in, end_time_in, heatmap_chk, gr.State()],
|
| 623 |
outputs=[
|
| 624 |
plot1, plot2, plot3, plot4, map_out,
|
|
|
|
| 630 |
]
|
| 631 |
)
|
| 632 |
|
| 633 |
+
# 自動更新邏輯
|
| 634 |
+
def start_auto_update(interval):
|
| 635 |
+
return gr.update(value=interval)
|
| 636 |
+
|
| 637 |
interval.change(
|
| 638 |
+
fn=start_auto_update,
|
| 639 |
inputs=[interval],
|
| 640 |
+
outputs=[interval]
|
| 641 |
)
|
| 642 |
|
| 643 |
+
demo.js = """
|
| 644 |
+
function startAutoUpdate() {
|
| 645 |
+
let intervalValue = parseInt(document.querySelector('input[type="range"]').value) * 1000;
|
| 646 |
+
function update() {
|
| 647 |
+
setTimeout(() => {
|
| 648 |
+
document.querySelector('button[aria-label="手動更新數據"]').click();
|
| 649 |
+
update();
|
| 650 |
+
}, intervalValue);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 651 |
}
|
| 652 |
+
update();
|
| 653 |
+
}
|
| 654 |
+
startAutoUpdate();
|
| 655 |
+
document.querySelector('input[type="range"]').addEventListener('input', function() {
|
| 656 |
+
let newInterval = parseInt(this.value) * 1000;
|
| 657 |
+
clearTimeout(window.updateTimeout);
|
| 658 |
+
startAutoUpdate();
|
| 659 |
+
});
|
| 660 |
+
"""
|
| 661 |
|
| 662 |
point_selector.change(
|
| 663 |
+
fn=update_detail,
|
| 664 |
inputs=[df_view, point_selector],
|
| 665 |
outputs=[detail_view]
|
| 666 |
)
|