hiroki0008 commited on
Commit
99d5f70
·
verified ·
1 Parent(s): a5f11f1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +8 -24
app.py CHANGED
@@ -1,24 +1,15 @@
1
  # app.py
2
- # HF Spaces (Gradio) で japan_ver85.shp を単純にプロットするアプリ
3
- # 使い方:
4
- # - 「Shapefile (ZIP)」に .shp/.shx/.dbf/.prj を ZIP にまとめたファイルをアップロード
5
- # - そのまま「描画」ボタンを押すと境界線のみを静的プロット表示
6
-
7
  import os
8
  import io
9
  import geopandas as gpd
10
  import matplotlib.pyplot as plt
11
  import gradio as gr
 
12
 
13
- DEFAULT_ZIP = "data/japan_ver85.zip" # リポジトリに置いた場合のデフォルト
14
 
15
  def load_gdf_from_zip(zip_path: str) -> gpd.GeoDataFrame:
16
- """
17
- Shapefile を ZIP から読み込む。
18
- """
19
- # pyogrio が入っていれば engine="pyogrio" が高速
20
  gdf = gpd.read_file(f"zip://{zip_path}") # , engine="pyogrio"
21
- # 座標系が設定されていれば WGS84 へ(なくてもそのままプロット可)
22
  try:
23
  if gdf.crs:
24
  gdf = gdf.to_crs("EPSG:4326")
@@ -28,20 +19,21 @@ def load_gdf_from_zip(zip_path: str) -> gpd.GeoDataFrame:
28
 
29
  def plot_boundary(gdf: gpd.GeoDataFrame, linewidth: float = 0.6, figsize=(7,7)):
30
  """
31
- GeoDataFrame の境界線のみを静的にプロットし、PNGバイナリを返す
32
  """
33
  fig, ax = plt.subplots(figsize=figsize)
34
  gdf.boundary.plot(ax=ax, linewidth=linewidth)
35
  ax.set_axis_off()
36
  plt.tight_layout()
 
37
  buf = io.BytesIO()
38
  fig.savefig(buf, format="png", dpi=200)
39
  plt.close(fig)
40
  buf.seek(0)
41
- return buf
 
42
 
43
  def run(zip_file, line_width, width_px):
44
- # 1) 読み込み元の決定
45
  if zip_file is not None and hasattr(zip_file, "name") and os.path.exists(zip_file.name):
46
  zip_path = zip_file.name
47
  elif os.path.exists(DEFAULT_ZIP):
@@ -49,34 +41,27 @@ def run(zip_file, line_width, width_px):
49
  else:
50
  return None, "Shapefile の ZIP をアップロードするか、data/japan_ver85.zip を配置してください。"
51
 
52
- # 2) 読み込み
53
  try:
54
  gdf = load_gdf_from_zip(zip_path)
55
  except Exception as e:
56
  return None, f"読み込みに失敗しました: {e}"
57
 
58
- # 3) プロット
59
  try:
 
60
  img = plot_boundary(gdf, linewidth=line_width)
61
  except Exception as e:
62
  return None, f"描画に失敗しました: {e}"
63
 
64
- # 4) 出力(画像 + ちょっとした情報)
65
  info = []
66
  info.append(f"レコード数: {len(gdf)}")
67
  if gdf.crs:
68
  info.append(f"CRS: {gdf.crs}")
69
- # 主な列名(多すぎると邪魔なので先頭10件)
70
  cols = list(map(str, gdf.columns))
71
  info.append("列名(先頭10): " + ", ".join(cols[:10]))
72
  return img, "\n".join(info)
73
 
74
  with gr.Blocks(title="Japan Shapefile Plotter") as demo:
75
  gr.Markdown("## japan_ver85.shp(ZIP)を単純にプロット")
76
- gr.Markdown(
77
- "- **Shapefile を ZIP**(`.shp/.shx/.dbf/.prj` 等を1つに)でアップロードしてください。\n"
78
- "- 何もアップロードしない場合は `data/japan_ver85.zip` を読み込みます(置いてある場合)。"
79
- )
80
 
81
  with gr.Row():
82
  zip_in = gr.File(label="Shapefile (ZIP)", file_count="single", file_types=[".zip"])
@@ -85,11 +70,10 @@ with gr.Blocks(title="Japan Shapefile Plotter") as demo:
85
  width_px = gr.Slider(400, 1600, value=900, step=50, label="画像幅(px)(注: PNGは実質dpi依存)")
86
 
87
  run_btn = gr.Button("描画")
88
- out_img = gr.Image(label="静的プロット(境界線)", type="pil")
89
  out_txt = gr.Textbox(label="メタ情報", lines=4)
90
 
91
  run_btn.click(fn=run, inputs=[zip_in, line_width, width_px], outputs=[out_img, out_txt])
92
 
93
  if __name__ == "__main__":
94
- # Spaces では基本これでOK
95
  demo.launch()
 
1
  # app.py
 
 
 
 
 
2
  import os
3
  import io
4
  import geopandas as gpd
5
  import matplotlib.pyplot as plt
6
  import gradio as gr
7
+ from PIL import Image # ★ 追加
8
 
9
+ DEFAULT_ZIP = "data/japan_ver85.zip"
10
 
11
  def load_gdf_from_zip(zip_path: str) -> gpd.GeoDataFrame:
 
 
 
 
12
  gdf = gpd.read_file(f"zip://{zip_path}") # , engine="pyogrio"
 
13
  try:
14
  if gdf.crs:
15
  gdf = gdf.to_crs("EPSG:4326")
 
19
 
20
  def plot_boundary(gdf: gpd.GeoDataFrame, linewidth: float = 0.6, figsize=(7,7)):
21
  """
22
+ GeoDataFrame の境界線のみを静的にプロットし、PIL.Image を返す
23
  """
24
  fig, ax = plt.subplots(figsize=figsize)
25
  gdf.boundary.plot(ax=ax, linewidth=linewidth)
26
  ax.set_axis_off()
27
  plt.tight_layout()
28
+
29
  buf = io.BytesIO()
30
  fig.savefig(buf, format="png", dpi=200)
31
  plt.close(fig)
32
  buf.seek(0)
33
+ img = Image.open(buf) # ★ BytesIO → PIL.Image に変換
34
+ return img
35
 
36
  def run(zip_file, line_width, width_px):
 
37
  if zip_file is not None and hasattr(zip_file, "name") and os.path.exists(zip_file.name):
38
  zip_path = zip_file.name
39
  elif os.path.exists(DEFAULT_ZIP):
 
41
  else:
42
  return None, "Shapefile の ZIP をアップロードするか、data/japan_ver85.zip を配置してください。"
43
 
 
44
  try:
45
  gdf = load_gdf_from_zip(zip_path)
46
  except Exception as e:
47
  return None, f"読み込みに失敗しました: {e}"
48
 
 
49
  try:
50
+ # width_px は PNG の実寸に直接効かないので、必要なら figsize/dpi を調整してください
51
  img = plot_boundary(gdf, linewidth=line_width)
52
  except Exception as e:
53
  return None, f"描画に失敗しました: {e}"
54
 
 
55
  info = []
56
  info.append(f"レコード数: {len(gdf)}")
57
  if gdf.crs:
58
  info.append(f"CRS: {gdf.crs}")
 
59
  cols = list(map(str, gdf.columns))
60
  info.append("列名(先頭10): " + ", ".join(cols[:10]))
61
  return img, "\n".join(info)
62
 
63
  with gr.Blocks(title="Japan Shapefile Plotter") as demo:
64
  gr.Markdown("## japan_ver85.shp(ZIP)を単純にプロット")
 
 
 
 
65
 
66
  with gr.Row():
67
  zip_in = gr.File(label="Shapefile (ZIP)", file_count="single", file_types=[".zip"])
 
70
  width_px = gr.Slider(400, 1600, value=900, step=50, label="画像幅(px)(注: PNGは実質dpi依存)")
71
 
72
  run_btn = gr.Button("描画")
73
+ out_img = gr.Image(label="静的プロット(境界線)", type="pil") # ★ PIL を受け取る
74
  out_txt = gr.Textbox(label="メタ情報", lines=4)
75
 
76
  run_btn.click(fn=run, inputs=[zip_in, line_width, width_px], outputs=[out_img, out_txt])
77
 
78
  if __name__ == "__main__":
 
79
  demo.launch()