import ssl import logging import gradio as gr import matplotlib.pyplot as plt from io import BytesIO import base64 from datetime import datetime # 로그 설정 #logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # SSL 인증서 검증 비활성화 ssl._create_default_https_context = ssl._create_unverified_context current_time = datetime.now().strftime("%b-%d-%Y") def load_css(): with open('style.css', 'r', encoding='utf-8') as file: css = file.read() return f"" def format_quantity(quantity): # 아주 작은 값을 0으로 처리 if abs(quantity) < 1e-5: # 임계값을 조정하여 더 적절한 값을 설정할 수 있습니다. quantity = 0 if quantity < 0: return f"({-quantity:,.1f})" else: return f"{quantity:,.1f}" def format_value(value): # 아주 작은 값을 0으로 처리 if abs(value) < 1e-5: # 임계값을 조정하여 더 적절한 값을 설정할 수 있습니다. value = 0 if value < 0: return f"({-value:,.0f})" else: return f"{value:,.0f}" currency_symbols = { "KRW": "₩", "USD": "$", "CAD": "$", "EUR": "€", "JPY": "¥", "GBP": "£" } def get_currency_symbol(currency_code): return currency_symbols.get(currency_code.upper(), "") def get_currency_codes(): return list(currency_symbols.keys()) currency_codes = get_currency_codes() # Helper function to add buttons def clear_buttons(inputs): clear_button = gr.ClearButton(value="Clear") clear_button.click( fn=lambda: [None] * len(inputs), inputs=[], outputs=inputs ) return clear_button def submit_buttons(inputs, update_fn, output): submit_button = gr.Button(value="Run", variant="primary") submit_button.click( fn=update_fn, inputs=inputs, outputs=output ) return submit_button def on_change(inputs, update_ouutput, outputs): for input_component in inputs: input_component.change( fn=update_ouutput, inputs=inputs, outputs=outputs ) def render_components(component_rows): for row in component_rows: if isinstance(row, list): with gr.Row(): for component in row: component.render() else: row.render() def create_tab(tab_name, inputs, outputs, update_fn, examples, component_rows): with gr.TabItem(tab_name): with gr.Row(): with gr.Column(elem_classes="input"): render_components(component_rows) clear_buttons(inputs) submit_buttons(inputs, update_fn, outputs) gr.Examples(examples=examples, cache_examples=False, inputs=inputs) with gr.Column(): outputs.render() on_change(inputs, update_fn, outputs) import matplotlib.pyplot as plt import numpy as np from io import BytesIO import base64 from matplotlib import font_manager # Global dictionary to store color mapping color_map_storage = {} def get_color_for_label(index, color_map, num_labels): """Retrieve or generate color for the given index.""" if index not in color_map_storage: cmap = plt.get_cmap(color_map) # Generate a color based on index (inverse of the index for color intensity) color_map_storage[index] = cmap(1 - index / (num_labels - 1)) return color_map_storage[index] def plot_donut_chart(data, color_map='Blues', font_path='Quicksand-Regular.ttf', legend_fontsize=30): # 데이터 필터링: 비중이 0이 아닌 항목만 추출 filtered_data = {k: v for k, v in data.items() if v > 0} if not filtered_data: return '

No data to display.

' # 데이터가 없는 경우 처리 # 비중에 따라 데이터를 정렬 sorted_data = sorted(filtered_data.items(), key=lambda item: item[1], reverse=True) labels, sizes = zip(*sorted_data) # 색상 맵을 설정 num_labels = len(labels) # 원형 차트의 색상 리스트 생성 colors = [get_color_for_label(i, color_map, num_labels) for i in range(num_labels)] # 도넛 차트 시각화 fig, ax = plt.subplots(figsize=(12, 8), dpi=300) # figsize와 dpi를 설정하여 해상도 높이기 wedges, _ = ax.pie( sizes, colors=colors, labels=[None]*num_labels, # 라벨을 없애기 autopct=None, # 값 표시를 없애기 startangle=-90, # 12시 방향부터 시작 pctdistance=0.85, wedgeprops=dict(width=0.4, edgecolor='w') # 도넛 차트 ) # y축 뒤집기 ax.invert_yaxis() # 범례 생성 handles = [plt.Line2D([0], [0], marker='o', color='w', label=f'{label} {size * 100:.1f}%', markersize=15, markerfacecolor=get_color_for_label(i, color_map, num_labels)) for i, (label, size) in enumerate(zip(labels, sizes))] # 범례 추가, 제목 제거, 글자 크기를 키우고 범례 박스를 조정 ax.legend(handles=handles, loc='upper left', bbox_to_anchor=(1, 1), prop=font_manager.FontProperties(fname=font_path, size=legend_fontsize), frameon=False) # 축을 숨깁니다. ax.axis('off') # SVG로 저장 buf = BytesIO() plt.savefig(buf, format='svg', bbox_inches='tight') # bbox_inches='tight'를 추가하여 범례가 잘리는 문제를 방지 plt.close(fig) buf.seek(0) # SVG 데이터를 base64로 인코딩 svg_str = buf.getvalue().decode('utf-8') return f''