@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 +142 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +1140 -0
- package/package.json +66 -0
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.
|
package/dist/index.d.ts
ADDED
|
@@ -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 };
|