|
1 | | -""" pyplots.ai |
| 1 | +""" anyplot.ai |
2 | 2 | polar-bar: Polar Bar Chart (Wind Rose) |
3 | | -Library: letsplot 4.8.2 | Python 3.13.11 |
4 | | -Quality: 92/100 | Created: 2025-12-30 |
| 3 | +Library: letsplot 4.9.0 | Python 3.13.13 |
| 4 | +Quality: 92/100 | Updated: 2026-05-13 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | + |
7 | 9 | import numpy as np |
8 | 10 | import pandas as pd |
9 | 11 | from lets_plot import ( |
10 | 12 | LetsPlot, |
11 | 13 | aes, |
12 | 14 | coord_polar, |
13 | 15 | element_line, |
| 16 | + element_rect, |
14 | 17 | element_text, |
15 | 18 | geom_bar, |
16 | 19 | ggplot, |
| 20 | + ggsave, |
17 | 21 | ggsize, |
18 | 22 | labs, |
19 | 23 | scale_fill_manual, |
20 | 24 | scale_y_continuous, |
21 | 25 | theme, |
22 | 26 | theme_minimal, |
23 | 27 | ) |
24 | | -from lets_plot.export import ggsave |
25 | 28 |
|
26 | 29 |
|
27 | 30 | LetsPlot.setup_html() |
28 | 31 |
|
29 | | -# Data - Wind direction frequency data (8 compass directions) |
30 | | -np.random.seed(42) |
31 | | -directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"] |
| 32 | +# Theme-adaptive colors |
| 33 | +THEME = os.getenv("ANYPLOT_THEME", "light") |
| 34 | +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" |
| 35 | +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" |
| 36 | +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
32 | 37 |
|
33 | | -# Generate realistic wind frequency data |
34 | | -frequencies = np.array([15, 8, 12, 5, 10, 18, 22, 14]) |
| 38 | +# Okabe-Ito palette + adaptive neutral for 8 compass directions |
| 39 | +OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9", "#F0E442"] |
| 40 | +NEUTRAL = "#1A1A1A" if THEME == "light" else "#E8E8E0" |
| 41 | +DIRECTION_COLORS = OKABE_ITO + [NEUTRAL] |
35 | 42 |
|
36 | | -# Create DataFrame - direction as categorical factor |
| 43 | +# Data - Monsoon wind pattern (SW-dominant, distinct from westerlies) |
| 44 | +directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"] |
| 45 | +frequencies = np.array([3, 5, 6, 12, 28, 35, 6, 5]) |
| 46 | + |
| 47 | +# Create DataFrame |
37 | 48 | df = pd.DataFrame( |
38 | 49 | {"direction": pd.Categorical(directions, categories=directions, ordered=True), "frequency": frequencies} |
39 | 50 | ) |
40 | 51 |
|
41 | 52 | # Create polar bar chart (wind rose) |
42 | | -# Use coord_polar to wrap bars in a circle |
43 | 53 | plot = ( |
44 | 54 | ggplot(df, aes(x="direction", y="frequency", fill="direction")) |
45 | | - + geom_bar(stat="identity", color="white", size=0.8, alpha=0.85, width=0.95) |
46 | | - + coord_polar(start=-np.pi / 8) # Rotate so N is at top |
47 | | - + scale_fill_manual(values=["#306998", "#4A90C2", "#FFD43B", "#F5A623", "#7B68EE", "#9B59B6", "#2ECC71", "#27AE60"]) |
| 55 | + + geom_bar(stat="identity", color="white", size=0.5, alpha=0.85, width=0.95) |
| 56 | + + coord_polar(start=-np.pi / 8) |
| 57 | + + scale_fill_manual(values=DIRECTION_COLORS) |
48 | 58 | + scale_y_continuous(limits=[0, None], expand=[0, 0.5]) |
49 | | - + labs(title="polar-bar · letsplot · pyplots.ai", x="", y="Frequency (%)") |
| 59 | + + labs(title="polar-bar · letsplot · anyplot.ai", x="", y="Frequency (%)") |
50 | 60 | + theme_minimal() |
51 | 61 | + theme( |
52 | | - plot_title=element_text(size=24, face="bold"), |
53 | | - axis_title_y=element_text(size=18), |
54 | | - axis_text=element_text(size=14), |
55 | | - legend_position="none", # Hide legend (labels shown around chart) |
56 | | - panel_grid_major=element_line(color="#CCCCCC", size=0.3), |
| 62 | + plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), |
| 63 | + panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG), |
| 64 | + panel_grid_major=element_line(color=INK_SOFT, size=0.3), |
| 65 | + plot_title=element_text(size=24, color=INK, face="bold"), |
| 66 | + axis_title_y=element_text(size=20, color=INK), |
| 67 | + axis_text=element_text(size=16, color=INK_SOFT), |
| 68 | + legend_position="none", |
57 | 69 | ) |
58 | | - + ggsize(1200, 1200) # Square for polar chart |
| 70 | + + ggsize(1200, 1200) |
59 | 71 | ) |
60 | 72 |
|
61 | | -# Save as PNG (scale 3x for high resolution: 3600x3600 for square polar) |
62 | | -ggsave(plot, "plot.png", scale=3, path=".") |
63 | | - |
64 | | -# Save interactive HTML |
65 | | -ggsave(plot, "plot.html", path=".") |
| 73 | +# Save as PNG and HTML (theme-suffixed) |
| 74 | +ggsave(plot, f"plot-{THEME}.png", scale=3, path=".") |
| 75 | +ggsave(plot, f"plot-{THEME}.html", path=".") |
0 commit comments