Skip to content

Commit 025d38d

Browse files
HanSur94claude
andauthored
docs(readme): fix broken examples, correct counts, surface missing features (#209)
* docs(readme): correct widget-type count from 21 to 19 The DashboardWidgetRegistry seeds exactly 19 built-in widget types (verified via DashboardWidgetRegistry.types() in a live session and by counting concrete *Widget.m classes in libs/Dashboard/). The README claimed 21 in three places (badges line, dashboard feature list, and What's in the box). Corrected all three to match the code. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): replace wrong '6 themes' with accurate themes + palettes FastSenseTheme has only 2 distinct presets (light, dark) — the four legacy names (default/industrial/scientific/ocean) all alias to light, and the engine's own error says 'Use light or dark'. The '6' conflated the 2 themes with the 4 separate line-color palettes (vibrant, muted, colorblind, ocean). Replaced '6 themes' with 'light & dark themes, 4 color palettes', verified against a live FastSenseTheme() session. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): fix broken TagRegistry.register calls in Tags example The Tags quickstart called TagRegistry.register(press) with a single argument, which errors at runtime (MATLAB:minrhs — register's signature is register(key, tag)). Verified the original snippet throws and the two-arg form renders cleanly end-to-end in a live MATLAB session. Corrected both calls to pass the tag key: TagRegistry.register('press_a', press) TagRegistry.register('press_high', alarm) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): fix broken dashboard example (Label->Title, MonitorTag->Threshold) The 'Build a dashboard' quickstart errored at runtime in two ways, both verified in a live MATLAB session: 1. 'Label' is not a valid widget option (DashboardWidget:unknownOption). number/gauge/status widgets all document 'Title'. Changed Label->Title. 2. A MonitorTag bound via 'Tag' routes to the Sensor slot (Sensor is a backward-compat alias for Tag), and StatusWidget then reads .Y, which MonitorTag lacks (MATLAB:noSuchMethodOrField 'Y'). StatusWidget's documented contract wires a MonitorTag-backed indicator via 'Threshold'. Changed the status widget to 'Threshold', alarm. Corrected snippet now renders all 4 widgets and round-trips through save/load cleanly (ok=1, 4 widgets reloaded). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): correct examples count (40+ -> 70+) and run_all_examples claim Two inaccuracies in the examples line, both verified against examples/: - '40+ runnable scripts' undercounts — there are 72 example_*.m scripts in the topic dirs (01-basics .. 07-advanced), 82 .m files total. - 'Run them all with run_all_examples' is misleading: run_all_examples executes a hardcoded curated list of 23 examples (prints 'FastSense Examples (23 total)'), not all 72. All 23 curated files exist on disk. Rewrote to '70+ runnable scripts ... run_all_examples plays a guided tour of the highlights.' Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): add missing DerivedTag (5th Tag flavour) The Tags section said 'four flavours' and listed only 4, but there are 5 concrete Tag subclasses (SensorTag, StateTag, MonitorTag, CompositeTag, DerivedTag) — verified via superclasses() in a live session. DerivedTag is the continuous-output counterpart to the 0/1 Monitor/Composite tags; the README's own prose already promised 'derived signals' with no matching table row. - four -> five flavours; added a DerivedTag row (continuous signal from other tags). Verified DerivedTag computes power=V.*I correctly over 1000 pts (matches expected to 1e-9). - tightened CompositeTag's description to '0/1 aggregated from monitors' to distinguish it from the continuous DerivedTag (per CompositeTag's own header). - added DerivedTag to the 'What's in the box' Tag list. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): surface per-widget info popups (flagship dashboard feature) The README listed the dashboard's nested-layout and detach features but omitted per-widget info popups — one of the three flagship features of the Advanced Dashboard work. Every DashboardWidget has a Description ('Doc text shown in a popup when the widget's info (i) button is clicked'); a non-empty Description renders an InfoIconButton that opens a doc popup. Verified in a live render: a widget WITH a Description shows exactly 1 InfoIconButton; a sibling without one shows none. Added 'per-widget info popups' to the dashboard feature line and 'info popups' to the What's-in-the-box Dashboards recap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(readme): rename example variable fp -> fs (FastPlot relic) The quickstart code blocks named the FastSense handle 'fp' — an abbreviation of the project's old name (FastPlot). Renamed both blocks' variable to 'fs' so the front-door examples match the current product name. Verified the renamed '30 seconds in' snippet still renders cleanly (ok=1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 545b4b2 commit 025d38d

1 file changed

Lines changed: 28 additions & 27 deletions

File tree

README.md

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
[![Tests](https://github.com/HanSur94/FastSense/actions/workflows/tests.yml/badge.svg)](https://github.com/HanSur94/FastSense/actions/workflows/tests.yml) [![Benchmark](https://github.com/HanSur94/FastSense/actions/workflows/benchmark.yml/badge.svg)](https://hansur94.github.io/FastSense/dev/bench/) [![codecov](https://codecov.io/gh/HanSur94/FastSense/graph/badge.svg)](https://codecov.io/gh/HanSur94/FastSense) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![MATLAB](https://img.shields.io/badge/MATLAB-R2020b%2B-orange.svg)](https://www.mathworks.com/products/matlab.html) [![Octave](https://img.shields.io/badge/GNU%20Octave-7%2B-blue.svg)](https://octave.org) [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey.svg)](#install)
1010

11-
`100M+ points` · `Tags` · `live event detection` · `21 dashboard widgets` · `no toolboxes`
11+
`100M+ points` · `Tags` · `live event detection` · `19 dashboard widgets` · `no toolboxes`
1212

1313
</div>
1414

@@ -38,10 +38,10 @@ install; % run once: adds paths + builds MEX accelerators
3838
x = linspace(0, 100, 1e7); % 10 million points
3939
y = sin(x) + 0.1 * randn(size(x));
4040
41-
fp = FastSense('Theme', 'dark');
42-
fp.addLine(x, y, 'DisplayName', 'Sensor');
43-
fp.addThreshold(0.8, 'Direction', 'upper', 'ShowViolations', true);
44-
fp.render();
41+
fs = FastSense('Theme', 'dark');
42+
fs.addLine(x, y, 'DisplayName', 'Sensor');
43+
fs.addThreshold(0.8, 'Direction', 'upper', 'ShowViolations', true);
44+
fs.render();
4545
```
4646

4747
That renders in **a few milliseconds and stays at 200+ FPS while you zoom and pan**. MATLAB's built-in `plot()` takes ~3 seconds on the same data and crawls at ~2 FPS. ([benchmarks ↓](#performance))
@@ -50,14 +50,15 @@ That renders in **a few milliseconds and stays at 200+ FPS while you zoom and pa
5050

5151
## The core idea: Tags
5252

53-
Everything in FastSense — sensors, machine states, alarms, derived signals — is a **Tag**. One unified type, four flavours:
53+
Everything in FastSense — sensors, machine states, alarms, derived signals — is a **Tag**. One unified type, five flavours:
5454

55-
| Tag | What it is |
56-
|----------------|-------------------------------------------------------------|
57-
| `SensorTag` | A measured time-series (pressure, temperature, …) |
58-
| `StateTag` | A discrete system state (idle / running / fault, recipe) |
59-
| `MonitorTag` | A derived 0/1 alarm signal — "is this sensor out of spec?" |
60-
| `CompositeTag` | An aggregation of other tags |
55+
| Tag | What it is |
56+
|----------------|--------------------------------------------------------------|
57+
| `SensorTag` | A measured time-series (pressure, temperature, …) |
58+
| `StateTag` | A discrete system state (idle / running / fault, recipe) |
59+
| `MonitorTag` | A derived 0/1 alarm signal — "is this sensor out of spec?" |
60+
| `CompositeTag` | A 0/1 signal aggregated from multiple monitors |
61+
| `DerivedTag` | A continuous signal computed from other tags (power = V × I) |
6162

6263
Tags carry their own metadata (units, criticality, labels) and live in a shared **`TagRegistry`** so every part of the system — plots, dashboards, event detection, the web bridge — speaks the same language.
6364

@@ -68,13 +69,13 @@ press.updateData(t, pressure_data);
6869
% Alarm whenever pressure > 55 bar
6970
alarm = MonitorTag('press_high', press, @(x, y) y > 55);
7071
71-
TagRegistry.register(press);
72-
TagRegistry.register(alarm);
72+
TagRegistry.register('press_a', press);
73+
TagRegistry.register('press_high', alarm);
7374
74-
fp = FastSense();
75-
fp.addTag(press);
76-
fp.addTag(alarm); % overlaid as a 0/1 step trace
77-
fp.render();
75+
fs = FastSense();
76+
fs.addTag(press);
77+
fs.addTag(alarm); % overlaid as a 0/1 step trace
78+
fs.render();
7879
```
7980

8081
The same `alarm` tag drives event detection, lights up status widgets in the dashboard, fires notifications, and shows up in the browser bridge — without you re-declaring the rule four times. For monitors that depend on multiple parents (e.g., a state-conditional alarm), compose them via `CompositeTag`.
@@ -89,17 +90,17 @@ Compose monitoring dashboards from widgets on a 24-column grid. The same Tags dr
8990
d = DashboardEngine('Process Monitor');
9091
d.Theme = 'dark';
9192
d.addWidget('fastsense', 'Position', [1 1 16 8], 'Tag', press);
92-
d.addWidget('number', 'Position', [17 1 8 4], 'Tag', press, 'Label', 'Pressure');
93-
d.addWidget('gauge', 'Position', [17 5 8 4], 'Tag', press, 'Label', 'Live');
94-
d.addWidget('status', 'Position', [1 9 24 2], 'Tag', alarm, 'Label', 'Alarm');
93+
d.addWidget('number', 'Position', [17 1 8 4], 'Tag', press, 'Title', 'Pressure');
94+
d.addWidget('gauge', 'Position', [17 5 8 4], 'Tag', press, 'Title', 'Live');
95+
d.addWidget('status', 'Position', [1 9 24 2], 'Threshold', alarm, 'Title', 'Alarm');
9596
d.render();
9697
9798
d.save('process.json'); % JSON-persist
9899
% later: d = DashboardEngine.load('process.json');
99100
```
100101

101-
- **21 widget types** — plots, numbers, gauges, status lights, gantt timelines, heatmaps, tables, markdown, …
102-
- **Multi-page tabs · collapsible groups · pop-out detached widgets**
102+
- **19 widget types** — plots, numbers, gauges, status lights, gantt timelines, heatmaps, tables, markdown, …
103+
- **Multi-page tabs · collapsible groups · per-widget info popups · pop-out detached widgets**
103104
- **Live mode** — synchronised refresh on a configurable timer
104105
- **Browser bridge**`WebBridge(d).serve()` exposes the dashboard over TCP to a FastAPI + uPlot frontend
105106

@@ -124,10 +125,10 @@ The trick: per-pixel **MinMax** and **LTTB** downsampling (SIMD C kernels with p
124125

125126
## What's in the box
126127

127-
- **Plotting engine** — 100M+ point time-series, 6 themes, linked axes, datetime support, optional MEX SIMD kernels
128-
- **Tag domain model**`SensorTag`, `StateTag`, `MonitorTag`, `CompositeTag`, shared `TagRegistry`
128+
- **Plotting engine** — 100M+ point time-series, light & dark themes, 4 color palettes, linked axes, datetime support, optional MEX SIMD kernels
129+
- **Tag domain model**`SensorTag`, `StateTag`, `MonitorTag`, `CompositeTag`, `DerivedTag`, shared `TagRegistry`
129130
- **Event detection** — group violations into events, statistics, live pipeline, interactive Gantt viewer, notifications
130-
- **Dashboards**21 widget types, JSON persistence, multi-page, collapsible, detachable, live refresh
131+
- **Dashboards**19 widget types, JSON persistence, multi-page, collapsible, info popups, detachable, live refresh
131132
- **Browser bridge** — TCP → FastAPI → uPlot, bidirectional callbacks
132133
- **Disk-backed storage** — SQLite chunks with WAL for live reads, pyramid-cached downsamples
133134
- **Pure MATLAB / Octave** — no toolboxes, no internet, no licenses
@@ -153,7 +154,7 @@ MEX is optional — pure-MATLAB fallbacks kick in if no C compiler is available.
153154

154155
## Examples & docs
155156

156-
40+ runnable scripts in [`examples/`](examples/), grouped by topic (`01-basics``07-advanced`). Run them all with `run_all_examples`.
157+
70+ runnable scripts in [`examples/`](examples/), grouped by topic (`01-basics``07-advanced`). `run_all_examples` plays a guided tour of the highlights.
157158

158159
Full reference lives in the [Wiki](https://github.com/HanSur94/FastSense/wiki): Getting Started · API Reference · Architecture · MEX details · Performance.
159160

0 commit comments

Comments
 (0)