Skip to content

Commit e000ada

Browse files
author
Andrija Kolic
committed
Add the benchmark files as-is from the issue description.
1 parent 8107d5a commit e000ada

8 files changed

Lines changed: 554 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env python3
2+
"""
3+
3D plotting example: surface, wireframe, and contour projections.
4+
Saves to PDF.
5+
6+
Run:
7+
python tst/3d_surface_wireframe.py
8+
"""
9+
10+
from pathlib import Path
11+
12+
# Use a non-interactive backend to work in headless environments
13+
import matplotlib
14+
matplotlib.use("Agg")
15+
16+
import matplotlib.pyplot as plt
17+
import numpy as np
18+
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 # needed for 3D projection
19+
20+
21+
def main() -> None:
22+
out_path = Path(__file__).parent / "surface_3d.pdf"
23+
24+
# Domain and function
25+
x = np.linspace(-4, 4, 200)
26+
y = np.linspace(-4, 4, 200)
27+
X, Y = np.meshgrid(x, y)
28+
29+
R = np.sqrt(X**2 + Y**2) + 1e-12
30+
Z = np.sin(R) / R + 0.15 * np.cos(3*X) * np.sin(3*Y) / (1 + 0.5 * (X**2 + Y**2))
31+
32+
fig = plt.figure(figsize=(7.5, 5.8), dpi=150)
33+
ax = fig.add_subplot(111, projection="3d")
34+
35+
# Surface with colormap
36+
surf = ax.plot_surface(X, Y, Z, cmap="viridis", linewidth=0, antialiased=True, alpha=0.95)
37+
38+
# Wireframe overlay (sparser grid to avoid clutter)
39+
step = 10
40+
ax.plot_wireframe(X[::step, ::step], Y[::step, ::step], Z[::step, ::step],
41+
rstride=1, cstride=1, color="k", linewidth=0.3, alpha=0.5)
42+
43+
# Contour projections on Z, X, and Y planes
44+
z_offset = Z.min() - 0.4
45+
ax.contour(X, Y, Z, zdir="z", offset=z_offset, cmap="viridis", levels=18, linewidths=0.8)
46+
47+
x_offset = x.min() - 0.6
48+
ax.contour(X, Y, Z, zdir="x", offset=x_offset, cmap="magma", levels=14, linewidths=0.7)
49+
50+
y_offset = y.max() + 0.6
51+
ax.contour(X, Y, Z, zdir="y", offset=y_offset, cmap="plasma", levels=14, linewidths=0.7)
52+
53+
# Axes labels and limits
54+
ax.set_xlabel("X")
55+
ax.set_ylabel("Y")
56+
ax.set_zlabel("Z")
57+
58+
ax.set_xlim(x_offset, x.max())
59+
ax.set_ylim(y.min(), y_offset)
60+
ax.set_zlim(z_offset, Z.max())
61+
62+
# Colorbar
63+
cb = fig.colorbar(surf, ax=ax, shrink=0.6, aspect=12, pad=0.08)
64+
cb.set_label("Z value")
65+
66+
# View angle
67+
ax.view_init(elev=25, azim=-55)
68+
69+
ax.set_title("3D Surface + Wireframe + Contour Projections")
70+
fig.tight_layout()
71+
72+
fig.savefig(out_path, format="pdf")
73+
plt.close(fig)
74+
75+
print(f"Wrote PDF: {out_path.resolve()}")
76+
77+
78+
if __name__ == "__main__":
79+
main()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[[rule]]
2+
files = "*"
3+
any = [
4+
"francois.farquet@oracle.com",
5+
"andrija.kolic@oracle.com",
6+
]
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Categorical plots: grouped bar chart with error bars and a boxplot.
4+
Saves a multi-page PDF using PdfPages.
5+
6+
Run:
7+
python tst/categorical_bar_and_box.py
8+
"""
9+
10+
from pathlib import Path
11+
12+
# Use a non-interactive backend to work in headless environments
13+
import matplotlib
14+
matplotlib.use("Agg")
15+
16+
import matplotlib.pyplot as plt
17+
import numpy as np
18+
from matplotlib.backends.backend_pdf import PdfPages
19+
20+
21+
def _colorize_boxplot(bp, facecolor="#1f77b4", edgecolor="black", alpha=0.6):
22+
for box in bp["boxes"]:
23+
box.set(facecolor=facecolor, edgecolor=edgecolor, alpha=alpha)
24+
for median in bp["medians"]:
25+
median.set(color="black", linewidth=1.2)
26+
for whisker in bp["whiskers"]:
27+
whisker.set(color=edgecolor, linewidth=1.0)
28+
for cap in bp["caps"]:
29+
cap.set(color=edgecolor, linewidth=1.0)
30+
for flier in bp["fliers"]:
31+
flier.set(marker="o", markersize=3, markerfacecolor="white", markeredgecolor=edgecolor, alpha=0.7)
32+
33+
34+
def main() -> None:
35+
out_path = Path(__file__).parent / "categorical_plots.pdf"
36+
37+
rng = np.random.default_rng(2024)
38+
categories = ["A", "B", "C", "D"]
39+
n = len(categories)
40+
41+
with PdfPages(out_path) as pdf:
42+
# Page 1: Grouped bar chart with error bars
43+
x = np.arange(n)
44+
bar_w = 0.35
45+
46+
means1 = rng.normal(3.0, 0.4, n)
47+
errs1 = rng.uniform(0.1, 0.4, n)
48+
49+
means2 = rng.normal(2.2, 0.5, n)
50+
errs2 = rng.uniform(0.1, 0.4, n)
51+
52+
fig1, ax1 = plt.subplots(figsize=(7, 4), dpi=150)
53+
b1 = ax1.bar(x - bar_w / 2, means1, yerr=errs1, width=bar_w, capsize=3,
54+
label="Series 1", color="#1f77b4", edgecolor="black", alpha=0.85)
55+
b2 = ax1.bar(x + bar_w / 2, means2, yerr=errs2, width=bar_w, capsize=3,
56+
label="Series 2", color="#ff7f0e", edgecolor="black", alpha=0.85)
57+
58+
ax1.set_xticks(x, categories)
59+
ax1.set_ylabel("Value")
60+
ax1.set_title("Grouped Bar Chart with Error Bars")
61+
ax1.grid(axis="y", linestyle="--", alpha=0.35)
62+
ax1.legend(loc="best")
63+
64+
# Annotate bars with heights
65+
for bars in (b1, b2):
66+
for rect in bars:
67+
h = rect.get_height()
68+
ax1.text(rect.get_x() + rect.get_width() / 2.0, h + 0.05,
69+
f"{h:.2f}", ha="center", va="bottom", fontsize=8, rotation=0)
70+
71+
fig1.tight_layout()
72+
pdf.savefig(fig1)
73+
plt.close(fig1)
74+
75+
# Page 2: Boxplot across categories
76+
# Generate some synthetic distributions with varying mean/variance
77+
mus = [2.8, 3.2, 2.5, 3.5]
78+
sigmas = [0.50, 0.60, 0.45, 0.55]
79+
data = [rng.normal(loc=m, scale=s, size=400) for m, s in zip(mus, sigmas)]
80+
81+
fig2, ax2 = plt.subplots(figsize=(7, 4), dpi=150)
82+
bp = ax2.boxplot(
83+
data,
84+
tick_labels=categories,
85+
widths=0.6,
86+
patch_artist=True,
87+
showfliers=True,
88+
whis=(5, 95),
89+
)
90+
# Colorize boxes with a palette
91+
palette = ["#1f77b4", "#ff7f0e", "#2ca02c", "#9467bd"]
92+
for box, color in zip(bp["boxes"], palette):
93+
box.set(facecolor=color, edgecolor="black", alpha=0.6)
94+
95+
# Style the rest
96+
for median in bp["medians"]:
97+
median.set(color="black", linewidth=1.4)
98+
for whisker in bp["whiskers"]:
99+
whisker.set(color="black", linewidth=1.0)
100+
for cap in bp["caps"]:
101+
cap.set(color="black", linewidth=1.0)
102+
for flier in bp["fliers"]:
103+
flier.set(marker="o", markersize=3, markerfacecolor="white", markeredgecolor="black", alpha=0.7)
104+
105+
ax2.set_title("Boxplot by Category")
106+
ax2.set_ylabel("Distribution")
107+
ax2.grid(axis="y", linestyle="--", alpha=0.35)
108+
fig2.tight_layout()
109+
110+
pdf.savefig(fig2)
111+
plt.close(fig2)
112+
113+
print(f"Wrote PDF: {out_path.resolve()}")
114+
115+
116+
if __name__ == "__main__":
117+
main()
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Distribution plots: 1D histogram, 2D histogram, and hexbin with colorbars.
4+
5+
Run:
6+
python tst/distributions_hist_2d.py
7+
"""
8+
9+
from pathlib import Path
10+
11+
# Use a non-interactive backend to work in headless environments
12+
import matplotlib
13+
matplotlib.use("Agg")
14+
15+
import matplotlib.pyplot as plt
16+
import numpy as np
17+
18+
19+
def main() -> None:
20+
out_path = Path(__file__).parent / "distributions_2d.pdf"
21+
22+
rng = np.random.default_rng(7)
23+
n = 6000
24+
25+
# Create two correlated variables
26+
x = rng.normal(0.0, 1.0, n)
27+
y = 0.65 * x + rng.normal(0.0, 0.8, n)
28+
29+
fig, axs = plt.subplots(1, 3, figsize=(12, 4), dpi=150)
30+
31+
# 1) 1D histograms overlayed
32+
ax = axs[0]
33+
ax.hist(x, bins=40, alpha=0.8, label="x", color="#1f77b4", edgecolor="white")
34+
ax.hist(y, bins=40, alpha=0.6, label="y", color="#ff7f0e", edgecolor="white")
35+
ax.set_title("1D Histograms")
36+
ax.set_xlabel("Value")
37+
ax.set_ylabel("Frequency")
38+
ax.grid(True, linestyle="--", alpha=0.3)
39+
ax.legend(loc="best")
40+
41+
# 2) 2D histogram via pcolormesh
42+
ax = axs[1]
43+
H, xedges, yedges = np.histogram2d(x, y, bins=60)
44+
X, Y = np.meshgrid(xedges, yedges)
45+
pcm = ax.pcolormesh(X, Y, H.T, cmap="viridis", shading="auto")
46+
ax.set_title("2D Histogram")
47+
ax.set_xlabel("x")
48+
ax.set_ylabel("y")
49+
cb = fig.colorbar(pcm, ax=ax)
50+
cb.set_label("Count")
51+
ax.grid(False)
52+
53+
# 3) Hexbin with log color scale
54+
ax = axs[2]
55+
hb = ax.hexbin(x, y, gridsize=45, cmap="plasma", mincnt=1, bins="log")
56+
ax.set_title("Hexbin (log density)")
57+
ax.set_xlabel("x")
58+
ax.set_ylabel("y")
59+
cb = fig.colorbar(hb, ax=ax)
60+
cb.set_label("log10(count)")
61+
ax.grid(False)
62+
63+
fig.suptitle("Distributions: 1D and 2D Density", fontsize=14)
64+
fig.tight_layout(rect=[0, 0.03, 1, 0.95])
65+
66+
fig.savefig(out_path, format="pdf")
67+
plt.close(fig)
68+
69+
print(f"Wrote PDF: {out_path.resolve()}")
70+
71+
72+
if __name__ == "__main__":
73+
main()
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Vector and polar plots: polar plot, quiver, and streamplot on separate pages.
4+
Saves a multi-page PDF using PdfPages.
5+
6+
Run:
7+
python tst/polar_quiver_stream.py
8+
"""
9+
10+
from pathlib import Path
11+
12+
# Use a non-interactive backend to work in headless environments
13+
import matplotlib
14+
matplotlib.use("Agg")
15+
16+
import matplotlib.pyplot as plt
17+
import numpy as np
18+
from matplotlib.backends.backend_pdf import PdfPages
19+
20+
21+
def page_polar(ax):
22+
# Polar demo with multiple radii and an area fill
23+
theta = np.linspace(0, 2*np.pi, 512)
24+
r1 = 1.0 + 0.3*np.sin(5*theta)
25+
r2 = 0.7 + 0.2*np.cos(3*theta + 0.5)
26+
27+
ax.plot(theta, r1, color="#1f77b4", linewidth=2.0, label="r1(θ) = 1 + 0.3 sin(5θ)")
28+
ax.plot(theta, r2, color="#ff7f0e", linewidth=2.0, linestyle="--", label="r2(θ) = 0.7 + 0.2 cos(3θ+0.5)")
29+
ax.fill_between(theta, r2, color="#ff7f0e", alpha=0.25, step="mid")
30+
ax.set_theta_zero_location("N")
31+
ax.set_theta_direction(-1)
32+
ax.set_title("Polar Plot", va="bottom")
33+
ax.grid(True, alpha=0.4)
34+
ax.legend(loc="upper right", bbox_to_anchor=(1.25, 1.15), frameon=False)
35+
36+
37+
def page_quiver(ax):
38+
# Quiver plot for a simple rotational vector field
39+
n = 25
40+
x = np.linspace(-2.0, 2.0, n)
41+
y = np.linspace(-2.0, 2.0, n)
42+
X, Y = np.meshgrid(x, y)
43+
44+
# Vector field: rotation around origin
45+
U = -Y
46+
V = X
47+
speed = np.hypot(U, V)
48+
49+
q = ax.quiver(X, Y, U, V, speed, cmap="viridis", pivot="mid", angles="xy", scale=35, width=0.006)
50+
ax.set_aspect("equal", adjustable="box")
51+
ax.set_title("Quiver: Rotational Field")
52+
ax.set_xlabel("x")
53+
ax.set_ylabel("y")
54+
cb = ax.figure.colorbar(q, ax=ax, pad=0.01)
55+
cb.set_label("|v|")
56+
ax.grid(True, linestyle="--", alpha=0.3)
57+
58+
59+
def page_streamplot(ax):
60+
# Streamplot with linewidth and color mapped to speed
61+
x = np.linspace(-3.0, 3.0, 200)
62+
y = np.linspace(-3.0, 3.0, 200)
63+
X, Y = np.meshgrid(x, y)
64+
65+
# Double-vortex-like field
66+
U = 1 - (X**2) + (Y**2)
67+
V = -2*X*Y
68+
speed = np.sqrt(U**2 + V**2)
69+
70+
lw = 1.5 * speed / (speed.max() + 1e-12)
71+
strm = ax.streamplot(X, Y, U, V, color=speed, linewidth=lw, cmap="plasma", density=1.4, arrowsize=1.2)
72+
ax.set_aspect("equal", adjustable="box")
73+
ax.set_title("Streamplot: Speed-coded")
74+
ax.set_xlabel("x")
75+
ax.set_ylabel("y")
76+
cb = ax.figure.colorbar(strm.lines, ax=ax, pad=0.01)
77+
cb.set_label("|v|")
78+
ax.grid(True, linestyle="--", alpha=0.25)
79+
80+
81+
def main() -> None:
82+
out_path = Path(__file__).parent / "vector_and_polar.pdf"
83+
84+
with PdfPages(out_path) as pdf:
85+
# Page 1: Polar
86+
fig1 = plt.figure(figsize=(6.2, 5.5), dpi=150)
87+
ax1 = fig1.add_subplot(111, projection="polar")
88+
page_polar(ax1)
89+
fig1.tight_layout()
90+
pdf.savefig(fig1)
91+
plt.close(fig1)
92+
93+
# Page 2: Quiver
94+
fig2, ax2 = plt.subplots(figsize=(6.2, 5.0), dpi=150)
95+
page_quiver(ax2)
96+
fig2.tight_layout()
97+
pdf.savefig(fig2)
98+
plt.close(fig2)
99+
100+
# Page 3: Streamplot
101+
fig3, ax3 = plt.subplots(figsize=(6.6, 5.2), dpi=150)
102+
page_streamplot(ax3)
103+
fig3.tight_layout()
104+
pdf.savefig(fig3)
105+
plt.close(fig3)
106+
107+
print(f"Wrote PDF: {out_path.resolve()}")
108+
109+
110+
if __name__ == "__main__":
111+
main()

0 commit comments

Comments
 (0)