{"spec_id":"phase-diagram","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nphase-diagram: Phase Diagram (State Space Plot)\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 81/100 | Updated: 2026-05-14\n\"\"\"\n\nimport numpy as np\nimport pygal\nfrom pygal.style import Style\n\n\n# Data: Damped pendulum phase space\n# The damped pendulum follows: d²x/dt² = -ω²x - γ(dx/dt)\n# This creates a spiral trajectory converging to equilibrium\n\nnp.random.seed(42)\n\n# Parameters for damped harmonic oscillator\nomega = 2.0  # Natural frequency\ngamma = 0.3  # Damping coefficient\ndt = 0.02  # Time step\nt_max = 15  # Total time\n\n# Generate trajectory using numerical integration (Euler method)\nt = np.arange(0, t_max, dt)\nn_points = len(t)\n\n# Initial conditions: displaced position, zero velocity\nx = np.zeros(n_points)\nv = np.zeros(n_points)  # v = dx/dt\nx[0] = 2.0  # Initial displacement\nv[0] = 0.0  # Initial velocity\n\n# Integrate the equations of motion\nfor i in range(1, n_points):\n    # Acceleration: a = -ω²x - γv\n    a = -(omega**2) * x[i - 1] - gamma * v[i - 1]\n    # Update velocity and position\n    v[i] = v[i - 1] + a * dt\n    x[i] = x[i - 1] + v[i] * dt\n\n# Also generate an undamped oscillator for comparison (limit cycle)\nx_undamped = np.zeros(n_points)\nv_undamped = np.zeros(n_points)\nx_undamped[0] = 1.5\nv_undamped[0] = 0.0\n\nfor i in range(1, n_points):\n    a = -(omega**2) * x_undamped[i - 1]\n    v_undamped[i] = v_undamped[i - 1] + a * dt\n    x_undamped[i] = x_undamped[i - 1] + v_undamped[i] * dt\n\n# Custom style for large canvas\ncustom_style = Style(\n    background=\"white\",\n    plot_background=\"white\",\n    foreground=\"#333333\",\n    foreground_strong=\"#333333\",\n    foreground_subtle=\"#666666\",\n    colors=(\"#306998\", \"#FFD43B\", \"#FF6B6B\"),\n    title_font_size=60,\n    label_font_size=40,\n    major_label_font_size=36,\n    legend_font_size=36,\n    value_font_size=28,\n    stroke_width=4,\n    opacity=0.85,\n    opacity_hover=1.0,\n)\n\n# Create XY chart (scatter plot with lines)\nchart = pygal.XY(\n    width=4800,\n    height=2700,\n    style=custom_style,\n    title=\"phase-diagram · pygal · pyplots.ai\",\n    x_title=\"Position x\",\n    y_title=\"Velocity dx/dt\",\n    show_dots=False,  # Lines only for smooth trajectory\n    stroke=True,\n    fill=False,\n    show_x_guides=True,\n    show_y_guides=True,\n    dots_size=3,\n    stroke_style={\"width\": 4},\n    legend_at_bottom=True,\n    legend_box_size=24,\n    truncate_legend=-1,\n    show_legend=True,\n)\n\n# Downsample for visualization (pygal works better with fewer points)\nstep = 3\ndamped_points = [(float(x[i]), float(v[i])) for i in range(0, n_points, step)]\nundamped_points = [(float(x_undamped[i]), float(v_undamped[i])) for i in range(0, n_points, step)]\n\n# Add trajectories\nchart.add(\"Damped Oscillator (γ=0.3)\", damped_points)\nchart.add(\"Undamped Oscillator (Limit Cycle)\", undamped_points)\n\n# Add fixed point marker at origin\nchart.add(\"Equilibrium (Fixed Point)\", [(0, 0)], dots_size=12, show_dots=True, stroke=False)\n\n# Save outputs\nchart.render_to_file(\"plot.html\")\nchart.render_to_png(\"plot.png\")\n"}