From 1898fc58386102090d4ad2edcb68bff2bac62c2c Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Sun, 5 Apr 2026 22:39:19 +0200 Subject: [PATCH 1/7] =?UTF-8?q?update(dendrogram-basic):=20bokeh=20?= =?UTF-8?q?=E2=80=94=20comprehensive=20quality=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive review improving code quality, data choice, visual design, spec compliance, and library feature usage. --- .../dendrogram-basic/implementations/bokeh.py | 149 +++++++++--------- plots/dendrogram-basic/metadata/bokeh.yaml | 10 +- 2 files changed, 80 insertions(+), 79 deletions(-) diff --git a/plots/dendrogram-basic/implementations/bokeh.py b/plots/dendrogram-basic/implementations/bokeh.py index b8054590e0..2bb79d14bb 100644 --- a/plots/dendrogram-basic/implementations/bokeh.py +++ b/plots/dendrogram-basic/implementations/bokeh.py @@ -1,12 +1,12 @@ -""" pyplots.ai +"""pyplots.ai dendrogram-basic: Basic Dendrogram -Library: bokeh 3.8.1 | Python 3.13.11 -Quality: 91/100 | Created: 2025-12-23 +Library: bokeh 3.8.2 | Python 3.14.3 +Quality: /100 | Updated: 2026-04-05 """ import numpy as np from bokeh.io import export_png -from bokeh.models import Label +from bokeh.models import ColumnDataSource, Label from bokeh.plotting import figure, output_file, save from scipy.cluster.hierarchy import leaves_list, linkage @@ -14,8 +14,6 @@ # Data - Iris flower measurements (4 features for 15 samples) np.random.seed(42) -# Simulate iris-like measurements: sepal length, sepal width, petal length, petal width -# Three species with distinct characteristics samples_per_species = 5 labels = [] @@ -26,10 +24,10 @@ labels.append(f"Setosa-{i + 1}") data.append( [ - 5.0 + np.random.randn() * 0.3, # sepal length - 3.4 + np.random.randn() * 0.3, # sepal width - 1.5 + np.random.randn() * 0.2, # petal length - 0.3 + np.random.randn() * 0.1, # petal width + 5.0 + np.random.randn() * 0.3, + 3.4 + np.random.randn() * 0.3, + 1.5 + np.random.randn() * 0.2, + 0.3 + np.random.randn() * 0.1, ] ) @@ -38,10 +36,10 @@ labels.append(f"Versicolor-{i + 1}") data.append( [ - 5.9 + np.random.randn() * 0.4, # sepal length - 2.8 + np.random.randn() * 0.3, # sepal width - 4.3 + np.random.randn() * 0.4, # petal length - 1.3 + np.random.randn() * 0.2, # petal width + 5.9 + np.random.randn() * 0.4, + 2.8 + np.random.randn() * 0.3, + 4.3 + np.random.randn() * 0.4, + 1.3 + np.random.randn() * 0.2, ] ) @@ -50,10 +48,10 @@ labels.append(f"Virginica-{i + 1}") data.append( [ - 6.6 + np.random.randn() * 0.5, # sepal length - 3.0 + np.random.randn() * 0.3, # sepal width - 5.5 + np.random.randn() * 0.5, # petal length - 2.0 + np.random.randn() * 0.3, # petal width + 6.6 + np.random.randn() * 0.5, + 3.0 + np.random.randn() * 0.3, + 5.5 + np.random.randn() * 0.5, + 2.0 + np.random.randn() * 0.3, ] ) @@ -68,7 +66,6 @@ ordered_labels = [labels[i] for i in leaf_order] # Build dendrogram structure manually -# Position of each node (leaf nodes get integer positions) node_positions = {} for idx, leaf_idx in enumerate(leaf_order): node_positions[leaf_idx] = idx @@ -77,103 +74,107 @@ max_dist = linkage_matrix[:, 2].max() color_threshold = 0.7 * max_dist -# Collect line segments for drawing -line_xs = [] -line_ys = [] -line_colors = [] +# Collect line segments grouped by color for multi_line rendering +above_xs, above_ys = [], [] +below_xs, below_ys = [], [] -# Process each merge in the linkage matrix for i, (left, right, dist, _) in enumerate(linkage_matrix): left, right = int(left), int(right) new_node = n_samples + i - # Get x positions of children left_x = node_positions[left] right_x = node_positions[right] + left_y = 0 if left < n_samples else linkage_matrix[left - n_samples, 2] + right_y = 0 if right < n_samples else linkage_matrix[right - n_samples, 2] - # Get y positions (heights) of children - if left < n_samples: - left_y = 0 - else: - left_y = linkage_matrix[left - n_samples, 2] - - if right < n_samples: - right_y = 0 - else: - right_y = linkage_matrix[right - n_samples, 2] - - # New node position is midpoint of children new_x = (left_x + right_x) / 2 node_positions[new_node] = new_x - # Determine color based on threshold - color = "#306998" if dist > color_threshold else "#FFD43B" - - # Draw left vertical line - line_xs.append([left_x, left_x]) - line_ys.append([left_y, dist]) - line_colors.append(color) + # U-shaped connector: left vertical, horizontal, right vertical + xs = [left_x, left_x, right_x, right_x] + ys = [left_y, dist, dist, right_y] - # Draw right vertical line - line_xs.append([right_x, right_x]) - line_ys.append([right_y, dist]) - line_colors.append(color) - - # Draw horizontal line connecting the two - line_xs.append([left_x, right_x]) - line_ys.append([dist, dist]) - line_colors.append(color) + if dist > color_threshold: + above_xs.append(xs) + above_ys.append(ys) + else: + below_xs.append(xs) + below_ys.append(ys) -# Create figure with extra space at bottom for labels +# Plot p = figure( width=4800, height=2700, - title="dendrogram-basic · bokeh · pyplots.ai", - x_axis_label="Sample", - y_axis_label="Distance (Ward)", - x_range=(-0.5, n_samples - 0.5), - y_range=(-max_dist * 0.18, max_dist * 1.1), + title="Iris Species Clustering · dendrogram-basic · bokeh · pyplots.ai", + x_axis_label="Iris Sample", + y_axis_label="Distance (Ward's Method)", + x_range=(-0.8, n_samples - 0.2), + y_range=(-max_dist * 0.16, max_dist * 1.08), toolbar_location=None, ) -# Draw dendrogram lines with thicker lines for visibility -for xs, ys, color in zip(line_xs, line_ys, line_colors, strict=True): - p.line(xs, ys, line_width=4, line_color=color) +# Draw dendrogram branches using multi_line with ColumnDataSource +if below_xs: + source_below = ColumnDataSource(data={"xs": below_xs, "ys": below_ys}) + p.multi_line( + xs="xs", ys="ys", source=source_below, line_width=4, line_color="#D4A017", legend_label="Within-cluster" + ) -# Add leaf labels with larger font +source_above = ColumnDataSource(data={"xs": above_xs, "ys": above_ys}) +p.multi_line(xs="xs", ys="ys", source=source_above, line_width=4, line_color="#306998", legend_label="Between-cluster") + +# Leaf labels for idx, label in enumerate(ordered_labels): label_obj = Label( x=idx, y=-max_dist * 0.02, text=label, text_font_size="20pt", + text_color="#444444", text_align="right", - angle=0.785, # 45 degrees in radians + angle=0.785, angle_units="rad", y_offset=-15, ) p.add_layout(label_obj) -# Style - larger fonts for 4800x2700 canvas -p.title.text_font_size = "32pt" +# Style +p.title.text_font_size = "30pt" +p.title.text_font_style = "normal" +p.title.text_color = "#333333" p.xaxis.axis_label_text_font_size = "24pt" p.yaxis.axis_label_text_font_size = "24pt" -p.xaxis.major_label_text_font_size = "0pt" # Hide default x-axis labels +p.xaxis.axis_label_text_color = "#555555" +p.yaxis.axis_label_text_color = "#555555" +p.xaxis.major_label_text_font_size = "0pt" p.yaxis.major_label_text_font_size = "20pt" +p.yaxis.major_label_text_color = "#666666" -# Grid styling p.xgrid.visible = False -p.ygrid.grid_line_alpha = 0.3 -p.ygrid.grid_line_dash = "dashed" +p.ygrid.grid_line_alpha = 0.15 +p.ygrid.grid_line_dash = [1, 0] -# Remove tick marks on x-axis +p.xaxis.axis_line_color = "#CCCCCC" +p.yaxis.axis_line_color = "#CCCCCC" p.xaxis.major_tick_line_color = None p.xaxis.minor_tick_line_color = None - -# Clean outline +p.yaxis.major_tick_line_color = "#CCCCCC" +p.yaxis.minor_tick_line_color = None p.outline_line_color = None -# Save outputs +# Legend +p.legend.location = "top_right" +p.legend.label_text_font_size = "18pt" +p.legend.label_text_color = "#444444" +p.legend.glyph_width = 40 +p.legend.glyph_height = 6 +p.legend.spacing = 8 +p.legend.padding = 15 +p.legend.background_fill_alpha = 0.9 +p.legend.border_line_color = "#DDDDDD" +p.legend.border_line_alpha = 0.5 + +# Save export_png(p, filename="plot.png") output_file("plot.html") save(p) diff --git a/plots/dendrogram-basic/metadata/bokeh.yaml b/plots/dendrogram-basic/metadata/bokeh.yaml index 9f0d1c41d3..af0fe05207 100644 --- a/plots/dendrogram-basic/metadata/bokeh.yaml +++ b/plots/dendrogram-basic/metadata/bokeh.yaml @@ -1,15 +1,15 @@ library: bokeh specification_id: dendrogram-basic created: '2025-12-23T10:01:43Z' -updated: '2025-12-23T10:07:56Z' -generated_by: claude-opus-4-5-20251101 +updated: '2026-04-05T20:00:00+00:00' +generated_by: claude-opus-4-6 workflow_run: 20457532402 issue: 0 -python_version: 3.13.11 -library_version: 3.8.1 +python_version: '3.14.3' +library_version: 3.8.2 preview_url: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.png preview_html: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.html -quality_score: 91 +quality_score: null impl_tags: dependencies: - scipy From a1fc32066fce2af60543e309a8fdf64c6880d349 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 20:43:12 +0000 Subject: [PATCH 2/7] chore(bokeh): update quality score 84 and review feedback for dendrogram-basic --- .../dendrogram-basic/implementations/bokeh.py | 4 +- plots/dendrogram-basic/metadata/bokeh.yaml | 268 ++++++++++-------- 2 files changed, 149 insertions(+), 123 deletions(-) diff --git a/plots/dendrogram-basic/implementations/bokeh.py b/plots/dendrogram-basic/implementations/bokeh.py index 2bb79d14bb..1772540183 100644 --- a/plots/dendrogram-basic/implementations/bokeh.py +++ b/plots/dendrogram-basic/implementations/bokeh.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai dendrogram-basic: Basic Dendrogram Library: bokeh 3.8.2 | Python 3.14.3 -Quality: /100 | Updated: 2026-04-05 +Quality: 84/100 | Updated: 2026-04-05 """ import numpy as np diff --git a/plots/dendrogram-basic/metadata/bokeh.yaml b/plots/dendrogram-basic/metadata/bokeh.yaml index af0fe05207..991ad212c7 100644 --- a/plots/dendrogram-basic/metadata/bokeh.yaml +++ b/plots/dendrogram-basic/metadata/bokeh.yaml @@ -1,167 +1,185 @@ library: bokeh specification_id: dendrogram-basic created: '2025-12-23T10:01:43Z' -updated: '2026-04-05T20:00:00+00:00' +updated: '2026-04-05T20:43:11Z' generated_by: claude-opus-4-6 workflow_run: 20457532402 issue: 0 -python_version: '3.14.3' +python_version: 3.14.3 library_version: 3.8.2 preview_url: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.png preview_html: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.html -quality_score: null +quality_score: 84 impl_tags: dependencies: - - scipy + - scipy techniques: - - html-export + - annotations + - custom-legend + - html-export patterns: - - data-generation - - iteration-over-groups + - data-generation + - columndatasource + - iteration-over-groups dataprep: - - hierarchical-clustering - styling: [] + - hierarchical-clustering + styling: + - grid-styling review: strengths: - - Excellent manual implementation of dendrogram structure using Bokeh primitives - (line glyphs) - - Two-color scheme effectively distinguishes cluster levels with colorblind-safe - palette - - Biologically accurate iris data clustering with proper species separation - - Clean KISS code structure with proper seed for reproducibility - - Rotated labels prevent overlap and maintain readability - - Generates both PNG and interactive HTML output leveraging Bokeh web capabilities + - Perfect spec compliance with correct dendrogram structure and proportional merge + distances + - Clean code structure with appropriate manual dendrogram construction for Bokeh + - Good use of Bokeh-specific patterns (ColumnDataSource, multi_line, Label) + - Effective two-color scheme distinguishing within-cluster from between-cluster + merges + - Full code quality marks — reproducible, clean, and well-structured weaknesses: - - X-axis label Sample is generic; could be more descriptive like Iris Samples - - No legend or annotation explaining the blue/yellow color threshold meaning - - Could use ColumnDataSource for more idiomatic Bokeh code - image_description: 'The plot displays a hierarchical dendrogram visualizing clustering - of 15 iris flower samples across three species (Setosa, Versicolor, Virginica). - The tree structure uses a two-color scheme: blue (#306998) for high-level merges - above the color threshold and yellow/gold (#FFD43B) for lower-level within-cluster - merges. The Y-axis shows "Distance (Ward)" ranging from 0 to approximately 10, - with dashed grid lines. The X-axis is labeled "Sample" with 15 rotated labels - (45°) showing sample names like "Setosa-1", "Versicolor-4", "Virginica-3", etc. - The title "dendrogram-basic · bokeh · pyplots.ai" appears at the top left. The - dendrogram correctly shows Setosa samples clustering separately on the left, while - Versicolor and Virginica samples intermix on the right before merging at a higher - distance level - biologically accurate for iris data.' + - Large empty space in the upper portion of the plot due to the high top-level merge + distance + - Leaf labels could be more visually connected to their species groups (e.g., color-coded + by species) + - Legend is small and placed far from the data in the corner + - Data storytelling could be enhanced with species-level color coding or cluster + annotations + image_description: 'The plot displays a dendrogram of iris species hierarchical + clustering with 15 samples (5 each of Setosa, Versicolor, Virginica). The tree + uses two colors: dark blue (#306998) for between-cluster merges (the top-level + merge at distance ~10 connecting the Setosa group to the Versicolor/Virginica + group) and gold (#D4A017) for within-cluster merges (all lower-level merges). + U-shaped connectors link samples and sub-clusters at their merge distances. The + x-axis labels are rotated ~45 degrees showing sample names (e.g., "Setosa-4", + "Versicolor-1", "Virginica-3"), ordered by clustering proximity. The y-axis shows + "Distance (Ward''s Method)" from 0 to ~10. A legend in the top-right distinguishes + "Within-cluster" (gold) from "Between-cluster" (blue). The background is white + with subtle y-axis grid lines. The outline is removed and the overall layout is + clean. The clustering correctly groups species together, with Versicolor and Virginica + merging before joining Setosa.' criteria_checklist: visual_quality: - score: 36 - max: 40 + score: 26 + max: 30 items: - id: VQ-01 name: Text Legibility - score: 9 - max: 10 + score: 7 + max: 8 passed: true - comment: Title, axis labels, and tick labels are readable; rotated sample - labels are slightly small but legible + comment: All font sizes explicitly set (title 30pt, axis labels 24pt, ticks + 20pt, leaf labels 20pt). Leaf labels slightly small at rendered scale but + readable. - id: VQ-02 name: No Overlap - score: 8 - max: 8 + score: 5 + max: 6 passed: true - comment: No overlapping text elements; rotated labels fit well + comment: Rotated leaf labels avoid overlap. Some labels appear tight but remain + readable. - id: VQ-03 name: Element Visibility - score: 8 - max: 8 + score: 5 + max: 6 passed: true - comment: Line width of 4 makes dendrogram branches clearly visible + comment: Lines at line_width=4 are visible. U-shaped connectors clear, slightly + thin for 4800px canvas. - id: VQ-04 name: Color Accessibility - score: 5 - max: 5 + score: 4 + max: 4 passed: true - comment: Blue and yellow provide excellent contrast and are colorblind-safe + comment: Blue and gold are easily distinguishable and colorblind-safe. - id: VQ-05 - name: Layout Balance - score: 4 - max: 5 + name: Layout & Canvas + score: 3 + max: 4 passed: true - comment: Good proportions, slight extra whitespace on right side + comment: Good proportions but large empty area in upper half due to top-level + merge distance. Legend far from data. - id: VQ-06 - name: Axis Labels - score: 1 + name: Axis Labels & Title + score: 2 max: 2 passed: true - comment: '"Distance (Ward)" is descriptive but "Sample" is generic' - - id: VQ-07 - name: Grid & Legend - score: 1 - max: 2 + comment: 'Descriptive labels: ''Iris Sample'' and ''Distance (Ward''s Method)''.' + design_excellence: + score: 12 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: Thoughtful two-color palette (Python Blue + gold), custom styling, + above defaults but not publication-exceptional. + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: Subtle grid (alpha 0.15), outline removed, x-grid hidden, tick marks + refined. + - id: DE-03 + name: Data Storytelling + score: 3 + max: 6 passed: true - comment: Dashed grid is subtle (alpha 0.3), no legend needed but color meaning - unexplained + comment: Within/between-cluster color coding creates some hierarchy. Species + groups are clear but could be stronger. spec_compliance: - score: 25 - max: 25 + score: 15 + max: 15 items: - id: SC-01 name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct dendrogram/tree visualization - - id: SC-02 - name: Data Mapping score: 5 max: 5 passed: true - comment: Samples on X-axis, merge distances on Y-axis - - id: SC-03 + comment: Correct dendrogram with proper U-shaped connectors. + - id: SC-02 name: Required Features - score: 5 - max: 5 + score: 4 + max: 4 passed: true - comment: Hierarchical structure, branch heights proportional to merge distances, - labels present - - id: SC-04 - name: Data Range + comment: Hierarchical clustering via scipy linkage, proportional branch heights, + vertical orientation, leaf labels. + - id: SC-03 + name: Data Mapping score: 3 max: 3 passed: true - comment: Y-axis shows full range from 0 to max distance - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: No legend required for this plot type - - id: SC-06 - name: Title Format - score: 2 - max: 2 + comment: X-axis shows samples, Y-axis shows merge distances. Correct mapping. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 passed: true - comment: Uses correct format "dendrogram-basic · bokeh · pyplots.ai" + comment: Title follows format. Legend correctly labels cluster types. data_quality: - score: 18 - max: 20 + score: 14 + max: 15 items: - id: DQ-01 name: Feature Coverage - score: 7 - max: 8 + score: 5 + max: 6 passed: true - comment: Shows hierarchical merging at multiple levels, cluster separation - visible; could show more diversity in merge distances + comment: Shows 3 species with varied merge distances, clear intra- and inter-species + clustering. - id: DQ-02 name: Realistic Context - score: 7 - max: 7 + score: 5 + max: 5 passed: true - comment: Iris flower species is a classic, real-world clustering example + comment: Iris flower species — classic, real-world, neutral scientific dataset. - id: DQ-03 name: Appropriate Scale score: 4 - max: 5 + max: 4 passed: true - comment: 15 samples is within recommended 10-50 range; Ward distances are - realistic + comment: Realistic iris measurement values, sensible merge distances. code_quality: - score: 9 + score: 10 max: 10 items: - id: CQ-01 @@ -169,40 +187,48 @@ review: score: 3 max: 3 passed: true - comment: 'Linear script: imports → data → linkage → plot → save' + comment: 'Linear flow: imports, data, linkage, dendrogram construction, plot, + style, 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) set. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used + comment: All imports are used. - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 + name: Code Elegance + score: 2 + max: 2 passed: true - comment: Uses current Bokeh API + comment: Manual dendrogram construction is necessary for Bokeh. Clean implementation. - id: CQ-05 - name: Output Correct - score: 0 + name: Output & API + score: 1 max: 1 - passed: false - comment: Saves both plot.png and plot.html (minor issue, but PNG is correct) - library_features: - score: 3 - max: 5 + passed: true + comment: Saves as plot.png via export_png, also saves HTML. + 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: Good use of ColumnDataSource, multi_line, Label objects. Idiomatic + Bokeh patterns. + - id: LM-02 + name: Distinctive Features score: 3 max: 5 passed: true - comment: Manual rendering with Bokeh figure and line glyphs; generates HTML - output for interactivity; however, could use ColumnDataSource pattern more - verdict: APPROVED + comment: multi_line with ColumnDataSource is Bokeh-specific. HTML export leverages + Bokeh web-native nature. + verdict: REJECTED From dad6627bb1e762934a29de47f0506ab2a2083c58 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 20:54:53 +0000 Subject: [PATCH 3/7] chore(bokeh): update quality score 84 and review feedback for dendrogram-basic --- plots/dendrogram-basic/metadata/bokeh.yaml | 139 ++++++++++----------- 1 file changed, 65 insertions(+), 74 deletions(-) diff --git a/plots/dendrogram-basic/metadata/bokeh.yaml b/plots/dendrogram-basic/metadata/bokeh.yaml index 991ad212c7..1ad0d5cc78 100644 --- a/plots/dendrogram-basic/metadata/bokeh.yaml +++ b/plots/dendrogram-basic/metadata/bokeh.yaml @@ -1,7 +1,7 @@ library: bokeh specification_id: dendrogram-basic created: '2025-12-23T10:01:43Z' -updated: '2026-04-05T20:43:11Z' +updated: '2026-04-05T20:54:53Z' generated_by: claude-opus-4-6 workflow_run: 20457532402 issue: 0 @@ -14,50 +14,45 @@ impl_tags: dependencies: - scipy techniques: - - annotations - - custom-legend - html-export patterns: - data-generation - - columndatasource - iteration-over-groups + - columndatasource dataprep: - hierarchical-clustering styling: - grid-styling review: strengths: - - Perfect spec compliance with correct dendrogram structure and proportional merge - distances - - Clean code structure with appropriate manual dendrogram construction for Bokeh - - Good use of Bokeh-specific patterns (ColumnDataSource, multi_line, Label) - - Effective two-color scheme distinguishing within-cluster from between-cluster - merges - - Full code quality marks — reproducible, clean, and well-structured + - Excellent spec compliance with all required dendrogram features and correct hierarchical + structure + - Clean, well-organized code with proper seed for reproducibility + - Strong design with species-specific coloring and background shading that aids + cluster identification + - Good data storytelling with visual hierarchy communicating three-species clustering + pattern weaknesses: - - Large empty space in the upper portion of the plot due to the high top-level merge + - No Bokeh-specific interactive features (HoverTool for merge distances) — biggest + gap for Library Mastery + - Lower-level merge structure visually compressed due to dominant top-level merge distance - - Leaf labels could be more visually connected to their species groups (e.g., color-coded - by species) - - Legend is small and placed far from the data in the corner - - Data storytelling could be enhanced with species-level color coding or cluster - annotations - image_description: 'The plot displays a dendrogram of iris species hierarchical - clustering with 15 samples (5 each of Setosa, Versicolor, Virginica). The tree - uses two colors: dark blue (#306998) for between-cluster merges (the top-level - merge at distance ~10 connecting the Setosa group to the Versicolor/Virginica - group) and gold (#D4A017) for within-cluster merges (all lower-level merges). - U-shaped connectors link samples and sub-clusters at their merge distances. The - x-axis labels are rotated ~45 degrees showing sample names (e.g., "Setosa-4", - "Versicolor-1", "Virginica-3"), ordered by clustering proximity. The y-axis shows - "Distance (Ward''s Method)" from 0 to ~10. A legend in the top-right distinguishes - "Within-cluster" (gold) from "Between-cluster" (blue). The background is white - with subtle y-axis grid lines. The outline is removed and the overall layout is - clean. The clustering correctly groups species together, with Versicolor and Virginica - merging before joining Setosa.' + - Color palette not fully colorblind-safe (blue vs pink/mauve distinction) + image_description: 'The plot displays a vertical dendrogram of 15 iris flower samples + clustered into three species groups (Setosa, Versicolor, Virginica) using Ward''s + method. Each species cluster is rendered in a distinct color: light blue for Setosa + (left group of 5), pink/mauve for Versicolor (center group of 5), and orange for + Virginica (right group of 5). Cross-group merges at higher distances are drawn + in dark gray/black. Subtle colored background rectangles shade each species cluster + region. Leaf labels are rotated ~45 degrees at the bottom, with species group + labels below each cluster. The y-axis shows "Distance (Ward''s Method, √ scale)" + ranging from 0 to ~10, and the x-axis is labeled "Iris Sample". A 4-entry legend + in the top-left identifies each color. The title reads "Iris Species Clustering + · dendrogram-basic · bokeh · pyplots.ai". The design is clean with subtle grid + lines and no chart outline.' criteria_checklist: visual_quality: - score: 26 + score: 25 max: 30 items: - id: VQ-01 @@ -65,67 +60,65 @@ review: score: 7 max: 8 passed: true - comment: All font sizes explicitly set (title 30pt, axis labels 24pt, ticks - 20pt, leaf labels 20pt). Leaf labels slightly small at rendered scale but - readable. + comment: Font sizes explicitly set (30pt title, 24pt labels, 20pt ticks). + Leaf labels could be slightly larger. - id: VQ-02 name: No Overlap score: 5 max: 6 passed: true - comment: Rotated leaf labels avoid overlap. Some labels appear tight but remain - readable. + comment: Rotated leaf labels avoid overlap. Slight crowding between adjacent + labels. - id: VQ-03 name: Element Visibility score: 5 max: 6 passed: true - comment: Lines at line_width=4 are visible. U-shaped connectors clear, slightly - thin for 4800px canvas. + comment: Branches visible with line_width=4. Lower-level merges slightly compressed. - id: VQ-04 name: Color Accessibility - score: 4 + score: 3 max: 4 passed: true - comment: Blue and gold are easily distinguishable and colorblind-safe. + comment: Blue, pink, orange, gray mostly distinguishable. Blue/pink could + challenge tritanopia. - id: VQ-05 name: Layout & Canvas score: 3 max: 4 passed: true - comment: Good proportions but large empty area in upper half due to top-level - merge distance. Legend far from data. + comment: Good canvas utilization. High top merge compresses lower structure. - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: 'Descriptive labels: ''Iris Sample'' and ''Distance (Ward''s Method)''.' + comment: Descriptive labels with method info. design_excellence: - score: 12 + score: 14 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 5 + score: 6 max: 8 passed: true - comment: Thoughtful two-color palette (Python Blue + gold), custom styling, - above defaults but not publication-exceptional. + comment: Strong design with species-specific coloring and background shading. + Harmonious palette. - id: DE-02 name: Visual Refinement score: 4 max: 6 passed: true - comment: Subtle grid (alpha 0.15), outline removed, x-grid hidden, tick marks - refined. + comment: Subtle grid, outline removed, refined ticks. Could go further with + minimal chrome. - id: DE-03 name: Data Storytelling - score: 3 + score: 4 max: 6 passed: true - comment: Within/between-cluster color coding creates some hierarchy. Species - groups are clear but could be stronger. + comment: Species coloring and backgrounds create clear visual hierarchy. Group + labels reinforce narrative. spec_compliance: score: 15 max: 15 @@ -135,26 +128,26 @@ review: score: 5 max: 5 passed: true - comment: Correct dendrogram with proper U-shaped connectors. + comment: Correct dendrogram with hierarchical tree structure. - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Hierarchical clustering via scipy linkage, proportional branch heights, - vertical orientation, leaf labels. + comment: Labels, linkage, vertical orientation, proportional heights all present. - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X-axis shows samples, Y-axis shows merge distances. Correct mapping. + comment: Samples on x-axis in leaf order, merge distance on y-axis. - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title follows format. Legend correctly labels cluster types. + comment: Title includes spec-id, library, pyplots.ai. Legend identifies color + groups. data_quality: score: 14 max: 15 @@ -164,20 +157,20 @@ review: score: 5 max: 6 passed: true - comment: Shows 3 species with varied merge distances, clear intra- and inter-species - clustering. + comment: Shows multiple merge levels, within/between cluster distances. Could + show more varied merge distances. - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Iris flower species — classic, real-world, neutral scientific dataset. + comment: Iris flower species — classic, neutral, real-world clustering scenario. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Realistic iris measurement values, sensible merge distances. + comment: Plausible iris feature measurements in cm range. code_quality: score: 10 max: 10 @@ -187,34 +180,33 @@ review: score: 3 max: 3 passed: true - comment: 'Linear flow: imports, data, linkage, dendrogram construction, plot, - style, save.' + comment: 'Clean linear flow: imports, data, linkage, plot, save.' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set. + comment: np.random.seed(42) for deterministic output. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used. + comment: All imports used. - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Manual dendrogram construction is necessary for Bokeh. Clean implementation. + comment: Manual dendrogram construction is clean and well-commented. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png via export_png, also saves HTML. + comment: Saves plot.png and plot.html. Current API. library_mastery: - score: 7 + score: 6 max: 10 items: - id: LM-01 @@ -222,13 +214,12 @@ review: score: 4 max: 5 passed: true - comment: Good use of ColumnDataSource, multi_line, Label objects. Idiomatic - Bokeh patterns. + comment: Good use of ColumnDataSource, multi_line, Label. Follows Bokeh patterns. - id: LM-02 name: Distinctive Features - score: 3 + score: 2 max: 5 - passed: true - comment: multi_line with ColumnDataSource is Bokeh-specific. HTML export leverages - Bokeh web-native nature. + passed: false + comment: HTML export is Bokeh-specific but no interactive features (HoverTool, + TapTool). Major missed opportunity. verdict: REJECTED From 046dbe189fd0b78330af1b67262b3a26456522e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 20:58:59 +0000 Subject: [PATCH 4/7] fix(bokeh): address review feedback for dendrogram-basic Attempt 2/3 - fixes based on AI review --- .../dendrogram-basic/implementations/bokeh.py | 108 ++++++++++++++---- 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/plots/dendrogram-basic/implementations/bokeh.py b/plots/dendrogram-basic/implementations/bokeh.py index 1772540183..6c8e0ad6d1 100644 --- a/plots/dendrogram-basic/implementations/bokeh.py +++ b/plots/dendrogram-basic/implementations/bokeh.py @@ -1,4 +1,4 @@ -""" pyplots.ai +"""pyplots.ai dendrogram-basic: Basic Dendrogram Library: bokeh 3.8.2 | Python 3.14.3 Quality: 84/100 | Updated: 2026-04-05 @@ -6,7 +6,7 @@ import numpy as np from bokeh.io import export_png -from bokeh.models import ColumnDataSource, Label +from bokeh.models import ColumnDataSource, HoverTool, Label from bokeh.plotting import figure, output_file, save from scipy.cluster.hierarchy import leaves_list, linkage @@ -70,15 +70,28 @@ for idx, leaf_idx in enumerate(leaf_order): node_positions[leaf_idx] = idx +# Track cluster members for hover info +cluster_members = {} +for i in range(n_samples): + cluster_members[i] = [labels[i]] + # Color threshold for distinguishing clusters max_dist = linkage_matrix[:, 2].max() color_threshold = 0.7 * max_dist -# Collect line segments grouped by color for multi_line rendering -above_xs, above_ys = [], [] -below_xs, below_ys = [], [] +# Colorblind-safe palette +colors_within = "#0F7B6C" # teal for within-cluster +colors_between = "#444444" # dark gray for between-cluster (cross-species merges) + +# Collect line segments with hover metadata +all_xs, all_ys = [], [] +all_colors = [] +all_distances = [] +all_left_items = [] +all_right_items = [] +all_cluster_sizes = [] -for i, (left, right, dist, _) in enumerate(linkage_matrix): +for i, (left, right, dist, count) in enumerate(linkage_matrix): left, right = int(left), int(right) new_node = n_samples + i @@ -90,44 +103,91 @@ new_x = (left_x + right_x) / 2 node_positions[new_node] = new_x + # Track members + left_members = cluster_members[left] + right_members = cluster_members[right] + cluster_members[new_node] = left_members + right_members + # U-shaped connector: left vertical, horizontal, right vertical xs = [left_x, left_x, right_x, right_x] ys = [left_y, dist, dist, right_y] - if dist > color_threshold: - above_xs.append(xs) - above_ys.append(ys) - else: - below_xs.append(xs) - below_ys.append(ys) + color = colors_between if dist > color_threshold else colors_within + + all_xs.append(xs) + all_ys.append(ys) + all_colors.append(color) + all_distances.append(f"{dist:.2f}") + all_left_items.append(", ".join(left_members[:3]) + ("..." if len(left_members) > 3 else "")) + all_right_items.append(", ".join(right_members[:3]) + ("..." if len(right_members) > 3 else "")) + all_cluster_sizes.append(str(int(count))) + +# Apply sqrt scaling to y-axis for better visibility of lower merges +sqrt_max = np.sqrt(max_dist) + +all_ys_scaled = [] +for ys in all_ys: + all_ys_scaled.append([np.sqrt(y) for y in ys]) # Plot p = figure( width=4800, height=2700, - title="Iris Species Clustering · dendrogram-basic · bokeh · pyplots.ai", + title="Iris Species Clustering \u00b7 dendrogram-basic \u00b7 bokeh \u00b7 pyplots.ai", x_axis_label="Iris Sample", - y_axis_label="Distance (Ward's Method)", + y_axis_label="Distance (Ward\u2019s Method, \u221a scale)", x_range=(-0.8, n_samples - 0.2), - y_range=(-max_dist * 0.16, max_dist * 1.08), + y_range=(-sqrt_max * 0.16, sqrt_max * 1.08), toolbar_location=None, ) -# Draw dendrogram branches using multi_line with ColumnDataSource -if below_xs: - source_below = ColumnDataSource(data={"xs": below_xs, "ys": below_ys}) - p.multi_line( - xs="xs", ys="ys", source=source_below, line_width=4, line_color="#D4A017", legend_label="Within-cluster" - ) +# Draw dendrogram branches using multi_line with ColumnDataSource and hover data +source = ColumnDataSource( + data={ + "xs": all_xs, + "ys": all_ys_scaled, + "color": all_colors, + "distance": all_distances, + "left_cluster": all_left_items, + "right_cluster": all_right_items, + "cluster_size": all_cluster_sizes, + } +) + +branch_renderer = p.multi_line( + xs="xs", + ys="ys", + source=source, + line_width=4, + line_color="color", + line_alpha=0.85, + hover_line_width=7, + hover_line_alpha=1.0, + hover_line_color="#E74C3C", +) + +# Add HoverTool for interactive branch inspection +hover = HoverTool( + renderers=[branch_renderer], + tooltips=[ + ("Merge Distance", "@distance"), + ("Cluster Size", "@cluster_size items"), + ("Left", "@left_cluster"), + ("Right", "@right_cluster"), + ], + line_policy="interp", +) +p.add_tools(hover) -source_above = ColumnDataSource(data={"xs": above_xs, "ys": above_ys}) -p.multi_line(xs="xs", ys="ys", source=source_above, line_width=4, line_color="#306998", legend_label="Between-cluster") +# Legend entries via invisible scatter points +p.scatter([], [], color=colors_within, legend_label="Within-cluster", size=0) +p.scatter([], [], color=colors_between, legend_label="Between-cluster", size=0) # Leaf labels for idx, label in enumerate(ordered_labels): label_obj = Label( x=idx, - y=-max_dist * 0.02, + y=-sqrt_max * 0.02, text=label, text_font_size="20pt", text_color="#444444", From 9edde6b642868c6cddfd78a1234b8710b7922cd9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 21:02:42 +0000 Subject: [PATCH 5/7] chore(bokeh): update quality score 85 and review feedback for dendrogram-basic --- .../dendrogram-basic/implementations/bokeh.py | 4 +- plots/dendrogram-basic/metadata/bokeh.yaml | 140 +++++++++--------- 2 files changed, 73 insertions(+), 71 deletions(-) diff --git a/plots/dendrogram-basic/implementations/bokeh.py b/plots/dendrogram-basic/implementations/bokeh.py index 6c8e0ad6d1..df58d47324 100644 --- a/plots/dendrogram-basic/implementations/bokeh.py +++ b/plots/dendrogram-basic/implementations/bokeh.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai dendrogram-basic: Basic Dendrogram Library: bokeh 3.8.2 | Python 3.14.3 -Quality: 84/100 | Updated: 2026-04-05 +Quality: 85/100 | Updated: 2026-04-05 """ import numpy as np diff --git a/plots/dendrogram-basic/metadata/bokeh.yaml b/plots/dendrogram-basic/metadata/bokeh.yaml index 1ad0d5cc78..fe47818ce4 100644 --- a/plots/dendrogram-basic/metadata/bokeh.yaml +++ b/plots/dendrogram-basic/metadata/bokeh.yaml @@ -1,7 +1,7 @@ library: bokeh specification_id: dendrogram-basic created: '2025-12-23T10:01:43Z' -updated: '2026-04-05T20:54:53Z' +updated: '2026-04-05T21:02:41Z' generated_by: claude-opus-4-6 workflow_run: 20457532402 issue: 0 @@ -9,11 +9,13 @@ python_version: 3.14.3 library_version: 3.8.2 preview_url: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.png preview_html: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.html -quality_score: 84 +quality_score: 85 impl_tags: dependencies: - scipy techniques: + - hover-tooltips + - custom-legend - html-export patterns: - data-generation @@ -23,36 +25,38 @@ impl_tags: - hierarchical-clustering styling: - grid-styling + - alpha-blending review: strengths: - - Excellent spec compliance with all required dendrogram features and correct hierarchical - structure - - Clean, well-organized code with proper seed for reproducibility - - Strong design with species-specific coloring and background shading that aids - cluster identification - - Good data storytelling with visual hierarchy communicating three-species clustering - pattern + - Excellent use of Bokeh HoverTool with merge distance, cluster members, and cluster + size metadata + - Clean manual dendrogram construction necessary for Bokeh which lacks built-in + dendrogram + - Colorblind-safe teal/gray palette with good contrast + - Sqrt scaling improves visibility of lower-distance merges + - Realistic iris dataset with clear species clustering + - All font sizes explicitly set for 4800x2700 canvas weaknesses: - - No Bokeh-specific interactive features (HoverTool for merge distances) — biggest - gap for Library Mastery - - Lower-level merge structure visually compressed due to dominant top-level merge - distance - - Color palette not fully colorblind-safe (blue vs pink/mauve distinction) - image_description: 'The plot displays a vertical dendrogram of 15 iris flower samples - clustered into three species groups (Setosa, Versicolor, Virginica) using Ward''s - method. Each species cluster is rendered in a distinct color: light blue for Setosa - (left group of 5), pink/mauve for Versicolor (center group of 5), and orange for - Virginica (right group of 5). Cross-group merges at higher distances are drawn - in dark gray/black. Subtle colored background rectangles shade each species cluster - region. Leaf labels are rotated ~45 degrees at the bottom, with species group - labels below each cluster. The y-axis shows "Distance (Ward''s Method, √ scale)" - ranging from 0 to ~10, and the x-axis is labeled "Iris Sample". A 4-entry legend - in the top-left identifies each color. The title reads "Iris Species Clustering - · dendrogram-basic · bokeh · pyplots.ai". The design is clean with subtle grid - lines and no chart outline.' + - Title format prepends descriptive text before the standard spec-id format + - Between-cluster color (#444444) is subtle against background — needs stronger + contrast + - Legend is small and positioned far from data in top-right corner + - Negative y-range creates unnecessary whitespace below leaf labels + image_description: The plot displays a hierarchical dendrogram of 15 iris flower + samples clustered using Ward's method. The x-axis shows sample labels (Setosa-1 + through -5, Versicolor-1 through -5, Virginica-1 through -5) rotated at approximately + 45 degrees. The y-axis shows "Distance (Ward's Method, √ scale)" with sqrt-transformed + values ranging from -0.5 to ~3.3. U-shaped connectors form the tree structure + with teal-colored branches for within-cluster merges and dark gray for the top-level + between-cluster merge. A legend in the top-right corner labels "Within-cluster" + and "Between-cluster". The title reads "Iris Species Clustering · dendrogram-basic + · bokeh · pyplots.ai". The Setosa samples cluster together on the left, Versicolor + in the middle, and Virginica on the right, with Versicolor and Virginica merging + before joining Setosa at the highest distance level. Grid lines are subtle (y-axis + only), the outline is removed, and the overall appearance is clean and professional. criteria_checklist: visual_quality: - score: 25 + score: 27 max: 30 items: - id: VQ-01 @@ -60,67 +64,66 @@ review: score: 7 max: 8 passed: true - comment: Font sizes explicitly set (30pt title, 24pt labels, 20pt ticks). - Leaf labels could be slightly larger. + comment: All font sizes explicitly set (title 30pt, labels 24pt, ticks 20pt, + leaf labels 20pt). Legend text slightly small. - id: VQ-02 name: No Overlap - score: 5 + score: 6 max: 6 passed: true - comment: Rotated leaf labels avoid overlap. Slight crowding between adjacent - labels. + comment: Labels rotated at 45 degrees prevent all overlap - id: VQ-03 name: Element Visibility score: 5 max: 6 passed: true - comment: Branches visible with line_width=4. Lower-level merges slightly compressed. + comment: Branch lines visible at width 4. Between-cluster color distinction + is subtle. - id: VQ-04 name: Color Accessibility - score: 3 + score: 4 max: 4 passed: true - comment: Blue, pink, orange, gray mostly distinguishable. Blue/pink could - challenge tritanopia. + comment: Teal and dark gray are colorblind-safe with good contrast - id: VQ-05 name: Layout & Canvas score: 3 max: 4 passed: true - comment: Good canvas utilization. High top merge compresses lower structure. + comment: Good canvas usage but negative y-range creates unnecessary whitespace - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Descriptive labels with method info. + comment: Descriptive labels with method and scale info design_excellence: - score: 14 + score: 12 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 6 + score: 5 max: 8 passed: true - comment: Strong design with species-specific coloring and background shading. - Harmonious palette. + comment: Custom teal/gray palette, muted text colors, outline removed. Above + configured default. - id: DE-02 name: Visual Refinement score: 4 max: 6 passed: true - comment: Subtle grid, outline removed, refined ticks. Could go further with - minimal chrome. + comment: Outline removed, x-grid hidden, y-grid subtle, tick marks customized, + axis lines styled - id: DE-03 name: Data Storytelling - score: 4 + score: 3 max: 6 passed: true - comment: Species coloring and backgrounds create clear visual hierarchy. Group - labels reinforce narrative. + comment: Color coding distinguishes within/between-cluster merges. Sqrt scaling + improves lower-distance visibility. spec_compliance: - score: 15 + score: 14 max: 15 items: - id: SC-01 @@ -128,26 +131,26 @@ review: score: 5 max: 5 passed: true - comment: Correct dendrogram with hierarchical tree structure. + comment: Correct dendrogram with U-shaped connectors - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Labels, linkage, vertical orientation, proportional heights all present. + comment: Labels, linkage, proportional heights, vertical orientation all present - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Samples on x-axis in leaf order, merge distance on y-axis. + comment: X shows samples in leaf order, Y shows merge distances - id: SC-04 name: Title & Legend - score: 3 + score: 2 max: 3 passed: true - comment: Title includes spec-id, library, pyplots.ai. Legend identifies color - groups. + comment: Title has extra descriptive prefix before standard format. Legend + labels match. data_quality: score: 14 max: 15 @@ -157,20 +160,20 @@ review: score: 5 max: 6 passed: true - comment: Shows multiple merge levels, within/between cluster distances. Could - show more varied merge distances. + comment: Shows species clustering, varying merge distances, tight and loose + clusters - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Iris flower species — classic, neutral, real-world clustering scenario. + comment: Iris dataset is a classic neutral real-world clustering scenario - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Plausible iris feature measurements in cm range. + comment: Realistic iris flower measurements in cm range code_quality: score: 10 max: 10 @@ -180,33 +183,33 @@ review: score: 3 max: 3 passed: true - comment: 'Clean linear flow: imports, data, linkage, plot, save.' + comment: 'Linear flow: imports, data, clustering, plotting, save' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) for deterministic output. + comment: np.random.seed(42) set - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used. + comment: All imports used - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Manual dendrogram construction is clean and well-commented. + comment: Clean manual dendrogram construction, well-organized - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot.png and plot.html. Current API. + comment: Saves as plot.png and plot.html, current API library_mastery: - score: 6 + score: 8 max: 10 items: - id: LM-01 @@ -214,12 +217,11 @@ review: score: 4 max: 5 passed: true - comment: Good use of ColumnDataSource, multi_line, Label. Follows Bokeh patterns. + comment: ColumnDataSource, multi_line, Label objects, proper figure configuration - id: LM-02 name: Distinctive Features - score: 2 + score: 4 max: 5 - passed: false - comment: HTML export is Bokeh-specific but no interactive features (HoverTool, - TapTool). Major missed opportunity. + passed: true + comment: HoverTool with custom tooltips, hover visual feedback, HTML export verdict: REJECTED From 145b212738484b812e2553be71714b82273f4cf0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 21:09:46 +0000 Subject: [PATCH 6/7] fix(bokeh): address review feedback for dendrogram-basic Attempt 3/3 - fixes based on AI review --- .../dendrogram-basic/implementations/bokeh.py | 93 ++++++++++++------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/plots/dendrogram-basic/implementations/bokeh.py b/plots/dendrogram-basic/implementations/bokeh.py index df58d47324..0cfd472dfe 100644 --- a/plots/dendrogram-basic/implementations/bokeh.py +++ b/plots/dendrogram-basic/implementations/bokeh.py @@ -1,4 +1,4 @@ -""" pyplots.ai +"""pyplots.ai dendrogram-basic: Basic Dendrogram Library: bokeh 3.8.2 | Python 3.14.3 Quality: 85/100 | Updated: 2026-04-05 @@ -6,7 +6,7 @@ import numpy as np from bokeh.io import export_png -from bokeh.models import ColumnDataSource, HoverTool, Label +from bokeh.models import ColumnDataSource, FixedTicker, HoverTool, Label, Span from bokeh.plotting import figure, output_file, save from scipy.cluster.hierarchy import leaves_list, linkage @@ -81,7 +81,7 @@ # Colorblind-safe palette colors_within = "#0F7B6C" # teal for within-cluster -colors_between = "#444444" # dark gray for between-cluster (cross-species merges) +colors_between = "#C0392B" # warm red for between-cluster (cross-species merges) # Collect line segments with hover metadata all_xs, all_ys = [], [] @@ -133,12 +133,13 @@ p = figure( width=4800, height=2700, - title="Iris Species Clustering \u00b7 dendrogram-basic \u00b7 bokeh \u00b7 pyplots.ai", + title="dendrogram-basic \u00b7 bokeh \u00b7 pyplots.ai", x_axis_label="Iris Sample", y_axis_label="Distance (Ward\u2019s Method, \u221a scale)", x_range=(-0.8, n_samples - 0.2), - y_range=(-sqrt_max * 0.16, sqrt_max * 1.08), + y_range=(-sqrt_max * 0.02, sqrt_max * 1.12), toolbar_location=None, + min_border_bottom=220, ) # Draw dendrogram branches using multi_line with ColumnDataSource and hover data @@ -179,24 +180,38 @@ ) p.add_tools(hover) -# Legend entries via invisible scatter points -p.scatter([], [], color=colors_within, legend_label="Within-cluster", size=0) -p.scatter([], [], color=colors_between, legend_label="Between-cluster", size=0) - -# Leaf labels -for idx, label in enumerate(ordered_labels): - label_obj = Label( - x=idx, - y=-sqrt_max * 0.02, - text=label, - text_font_size="20pt", - text_color="#444444", - text_align="right", - angle=0.785, - angle_units="rad", - y_offset=-15, - ) - p.add_layout(label_obj) +# Cluster threshold line for visual storytelling +threshold_y_scaled = np.sqrt(color_threshold) +threshold_line = Span( + location=threshold_y_scaled, + dimension="width", + line_color="#999999", + line_dash="dashed", + line_width=2, + line_alpha=0.5, +) +p.add_layout(threshold_line) + +threshold_label = Label( + x=n_samples - 1.2, + y=threshold_y_scaled, + text="cluster threshold", + text_font_size="16pt", + text_color="#888888", + text_font_style="italic", + y_offset=8, + text_align="right", +) +p.add_layout(threshold_label) + +# Legend entries via off-screen line glyphs for colored swatches +p.line([-99, -98], [-99, -99], line_color=colors_within, line_width=6, legend_label="Within-cluster") +p.line([-99, -98], [-99, -99], line_color=colors_between, line_width=6, legend_label="Between-cluster") + +# Leaf labels as x-axis tick labels (renders outside plot frame, no clipping) +p.xaxis.ticker = FixedTicker(ticks=list(range(n_samples))) +p.xaxis.major_label_overrides = {i: ordered_labels[i] for i in range(n_samples)} +p.xaxis.major_label_orientation = 0.785 # 45 degrees in radians # Style p.title.text_font_size = "30pt" @@ -206,13 +221,17 @@ p.yaxis.axis_label_text_font_size = "24pt" p.xaxis.axis_label_text_color = "#555555" p.yaxis.axis_label_text_color = "#555555" -p.xaxis.major_label_text_font_size = "0pt" +p.xaxis.major_label_text_font_size = "18pt" +p.xaxis.major_label_text_color = "#444444" p.yaxis.major_label_text_font_size = "20pt" p.yaxis.major_label_text_color = "#666666" +p.background_fill_color = "#FAFAFA" +p.border_fill_color = "white" p.xgrid.visible = False -p.ygrid.grid_line_alpha = 0.15 -p.ygrid.grid_line_dash = [1, 0] +p.ygrid.grid_line_alpha = 0.12 +p.ygrid.grid_line_dash = [4, 4] +p.ygrid.grid_line_color = "#AAAAAA" p.xaxis.axis_line_color = "#CCCCCC" p.yaxis.axis_line_color = "#CCCCCC" @@ -223,16 +242,18 @@ p.outline_line_color = None # Legend -p.legend.location = "top_right" -p.legend.label_text_font_size = "18pt" -p.legend.label_text_color = "#444444" -p.legend.glyph_width = 40 -p.legend.glyph_height = 6 -p.legend.spacing = 8 -p.legend.padding = 15 -p.legend.background_fill_alpha = 0.9 -p.legend.border_line_color = "#DDDDDD" -p.legend.border_line_alpha = 0.5 +p.legend.location = "top_left" +p.legend.label_text_font_size = "22pt" +p.legend.label_text_color = "#333333" +p.legend.glyph_width = 50 +p.legend.glyph_height = 8 +p.legend.spacing = 12 +p.legend.padding = 20 +p.legend.margin = 15 +p.legend.background_fill_alpha = 0.92 +p.legend.background_fill_color = "#FAFAFA" +p.legend.border_line_color = "#CCCCCC" +p.legend.border_line_alpha = 0.6 # Save export_png(p, filename="plot.png") From 1b0b84c8f15b3b1d63077c95eebc3b40739deeca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 21:15:38 +0000 Subject: [PATCH 7/7] chore(bokeh): update quality score 90 and review feedback for dendrogram-basic --- .../dendrogram-basic/implementations/bokeh.py | 4 +- plots/dendrogram-basic/metadata/bokeh.yaml | 123 +++++++++--------- 2 files changed, 61 insertions(+), 66 deletions(-) diff --git a/plots/dendrogram-basic/implementations/bokeh.py b/plots/dendrogram-basic/implementations/bokeh.py index 0cfd472dfe..764c607ba3 100644 --- a/plots/dendrogram-basic/implementations/bokeh.py +++ b/plots/dendrogram-basic/implementations/bokeh.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai dendrogram-basic: Basic Dendrogram Library: bokeh 3.8.2 | Python 3.14.3 -Quality: 85/100 | Updated: 2026-04-05 +Quality: 90/100 | Updated: 2026-04-05 """ import numpy as np diff --git a/plots/dendrogram-basic/metadata/bokeh.yaml b/plots/dendrogram-basic/metadata/bokeh.yaml index fe47818ce4..6e443ed524 100644 --- a/plots/dendrogram-basic/metadata/bokeh.yaml +++ b/plots/dendrogram-basic/metadata/bokeh.yaml @@ -1,7 +1,7 @@ library: bokeh specification_id: dendrogram-basic created: '2025-12-23T10:01:43Z' -updated: '2026-04-05T21:02:41Z' +updated: '2026-04-05T21:15:38Z' generated_by: claude-opus-4-6 workflow_run: 20457532402 issue: 0 @@ -9,12 +9,13 @@ python_version: 3.14.3 library_version: 3.8.2 preview_url: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.png preview_html: https://storage.googleapis.com/pyplots-images/plots/dendrogram-basic/bokeh/plot.html -quality_score: 85 +quality_score: 90 impl_tags: dependencies: - scipy techniques: - hover-tooltips + - manual-ticks - custom-legend - html-export patterns: @@ -28,102 +29,96 @@ impl_tags: - alpha-blending review: strengths: - - Excellent use of Bokeh HoverTool with merge distance, cluster members, and cluster - size metadata - - Clean manual dendrogram construction necessary for Bokeh which lacks built-in - dendrogram - - Colorblind-safe teal/gray palette with good contrast - - Sqrt scaling improves visibility of lower-distance merges - - Realistic iris dataset with clear species clustering - - All font sizes explicitly set for 4800x2700 canvas + - Excellent manual dendrogram construction with proper U-shaped connectors and leaf + ordering + - Interactive HoverTool showing merge distance, cluster size, and member names on + each branch + - Semantic color coding (within vs between-cluster) with threshold line tells a + clear clustering story + - Sqrt scaling on y-axis improves visibility of lower-level merges + - Dual output (PNG + HTML) leverages Bokeh interactive strengths weaknesses: - - Title format prepends descriptive text before the standard spec-id format - - Between-cluster color (#444444) is subtle against background — needs stronger - contrast - - Legend is small and positioned far from data in top-right corner - - Negative y-range creates unnecessary whitespace below leaf labels - image_description: The plot displays a hierarchical dendrogram of 15 iris flower - samples clustered using Ward's method. The x-axis shows sample labels (Setosa-1 - through -5, Versicolor-1 through -5, Virginica-1 through -5) rotated at approximately - 45 degrees. The y-axis shows "Distance (Ward's Method, √ scale)" with sqrt-transformed - values ranging from -0.5 to ~3.3. U-shaped connectors form the tree structure - with teal-colored branches for within-cluster merges and dark gray for the top-level - between-cluster merge. A legend in the top-right corner labels "Within-cluster" - and "Between-cluster". The title reads "Iris Species Clustering · dendrogram-basic - · bokeh · pyplots.ai". The Setosa samples cluster together on the left, Versicolor - in the middle, and Virginica on the right, with Versicolor and Virginica merging - before joining Setosa at the highest distance level. Grid lines are subtle (y-axis - only), the outline is removed, and the overall appearance is clean and professional. + - Axis lines still visible; removing them would further refine visual appearance + - Branch line_width could be slightly increased for finest merges on 4800px canvas + image_description: 'The plot displays a vertical dendrogram of 15 iris flower samples + (5 each of Setosa, Versicolor, Virginica) using Ward''s method with sqrt-scaled + y-axis. X-axis labels are rotated ~45 degrees showing sample names (e.g., "Setosa-4", + "Versicolor-1", "Virginica-3"). Teal (#0F7B6C) lines represent within-cluster + merges and warm red (#C0392B) lines represent between-cluster merges. A dashed + horizontal line labeled "cluster threshold" separates the two color regimes. The + hierarchical structure clearly shows three species clusters: Setosa on the left, + Versicolor in the middle, and Virginica on the right, with the final cross-species + merge at the top in red. Legend in top-left shows "Within-cluster" and "Between-cluster" + with a clean bordered background. The background is light gray (#FAFAFA), y-grid + is subtle dashed lines, x-grid is hidden, and the outline is removed.' criteria_checklist: visual_quality: - score: 27 + score: 29 max: 30 items: - id: VQ-01 name: Text Legibility - score: 7 + score: 8 max: 8 passed: true - comment: All font sizes explicitly set (title 30pt, labels 24pt, ticks 20pt, - leaf labels 20pt). Legend text slightly small. + comment: 'All font sizes explicitly set: title 30pt, axis labels 24pt, x-ticks + 18pt, y-ticks 20pt, legend 22pt' - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: Labels rotated at 45 degrees prevent all overlap + comment: X-axis labels rotated 45 degrees with generous min_border_bottom, + no collisions - id: VQ-03 name: Element Visibility score: 5 max: 6 passed: true - comment: Branch lines visible at width 4. Between-cluster color distinction - is subtle. + comment: Lines at line_width=4 are good but could be slightly thicker for + finest branches - id: VQ-04 name: Color Accessibility score: 4 max: 4 passed: true - comment: Teal and dark gray are colorblind-safe with good contrast + comment: Teal vs warm red is colorblind-safe - id: VQ-05 name: Layout & Canvas - score: 3 + score: 4 max: 4 passed: true - comment: Good canvas usage but negative y-range creates unnecessary whitespace + comment: Plot fills canvas well, balanced margins - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Descriptive labels with method and scale info + comment: Descriptive labels with method context design_excellence: - score: 12 + score: 14 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 5 + score: 6 max: 8 passed: true - comment: Custom teal/gray palette, muted text colors, outline removed. Above - configured default. + comment: Intentional color palette, custom typography, professional polish - id: DE-02 name: Visual Refinement score: 4 max: 6 passed: true - comment: Outline removed, x-grid hidden, y-grid subtle, tick marks customized, - axis lines styled + comment: X-grid hidden, y-grid subtle, outline removed, selective tick styling - id: DE-03 name: Data Storytelling - score: 3 + score: 4 max: 6 passed: true - comment: Color coding distinguishes within/between-cluster merges. Sqrt scaling - improves lower-distance visibility. + comment: Color coding within vs between-cluster, threshold line, sqrt scaling spec_compliance: - score: 14 + score: 15 max: 15 items: - id: SC-01 @@ -131,26 +126,26 @@ review: score: 5 max: 5 passed: true - comment: Correct dendrogram with U-shaped connectors + comment: Correct dendrogram with hierarchical tree structure - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Labels, linkage, proportional heights, vertical orientation all present + comment: Ward's method, proportional branch heights, vertical orientation, + sample labels - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X shows samples in leaf order, Y shows merge distances + comment: X-axis shows samples in leaf order, Y-axis shows merge distances - id: SC-04 name: Title & Legend - score: 2 + score: 3 max: 3 passed: true - comment: Title has extra descriptive prefix before standard format. Legend - labels match. + comment: Correct title format and legend labels data_quality: score: 14 max: 15 @@ -160,20 +155,20 @@ review: score: 5 max: 6 passed: true - comment: Shows species clustering, varying merge distances, tight and loose - clusters + comment: Three distinct clusters with varying merge distances, within and + between-cluster merges - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Iris dataset is a classic neutral real-world clustering scenario + comment: Iris flower measurements - classic, neutral scientific dataset - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Realistic iris flower measurements in cm range + comment: Realistic iris measurement ranges code_quality: score: 10 max: 10 @@ -183,7 +178,7 @@ review: score: 3 max: 3 passed: true - comment: 'Linear flow: imports, data, clustering, plotting, save' + comment: 'Linear flow: imports, data, computation, plotting, save' - id: CQ-02 name: Reproducibility score: 2 @@ -201,13 +196,13 @@ review: score: 2 max: 2 passed: true - comment: Clean manual dendrogram construction, well-organized + comment: Clean manual dendrogram construction, appropriate complexity - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png and plot.html, current API + comment: Saves as plot.png via export_png, also HTML library_mastery: score: 8 max: 10 @@ -217,11 +212,11 @@ review: score: 4 max: 5 passed: true - comment: ColumnDataSource, multi_line, Label objects, proper figure configuration + comment: Uses ColumnDataSource, multi_line, HoverTool, Span, Label, FixedTicker - id: LM-02 name: Distinctive Features score: 4 max: 5 passed: true - comment: HoverTool with custom tooltips, hover visual feedback, HTML export - verdict: REJECTED + comment: HoverTool with branch tooltips, hover visual feedback, HTML export + verdict: APPROVED