{"spec_id":"map-connection-lines","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nmap-connection-lines: Connection Lines Map (Origin-Destination)\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-05-28\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme tokens\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\"\n\n# Data: Major global flight routes between airports\nnp.random.seed(42)\n\nairports = {\n    \"JFK\": (40.6413, -73.7781, \"New York\"),\n    \"LAX\": (33.9416, -118.4085, \"Los Angeles\"),\n    \"LHR\": (51.4700, -0.4543, \"London\"),\n    \"CDG\": (49.0097, 2.5479, \"Paris\"),\n    \"NRT\": (35.7720, 140.3929, \"Tokyo\"),\n    \"SYD\": (-33.9399, 151.1753, \"Sydney\"),\n    \"DXB\": (25.2532, 55.3657, \"Dubai\"),\n    \"SIN\": (1.3644, 103.9915, \"Singapore\"),\n    \"HKG\": (22.3080, 113.9185, \"Hong Kong\"),\n    \"FRA\": (50.0379, 8.5622, \"Frankfurt\"),\n}\n\nroutes = [\n    (\"JFK\", \"LHR\", 4200),\n    (\"JFK\", \"CDG\", 2800),\n    (\"LAX\", \"NRT\", 3100),\n    (\"LAX\", \"SYD\", 1900),\n    (\"LHR\", \"DXB\", 3500),\n    (\"LHR\", \"SIN\", 2200),\n    (\"LHR\", \"HKG\", 2900),\n    (\"CDG\", \"NRT\", 1800),\n    (\"DXB\", \"SIN\", 2600),\n    (\"DXB\", \"HKG\", 2100),\n    (\"SIN\", \"SYD\", 2400),\n    (\"HKG\", \"NRT\", 2700),\n    (\"FRA\", \"JFK\", 3000),\n    (\"FRA\", \"DXB\", 2300),\n    (\"SIN\", \"NRT\", 1600),\n]\n\nmin_pass = min(r[2] for r in routes)\nmax_pass = max(r[2] for r in routes)\n\n# Map geographic colors (theme-adaptive)\nif THEME == \"light\":\n    land_color = \"#EAE8E1\"\n    ocean_color = \"#D5E5EE\"\n    coast_color = \"#9A9A92\"\n    country_color = \"#C2C0BA\"\nelse:\n    land_color = \"#252521\"\n    ocean_color = \"#1C2330\"\n    coast_color = \"#4A4A44\"\n    country_color = \"#383835\"\n\n# Create figure\nfig = go.Figure()\n\n# Flight routes — both color and width encode passenger volume (imprint_seq: #009E73 → #4467A3)\nfor origin, dest, passengers in routes:\n    origin_lat, origin_lon, origin_city = airports[origin]\n    dest_lat, dest_lon, dest_city = airports[dest]\n\n    t = (passengers - min_pass) / (max_pass - min_pass)\n    rc = int(0x00 + t * (0x44 - 0x00))\n    gc = int(0x9E + t * (0x67 - 0x9E))\n    bc = int(0x73 + t * (0xA3 - 0x73))\n    route_color = f\"#{rc:02X}{gc:02X}{bc:02X}\"\n    line_width = 2 + t * 7  # 2–9 px\n    opacity = 0.45 + t * 0.35  # 0.45–0.80\n\n    fig.add_trace(\n        go.Scattergeo(\n            lon=[origin_lon, dest_lon],\n            lat=[origin_lat, dest_lat],\n            mode=\"lines\",\n            line={\"width\": line_width, \"color\": route_color},\n            opacity=opacity,\n            hoverinfo=\"text\",\n            text=f\"{origin_city} → {dest_city}<br>{passengers:,}K passengers/year\",\n            showlegend=False,\n        )\n    )\n\n# Visual legend — three representative passenger volume levels with matching line style\nfor leg_label, leg_pass in [(\"Low (1.6M/yr)\", 1600), (\"Medium (2.9M/yr)\", 2900), (\"High (4.2M/yr)\", 4200)]:\n    t = (leg_pass - min_pass) / (max_pass - min_pass)\n    rc = int(0x00 + t * (0x44 - 0x00))\n    gc = int(0x9E + t * (0x67 - 0x9E))\n    bc = int(0x73 + t * (0xA3 - 0x73))\n    leg_color = f\"#{rc:02X}{gc:02X}{bc:02X}\"\n    fig.add_trace(\n        go.Scattergeo(\n            lon=[None],\n            lat=[None],\n            mode=\"lines\",\n            line={\"width\": 2 + t * 7, \"color\": leg_color},\n            opacity=0.45 + t * 0.35,\n            name=leg_label,\n            showlegend=True,\n        )\n    )\n\n# Airport markers — anyplot ochre (#BD8233) contrasts with the green-blue route palette\ntext_positions = {\n    \"LHR\": \"bottom left\",\n    \"CDG\": \"top right\",\n    \"FRA\": \"bottom right\",\n    \"JFK\": \"bottom right\",\n    \"LAX\": \"bottom left\",\n    \"SYD\": \"bottom center\",\n}\nairport_codes = list(airports.keys())\nairport_lons = [airports[code][1] for code in airport_codes]\nairport_lats = [airports[code][0] for code in airport_codes]\nairport_hover = [f\"{airports[code][2]} ({code})\" for code in airport_codes]\nairport_textpos = [text_positions.get(code, \"top center\") for code in airport_codes]\n\nfig.add_trace(\n    go.Scattergeo(\n        lon=airport_lons,\n        lat=airport_lats,\n        mode=\"markers+text\",\n        marker={\"size\": 12, \"color\": \"#BD8233\", \"line\": {\"width\": 2, \"color\": INK}},\n        text=airport_codes,\n        textposition=airport_textpos,\n        textfont={\"size\": 10, \"color\": INK, \"family\": \"Arial\"},\n        hoverinfo=\"text\",\n        hovertext=airport_hover,\n        name=\"Airports\",\n        showlegend=True,\n    )\n)\n\n# Title with auto-scaled fontsize (baseline 67 chars → 16px)\ntitle = \"Global Flight Routes · map-connection-lines · python · plotly · anyplot.ai\"\ntitle_fontsize = max(11, round(16 * 67 / len(title))) if len(title) > 67 else 16\n\nfig.update_layout(\n    autosize=False,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    title={\"text\": title, \"font\": {\"size\": title_fontsize, \"color\": INK}, \"x\": 0.5, \"xanchor\": \"center\"},\n    geo={\n        \"projection_type\": \"natural earth\",\n        \"showland\": True,\n        \"landcolor\": land_color,\n        \"showocean\": True,\n        \"oceancolor\": ocean_color,\n        \"showcoastlines\": True,\n        \"coastlinecolor\": coast_color,\n        \"coastlinewidth\": 0.8,\n        \"showlakes\": True,\n        \"lakecolor\": ocean_color,\n        \"showcountries\": True,\n        \"countrycolor\": country_color,\n        \"countrywidth\": 0.4,\n        \"showframe\": False,\n        \"bgcolor\": PAGE_BG,\n    },\n    legend={\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"font\": {\"color\": INK_SOFT, \"size\": 10},\n        \"title\": {\"text\": \"Passenger volume\", \"font\": {\"size\": 10, \"color\": INK_SOFT}},\n        \"x\": 0.01,\n        \"y\": 0.01,\n        \"xanchor\": \"left\",\n        \"yanchor\": \"bottom\",\n    },\n    margin={\"l\": 20, \"r\": 20, \"t\": 70, \"b\": 20},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}