{"spec_id":"circos-basic","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\ncircos-basic: Circos Plot\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 91/100 | Created: 2026-05-15\n\"\"\"\n\nimport math\nimport os\nimport sys\n\nimport numpy as np\n\n\n# Handle the name conflict: load pygal from site-packages first\n# Remove current directory from path to prevent the script from shadowing pygal module\noriginal_path = sys.path.copy()\nif \"\" in sys.path:\n    sys.path.remove(\"\")\nif \".\" in sys.path:\n    sys.path.remove(\".\")\n\n# Now safe to import pygal\nimport pygal\nfrom pygal.style import Style\n\n\n# Restore path for other operations\nsys.path = original_path\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=IMPRINT,\n    title_font_size=28,\n    label_font_size=22,\n    major_label_font_size=18,\n    legend_font_size=16,\n    value_font_size=14,\n    stroke_width=3,\n)\n\n# Data: genomic segments with inter-chromosomal connections\nnp.random.seed(42)\nsegments = [\"Chr1\", \"Chr2\", \"Chr3\", \"Chr4\", \"Chr5\", \"Chr6\", \"Chr7\", \"Chr8\", \"Chr9\", \"Chr10\"]\nn_segments = len(segments)\n\n# Calculate angle for each segment\nsegment_angles = np.linspace(0, 2 * np.pi, n_segments, endpoint=False)\n\n# Create XY scatter plot arranged in circle\nchart = pygal.XY(\n    style=custom_style,\n    width=4800,\n    height=2700,\n    title=\"circos-basic · pygal · anyplot.ai\",\n    x_title=\"\",\n    y_title=\"\",\n    show_legend=True,\n    dots_size=6,\n    stroke_style={\"width\": 3},\n)\n\nchart.x_labels = []\nchart.y_labels = []\n\nouter_radius = 90\n\n# Create segment points on outer circle\nsegment_points = []\nfor i, (angle, segment) in enumerate(zip(segment_angles, segments)):\n    x = outer_radius * math.cos(angle)\n    y = outer_radius * math.sin(angle)\n    segment_points.append((x, y, segment, IMPRINT[i % len(IMPRINT)]))\n\n# Add segment positions as points\nfor x, y, segment, _color in segment_points:\n    chart.add(segment, [(x, y)], dots_size=10, allow_interruptions=True)\n\n# Create connections between segments\nconnections = [\n    (0, 3, 45),\n    (1, 4, 60),\n    (2, 5, 55),\n    (3, 6, 40),\n    (4, 7, 65),\n    (5, 8, 50),\n    (6, 9, 35),\n    (0, 5, 70),\n    (1, 8, 48),\n    (2, 7, 52),\n    (3, 9, 38),\n]\n\n# Create arc points for connections\nfor source_idx, target_idx, magnitude in connections:\n    source_x, source_y, _, _ = segment_points[source_idx]\n    target_x, target_y, _, _ = segment_points[target_idx]\n\n    curve_factor = 0.3 + (magnitude / 100) * 0.4\n    inner_radius = outer_radius * (1 - curve_factor)\n\n    arc_points = []\n    for t in np.linspace(0, 1, 20):\n        angle_interp = segment_angles[source_idx] * (1 - t) + segment_angles[target_idx] * t\n        radius_t = outer_radius - ((outer_radius - inner_radius) * 4 * t * (1 - t))\n        x = radius_t * math.cos(angle_interp)\n        y = radius_t * math.sin(angle_interp)\n        arc_points.append((x, y))\n\n    chart.add(\"\", arc_points, show_legend=False, dots_size=0, allow_interruptions=True)\n\n# Render outputs\nchart.render_to_png(f\"plot-{THEME}.png\")\n\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}