@danielsimonjr/mathts-plot 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @danielsimonjr/mathts-plot
2
+
3
+ Headless SVG 2D/3D plotting for [MathTS](https://github.com/danielsimonjr/mathts).
4
+
5
+ Pure functions returning self-contained SVG strings — no browser, no canvas, no runtime
6
+ dependencies beyond the MathTS bedrock (`core`/`functions`/`expression`). Every function
7
+ coerces its input and never throws on bad data: empty, `NaN`, or `Infinity` inputs render a
8
+ "no data" placeholder SVG instead of crashing. See
9
+ `docs/superpowers/specs/2026-07-07-plotting-design.md` for the design.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ npm install @danielsimonjr/mathts-plot
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ Every function below returns a self-contained SVG string (`<svg ...>...</svg>`) — render it
20
+ directly in an `<img src="data:image/svg+xml,...">`, write it to a `.svg` file, or drop it
21
+ into HTML.
22
+
23
+ ### `line` — one series, or overlaid with others
24
+
25
+ ```ts
26
+ import { line } from '@danielsimonjr/mathts-plot';
27
+
28
+ const svg = line([0, 1, 2, 3], [0, 1, 4, 9], { title: 'squares', xLabel: 'x', yLabel: 'y' });
29
+ // svg === '<svg ...>...</svg>'
30
+ ```
31
+
32
+ ### `overlay` — combine several layers on shared, auto-scaled axes
33
+
34
+ ```ts
35
+ import { overlay } from '@danielsimonjr/mathts-plot';
36
+
37
+ const svg = overlay(
38
+ [
39
+ { type: 'line', x: [0, 1, 2], y: [0, 1, 2], label: 'model' },
40
+ { type: 'scatter', x: [0, 1, 2], y: [0.1, 1.2, 1.8], label: 'data' },
41
+ ],
42
+ { legend: true }
43
+ );
44
+ ```
45
+
46
+ ### `surface` — 3D surface via orthographic projection + painter's algorithm
47
+
48
+ ```ts
49
+ import { surface } from '@danielsimonjr/mathts-plot';
50
+
51
+ const z = [
52
+ [0, 1, 2],
53
+ [1, 2, 3],
54
+ [2, 3, 4],
55
+ ]; // z[row][col]
56
+ const svg = surface(z, { kind: 'filled', azim: 45, elev: 25 });
57
+ ```
58
+
59
+ ### `plot` — generic, polymorphic entry point (including expression strings)
60
+
61
+ ```ts
62
+ import { plot } from '@danielsimonjr/mathts-plot';
63
+
64
+ // numeric series → line
65
+ plot([0, 1, 4, 9]);
66
+ plot([0, 1, 2, 3], [0, 1, 4, 9]);
67
+
68
+ // expression string, sampled via functions/expression → line
69
+ plot('sin(x)', { from: 0, to: Math.PI, samples: 200 });
70
+
71
+ // two free variables → contour (default) or 3D surface
72
+ plot('x^2 + y^2', { from: -2, to: 2 });
73
+ plot('x^2 + y^2', { from: -2, to: 2, kind: 'surface' });
74
+
75
+ // array of Layer2D → overlay
76
+ plot([
77
+ { type: 'line', x: [0, 1, 2], y: [0, 1, 2] },
78
+ { type: 'scatter', x: [0, 1, 2], y: [0.1, 1.2, 1.8] },
79
+ ]);
80
+ ```
81
+
82
+ ### TikZ / LaTeX output
83
+
84
+ Every function also accepts `{ format: 'tikz' }` (default is `'svg'`), and there's a
85
+ generic `toTikZ()` mirroring `plot()`. The geometry matches the SVG output exactly (a
86
+ deterministic y-flip maps SVG's top-left origin to TikZ's bottom-left); only
87
+ `\usepackage{tikz}` is required to compile the result.
88
+
89
+ ```ts
90
+ import { toTikZ, line, surface } from '@danielsimonjr/mathts-plot';
91
+
92
+ // generic entry point, expression source → line
93
+ const tex = toTikZ('sin(x)', { from: 0, to: Math.PI });
94
+
95
+ // per-type function via the format option
96
+ const tex2 = line([0, 1, 2, 3], [0, 1, 4, 9], { format: 'tikz' });
97
+
98
+ // standalone: false → a bare tikzpicture for \input, not a compilable document
99
+ const z = [
100
+ [0, 1, 2],
101
+ [1, 2, 3],
102
+ [2, 3, 4],
103
+ ];
104
+ const fragment = surface(z, { format: 'tikz', tikz: { standalone: false } });
105
+ ```
106
+
107
+ `toTikZ`/`{ format: 'tikz' }` return a LaTeX string, not SVG. With `standalone`
108
+ (default `true`) the string is a complete `\documentclass{...}` document you can
109
+ compile as-is; `standalone: false` returns just the `tikzpicture` environment, meant
110
+ to be pulled in via `\input{...}` from a larger document.
111
+
112
+ ## What it provides
113
+
114
+ Per-type mark functions, each `(x, y, opts?) => string` unless noted:
115
+
116
+ - **2D**: `line`, `scatter`, `bar`, `area`, `step`, `errorbar(x, y, yerr, opts?)`,
117
+ `quiver(x, y, u, v, opts?)`.
118
+ - **`histogram(data, opts?)`** — bins via `functions.histogram`, then renders bar heights at
119
+ bin centers.
120
+ - **`heatmap(z, opts?)`** — viridis-colored grid, `z` as `z[row][col]`.
121
+ - **`contour(z, opts?)`** — marching squares over a `z[row][col]` grid.
122
+ - **`overlay(layers, opts?)`** — several `Layer2D`s on shared, auto-scaled axes.
123
+ - **3D**: `surface(z, opts?)` (wireframe or painter's-algorithm filled),
124
+ `scatter3d(x, y, z, opts?)`, `curve3d(x, y, z, opts?)` — all projected with an orthographic
125
+ camera (`azim`/`elev`).
126
+ - **`plot(...)`** — generic polymorphic dispatch over numeric series, layer arrays, and
127
+ expression-source strings (evaluated via `@danielsimonjr/mathts-expression` /
128
+ `@danielsimonjr/mathts-functions`).
129
+ - **`viridis(t)`** — the perceptually-uniform colormap used by `heatmap`/`contour`/`surface`,
130
+ exposed for reuse.
131
+
132
+ Notes:
133
+
134
+ - Pure ESM, `strict` TypeScript, no runtime dependencies beyond the MathTS bedrock
135
+ (`core`/`functions`/`expression`).
136
+ - SVG-only in v1 — no PNG/canvas rendering.
137
+ - `workbook` renders its charts through this package (its former private `svg.ts` plotter was
138
+ removed).
139
+
140
+ ## License
141
+
142
+ MIT (c) Daniel Simon Jr.
@@ -0,0 +1,107 @@
1
+ /** Anything the plotter accepts as a data series: numbers, typed arrays, or core values. */
2
+ type Data = unknown;
3
+ /** A 2-D coordinate axis. */
4
+ interface AxisSpec {
5
+ label?: string;
6
+ scale?: 'linear' | 'log';
7
+ }
8
+ /** Options shared by all plot functions (each uses the subset it needs). */
9
+ interface PlotOptions {
10
+ title?: string;
11
+ xLabel?: string;
12
+ yLabel?: string;
13
+ x?: AxisSpec;
14
+ y?: AxisSpec;
15
+ width?: number;
16
+ height?: number;
17
+ theme?: 'light' | 'dark';
18
+ palette?: readonly string[];
19
+ legend?: boolean;
20
+ from?: number;
21
+ to?: number;
22
+ samples?: number;
23
+ kind?: '2d' | '3d' | 'surface';
24
+ scope?: Record<string, unknown>;
25
+ format?: 'svg' | 'tikz';
26
+ tikz?: {
27
+ standalone?: boolean;
28
+ scale?: number;
29
+ };
30
+ }
31
+ /** One drawable 2-D layer for the shared draw2D core / overlay. */
32
+ interface Layer2D {
33
+ type: 'line' | 'scatter' | 'bar' | 'area' | 'step' | 'errorbar' | 'quiver';
34
+ x?: Data;
35
+ y: Data;
36
+ yerr?: Data;
37
+ u?: Data;
38
+ v?: Data;
39
+ label?: string;
40
+ color?: string;
41
+ }
42
+
43
+ /**
44
+ * Generic entry point. Data forms:
45
+ * plot(y, opts?) → line, x = 0..n-1
46
+ * plot(x, y, opts?) → line
47
+ * plot(layers[], opts?) → overlay
48
+ * plot(source, opts?) → expression sampling (line / contour / surface)
49
+ */
50
+ declare function plot(a: unknown, b?: unknown, c?: PlotOptions): string;
51
+ /** Generic TikZ entry — same polymorphism as plot(), forced to the TikZ backend. */
52
+ declare function toTikZ(a: unknown, b?: unknown, c?: PlotOptions): string;
53
+
54
+ /** Public: line chart of one or many series. */
55
+ declare function line(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
56
+ /** Public: scatter plot of one or many series. */
57
+ declare function scatter(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
58
+ /** Public: bar chart of one or many series. */
59
+ declare function bar(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
60
+ /** Public: filled area under one or many series. */
61
+ declare function area(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
62
+ /** Public: step chart (horizontal-then-vertical) of one or many series. */
63
+ declare function step(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
64
+ /** Public: vertical error bars (whisker + point) for one or many series. */
65
+ declare function errorbar(x: Layer2D['x'], y: Layer2D['y'], yerr: Layer2D['yerr'], opts?: PlotOptions): string;
66
+ /** Public: 2-D vector field (arrows) of one or many series. */
67
+ declare function quiver(x: Layer2D['x'], y: Layer2D['y'], u: Layer2D['u'], v: Layer2D['v'], opts?: PlotOptions): string;
68
+
69
+ /** Histogram: bins via functions.histogram, then renders bar heights at bin centers. */
70
+ declare function histogram(data: unknown, opts?: PlotOptions & {
71
+ bins?: number;
72
+ }): string;
73
+
74
+ /** Heatmap of a 2-D grid z[row][col], colored by viridis over the data range. */
75
+ declare function heatmap(z: unknown, opts?: PlotOptions): string;
76
+
77
+ /** Contour plot via marching squares over grid z[row][col]. */
78
+ declare function contour(z: unknown, opts?: PlotOptions & {
79
+ levels?: number;
80
+ }): string;
81
+
82
+ /** Draw several 2-D layers (of any mix of types) on shared auto-scaled axes. */
83
+ declare function overlay(layers: Layer2D[], opts?: PlotOptions): string;
84
+
85
+ /** 3-D surface z[row][col], projected to 2-D SVG. Painter's algorithm for `filled`. */
86
+ declare function surface(z: unknown, opts?: Omit<PlotOptions, 'kind'> & {
87
+ azim?: number;
88
+ elev?: number;
89
+ kind?: 'wireframe' | 'filled';
90
+ }): string;
91
+
92
+ interface P3Opts extends PlotOptions {
93
+ azim?: number;
94
+ elev?: number;
95
+ }
96
+ /** 3-D scatter of (x,y,z) point triples, projected to 2-D SVG. */
97
+ declare function scatter3d(x: unknown, y: unknown, z: unknown, opts?: P3Opts): string;
98
+ /** Parametric 3-D curve through (x,y,z) coordinate arrays. */
99
+ declare function curve3d(x: unknown, y: unknown, z: unknown, opts?: P3Opts): string;
100
+
101
+ /** viridis colormap: t in [0,1] → "#rrggbb". */
102
+ declare function viridis(t: number): string;
103
+
104
+ /** @danielsimonjr/mathts-plot — headless SVG 2D/3D plotting for MathTS. */
105
+ declare const VERSION = "0.2.0";
106
+
107
+ export { type AxisSpec, type Data, type Layer2D, type PlotOptions, VERSION, area, bar, contour, curve3d, errorbar, heatmap, histogram, line, overlay, plot, quiver, scatter, scatter3d, step, surface, toTikZ, viridis };