|
1 | | -""" pyplots.ai |
| 1 | +"""anyplot.ai |
2 | 2 | line-navigator: Line Chart with Mini Navigator |
3 | | -Library: plotly 6.5.2 | Python 3.13.11 |
4 | | -Quality: 94/100 | Created: 2026-01-20 |
| 3 | +Library: plotly 6.7.0 | Python 3.13.13 |
| 4 | +Quality: 87/100 | Updated: 2026-05-27 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | +import sys |
| 9 | + |
| 10 | + |
| 11 | +# Prevent this file from shadowing the installed plotly package |
| 12 | +_script_dir = os.path.dirname(os.path.abspath(__file__)) |
| 13 | +sys.path[:] = [p for p in sys.path if p and os.path.abspath(p) != _script_dir] |
| 14 | + |
7 | 15 | import numpy as np |
8 | 16 | import pandas as pd |
9 | 17 | import plotly.graph_objects as go |
10 | 18 |
|
11 | 19 |
|
12 | | -# Data - Daily sensor readings over 3 years (1095+ data points) |
| 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 | +GRID = "rgba(26,26,23,0.15)" if THEME == "light" else "rgba(240,239,232,0.15)" |
| 26 | +BRAND = "#009E73" |
| 27 | +FILL_COLOR = "rgba(0,158,115,0.12)" if THEME == "light" else "rgba(0,158,115,0.15)" |
| 28 | + |
| 29 | +# Data - Daily temperature sensor data over 3 years (~1100 data points) |
13 | 30 | np.random.seed(42) |
14 | 31 | dates = pd.date_range("2022-01-01", periods=1100, freq="D") |
15 | | - |
16 | | -# Simulate temperature sensor data with seasonal patterns and noise |
17 | 32 | days_of_year = np.arange(1100) % 365 |
18 | | -seasonal = 15 * np.sin(2 * np.pi * days_of_year / 365) # Seasonal cycle |
19 | | -trend = np.linspace(0, 3, 1100) # Slight warming trend |
| 33 | +seasonal = 15 * np.sin(2 * np.pi * days_of_year / 365) |
| 34 | +trend = np.linspace(0, 3, 1100) |
20 | 35 | noise = np.random.randn(1100) * 2 |
21 | | -values = 20 + seasonal + trend + noise # Base temp around 20C |
| 36 | +values = 20 + seasonal + trend + noise |
22 | 37 |
|
23 | 38 | df = pd.DataFrame({"date": dates, "value": values}) |
24 | 39 |
|
25 | | -# Create figure with main line chart |
| 40 | +title = "Temperature Sensor Data · line-navigator · python · plotly · anyplot.ai" |
| 41 | +n = len(title) |
| 42 | +ratio = 67 / n if n > 67 else 1.0 |
| 43 | +title_fontsize = max(11, round(16 * ratio)) |
| 44 | + |
| 45 | +# Plot |
26 | 46 | fig = go.Figure() |
27 | 47 |
|
28 | 48 | fig.add_trace( |
|
31 | 51 | y=df["value"], |
32 | 52 | mode="lines", |
33 | 53 | name="Temperature", |
34 | | - line={"color": "#306998", "width": 2}, |
35 | | - hovertemplate="%{x|%Y-%m-%d}<br>Temperature: %{y:.1f}°C<extra></extra>", |
| 54 | + line={"color": BRAND, "width": 2}, |
| 55 | + fill="tozeroy", |
| 56 | + fillcolor=FILL_COLOR, |
| 57 | + hovertemplate="%{x|%Y-%m-%d}<br>%{y:.1f}°C<extra></extra>", |
| 58 | + showlegend=False, |
36 | 59 | ) |
37 | 60 | ) |
38 | 61 |
|
39 | | -# Layout with rangeslider (mini navigator) |
40 | 62 | fig.update_layout( |
41 | | - title={ |
42 | | - "text": "Temperature Sensor Data · line-navigator · plotly · pyplots.ai", |
43 | | - "font": {"size": 28}, |
44 | | - "x": 0.5, |
45 | | - "xanchor": "center", |
46 | | - }, |
| 63 | + autosize=False, |
| 64 | + paper_bgcolor=PAGE_BG, |
| 65 | + plot_bgcolor=PAGE_BG, |
| 66 | + font={"color": INK}, |
| 67 | + title={"text": title, "font": {"size": title_fontsize, "color": INK}, "x": 0.5, "xanchor": "center"}, |
47 | 68 | xaxis={ |
48 | | - "title": {"text": "Date", "font": {"size": 22}}, |
49 | | - "tickfont": {"size": 18}, |
| 69 | + "title": {"text": "Date", "font": {"size": 12, "color": INK}}, |
| 70 | + "tickfont": {"size": 10, "color": INK_SOFT}, |
| 71 | + "showgrid": False, |
| 72 | + "showline": False, |
| 73 | + "linecolor": INK_SOFT, |
| 74 | + "zerolinecolor": INK_SOFT, |
| 75 | + "showspikes": True, |
| 76 | + "spikemode": "across", |
| 77 | + "spikesnap": "cursor", |
| 78 | + "spikethickness": 1, |
| 79 | + "spikecolor": INK_SOFT, |
| 80 | + "spikedash": "dot", |
50 | 81 | "rangeslider": { |
51 | 82 | "visible": True, |
52 | | - "thickness": 0.15, # 15% of chart height |
53 | | - "bgcolor": "#f8f9fa", |
54 | | - "bordercolor": "#dee2e6", |
| 83 | + "thickness": 0.15, |
| 84 | + "bgcolor": ELEVATED_BG, |
| 85 | + "bordercolor": INK_SOFT, |
55 | 86 | "borderwidth": 1, |
56 | 87 | }, |
57 | 88 | "rangeselector": { |
|
62 | 93 | {"count": 1, "label": "1Y", "step": "year", "stepmode": "backward"}, |
63 | 94 | {"step": "all", "label": "All"}, |
64 | 95 | ], |
65 | | - "font": {"size": 14}, |
66 | | - "bgcolor": "#ffffff", |
67 | | - "activecolor": "#306998", |
68 | | - "bordercolor": "#dee2e6", |
| 96 | + "font": {"size": 10, "color": INK}, |
| 97 | + "bgcolor": ELEVATED_BG, |
| 98 | + "activecolor": BRAND, |
| 99 | + "bordercolor": INK_SOFT, |
69 | 100 | "borderwidth": 1, |
70 | 101 | "x": 0, |
71 | 102 | "y": 1.08, |
72 | 103 | }, |
73 | 104 | "type": "date", |
74 | 105 | }, |
75 | 106 | yaxis={ |
76 | | - "title": {"text": "Temperature (°C)", "font": {"size": 22}}, |
77 | | - "tickfont": {"size": 18}, |
78 | | - "gridcolor": "rgba(0,0,0,0.1)", |
79 | | - "gridwidth": 1, |
| 107 | + "title": {"text": "Temperature (°C)", "font": {"size": 12, "color": INK}}, |
| 108 | + "tickfont": {"size": 10, "color": INK_SOFT}, |
| 109 | + "gridcolor": GRID, |
| 110 | + "showline": False, |
| 111 | + "zeroline": False, |
| 112 | + "showspikes": True, |
| 113 | + "spikemode": "across", |
| 114 | + "spikesnap": "cursor", |
| 115 | + "spikethickness": 1, |
| 116 | + "spikecolor": INK_SOFT, |
| 117 | + "spikedash": "dot", |
80 | 118 | }, |
81 | | - template="plotly_white", |
82 | 119 | hovermode="x unified", |
83 | | - margin={"l": 80, "r": 40, "t": 100, "b": 40}, |
84 | | - showlegend=False, |
| 120 | + margin={"l": 80, "r": 40, "t": 100, "b": 60}, |
85 | 121 | ) |
86 | 122 |
|
87 | | -# Save as PNG |
88 | | -fig.write_image("plot.png", width=1600, height=900, scale=3) |
| 123 | +fig.add_hline( |
| 124 | + y=0, |
| 125 | + line_dash="dot", |
| 126 | + line_color=INK_SOFT, |
| 127 | + line_width=1, |
| 128 | + annotation_text="Freezing Point", |
| 129 | + annotation_font_size=9, |
| 130 | + annotation_font_color=INK_SOFT, |
| 131 | + annotation_position="bottom right", |
| 132 | +) |
89 | 133 |
|
90 | | -# Save as HTML for interactivity |
91 | | -fig.write_html("plot.html", include_plotlyjs="cdn") |
| 134 | +# Save |
| 135 | +fig.write_image(f"plot-{THEME}.png", width=800, height=450, scale=4) |
| 136 | +fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn") |
0 commit comments