Skip to content

Commit 4bb30bd

Browse files
feat(plotly): implement line-navigator (#7732)
## Implementation: `line-navigator` - python/plotly Implements the **python/plotly** version of `line-navigator`. **File:** `plots/line-navigator/implementations/python/plotly.py` **Parent Issue:** #3785 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/26507868601)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 972063e commit 4bb30bd

3 files changed

Lines changed: 248 additions & 154 deletions

File tree

Lines changed: 84 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,48 @@
1-
""" pyplots.ai
1+
"""anyplot.ai
22
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
55
"""
66

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+
715
import numpy as np
816
import pandas as pd
917
import plotly.graph_objects as go
1018

1119

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)
1330
np.random.seed(42)
1431
dates = pd.date_range("2022-01-01", periods=1100, freq="D")
15-
16-
# Simulate temperature sensor data with seasonal patterns and noise
1732
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)
2035
noise = np.random.randn(1100) * 2
21-
values = 20 + seasonal + trend + noise # Base temp around 20C
36+
values = 20 + seasonal + trend + noise
2237

2338
df = pd.DataFrame({"date": dates, "value": values})
2439

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
2646
fig = go.Figure()
2747

2848
fig.add_trace(
@@ -31,27 +51,38 @@
3151
y=df["value"],
3252
mode="lines",
3353
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,
3659
)
3760
)
3861

39-
# Layout with rangeslider (mini navigator)
4062
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"},
4768
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",
5081
"rangeslider": {
5182
"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,
5586
"borderwidth": 1,
5687
},
5788
"rangeselector": {
@@ -62,30 +93,44 @@
6293
{"count": 1, "label": "1Y", "step": "year", "stepmode": "backward"},
6394
{"step": "all", "label": "All"},
6495
],
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,
69100
"borderwidth": 1,
70101
"x": 0,
71102
"y": 1.08,
72103
},
73104
"type": "date",
74105
},
75106
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",
80118
},
81-
template="plotly_white",
82119
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},
85121
)
86122

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+
)
89133

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

Comments
 (0)