Skip to content

Commit 75e103b

Browse files
authored
feat: update api spec to handle multi-plot with multiple layers (#5)
1 parent c930c79 commit 75e103b

8 files changed

+2331
-70
lines changed

Diff for: api/latest.json

+74-70
Original file line numberDiff line numberDiff line change
@@ -30,51 +30,40 @@
3030
"properties": {
3131
"id": {
3232
"type": "string",
33-
"example": "container-figure-id"
33+
"example": "figure-id"
3434
},
35-
"selector": {
35+
"library": {
3636
"type": "string",
37-
"example": ""
37+
"example": "matplotlib"
38+
},
39+
"coordinate": {
40+
"type": "string",
41+
"example": "cartesian"
3842
},
3943
"layout": {
4044
"type": "object",
4145
"properties": {
4246
"rows": {
4347
"type": "integer",
44-
"example": 3
48+
"example": 2
4549
},
4650
"columns": {
4751
"type": "integer",
48-
"example": 2
52+
"example": 3
4953
}
5054
}
5155
},
5256
"title": {
5357
"type": "string",
54-
"example": "Penguin Bill Dimensions by Species and Sex"
58+
"example": "figure-title"
5559
},
56-
"axes": {
57-
"type": "object",
58-
"properties": {
59-
"x": {
60-
"type": "object",
61-
"properties": {
62-
"label": {
63-
"type": "string",
64-
"example": "Bill Length (mm)"
65-
}
66-
}
67-
},
68-
"y": {
69-
"type": "object",
70-
"properties": {
71-
"label": {
72-
"type": "string",
73-
"example": "Bill Depth (mm)"
74-
}
75-
}
76-
}
77-
}
60+
"subtitle": {
61+
"type": "string",
62+
"example": "R-figure-subtitle"
63+
},
64+
"caption": {
65+
"type": "string",
66+
"example": "R-figure-caption"
7867
},
7968
"panels": {
8069
"type": "array",
@@ -83,66 +72,81 @@
8372
"properties": {
8473
"id": {
8574
"type": "string",
86-
"example": "panel-01"
87-
},
88-
"selector": {
89-
"type": "string",
90-
"example": ""
91-
},
92-
"type": {
93-
"type": "string",
94-
"description": "Specifies the type of the item, e.g., 'point', 'bar', or 'line'.",
95-
"enum": [
96-
"bar",
97-
"hist",
98-
"heat",
99-
"box",
100-
"point",
101-
"line",
102-
"stacked",
103-
"dodged"
104-
],
105-
"example": "point"
75+
"example": "panel-id"
10676
},
10777
"title": {
10878
"type": "string",
109-
"example": "Adelie - Female"
79+
"example": "panel-title"
11080
},
11181
"axes": {
11282
"type": "object",
11383
"properties": {
11484
"x": {
115-
"type": "object",
116-
"properties": {
117-
"label": {
118-
"type": "string",
119-
"example": "Bill Length (mm)"
120-
}
121-
}
85+
"type": "string",
86+
"example": "x-axis"
12287
},
12388
"y": {
124-
"type": "object",
125-
"properties": {
126-
"label": {
127-
"type": "string",
128-
"example": "Bill Depth (mm)"
129-
}
130-
}
89+
"type": "string",
90+
"example": "y-axis"
91+
},
92+
"z": {
93+
"type": "string",
94+
"example": "z-axis"
13195
}
13296
}
13397
},
134-
"data": {
98+
"legend": {
99+
"type": "object",
100+
"additionalProperties": {
101+
"type": "string"
102+
},
103+
"example": {
104+
"gentoo": "red",
105+
"adelie": "green"
106+
}
107+
},
108+
"layers": {
135109
"type": "array",
136110
"items": {
137111
"type": "object",
138112
"properties": {
139-
"x": {
140-
"type": "number",
141-
"example": 39.5
113+
"type": {
114+
"type": "string",
115+
"description": "Layer type, e.g., 'bar', 'line', 'scatter', etc.",
116+
"enum": [
117+
"bar",
118+
"hist",
119+
"heat",
120+
"box",
121+
"point",
122+
"line",
123+
"stacked",
124+
"dodged"
125+
],
126+
"example": "layer-type"
142127
},
143-
"y": {
144-
"type": "number",
145-
"example": 17.4
128+
"selector": {
129+
"type": "array",
130+
"items": {
131+
"type": "string",
132+
"example": "selectors"
133+
}
134+
},
135+
"data": {
136+
"type": "array",
137+
"items": {
138+
"type": "object",
139+
"properties": {
140+
"x": {
141+
"type": "number",
142+
"example": 39.5
143+
},
144+
"y": {
145+
"type": "number",
146+
"example": 17.4
147+
}
148+
}
149+
}
146150
}
147151
}
148152
}

Diff for: examples/multi-layer/multi-layer-seaborn.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import seaborn as sns
2+
import matplotlib.pyplot as plt
3+
import pandas as pd
4+
import numpy as np
5+
6+
# Load example dataset
7+
tips = sns.load_dataset("tips")
8+
9+
# Prepare data for the bar chart (average total bill by day)
10+
avg_bill = tips.groupby('day')['total_bill'].mean().reset_index()
11+
12+
# Prepare data for the line chart (average tip by day)
13+
avg_tip = tips.groupby('day')['tip'].mean().reset_index()
14+
15+
# Start plotting
16+
plt.figure(figsize=(10, 6))
17+
sns.set(style="whitegrid")
18+
19+
# Create bar chart
20+
bar = sns.barplot(x='day', y='total_bill', data=avg_bill, color='lightblue', label='Average Total Bill')
21+
22+
# Create line chart
23+
line = sns.lineplot(x='day', y='tip', data=avg_tip, sort=False, marker='o', color='red', label='Average Tip')
24+
25+
# Adding legend
26+
plt.legend()
27+
28+
# Show the plot
29+
plt.show()

Diff for: examples/multi-layer/mutli-layer.json

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"id": "figure-id",
3+
"library": "seaborn",
4+
"coordinate": "cartesian",
5+
"layout": {
6+
"rows": 1,
7+
"columns": 1
8+
},
9+
"title": "Average Bill and Tip by Day of Week",
10+
"panels": [
11+
{
12+
"id": "panel-01",
13+
"title": "Bar and Line Chart",
14+
"axes": {
15+
"x": "Day of the Week",
16+
"y": "Amount in USD"
17+
},
18+
"layers": [
19+
{
20+
"type": "bar",
21+
"selector": [],
22+
"data": [
23+
{
24+
"x": "Thur",
25+
"y": 17.68
26+
},
27+
{
28+
"x": "Fri",
29+
"y": 17.15
30+
},
31+
{
32+
"x": "Sat",
33+
"y": 20.44
34+
},
35+
{
36+
"x": "Sun",
37+
"y": 21.41
38+
}
39+
]
40+
},
41+
{
42+
"type": "line",
43+
"selector": [],
44+
"data": [
45+
{
46+
"x": "Thur",
47+
"y": 2.77
48+
},
49+
{
50+
"x": "Fri",
51+
"y": 2.73
52+
},
53+
{
54+
"x": "Sat",
55+
"y": 2.99
56+
},
57+
{
58+
"x": "Sun",
59+
"y": 3.26
60+
}
61+
]
62+
}
63+
]
64+
}
65+
]
66+
}

Diff for: examples/multi-panel/multi-panel-R.r

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Load the required libraries
2+
library(ggplot2)
3+
library(palmerpenguins)
4+
library(svglite)
5+
6+
# Load the penguins dataset
7+
data("penguins")
8+
penguins <- na.omit(penguins)
9+
10+
# Create a ggplot
11+
p <- ggplot(penguins, aes(x = bill_length_mm, y = bill_depth_mm)) +
12+
geom_point() +
13+
facet_grid(species ~ sex) +
14+
labs(
15+
title = "Penguin Bill Dimensions by Species and Sex",
16+
x = "Bill Length (mm)",
17+
y = "Bill Depth (mm)"
18+
) +
19+
theme(
20+
plot.title = element_text(size = 16, hjust = 0.5),
21+
strip.text = element_text(size = 12),
22+
axis.title = element_text(size = 12)
23+
)
24+
25+
# Save the plot as an SVG file using ggsave and svglite
26+
ggsave("multi-panel.svg", plot = p, device = svglite, width = 10, height = 8)
27+
28+
# Extract raw data used for plotting per panel
29+
plot_data <- ggplot_build(p)$data[[1]]
30+
# Split the data by panel
31+
plot_data_split <- split(plot_data, plot_data$PANEL)
32+
33+
# Save each panel data as a separate data frame object
34+
panel_data_list <- lapply(names(plot_data_split), function(panel) {
35+
panel_data <- plot_data_split[[panel]]
36+
assign(paste0("panel_data_", panel), panel_data, envir = .GlobalEnv)
37+
return(panel_data)
38+
})
39+
40+
# Assign names to the list elements for easier reference
41+
names(panel_data_list) <- names(plot_data_split)
42+
43+
# Load the required library for JSON
44+
library(jsonlite)
45+
46+
# Save each panel data as a JSON file containing only x and y variables
47+
lapply(names(panel_data_list), function(panel) {
48+
panel_data <- panel_data_list[[panel]][, c("x", "y")]
49+
json_file <- paste0("panel_data_", panel, ".json")
50+
write_json(panel_data, json_file)
51+
})
52+
53+
54+
55+
# Extract the layout information to get the panel titles
56+
layout_info <- ggplot_build(p)$layout$layout
57+
58+
# Create a data frame that maps panel numbers to species and sex
59+
panel_mapping <- data.frame(
60+
PANEL = layout_info$PANEL,
61+
species = layout_info$species,
62+
sex = layout_info$sex
63+
)
64+
65+
print(panel_mapping)

Diff for: examples/multi-panel/multi-panel-matplotlib.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import matplotlib.pyplot as plt
2+
import seaborn as sns
3+
4+
# Load the penguins dataset using seaborn
5+
penguins = sns.load_dataset("penguins")
6+
7+
# Get unique species and sexes
8+
species = penguins["species"].dropna().unique()
9+
sexes = penguins["sex"].dropna().unique()
10+
11+
# Create a figure and a grid of subplots
12+
fig, axes = plt.subplots(
13+
nrows=len(species), ncols=len(sexes), figsize=(12, 8), sharex=True, sharey=True
14+
)
15+
16+
# Set a global title for the figure
17+
fig.suptitle("Penguin Bill Dimensions by Species and Sex", fontsize=16)
18+
19+
# Loop through species and sexes to create each subplot
20+
for i, sp in enumerate(species):
21+
for j, sex in enumerate(sexes):
22+
ax = axes[i, j]
23+
subset = penguins[(penguins["species"] == sp) & (penguins["sex"] == sex)]
24+
ax.scatter(subset["bill_length_mm"], subset["bill_depth_mm"])
25+
26+
# Set panel-specific titles
27+
ax.set_title(f"{sp} - {sex}", fontsize=12)
28+
29+
# Set x and y labels for the leftmost and bottom plots only
30+
if i == len(species) - 1:
31+
ax.set_xlabel("Bill Length (mm)")
32+
if j == 0:
33+
ax.set_ylabel("Bill Depth (mm)")
34+
35+
# Show the plot
36+
plt.show()

0 commit comments

Comments
 (0)