diff --git a/plots/ohlc-bar/implementations/python/seaborn.py b/plots/ohlc-bar/implementations/python/seaborn.py index fa5e891232..7e31581512 100644 --- a/plots/ohlc-bar/implementations/python/seaborn.py +++ b/plots/ohlc-bar/implementations/python/seaborn.py @@ -1,17 +1,45 @@ -""" pyplots.ai +""" anyplot.ai ohlc-bar: OHLC Bar Chart -Library: seaborn 0.13.2 | Python 3.13.11 -Quality: 91/100 | Created: 2026-01-08 +Library: seaborn 0.13.2 | Python 3.13.13 +Quality: 90/100 | Updated: 2026-05-17 """ +import os + import matplotlib.pyplot as plt import numpy as np import pandas as pd import seaborn as sns -# Set seaborn style for consistent aesthetics -sns.set_theme(style="whitegrid") +# 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" + +# OHLC-specific colors: up bars and down bars +COLOR_UP = "#306998" +COLOR_DOWN = "#C44E52" + +# Set seaborn theme with theme-adaptive styling +sns.set_theme( + style="ticks", + rc={ + "figure.facecolor": PAGE_BG, + "axes.facecolor": PAGE_BG, + "axes.edgecolor": INK_SOFT, + "axes.labelcolor": INK, + "text.color": INK, + "xtick.color": INK_SOFT, + "ytick.color": INK_SOFT, + "grid.color": INK, + "grid.alpha": 0.10, + "legend.facecolor": ELEVATED_BG, + "legend.edgecolor": INK_SOFT, + }, +) # Generate synthetic OHLC stock data np.random.seed(42) @@ -37,20 +65,15 @@ # Add direction column for coloring df["direction"] = np.where(df["close"] >= df["open"], "up", "down") -# Create figure with seaborn styling -fig, ax = plt.subplots(figsize=(16, 9)) - -# Define colors - Python blue for up, desaturated red for down -color_up = "#306998" # Python Blue -color_down = "#C44E52" # Soft red (colorblind-friendly) +# Create figure +fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG) -# Draw OHLC bars using seaborn's lineplot for consistent styling -# We'll draw each bar as individual elements -tick_width = 0.4 # Width of open/close ticks +# Draw OHLC bars using matplotlib primitives +tick_width = 0.4 for idx, row in df.iterrows(): i = df.index.get_loc(idx) - color = color_up if row["direction"] == "up" else color_down + color = COLOR_UP if row["direction"] == "up" else COLOR_DOWN # Vertical line from low to high ax.vlines(x=i, ymin=row["low"], ymax=row["high"], color=color, linewidth=2) @@ -61,25 +84,29 @@ # Right tick for close price ax.hlines(y=row["close"], xmin=i, xmax=i + tick_width, color=color, linewidth=2) -# Add invisible scatter points for the legend -for label, color in [("Up (Close ≥ Open)", color_up), ("Down (Close < Open)", color_down)]: - ax.scatter([], [], color=color, s=150, marker="s", label=label) +# Create custom legend with line representations +up_line = plt.Line2D([0], [0], color=COLOR_UP, linewidth=2.5, label="Up (Close ≥ Open)") +down_line = plt.Line2D([0], [0], color=COLOR_DOWN, linewidth=2.5, label="Down (Close < Open)") +ax.legend(handles=[up_line, down_line], fontsize=16, loc="upper left") # Configure x-axis with date labels tick_positions = np.arange(0, len(df), max(1, len(df) // 8)) tick_labels = [df["date"].iloc[i].strftime("%b %d") for i in tick_positions] ax.set_xticks(tick_positions) -ax.set_xticklabels(tick_labels, rotation=45, ha="right") +ax.set_xticklabels(tick_labels, rotation=45, ha="right", fontsize=16) # Style the plot -ax.set_xlabel("Date", fontsize=20) -ax.set_ylabel("Price ($)", fontsize=20) -ax.set_title("ohlc-bar · seaborn · pyplots.ai", fontsize=24) -ax.tick_params(axis="both", labelsize=16) -ax.legend(fontsize=16, loc="upper left", framealpha=0.9) - -# Adjust grid -ax.grid(True, alpha=0.3, linestyle="--") +ax.set_xlabel("Date", fontsize=20, color=INK) +ax.set_ylabel("Price ($)", fontsize=20, color=INK) +ax.set_title("ohlc-bar · seaborn · anyplot.ai", fontsize=24, color=INK) +ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT) + +# Remove top and right spines +ax.spines["top"].set_visible(False) +ax.spines["right"].set_visible(False) + +# Subtle grid +ax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK) ax.set_axisbelow(True) # Set axis limits with padding @@ -89,4 +116,4 @@ ax.set_ylim(y_min - y_padding, y_max + y_padding) plt.tight_layout() -plt.savefig("plot.png", dpi=300, bbox_inches="tight") +plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG) diff --git a/plots/ohlc-bar/metadata/python/seaborn.yaml b/plots/ohlc-bar/metadata/python/seaborn.yaml index f4cd2fb964..1954dd7172 100644 --- a/plots/ohlc-bar/metadata/python/seaborn.yaml +++ b/plots/ohlc-bar/metadata/python/seaborn.yaml @@ -1,152 +1,191 @@ library: seaborn +language: python specification_id: ohlc-bar created: '2026-01-08T16:02:44Z' -updated: '2026-01-08T16:09:04Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20823042837 +updated: '2026-05-17T10:42:25Z' +generated_by: claude-haiku +workflow_run: 25988429133 issue: 3293 -python_version: 3.13.11 +language_version: 3.13.13 library_version: 0.13.2 -preview_url: https://storage.googleapis.com/anyplot-images/plots/ohlc-bar/seaborn/plot.png -preview_html: null -quality_score: 91 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/ohlc-bar/python/seaborn/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/ohlc-bar/python/seaborn/plot-dark.png +preview_html_light: null +preview_html_dark: null +quality_score: 90 review: strengths: - - Excellent OHLC bar implementation with proper open/close tick positions - - Good colorblind-friendly color scheme (Python Blue and soft red) - - Realistic synthetic stock data with clear price movements - - Clean, well-commented code following KISS principles - - Proper seaborn styling integration with whitegrid theme + - Correct OHLC bar implementation with proper high-low ranges and open-close ticks + - 'Excellent theme adaptation: both light and dark renders perfectly readable with + zero dark-on-dark or light-on-light issues' + - Perfect visual quality across all measures (legibility, no overlaps, element visibility, + appropriate layout) + - Clean, reproducible code with proper theme token approach and seeded randomness + - Realistic financial context with appropriate 45-day trading period and sensible + price dynamics + - 'All specification requirements met: correct plot type, required features, proper + data mapping, and correct title/legend format' weaknesses: - - Legend uses square markers that do not visually represent the actual OHLC bar - style (should use custom legend with line markers) - - Relies heavily on matplotlib primitives since seaborn lacks native OHLC support - image_description: 'The plot displays a professional OHLC (Open-High-Low-Close) - bar chart spanning 45 trading days from January 2 to late February 2024. Each - bar consists of a thin vertical line representing the high-low price range, with - a horizontal tick extending left for the open price and right for the close price. - Up bars (close ≥ open) are colored in Python Blue (#306998) and down bars (close - < open) are in a soft red (#C44E52). The data shows a clear downtrend from approximately - $165 to $130 over the period. The chart uses a whitegrid seaborn style with subtle - dashed gridlines (alpha 0.3). Axis labels are properly formatted with "Date" on - x-axis and "Price ($)" on y-axis. The legend in the upper left clearly explains - the color coding. The title correctly follows the required format: "ohlc-bar · - seaborn · pyplots.ai".' + - Design Excellence is functional but not exceptional—could benefit from more intentional + visual hierarchy or sophisticated styling beyond default refinement + - seaborn library features not leveraged distinctively; implementation appropriately + drops to matplotlib primitives for custom OHLC, but doesn't showcase seaborn-specific + strengths + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — perfect for light theme + Chrome: Title ("ohlc-bar · seaborn · anyplot.ai") in dark text (24pt), axis labels (20pt) and tick labels (16pt) all clearly visible in dark ink colors; legend in upper left with clear labels + Data: 45 trading days of OHLC bars with blue bars for up movements (close ≥ open) and red bars for down movements (close < open); vertical lines show high-low range, left/right ticks show open/close prices + Grid: Subtle y-axis grid at 15% alpha aids price-level reading without visual clutter + Legibility verdict: PASS — all text readable, strong contrast against light background, no light-on-light issues + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — perfect for dark theme + Chrome: Title in light text (#F0EFE8), axis labels and tick labels in light secondary text (#B8B7B0), all clearly visible against dark background; legend equally readable + Data: Identical data colors (blue and red) to light render — only chrome adapted to dark theme, confirming proper theme implementation + Grid: Same subtle styling as light render, visible against dark background + Legibility verdict: PASS — all text readable, no dark-on-dark failures, adequate contrast throughout + + Both renders demonstrate perfect theme adaptation with identical data visualization and only theme-appropriate chrome changes. criteria_checklist: visual_quality: - score: 36 - 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 at 24pt, labels at 20pt, ticks at 16pt - all perfectly readable + comment: 'All text explicitly sized and readable in both themes: title 24pt, + axis labels 20pt, tick labels 16pt, legend 16pt' - id: VQ-02 name: No Overlap - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: No overlapping text, x-axis labels rotated 45° with good spacing + comment: No overlapping elements; date labels rotated 45° for clarity; legend + positioned in upper left without overlap - id: VQ-03 name: Element Visibility - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: OHLC bars clearly visible with linewidth=2, appropriate density for - 45 data points + comment: All 45 OHLC bars clearly visible and distinguishable with appropriate + line width (2pt); colors have good contrast - id: VQ-04 name: Color Accessibility - score: 5 - max: 5 + score: 2 + max: 2 passed: true - comment: Python Blue and soft red are colorblind-friendly + comment: Good color contrast; blue/red distinction is CVD-safe and clear - id: VQ-05 - name: Layout Balance - score: 3 - max: 5 + name: Layout & Canvas + score: 4 + max: 4 passed: true - comment: Good proportions but plot area could utilize more vertical space + comment: Standard 16:9 landscape (4800×2700px); plot fills 60-70% of canvas + with balanced margins and generous padding - id: VQ-06 - name: Axis Labels + name: Axis Labels & Title score: 2 max: 2 passed: true - comment: 'Descriptive with units: Price ($) and Date' + comment: Title follows format; axis labels descriptive with units ('Date' + and 'Price ($)') - id: VQ-07 - name: Grid & Legend - score: 0 + name: Palette Compliance + score: 2 max: 2 - passed: false - comment: Legend uses square markers instead of line markers matching OHLC - style + passed: true + comment: 'Perfect theme chrome: backgrounds correct (#FAF8F1 light, #1A1A17 + dark); text colors theme-adaptive; data colors identical between renders' + design_excellence: + score: 15 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 6 + max: 8 + passed: true + comment: Professional polish with intentional theme-adaptive design; clear + visual hierarchy (title > labels > ticks); thoughtful approach to color + encoding, though not exceptionally innovative + - id: DE-02 + name: Visual Refinement + score: 5 + max: 6 + passed: true + comment: Spines removed appropriately (top/right); custom grid styling (15% + alpha, 0.8pt width); generous whitespace; well-polished details + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Clear visual hierarchy through color encoding (up/down); price trend + progresses left-to-right with natural narrative; could benefit from more + emphasis spec_compliance: - score: 23 - max: 25 + score: 15 + max: 15 items: - id: SC-01 name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct OHLC bar chart implementation - - id: SC-02 - name: Data Mapping score: 5 max: 5 passed: true - comment: Date on x-axis, price on y-axis, OHLC correctly rendered - - id: SC-03 + comment: 'Perfect OHLC bar implementation: vertical lines for high-low range, + left tick for open, right tick for close' + - id: SC-02 name: Required Features - score: 5 - max: 5 + score: 4 + max: 4 passed: true - comment: Vertical high-low line, left tick for open, right tick for close, - color coding - - id: SC-04 - name: Data Range + comment: 'All spec features present: OHLC bars, up/down color distinction, + date axis with appropriate formatting, grid for price-level reading' + - id: SC-03 + name: Data Mapping score: 3 max: 3 passed: true - comment: All data visible with appropriate padding - - id: SC-05 - name: Legend Accuracy - score: 0 - max: 2 - passed: false - comment: Legend uses square markers but chart uses lines/ticks - - id: SC-06 - name: Title Format - score: 2 - max: 2 + comment: X-axis (dates) and Y-axis (prices) correctly mapped; all data visible + within axis limits with 10% padding + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 passed: true - comment: 'Correct format: ohlc-bar · seaborn · pyplots.ai' + comment: Title 'ohlc-bar · seaborn · anyplot.ai' correct; legend with clear + labels 'Up (Close ≥ Open)' and 'Down (Close < Open)' data_quality: - score: 20 - max: 20 + score: 15 + max: 15 items: - id: DQ-01 name: Feature Coverage - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: Shows both up and down bars, various bar heights, demonstrates full - OHLC pattern + comment: 'Shows all OHLC aspects: open, high, low, close properly visualized; + both up and down bars present' - id: DQ-02 name: Realistic Context - score: 7 - max: 7 + score: 5 + max: 5 passed: true - comment: Plausible stock price data with realistic price movements + comment: Realistic stock context with $150 base price; appropriate volatility + (daily returns ~N(0.001, 0.02)); 45 trading days (~2 months) realistic timeframe - id: DQ-03 name: Appropriate Scale - score: 5 - max: 5 + score: 4 + max: 4 passed: true - comment: Sensible stock prices with business day frequency + comment: Price range ($128-$170) sensible for stock data; date range (Jan + 2 - Feb 27, 2024) sensible for 45 business days; scaling correct code_quality: - score: 9 + score: 10 max: 10 items: - id: CQ-01 @@ -154,42 +193,55 @@ review: score: 3 max: 3 passed: true - comment: 'Clean linear flow: imports → data → plot → save' + comment: 'Straightforward procedural code: imports → theme tokens → data generation + → plotting → save' - id: CQ-02 name: Reproducibility - score: 3 - max: 3 + score: 2 + max: 2 passed: true - comment: np.random.seed(42) set + comment: np.random.seed(42) ensures deterministic output on repeated runs - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used + comment: 'Only necessary imports: os, matplotlib.pyplot, numpy, pandas, seaborn; + all used' - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 + name: Code Elegance + score: 2 + max: 2 passed: true - comment: Modern API usage + comment: Pythonic, appropriate complexity; custom legend construction is elegant; + no fake UI or over-engineering - id: CQ-05 - name: Output Correct - score: 0 + name: Output & API + score: 1 max: 1 passed: true - comment: Saves as plot.png - library_features: - score: 3 - max: 5 + comment: Correct output filename f'plot-{THEME}.png'; DPI 300; facecolor properly + set + library_mastery: + score: 6 + max: 10 items: - - id: LF-01 + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: 'Good idiomatic seaborn: sns.set_theme() with rc dict is the recommended + pattern; appropriately mixes seaborn styling with matplotlib primitives + for custom OHLC' + - id: LM-02 name: Distinctive Features - score: 3 + score: 2 max: 5 passed: true - comment: Uses sns.set_theme for styling, but OHLC bars drawn with matplotlib - primitives since seaborn lacks native OHLC support + comment: Uses matplotlib primitives (vlines, hlines) for OHLC bars; appropriate + choice for this plot type but not distinctive to seaborn + score_caps_applied: None verdict: APPROVED impl_tags: dependencies: [] @@ -198,8 +250,9 @@ impl_tags: - custom-legend patterns: - data-generation - - iteration-over-groups + - explicit-figure dataprep: - time-series styling: - grid-styling + - publication-ready