Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6aaf01e
feat(highcharts): implement line-basic (#317)
claude[bot] Dec 6, 2025
2911bbb
feat(letsplot): implement line-basic (#307)
claude[bot] Dec 6, 2025
1695a37
feat(matplotlib): implement line-basic (#287)
claude[bot] Dec 6, 2025
2aee75b
feat(altair): implement line-basic (#310)
claude[bot] Dec 6, 2025
3da93d5
feat(seaborn): implement line-basic (#297)
claude[bot] Dec 6, 2025
1f723b5
feat(plotnine): implement line-basic (#345)
claude[bot] Dec 7, 2025
bf6767a
feat(pygal): implement line-basic (#361)
claude[bot] Dec 7, 2025
7fa128d
feat(plotly): implement line-basic (#344)
claude[bot] Dec 7, 2025
bd7e4a9
feat(altair): implement line-basic (#373)
claude[bot] Dec 7, 2025
3456191
feat(plotnine): implement line-basic (#381)
claude[bot] Dec 7, 2025
e758ca1
feat(plotly): implement line-basic (#382)
claude[bot] Dec 7, 2025
81a5bae
feat(highcharts): implement line-basic (#383)
claude[bot] Dec 7, 2025
c679f6f
feat(highcharts): implement line-basic (#389)
claude[bot] Dec 7, 2025
3562c72
feat(altair): implement line-basic (#391)
claude[bot] Dec 7, 2025
acbb5f1
feat(matplotlib): implement line-basic (#394)
claude[bot] Dec 7, 2025
35e12df
feat(plotly): implement line-basic (#393)
claude[bot] Dec 7, 2025
586abcc
feat(altair): implement line-basic (#416)
claude[bot] Dec 7, 2025
b590eb7
feat(matplotlib): implement line-basic (#418)
claude[bot] Dec 7, 2025
07617ea
feat(plotnine): implement line-basic (#420)
claude[bot] Dec 7, 2025
077c254
feat(highcharts): implement line-basic (#422)
claude[bot] Dec 7, 2025
6dcc406
feat(highcharts): implement line-basic (#424)
claude[bot] Dec 7, 2025
99bceea
feat(highcharts): implement line-basic (#434)
claude[bot] Dec 7, 2025
39effdd
feat(matplotlib): implement line-basic (#445)
claude[bot] Dec 7, 2025
ee01978
feat(plotly): implement line-basic (#446)
claude[bot] Dec 7, 2025
a60a352
feat(highcharts): implement line-basic (#448)
claude[bot] Dec 7, 2025
dc54b03
feat(letsplot): implement line-basic (#450)
claude[bot] Dec 7, 2025
870ff67
feat(matplotlib): implement line-basic (#476)
claude[bot] Dec 7, 2025
0c66666
feat(highcharts): implement line-basic (#478)
claude[bot] Dec 7, 2025
001ecc1
chore: merge main with selenium fix
MarkusNeusinger Dec 7, 2025
0786958
feat(bokeh): implement line-basic (#374)
claude[bot] Dec 7, 2025
13e600c
feat(letsplot): implement line-basic (#460)
claude[bot] Dec 7, 2025
5001a77
feat(plotly): implement line-basic (#502)
claude[bot] Dec 7, 2025
87b67c1
feat(highcharts): implement line-basic (#504)
claude[bot] Dec 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 23 additions & 142 deletions plots/altair/line/line-basic/default.py
Original file line number Diff line number Diff line change
@@ -1,154 +1,35 @@
"""
line-basic: Basic Line Chart
Implementation for: altair
Variant: default
Python: 3.10+
line-basic: Basic Line Plot
Library: altair
"""

from typing import TYPE_CHECKING, Optional

import altair as alt
import pandas as pd


if TYPE_CHECKING:
from altair import Chart


def create_plot(
data: pd.DataFrame,
x: str,
y: str,
title: Optional[str] = None,
xlabel: Optional[str] = None,
ylabel: Optional[str] = None,
color: str = "steelblue",
linewidth: float = 2,
marker: Optional[str] = None,
marker_size: int = 60,
width: int = 800,
height: int = 450,
**kwargs,
) -> "Chart":
"""
Create a basic line chart showing trends over a continuous axis using altair.

Args:
data: Input DataFrame with required columns
x: Column name for x-axis values (typically time or sequence)
y: Column name for y-axis values
title: Plot title (optional)
xlabel: Custom x-axis label (optional, defaults to x column name)
ylabel: Custom y-axis label (optional, defaults to y column name)
color: Line color (default: 'steelblue')
linewidth: Width of the line (default: 2)
marker: Marker style - 'circle', 'square', 'diamond', etc. (optional)
marker_size: Size of markers if enabled (default: 60)
width: Figure width in pixels (default: 800)
height: Figure height in pixels (default: 450)
**kwargs: Additional parameters for altair chart configuration

Returns:
Altair Chart object

Raises:
ValueError: If data is empty
KeyError: If required columns not found

Example:
>>> data = pd.DataFrame({
... 'month': [1, 2, 3, 4, 5, 6],
... 'sales': [100, 150, 130, 180, 200, 190]
... })
>>> chart = create_plot(data, x='month', y='sales')
"""
# Input validation
if data.empty:
raise ValueError("Data cannot be empty")

# Check required columns
for col in [x, y]:
if col not in data.columns:
available = ", ".join(data.columns)
raise KeyError(f"Column '{col}' not found. Available columns: {available}")

# Sort data by x-axis to ensure proper line connections
plot_data = data.sort_values(by=x).copy()
# Data
data = pd.DataFrame({"time": [1, 2, 3, 4, 5, 6, 7], "value": [10, 15, 13, 18, 22, 19, 25]})

# Determine x encoding type based on data
x_dtype = plot_data[x].dtype
if pd.api.types.is_datetime64_any_dtype(x_dtype):
x_encoding = f"{x}:T"
else:
x_encoding = f"{x}:Q"

# Create the line chart
line = (
alt.Chart(plot_data)
.mark_line(color=color, strokeWidth=linewidth)
.encode(
x=alt.X(x_encoding, title=xlabel or x, axis=alt.Axis(labelAngle=0, labelLimit=200)),
y=alt.Y(f"{y}:Q", title=ylabel or y, scale=alt.Scale(zero=False)),
tooltip=[
alt.Tooltip(x_encoding, title=xlabel or x),
alt.Tooltip(f"{y}:Q", title=ylabel or y, format=".2f"),
],
)
)

# Add markers if specified
if marker:
points = (
alt.Chart(plot_data)
.mark_point(color=color, size=marker_size, filled=True, shape=marker)
.encode(
x=alt.X(x_encoding),
y=alt.Y(f"{y}:Q"),
tooltip=[
alt.Tooltip(x_encoding, title=xlabel or x),
alt.Tooltip(f"{y}:Q", title=ylabel or y, format=".2f"),
],
)
)
chart_base = line + points
else:
chart_base = line

# Apply properties and configuration
chart = (
chart_base.properties(
width=width, height=height, title=alt.TitleParams(text=title or "Line Chart", fontSize=16, anchor="middle")
)
.configure_view(strokeWidth=0)
.configure_axis(grid=True, gridOpacity=0.3, gridDash=[3, 3], domainWidth=1, tickWidth=1)
# Create line chart
line = (
alt.Chart(data)
.mark_line(strokeWidth=2, color="#306998")
.encode(
x=alt.X("time:Q", title="Time", axis=alt.Axis(labelFontSize=16, titleFontSize=20)),
y=alt.Y("value:Q", title="Value", axis=alt.Axis(labelFontSize=16, titleFontSize=20)),
)
)

return chart
# Add points on the line for clarity
points = alt.Chart(data).mark_point(size=100, color="#306998", filled=True).encode(x="time:Q", y="value:Q")

# Combine and configure chart
chart = (
(line + points)
.properties(width=1600, height=900, title=alt.Title("Basic Line Plot", fontSize=20))
.configure_view(strokeWidth=0)
.configure_axis(grid=True, gridOpacity=0.3)
)

if __name__ == "__main__":
# Sample data for testing - monthly sales trend
sample_data = pd.DataFrame(
{
"Month": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
"Sales": [120, 150, 170, 165, 180, 220, 250, 240, 210, 190, 180, 200],
}
)

# Create plot with markers
chart = create_plot(
sample_data,
x="Month",
y="Sales",
title="Monthly Sales Trend (2024)",
xlabel="Month",
ylabel="Sales (thousands)",
color="steelblue",
linewidth=2.5,
marker="circle",
marker_size=80,
)

# Save as PNG
chart.save("plot.png", scale_factor=2.0)
print("Plot saved to plot.png")
# Save as PNG (1600 × 900 at scale 3 = 4800 × 2700 px)
chart.save("plot.png", scale_factor=3.0)
170 changes: 33 additions & 137 deletions plots/bokeh/line/line-basic/default.py
Original file line number Diff line number Diff line change
@@ -1,154 +1,50 @@
"""
line-basic: Basic Line Plot
Implementation for: bokeh
Variant: default
Python: 3.10+
Library: bokeh
"""

from typing import TYPE_CHECKING, Optional

import numpy as np
import pandas as pd
from bokeh.io import export_png
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service


if TYPE_CHECKING:
from bokeh.plotting import Figure


def create_plot(
data: pd.DataFrame,
x: str,
y: str,
title: Optional[str] = None,
xlabel: Optional[str] = None,
ylabel: Optional[str] = None,
color: str = "steelblue",
line_width: float = 2.0,
marker: Optional[str] = None,
marker_size: float = 8,
alpha: float = 1.0,
width: int = 1600,
height: int = 900,
**kwargs,
) -> "Figure":
"""
Create a basic line plot visualizing trends over continuous or sequential data.

Args:
data: Input DataFrame with required columns
x: Column name for x-axis values (numeric or datetime)
y: Column name for y-axis values (numeric)
title: Plot title (optional)
xlabel: Custom x-axis label (optional, defaults to column name)
ylabel: Custom y-axis label (optional, defaults to column name)
color: Line color (default: "steelblue")
line_width: Width of the line (default: 2.0)
marker: Marker style for data points (optional, e.g., "circle", "square")
marker_size: Size of markers if enabled (default: 8)
alpha: Line transparency (default: 1.0)
width: Figure width in pixels (default: 1600)
height: Figure height in pixels (default: 900)
**kwargs: Additional parameters

Returns:
Bokeh Figure object

Raises:
ValueError: If data is empty
KeyError: If required columns not found
TypeError: If y column contains non-numeric data

Example:
>>> data = pd.DataFrame({'x': [1, 2, 3, 4, 5], 'y': [2, 4, 3, 5, 6]})
>>> fig = create_plot(data, 'x', 'y')
"""
# Input validation
if data.empty:
raise ValueError("Data cannot be empty")

# Check required columns
for col in [x, y]:
if col not in data.columns:
available = ", ".join(data.columns)
raise KeyError(f"Column '{col}' not found. Available columns: {available}")

# Check if y column is numeric
if not pd.api.types.is_numeric_dtype(data[y]):
raise TypeError(f"Column '{y}' must contain numeric data")

# Sort data by x to ensure proper line connection
plot_data = data[[x, y]].dropna().sort_values(by=x)

# Determine x-axis type
x_axis_type = "datetime" if pd.api.types.is_datetime64_any_dtype(plot_data[x]) else "auto"

# Create ColumnDataSource
source = ColumnDataSource(data={"x": plot_data[x], "y": plot_data[y]})

# Create figure
p = figure(
width=width,
height=height,
title=title or "Line Plot",
x_axis_type=x_axis_type,
toolbar_location="above",
tools="pan,wheel_zoom,box_zoom,reset,save",
)

# Plot line
p.line(x="x", y="y", source=source, line_color=color, line_width=line_width, line_alpha=alpha)

# Add markers if specified
if marker:
p.scatter(x="x", y="y", source=source, size=marker_size, color=color, alpha=alpha, marker=marker)

# Labels
p.xaxis.axis_label = xlabel or x
p.yaxis.axis_label = ylabel or y

# Styling
p.title.text_font_size = "14pt"
p.title.align = "center"
p.xaxis.axis_label_text_font_size = "12pt"
p.yaxis.axis_label_text_font_size = "12pt"
p.xgrid.grid_line_alpha = 0.3
p.ygrid.grid_line_alpha = 0.3
p.xgrid.grid_line_dash = [6, 4]
p.ygrid.grid_line_dash = [6, 4]
# Data
data = pd.DataFrame({"time": [1, 2, 3, 4, 5, 6, 7], "value": [10, 15, 13, 18, 22, 19, 25]})

return p
source = ColumnDataSource(data={"x": data["time"], "y": data["value"]})

# Create figure
p = figure(width=4800, height=2700, title="Basic Line Plot", x_axis_label="Time", y_axis_label="Value")

if __name__ == "__main__":
from bokeh.io import export_png
# Plot line
p.line(x="x", y="y", source=source, line_width=2, line_color="#306998")

# Sample data for testing - simulating time series data
np.random.seed(42)
n_points = 50
# Add markers at data points
p.scatter(x="x", y="y", source=source, size=8, color="#306998")

# Create sequential x values
x_values = np.arange(n_points)
# Create y values with a trend and some noise
y_values = 10 + 0.5 * x_values + np.random.randn(n_points) * 2
# Styling
p.title.text_font_size = "20pt"
p.xaxis.axis_label_text_font_size = "20pt"
p.yaxis.axis_label_text_font_size = "20pt"
p.xaxis.major_label_text_font_size = "16pt"
p.yaxis.major_label_text_font_size = "16pt"
p.grid.grid_line_alpha = 0.3

data = pd.DataFrame({"Time": x_values, "Value": y_values})
# Setup Chrome/Chromium webdriver for PNG export
chrome_options = Options()
chrome_options.add_argument("--headless=new")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")

# Create plot
fig = create_plot(
data,
x="Time",
y="Value",
title="Basic Line Plot Example",
xlabel="Time (units)",
ylabel="Measurement Value",
color="steelblue",
line_width=2.5,
marker="circle",
marker_size=6,
)
# Use system chromedriver (pre-installed on GitHub Actions runners)
service = Service()
driver = webdriver.Chrome(service=service, options=chrome_options)

# Save as PNG
export_png(fig, filename="plot.png")
print("Plot saved to plot.png")
# Save
export_png(p, filename="plot.png", webdriver=driver)
driver.quit()
Loading
Loading