Skip to content

Commit 48973ac

Browse files
author
root
committed
Add complete example coverage
1 parent 7a77914 commit 48973ac

10 files changed

Lines changed: 455 additions & 0 deletions

File tree

.github/workflows/pages.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ jobs:
3030
- name: Install dependencies
3131
run: npm ci
3232

33+
- name: Check example coverage
34+
run: npm run check:examples
35+
3336
- name: Prepare versioned demo asset
3437
run: cp public/demo.js public/demo-${{ github.sha }}.js
3538

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ Search-focused guides:
368368
- `p.set_axis_limits_constraints(...)`, `p.set_axis_zoom_constraints(...)`, `p.set_axis_link(...)`
369369
- `p.hide_next_item()`
370370
- `p.on_perf_stats(callback, interval_ms=500)`
371+
- `p.on_view_change(callback)`
371372
- `p.on_tool_change(callback)`
372373
- `p.on_selection_change(callback)`
373374
- `p.on_select(callback)`

app/page.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ const examples = [
109109
text: "Use the selector, slider, and buttons to verify that heatmaps and colorbar widgets use the active ImPlot colormap.",
110110
code: 'plot.setColormap("Plasma");\nplot.colormapSelector({ label: "Choose map" });\nplot.colormapSlider({ label: "Sample" });',
111111
},
112+
{
113+
id: "advanced-api-plot",
114+
section: "Advanced API",
115+
title: "View, Constraints, Axis Links, Raw Primitives",
116+
text: "A focused API coverage example for view/perf callbacks, manual render scheduling, axis constraints/state/linking, aligned groups, time axes, and direct primitive access.",
117+
code: 'plot.onViewChange(console.log);\nplot.setAxisLimitsConstraints("y1", -1.4, 1.4);\nplot.setAxisLink("x2", "x1");\nplot.primitive("tag_y", { value: 0.85 });',
118+
},
112119
];
113120

114121
export default function Page() {

docs/EXAMPLES.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,50 @@ p.set_view(1000, 5000, float(y.min()), float(y.max()))
265265
p.render()
266266
```
267267

268+
## Advanced API Controls
269+
270+
```python
271+
advanced_view_events = []
272+
advanced_perf_events = []
273+
274+
x = (np.arange(240, dtype=np.float32) * 60.0).astype(np.float32)
275+
y = (0.7 * np.sin(np.arange(240, dtype=np.float32) * 0.08)).astype(np.float32)
276+
y2 = (120 + 35 * np.sin(np.arange(240, dtype=np.float32) * 0.05)).astype(np.float32)
277+
278+
p = ip.Plot(width=1100, height=520, title="Advanced API Controls")
279+
280+
def on_view(plot, view):
281+
advanced_view_events.append(view)
282+
283+
def on_perf(plot, stats):
284+
advanced_perf_events.append(stats)
285+
286+
p.on_view_change(on_view)
287+
p.on_perf_stats(on_perf, interval_ms=500)
288+
p.set_plot_flags(no_legend=False, no_menus=False, no_box_select=False, crosshairs=True)
289+
p.set_subplots_config(rows=1, cols=2, flags=0)
290+
p.set_aligned_group("advanced-api", enabled=True, vertical=True)
291+
p.set_secondary_axes(x2=True, y2=True)
292+
p.set_time_axis("x1")
293+
p.set_axis_state("x2", enabled=True, scale="time")
294+
p.set_axis_state("y2", enabled=True, scale="linear")
295+
p.set_axis_link("x2", "x1")
296+
p.set_axis_limits_constraints("y1", -1.4, 1.4)
297+
p.set_axis_zoom_constraints("x1", 5 * 60, 180 * 60)
298+
p.set_axis_ticks("x1", np.array([0, 1800, 3600, 5400], dtype=np.float32),
299+
labels=["00:00", "00:30", "01:00", "01:30"], keep_default=False)
300+
p.clear_axis_ticks("x2")
301+
302+
p.line("primary", y, x=x, subplot_index=0)
303+
p.line("secondary y2", y2, x=x, y_axis="y2", subplot_index=0)
304+
p.inf_lines("maintenance", np.array([3600, 7200], dtype=np.float32), axis="x", subplot_index=0)
305+
p.tag_y(0.85, label_fmt="tag_y wrapper", round_value=False, subplot_index=0)
306+
p.scatter("linked samples", y[::5], x=x[::5], subplot_index=1)
307+
p.set_view(0, 4 * 3600, -1.25, 1.25)
308+
p.render()
309+
p.show()
310+
```
311+
268312
## Subplots
269313

270314
```python
@@ -301,7 +345,11 @@ def on_tool(plot, payload):
301345
def on_sel(plot, payload):
302346
print("selection:", payload)
303347

348+
def on_view(plot, view):
349+
print("view:", view)
350+
304351
p.on_perf_stats(on_perf, interval_ms=1000)
352+
p.on_view_change(on_view)
305353
p.on_tool_change(on_tool)
306354
p.on_selection_change(on_sel)
307355
p.show()

notebooks/nbimplot_api_gallery.ipynb

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,77 @@
20922092
"al.show()\n"
20932093
]
20942094
},
2095+
{
2096+
"cell_type": "markdown",
2097+
"metadata": {},
2098+
"source": [
2099+
"## Advanced API Controls\n",
2100+
"\n",
2101+
"This section collects the less common control APIs in one runnable example:\n",
2102+
"`on_view_change`, `on_perf_stats`, `set_plot_flags`, `set_axis_state`, `set_time_axis`,\n",
2103+
"`set_axis_limits_constraints`, `set_axis_zoom_constraints`, `set_axis_link`,\n",
2104+
"`set_aligned_group`, custom ticks plus `clear_axis_ticks`, subplots, secondary axes,\n",
2105+
"and lifecycle calls such as `p.render()`, `p.show()`, and `p.close()` when you are done.\n"
2106+
]
2107+
},
2108+
{
2109+
"cell_type": "code",
2110+
"execution_count": null,
2111+
"metadata": {},
2112+
"outputs": [],
2113+
"source": [
2114+
"advanced_view_events = []\n",
2115+
"advanced_perf_events = []\n",
2116+
"\n",
2117+
"x_adv = (np.arange(240, dtype=np.float32) * 60.0).astype(np.float32)\n",
2118+
"y_adv = (0.7 * np.sin(np.arange(240, dtype=np.float32) * 0.08) + 0.25 * np.cos(np.arange(240, dtype=np.float32) * 0.017)).astype(np.float32)\n",
2119+
"y_adv2 = (120 + 35 * np.sin(np.arange(240, dtype=np.float32) * 0.05) + 12 * np.cos(np.arange(240, dtype=np.float32) * 0.19)).astype(np.float32)\n",
2120+
"\n",
2121+
"p = ip.Plot(width=1100, height=520, title=\"Advanced API Controls\")\n",
2122+
"\n",
2123+
"def on_view(plot, view):\n",
2124+
" advanced_view_events.append(view)\n",
2125+
" print(\"view\", view)\n",
2126+
"\n",
2127+
"def on_perf(plot, stats):\n",
2128+
" advanced_perf_events.append(stats)\n",
2129+
"\n",
2130+
"p.on_view_change(on_view)\n",
2131+
"p.on_perf_stats(on_perf, interval_ms=500)\n",
2132+
"p.set_plot_flags(no_legend=False, no_menus=False, no_box_select=False, crosshairs=True)\n",
2133+
"p.set_subplots_config(rows=1, cols=2, flags=0)\n",
2134+
"p.set_aligned_group(\"advanced-api-gallery\", enabled=True, vertical=True)\n",
2135+
"p.set_secondary_axes(x2=True, y2=True)\n",
2136+
"p.set_time_axis(\"x1\")\n",
2137+
"p.set_axis_state(\"x2\", enabled=True, scale=\"time\")\n",
2138+
"p.set_axis_state(\"y2\", enabled=True, scale=\"linear\")\n",
2139+
"p.set_axis_link(\"x2\", \"x1\")\n",
2140+
"p.set_axis_limits_constraints(\"y1\", -1.4, 1.4)\n",
2141+
"p.set_axis_zoom_constraints(\"x1\", 5 * 60, 180 * 60)\n",
2142+
"p.set_axis_label(\"x1\", \"time axis\")\n",
2143+
"p.set_axis_label(\"x2\", \"linked time axis\")\n",
2144+
"p.set_axis_label(\"y1\", \"signal\")\n",
2145+
"p.set_axis_label(\"y2\", \"load\")\n",
2146+
"p.set_axis_format(\"y1\", \"%.2f\")\n",
2147+
"p.set_axis_format(\"y2\", \"%.0f\")\n",
2148+
"\n",
2149+
"ticks = np.array([0, 1800, 3600, 5400, 7200, 9000, 10800, 12600], dtype=np.float32)\n",
2150+
"labels = [\"00:00\", \"00:30\", \"01:00\", \"01:30\", \"02:00\", \"02:30\", \"03:00\", \"03:30\"]\n",
2151+
"p.set_axis_ticks(\"x1\", ticks, labels=labels, keep_default=False)\n",
2152+
"p.set_axis_ticks(\"x2\", ticks, labels=labels, keep_default=False)\n",
2153+
"p.clear_axis_ticks(\"x2\")\n",
2154+
"\n",
2155+
"h = p.line(\"primary\", y_adv, x=x_adv, subplot_index=0, color=\"#1f6f66\", line_weight=2.0)\n",
2156+
"p.line(\"secondary y2\", y_adv2, x=x_adv, y_axis=\"y2\", subplot_index=0, color=\"#b74b2b\", line_weight=1.6)\n",
2157+
"p.inf_lines(\"maintenance windows\", np.array([3600, 7200, 10800], dtype=np.float32), axis=\"x\", subplot_index=0)\n",
2158+
"p.tag_y(0.85, label_fmt=\"tag_y wrapper\", round_value=False, subplot_index=0)\n",
2159+
"p.scatter(\"linked samples\", y_adv[::5], x=x_adv[::5], subplot_index=1, marker=\"diamond\", size=4.0)\n",
2160+
"p.line(\"linked trend\", y_adv, x=x_adv, subplot_index=1, color=\"#3f5f8f\")\n",
2161+
"p.set_view(0, 4 * 3600, -1.25, 1.25)\n",
2162+
"p.render()\n",
2163+
"p.show()\n"
2164+
]
2165+
},
20952166
{
20962167
"cell_type": "markdown",
20972168
"id": "b554df42",

notebooks/nbimplot_colab_complete.ipynb

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,77 @@
21582158
"al.show()\n"
21592159
]
21602160
},
2161+
{
2162+
"cell_type": "markdown",
2163+
"metadata": {},
2164+
"source": [
2165+
"## Advanced API Controls\n",
2166+
"\n",
2167+
"This section collects the less common control APIs in one runnable example:\n",
2168+
"`on_view_change`, `on_perf_stats`, `set_plot_flags`, `set_axis_state`, `set_time_axis`,\n",
2169+
"`set_axis_limits_constraints`, `set_axis_zoom_constraints`, `set_axis_link`,\n",
2170+
"`set_aligned_group`, custom ticks plus `clear_axis_ticks`, subplots, secondary axes,\n",
2171+
"and lifecycle calls such as `p.render()`, `p.show()`, and `p.close()` when you are done.\n"
2172+
]
2173+
},
2174+
{
2175+
"cell_type": "code",
2176+
"execution_count": null,
2177+
"metadata": {},
2178+
"outputs": [],
2179+
"source": [
2180+
"advanced_view_events = []\n",
2181+
"advanced_perf_events = []\n",
2182+
"\n",
2183+
"x_adv = (np.arange(240, dtype=np.float32) * 60.0).astype(np.float32)\n",
2184+
"y_adv = (0.7 * np.sin(np.arange(240, dtype=np.float32) * 0.08) + 0.25 * np.cos(np.arange(240, dtype=np.float32) * 0.017)).astype(np.float32)\n",
2185+
"y_adv2 = (120 + 35 * np.sin(np.arange(240, dtype=np.float32) * 0.05) + 12 * np.cos(np.arange(240, dtype=np.float32) * 0.19)).astype(np.float32)\n",
2186+
"\n",
2187+
"p = ip.Plot(width=1100, height=520, title=\"Advanced API Controls\")\n",
2188+
"\n",
2189+
"def on_view(plot, view):\n",
2190+
" advanced_view_events.append(view)\n",
2191+
" print(\"view\", view)\n",
2192+
"\n",
2193+
"def on_perf(plot, stats):\n",
2194+
" advanced_perf_events.append(stats)\n",
2195+
"\n",
2196+
"p.on_view_change(on_view)\n",
2197+
"p.on_perf_stats(on_perf, interval_ms=500)\n",
2198+
"p.set_plot_flags(no_legend=False, no_menus=False, no_box_select=False, crosshairs=True)\n",
2199+
"p.set_subplots_config(rows=1, cols=2, flags=0)\n",
2200+
"p.set_aligned_group(\"advanced-api-gallery\", enabled=True, vertical=True)\n",
2201+
"p.set_secondary_axes(x2=True, y2=True)\n",
2202+
"p.set_time_axis(\"x1\")\n",
2203+
"p.set_axis_state(\"x2\", enabled=True, scale=\"time\")\n",
2204+
"p.set_axis_state(\"y2\", enabled=True, scale=\"linear\")\n",
2205+
"p.set_axis_link(\"x2\", \"x1\")\n",
2206+
"p.set_axis_limits_constraints(\"y1\", -1.4, 1.4)\n",
2207+
"p.set_axis_zoom_constraints(\"x1\", 5 * 60, 180 * 60)\n",
2208+
"p.set_axis_label(\"x1\", \"time axis\")\n",
2209+
"p.set_axis_label(\"x2\", \"linked time axis\")\n",
2210+
"p.set_axis_label(\"y1\", \"signal\")\n",
2211+
"p.set_axis_label(\"y2\", \"load\")\n",
2212+
"p.set_axis_format(\"y1\", \"%.2f\")\n",
2213+
"p.set_axis_format(\"y2\", \"%.0f\")\n",
2214+
"\n",
2215+
"ticks = np.array([0, 1800, 3600, 5400, 7200, 9000, 10800, 12600], dtype=np.float32)\n",
2216+
"labels = [\"00:00\", \"00:30\", \"01:00\", \"01:30\", \"02:00\", \"02:30\", \"03:00\", \"03:30\"]\n",
2217+
"p.set_axis_ticks(\"x1\", ticks, labels=labels, keep_default=False)\n",
2218+
"p.set_axis_ticks(\"x2\", ticks, labels=labels, keep_default=False)\n",
2219+
"p.clear_axis_ticks(\"x2\")\n",
2220+
"\n",
2221+
"h = p.line(\"primary\", y_adv, x=x_adv, subplot_index=0, color=\"#1f6f66\", line_weight=2.0)\n",
2222+
"p.line(\"secondary y2\", y_adv2, x=x_adv, y_axis=\"y2\", subplot_index=0, color=\"#b74b2b\", line_weight=1.6)\n",
2223+
"p.inf_lines(\"maintenance windows\", np.array([3600, 7200, 10800], dtype=np.float32), axis=\"x\", subplot_index=0)\n",
2224+
"p.tag_y(0.85, label_fmt=\"tag_y wrapper\", round_value=False, subplot_index=0)\n",
2225+
"p.scatter(\"linked samples\", y_adv[::5], x=x_adv[::5], subplot_index=1, marker=\"diamond\", size=4.0)\n",
2226+
"p.line(\"linked trend\", y_adv, x=x_adv, subplot_index=1, color=\"#3f5f8f\")\n",
2227+
"p.set_view(0, 4 * 3600, -1.25, 1.25)\n",
2228+
"p.render()\n",
2229+
"p.show()\n"
2230+
]
2231+
},
21612232
{
21622233
"cell_type": "markdown",
21632234
"id": "b554df42",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"type": "module",
66
"scripts": {
77
"dev": "next dev",
8+
"check:examples": "python3 scripts/check_example_coverage.py",
89
"build": "next build",
910
"start": "next start"
1011
},

packages/web/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,14 @@ Core methods:
9696
- `handle.setData(y, { x })`
9797
- `handle.append(y)`
9898
- `plot.render()`
99+
- `plot.requestRender()` / `plot.draw()`
99100
- `plot.autoscale()`
100101
- `plot.setView(xMin, xMax, yMin, yMax)`
102+
- `plot.getView()`
103+
- `plot.getPerfStats()`
101104
- `plot.dispose()`
105+
- `plot.onViewChange(callback)`
106+
- `plot.onPerfStats(callback)`
102107
- `plot.onHover(callback)`
103108
- `plot.onClick(callback)`
104109
- `plot.onSelection(callback)` / `plot.onSelect(callback)`
@@ -158,6 +163,25 @@ Selection events include the ImPlot rectangle plus per-series x-index ranges fro
158163
WASM. `indicesForSelection(...)` computes exact y-filtered indices only when
159164
called.
160165

166+
## View, Axis, and Perf Controls
167+
168+
```js
169+
plot.setPlotFlags({ noLegend: false, noMenus: false, noBoxSelect: false, crosshairs: true });
170+
plot.setSecondaryAxes({ x2: true, y2: true });
171+
plot.setTimeAxis("x1");
172+
plot.setAxisState("x2", { enabled: true, scale: "time" });
173+
plot.setAxisLink("x2", "x1");
174+
plot.setAxisLimitsConstraints("y1", -1.4, 1.4);
175+
plot.setAxisZoomConstraints("x1", 300, 10800);
176+
plot.setAlignedGroup("advanced-api", { enabled: true, vertical: true });
177+
178+
plot.onViewChange((view) => console.log(view));
179+
plot.onPerfStats((stats) => console.log(stats.frameMs));
180+
console.log(plot.getView(), plot.getPerfStats());
181+
plot.requestRender();
182+
plot.draw();
183+
```
184+
161185
For explicit x coordinates:
162186

163187
```js

0 commit comments

Comments
 (0)