85 lines
3.6 KiB
Python
85 lines
3.6 KiB
Python
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
from matplotlib.patches import FancyBboxPatch, Rectangle
|
|
from matplotlib.colors import LinearSegmentedColormap
|
|
|
|
# Color scheme
|
|
green = '#8DC58D'
|
|
yellow = '#FBBC78'
|
|
red = '#F77F7F'
|
|
gray = '#DDDDDD'
|
|
light_blue = '#D9E8F5'
|
|
light_gray = '#F5F5F5'
|
|
|
|
# Data
|
|
categories = ["Resiko Hipertensi dalam 4 tahun (Hypertension Risk in 4 years)",
|
|
"Lingkar Pinggang (Waist Circumference)", "Tekanan Darah Sistolik (Systolic BP)",
|
|
"Tekanan Darah Diastolik (Diastolic BP)", "Indeks Massa Tubuh (BMI)"]
|
|
values = [51.17, 93.0, 132.0, 88.0, 31.11]
|
|
ranges = [(0, 100, [5, 10]), (60, 120, [80]), (70, 180, [90, 130, 140]), (50, 120, [60, 85, 90]), (15, 40, [18.5, 23, 25, 30])]
|
|
colors = [[green, yellow, red], # Hypertension
|
|
[green, red], # Waist
|
|
[yellow, green, yellow, red], # Systolic BP
|
|
[yellow, green, yellow, red], # Diastolic BP
|
|
[yellow, green, yellow, red, red]] # BMI
|
|
|
|
fig, axes = plt.subplots(len(categories), 1, figsize=(12, 7))
|
|
|
|
for i, ax in enumerate(axes):
|
|
min_val, max_val, thresholds = ranges[i]
|
|
value = values[i]
|
|
|
|
# First create a background bar (gray) with rounded corners
|
|
bg_rect = FancyBboxPatch((min_val, 0), max_val - min_val, 0.1,
|
|
boxstyle="round,pad=0.01",
|
|
facecolor=gray, alpha=0.3, linewidth=0)
|
|
ax.add_patch(bg_rect)
|
|
|
|
# Create segments
|
|
y_gap = 0.01 # Define the gap between segments on the y-axis
|
|
ax.set_ylim(-y_gap, 0.1 + y_gap) # Adjust the y-axis limits to include the gap
|
|
all_points = [min_val] + thresholds + [max_val]
|
|
for j in range(len(all_points)-1):
|
|
start = all_points[j]
|
|
end = all_points[j+1]
|
|
|
|
if i == 0: # Apply gradient only for the first chart's first segment
|
|
# Define the gradient colormap
|
|
gradient_cmap = LinearSegmentedColormap.from_list("gradient", [gray, colors[i][j]], N=256)
|
|
|
|
# Create a gradient rectangle usingimshow
|
|
gradient_width = value - start
|
|
if gradient_width > 0:
|
|
gradient_rect = plt.Rectangle((start, y_gap), gradient_width, 0.1 - 2*y_gap, facecolor=gradient_cmap(0.9), linewidth=0)
|
|
ax.add_patch(gradient_rect)
|
|
|
|
# Fill the remaining part with gray
|
|
remaining_width = end - max(value, start)
|
|
if remaining_width > 0:
|
|
remaining_rect = plt.Rectangle((max(value, start), y_gap), remaining_width, 0.1 - 2*y_gap, facecolor=gray, linewidth=0)
|
|
ax.add_patch(remaining_rect)
|
|
else:
|
|
segment_width = end - start
|
|
rect = Rectangle((start, y_gap), segment_width, 0.1 - 2*y_gap,
|
|
facecolor=colors[i][j % len(colors[i])], linewidth=0)
|
|
ax.add_patch(rect)
|
|
|
|
# Plot value marker
|
|
ax.scatter([value], [0.06], color="white", marker="o", s=100, zorder=3, edgecolor='gray')
|
|
ax.text(value, 0.02, f"{value:.1f}", ha="center", fontsize=10, color="black", weight="bold",
|
|
fontfamily='monospace')
|
|
|
|
# Axis formatting - properly align ticks with segment boundaries
|
|
ax.set_xlim(min_val, max_val)
|
|
ax.set_yticks([])
|
|
ax.set_xticks(all_points) # Set ticks at exact boundary points
|
|
ax.set_title(categories[i], fontsize=12, weight="normal", fontfamily='sans-serif')
|
|
ax.spines['top'].set_visible(False)
|
|
ax.spines['right'].set_visible(False)
|
|
ax.spines['left'].set_visible(False)
|
|
|
|
filename = '1_bp_biometrik.png'
|
|
|
|
plt.tight_layout()
|
|
plt.savefig(filename, dpi=300, bbox_inches='tight')
|
|
print(f"Image saved as {filename}") |