Gauge Chart

Health Risk Score

Patient risk assessment with adaptive color zones

Output
Health Risk Score
Python
import matplotlib.pyplot as plt
from matplotlib.patches import Wedge, Circle, Polygon
import numpy as np

# Data
risk = 35
max_value = 100

# Dynamic color
if risk < 30:
    arc_color = '#27F5B0'
    status = 'Low Risk'
elif risk < 60:
    arc_color = '#F5B027'
    status = 'Moderate Risk'
else:
    arc_color = '#F54927'
    status = 'High Risk'

# Colors - Light theme
bg_color = '#ffffff'
track_color = '#f3f4f6'
text_color = '#1f2937'
dim_color = '#9ca3af'

start_angle, end_angle = -30, 210
sweep = end_angle - start_angle

fig, ax = plt.subplots(figsize=(10, 8), facecolor=bg_color)
ax.set_facecolor(bg_color)
ax.set_xlim(-1.4, 1.4)
ax.set_ylim(-0.5, 1.4)
ax.set_aspect('equal')
ax.axis('off')

# Risk zones on track
zones = [(0, 30, '#dcfce7'), (30, 60, '#fef3c7'), (60, 100, '#fee2e2')]
for z_start, z_end, z_color in zones:
    z_s_ang = end_angle - (z_start / 100) * sweep
    z_e_ang = end_angle - (z_end / 100) * sweep
    ax.add_patch(Wedge((0, 0), 1.0, z_e_ang, z_s_ang, width=0.15,
                       facecolor=z_color, edgecolor='none'))

# Value arc
value_pct = risk / 100
value_angle = start_angle + (1 - value_pct) * sweep
for r_off, w_off, alpha in [(0.03, 0.04, 0.2), (0.015, 0.02, 0.45), (0, 0, 0.95)]:
    ax.add_patch(Wedge((0, 0), 1.0 + r_off, value_angle, end_angle,
                       width=0.15 + w_off, facecolor=arc_color, edgecolor='none', alpha=alpha))

# Ticks
for i in range(11):
    pct = i / 10
    angle = np.radians(end_angle - pct * sweep)
    r1, r2 = (0.87, 0.80) if i % 5 == 0 else (0.87, 0.83)
    ax.plot([r1*np.cos(angle), r2*np.cos(angle)], 
            [r1*np.sin(angle), r2*np.sin(angle)], color='#d1d5db', linewidth=2 if i%5==0 else 1)
    if i % 5 == 0:
        ax.text(0.72*np.cos(angle), 0.72*np.sin(angle), f'{int(pct*100)}',
                fontsize=11, color=dim_color, ha='center', va='center')

# Needle
needle_angle = np.radians(end_angle - value_pct * sweep)
nx, ny = 0.62 * np.cos(needle_angle), 0.62 * np.sin(needle_angle)
perp = needle_angle + np.pi/2
bx1, by1 = 0.035 * np.cos(perp), 0.035 * np.sin(perp)

ax.add_patch(Polygon([(nx+0.01, ny-0.01), (bx1+0.01, by1-0.01), (-bx1+0.01, -by1-0.01)],
                     facecolor='#000000', edgecolor='none', alpha=0.1))
ax.add_patch(Polygon([(nx, ny), (bx1, by1), (-bx1, -by1)], facecolor=text_color, edgecolor='none'))

# Hub
ax.add_patch(Circle((0.01, -0.01), 0.09, facecolor='#000000', edgecolor='none', alpha=0.08))
for r, c, a in [(0.10, arc_color, 0.2), (0.08, '#ffffff', 1), (0.06, arc_color, 0.9)]:
    ax.add_patch(Circle((0, 0), r, facecolor=c, edgecolor='none', alpha=a))

# Text
ax.text(0, -0.22, f'{risk}', fontsize=56, fontweight='bold', color=text_color, ha='center', va='center')
ax.text(0, -0.40, 'RISK SCORE', fontsize=13, color=dim_color, ha='center', va='center', fontweight='500')
ax.text(0, -0.56, status, fontsize=14, color=arc_color, ha='center', va='center', fontweight='bold')
ax.text(0, 1.22, 'Health Assessment', fontsize=18, fontweight='bold', color=text_color, ha='center', va='center')

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Part-to-Whole

Did this help you?

Support PyLucid to keep it free & growing

Support