Skip to content

Commit 69d0b29

Browse files
Merge branch 'main' into implementation/line-timeseries/pygal
2 parents c30e662 + 9f3b78b commit 69d0b29

6 files changed

Lines changed: 573 additions & 434 deletions

File tree

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
line-timeseries: Time Series Line Plot
3-
Library: altair 6.0.0 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-26
3+
Library: altair 6.1.0 | Python 3.13.13
4+
Quality: 92/100 | Updated: 2026-05-09
55
"""
66

7-
import altair as alt
8-
import numpy as np
9-
import pandas as pd
7+
import os
8+
import sys
109

1110

11+
# Remove the current directory from sys.path to avoid importing altair.py
12+
sys.path = [p for p in sys.path if p != "" and not p.endswith("python")]
13+
14+
import altair as alt # noqa: E402
15+
import numpy as np # noqa: E402
16+
import pandas as pd # noqa: E402
17+
18+
19+
# Theme tokens
20+
THEME = os.getenv("ANYPLOT_THEME", "light")
21+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
22+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
23+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
24+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
25+
BRAND = "#009E73" # Okabe-Ito position 1
26+
1227
# Data - Daily stock prices over one year
1328
np.random.seed(42)
1429

@@ -29,41 +44,56 @@
2944
# Create time series line chart
3045
chart = (
3146
alt.Chart(df)
32-
.mark_line(
33-
strokeWidth=3,
34-
color="#306998", # Python Blue
35-
)
47+
.mark_line(strokeWidth=3, color=BRAND, point=True, size=150)
3648
.encode(
3749
x=alt.X(
3850
"date:T",
3951
title="Date",
4052
axis=alt.Axis(
41-
format="%b %Y", # Month Year format
53+
format="%b %Y",
4254
labelFontSize=18,
4355
titleFontSize=22,
4456
labelAngle=-45,
4557
tickCount=12,
58+
labelColor=INK_SOFT,
59+
titleColor=INK,
60+
domainColor=INK_SOFT,
61+
gridColor=INK,
62+
gridOpacity=0.10,
4663
),
4764
),
4865
y=alt.Y(
4966
"price:Q",
5067
title="Stock Price ($)",
5168
scale=alt.Scale(zero=False),
52-
axis=alt.Axis(labelFontSize=18, titleFontSize=22, grid=True, gridOpacity=0.3),
69+
axis=alt.Axis(
70+
labelFontSize=18,
71+
titleFontSize=22,
72+
labelColor=INK_SOFT,
73+
titleColor=INK,
74+
domainColor=INK_SOFT,
75+
gridColor=INK,
76+
gridOpacity=0.10,
77+
),
5378
),
5479
tooltip=[
5580
alt.Tooltip("date:T", title="Date", format="%B %d, %Y"),
5681
alt.Tooltip("price:Q", title="Price", format="$.2f"),
5782
],
5883
)
5984
.properties(
60-
width=1600, height=900, title=alt.Title("line-timeseries · altair · pyplots.ai", fontSize=28, anchor="middle")
85+
width=1600,
86+
height=900,
87+
background=PAGE_BG,
88+
title=alt.Title("line-timeseries · altair · anyplot.ai", fontSize=28, anchor="middle", color=INK),
6189
)
62-
.configure_view(strokeWidth=0)
63-
.configure_axis(gridColor="#cccccc", gridOpacity=0.3, domainColor="#333333")
90+
.configure_view(fill=PAGE_BG, stroke=INK_SOFT, strokeWidth=1)
91+
.configure_title(color=INK, fontSize=28)
92+
.configure_legend(fillColor=ELEVATED_BG, strokeColor=INK_SOFT, labelColor=INK_SOFT, titleColor=INK)
6493
.interactive()
6594
)
6695

6796
# Save outputs
68-
chart.save("plot.png", scale_factor=3.0)
69-
chart.save("plot.html")
97+
script_dir = os.path.dirname(os.path.abspath(__file__))
98+
chart.save(os.path.join(script_dir, f"plot-{THEME}.png"), scale_factor=3.0)
99+
chart.save(os.path.join(script_dir, f"plot-{THEME}.html"))
Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,87 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
line-timeseries: Time Series Line Plot
3-
Library: plotly 6.5.0 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-26
3+
Library: plotly 6.7.0 | Python 3.13.13
4+
Quality: 90/100 | Updated: 2026-05-09
55
"""
66

7+
import os
8+
79
import numpy as np
810
import pandas as pd
911
import plotly.graph_objects as go
1012

1113

12-
# Data - Daily temperature readings over one year
14+
# Theme tokens
15+
THEME = os.getenv("ANYPLOT_THEME", "light")
16+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
17+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
18+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
19+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
20+
GRID = "rgba(26,26,23,0.10)" if THEME == "light" else "rgba(240,239,232,0.10)"
21+
BRAND = "#009E73" # Okabe-Ito position 1
22+
23+
# Data - Stock prices with uptrend
1324
np.random.seed(42)
1425
dates = pd.date_range(start="2024-01-01", end="2024-12-31", freq="D")
26+
days = np.arange(len(dates))
27+
trend = 100 + 0.15 * days
28+
volatility = 5 * np.sin(2 * np.pi * days / 60)
29+
noise = np.random.randn(len(dates)) * 2
30+
prices = trend + volatility + noise
1531

16-
# Create realistic temperature pattern with seasonal variation
17-
day_of_year = np.arange(len(dates))
18-
seasonal = 15 * np.sin(2 * np.pi * (day_of_year - 80) / 365) # Peak around late July
19-
baseline = 12 # Average temperature
20-
noise = np.random.randn(len(dates)) * 3
21-
temperatures = baseline + seasonal + noise
22-
23-
df = pd.DataFrame({"date": dates, "temperature": temperatures})
32+
df = pd.DataFrame({"date": dates, "price": prices})
2433

2534
# Create plot
2635
fig = go.Figure()
2736

2837
fig.add_trace(
2938
go.Scatter(
3039
x=df["date"],
31-
y=df["temperature"],
40+
y=df["price"],
3241
mode="lines",
33-
line={"color": "#306998", "width": 2.5},
34-
name="Temperature",
35-
hovertemplate="Date: %{x|%b %d, %Y}<br>Temperature: %{y:.1f}°C<extra></extra>",
42+
line={"color": BRAND, "width": 3},
43+
name="Stock Price",
44+
hovertemplate="Date: %{x|%b %d, %Y}<br>Price: $%{y:.2f}<extra></extra>",
3645
)
3746
)
3847

3948
# Layout for 4800x2700 px
4049
fig.update_layout(
4150
title={
42-
"text": "Daily Temperature 2024 · line-timeseries · plotly · pyplots.ai",
43-
"font": {"size": 32},
51+
"text": "line-timeseries · plotly · anyplot.ai",
52+
"font": {"size": 28, "color": INK},
4453
"x": 0.5,
4554
"xanchor": "center",
4655
},
4756
xaxis={
48-
"title": {"text": "Date", "font": {"size": 24}},
49-
"tickfont": {"size": 18},
57+
"title": {"text": "Date", "font": {"size": 22, "color": INK}},
58+
"tickfont": {"size": 18, "color": INK_SOFT},
5059
"tickformat": "%b %Y",
5160
"dtick": "M1",
52-
"gridcolor": "rgba(128, 128, 128, 0.3)",
61+
"gridcolor": GRID,
5362
"gridwidth": 1,
5463
"showgrid": True,
64+
"linecolor": INK_SOFT,
65+
"zerolinecolor": INK_SOFT,
66+
"rangeslider": {"visible": True, "thickness": 0.05},
5567
},
5668
yaxis={
57-
"title": {"text": "Temperature (°C)", "font": {"size": 24}},
58-
"tickfont": {"size": 18},
59-
"gridcolor": "rgba(128, 128, 128, 0.3)",
69+
"title": {"text": "Stock Price ($)", "font": {"size": 22, "color": INK}},
70+
"tickfont": {"size": 18, "color": INK_SOFT},
71+
"gridcolor": GRID,
6072
"gridwidth": 1,
6173
"showgrid": True,
74+
"linecolor": INK_SOFT,
75+
"zerolinecolor": INK_SOFT,
6276
},
63-
template="plotly_white",
64-
plot_bgcolor="white",
65-
paper_bgcolor="white",
77+
paper_bgcolor=PAGE_BG,
78+
plot_bgcolor=PAGE_BG,
79+
font={"color": INK},
6680
margin={"l": 100, "r": 80, "t": 120, "b": 100},
6781
showlegend=False,
82+
hovermode="x unified",
6883
)
6984

7085
# Save as PNG (4800x2700 px) and HTML
71-
fig.write_image("plot.png", width=1600, height=900, scale=3)
72-
fig.write_html("plot.html", include_plotlyjs="cdn")
86+
fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3)
87+
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")
Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
line-timeseries: Time Series Line Plot
3-
Library: plotnine 0.15.2 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-26
3+
Library: plotnine 0.15.4 | Python 3.13.13
4+
Quality: 92/100 | Updated: 2026-05-09
55
"""
66

7+
import os
8+
79
import numpy as np
810
import pandas as pd
911
from mizani.breaks import breaks_date
1012
from mizani.labels import label_date
1113
from plotnine import (
1214
aes,
1315
element_line,
16+
element_rect,
1417
element_text,
1518
geom_line,
1619
geom_point,
@@ -22,36 +25,51 @@
2225
)
2326

2427

25-
# Data: Daily stock prices over one year
28+
THEME = os.getenv("ANYPLOT_THEME", "light")
29+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
30+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
31+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
32+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
33+
BRAND = "#009E73"
34+
35+
# Data: Bitcoin prices over one year with explicit trend and volatility
2636
np.random.seed(42)
27-
dates = pd.date_range(start="2024-01-01", periods=252, freq="B") # Business days
28-
price = 100.0
37+
dates = pd.date_range(start="2023-01-01", periods=365, freq="D")
38+
price = 16500.0
2939
prices = []
30-
for _ in range(252):
31-
price = price * (1 + np.random.randn() * 0.015)
40+
for i in range(365):
41+
# Trend component: upward over the year, with mid-year dip
42+
trend = 20000 + 15000 * np.sin(i / 365 * np.pi * 2) + i * 5
43+
# Volatility: crypto is more volatile than stocks
44+
volatility = price * (1 + np.random.randn() * 0.035)
45+
# Mix trend and volatility
46+
price = 0.7 * trend + 0.3 * volatility
3247
prices.append(price)
3348

3449
df = pd.DataFrame({"date": dates, "price": prices})
3550

3651
# Plot
3752
plot = (
3853
ggplot(df, aes(x="date", y="price"))
39-
+ geom_line(color="#306998", size=1.5, alpha=0.9)
40-
+ geom_point(color="#306998", size=0.8, alpha=0.5)
41-
+ scale_x_datetime(breaks=breaks_date(7), labels=label_date("%b %Y"))
42-
+ labs(title="line-timeseries · plotnine · pyplots.ai", x="Date", y="Stock Price ($)")
54+
+ geom_line(color=BRAND, size=1.5, alpha=0.9)
55+
+ geom_point(color=BRAND, size=0.8, alpha=0.5)
56+
+ scale_x_datetime(breaks=breaks_date(30), labels=label_date("%b"))
57+
+ labs(title="line-timeseries · plotnine · anyplot.ai", x="Date", y="Bitcoin Price (USD)")
4358
+ theme_minimal()
4459
+ theme(
4560
figure_size=(16, 9),
46-
text=element_text(size=14),
47-
axis_title=element_text(size=20),
48-
axis_text=element_text(size=16),
61+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
62+
panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
63+
panel_grid_major=element_line(color=INK, size=0.3, alpha=0.10),
64+
panel_grid_minor=element_line(color=INK, size=0.2, alpha=0.05),
65+
panel_border=element_rect(color=INK_SOFT, fill=None),
66+
text=element_text(size=14, color=INK),
67+
axis_title=element_text(size=20, color=INK),
68+
axis_text=element_text(size=16, color=INK_SOFT),
4969
axis_text_x=element_text(angle=45, hjust=1),
50-
plot_title=element_text(size=24),
51-
panel_grid_major=element_line(color="#cccccc", size=0.5, alpha=0.3),
52-
panel_grid_minor=element_line(color="#dddddd", size=0.3, alpha=0.2),
70+
plot_title=element_text(size=24, color=INK),
5371
)
5472
)
5573

5674
# Save
57-
plot.save("plot.png", dpi=300)
75+
plot.save(f"plot-{THEME}.png", dpi=300)

0 commit comments

Comments
 (0)