import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap
[docs]
class Semi_Circle_Gauge():
def __init__(self):
# Create a polar plot for the speedometer background
self.fig, self.ax = plt.subplots(figsize=(6, 3), subplot_kw={'projection': 'polar'})
self.ax.set_theta_zero_location('W')
self.ax.set_theta_direction(-1)
[docs]
def plot_background(self):
# Define the ranges for red, yellow, and green
theta = np.linspace(0, np.pi, 500)
# Create metallic gradient for green with highlights for a modern effect
green_cmap = LinearSegmentedColormap.from_list(
"metallic_green", ["#003300", "#00FF00", "#66FF66", "#00FF00", "#003300"]
)
green_colors = green_cmap(np.linspace(0, 1, 500))
self.ax.fill_between(theta, 0, 1, where=(theta <= np.pi/3), color=None, alpha=0.7, facecolor=green_colors)
# green_cmap = LinearSegmentedColormap.from_list("metallic_green", ["#006400", "#00FF00", "#006400"])
# green_colors = green_cmap(np.linspace(0, 1, 500))
# ax.fill_between(theta, 0, 1, where=(theta <= np.pi/3), color=None, alpha=0.7, facecolor=green_colors)
# Create metallic gradient for yellow
yellow_cmap = LinearSegmentedColormap.from_list("metallic_yellow", ["#FFD700", "#FFFF00", "#FFD700"])
yellow_colors = yellow_cmap(np.linspace(0, 1, 500))
self.ax.fill_between(theta, 0, 1, where=((theta > np.pi/3) & (theta <= 2*np.pi/3)), color=None, alpha=0.7, facecolor=yellow_colors)
# Create metallic gradient for red
red_cmap = LinearSegmentedColormap.from_list("metallic_red", ["#8B0000", "#FF0000", "#8B0000"])
red_colors = red_cmap(np.linspace(0, 1, 500))
self.ax.fill_between(theta, 0, 1, where=(theta > 2*np.pi/3), color=None, alpha=0.7, facecolor=red_colors)
# Remove polar grid and labels for a clean look
self.ax.grid(False)
self.ax.set_yticks([])
self.ax.set_xticks([])
self.ax.set_ylim(0, 1)
self.ax.set_xlim(0, np.pi)
[docs]
def plot_needle(self, value, color='black'):
# Add a needle to indicate a specific value
width = 0.1 # Needle width
self.ax.fill([value, value-width, value, value+width, value],
[0, .25, .9, .25, 0], color='black', linewidth=2, zorder=5)
self.ax.plot([value, value+width*.9, value],
[.9, .25, 0], color='grey', linewidth=2, zorder=6)
self.ax.plot([value, value+width, value],
[.9, .25, 0], color='white', linewidth=1, zorder=6)
# Plot a black semi-circle at the origin
semi_circle = plt.Circle((0, 0), 0.1, transform=self.ax.transData._b, color='black', zorder=7)
self.ax.add_artist(semi_circle)
[docs]
def plot_text(self, text, value):
# Add text to the speedometer
# The text is above the speedometer in the center
# The value is the angle of the needle
self.ax.text(np.pi/2., 1.15, text, fontsize=12, ha='center', va='center', color='black')
[docs]
class Rectangular_Gauge():
def __init__(self, horizontal_or_vertical='vertical'):
# Create a rectangular plot for the speedometer background
if horizontal_or_vertical == 'horizontal':
self.fig, self.ax = plt.subplots(figsize=(6, 3))
self.direction = 'horizontal'
else:
# Default to vertical if not specified
self.fig, self.ax = plt.subplots(figsize=(3, 6))
self.direction = 'vertical'
self.ax.set_xlim(0, 1)
self.ax.set_ylim(0, 1)
[docs]
def plot_background(self):
# Define the ranges for red, yellow, and green
if self.direction == 'horizontal':
# Horizontal speedometer
self.ax.fill_between([0, 1/3], 0, 1, color='green', alpha=0.7)
self.ax.fill_between([1/3, 2/3], 0, 1, color='yellow', alpha=0.7)
self.ax.fill_between([2/3, 1], 0, 1, color='red', alpha=0.7)
else:
# Vertical speedometer
self.ax.fill_between([0, 1], 0, 1/3, color='green', alpha=0.7)
self.ax.fill_between([0, 1], 1/3, 2/3, color='yellow', alpha=0.7)
self.ax.fill_between([0, 1], 2/3, 1, color='red', alpha=0.7)
# Remove grid and ticks for a clean look
self.ax.grid(False)
self.ax.set_xticks([])
self.ax.set_yticks([])
[docs]
def plot_needle(self, value):
# Add a needle to indicate a specific value
width = 0.01 # Needle width
if self.direction == 'horizontal':
# Horizontal speedometer
self.ax.fill([value-width, value+width, value+width, value-width],
[0.25, 0.25, 0.9, 0.9], color='black', linewidth=2)
else:
# Vertical speedometer
self.ax.fill([0, 1, 1, 0],
[value-width, value-width, value+width, value+width], color='black', linewidth=2)
[docs]
def plot_text(self, text, value):
# Add text to the speedometer
self.ax.text(0.5, 1.15, text, fontsize=12, ha='center', va='center', color='black')
if __name__ == "__main__":
# Test the speedometer function
[docs]
fig = Semi_Circle_Gauge()
import matplotlib.animation as animation
def update(frame):
fig.ax.clear()
fig.plot_background() # Reinitialize the speedometer to clear previous needle
fig.plot_needle(frame)
fig.plot_text("Danger: {:.2f}".format(frame), frame)
# Create an animation with values ranging from 0 to π
ani = animation.FuncAnimation(fig.fig, update, frames=np.linspace(0, np.pi, 100), interval=50)
plt.show()
pass