|
1 | | -""" pyplots.ai |
| 1 | +""" anyplot.ai |
2 | 2 | ecdf-basic: Basic ECDF Plot |
3 | | -Library: altair 6.0.0 | Python 3.13.11 |
4 | | -Quality: 92/100 | Created: 2025-12-23 |
| 3 | +Library: altair 6.1.0 | Python 3.14.4 |
| 4 | +Quality: 86/100 | Updated: 2026-04-24 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | + |
7 | 9 | import altair as alt |
8 | 10 | import numpy as np |
9 | 11 | import pandas as pd |
10 | 12 |
|
11 | 13 |
|
12 | | -# Data |
| 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 | +BRAND = "#009E73" |
| 21 | + |
| 22 | +# Data: API response latency from a production web service |
13 | 23 | np.random.seed(42) |
14 | | -values = np.random.normal(loc=50, scale=15, size=200) |
| 24 | +response_times_ms = np.random.normal(loc=120, scale=35, size=250) |
| 25 | +response_times_ms = np.clip(response_times_ms, 20, None) |
15 | 26 |
|
16 | | -# Sort values and compute ECDF |
17 | | -sorted_values = np.sort(values) |
18 | | -ecdf_y = np.arange(1, len(sorted_values) + 1) / len(sorted_values) |
| 27 | +sorted_latency = np.sort(response_times_ms) |
| 28 | +cumulative_proportion = np.arange(1, len(sorted_latency) + 1) / len(sorted_latency) |
19 | 29 |
|
20 | | -df = pd.DataFrame({"value": sorted_values, "ecdf": ecdf_y}) |
| 30 | +df = pd.DataFrame({"latency_ms": sorted_latency, "cumulative": cumulative_proportion}) |
21 | 31 |
|
22 | 32 | # Chart |
23 | 33 | chart = ( |
24 | 34 | alt.Chart(df) |
25 | | - .mark_line(interpolate="step-after", strokeWidth=3, color="#306998") |
| 35 | + .mark_line(interpolate="step-after", strokeWidth=3.5, color=BRAND) |
26 | 36 | .encode( |
27 | | - x=alt.X("value:Q", title="Value", scale=alt.Scale(nice=True)), |
28 | | - y=alt.Y("ecdf:Q", title="Cumulative Proportion", scale=alt.Scale(domain=[0, 1])), |
29 | | - tooltip=["value:Q", "ecdf:Q"], |
| 37 | + x=alt.X("latency_ms:Q", title="API Response Time (ms)", scale=alt.Scale(nice=True)), |
| 38 | + y=alt.Y( |
| 39 | + "cumulative:Q", |
| 40 | + title="Cumulative Proportion", |
| 41 | + scale=alt.Scale(domain=[0, 1]), |
| 42 | + axis=alt.Axis(format=".0%", tickCount=11), |
| 43 | + ), |
| 44 | + tooltip=[ |
| 45 | + alt.Tooltip("latency_ms:Q", title="Latency (ms)", format=".1f"), |
| 46 | + alt.Tooltip("cumulative:Q", title="Proportion", format=".3f"), |
| 47 | + ], |
| 48 | + ) |
| 49 | + .properties( |
| 50 | + width=1600, |
| 51 | + height=900, |
| 52 | + background=PAGE_BG, |
| 53 | + title=alt.Title("ecdf-basic · altair · anyplot.ai", fontSize=28, color=INK), |
| 54 | + ) |
| 55 | + .interactive() |
| 56 | + .configure_view(fill=PAGE_BG, strokeWidth=0) |
| 57 | + .configure_axis( |
| 58 | + domainColor=INK_SOFT, |
| 59 | + tickColor=INK_SOFT, |
| 60 | + gridColor=INK, |
| 61 | + gridOpacity=0.10, |
| 62 | + labelColor=INK_SOFT, |
| 63 | + titleColor=INK, |
| 64 | + labelFontSize=18, |
| 65 | + titleFontSize=22, |
30 | 66 | ) |
31 | | - .properties(width=1600, height=900, title=alt.Title("ecdf-basic · altair · pyplots.ai", fontSize=28)) |
32 | | - .configure_axis(labelFontSize=18, titleFontSize=22, gridOpacity=0.3, gridDash=[4, 4]) |
33 | | - .configure_view(strokeWidth=0) |
| 67 | + .configure_title(color=INK) |
34 | 68 | ) |
35 | 69 |
|
36 | 70 | # Save |
37 | | -chart.save("plot.png", scale_factor=3.0) |
38 | | -chart.save("plot.html") |
| 71 | +chart.save(f"plot-{THEME}.png", scale_factor=3.0) |
| 72 | +chart.save(f"plot-{THEME}.html") |
0 commit comments