Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions plots/altair/bar/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
histogram-basic: Basic Histogram
Library: altair
"""

import altair as alt
import numpy as np
import pandas as pd


# Data
np.random.seed(42)
data = pd.DataFrame({"value": np.random.normal(100, 15, 500)})

# Create histogram chart
chart = (
alt.Chart(data)
.mark_bar(color="#306998", opacity=0.8)
.encode(alt.X("value:Q", bin=alt.Bin(maxbins=30), title="Value"), alt.Y("count()", title="Frequency"))
.properties(width=1600, height=900, title="Basic Histogram")
.configure_axis(labelFontSize=16, titleFontSize=20)
.configure_title(fontSize=20)
)

# Save as PNG (1600 × 900 at scale 3 = 4800 × 2700)
chart.save("plot.png", scale_factor=3.0)
51 changes: 51 additions & 0 deletions plots/bokeh/quad/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
histogram-basic: Basic Histogram
Library: bokeh
"""

import numpy as np
from bokeh.io import export_png
from bokeh.plotting import figure


# Data - 500 normally distributed values (mean=100, std=15)
np.random.seed(42)
values = np.random.normal(100, 15, 500)

# Compute histogram bins
hist, edges = np.histogram(values, bins=30)

# Create figure (4800 x 2700 px for high resolution)
p = figure(width=4800, height=2700, title="Basic Histogram", x_axis_label="Value", y_axis_label="Frequency")

# Draw histogram using quad glyph
p.quad(
top=hist,
bottom=0,
left=edges[:-1],
right=edges[1:],
fill_color="#306998",
fill_alpha=0.7,
line_color="white",
line_width=1,
)

# Style title
p.title.text_font_size = "20pt"
p.title.align = "center"

# Style axis labels
p.xaxis.axis_label_text_font_size = "20pt"
p.yaxis.axis_label_text_font_size = "20pt"
p.xaxis.major_label_text_font_size = "16pt"
p.yaxis.major_label_text_font_size = "16pt"

# Style grid - subtle
p.xgrid.grid_line_alpha = 0.3
p.ygrid.grid_line_alpha = 0.3

# Ensure y-axis starts at zero
p.y_range.start = 0

# Save output
export_png(p, filename="plot.png")
124 changes: 124 additions & 0 deletions plots/highcharts/histogram/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
"""
histogram-basic: Basic Histogram
Library: highcharts
"""

import tempfile
import time
import urllib.request
from pathlib import Path

import numpy as np
from highcharts_core.chart import Chart
from highcharts_core.options import HighchartsOptions
from highcharts_core.options.series.bar import ColumnSeries
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


# Data
np.random.seed(42)
values = np.random.normal(100, 15, 500) # 500 values, mean=100, std=15

# Calculate histogram bins
bins = 30
counts, bin_edges = np.histogram(values, bins=bins)

# Create bin labels (center of each bin)
bin_centers = [(bin_edges[i] + bin_edges[i + 1]) / 2 for i in range(len(counts))]
bin_labels = [f"{bin_edges[i]:.1f}-{bin_edges[i + 1]:.1f}" for i in range(len(counts))]

# Create chart with container ID
chart = Chart(container="container")
chart.options = HighchartsOptions()

# Chart configuration
chart.options.chart = {
"type": "column",
"width": 4800,
"height": 2700,
"backgroundColor": "#ffffff",
"spacingBottom": 120, # Add space for x-axis title
}

# Title
chart.options.title = {"text": "Basic Histogram", "style": {"fontSize": "48px", "fontWeight": "bold"}}

# X-axis configuration
chart.options.x_axis = {
"categories": bin_labels,
"title": {"text": "Value", "style": {"fontSize": "40px"}},
"labels": {
"rotation": 315, # 315 degrees = -45 degrees
"style": {"fontSize": "28px"},
"step": 3, # Show every 3rd label to avoid overlap
},
}

# Y-axis configuration
chart.options.y_axis = {
"title": {"text": "Frequency", "style": {"fontSize": "40px"}},
"min": 0,
"gridLineWidth": 1,
"gridLineDashStyle": "Dot",
"gridLineColor": "rgba(0, 0, 0, 0.15)",
"labels": {"style": {"fontSize": "32px"}},
}

# Create series with histogram data
series = ColumnSeries()
series.data = counts.tolist()
series.name = "Frequency"
series.color = "#306998" # Python Blue
series.border_color = "white"
series.border_width = 1

# Plot options for histogram appearance
chart.options.plot_options = {"column": {"pointPadding": 0, "groupPadding": 0, "borderWidth": 1, "opacity": 0.8}}

chart.add_series(series)

# Legend (single series, hide)
chart.options.legend = {"enabled": False}

# Credits
chart.options.credits = {"enabled": False}

# Download Highcharts JS (required for headless Chrome)
highcharts_url = "https://code.highcharts.com/highcharts.js"
with urllib.request.urlopen(highcharts_url, timeout=30) as response:
highcharts_js = response.read().decode("utf-8")

# Generate HTML with inline scripts
html_str = chart.to_js_literal()
html_content = f"""<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>{highcharts_js}</script>
</head>
<body style="margin:0;">
<div id="container" style="width: 4800px; height: 2700px;"></div>
<script>{html_str}</script>
</body>
</html>"""

# Write temp HTML and take screenshot
with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f:
f.write(html_content)
temp_path = f.name

chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--window-size=4800,2800") # Slightly larger to capture full chart

driver = webdriver.Chrome(options=chrome_options)
driver.get(f"file://{temp_path}")
time.sleep(5) # Wait for chart to render
driver.save_screenshot("plot.png")
driver.quit()

Path(temp_path).unlink() # Clean up temp file
28 changes: 28 additions & 0 deletions plots/letsplot/histogram/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
histogram-basic: Basic Histogram
Library: letsplot
"""

import numpy as np
import pandas as pd
from lets_plot import LetsPlot, aes, element_text, geom_histogram, ggplot, ggsave, ggsize, labs, theme, theme_minimal


LetsPlot.setup_html()

# Data
np.random.seed(42)
data = pd.DataFrame({"value": np.random.normal(100, 15, 500)})

# Plot
plot = (
ggplot(data, aes(x="value"))
+ geom_histogram(bins=30, fill="#306998", color="white", alpha=0.8)
+ labs(x="Value", y="Frequency", title="Basic Histogram")
+ theme_minimal()
+ theme(plot_title=element_text(size=20), axis_title=element_text(size=20), axis_text=element_text(size=16))
+ ggsize(1600, 900)
)

# Save - scale 3x to get 4800 x 2700 px
ggsave(plot, "plot.png", path=".", scale=3)
27 changes: 27 additions & 0 deletions plots/matplotlib/hist/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
histogram-basic: Basic Histogram
Library: matplotlib
"""

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


# Data
np.random.seed(42)
data = pd.DataFrame({"value": np.random.normal(100, 15, 500)})

# Create plot
fig, ax = plt.subplots(figsize=(16, 9))
ax.hist(data["value"], bins=30, alpha=0.8, color="#306998", edgecolor="white", linewidth=0.5)

# Labels and styling
ax.set_xlabel("Value", fontsize=20)
ax.set_ylabel("Frequency", fontsize=20)
ax.set_title("Basic Histogram", fontsize=20)
ax.tick_params(axis="both", labelsize=16)
ax.grid(True, alpha=0.3, axis="y")

plt.tight_layout()
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
31 changes: 31 additions & 0 deletions plots/plotly/histogram/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""
histogram-basic: Basic Histogram
Library: plotly
"""

import numpy as np
import plotly.graph_objects as go


# Data
np.random.seed(42)
values = np.random.normal(100, 15, 500) # 500 values, mean=100, std=15

# Create figure
fig = go.Figure()
fig.add_trace(go.Histogram(x=values, marker={"color": "#306998", "line": {"color": "white", "width": 1}}, opacity=0.85))
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

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

The histogram should specify the number of bins to match the spec and other library implementations. All other implementations use 30 bins explicitly. Add nbins=30 parameter to the go.Histogram constructor.

Suggested fix:

fig.add_trace(go.Histogram(x=values, nbins=30, marker={"color": "#306998", "line": {"color": "white", "width": 1}}, opacity=0.85))
Suggested change
fig.add_trace(go.Histogram(x=values, marker={"color": "#306998", "line": {"color": "white", "width": 1}}, opacity=0.85))
fig.add_trace(go.Histogram(x=values, nbins=30, marker={"color": "#306998", "line": {"color": "white", "width": 1}}, opacity=0.85))

Copilot uses AI. Check for mistakes.

# Layout
fig.update_layout(
title={"text": "Basic Histogram", "font": {"size": 40}, "x": 0.5, "xanchor": "center"},
xaxis_title="Value",
yaxis_title="Frequency",
template="plotly_white",
font={"size": 32},
xaxis={"title_font": {"size": 40}, "tickfont": {"size": 32}, "showgrid": True, "gridcolor": "rgba(0,0,0,0.1)"},
yaxis={"title_font": {"size": 40}, "tickfont": {"size": 32}, "showgrid": True, "gridcolor": "rgba(0,0,0,0.1)"},
bargap=0.05,
)

# Save
fig.write_image("plot.png", width=1600, height=900, scale=3)
30 changes: 30 additions & 0 deletions plots/plotnine/histogram/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
histogram-basic: Basic Histogram
Library: plotnine
"""

import numpy as np
import pandas as pd
from plotnine import aes, element_text, geom_histogram, ggplot, labs, theme, theme_minimal


# Data
np.random.seed(42)
data = pd.DataFrame({"value": np.random.normal(100, 15, 500)})

# Plot
plot = (
ggplot(data, aes(x="value"))
+ geom_histogram(bins=30, fill="#306998", color="white", alpha=0.8)
+ labs(x="Value", y="Frequency", title="Basic Histogram")
+ theme_minimal()
+ theme(
figure_size=(16, 9),
plot_title=element_text(size=20),
axis_title=element_text(size=20),
axis_text=element_text(size=16),
)
)

# Save
plot.save("plot.png", dpi=300)
55 changes: 55 additions & 0 deletions plots/pygal/histogram/histogram-basic/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
histogram-basic: Basic Histogram
Library: pygal
"""

import numpy as np
import pygal
from pygal.style import Style


# Data
np.random.seed(42)
values = np.random.normal(100, 15, 500) # 500 values, mean=100, std=15

# Calculate histogram bins
counts, bin_edges = np.histogram(values, bins=20)
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

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

The number of bins should be 30 to match the spec and other library implementations. Currently using 20 bins.

Change line 16 to:

counts, bin_edges = np.histogram(values, bins=30)
Suggested change
counts, bin_edges = np.histogram(values, bins=20)
counts, bin_edges = np.histogram(values, bins=30)

Copilot uses AI. Check for mistakes.

# Convert to pygal histogram format: (height, start, end)
histogram_data = [(int(count), float(bin_edges[i]), float(bin_edges[i + 1])) for i, count in enumerate(counts)]

# Custom style matching default style guide colors
custom_style = Style(
background="white",
plot_background="white",
foreground="#333333",
foreground_strong="#333333",
foreground_subtle="#666666",
opacity="0.8",
opacity_hover="0.9",
colors=("#306998",), # Python Blue
guide_stroke_color="#cccccc",
major_guide_stroke_color="#cccccc",
title_font_size=48,
label_font_size=36,
major_label_font_size=36,
)

# Create histogram chart
chart = pygal.Histogram(
width=4800,
height=2700,
title="Basic Histogram",
x_title="Value",
y_title="Frequency",
style=custom_style,
show_legend=False,
show_y_guides=True,
show_x_guides=False,
)

# Add histogram data
chart.add("Distribution", histogram_data)

# Save to PNG
chart.render_to_png("plot.png")
Loading
Loading