diff --git a/plots/manhattan-gwas/implementations/python/highcharts.py b/plots/manhattan-gwas/implementations/python/highcharts.py index 27de648d9e..23b270cf33 100644 --- a/plots/manhattan-gwas/implementations/python/highcharts.py +++ b/plots/manhattan-gwas/implementations/python/highcharts.py @@ -1,13 +1,14 @@ -""" pyplots.ai +""" anyplot.ai manhattan-gwas: Manhattan Plot for GWAS -Library: highcharts unknown | Python 3.13.11 -Quality: 91/100 | Created: 2025-12-31 +Library: highcharts unknown | Python 3.13.13 +Quality: 93/100 | Updated: 2026-05-15 """ import json +import os +import subprocess import tempfile import time -import urllib.request from pathlib import Path import numpy as np @@ -15,6 +16,17 @@ from selenium.webdriver.chrome.options import Options +# Theme tokens +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +GRID = "rgba(26,26,23,0.10)" if THEME == "light" else "rgba(240,239,232,0.10)" + +# Okabe-Ito palette for alternating chromosomes +OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9", "#F0E442"] + # Data - Simulated GWAS data with random p-values and significant peaks np.random.seed(42) @@ -82,18 +94,20 @@ cumulative_offset += chr_sizes[chrom] chr_boundaries.append(cumulative_offset) -# Prepare series by chromosome for alternating colors +# Prepare series by chromosome with Okabe-Ito alternating colors series_data = [] for chrom in range(1, 23): chrom_points = [[d["x"], d["y"]] for d in all_data if d["chr"] == chrom] - color = "#306998" if chrom % 2 == 1 else "#7a7a7a" # Python Blue / Gray + # Use alternating Okabe-Ito colors + color_idx = (chrom - 1) % len(OKABE_ITO) + color = OKABE_ITO[color_idx] series_data.append( { "name": f"Chr {chrom}", "data": chrom_points, "color": color, "showInLegend": False, - "marker": {"radius": 6, "symbol": "circle"}, + "marker": {"radius": 8, "symbol": "circle"}, "turboThreshold": 0, "animation": False, } @@ -105,8 +119,23 @@ # Download Highcharts JS highcharts_url = "https://code.highcharts.com/highcharts.js" -with urllib.request.urlopen(highcharts_url, timeout=30) as response: - highcharts_js = response.read().decode("utf-8") +result = subprocess.run( + [ + "curl", + "-s", + "-A", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", + "-H", + "Accept: */*", + "-H", + "Referer: https://www.highcharts.com/", + highcharts_url, + ], + capture_output=True, + text=True, + timeout=30, +) +highcharts_js = result.stdout # Build Highcharts configuration chart_config = { @@ -114,62 +143,65 @@ "type": "scatter", "width": 4800, "height": 2700, - "backgroundColor": "#ffffff", + "backgroundColor": PAGE_BG, "marginBottom": 180, "marginTop": 120, "marginLeft": 150, "marginRight": 80, - "style": {"fontFamily": "Arial, sans-serif"}, + "style": {"fontFamily": "Arial, sans-serif", "color": INK}, + }, + "title": { + "text": "manhattan-gwas · highcharts · anyplot.ai", + "style": {"fontSize": "28px", "fontWeight": "bold", "color": INK}, }, - "title": {"text": "manhattan-gwas · highcharts · pyplots.ai", "style": {"fontSize": "64px", "fontWeight": "bold"}}, "subtitle": { "text": "Simulated GWAS Results Across Human Chromosomes", - "style": {"fontSize": "40px", "color": "#666666"}, + "style": {"fontSize": "22px", "color": INK_SOFT}, }, "xAxis": { - "title": {"text": "Chromosome", "style": {"fontSize": "48px", "fontWeight": "bold"}}, - "labels": {"style": {"fontSize": "36px"}, "y": 45}, + "title": {"text": "Chromosome", "style": {"fontSize": "22px", "fontWeight": "bold", "color": INK}}, + "labels": {"style": {"fontSize": "18px", "color": INK_SOFT}, "y": 45}, "tickPositions": tick_positions, "min": 0, "max": cumulative_offset, "tickLength": 0, - "lineWidth": 3, - "lineColor": "#333333", + "lineWidth": 2, + "lineColor": INK_SOFT, }, "yAxis": { - "title": {"text": "-log\u2081\u2080(p-value)", "style": {"fontSize": "48px", "fontWeight": "bold"}}, - "labels": {"style": {"fontSize": "36px"}}, + "title": {"text": "-log₁₀(p-value)", "style": {"fontSize": "22px", "fontWeight": "bold", "color": INK}}, + "labels": {"style": {"fontSize": "18px", "color": INK_SOFT}}, "min": 0, "max": 16, "gridLineWidth": 1, - "gridLineColor": "#e0e0e0", - "lineWidth": 3, - "lineColor": "#333333", + "gridLineColor": GRID, + "lineWidth": 2, + "lineColor": INK_SOFT, "plotLines": [ { "value": 7.3, - "color": "#DC2626", + "color": "#009E73", "width": 4, "dashStyle": "Dash", "zIndex": 5, "label": { - "text": "Genome-wide significance (p = 5\u00d710\u207b\u2078)", + "text": "Genome-wide significance (p = 5×10⁻⁸)", "align": "right", "x": -20, - "style": {"fontSize": "32px", "color": "#DC2626", "fontWeight": "bold"}, + "style": {"fontSize": "18px", "color": "#009E73", "fontWeight": "bold"}, }, }, { "value": 5, - "color": "#2563EB", + "color": INK_SOFT, "width": 3, "dashStyle": "Dot", "zIndex": 5, "label": { - "text": "Suggestive (p = 10\u207b\u2075)", + "text": "Suggestive (p = 10⁻⁵)", "align": "right", "x": -20, - "style": {"fontSize": "28px", "color": "#2563EB"}, + "style": {"fontSize": "16px", "color": INK_SOFT}, }, }, ], @@ -177,8 +209,8 @@ "legend": {"enabled": False}, "tooltip": { "headerFormat": "", - "pointFormat": "{series.name}
-log\u2081\u2080(p): {point.y:.2f}", - "style": {"fontSize": "24px"}, + "pointFormat": "{series.name}
-log₁₀(p): {point.y:.2f}", + "style": {"fontSize": "16px"}, }, "credits": {"enabled": False}, "series": series_data, @@ -193,7 +225,7 @@ - +