{"spec_id":"windbarb-basic","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nwindbarb-basic: Wind Barb Plot for Meteorological Data\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 83/100 | Updated: 2026-05-19\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nfrom matplotlib.patches import Circle\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n    },\n)\nsns.set_context(\"talk\", font_scale=1.2)\n\n# Data: Simulated surface wind observations from a grid of weather stations\nnp.random.seed(42)\n\n# Create a grid of observation points (6x4 grid = 24 stations)\nx_grid = np.linspace(2, 12, 6)\ny_grid = np.linspace(2, 8, 4)\nx, y = np.meshgrid(x_grid, y_grid)\nx = x.flatten()\ny = y.flatten()\n\nn_points = len(x)\n\n# Generate wind components with full range: calm, moderate, and strong (with pennants)\nbase_u = 20 * np.sin(x * 0.4) + 15\nbase_v = 15 * np.cos(y * 0.5) + 10\nnoise_u = np.random.randn(n_points) * 8\nnoise_v = np.random.randn(n_points) * 8\n\nu = base_u + noise_u\nv = base_v + noise_v\n\n# Force calm winds (< 2.5 knots) shown as open circles\ncalm_indices = [0, 11, 23]\nfor idx in calm_indices:\n    u[idx] = 0.5 * (np.random.rand() - 0.5)\n    v[idx] = 0.5 * (np.random.rand() - 0.5)\n\n# Force strong winds with pennants (50+ knots)\nstrong_indices = [5, 9, 18]\nfor idx in strong_indices:\n    angle = np.random.rand() * 2 * np.pi\n    speed_val = 55 + np.random.rand() * 15\n    u[idx] = speed_val * np.cos(angle)\n    v[idx] = speed_val * np.sin(angle)\n\nspeed = np.sqrt(u**2 + v**2)\n\ncalm_mask = speed < 2.5\nbarb_mask = ~calm_mask\n\n# Plot\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\nfig.subplots_adjust(bottom=0.15)\n\nif np.any(barb_mask):\n    barbs = ax.barbs(\n        x[barb_mask],\n        y[barb_mask],\n        u[barb_mask],\n        v[barb_mask],\n        speed[barb_mask],\n        cmap=\"viridis\",\n        length=9,\n        linewidth=2.5,\n        barb_increments={\"half\": 5, \"full\": 10, \"flag\": 50},\n        pivot=\"middle\",\n        clim=(0, 75),\n    )\n\n    cbar = plt.colorbar(barbs, ax=ax, pad=0.02)\n    cbar.set_label(\"Wind Speed (knots)\", fontsize=20, color=INK, rotation=270, labelpad=25)\n    cbar.ax.tick_params(labelsize=16, colors=INK_SOFT)\n    cbar.ax.yaxis.set_tick_params(color=INK_SOFT)\n    plt.setp(cbar.ax.yaxis.get_ticklabels(), color=INK_SOFT)\n    cbar.outline.set_edgecolor(INK_SOFT)\n\n# Calm winds as open circles (standard meteorological notation)\ncalm_circle_color = \"#440154\" if THEME == \"light\" else \"#90d743\"\nfor idx in np.where(calm_mask)[0]:\n    circle = Circle((x[idx], y[idx]), radius=0.35, fill=False, edgecolor=calm_circle_color, linewidth=3)\n    ax.add_patch(circle)\n\n# Style\nax.set_xlabel(\"Longitude (°E)\", fontsize=20, color=INK)\nax.set_ylabel(\"Latitude (°N)\", fontsize=20, color=INK)\nax.set_title(\"windbarb-basic · python · seaborn · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK)\nax.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\n\nax.set_xlim(0, 14)\nax.set_ylim(0, 10)\nax.grid(False)\n\nfor spine in ax.spines.values():\n    spine.set_color(INK_SOFT)\n    spine.set_linewidth(0.8)\n\nlegend_text = \"Barb notation: ○ = calm (<2.5 kt) | half barb = 5 kt | full barb = 10 kt | pennant ▲ = 50 kt\"\nfig.text(0.5, 0.02, legend_text, fontsize=16, ha=\"center\", va=\"bottom\", color=INK_MUTED)\n\n# Save\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}