Skip to content

feat(plotnine): implement wireframe-3d-basic - #11825

Merged
MarkusNeusinger merged 8 commits into
mainfrom
implementation/wireframe-3d-basic/plotnine
Sep 10, 2026
Merged

feat(plotnine): implement wireframe-3d-basic#11825
MarkusNeusinger merged 8 commits into
mainfrom
implementation/wireframe-3d-basic/plotnine

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: wireframe-3d-basic - python/plotnine

Implements the python/plotnine version of wireframe-3d-basic.

File: plots/wireframe-3d-basic/implementations/python/plotnine.py

Parent Issue: #1015


🤖 impl-generate workflow

@claude

claude Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1). Title "wireframe-3d-basic · python · plotnine · anyplot.ai" centered at top in dark ink, fully visible. Bold axis titles "X (cm)", "Y (cm)", "Z (mm)" at the ends of the three projected axis edges, with softer-ink tick labels (-6..6 for X/Y, 1/0/-1 for Z). A green (#009E73) wireframe mesh forms two nested dome/ripple shapes matching sin(sqrt(x²+y²)), with mesh lines running in both grid directions. All text is clearly readable against the light background — no legibility failures.

Dark render (plot-dark.png): Warm near-black background (#1A1A17). Same title, axis titles, and tick labels, now in light ink, all clearly legible — no dark-on-dark issues. The green mesh geometry and color are identical to the light render; only chrome (background, axis-line color, text color) flips between themes, confirming correct theme-adaptive implementation.

Both renders are text-legible. The recurring issue in both is structural, not a theme problem: near-side and far-side mesh lines are fully superimposed with no depth ordering, creating a tangled cluster of crossings near the lower-center of the dome.

Score: 72/100

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

Visual Quality (20/30)

  • VQ-01: Text Legibility (6/8)
  • VQ-02: No Overlap (3/6)
  • VQ-03: Element Visibility (3/6)
  • VQ-04: Color Accessibility (2/2)
  • VQ-05: Layout & Canvas (3/4)
  • VQ-06: Axis Labels & Title (1/2)
  • VQ-07: Palette Compliance (2/2)

Design Excellence (10/20)

  • DE-01: Aesthetic Sophistication (5/8) - Creative native-plotnine 3D projection technique, raised above generic default
  • DE-02: Visual Refinement (3/6) - Clean chrome removal, but the mesh tangle undercuts refinement
  • DE-03: Data Storytelling (2/6) - Tangle + disconnected Z-ticks work against a clear focal point

Spec Compliance (14/15)

  • SC-01: Plot Type (4/5)
  • SC-02: Required Features (4/4)
  • SC-03: Data Mapping (3/3)
  • SC-04: Title & Legend (3/3)

Data Quality (13/15)

  • DQ-01: Feature Coverage (4/6)
  • DQ-02: Realistic Context (5/5)
  • DQ-03: Appropriate Scale (4/4)

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3)
  • CQ-02: Reproducibility (2/2)
  • CQ-03: Clean Imports (2/2)
  • CQ-04: Code Elegance (2/2)
  • CQ-05: Output & API (1/1)

Library Mastery (5/10)

  • LM-01: Idiomatic Usage (3/5)
  • LM-02: Distinctive Features (2/5) - Creative projection technique, raised above generic default

Score Caps Applied

  • None

Strengths

  • Correct Imprint theme-adaptive chrome in both renders: page background matches #FAF8F1 (light) / #1A1A17 (dark), ink tokens flip correctly, and the mesh stays #009E73 (brand green) unchanged between themes with no dark-on-dark or light-on-light legibility failures.
  • Title matches the mandated format exactly.
  • Respects the plotnine "no workarounds" rule: since plotnine has no native 3D grammar, the implementation builds its own orthographic projection (elevation 30°/azimuth 45°) and draws the result with plotnine's own geom_path/geom_segment/geom_text primitives instead of falling back to matplotlib.
  • All three axes are labeled with units (X/Y in cm, Z in mm) and tick marks, and wireframe mesh lines run in both x and y directions per the spec's "Notes" section.
  • Clean top-to-bottom script: no functions/classes, all imports used, correct plot.save(...) API and filename pattern.

Weaknesses

  • No depth/hidden-line handling: every mesh line (near side and far side of the surface) is drawn at the same fixed alpha=0.35 with no z-depth-based ordering or fading, so the front and back of the ripple surface are fully superimposed. This produces a dense, tangled cluster of crossing lines near the plot center/lower dome that reads as visual noise rather than a legible 3D structure.
  • Z-axis tick labels ('1', '0', '-1') are pushed 13 units left of their true projected position to avoid merging with the Y-axis tick column, but this leaves them visually stranded far from the vertical Z-axis line at top-center, with no tick marks or leader connecting them to that axis — a viewer can easily mistake them for an unrelated fourth axis.
  • The combination of the two issues above works against the spec's stated goal that a wireframe should "reveal the underlying structure" of the surface — the render is harder to parse as a coherent 3D ripple than it should be.

Issues Found

  1. VQ-02/VQ-03 MEDIUM: Wireframe mesh has no depth-based line handling — near and far surface lines fully overlap, creating a tangled, hard-to-read cluster near the lower-center of the dome.
    • Fix: fade/thin lines by projected depth (e.g. scale alpha or linewidth by distance along the view direction), or draw back-facing rows/columns first at lower alpha and front-facing ones last at higher alpha to approximate hidden-line suppression. Consider slightly reducing grid_n (e.g. to 20-22) to further reduce line density.
  2. VQ-06 MEDIUM: Z-axis tick labels are disconnected from the Z-axis line, reading as an orphaned label column.
    • Fix: reduce the z_ticks['px'] - 13 offset so the labels sit closer to the vertical Z-axis line, or add short tick/leader marks connecting each Z label back to the axis.

AI Feedback for Next Attempt

Add depth-aware rendering to the wireframe mesh (alpha or linewidth that falls off with projected depth, or draw far-side lines before near-side lines) so the surface reads as a clean 3D shape instead of a tangled overlap of near/far lines. Also move the Z-axis tick labels closer to the Z-axis line (or add a leader/tick mark) so they're clearly associated with that axis rather than looking orphaned. Keep the existing palette, theme chrome, title, and code structure — those are correct.

Verdict: REJECTED

@github-actions github-actions Bot added quality:72 Quality score 72/100 ai-rejected Quality not OK, triggers update labels Sep 10, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Sep 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

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


🤖 impl-repair

@claude

claude Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1). Title, three bold axis labels ("X (cm)", "Y (cm)", "Z (mm)"), and all tick labels (X/Y: -6,-3,0,3,6; Z: -1,0,1 with leader segments) render in dark ink, clearly readable. A three-edge axis "box" in soft dark gray converges at a single point near the middle of the composition. The data is a dense mesh of thin #009E73 green segments forming a radially-symmetric ripple surface, projected with depth-weighted alpha (fainter = farther). The overall silhouette reads as a crown/flower shape with two upturned "wing" lobes and a domed peak, but the interior is a dense tangle of crossing diagonal lines rather than clearly separable concentric rings. All chrome text is readable against the light background.

Dark render (plot-dark.png): Warm near-black background (#1A1A17). Same title/axis labels/tick labels, now in light ink (#F0EFE8) and soft light gray (#B8B7B0), all clearly legible with no dark-on-dark failures. Data colors are identical to the light render — same #009E73 green mesh with the same depth-alpha treatment and same crown/tangle silhouette, confirming only chrome flips between themes.

Both renders pass text legibility; both share the same underlying data-mesh readability weakness (see below).

Score: 77/100

Category Score Max
Visual Quality 23 30
Design Excellence 11 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 8 10
Library Mastery 5 10
Total 77 100

Visual Quality (23/30)

  • VQ-01: Text Legibility (7/8)
  • VQ-02: No Overlap (5/6)
  • VQ-03: Element Visibility (2/6) - Wireframe reads as a dense self-crossing tangle, not a legible surface
  • VQ-04: Color Accessibility (2/2)
  • VQ-05: Layout & Canvas (3/4)
  • VQ-06: Axis Labels & Title (2/2)
  • VQ-07: Palette Compliance (2/2)

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (4/8) - Sophisticated technique, but busy/hard-to-parse result
  • DE-02: Visual Refinement (4/6) - Clean theme_void chrome, generous whitespace
  • DE-03: Data Storytelling (3/6) - Depth-alpha hierarchy present but overall shape doesn't clearly guide the eye

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5)
  • SC-02: Required Features (4/4)
  • SC-03: Data Mapping (3/3)
  • SC-04: Title & Legend (3/3)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6)
  • DQ-02: Realistic Context (5/5)
  • DQ-03: Appropriate Scale (4/4)

Code Quality (8/10)

  • CQ-01: KISS Structure (2/3) - Two small helper functions, justified but not pure-script
  • CQ-02: Reproducibility (1/2) - np.random.seed(42) set but never used (data is fully deterministic)
  • CQ-03: Clean Imports (2/2)
  • CQ-04: Code Elegance (2/2)
  • CQ-05: Output & API (1/1)

Library Mastery (5/10)

  • LM-01: Idiomatic Usage (3/5) - Uses plotnine's own grammar throughout, though the whole approach is a necessary workaround
  • LM-02: Distinctive Features (2/5) - Creative custom projection, but execution quality limits the payoff

Score Caps Applied

  • None

Strengths

  • Technically sophisticated hand-rolled 3D-to-2D projection (view/right/up basis vectors, painter's-algorithm depth sort, depth-based alpha for approximate hidden-line suppression) built entirely from plotnine's native geom_segment/geom_text — respects the library's no-matplotlib-workaround rule.
  • Z-axis tick labels now have leader segments connecting them back to the axis line, fixing the previous attempt's stranded-label issue.
  • Correct Imprint palette usage and correct theme-adaptive chrome tokens — all text legible in both themes with no dark-on-dark/light-on-light failures.
  • Title format, three labeled axes with units and tick marks, and a deterministic ripple dataset all match the specification.

Weaknesses

  • The wireframe reads as a dense, self-crossing tangle (a "crown"/basket-weave pattern) rather than a legible rippled surface — Z_LIFT=3.2 combined with the multi-period sin(sqrt(x^2+y^2)) ripple over a 21x21 grid makes adjacent rings overlap heavily once projected. Try reducing Z_LIFT to roughly 1.5-2.0 and/or slightly reducing grid_n, and consider widening the depth-alpha range (currently 0.12-0.6) so near-side rings separate more clearly from far-side ones.
  • np.random.seed(42) is dead code — remove it since the grid data is fully deterministic (linspace/meshgrid/sin, no np.random calls).
  • The X/Y/Z axis lines converge at a point in the middle of the wireframe mass, drawing the eye through the densest part of the mesh instead of framing it from a clear corner — consider nudging the axis-box corner or lightening mesh alpha near the convergence point.

Issues Found

  1. VQ-03 / DE-03 MEDIUM: Wireframe is visually tangled and hard to read as a coherent surface
    • Fix: Reduce Z_LIFT (currently 3.2) toward ~1.5-2.0 and/or widen the depth-alpha range so the concentric ripple structure stays traceable.
  2. CQ-02 LOW: Unused np.random.seed(42) call
    • Fix: Remove it — the data pipeline is already fully deterministic.

AI Feedback for Next Attempt

The technique (hand-rolled 3D projection with depth-based alpha) is sound and well within plotnine's grammar, but the height exaggeration is too aggressive for this ripple function, causing the mesh to read as a tangled crown rather than a legible topology. Reduce Z_LIFT and/or widen the depth-alpha contrast so near/far rings separate visually. Also drop the unused np.random.seed(42) call.

Verdict: REJECTED

@github-actions github-actions Bot added quality:77 Quality score 77/100 ai-rejected Quality not OK, triggers update and removed quality:72 Quality score 72/100 labels Sep 10, 2026
@github-actions github-actions Bot added ai-attempt-2 Second repair attempt and removed ai-rejected Quality not OK, triggers update labels Sep 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 2/4

Applied fixes based on AI review feedback.

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


🤖 impl-repair

@claude

claude Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 3/3

Image Description

Light render (plot-light.png): Warm off-white (#FAF8F1) background. Title "wireframe-3d-basic · python · plotnine · anyplot.ai" centered at top in dark ink, clearly legible. Axis labels "X (cm)", "Y (cm)", "Z (mm)" in bold dark ink at the ends of their axis lines. Tick labels (-6..6 on X/Y, -1/0/1 on Z) render in soft grey ink and are individually legible, though the X=0/X=3 ticks sit close to the Z-axis tick cluster in the upper-right, crowding that corner. The wireframe mesh is brand green (#009E73), forming a rippled "drumhead" bowl with grid lines in both x and y directions; depth-based alpha makes the near side fully opaque and the far/top ridge fade to near-invisibility (~0.08 alpha). All text is readable against the light background — no light-on-light failures.

Dark render (plot-dark.png): Warm near-black (#1A1A17) background. Title, axis labels, and tick labels flip to light ink (#F0EFE8 labels / #B8B7B0 ticks/axis lines) and remain clearly readable — no dark-on-dark failures observed. The mesh color is identical brand green (#009E73) to the light render — only chrome flipped, as required. Same depth-fade behavior and same faint top ridge as the light render.

Both renders pass legibility; the only notable rough edges are the tick-label crowding in the upper-right and the very faint far-side mesh.

Score: 85/100

Category Score Max
Visual Quality 23 30
Design Excellence 16 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 9 10
Library Mastery 8 10
Total 85 100

Visual Quality (23/30)

  • VQ-01: Text Legibility (6/8) - readable in both themes; X/Z tick labels crowd together in the upper-right
  • VQ-02: No Overlap (4/6) - X-axis tick "0" sits very close to Z-axis tick "1", near-collision
  • VQ-03: Element Visibility (4/6) - depth-fade alpha floor (~0.08) makes the far/top mesh ridge nearly invisible
  • VQ-04: Color Accessibility (2/2) - strong single-hue contrast, no red-green reliance
  • VQ-05: Layout & Canvas (3/4) - canvas dimension gate passed; good proportions; minor crowding
  • VQ-06: Axis Labels & Title (2/2) - descriptive with units (cm, mm)
  • VQ-07: Palette Compliance (2/2) - #009E73 identical across themes; backgrounds match spec exactly

Design Excellence (16/20)

  • DE-01: Aesthetic Sophistication (6/8) - genuine camera-projection math, painter's-algorithm depth sorting, deliberate axis-corner placement
  • DE-02: Visual Refinement (5/6) - theme_void, minimal partial axis frame, generous whitespace
  • DE-03: Data Storytelling (5/6) - depth-fade creates clear near/far hierarchy and a legible focal point

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) - correct wireframe via legitimate manual 3D-to-2D projection (per plotnine's no-3D-native-support rule, no matplotlib fallback)
  • SC-02: Required Features (4/4) - grid lines in both directions, elevation 30/azimuth 45 camera, all three axes labeled with ticks
  • SC-03: Data Mapping (3/3) - X/Y/Z correctly mapped across full data range
  • SC-04: Title & Legend (3/3) - title matches mandated format; no legend needed for single series

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) - grid mesh, camera projection, axis frame and ticks; partial (not full-box) axis frame
  • DQ-02: Realistic Context (5/5) - plausible, neutral "drumhead vibration" framing with sensible cm/mm units
  • DQ-03: Appropriate Scale (4/4) - X/Y range -6..6 cm, Z displacement ~-1..1 mm, physically sensible

Code Quality (9/10)

  • CQ-01: KISS Structure (2/3) - two small helper functions (project, depth), justified by the manual projection math
  • CQ-02: Reproducibility (2/2) - fully deterministic linspace/meshgrid
  • CQ-03: Clean Imports (2/2) - all imports used
  • CQ-04: Code Elegance (2/2) - appropriate complexity, no fake UI
  • CQ-05: Output & API (1/1) - saves plot-{THEME}.png at correct landscape dimensions

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (4/5) - faithful use of plotnine's own geoms (geom_segment, geom_text, theme_void) to build the projection
  • LM-02: Distinctive Features (4/5) - custom camera-projection + depth-sorted alpha painter's algorithm is genuinely distinctive for a library with no native 3D support

Score Caps Applied

  • None

Strengths

  • Faithful adherence to plotnine's "no 3D workaround" rule — implements genuine camera-projection math (elevation 30°/azimuth 45°) instead of faking 3D or falling back to matplotlib.
  • Depth-based alpha combined with painter's-algorithm edge sorting creates a convincing hidden-line-suppression effect with real visual hierarchy.
  • Correct theme-adaptive chrome: identical brand-green mesh across light/dark, INK/INK_SOFT correctly applied, both backgrounds match spec exactly.
  • Deterministic, well-commented code explaining non-obvious choices (e.g. axis-corner selection to avoid cutting through the densest part of the mesh).
  • Physically plausible "drumhead vibration" framing with sensible cm/mm units and a legible 21x21 grid density.

Weaknesses

  • In the upper-right region, the X-axis tick label "0" (and to a lesser extent "3") lands very close to the Z-axis tick labels ("1"/"0"), crowding that area — increase separation between the X-tick offset (currently y=-9.6) and the Z-axis tick/leader cluster.
  • The far/top ridge of the wireframe fades to alpha≈0.08, verging on invisible in both renders — raise the alpha floor in scale_alpha_continuous (e.g. to ~0.18-0.20) so the distant surface stays faintly legible.
  • Two small top-level helper functions (project, depth) deviate from the CQ-01 "no functions" default — justified here by the manual 3D-projection math.

Issues Found

  1. VQ-02 MEDIUM: X-axis tick "0" nearly collides with Z-axis tick "1" in the upper-right corner of the frame
    • Fix: Push the X-tick offset further from the plot (e.g. y=-11 instead of -9.6), or move the Z-tick leader further from the axis corner
  2. VQ-03 LOW: Far/top ridge of the mesh fades to near-invisibility (alpha≈0.08)
    • Fix: Raise the alpha floor in scale_alpha_continuous(range=(0.08, 0.85)) to roughly (0.18, 0.85)

AI Feedback for Next Attempt

This implementation is solid — the manual camera projection and depth-fade painter's algorithm are genuinely well engineered and should be kept. If further tuned: separate the X-axis ticks from the Z-axis tick cluster in the upper-right corner (they currently crowd together), and raise the minimum alpha for the depth fade so the far side of the mesh doesn't nearly disappear.

Verdict: APPROVED

@github-actions github-actions Bot added quality:85 Quality score 85/100 ai-approved Quality OK, ready for merge and removed quality:77 Quality score 77/100 labels Sep 10, 2026
@MarkusNeusinger
MarkusNeusinger merged commit bd4f8a2 into main Sep 10, 2026
@MarkusNeusinger
MarkusNeusinger deleted the implementation/wireframe-3d-basic/plotnine branch September 10, 2026 06:56
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant