Spaces:
Sleeping
Sleeping
Download src/ui/chart_components.py from FajarHidaa/HumanPlusX: direct link, hf CLI and curl.
- Browser
- Download file 3.99 kB
-
https://huggingface.co/spaces/FajarHidaa/HumanPlusX/resolve/main/src/ui/chart_components.py
- Command line
-
hf download hf://spaces/FajarHidaa/HumanPlusX/src/ui/chart_components.py
-
curl -L -o chart_components.py https://huggingface.co/spaces/FajarHidaa/HumanPlusX/resolve/main/src/ui/chart_components.py
3.99 kB
| """ | |
| Human+ Chart Components | |
| Streamlit rendering wrappers untuk semua Plotly charts. | |
| Import dari sini di halaman mana saja. | |
| """ | |
| import streamlit as st | |
| from core.chart_builder import ( | |
| build_gauge_chart, | |
| build_biomarker_bar_chart, | |
| build_status_donut, | |
| get_gauge_preset, | |
| ) | |
| # Plotly config — hide toolbar, dark bg, responsive | |
| _PLOTLY_CONFIG = { | |
| "displayModeBar": False, | |
| "responsive": True, | |
| "staticPlot": False, | |
| } | |
| # Max gauge charts to show (avoid information overload) | |
| _MAX_GAUGES = 6 | |
| def render_gauge_grid(biomarkers: list[dict]): | |
| """ | |
| Render a responsive 2-column grid of gauge charts | |
| for the most important biomarkers (those with presets + non-neutral status). | |
| """ | |
| # Filter to biomarkers that have gauge presets AND are non-neutral | |
| gaugeables = [ | |
| b for b in biomarkers | |
| if b.get("raw_value") is not None | |
| and b.get("status") != "neutral" | |
| and get_gauge_preset(b["name"]) is not None | |
| ] | |
| # Sort danger → warning → optimal, cap at max | |
| priority = {"danger": 0, "warning": 1, "optimal": 2} | |
| gaugeables = sorted(gaugeables, key=lambda b: priority.get(b["status"], 3)) | |
| gaugeables = gaugeables[:_MAX_GAUGES] | |
| if not gaugeables: | |
| st.markdown(""" | |
| <div style=" | |
| text-align:center; padding:20px; | |
| font-family:'DM Sans',sans-serif; | |
| font-size:0.8rem; color:#4a4a6a | |
| ">Tidak ada marker dengan gauge preset yang tersedia.</div> | |
| """, unsafe_allow_html=True) | |
| return | |
| # Render in 2-column grid | |
| pairs = [gaugeables[i:i+2] for i in range(0, len(gaugeables), 2)] | |
| for pair in pairs: | |
| cols = st.columns(len(pair)) | |
| for col, b in zip(cols, pair): | |
| with col: | |
| preset = get_gauge_preset(b["name"]) | |
| if preset is None: | |
| continue | |
| range_lo, range_hi, opt_lo, opt_hi = preset | |
| try: | |
| fig = build_gauge_chart( | |
| name=b["name"], | |
| value=float(b["raw_value"]), | |
| unit=b.get("unit", ""), | |
| status=b["status"], | |
| range_lo=range_lo, | |
| range_hi=range_hi, | |
| optimal_lo=opt_lo, | |
| optimal_hi=opt_hi, | |
| height=210, | |
| ) | |
| st.plotly_chart( | |
| fig, | |
| use_container_width=True, | |
| config=_PLOTLY_CONFIG, | |
| key=f"gauge_{b['name'].replace(' ', '_')}", | |
| ) | |
| except Exception as e: | |
| # Graceful fallback — don't crash the whole page | |
| st.caption(f"⚠️ Chart tidak tersedia: {b['name']}") | |
| def render_biomarker_bar_chart(biomarkers: list[dict]): | |
| """ | |
| Render horizontal bar chart untuk semua biomarker. | |
| Color-coded by status sesuai Human+ brand. | |
| """ | |
| try: | |
| fig = build_biomarker_bar_chart(biomarkers, height=350) | |
| if fig is None: | |
| st.caption("Tidak ada data numerik untuk ditampilkan.") | |
| return | |
| st.plotly_chart( | |
| fig, | |
| use_container_width=True, | |
| config=_PLOTLY_CONFIG, | |
| key="biomarker_bar", | |
| ) | |
| except Exception: | |
| st.caption("⚠️ Chart tidak tersedia saat ini.") | |
| def render_status_donut(optimal: int, warning: int, danger: int): | |
| """ | |
| Render donut pie chart untuk summary status biomarker. | |
| Small chart cocok untuk sidebar atau kolom kecil. | |
| """ | |
| try: | |
| fig = build_status_donut(optimal, warning, danger) | |
| if fig is None: | |
| return | |
| st.plotly_chart( | |
| fig, | |
| use_container_width=True, | |
| config=_PLOTLY_CONFIG, | |
| key="status_donut", | |
| ) | |
| except Exception: | |
| pass # Non-critical — skip silently | |