basketball-tracker / visualizer /shot_chart.py
SportsByNumbers's picture
Update visualizer/shot_chart.py
6a2dffd verified
import matplotlib.pyplot as plt
# Basketball half-court dimensions in pixels (you may adjust)
COURT_WIDTH = 1280
COURT_HEIGHT = 720
def draw_half_court(ax):
# Court outline
ax.plot([0, COURT_WIDTH], [0, 0], color="black")
ax.plot([0, 0], [0, COURT_HEIGHT], color="black")
ax.plot([COURT_WIDTH, COURT_WIDTH], [0, COURT_HEIGHT], color="black")
ax.plot([0, COURT_WIDTH], [COURT_HEIGHT, COURT_HEIGHT], color="black")
# Hoop (approx)
hoop_x, hoop_y = 640, 180
hoop_radius = 15
hoop = plt.Circle((hoop_x, hoop_y), hoop_radius, color="orange", fill=False)
ax.add_patch(hoop)
# 3-point arc (simplified)
arc = plt.Circle((hoop_x, hoop_y), 230, color="gray", fill=False, linestyle='--')
ax.add_patch(arc)
def plot_shot_chart(shot_chart):
fig, ax = plt.subplots(figsize=(8, 6))
draw_half_court(ax)
for shot in shot_chart:
x, y = shot["player_position"]
color = "green" if shot["made"] else "red"
label = "Made" if shot["made"] else "Missed"
ax.scatter(x, y, c=color, s=60, label=label, alpha=0.7, edgecolors='black')
ax.set_xlim(0, COURT_WIDTH)
ax.set_ylim(COURT_HEIGHT, 0) # Flip Y-axis for visual realism
ax.set_title("Shot Chart (Green = Made, Red = Missed)")
ax.set_aspect("equal")
ax.axis("off")
# Remove duplicate legend entries
handles, labels = ax.get_legend_handles_labels()
unique = dict(zip(labels, handles))
ax.legend(unique.values(), unique.keys())
plt.tight_layout()
plt.show()