{"spec_id":"line-3d-trajectory","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nline-3d-trajectory: 3D Line Plot for Trajectory Visualization\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 90/100 | Created: 2026-05-16\n\"\"\"\n\nimport os\nimport pathlib\nimport shutil\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\n\n\nLetsPlot.setup_html()\n\n# Theme\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\"\nBRAND = \"#009E73\"\n\n# Generate Lorenz attractor trajectory\nnp.random.seed(42)\ndt = 0.01\nnum_steps = 1200\nx, y, z = 0.1, 0.1, 0.1\nxs, ys, zs = [], [], []\n\nsigma = 10.0\nrho = 28.0\nbeta = 8.0 / 3.0\n\nfor _ in range(num_steps):\n    dx = sigma * (y - x)\n    dy = x * (rho - z) - y\n    dz = x * y - beta * z\n    x += dt * dx\n    y += dt * dy\n    z += dt * dz\n    xs.append(x)\n    ys.append(y)\n    zs.append(z)\n\ntime_steps = np.arange(num_steps)\n\n# Create DataFrame with computed 2D projection for visualization\n# Project 3D data to 2D while encoding the z-axis through color and secondary position\ndf = pd.DataFrame({\"x\": xs, \"y\": ys, \"z\": zs, \"time\": time_steps})\n\n# Normalize z for color encoding\nz_norm = (np.array(zs) - np.min(zs)) / (np.max(zs) - np.min(zs))\n\n# Create path-based visualization showing trajectory progression\n# Use x-y projection with z encoded as color gradient for temporal progression\nplot = (\n    ggplot(df, aes(x=\"x\", y=\"y\", color=\"time\"))\n    + geom_path(size=1.3, alpha=0.85)\n    + scale_color_viridis()\n    + ggsize(1600, 900)\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_grid_major=element_line(color=INK, size=0.2),\n        panel_grid_minor=element_blank(),\n        axis_title=element_text(color=INK, size=20, face=\"plain\"),\n        axis_text=element_text(color=INK_SOFT, size=16),\n        axis_line=element_line(color=INK_SOFT, size=0.5),\n        plot_title=element_text(color=INK, size=24, face=\"plain\"),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        legend_text=element_text(color=INK_SOFT, size=16),\n        legend_title=element_text(color=INK, size=16),\n        legend_position=\"right\",\n    )\n    + labs(\n        x=\"X Coordinate\", y=\"Y Coordinate\", color=\"Time Progression\", title=\"line-3d-trajectory · letsplot · anyplot.ai\"\n    )\n)\n\n# Save output\nggsave(plot, f\"plot-{THEME}.png\", scale=3)\nggsave(plot, f\"plot-{THEME}.html\")\n\n# Move files from lets-plot-images subdirectory to current directory if needed\nlpi_dir = pathlib.Path(\"lets-plot-images\")\nif lpi_dir.exists():\n    for ext in [\"png\", \"html\"]:\n        src = lpi_dir / f\"plot-{THEME}.{ext}\"\n        dst = pathlib.Path(f\"plot-{THEME}.{ext}\")\n        if src.exists() and not dst.exists():\n            shutil.copy(src, dst)\n"}