Skip to content

update(qrcode-basic): letsplot — scannable QR codes#5227

Merged
github-actions[bot] merged 6 commits intomainfrom
implementation/qrcode-basic/letsplot
Apr 7, 2026
Merged

update(qrcode-basic): letsplot — scannable QR codes#5227
github-actions[bot] merged 6 commits intomainfrom
implementation/qrcode-basic/letsplot

Conversation

@MarkusNeusinger
Copy link
Copy Markdown
Owner

Summary

Updated letsplot implementation for qrcode-basic.

Changes: Use qrcode library for real scannable QR code generation instead of manual matrix construction (fixes #3413)

Changes

  • Replaced manual QR matrix with qrcode library for proper encoding
  • QR code now encodes "https://pyplots.ai" and is scannable by standard readers
  • Maintained library-idiomatic rendering approach
  • Spec updated to require scannable output

Test Plan

  • Preview images uploaded to GCS staging
  • Implementation file passes ruff format/check
  • Metadata YAML updated with current versions
  • Automated review triggered

Generated with Claude Code /update command

…e QR codes

Fix #3413: Replace manual QR matrix construction with proper qrcode library encoding.
Copilot AI review requested due to automatic review settings April 7, 2026 17:50
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 7, 2026

AI Review - Attempt 1/3

Image Description

The plot displays a QR code rendered as a grid of black and white square tiles on a clean white background. The title "qrcode-basic · letsplot · pyplots.ai" appears centered at the top in dark text (~24pt), with a gray subtitle "Encoded: https://pyplots.ai | Error Correction: M (15%)" below it. The QR code itself features three finder patterns (large black-white-black squares) in the top-left, top-right, and bottom-left corners. The data modules form a complex pattern of black and white squares in the center and lower-right regions. A generous quiet zone (white border) surrounds the QR code. The image is square format (3600×3600 at scale=3). All axes, spines, grid lines, and ticks are removed, giving a clean presentation. The QR code appears well-formed and scannable.

Score: 85/100

Category Score Max
Visual Quality 28 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 10 10
Library Mastery 5 10
Total 85 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) - Title 24pt and subtitle 16pt explicitly set; subtitle slightly small for 3600×3600 canvas
  • VQ-02: No Overlap (6/6) - No overlapping elements anywhere
  • VQ-03: Element Visibility (6/6) - QR modules clearly visible, well-sized tiles with no gaps
  • VQ-04: Color Accessibility (4/4) - Black on white provides maximum contrast, inherently colorblind-safe
  • VQ-05: Layout & Canvas (3/4) - QR code centered but noticeable extra whitespace below; canvas utilization ~55%
  • VQ-06: Axis Labels & Title (2/2) - Axes appropriately hidden for QR code; title and subtitle are descriptive

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) - Clean, intentional design with appropriate black/white palette and gray subtitle hierarchy; above defaults but not publication-level polish
  • DE-02: Visual Refinement (5/6) - All chrome removed (axes, spines, grid, ticks, backgrounds); clean and polished presentation
  • DE-03: Data Storytelling (3/6) - Subtitle communicates encoded content and error correction level, adding meaningful context beyond just displaying the code

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) - Correct QR code generated using the qrcode library as recommended
  • SC-02: Required Features (4/4) - Quiet zone (border=4), high contrast black/white, finder patterns in 3 corners, error correction M (15%), scannable code
  • SC-03: Data Mapping (3/3) - Correct x/y coordinate mapping with y-flip for proper QR orientation
  • SC-04: Title & Legend (3/3) - Title matches required format; no legend needed for QR code

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) - Complete QR code with all standard elements (finder patterns, alignment, data modules, quiet zone)
  • DQ-02: Realistic Context (5/5) - Encodes a real, relevant URL (https://pyplots.ai)
  • DQ-03: Appropriate Scale (4/4) - Error correction M is appropriate default; auto-sizing via fit=True

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) - Clean imports → data generation → plot → save flow
  • CQ-02: Reproducibility (2/2) - Deterministic: same URL always produces the same QR code
  • CQ-03: Clean Imports (2/2) - All imports are used, explicit imports from lets_plot
  • CQ-04: Code Elegance (2/2) - Clean, appropriate complexity; matrix-to-dataframe conversion is concise
  • CQ-05: Output & API (1/1) - Saves as plot.png with ggsave, current API

Library Mastery (5/10)

  • LM-01: Idiomatic Usage (4/5) - Proper ggplot grammar with aes mapping, geom_tile, scale_fill_manual, coord_fixed, and theme customization
  • LM-02: Distinctive Features (1/5) - Generic ggplot approach; could be replicated identically in plotnine with minimal syntax changes

Score Caps Applied

  • None

Strengths

  • Uses the qrcode library as recommended by spec, producing a genuinely scannable QR code
  • Clean, minimal design with all unnecessary chrome properly removed
  • Proper quiet zone (border=4) and high-contrast black/white rendering
  • Deterministic output with clean KISS code structure
  • Full spec compliance with correct title format and error correction level

Weaknesses

  • No distinctive lets-plot features leveraged — implementation is generic ggplot that could be any grammar-of-graphics library
  • Extra whitespace below the QR code reduces canvas utilization
  • Subtitle font size (16pt) is slightly small relative to the 3600×3600 canvas

Issues Found

  1. LM-02 LOW: Generic ggplot usage with no lets-plot distinctive features
    • Fix: Consider leveraging lets-plot-specific theming, tooltip capabilities, or other unique API features
  2. VQ-05 MINOR: Extra whitespace below QR code
    • Fix: Adjust ggsize or plot margins to better utilize canvas space
  3. DE-01 MODERATE: Design is clean but could be more polished
    • Fix: Consider adding a subtle border/frame, refined typography, or additional contextual information

AI Feedback for Next Attempt

Improve library mastery by leveraging lets-plot distinctive features. Reduce excess whitespace below the QR code by adjusting margins or ggsize proportions. Consider enhancing design excellence with a subtle frame around the QR code, refined subtitle typography (larger font), or additional visual context elements. The code and spec compliance are excellent — focus improvements on design polish and library-specific features.

Verdict: REJECTED

@github-actions github-actions Bot added quality:85 Quality score 85/100 ai-rejected Quality not OK, triggers update labels Apr 7, 2026
@github-actions github-actions Bot added the ai-attempt-1 First repair attempt label Apr 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the qrcode-basic plot specification and the letsplot implementation to generate a proper, scannable QR code by using the qrcode encoder instead of manually constructing the module matrix (addresses the “not scannable” issue).

Changes:

  • Updated spec notes to explicitly require scannable QR output via a real QR encoding library.
  • Updated letsplot implementation to generate the QR matrix via qrcode and render it with geom_tile + fixed aspect ratio.
  • Updated letsplot metadata versions/timestamps (but currently introduces inconsistencies that need correction).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
plots/qrcode-basic/specification.yaml Sets updated timestamp and refines tagging (data_type).
plots/qrcode-basic/specification.md Adds explicit requirement that output MUST be scannable; clarifies recommended libraries.
plots/qrcode-basic/metadata/letsplot.yaml Updates generation metadata fields (but quality/timestamp consistency needs fixes).
plots/qrcode-basic/implementations/letsplot.py Switches QR generation to qrcode and renders with lets-plot tiles + coord_fixed().

Comment on lines +1 to +4
""" pyplots.ai
qrcode-basic: Basic QR Code Generator
Library: letsplot 4.8.2 | Python 3.13.11
Quality: 92/100 | Created: 2026-01-07
Library: letsplot 4.8.2 | Python 3.14.3
Quality: 85/100 | Updated: 2026-04-07
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation header no longer matches the repository’s standard 4-line format: it should start with """ pyplots.ai (note the space) and include a valid quality value ({score}/100 or pending) plus a Created: date. The current Quality: /100 | Updated: ... is malformed and may break downstream parsing/consistency with other implementations.

Copilot uses AI. Check for mistakes.

# Save as PNG and HTML
# Save
ggsave(plot, "plot.png", path=".", scale=3)
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation now only saves plot.png, but metadata still publishes a preview_html URL for plot.html. Either re-add exporting plot.html (common for lets-plot implementations) or update metadata to set preview_html: null so the published link doesn’t 404.

Suggested change
ggsave(plot, "plot.png", path=".", scale=3)
ggsave(plot, "plot.png", path=".", scale=3)
ggsave(plot, "plot.html", path=".")

Copilot uses AI. Check for mistakes.
created: '2026-01-07T16:33:44Z'
updated: '2026-01-07T16:44:29Z'
generated_by: claude-opus-4-5-20251101
updated: '2026-04-07T17:54:24Z'
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated timestamp uses +00:00 timezone suffix; the repo’s metadata writer normalizes UTC timestamps to end with Z. Consider changing this to ...Z for consistency with other plot metadata and the migration script output.

Suggested change
updated: '2026-04-07T17:54:24Z'
updated: '2026-04-07T17:45:00Z'

Copilot uses AI. Check for mistakes.
preview_url: https://storage.googleapis.com/pyplots-images/plots/qrcode-basic/letsplot/plot.png
preview_html: https://storage.googleapis.com/pyplots-images/plots/qrcode-basic/letsplot/plot.html
quality_score: 92
quality_score: 85
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quality_score was changed to null, but the same metadata file still contains a detailed criteria breakdown totaling a score and sets verdict: APPROVED. This leaves the implementation without a sortable quality score and makes the metadata internally inconsistent; either keep the numeric score (e.g., 92) or regenerate/update the review block so score/verdict/notes align with the new code.

Suggested change
quality_score: 85
quality_score: 92

Copilot uses AI. Check for mistakes.
@github-actions github-actions Bot removed the ai-rejected Quality not OK, triggers update label Apr 7, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

🔧 Repair Attempt 1/3

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 7, 2026

AI Review - Attempt 2/3

Image Description

The plot displays a QR code rendered using lets-plot's geom_tile on a warm cream/beige background. The QR code modules are dark teal/navy squares with white squares forming the negative space. Three finder patterns (large square-in-square markers) are visible in the top-left, top-right, and bottom-left corners. The title "qrcode-basic · letsplot · pyplots.ai" appears centered at the top in bold, with a subtitle "Encoded: https://pyplots.ai | Error Correction: M (15%)" in gray below it. A footer caption reads "Version 2 • 25×25 modules • ECC Level M (15%)" at the bottom. All axes, ticks, grid lines, and spines have been removed for a clean presentation. The QR code occupies roughly 60-65% of the canvas area with balanced margins.

Score: 85/100

Category Score Max
Visual Quality 27 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 10 10
Library Mastery 6 10
Total 85 100

Visual Quality (27/30)

  • VQ-01: Text Legibility (7/8) — Title explicitly set to 24pt, subtitle to 16pt; all text clearly readable at output resolution
  • VQ-02: No Overlap (6/6) — No overlapping elements whatsoever
  • VQ-03: Element Visibility (6/6) — QR code modules are clearly defined with sharp edges and proper sizing
  • VQ-04: Color Accessibility (3/4) — High contrast dark-on-light, but the cream/beige background slightly reduces contrast compared to pure white; spec recommends "high contrast black on white"
  • VQ-05: Layout & Canvas (3/4) — QR code fills ~60% of canvas with balanced margins, but some extra whitespace could be reclaimed
  • VQ-06: Axis Labels & Title (2/2) — Axes appropriately hidden for QR code; title present and descriptive

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Clean, professional presentation with centered typography, custom subtitle color (#666666), and deliberate minimalism. Above configured defaults but not publication-level design
  • DE-02: Visual Refinement (5/6) — All chrome removed (axes, ticks, grid, spines, panel background). Clean whitespace. Well-polished presentation
  • DE-03: Data Storytelling (3/6) — Subtitle communicates what's encoded and error correction level, providing useful context. Limited storytelling opportunity for QR codes, but could add more visual hierarchy or contextual elements

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct: QR code visualization using the qrcode library as recommended by spec
  • SC-02: Required Features (4/4) — Uses qrcode library (spec requirement), error correction M (15%), quiet zone via border=4, scannable output
  • SC-03: Data Mapping (3/3) — QR matrix correctly mapped to tile positions with proper Y-axis inversion
  • SC-04: Title & Legend (3/3) — Title follows exact format qrcode-basic · letsplot · pyplots.ai; no legend needed (show_legend=False appropriate)

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows complete QR code with finder patterns, timing patterns, and data modules. Could demonstrate more QR features (e.g., different error correction levels or content types)
  • DQ-02: Realistic Context (5/5) — Encodes "https://pyplots.ai" — a real, relevant, neutral URL
  • DQ-03: Appropriate Scale (4/4) — Version 1 QR with error correction M is appropriate for a short URL; 25×25 module grid is correct

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean imports → data generation → plot → save structure, no functions or classes
  • CQ-02: Reproducibility (2/2) — Deterministic: same URL input always produces identical QR code
  • CQ-03: Clean Imports (2/2) — All imports are used; explicit imports from lets_plot (not wildcard)
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic code. Good loop structure for matrix-to-dataframe conversion
  • CQ-05: Output & API (1/1) — Saves as plot.png via ggsave with scale=3

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — Good grammar-of-graphics usage: ggplot + aes + geom_tile + scale_fill_manual + coord_fixed + theme. Follows lets-plot patterns well
  • LM-02: Distinctive Features (2/5) — Uses standard grammar-of-graphics constructs available in any ggplot-family library. No lets-plot-specific features leveraged (e.g., interactive tooltips, livemap, lets-plot-specific themes, or GGBunch for multi-plot layouts)

Score Caps Applied

  • None

Strengths

  • Uses the qrcode library for genuine, scannable QR code generation (spec requirement)
  • Clean, minimal presentation with all unnecessary chrome removed
  • Perfect spec compliance with correct title format, error correction, and quiet zone
  • Deterministic output with clean, well-structured code
  • Explicit font sizing for title and subtitle

Weaknesses

  • Background is cream/beige (lets-plot default) rather than pure white — reduces contrast for QR scanning and deviates from spec's "high contrast black on white" recommendation
  • No distinctive lets-plot features used — implementation could work in plotnine with minimal changes
  • Design excellence could be improved with a more intentional color scheme or additional visual elements

Issues Found

  1. VQ-04 MINOR: Background is cream/beige rather than white, reducing contrast
    • Fix: Set explicit white background via plot_background=element_rect(fill='white') and panel_background=element_rect(fill='white')
  2. LM-02 LOW: No distinctive lets-plot features leveraged
    • Fix: Consider using theme_void(), flavor_high_contrast_dark(), or lets-plot-specific theme customization
  3. DE-01 MODERATE: Design is clean but could be more visually distinctive
    • Fix: Consider adding a subtle border/frame around the QR code area, or using branded colors for the title

AI Feedback for Next Attempt

Set an explicit white background (element_rect(fill='white') for both plot_background and panel_background) to maximize QR code contrast per spec requirements. Explore lets-plot distinctive features like theme_void() or flavor_* functions to boost Library Mastery. Consider adding visual refinements like a subtle frame or branded color accents to elevate Design Excellence.

Verdict: REJECTED

@github-actions github-actions Bot added the ai-rejected Quality not OK, triggers update label Apr 7, 2026
@github-actions github-actions Bot added ai-attempt-2 Second repair attempt and removed ai-rejected Quality not OK, triggers update labels Apr 7, 2026
Attempt 2/3 - fixes based on AI review
Copilot AI review requested due to automatic review settings April 7, 2026 18:07
@MarkusNeusinger MarkusNeusinger review requested due to automatic review settings April 7, 2026 18:07
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

🔧 Repair Attempt 2/3

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 7, 2026

AI Review - Attempt 3/3

Image Description

The plot shows a QR code rendered in dark navy (#1A1A2E) on a crisp white background in a square 1:1 format. Three finder patterns (large squares) are clearly visible in the top-left, top-right, and bottom-left corners — the hallmark of a valid QR code. The data modules form a recognizable pattern encoding "https://pyplots.ai". The title "qrcode-basic · letsplot · pyplots.ai" appears at top in bold, followed by a smaller subtitle "Encoded: https://pyplots.ai | Error Correction: M (15%)". A caption at the bottom reads "Version 2 · 25×25 modules · ECC Level M (15%)". No axes or gridlines are visible (theme_void). The QR code is well-centered with a proper quiet zone border.

Score: 90/100

Category Score Max
Visual Quality 28 30
Design Excellence 14 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 10 10
Library Mastery 9 10
Total 90 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (title=26, subtitle=16, caption=13). Bold title is very readable. Caption is slightly small but still legible at 3600×3600.
  • VQ-02: No Overlap (6/6) — No overlapping elements anywhere.
  • VQ-03: Element Visibility (6/6) — QR code modules are crisp and clearly defined. Each cell is distinct.
  • VQ-04: Color Accessibility (4/4) — High contrast dark navy on white. Excellent for accessibility and scanning.
  • VQ-05: Layout & Canvas (3/4) — Square format is appropriate. QR code is well-centered but there is some excess whitespace below the code before the caption.
  • VQ-06: Axis Labels & Title (2/2) — No axes needed for QR code. Title, subtitle, and caption provide all necessary descriptive information.

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) — Custom dark navy (#1A1A2E) instead of pure black adds sophistication. Clean typography hierarchy with bold title, lighter subtitle, and muted caption. flavor_high_contrast_light provides a polished base.
  • DE-02: Visual Refinement (5/6) — theme_void removes all chart chrome cleanly. White backgrounds explicitly set. element_geom provides consistent global styling. Generous whitespace.
  • DE-03: Data Storytelling (3/6) — Good information hierarchy: title identifies the plot, subtitle tells what's encoded, caption gives technical metadata. Adequate for the plot type but no exceptional storytelling.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct: QR code matrix visualization using geom_raster.
  • SC-02: Required Features (4/4) — All spec features present: quiet zone (border=4), high contrast, finder patterns visible, error correction M (15%), uses recommended qrcode library for scannable output.
  • SC-03: Data Mapping (3/3) — X/Y positions correctly mapped to grid coordinates. Y-axis inverted properly (size-1-y) so QR code reads correctly.
  • SC-04: Title & Legend (3/3) — Title follows exact format "qrcode-basic · letsplot · pyplots.ai". No legend needed for single-color QR code.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows a complete, functional QR code with finder patterns, timing patterns, and data modules. Could potentially show multiple error correction levels for comparison but that's beyond the spec.
  • DQ-02: Realistic Context (5/5) — Encodes "https://pyplots.ai" — a real, relevant URL that makes the QR code meaningful and scannable.
  • DQ-03: Appropriate Scale (4/4) — Version 2, 25×25 modules is appropriate for the URL length. Error correction M (15%) is the recommended default.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean linear flow: imports → QR generation → DataFrame conversion → plot → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — Fully deterministic: same URL input always produces identical QR code.
  • CQ-03: Clean Imports (2/2) — All imports are used. Specific imports from lets_plot rather than wildcard.
  • CQ-04: Code Elegance (2/2) — Appropriate complexity. Uses qrcode library properly with scale_fill_identity for direct color mapping — elegant approach.
  • CQ-05: Output & API (1/1) — Saves as plot.png with scale=3 for 3600×3600 output.

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — Excellent ggplot grammar: aes mapping, geom_raster for grid data, scale_fill_identity for direct color values, coord_fixed for square aspect, theme_void for clean base.
  • LM-02: Distinctive Features (4/5) — Uses several lets-plot-specific features: flavor_high_contrast_light() for crisp styling, element_geom() for global geom styling, geom_raster() optimized for grid rendering. These are distinctive to lets-plot.

Score Caps Applied

  • None — no caps triggered.

Strengths

  • Uses the qrcode library as recommended by the spec, producing a genuinely scannable QR code
  • Excellent use of lets-plot distinctive features: flavor_high_contrast_light, element_geom, scale_fill_identity
  • Clean information hierarchy with title, subtitle, and caption providing context at different levels
  • Dark navy color instead of pure black adds visual sophistication
  • Deterministic output with proper Y-axis inversion for correct QR code rendering

Weaknesses

  • Minor excess whitespace below QR code before caption
  • Caption font size (13pt) is slightly small relative to the image dimensions

Issues Found

None critical — minor layout refinement possible but not blocking.

AI Feedback for Next Attempt

N/A — implementation meets quality threshold.

Verdict: APPROVED

@github-actions github-actions Bot added quality:90 Quality score 90/100 ai-approved Quality OK, ready for merge labels Apr 7, 2026
Copilot AI review requested due to automatic review settings April 7, 2026 18:11
@MarkusNeusinger MarkusNeusinger review requested due to automatic review settings April 7, 2026 18:11
@github-actions github-actions Bot merged commit 7d03788 into main Apr 7, 2026
@github-actions github-actions Bot deleted the implementation/qrcode-basic/letsplot branch April 7, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt ai-attempt-2 Second repair attempt quality:85 Quality score 85/100 quality:90 Quality score 90/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[qrcode-basic] QR code not scannable

2 participants