diff --git a/plots/smith-chart-basic/implementations/seaborn.py b/plots/smith-chart-basic/implementations/seaborn.py new file mode 100644 index 0000000000..2ef5d2568f --- /dev/null +++ b/plots/smith-chart-basic/implementations/seaborn.py @@ -0,0 +1,173 @@ +""" pyplots.ai +smith-chart-basic: Smith Chart for RF/Impedance +Library: seaborn 0.13.2 | Python 3.13.11 +Quality: 90/100 | Created: 2026-01-15 +""" + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import seaborn as sns + + +# Set seaborn style for better aesthetics +sns.set_style("whitegrid") +sns.set_context("talk", font_scale=1.2) + +# Reference impedance (ohms) +z0 = 50 + +# Generate frequency sweep data (1 GHz to 6 GHz, 50 points) +np.random.seed(42) +n_points = 50 +freq_ghz = np.linspace(1, 6, n_points) + +# Simulate a realistic impedance locus (antenna-like behavior) +# Create a spiral pattern that doesn't close on itself (avoids label overlap) +t = np.linspace(0, 1.8 * np.pi, n_points) +# Spiral-like pattern typical of antenna impedance vs frequency with drift +z_real = 50 + 30 * np.sin(t) + 15 * np.cos(2 * t) + 10 * (t / (2 * np.pi)) +z_imag = 40 * np.sin(1.5 * t) + 20 * np.cos(t) - 15 * (t / (2 * np.pi)) + +# Normalize impedance to reference +z_norm = (z_real + 1j * z_imag) / z0 + +# Calculate reflection coefficient (Gamma) +gamma = (z_norm - 1) / (z_norm + 1) +gamma_real = gamma.real +gamma_imag = gamma.imag + +# Create figure (square for Smith chart) +fig, ax = plt.subplots(figsize=(12, 12)) + +# Draw Smith chart grid +# Constant resistance circles +r_values = [0, 0.2, 0.5, 1, 2, 5] +theta = np.linspace(0, 2 * np.pi, 200) + +for r in r_values: + # Circle center and radius in Gamma plane + center = r / (r + 1) + radius = 1 / (r + 1) + # Parametric circle + circle_x = center + radius * np.cos(theta) + circle_y = radius * np.sin(theta) + # Clip to unit circle + mask = circle_x**2 + circle_y**2 <= 1.001 + ax.plot(circle_x[mask], circle_y[mask], color="#306998", linewidth=1) + # Add r value labels on the real axis (inside unit circle) + if r > 0: + label_x = r / (r + 1) - 1 / (r + 1) + 0.02 # Left edge of circle + if label_x > -0.95: + ax.text(label_x, 0.03, f"r={r}", fontsize=10, color="#306998", va="bottom") + +# Constant reactance arcs +x_values = [0.2, 0.5, 1, 2, 5] + +for x in x_values: + # Positive reactance arc (inductive) + center_y = 1 / x + radius = 1 / x + arc_theta = np.linspace(-np.pi / 2, np.pi / 2, 200) + arc_x = 1 + radius * np.cos(arc_theta) + arc_y = center_y + radius * np.sin(arc_theta) + mask = (arc_x**2 + arc_y**2 <= 1.001) & (arc_x >= -0.001) + ax.plot(arc_x[mask], arc_y[mask], color="#D4A017", linewidth=1.5) + + # Negative reactance arc (capacitive) + arc_y_neg = -center_y + radius * np.sin(arc_theta) + mask_neg = (arc_x**2 + arc_y_neg**2 <= 1.001) & (arc_x >= -0.001) + ax.plot(arc_x[mask_neg], arc_y_neg[mask_neg], color="#D4A017", linewidth=1.5) + + # Add x value labels inside the unit circle boundary + if x <= 2: + label_angle = np.arctan(1 / x) + label_x_pos = 0.85 * np.cos(label_angle) + label_y_pos = 0.85 * np.sin(label_angle) + ax.text(label_x_pos, label_y_pos + 0.03, f"x={x}", fontsize=10, color="#D4A017", va="bottom", ha="center") + ax.text(label_x_pos, -label_y_pos - 0.03, f"x=-{x}", fontsize=10, color="#D4A017", va="top", ha="center") + +# Draw unit circle (|Gamma| = 1 boundary) +unit_theta = np.linspace(0, 2 * np.pi, 200) +ax.plot(np.cos(unit_theta), np.sin(unit_theta), color="#306998", linewidth=2.5) + +# Draw horizontal axis (real axis) +ax.axhline(0, color="#306998", linewidth=1.5, alpha=0.6) + +# Create DataFrame for seaborn plotting +df_locus = pd.DataFrame({"gamma_real": gamma_real, "gamma_imag": gamma_imag, "freq_ghz": freq_ghz}) + +# Plot impedance locus using seaborn lineplot for the trajectory +sns.lineplot( + data=df_locus, x="gamma_real", y="gamma_imag", color="#E74C3C", linewidth=3, ax=ax, legend=False, sort=False +) + +# Add markers at key frequency points using seaborn scatterplot +key_indices = [0, n_points // 4, n_points // 2, 3 * n_points // 4, n_points - 1] +df_markers = df_locus.iloc[key_indices].copy() +sns.scatterplot( + data=df_markers, + x="gamma_real", + y="gamma_imag", + s=200, + color="#E74C3C", + edgecolor="white", + linewidth=2, + ax=ax, + zorder=10, + legend=False, +) + +# Label key frequency points with smart positioning to avoid overlap +label_offsets = { + 0: (12, -18), + n_points // 4: (15, 12), + n_points // 2: (12, -18), + 3 * n_points // 4: (-60, 10), + n_points - 1: (-60, -15), +} + +for idx in key_indices: + offset = label_offsets.get(idx, (10, 10)) + ax.annotate( + f"{freq_ghz[idx]:.1f} GHz", + (gamma_real[idx], gamma_imag[idx]), + textcoords="offset points", + xytext=offset, + fontsize=14, + fontweight="bold", + color="#2C3E50", + ) + +# Mark the center (matched condition) +ax.scatter([0], [0], s=150, color="#27AE60", marker="+", linewidths=3, zorder=10) +ax.annotate( + "Z₀ (50Ω)", (0, 0), textcoords="offset points", xytext=(-40, -20), fontsize=14, color="#27AE60", fontweight="bold" +) + +# Add VSWR circle (|Gamma| = 0.5, VSWR = 3:1) +vswr_radius = 0.5 +vswr_circle_x = vswr_radius * np.cos(unit_theta) +vswr_circle_y = vswr_radius * np.sin(unit_theta) +ax.plot(vswr_circle_x, vswr_circle_y, "--", color="#9B59B6", linewidth=2) +ax.annotate("VSWR 3:1", (0.35, 0.35), fontsize=12, color="#9B59B6", fontweight="bold") + +# Styling +ax.set_xlim(-1.15, 1.15) +ax.set_ylim(-1.15, 1.15) +ax.set_aspect("equal") +ax.set_xlabel("Real(Γ)", fontsize=20) +ax.set_ylabel("Imag(Γ)", fontsize=20) +ax.set_title("smith-chart-basic · seaborn · pyplots.ai", fontsize=24, fontweight="bold", pad=20) +ax.tick_params(axis="both", labelsize=16) +ax.grid(False) # Turn off default grid, we drew our own Smith grid + +# Add legend with matching line styles +ax.plot([], [], color="#306998", linewidth=1, label="Constant R circles") +ax.plot([], [], color="#D4A017", linewidth=1.5, label="Constant X arcs") +ax.plot([], [], color="#E74C3C", linewidth=3, label="Impedance locus") +ax.plot([], [], color="#9B59B6", linewidth=2, linestyle="--", label="VSWR 3:1 circle") +ax.legend(loc="upper left", fontsize=14, framealpha=0.9) + +plt.tight_layout() +plt.savefig("plot.png", dpi=300, bbox_inches="tight") diff --git a/plots/smith-chart-basic/metadata/seaborn.yaml b/plots/smith-chart-basic/metadata/seaborn.yaml new file mode 100644 index 0000000000..55d28a8fdd --- /dev/null +++ b/plots/smith-chart-basic/metadata/seaborn.yaml @@ -0,0 +1,216 @@ +library: seaborn +specification_id: smith-chart-basic +created: '2026-01-15T21:52:07Z' +updated: '2026-01-15T22:10:29Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 21047488885 +issue: 3792 +python_version: 3.13.11 +library_version: 0.13.2 +preview_url: https://storage.googleapis.com/pyplots-images/plots/smith-chart-basic/seaborn/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/smith-chart-basic/seaborn/plot_thumb.png +preview_html: null +quality_score: 90 +review: + strengths: + - Excellent Smith chart grid implementation with proper constant R circles and X + arcs + - Smart frequency label positioning with manual offsets prevents overlap + - Complete feature set including VSWR circle and center marking + - Professional color scheme with good accessibility + - Title format exactly matches specification + weaknesses: + - Heavy reliance on matplotlib for grid drawing; seaborn only used for final locus + overlay + - Canvas utilization could be improved (square 12x12 on 16:9 target) + image_description: The plot displays a Smith chart for RF/impedance visualization. + The chart features a square 12x12 figure with proper aspect ratio. The outer boundary + is a dark blue unit circle representing |Γ|=1 (total reflection). Multiple constant + resistance circles (r=0.2, 0.5, 1, 2, 5) are drawn in blue, centered along the + horizontal real axis. Constant reactance arcs in gold/yellow (x=±0.2, ±0.5, ±1, + ±2) curve from the right edge. A red impedance locus curve traces the frequency + sweep from 1.0 GHz to 6.0 GHz, with five key frequency markers (1.0, 3.2, 4.8, + 3.6, 6.0 GHz) labeled in dark blue text. A dashed purple VSWR 3:1 circle (|Γ|=0.5) + is included. The center point is marked with a green '+' symbol and labeled 'Z₀ + (50Ω)'. A legend in the upper left shows all four element types. Axes are labeled + 'Real(Γ)' and 'Imag(Γ)' with appropriate font sizes. + criteria_checklist: + visual_quality: + score: 36 + max: 40 + items: + - id: VQ-01 + name: Text Legibility + score: 10 + max: 10 + passed: true + comment: Title at 24pt, axis labels at 20pt, tick labels at 16pt, frequency + annotations at 14pt bold - all clearly readable + - id: VQ-02 + name: No Overlap + score: 8 + max: 8 + passed: true + comment: Smart label positioning with custom offsets prevents all text overlap + - id: VQ-03 + name: Element Visibility + score: 6 + max: 8 + passed: true + comment: Impedance locus clearly visible with linewidth=3, markers s=200; + grid lines could be slightly thinner + - id: VQ-04 + name: Color Accessibility + score: 5 + max: 5 + passed: true + comment: Blue/gold/red/purple color scheme is colorblind-safe, high contrast + - id: VQ-05 + name: Layout Balance + score: 3 + max: 5 + passed: true + comment: Square 12x12 figure with xlim/ylim ±1.15 provides good margins, moderate + canvas utilization + - id: VQ-06 + name: Axis Labels + score: 2 + max: 2 + passed: true + comment: Real(Γ) and Imag(Γ) are descriptive for Smith chart context + - id: VQ-07 + name: Grid & Legend + score: 2 + max: 2 + passed: true + comment: Default grid disabled, custom Smith grid drawn with appropriate line + weights, legend well-placed + spec_compliance: + score: 25 + max: 25 + items: + - id: SC-01 + name: Plot Type + score: 8 + max: 8 + passed: true + comment: Correct Smith chart with constant resistance circles and reactance + arcs + - id: SC-02 + name: Data Mapping + score: 5 + max: 5 + passed: true + comment: Impedance correctly normalized to Z₀=50Ω, gamma calculated properly + - id: SC-03 + name: Required Features + score: 5 + max: 5 + passed: true + comment: 'All spec features: grid circles/arcs, impedance locus, frequency + labels, VSWR circle, center marking' + - id: SC-04 + name: Data Range + score: 3 + max: 3 + passed: true + comment: Unit circle boundary properly shown with ±1.15 limits + - id: SC-05 + name: Legend Accuracy + score: 2 + max: 2 + passed: true + comment: Legend correctly identifies all four element types + - id: SC-06 + name: Title Format + score: 2 + max: 2 + passed: true + comment: 'Uses exact format: smith-chart-basic · seaborn · pyplots.ai' + data_quality: + score: 18 + max: 20 + items: + - id: DQ-01 + name: Feature Coverage + score: 7 + max: 8 + passed: true + comment: Shows spiral impedance locus typical of antenna behavior, crosses + multiple grid regions + - id: DQ-02 + name: Realistic Context + score: 7 + max: 7 + passed: true + comment: RF antenna impedance sweep 1-6 GHz is a realistic VNA measurement + scenario + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 5 + passed: true + comment: Z₀=50Ω standard, impedance values reasonable for antenna (30-80Ω + range) + code_quality: + score: 8 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Linear flow: imports → data → Smith grid → seaborn plots → styling + → save' + - id: CQ-02 + name: Reproducibility + score: 3 + max: 3 + passed: true + comment: np.random.seed(42) set + - id: CQ-03 + name: Clean Imports + score: 0 + max: 2 + passed: false + comment: sns and pd imports present but seaborn barely used beyond lineplot/scatterplot + - id: CQ-04 + name: No Deprecated API + score: 1 + max: 1 + passed: true + comment: All APIs current + - id: CQ-05 + name: Output Correct + score: 1 + max: 1 + passed: true + comment: Saves as plot.png with dpi=300 + library_features: + score: 3 + max: 5 + items: + - id: LF-01 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses sns.lineplot and sns.scatterplot with DataFrames, sns.set_style/set_context + for theming, but heavy matplotlib reliance for grid drawing + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - annotations + - patches + - manual-ticks + - custom-legend + patterns: + - data-generation + - iteration-over-groups + - explicit-figure + dataprep: [] + styling: + - edge-highlighting + - grid-styling