diff --git a/plots/circos-basic/implementations/python/letsplot.py b/plots/circos-basic/implementations/python/letsplot.py index a056e98bcb..988f866e78 100644 --- a/plots/circos-basic/implementations/python/letsplot.py +++ b/plots/circos-basic/implementations/python/letsplot.py @@ -1,10 +1,11 @@ -""" pyplots.ai +""" anyplot.ai circos-basic: Circos Plot -Library: letsplot 4.8.2 | Python 3.13.11 -Quality: 91/100 | Created: 2025-12-31 +Library: letsplot 4.9.0 | Python 3.13.13 +Quality: 91/100 | Updated: 2026-05-15 """ import math +import os import numpy as np import pandas as pd @@ -13,6 +14,7 @@ aes, coord_fixed, element_blank, + element_rect, element_text, geom_polygon, geom_text, @@ -31,6 +33,13 @@ np.random.seed(42) +# 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" + # Genomic-style data: 8 chromosomes with connections and expression data chromosomes = ["Chr1", "Chr2", "Chr3", "Chr4", "Chr5", "Chr6", "Chr7", "Chr8"] n_chromosomes = len(chromosomes) @@ -277,45 +286,45 @@ ggplot() # Ribbons connecting chromosomes (innermost, with transparency) + geom_polygon( - aes(x="x", y="y", group="ribbon_id", fill="source"), data=ribbon_df, alpha=0.45, color="white", size=0.2 + aes(x="x", y="y", group="ribbon_id", fill="source"), data=ribbon_df, alpha=0.45, color=PAGE_BG, size=0.2 ) # Expression track 2 (inner track) + geom_polygon( - aes(x="x", y="y", group="track_id", fill="chromosome"), data=track2_df, alpha=0.65, color="white", size=0.3 + aes(x="x", y="y", group="track_id", fill="chromosome"), data=track2_df, alpha=0.65, color=PAGE_BG, size=0.3 ) # Expression track 1 (middle track) + geom_polygon( - aes(x="x", y="y", group="track_id", fill="chromosome"), data=track1_df, alpha=0.8, color="white", size=0.3 + aes(x="x", y="y", group="track_id", fill="chromosome"), data=track1_df, alpha=0.8, color=PAGE_BG, size=0.3 ) # Outer chromosome ring + geom_polygon( - aes(x="x", y="y", group="arc_id", fill="chromosome"), data=arc_df, alpha=0.95, color="white", size=0.8 + aes(x="x", y="y", group="arc_id", fill="chromosome"), data=arc_df, alpha=0.95, color=PAGE_BG, size=0.8 ) # Chromosome labels - + geom_text(aes(x="x", y="y", label="label"), data=label_df, size=14, color="#2C3E50", fontface="bold") + + geom_text(aes(x="x", y="y", label="label"), data=label_df, size=14, color=INK, fontface="bold") + scale_fill_manual(values=chr_colors, name="Chromosome") + coord_fixed(ratio=1) + scale_x_continuous(limits=(-1.45, 1.45)) + scale_y_continuous(limits=(-1.45, 1.45)) - + labs(title="Genomic Rearrangements · circos-basic · letsplot · pyplots.ai") - + ggsize(1200, 1200) # Square format for circular diagram + + labs(title="circos-basic · letsplot · anyplot.ai") + + ggsize(1200, 1200) + theme( - plot_title=element_text(size=26, face="bold", color="#2C3E50"), + plot_title=element_text(size=26, face="bold", color=INK), axis_title=element_blank(), axis_text=element_blank(), axis_ticks=element_blank(), axis_line=element_blank(), panel_grid=element_blank(), - legend_text=element_text(size=14), - legend_title=element_text(size=16, face="bold"), + legend_text=element_text(size=14, color=INK_SOFT), + legend_title=element_text(size=16, face="bold", color=INK), legend_position="bottom", - panel_background=element_blank(), - plot_background=element_blank(), + panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG), + plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), ) ) # Save as PNG (scale 3x for 3600x3600 px output) -ggsave(plot, "plot.png", path=".", scale=3) +ggsave(plot, f"plot-{THEME}.png", path=".", scale=3) # Save as HTML for interactivity -ggsave(plot, "plot.html", path=".") +ggsave(plot, f"plot-{THEME}.html", path=".") diff --git a/plots/circos-basic/metadata/python/letsplot.yaml b/plots/circos-basic/metadata/python/letsplot.yaml index a90320af29..1e2c4aeecb 100644 --- a/plots/circos-basic/metadata/python/letsplot.yaml +++ b/plots/circos-basic/metadata/python/letsplot.yaml @@ -1,208 +1,257 @@ library: letsplot +language: python specification_id: circos-basic created: '2025-12-31T21:34:33Z' -updated: '2025-12-31T21:36:58Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20627532731 +updated: '2026-05-15T09:40:38Z' +generated_by: claude-haiku +workflow_run: 25910785445 issue: 3005 -python_version: 3.13.11 -library_version: 4.8.2 -preview_url: https://storage.googleapis.com/anyplot-images/plots/circos-basic/letsplot/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/circos-basic/letsplot/plot.html +python_version: 3.13.13 +library_version: 4.9.0 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/letsplot/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/letsplot/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/letsplot/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/circos-basic/python/letsplot/plot-dark.html quality_score: 91 -impl_tags: - dependencies: [] - techniques: - - bezier-curves - - html-export - patterns: - - matrix-construction - - iteration-over-groups - dataprep: [] - styling: - - alpha-blending review: strengths: - - Excellent implementation of a complex Circos plot using only polygon geoms - - Clear visual hierarchy with outer ring, two expression tracks, and ribbon connections - - Well-chosen colorblind-friendly color palette with 8 distinct colors - - Realistic genomic data scenario with appropriate chromosome naming and sizing - - Good use of alpha transparency to show overlapping ribbons without obscuring information - - Clean legend placement at bottom - - Both PNG and HTML output generated - weaknesses: - - Title format should be "{spec-id} · {library} · pyplots.ai" not "Genomic Rearrangements - · circos-basic · letsplot · pyplots.ai" - - Could reduce whitespace at bottom of plot - - Interactive features of letsplot not fully utilized (tooltips would enhance the - visualization) - image_description: 'The plot displays a circular Circos visualization with 8 chromosomes - (Chr1-Chr8) arranged around the outer ring. The outer ring shows colored segments - in distinct colors: Chr1 (blue #306998), Chr2 (yellow #FFD43B), Chr3 (green #27AE60), - Chr4 (red #E74C3C), Chr5 (purple #9B59B6), Chr6 (teal #1ABC9C), Chr7 (orange #F39C12), - and Chr8 (light blue #3498DB). The segments are proportionally sized based on - chromosome size, with Chr1 being the largest and Chr8 the smallest.' + - Proper theme-adaptive rendering with correct color tokens (INK, PAGE_BG) in both + light and dark renders + - All text clearly readable and properly sized in both themes with no dark-on-dark + or light-on-light failures + - Excellent use of transparency layering (ribbons 0.45, inner tracks 0.65/0.8, outer + ring 0.95) to show hierarchy without visual clutter + - Complete circular geometry with precise angular calculations and proportional + ribbon widths + - 'All specification requirements met: 8 segments, 10 inter-segment connections, + 2 concentric expression tracks, chromosome labels, legend' + - Reproducible data generation with seed(42) and realistic genomic data (chromosome + sizes, expression levels) + - Clean, idiomatic letsplot code using ggplot grammar with geom_polygon, scale_fill_manual, + coord_fixed, and high-resolution PNG scaling + - Legend clearly shows all 8 chromosomes with their colors and is appropriately + positioned at plot bottom + weaknesses: [] + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct surface color + Chrome: Title "circos-basic · letsplot · anyplot.ai" is dark, bold, 26pt and clearly readable. Chromosome labels (Chr1-Chr8) are dark, bold, 14pt and positioned outside the circle with excellent readability. + Data: Eight chromosomes arranged in a circular ring with distinct custom colors (blues, yellow, green, red, purple, teal, orange). Two concentric expression tracks radiate inward with varying opacity. Ten ribbon connections between chromosomes are semi-transparent (alpha=0.45) showing relationship strength. All elements are clearly distinguishable from the light background. + Legibility verdict: PASS — all text is readable with appropriate contrast, all data elements are visible and distinct. + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct surface color + Chrome: Title is light cream (#F0EFE8) on dark background and clearly readable. Chromosome labels are light and well-positioned outside the circle with full legibility. + Data: All chromosome colors are identical to the light render (only chrome has flipped colors, as required). Ribbons, tracks, and outer ring maintain the same visual structure and proportions. All elements remain clearly visible and distinct against the dark background. + Legibility verdict: PASS — no dark-on-dark failures. Title and labels use INK token (#F0EFE8 in dark theme) providing strong contrast against PAGE_BG (#1A1A17). All data elements are visible and properly distinguished. + + Both renders demonstrate correct theme adaptation with data colors remaining constant while chrome (text, backgrounds) properly adapts to theme. The circos plot structure is consistent and professional across both surfaces. criteria_checklist: visual_quality: - score: 37 - max: 40 + score: 30 + max: 30 items: - id: VQ-01 name: Text Legibility - score: 10 - max: 10 + score: 8 + max: 8 passed: true - comment: Title is large and clear, chromosome labels are bold and easily readable + comment: Title 26pt bold, chromosome labels 14pt bold. All readable in both + light and dark renders with proper contrast. - id: VQ-02 name: No Overlap - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: No overlapping text, all labels well-spaced + comment: Chromosome labels positioned outside circle, ribbon connections layered + properly, no text collisions. - id: VQ-03 name: Element Visibility - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: Segments, tracks, and ribbons all clearly visible with appropriate - sizing + comment: All ribbons, tracks, and rings visible with appropriate transparency + for data density. No hidden elements. - id: VQ-04 name: Color Accessibility - score: 5 - max: 5 + score: 2 + max: 2 passed: true - comment: 8 distinct colors with good contrast, colorblind-friendly palette + comment: Custom chromosome colors are distinct and colorblind-friendly. Appropriate + for genomic domain. - id: VQ-05 - name: Layout Balance + name: Layout & Canvas score: 4 - max: 5 + max: 4 passed: true - comment: Good use of canvas with circular plot centered, minor whitespace - at bottom + comment: Square format 3600×3600px appropriate for circular plot. Well-proportioned + with no elements cut off. - id: VQ-06 - name: Axis Labels - score: 0 + name: Axis Labels & Title + score: 2 max: 2 passed: true - comment: N/A for circos plots (no traditional axes), chromosome labels present + comment: 'Title follows spec: ''circos-basic · letsplot · anyplot.ai''. No + axis labels (correct for polar circos).' - id: VQ-07 - name: Grid & Legend + name: Palette Compliance score: 2 max: 2 passed: true - comment: Clean background, legend at bottom is well-organized + comment: 'Plot backgrounds correct (#FAF8F1 light, #1A1A17 dark). Data colors + identical between renders. Theme-adaptive chrome only.' + design_excellence: + score: 14 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 6 + max: 8 + passed: true + comment: Custom chromosome palette with intentional color choices. Carefully + calibrated alpha values (0.45, 0.65, 0.8, 0.95) show deliberate design thought. + Professional polish. + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: Hidden axes (element_blank), clean circular arrangement with chromosome + gaps, generous whitespace, bottom legend placement. + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: 'Clear visual hierarchy: chromosome ring > expression tracks > ribbons. + Ribbon width encodes connection strength. Transparency progression emphasizes + importance.' spec_compliance: - score: 24 - max: 25 + score: 15 + max: 15 items: - id: SC-01 name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct Circos plot with circular layout - - id: SC-02 - name: Data Mapping score: 5 max: 5 passed: true - comment: Source/target connections properly mapped with bezier ribbons - - id: SC-03 + comment: Authentic circos plot with concentric tracks and ribbon connections. + Specification met precisely. + - id: SC-02 name: Required Features - score: 5 - max: 5 + score: 4 + max: 4 passed: true - comment: 'All spec features present: outer ring, gaps between segments, ribbons - proportional to value, distinct colors, 2 concentric data tracks' - - id: SC-04 - name: Data Range + comment: 'All features present: circular segments (8 chromosomes), inter-segment + connections (10 ribbons), concentric tracks (2 expression layers), distinct + colors, labels.' + - id: SC-03 + name: Data Mapping score: 3 max: 3 passed: true - comment: All segments visible with proportional sizing - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: Chromosome legend correct - - id: SC-06 - name: Title Format - score: 1 - max: 2 + comment: Segments positioned correctly, ribbon width proportional to connection + value, track heights encode expression levels. All data visible. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 passed: true - comment: Uses descriptive title with spec-id and library, but format is "Genomic - Rearrangements · circos-basic · letsplot · pyplots.ai" instead of "{spec-id} - · {library} · pyplots.ai" + comment: Title format correct. Legend shows all 8 chromosomes with matching + colors. data_quality: - score: 18 - 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 chromosomes, connections, and expression tracks; good variety - in connection strengths and expression values + comment: 'Complete circos visualization: outer ring, expression tracks, ribbon + connections, labels, legend. All aspects shown.' - id: DQ-02 name: Realistic Context - score: 7 - max: 7 + score: 5 + max: 5 passed: true - comment: Genomic rearrangement scenario is realistic and matches spec example + comment: Genomic data (chromosomes, expression levels) is realistic and neutral. + Authentic bioinformatics use case. - id: DQ-03 name: Appropriate Scale score: 4 - max: 5 + max: 4 passed: true - comment: Chromosome sizes (50-120 Mb) and expression values (0-1) are realistic; - connection values are sensible + comment: Chromosome sizes (120-50 Mb) realistic, connection values (8-25) + sensible, expression normalized 0-1. Appropriate domain scales. code_quality: - score: 9 + score: 10 max: 10 items: - id: CQ-01 name: KISS Structure - score: 2 + score: 3 max: 3 passed: true - comment: Mostly follows imports → data → plot → save, but builds complex intermediate - data structures + comment: No functions or classes. Straightforward data generation and plot + building. No unnecessary abstractions. - id: CQ-02 name: Reproducibility - score: 3 - max: 3 + score: 2 + max: 2 passed: true - comment: np.random.seed(42) set + comment: Uses np.random.seed(42) for deterministic data generation. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used + comment: 'Focused imports: os, numpy, pandas, letsplot components. All imports + used. No extraneous dependencies.' - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 + name: Code Elegance + score: 2 + max: 2 passed: true - comment: Uses current lets-plot API + comment: Well-organized sections (tokens, data, plot). No fake functionality. + Appropriate complexity. - 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: 3 - max: 5 + comment: Saves plot-{THEME}.png and plot-{THEME}.html with ggsave. Current + letsplot API. + library_mastery: + score: 7 + max: 10 items: - - id: LF-01 - name: Uses distinctive library features + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: 'Idiomatic letsplot: ggplot grammar, aes(), geom_polygon(), scale_fill_manual(), + coord_fixed(), theme(). Proper high-level API.' + - id: LM-02 + name: Distinctive Features score: 3 max: 5 passed: true - comment: Uses geom_polygon effectively for building circular elements, scale_fill_manual - for custom colors, coord_fixed for circular aspect ratio, ggsize for sizing. - Could have explored more interactive features. + comment: 'Uses letsplot strengths: ggsave() with scale parameter for high-res + PNG, HTML export, ggsize() for sizing, coord_fixed() for aspect preservation.' verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - bezier-curves + - layer-composition + patterns: + - data-generation + - matrix-construction + - iteration-over-groups + dataprep: [] + styling: + - alpha-blending + - minimal-chrome