diff --git a/plots/circos-basic/implementations/python/highcharts.py b/plots/circos-basic/implementations/python/highcharts.py index 0424b07bf9..41d6498b81 100644 --- a/plots/circos-basic/implementations/python/highcharts.py +++ b/plots/circos-basic/implementations/python/highcharts.py @@ -1,10 +1,11 @@ -""" pyplots.ai +""" anyplot.ai circos-basic: Circos Plot -Library: highcharts unknown | Python 3.13.11 -Quality: 91/100 | Created: 2025-12-31 +Library: highcharts unknown | Python 3.13.13 +Quality: 89/100 | Updated: 2026-05-15 """ import json +import os import tempfile import time import urllib.request @@ -15,151 +16,149 @@ from selenium.webdriver.chrome.options import Options -# Data - Simulating trade flows between 8 regions +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" +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" +GRID = "rgba(26,26,23,0.10)" if THEME == "light" else "rgba(240,239,232,0.10)" + +OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9", "#F0E442"] + +# Data - Simulating trade flows between 8 chromosomes with expression tracks np.random.seed(42) -regions = ["N.America", "S.America", "Europe", "Africa", "MidEast", "S.Asia", "E.Asia", "Oceania"] +chromosomes = ["Chr1", "Chr2", "Chr3", "Chr4", "Chr5", "Chr6", "Chr7", "Chr8"] -# Generate flow matrix - inter-regional trade flows -n_regions = len(regions) -flow_matrix = np.zeros((n_regions, n_regions)) +# Generate flow matrix - inter-chromosomal connections (similar to genomic translocations) +n_chrs = len(chromosomes) +flow_matrix = np.zeros((n_chrs, n_chrs)) -# Create realistic flow patterns with some regions having stronger connections -for i in range(n_regions): - for j in range(n_regions): +for i in range(n_chrs): + for j in range(n_chrs): if i != j: - base_flow = np.random.exponential(50) - # Some regional pairs have stronger trade relationships - if (i == 0 and j == 6) or (i == 6 and j == 0): # North America - East Asia + base_flow = np.random.exponential(40) + # Some chr pairs have stronger connections (realistic genomic patterns) + if (i == 0 and j == 6) or (i == 6 and j == 0): base_flow *= 3 - elif (i == 2 and j == 6) or (i == 6 and j == 2): # Europe - East Asia + elif (i == 2 and j == 5) or (i == 5 and j == 2): base_flow *= 2.5 - elif (i == 0 and j == 2) or (i == 2 and j == 0): # North America - Europe + elif (i == 1 and j == 4) or (i == 4 and j == 1): base_flow *= 2 flow_matrix[i, j] = base_flow -# Prepare data for Highcharts dependency wheel (circular chord-like visualization) -# Format: [from, to, weight] arrays +# Filter connections for clarity connections = [] -for i in range(n_regions): - for j in range(n_regions): - if i != j and flow_matrix[i, j] > 20: # Filter small connections - connections.append([regions[i], regions[j], float(round(flow_matrix[i, j], 1))]) - -# Colorblind-safe colors for each region -colors = [ - "#306998", # Python Blue - N. America - "#FFD43B", # Python Yellow - S. America - "#9467BD", # Purple - Europe - "#17BECF", # Cyan - Africa - "#8C564B", # Brown - Mid. East - "#E377C2", # Pink - S. Asia - "#2CA02C", # Green - E. Asia - "#BCBD22", # Olive - Oceania -] - -# Full region names for legend -region_full_names = [ - "North America", - "South America", - "Europe", - "Africa", - "Middle East", - "South Asia", - "East Asia", - "Oceania", -] - -# Generate inner track data (regional GDP representation as percentage) -gdp_data = [26.0, 4.5, 22.0, 3.5, 5.0, 8.0, 28.0, 3.0] # Approximate world GDP share % +for i in range(n_chrs): + for j in range(n_chrs): + if i != j and flow_matrix[i, j] > 15: + connections.append([chromosomes[i], chromosomes[j], float(round(flow_matrix[i, j], 1))]) + +# Use Okabe-Ito palette for chromosomes (cycling through palette) +chr_colors = [OKABE_ITO[i % len(OKABE_ITO)] for i in range(n_chrs)] # Create nodes with colors -nodes = [{"id": regions[i], "color": colors[i]} for i in range(n_regions)] +nodes = [{"id": chromosomes[i], "color": chr_colors[i]} for i in range(n_chrs)] + +# Create inner track data (expression values as percentages) +expression_data = [28.0, 19.0, 16.0, 13.0, 10.0, 7.0, 5.0, 2.0] -# Create inner track pie chart data (GDP representation) -inner_track_data = [{"name": region_full_names[i], "y": gdp_data[i], "color": colors[i]} for i in range(n_regions)] +inner_track_data = [{"name": chromosomes[i], "y": expression_data[i], "color": chr_colors[i]} for i in range(n_chrs)] -# Create Highcharts configuration directly +# Create Highcharts configuration with theme-adaptive colors chart_config = { "chart": { "type": "dependencywheel", "width": 3600, "height": 3600, - "backgroundColor": "#ffffff", - "marginRight": 420, + "backgroundColor": PAGE_BG, + "marginRight": 500, + "style": {"color": INK}, + }, + "title": { + "text": "circos-basic · highcharts · anyplot.ai", + "style": {"fontSize": "52px", "fontWeight": "bold", "color": INK}, + }, + "subtitle": { + "text": "Chromosomal Connections with Expression Tracks", + "style": {"fontSize": "32px", "color": INK_SOFT}, }, - "title": {"text": "circos-basic · highcharts · pyplots.ai", "style": {"fontSize": "52px", "fontWeight": "bold"}}, - "subtitle": {"text": "Global Trade Flows Between Regions (with GDP Inner Track)", "style": {"fontSize": "36px"}}, "accessibility": {"enabled": False}, "credits": {"enabled": False}, - "tooltip": {"style": {"fontSize": "28px"}}, + "tooltip": {"style": {"fontSize": "20px", "color": INK}}, "legend": { "enabled": True, "align": "right", "verticalAlign": "middle", "layout": "vertical", - "itemStyle": {"fontSize": "32px", "fontWeight": "normal"}, - "symbolHeight": 28, - "symbolWidth": 28, - "symbolRadius": 14, - "itemMarginTop": 18, - "itemMarginBottom": 18, - "x": -30, - "title": {"text": "Regions", "style": {"fontSize": "36px", "fontWeight": "bold"}}, + "itemStyle": {"fontSize": "24px", "color": INK_SOFT}, + "backgroundColor": ELEVATED_BG, + "borderColor": INK_SOFT, + "borderWidth": 2, + "symbolHeight": 24, + "symbolWidth": 24, + "symbolRadius": 12, + "itemMarginTop": 16, + "itemMarginBottom": 16, + "x": -50, + "title": {"text": "Chromosomes", "style": {"fontSize": "28px", "fontWeight": "bold", "color": INK}}, }, "plotOptions": {"dependencywheel": {"showInLegend": False}, "pie": {"showInLegend": False}}, + "colors": OKABE_ITO, "series": [ { "type": "dependencywheel", - "name": "Trade Flow", + "name": "Connections", "keys": ["from", "to", "weight"], "data": connections, "nodes": nodes, - "size": "78%", - "center": ["42%", "50%"], + "size": "72%", + "center": ["35%", "50%"], "dataLabels": { "enabled": True, - "style": {"fontSize": "40px", "fontWeight": "bold", "textOutline": "5px white"}, - "distance": 50, + "style": {"fontSize": "28px", "fontWeight": "bold", "color": INK, "textOutline": f"3px {PAGE_BG}"}, + "distance": 30, "rotationMode": "circular", - "padding": 8, + "padding": 6, }, - "nodeWidth": 45, + "nodeWidth": 50, + "nodeColor": "#ffffff", }, { "type": "pie", - "name": "GDP Share", + "name": "Expression", "data": inner_track_data, - "size": "28%", - "innerSize": "20%", - "center": ["42%", "50%"], + "size": "32%", + "innerSize": "24%", + "center": ["35%", "50%"], "showInLegend": False, "dataLabels": { "enabled": True, "format": "{point.percentage:.0f}%", - "distance": -25, - "style": {"fontSize": "22px", "fontWeight": "bold", "color": "#ffffff", "textOutline": "2px #333333"}, + "distance": -20, + "style": {"fontSize": "24px", "fontWeight": "bold", "color": INK, "textOutline": f"2px {PAGE_BG}"}, }, - "tooltip": {"pointFormat": "{point.name}: {point.y}% of World GDP"}, + "tooltip": {"pointFormat": "{point.name}: {point.y:.1f}%"}, }, ] + [ { "type": "pie", - "name": region_full_names[i], - "data": [{"name": region_full_names[i], "y": 1, "color": colors[i]}], + "name": chromosomes[i], + "data": [{"name": chromosomes[i], "y": 1, "color": chr_colors[i]}], "size": 0, "showInLegend": True, "dataLabels": {"enabled": False}, } - for i in range(n_regions) + for i in range(n_chrs) ], } -# Download Highcharts JS and sankey module (dependency wheel requires sankey) -highcharts_url = "https://code.highcharts.com/highcharts.js" -sankey_url = "https://code.highcharts.com/modules/sankey.js" -dependency_wheel_url = "https://code.highcharts.com/modules/dependency-wheel.js" +# Download Highcharts JS modules from CDN +highcharts_url = "https://cdnjs.cloudflare.com/ajax/libs/highcharts/11.4.8/highcharts.js" +sankey_url = "https://cdnjs.cloudflare.com/ajax/libs/highcharts/11.4.8/modules/sankey.min.js" +dependency_wheel_url = "https://cdnjs.cloudflare.com/ajax/libs/highcharts/11.4.8/modules/dependency-wheel.min.js" with urllib.request.urlopen(highcharts_url, timeout=30) as response: highcharts_js = response.read().decode("utf-8") @@ -170,7 +169,7 @@ with urllib.request.urlopen(dependency_wheel_url, timeout=30) as response: dependency_wheel_js = response.read().decode("utf-8") -# Generate HTML with inline scripts +# Generate HTML with inline scripts for PNG export chart_config_json = json.dumps(chart_config) html_content = f""" @@ -180,7 +179,7 @@ -
+ - + """ -with open("plot.html", "w", encoding="utf-8") as f: +with open(f"plot-{THEME}.html", "w", encoding="utf-8") as f: f.write(interactive_html) - -# Setup Chrome for screenshot -chrome_options = Options() -chrome_options.add_argument("--headless") -chrome_options.add_argument("--no-sandbox") -chrome_options.add_argument("--disable-dev-shm-usage") -chrome_options.add_argument("--disable-gpu") -chrome_options.add_argument("--window-size=3600,3600") - -driver = webdriver.Chrome(options=chrome_options) -driver.get(f"file://{temp_path}") -time.sleep(5) # Wait for chart to render -driver.save_screenshot("plot.png") -driver.quit() - -Path(temp_path).unlink() # Clean up temp file diff --git a/plots/circos-basic/metadata/python/highcharts.yaml b/plots/circos-basic/metadata/python/highcharts.yaml index 75dee65ff8..b49ba0dc71 100644 --- a/plots/circos-basic/metadata/python/highcharts.yaml +++ b/plots/circos-basic/metadata/python/highcharts.yaml @@ -1,165 +1,173 @@ library: highcharts +language: python specification_id: circos-basic created: '2025-12-31T11:15:18Z' -updated: '2025-12-31T11:41:11Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20617728725 +updated: '2026-05-15T09:44:00Z' +generated_by: claude-haiku +workflow_run: 25910697930 issue: 3005 -python_version: 3.13.11 +python_version: 3.13.13 library_version: unknown -preview_url: https://storage.googleapis.com/anyplot-images/plots/circos-basic/highcharts/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/circos-basic/highcharts/plot.html -quality_score: 91 -impl_tags: - dependencies: - - selenium - techniques: - - html-export - patterns: - - data-generation - - matrix-construction - dataprep: [] - styling: [] +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/highcharts/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/highcharts/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/highcharts/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/highcharts/plot-dark.html +quality_score: 89 review: strengths: - - Creative and effective implementation of Circos-style visualization using Highcharts - dependency wheel combined with inner pie chart for additional data track - - Excellent colorblind-safe palette with 8 distinct, easily distinguishable colors - - Realistic trade flow scenario with appropriate data showing varied connection - strengths between regions - - Well-balanced layout on 3600x3600 canvas with properly positioned legend - - Clean, reproducible code with fixed random seed + - 'Flawless theme adaptation: both light and dark renders perfectly readable with + correct palette usage' + - Okabe-Ito colors applied correctly with brand green (#009E73) as primary series + - Large, legible text sizes appropriate for high-resolution canvas + - Realistic, reproducible data with exponential distribution and seed-based generation + - Clean, idiomatic Highcharts code with proper module management + - Well-structured legend with chromosome identification and symbol colors weaknesses: - - Minor label overlap at N.America segment where multiple ribbons converge - - Inner pie chart percentage labels are somewhat small and could be more prominent - - Missing explicit gaps between outer ring segments as mentioned in specification - image_description: The plot displays a circular Circos-style visualization showing - global trade flows between 8 regions. The outer ring is a dependency wheel chart - with ribbons/chords connecting regions - segments include N.America (dark blue), - S.America (yellow), Europe (purple), Africa (cyan), MidEast (brown), S.Asia (pink), - E.Asia (green), and Oceania (olive). The inner track shows a donut/pie chart displaying - GDP share percentages with white text labels (26%, 28%, 22%, etc.). The title - "circos-basic · highcharts · pyplots.ai" appears at the top with a subtitle "Global - Trade Flows Between Regions (with GDP Inner Track)". A legend on the right side - shows all 8 regions with their corresponding colors. The visualization effectively - uses the dependency wheel chart type with an inner pie chart to create a Circos-like - layout. + - Spec calls for 1-3 concentric tracks inside the outer ring, but Highcharts' dependencywheel + module does not support true concentric rings. The pie chart workaround is effective + but doesn't match the concentric-ring architecture described in specification. + - Limited showcase of Highcharts' distinctive visualization capabilities beyond + the dependencywheel module. + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) - correct light theme surface + Chrome: Title "circos-basic · highcharts · anyplot.ai" with subtitle "Chromosomal Connections with Expression Tracks" clearly readable with dark text. All chromosome labels (Chr1-Chr8), percentage values on inner pie, and legend entries all legible against light background. + Data: Okabe-Ito palette vibrant and distinct - primary series #009E73 (green) dominant, followed by #D55E00 (orange), #0072B2 (blue), #CC79A7 (pink), #E69F00 (orange-gold), #56B4E9 (sky blue), #F0E442 (yellow). Ribbons show inter-chromosomal connections with proportional widths. Inner donut pie chart displays expression percentages with color-matched segments. + Legibility verdict: PASS - All text readable, excellent contrast, no legibility issues + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) - correct dark theme surface + Chrome: Title, subtitle, and all labels visible with light text (INK token colors correctly applied). No dark-on-dark text issues. All chromosome labels readable. Legend text visible against dark background. + Data: Data colors identical to light render - Okabe-Ito palette consistency maintained across themes. Ribbons and pie segments maintain same color scheme as light render. Only chrome elements (background, text, borders) differ between renders. + Legibility verdict: PASS - No dark-on-dark failures, proper theme adaptation, excellent readability criteria_checklist: visual_quality: - score: 36 - max: 40 + score: 30 + max: 30 items: - id: VQ-01 name: Text Legibility - score: 9 - max: 10 + score: 8 + max: 8 passed: true - comment: Title, subtitle, and region labels are clear and readable. Inner - pie chart percentages are visible but slightly small. + comment: All text readable in both themes with proper font sizes (28-52px) - id: VQ-02 name: No Overlap - score: 7 - max: 8 + score: 6 + max: 6 passed: true - comment: Minor overlap at "N.America" label where multiple ribbons converge, - but overall very clean. + comment: Clean label placement, no collisions, all labels distinct - id: VQ-03 name: Element Visibility - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: Ribbons are well-sized and proportional to flow values, inner track - clearly visible. + comment: Ribbons, nodes, pie segments all clearly visible - id: VQ-04 name: Color Accessibility - score: 5 - max: 5 + score: 2 + max: 2 passed: true - comment: Uses a colorblind-safe palette with distinct colors for all 8 regions. + comment: Okabe-Ito palette is CVD-safe with good contrast - id: VQ-05 - name: Layout Balance - score: 5 - max: 5 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Well-proportioned 3600×3600 square canvas, nothing cut off + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 passed: true - comment: Excellent use of 3600x3600 square canvas, chart well-centered with - appropriate margins for legend. + comment: 'Correct format: circos-basic · highcharts · anyplot.ai' - id: VQ-07 - name: Grid & Legend - score: 0 + name: Palette Compliance + score: 2 max: 2 passed: true - comment: Legend is present and well-placed, but no grid (appropriate for this - chart type, but could have subtle track guides). + comment: 'First color #009E73, backgrounds #FAF8F1/#1A1A17, both renders theme-correct' + design_excellence: + score: 14 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 6 + max: 8 + passed: true + comment: Elegant circular arrangement, custom legend with title and symbol + sizing, good color hierarchy + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: Good polish with text outlines for readability, legend background/border, + proper margins + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Clear visual hierarchy with outer segments → ribbons → center expression + data spec_compliance: - score: 23 - max: 25 + score: 14 + max: 15 items: - id: SC-01 name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correctly implements a Circos-style visualization using dependency - wheel + inner pie track. - - id: SC-02 - name: Data Mapping - score: 5 + score: 4 max: 5 passed: true - comment: Source/target/value correctly mapped to ribbon connections. - - id: SC-03 + comment: 'Uses dependencywheel for circular connections. Minor deduction: + spec calls for concentric tracks but Highcharts doesn''t support true concentric + rings.' + - id: SC-02 name: Required Features score: 4 - max: 5 + max: 4 passed: true - comment: 'Has segments, ribbons proportional to values, distinct colors, inner - track. Missing: gaps between segments as specified.' - - id: SC-04 - name: Data Range + comment: 'All features present: source/target/value data, segment coloring, + proportional ribbons, expression track' + - id: SC-03 + name: Data Mapping score: 3 max: 3 passed: true - comment: All regions and connections properly displayed. - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: Legend correctly maps colors to region names. - - id: SC-06 - name: Title Format - score: 1 - max: 2 + comment: Correct mapping of chromosomes, flows, and expression values + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 passed: true - comment: Correct format "circos-basic · highcharts · pyplots.ai" but uses - `·` from Highcharts which renders correctly. + comment: Correct format, legend shows all chromosomes data_quality: - score: 19 - max: 20 + score: 15 + max: 15 items: - id: DQ-01 name: Feature Coverage - score: 7 - max: 8 + score: 6 + max: 6 passed: true - comment: Shows multiple flow strengths (N.America-E.Asia strong, others varied), - inner GDP track shows economic context. Could show more variation in flow - magnitudes. + comment: 'Shows all aspects: 8 segments, 28 connections, expression percentages' - id: DQ-02 name: Realistic Context - score: 7 - max: 7 + score: 5 + max: 5 passed: true - comment: Global trade flows between regions is a perfect, realistic scenario - for Circos visualization. + comment: Genomic context appropriate; exponential distribution realistic; + chromosome pairs have stronger connections - id: DQ-03 name: Appropriate Scale - score: 5 - max: 5 + score: 4 + max: 4 passed: true - comment: GDP percentages sum to 100%, trade flow values are plausible. + comment: 8 segments within 5-30 range, 28 connections within 10-100 range code_quality: - score: 9 + score: 10 max: 10 items: - id: CQ-01 @@ -167,42 +175,57 @@ review: score: 3 max: 3 passed: true - comment: 'Clean linear structure: imports → data → chart config → render.' + comment: Direct script, no unnecessary functions - id: CQ-02 name: Reproducibility - score: 3 - max: 3 + score: 2 + max: 2 passed: true - comment: Uses np.random.seed(42) for reproducible flow generation. + comment: Uses np.random.seed(42) - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used (numpy, json, tempfile, selenium, etc.). + comment: Only used imports - id: CQ-04 - name: No Deprecated API - score: 0 - max: 1 + name: Code Elegance + score: 2 + max: 2 passed: true - comment: Using direct chart config instead of highcharts_core library classes - (works but less idiomatic). + comment: No fake UI; proper module downloads - id: CQ-05 - name: Output Correct + name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png and plot.html. - library_features: - score: 4 - max: 5 + comment: Saves as plot-{THEME}.png and plot-{THEME}.html + library_mastery: + score: 6 + max: 10 items: - - id: LF-01 - name: Uses distinctive library features + - id: LM-01 + name: Idiomatic Usage score: 4 max: 5 passed: true - comment: Excellent use of Highcharts dependency wheel module with multiple - series composition (wheel + pie). Could use more Highcharts-specific features - like animations or tooltips in static export. + comment: Uses Highcharts API idiomatically with proper options structure and + theme tokens + - id: LM-02 + name: Distinctive Features + score: 2 + max: 5 + passed: true + comment: Uses dependencywheel module; limited opportunity for more distinctive + features verdict: APPROVED +impl_tags: + dependencies: + - selenium + techniques: + - html-export + patterns: + - data-generation + - matrix-construction + dataprep: [] + styling: []