-
Notifications
You must be signed in to change notification settings - Fork 0
update(chord-basic): matplotlib — comprehensive review #5212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
95a47d9
c853944
f8957fc
177fb1f
2becacf
8d570b3
b28c43f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,7 @@ | ||||||||
| """ pyplots.ai | ||||||||
| """pyplots.ai | ||||||||
| chord-basic: Basic Chord Diagram | ||||||||
| Library: matplotlib 3.10.8 | Python 3.13.11 | ||||||||
| Quality: 98/100 | Created: 2025-12-14 | ||||||||
| Library: matplotlib 3.10.8 | Python 3.14 | ||||||||
| Quality: /100 | Updated: 2026-04-06 | ||||||||
| """ | ||||||||
|
|
||||||||
| import matplotlib.patches as mpatches | ||||||||
|
|
@@ -11,11 +11,9 @@ | |||||||
|
|
||||||||
|
|
||||||||
| # Data: Migration flows between continents (in millions) | ||||||||
| np.random.seed(42) | ||||||||
| entities = ["Africa", "Asia", "Europe", "N. America", "S. America", "Oceania"] | ||||||||
| n = len(entities) | ||||||||
|
|
||||||||
| # Flow matrix (row=source, col=target) | ||||||||
| flow_matrix = np.array( | ||||||||
| [ | ||||||||
| [0, 12, 8, 5, 2, 1], # From Africa | ||||||||
|
|
@@ -27,157 +25,123 @@ | |||||||
| ] | ||||||||
| ) | ||||||||
|
|
||||||||
| # Colors for each entity (colorblind-safe palette) | ||||||||
| colors = ["#306998", "#FFD43B", "#4ECDC4", "#FF6B6B", "#95E1A3", "#DDA0DD"] | ||||||||
| # Colorblind-safe palette starting with Python Blue | ||||||||
| colors = ["#306998", "#E69F00", "#009E73", "#D55E00", "#56B4E9", "#CC79A7"] | ||||||||
|
|
||||||||
| # Calculate totals for each entity (sum of outgoing + incoming) | ||||||||
| # Calculate entity totals and arc geometry | ||||||||
| totals = flow_matrix.sum(axis=1) + flow_matrix.sum(axis=0) | ||||||||
| total_flow = totals.sum() | ||||||||
| gap_deg = 3 | ||||||||
| available_deg = 360 - gap_deg * n | ||||||||
| arc_spans = (totals / total_flow) * available_deg | ||||||||
|
|
||||||||
| # Gap between entity arcs (in degrees) | ||||||||
| gap = 3 | ||||||||
| total_gap = gap * n | ||||||||
| available_degrees = 360 - total_gap | ||||||||
|
|
||||||||
| # Calculate arc spans for each entity | ||||||||
| arc_spans = (totals / total_flow) * available_degrees | ||||||||
|
|
||||||||
| # Calculate start angles for each entity arc | ||||||||
| # Start angles (clockwise from top) | ||||||||
| start_angles = np.zeros(n) | ||||||||
| current_angle = 90 # Start from top | ||||||||
| angle = 90 | ||||||||
| for i in range(n): | ||||||||
| start_angles[i] = current_angle | ||||||||
| current_angle -= arc_spans[i] + gap | ||||||||
| start_angles[i] = angle | ||||||||
| angle -= arc_spans[i] + gap_deg | ||||||||
|
|
||||||||
| # Create figure | ||||||||
| # Plot | ||||||||
| fig, ax = plt.subplots(figsize=(16, 9), subplot_kw={"aspect": "equal"}) | ||||||||
| ax.set_xlim(-1.5, 1.5) | ||||||||
| ax.set_ylim(-1.3, 1.3) | ||||||||
| ax.set_xlim(-1.55, 1.55) | ||||||||
| ax.set_ylim(-1.35, 1.35) | ||||||||
| ax.axis("off") | ||||||||
|
|
||||||||
| # Draw entity arcs on the outer ring | ||||||||
| radius = 1.0 | ||||||||
| arc_width = 0.08 | ||||||||
| inner_r = radius - arc_width | ||||||||
|
|
||||||||
| # Draw outer arcs | ||||||||
| for i in range(n): | ||||||||
| theta1 = start_angles[i] - arc_spans[i] | ||||||||
| theta2 = start_angles[i] | ||||||||
|
|
||||||||
| # Draw outer arc as a wedge | ||||||||
| wedge = mpatches.Wedge( | ||||||||
| (0, 0), radius, theta1, theta2, width=arc_width, facecolor=colors[i], edgecolor="white", linewidth=2 | ||||||||
| ) | ||||||||
| ax.add_patch(wedge) | ||||||||
|
|
||||||||
| # Add entity label | ||||||||
| mid_angle = (theta1 + theta2) / 2 | ||||||||
| label_radius = radius + 0.12 | ||||||||
| label_x = label_radius * np.cos(np.radians(mid_angle)) | ||||||||
| label_y = label_radius * np.sin(np.radians(mid_angle)) | ||||||||
| # Label placement | ||||||||
| mid = np.radians((theta1 + theta2) / 2) | ||||||||
| lx, ly = (radius + 0.12) * np.cos(mid), (radius + 0.12) * np.sin(mid) | ||||||||
| mid_deg = np.degrees(mid) % 360 | ||||||||
| ha = ( | ||||||||
| "center" | ||||||||
| if mid_deg < 15 or mid_deg > 345 or 165 < mid_deg < 195 | ||||||||
| else ("right" if 90 < mid_deg < 270 else "left") | ||||||||
| ) | ||||||||
| ax.text(lx, ly, entities[i], fontsize=18, fontweight="bold", ha=ha, va="center", color=colors[i]) | ||||||||
|
|
||||||||
| # Rotate text to align with arc | ||||||||
| rotation = mid_angle | ||||||||
| if mid_angle > 90 or mid_angle < -90: | ||||||||
| rotation = mid_angle + 180 | ||||||||
| if 90 < mid_angle < 270 or -270 < mid_angle < -90: | ||||||||
| ha = "right" | ||||||||
| else: | ||||||||
| ha = "left" | ||||||||
| if abs(mid_angle) < 10 or abs(mid_angle - 180) < 10 or abs(mid_angle + 180) < 10: | ||||||||
| ha = "center" | ||||||||
| # Track angular position within each arc for chord placement | ||||||||
| arc_cursors = start_angles.copy() | ||||||||
|
Comment on lines
+77
to
+78
|
||||||||
| # Track angular position within each arc for chord placement | |
| arc_cursors = start_angles.copy() | |
| # Angular span per unit of flow for chord placement |
Copilot
AI
Apr 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flows is computed and sorted but never used (the code renders based on chord_params instead). Remove flows and/or update the surrounding comment so it matches the actual draw-order logic.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,15 +1,15 @@ | ||||||
| library: matplotlib | ||||||
| specification_id: chord-basic | ||||||
| created: 2025-12-14 19:45:02+00:00 | ||||||
| updated: 2025-12-14 19:45:02+00:00 | ||||||
| generated_by: claude-opus-4-5-20251101 | ||||||
| updated: 2026-04-06T20:26:19+00:00 | ||||||
| generated_by: claude-opus-4-6 | ||||||
| workflow_run: 20213174710 | ||||||
| issue: 858 | ||||||
| python_version: 3.13.11 | ||||||
| python_version: '3.14' | ||||||
| library_version: 3.10.8 | ||||||
| preview_url: https://storage.googleapis.com/pyplots-images/plots/chord-basic/matplotlib/plot.png | ||||||
| preview_html: null | ||||||
| quality_score: 98 | ||||||
| quality_score: null | ||||||
|
||||||
| quality_score: null | |
| quality_score: 90 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Header metadata looks malformed:
Quality: /100is missing the numeric score. This likely breaks any parsers that extract quality/created/updated info from the standard 4-line header. Fill in the quality score (or use the establishedpendingpattern if it truly isn’t available).