Ken-INOUE commited on
Commit
d680eb8
·
1 Parent(s): 88d6d47

Add pagination support for trend figures and update rendering logic for individual plots. Introduce make_trend_figure_paged function and modify render_any to handle page and tags per page inputs.

Browse files
Files changed (1) hide show
  1. app.py +64 -23
app.py CHANGED
@@ -331,6 +331,7 @@ def make_trend_figure(
331
  thr_mode: str, # "excel" or "auto"
332
  date_min: Optional[str] = None,
333
  date_max: Optional[str] = None,
 
334
  ) -> Optional[go.Figure]:
335
  if df is None or not process_name:
336
  return None
@@ -357,7 +358,7 @@ def make_trend_figure(
357
  for r in recs:
358
  tag = extract_measure_tag(r["item"])
359
  groups.setdefault(tag, []).append(r)
360
- tags = list(groups.keys())
361
  if not tags:
362
  return None
363
 
@@ -447,6 +448,41 @@ def make_trend_figure(
447
  )
448
  return fig
449
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  # ======================================
451
  # 新規:計測項目タグごとに個別Figure
452
  # ======================================
@@ -648,30 +684,32 @@ def render_figs(process_name: str, items: List[str], thr_mode: str, date_min, da
648
  return "⚠ 図を生成できませんでした(データ無し or 条件不一致)", []
649
  return f"✅ {process_name}: {len(figs)}枚のトレンド図を生成しました(計測項目タグごと)", figs
650
 
651
- def render_any(process_name: str, items: List[str], display_mode: str, thr_mode_label: str, date_min, date_max):
652
- """
653
- 表示形式に応じて Plot(サブプロット1枚)または HTML(個別複数枚)を返す。
654
- """
655
  if G_DF is None:
656
- return "⚠ データ未読み込み", gr.update(visible=False), gr.update(value="", visible=False)
657
  if not process_name:
658
- return "⚠ プロセスを選択してください", gr.update(visible=False), gr.update(value="", visible=False)
659
  if not items:
660
- return "⚠ 項目を選択してください", gr.update(visible=False), gr.update(value="", visible=False)
661
 
662
  mode = "excel" if str(thr_mode_label).startswith("excel") else "auto"
663
 
664
  if str(display_mode).startswith("サブプロット"):
665
  fig = make_trend_figure(G_DF, G_PROCESS_MAP, process_name, items, G_THRESHOLDS_DF, mode, date_min, date_max)
666
  if fig is None:
667
- return "⚠ 図を生成できませんでした(データ無し or 条件不一致)", gr.update(visible=False), gr.update(value="", visible=False)
668
- return "✅ トレンド図(1枚サブプロット)を生成しました", gr.update(value=fig, visible=True), gr.update(value="", visible=False)
669
  else:
670
- figs_by_tag = make_trend_figs_by_tag(G_DF, G_PROCESS_MAP, process_name, items, G_THRESHOLDS_DF, mode, date_min, date_max)
671
- if not figs_by_tag:
672
- return "⚠ 図を生成できませんでした(データ無し or 条件不一致)", gr.update(visible=False), gr.update(value="", visible=False)
673
- html = figures_to_html(figs_by_tag)
674
- return f"✅ 個別トレンド図 {len(figs_by_tag)} 枚を生成しました", gr.update(visible=False), gr.update(value=html, visible=True)
 
 
 
675
 
676
  # ======================================
677
  # UI
@@ -700,7 +738,7 @@ with gr.Blocks(css="""
700
 
701
  # 表示形式の切り替え
702
  display_mode = gr.Radio(
703
- ["サブプロット(1枚)", "個別(複数枚)"],
704
  value="サブプロット(1枚)",
705
  label="表示形式"
706
  )
@@ -716,10 +754,13 @@ with gr.Blocks(css="""
716
  btn_render = gr.Button("トレンド図を生成", variant="primary")
717
 
718
  msg = gr.Markdown()
719
- # サブプロット用(1枚)
720
- plot = gr.Plot(label="トレンド図(タグ別サブプロット)", show_label=True, visible=True)
721
- # 個別(複数枚)用
722
- html_multi = gr.HTML(label="個別トレンド図(複数枚)", visible=False)
 
 
 
723
 
724
  # コールバック接続
725
  # 既定CSVの手動代入は不要(生成時に付与済み)
@@ -747,9 +788,9 @@ with gr.Blocks(css="""
747
 
748
  # 5) 図生成
749
  btn_render.click(
750
- fn=lambda proc, items, disp_mode, mode, dmin, dmax: render_any(proc, items, disp_mode, mode, dmin, dmax),
751
- inputs=[process_dd, items_cb, display_mode, thr_mode, date_min, date_max],
752
- outputs=[msg, plot, html_multi],
753
  )
754
 
755
  if __name__ == "__main__":
 
331
  thr_mode: str, # "excel" or "auto"
332
  date_min: Optional[str] = None,
333
  date_max: Optional[str] = None,
334
+ _force_tags: Optional[List[str]] = None, # ← 追加:ページ分割用に表示するタグを指定
335
  ) -> Optional[go.Figure]:
336
  if df is None or not process_name:
337
  return None
 
358
  for r in recs:
359
  tag = extract_measure_tag(r["item"])
360
  groups.setdefault(tag, []).append(r)
361
+ tags = list(groups.keys()) if _force_tags is None else _force_tags
362
  if not tags:
363
  return None
364
 
 
448
  )
449
  return fig
450
 
451
+ # 追加:ページ分割版(tags_per_pageごとに make_trend_figure を呼ぶだけ)
452
+ def make_trend_figure_paged(
453
+ df: pd.DataFrame,
454
+ process_map: Dict[str, List[dict]],
455
+ process_name: str,
456
+ selected_items: List[str],
457
+ thr_df: Optional[pd.DataFrame],
458
+ thr_mode: str,
459
+ date_min: Optional[str],
460
+ date_max: Optional[str],
461
+ page: int,
462
+ tags_per_page: int,
463
+ ) -> Tuple[Optional[go.Figure], int, List[str]]:
464
+ # 対象タグの全一覧を作る
465
+ recs = process_map.get(process_name, [])
466
+ if not recs:
467
+ return None, 0, []
468
+ selected_items_set = set([normalize(x) for x in (selected_items or [])])
469
+ recs = [r for r in recs if normalize(r["item"]) in selected_items_set]
470
+ if not recs:
471
+ return None, 0, []
472
+ groups: Dict[str, List[dict]] = {}
473
+ for r in recs:
474
+ groups.setdefault(extract_measure_tag(r["item"]), []).append(r)
475
+ all_tags = list(groups.keys())
476
+ total_pages = max(1, int(np.ceil(len(all_tags) / max(1, tags_per_page))))
477
+ page = int(max(1, min(page, total_pages)))
478
+ start = (page - 1) * tags_per_page
479
+ end = start + tags_per_page
480
+ tags_slice = all_tags[start:end]
481
+ fig = make_trend_figure(
482
+ df, process_map, process_name, selected_items, thr_df, thr_mode, date_min, date_max, _force_tags=tags_slice
483
+ )
484
+ return fig, total_pages, all_tags
485
+
486
  # ======================================
487
  # 新規:計測項目タグごとに個別Figure
488
  # ======================================
 
684
  return "⚠ 図を生成できませんでした(データ無し or 条件不一致)", []
685
  return f"✅ {process_name}: {len(figs)}枚のトレンド図を生成しました(計測項目タグごと)", figs
686
 
687
+ def render_any(process_name: str, items: List[str], display_mode: str, thr_mode_label: str,
688
+ date_min, date_max, page: int, tpp: int):
689
+ """表示形式に応じて Plot を返す(個別はページ分割)。"""
 
690
  if G_DF is None:
691
+ return "⚠ データ未読み込み", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
692
  if not process_name:
693
+ return "⚠ プロセスを選択してください", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
694
  if not items:
695
+ return "⚠ 項目を選択してください", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
696
 
697
  mode = "excel" if str(thr_mode_label).startswith("excel") else "auto"
698
 
699
  if str(display_mode).startswith("サブプロット"):
700
  fig = make_trend_figure(G_DF, G_PROCESS_MAP, process_name, items, G_THRESHOLDS_DF, mode, date_min, date_max)
701
  if fig is None:
702
+ return "⚠ 図を生成できませんでした(データ無し or 条件不一致)", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
703
+ return "✅ トレンド図(1枚サブプロット)を生成しました", gr.update(value=fig, visible=True), gr.update(visible=False), gr.update(visible=False)
704
  else:
705
+ fig, total_pages, all_tags = make_trend_figure_paged(
706
+ G_DF, G_PROCESS_MAP, process_name, items, G_THRESHOLDS_DF, mode, date_min, date_max,
707
+ page=int(page), tags_per_page=int(tpp)
708
+ )
709
+ if fig is None:
710
+ return "⚠ 図を生成できませんでした(データ無し or 条件不一致)", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
711
+ info = f"タグ総数: {len(all_tags)} | ページ {int(max(1,min(page,total_pages)))} / {total_pages} | タグ/ページ={int(tpp)}"
712
+ return "✅ 個別(ページ分割)を描画しました", gr.update(value=fig, visible=True), gr.update(value=info, visible=True), gr.update(visible=True)
713
 
714
  # ======================================
715
  # UI
 
738
 
739
  # 表示形式の切り替え
740
  display_mode = gr.Radio(
741
+ ["サブプロット(1枚)", "個別(ページ分割)"],
742
  value="サブプロット(1枚)",
743
  label="表示形式"
744
  )
 
754
  btn_render = gr.Button("トレンド図を生成", variant="primary")
755
 
756
  msg = gr.Markdown()
757
+ # 表示領域:Plot 1枚を使い回す(個別=ページ分割も同じPlotを再描画)
758
+ plot = gr.Plot(label="トレンド図(タグ別)", show_label=True, visible=True)
759
+ # ページ分割用コントロール(個別モード時のみ使用)
760
+ with gr.Row():
761
+ tags_per_page = gr.Slider(1, 12, value=8, step=1, label="タグ/ページ(個別モード)")
762
+ page_no = gr.Number(value=1, label="ページ(1〜)", precision=0)
763
+ page_info = gr.Markdown(visible=False)
764
 
765
  # コールバック接続
766
  # 既定CSVの手動代入は不要(生成時に付与済み)
 
788
 
789
  # 5) 図生成
790
  btn_render.click(
791
+ fn=lambda proc, items, disp_mode, mode, dmin, dmax, p, tpp: render_any(proc, items, disp_mode, mode, dmin, dmax, p, tpp),
792
+ inputs=[process_dd, items_cb, display_mode, thr_mode, date_min, date_max, page_no, tags_per_page],
793
+ outputs=[msg, plot, page_info, page_no],
794
  )
795
 
796
  if __name__ == "__main__":