Lashtw commited on
Commit
17039ec
·
verified ·
1 Parent(s): 2bdddb6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -54
app.py CHANGED
@@ -53,81 +53,57 @@ def create_radar_chart(df, selected_rows, selected_columns):
53
  ),
54
  marker=dict(opacity=0.5)
55
  ))
56
-
57
  fig.update_layout(
58
- polar=dict(
59
  radialaxis=dict(
60
  visible=True,
61
  range=[0, df[selected_columns].values.max() * 1.1],
62
- tickfont=dict(size=12, color='black', family="Microsoft JhengHei, Noto Sans CJK, Arial")
63
  ),
64
- angularaxis=dict(
65
- tickfont=dict(size=16, color='black', family="Microsoft JhengHei, Noto Sans CJK, Arial")
66
  )
67
  ),
68
  showlegend=True,
69
  legend=dict(
70
- font=dict(size=14, color='black', family="Microsoft JhengHei, Noto Sans CJK, Arial")
71
  ),
72
  title='學生成績雷達圖',
73
  plot_bgcolor='white',
74
  paper_bgcolor='white',
75
- font=dict(family="Microsoft JhengHei, Noto Sans CJK, Arial")
76
- )
77
-
78
- return fig
79
-
80
- def apply_font_to_all_text(fig):
81
- """強制設定圖表內所有文字元素的字型"""
82
- for trace in fig.data:
83
- if hasattr(trace, 'textfont'):
84
- trace.textfont.family = "Microsoft JhengHei, Noto Sans CJK, Arial"
85
- if hasattr(trace, 'marker') and hasattr(trace.marker, 'textfont'):
86
- trace.marker.textfont.family = "Microsoft JhengHei, Noto Sans CJK, Arial"
87
- fig.update_layout(
88
- font=dict(
89
- family="Microsoft JhengHei, Noto Sans CJK, Arial"
90
- )
91
  )
92
 
93
- if hasattr(fig, 'layout') and hasattr(fig.layout, 'xaxis'):
94
- fig.layout.xaxis.tickfont.family = "Microsoft JhengHei, Noto Sans CJK, Arial"
95
- if hasattr(fig, 'layout') and hasattr(fig.layout, 'yaxis'):
96
- fig.layout.yaxis.tickfont.family = "Microsoft JhengHei, Noto Sans CJK, Arial"
97
- if hasattr(fig, 'layout') and hasattr(fig.layout, 'polar') and hasattr(fig.layout.polar, 'radialaxis'):
98
- fig.layout.polar.radialaxis.tickfont.family = "Microsoft JhengHei, Noto Sans CJK, Arial"
99
- if hasattr(fig, 'layout') and hasattr(fig.layout, 'polar') and hasattr(fig.layout.polar, 'angularaxis'):
100
- fig.layout.polar.angularaxis.tickfont.family = "Microsoft JhengHei, Noto Sans CJK, Arial"
101
-
102
  return fig
103
 
104
-
105
  def save_all_radar_charts(df, selected_columns, comparison_rows):
106
  """批次生成並儲存每個學生與指定比較對象的雷達圖"""
107
  output_dir = "radar_charts"
108
  os.makedirs(output_dir, exist_ok=True)
 
 
 
 
 
 
109
 
110
  for student in df['姓名']:
111
  if student in comparison_rows:
112
  continue
113
 
114
- # 建立圖表
115
  fig = create_radar_chart(df, [student] + comparison_rows, selected_columns)
116
- fig = apply_font_to_all_text(fig)
117
-
118
- # 使用 to_image 取得圖表影像
119
  img_bytes = pio.to_image(fig, format="png", engine="kaleido")
120
-
121
- # 使用 PIL 打開影像
122
  img = Image.open(BytesIO(img_bytes)).convert("RGBA")
123
-
124
- # 建立空白背景
125
  background = Image.new('RGBA', img.size, (255, 255, 255, 255))
126
-
127
- # 合成圖片
128
  composite = Image.alpha_composite(background, img)
 
129
 
130
- # 儲存圖片
 
 
 
 
 
131
  file_path = os.path.join(output_dir, f"{student}_comparison.png")
132
  composite.save(file_path)
133
 
@@ -139,6 +115,7 @@ def save_all_radar_charts(df, selected_columns, comparison_rows):
139
 
140
  return zip_path
141
 
 
142
  def main():
143
  st.title('學生成績雷達圖產生器')
144
 
@@ -171,19 +148,21 @@ def main():
171
  st.error("請至少選擇一個比較對象")
172
  else:
173
  zip_path = save_all_radar_charts(df, selected_columns, comparison_rows)
174
- with open(zip_path, "rb") as f:
175
- st.download_button(
176
- label="下載壓縮檔",
177
- data=f,
178
- file_name="radar_charts.zip",
179
- mime="application/zip",
180
- key="download_button",
181
- on_click=lambda: st.session_state.update({'download_triggered':True}),
182
- disabled=st.session_state.get("download_triggered",False)
183
- )
184
- st.session_state.download_triggered = False
 
185
 
186
  if __name__ == "__main__":
187
  if 'download_triggered' not in st.session_state:
188
  st.session_state.download_triggered = False
 
189
  main()
 
53
  ),
54
  marker=dict(opacity=0.5)
55
  ))
 
56
  fig.update_layout(
57
+ polar=dict(
58
  radialaxis=dict(
59
  visible=True,
60
  range=[0, df[selected_columns].values.max() * 1.1],
61
+ tickfont=dict(size=12, color='black')
62
  ),
63
+ angularaxis=dict(
64
+ tickfont=dict(size=16, color='black')
65
  )
66
  ),
67
  showlegend=True,
68
  legend=dict(
69
+ font=dict(size=14, color='black')
70
  ),
71
  title='學生成績雷達圖',
72
  plot_bgcolor='white',
73
  paper_bgcolor='white',
74
+ font=dict(family="Microsoft JhengHei, Noto Sans CJK, Arial")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  )
76
 
 
 
 
 
 
 
 
 
 
77
  return fig
78
 
 
79
  def save_all_radar_charts(df, selected_columns, comparison_rows):
80
  """批次生成並儲存每個學生與指定比較對象的雷達圖"""
81
  output_dir = "radar_charts"
82
  os.makedirs(output_dir, exist_ok=True)
83
+ font_path = "path/to/your/font/file.ttf" # 請替換成你字體檔案的路徑
84
+ try:
85
+ font = ImageFont.truetype(font_path, size=12, encoding="utf-8") # 設置中文字型
86
+ except FileNotFoundError:
87
+ st.error(f"找不到字型檔案: {font_path},請確保檔案路徑正確")
88
+ return None
89
 
90
  for student in df['姓名']:
91
  if student in comparison_rows:
92
  continue
93
 
 
94
  fig = create_radar_chart(df, [student] + comparison_rows, selected_columns)
 
 
 
95
  img_bytes = pio.to_image(fig, format="png", engine="kaleido")
 
 
96
  img = Image.open(BytesIO(img_bytes)).convert("RGBA")
 
 
97
  background = Image.new('RGBA', img.size, (255, 255, 255, 255))
 
 
98
  composite = Image.alpha_composite(background, img)
99
+ draw = ImageDraw.Draw(composite)
100
 
101
+ #手動繪製圖表標籤文字
102
+ for trace in fig.data:
103
+ if isinstance(trace, go.Scatterpolar):
104
+ for i, theta in enumerate(trace.theta):
105
+ x, y = fig.layout.polar.radialaxis.range[1] * (0.5 - 0.5*trace.r[i] / fig.layout.polar.radialaxis.range[1]) * np.cos(np.radians(90-theta)), fig.layout.polar.radialaxis.range[1] * (0.5 - 0.5*trace.r[i] / fig.layout.polar.radialaxis.range[1]) * np.sin(np.radians(90-theta))
106
+ draw.text((img.width / 2 + x, img.height / 2 + y - 25), str(trace.name), font=font, fill=(0, 0, 0))
107
  file_path = os.path.join(output_dir, f"{student}_comparison.png")
108
  composite.save(file_path)
109
 
 
115
 
116
  return zip_path
117
 
118
+
119
  def main():
120
  st.title('學生成績雷達圖產生器')
121
 
 
148
  st.error("請至少選擇一個比較對象")
149
  else:
150
  zip_path = save_all_radar_charts(df, selected_columns, comparison_rows)
151
+ if zip_path: #check the path is valid
152
+ with open(zip_path, "rb") as f:
153
+ st.download_button(
154
+ label="下載壓縮檔",
155
+ data=f,
156
+ file_name="radar_charts.zip",
157
+ mime="application/zip",
158
+ key="download_button",
159
+ on_click=lambda: st.session_state.update({'download_triggered':True}),
160
+ disabled=st.session_state.get("download_triggered",False)
161
+ )
162
+ st.session_state.download_triggered = False
163
 
164
  if __name__ == "__main__":
165
  if 'download_triggered' not in st.session_state:
166
  st.session_state.download_triggered = False
167
+ import numpy as np
168
  main()