smithkit 0.3.0 → 0.5.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 +324 -37
- package/dist/lib/OptionsValidation.d.ts +16 -0
- package/dist/lib/OptionsValidation.js +172 -0
- package/dist/lib/Smith.d.ts +20 -5
- package/dist/lib/Smith.js +114 -15
- package/dist/lib/appearance/Theme.js +5 -0
- package/dist/lib/grid/CircleLayerControl.d.ts +1 -1
- package/dist/lib/grid/CircleLayerControl.js +10 -8
- package/dist/lib/grid/ConstQCircles.d.ts +1 -0
- package/dist/lib/grid/ConstQCircles.js +5 -0
- package/dist/lib/grid/ConstSwrCircles.d.ts +1 -0
- package/dist/lib/grid/ConstSwrCircles.js +5 -0
- package/dist/lib/grid/GridLayerControl.js +5 -4
- package/dist/lib/grid/LayerControl.d.ts +1 -2
- package/dist/lib/grid/LayerControl.js +1 -10
- package/dist/lib/index.d.ts +3 -2
- package/dist/lib/io/Touchstone.d.ts +13 -7
- package/dist/lib/io/Touchstone.js +146 -46
- package/dist/lib/io/types.d.ts +17 -0
- package/dist/lib/io/types.js +1 -0
- package/dist/lib/layers.d.ts +7 -1
- package/dist/lib/measurements.d.ts +2 -0
- package/dist/lib/options.d.ts +58 -0
- package/dist/lib/options.js +1 -0
- package/dist/lib/rendering/SvgChartRenderer.d.ts +6 -3
- package/dist/lib/rendering/SvgChartRenderer.js +58 -11
- package/dist/lib/rf/RfCalculations.d.ts +3 -1
- package/dist/lib/rf/RfCalculations.js +23 -6
- package/dist/lib/samples.d.ts +5 -1
- package/dist/lib/scales/SmithPeripheralScales.d.ts +5 -0
- package/dist/lib/scales/SmithPeripheralScales.js +20 -1
- package/dist/lib/svg/SvgExporter.d.ts +1 -1
- package/dist/lib/svg/SvgExporter.js +4 -3
- package/dist/lib/svg/export.d.ts +3 -1
- package/dist/lib/traces/SmithData.d.ts +10 -4
- package/dist/lib/traces/SmithData.js +14 -4
- package/dist/lib/traces/TraceBuffer.d.ts +19 -0
- package/dist/lib/traces/TraceBuffer.js +176 -0
- package/dist/lib/traces/TraceLineDetail.d.ts +8 -0
- package/dist/lib/traces/TraceLineDetail.js +52 -0
- package/dist/lib/traces/TraceModel.d.ts +6 -8
- package/dist/lib/traces/TraceModel.js +24 -49
- package/dist/lib/traces/TraceRenderer.d.ts +13 -3
- package/dist/lib/traces/TraceRenderer.js +83 -23
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
**`smithkit`** is a framework-independent JavaScript and TypeScript library for
|
|
4
4
|
interactive SVG Smith charts, RF calculations, and S11 measurement exploration.
|
|
5
5
|
|
|
6
|
-
[Try the interactive demo](https://rosek86.github.io/smithkit/)
|
|
6
|
+
[Try the interactive demo](https://rosek86.github.io/smithkit/) or browse the
|
|
7
|
+
[integration examples](https://rosek86.github.io/smithkit/examples/index.html):
|
|
8
|
+
static charts, marker controls, a 100,000-sample trace, themes, report exports, and lifecycle cleanup.
|
|
9
|
+
Each example includes its TypeScript source.
|
|
10
|
+
|
|
11
|
+
Upgrading from 0.3.x? Version 0.4.0 introduces grouped constructor options and
|
|
12
|
+
`setOptions()`, static chart defaults, and explicit marker creation. See the
|
|
13
|
+
[0.4 migration guide](https://github.com/rosek86/smithkit/blob/v0.4.0/docs/migration-0.4.md).
|
|
7
14
|
|
|
8
15
|
Upgrading from 0.2.x? Version 0.3.0 replaces `GridLayer.setMinorVisible()` with
|
|
9
16
|
`setDetail('basic' | 'standard' | 'detailed')`. Replace `false` with `'standard'`
|
|
@@ -13,6 +20,10 @@ Upgrading from 0.1.x? Version 0.2.0 groups calculation, parsing, formatting, and
|
|
|
13
20
|
comparison functions into classes. See the [migration guide](https://github.com/rosek86/smithkit/blob/v0.2.0/docs/migration-0.2.md)
|
|
14
21
|
for the changed imports.
|
|
15
22
|
|
|
23
|
+
The [API review and compatibility policy](https://github.com/rosek86/smithkit/blob/main/docs/api-review.md)
|
|
24
|
+
define the public contract and the compatibility scope intended for 1.0. During
|
|
25
|
+
0.x development, breaking changes are documented in minor releases.
|
|
26
|
+
|
|
16
27
|
## Features
|
|
17
28
|
|
|
18
29
|
- Labeled resistance, reactance, conductance, and susceptance grids.
|
|
@@ -23,7 +34,7 @@ for the changed imports.
|
|
|
23
34
|
- Physical impedance/admittance conversions and DOM-independent RF readings.
|
|
24
35
|
- Twelve parameter scales mounted independently of chart zoom.
|
|
25
36
|
- Four peripheral rulers for phase and electrical length.
|
|
26
|
-
-
|
|
37
|
+
- Touchstone 1.x `.s1p` / `.s2p` reflection import (RI/MA/DB), packed output, and `.s1p` export.
|
|
27
38
|
- Standalone SVG and configurable PNG export of the chart and radial scales.
|
|
28
39
|
- ESM modules and TypeScript declarations.
|
|
29
40
|
|
|
@@ -54,7 +65,7 @@ Give the container an explicit size and run the code after it is mounted:
|
|
|
54
65
|
```ts
|
|
55
66
|
import { Smith } from 'smithkit';
|
|
56
67
|
|
|
57
|
-
const chart = new Smith(50); // Reference impedance in ohms; defaults to 50.
|
|
68
|
+
const chart = new Smith({ referenceImpedanceOhms: 50 }); // Reference impedance in ohms; defaults to 50.
|
|
58
69
|
chart.draw('#smith');
|
|
59
70
|
const traceId = chart.addTrace(
|
|
60
71
|
[
|
|
@@ -71,33 +82,202 @@ coefficient Γ as `[real, imaginary]`. Samples are copied and validated; readonl
|
|
|
71
82
|
must be finite and non-negative; both coordinates must be finite. A trace must
|
|
72
83
|
contain at least one sample.
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
Traces start without markers. Call `chart.addMarker(traceId)` to add one at the
|
|
86
|
+
first sample, or pass a sample index to choose its initial position. Drag markers to select
|
|
87
|
+
samples with a mouse or touch. Enable zoom to scroll to zoom and drag the chart to pan. Markers
|
|
76
88
|
and their focus indicators stay above grid labels and sample points. `chart.resetView()` restores the initial view, including peripheral rulers.
|
|
77
89
|
|
|
78
90
|
Construct `Smith` only in a browser, such as your framework's mount hook. Importing
|
|
79
91
|
the package and using its calculation or parsing methods does not require a DOM.
|
|
80
92
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
page scrolling. Disabling during an active gesture freezes the view while that
|
|
87
|
-
gesture finishes normally.
|
|
93
|
+
The default chart is a static presentation: standard impedance grid with labels,
|
|
94
|
+
no peripheral scales, and zoom and cursor tracking disabled. Markers are optional
|
|
95
|
+
and remain interactive when explicitly added.
|
|
96
|
+
|
|
97
|
+
Enable interactions through constructor options or the corresponding setters:
|
|
88
98
|
|
|
89
99
|
```ts
|
|
90
100
|
import { Smith } from 'smithkit';
|
|
91
101
|
|
|
92
|
-
const chart = new Smith(
|
|
93
|
-
chart.setZoomEnabled(false);
|
|
102
|
+
const chart = new Smith({ interaction: { zoom: true, cursor: true } });
|
|
94
103
|
chart.draw('#smith');
|
|
104
|
+
|
|
105
|
+
chart.setZoomEnabled(false); // Freeze the current view; page scrolling is unaffected.
|
|
106
|
+
chart.setCursorEnabled(false); // Hide cursor geometry and cancel pending readings.
|
|
95
107
|
```
|
|
96
108
|
|
|
109
|
+
Zoom controls wheel/double-click zoom and mouse/touch panning and pinch gestures;
|
|
110
|
+
it is independent of cursor tracking and marker interaction. `resetView()` remains
|
|
111
|
+
available with zoom disabled. Disabling during an active gesture freezes the view
|
|
112
|
+
while that gesture finishes normally.
|
|
113
|
+
|
|
114
|
+
Cursor tracking controls the cursor overlay and `Cursor` events. Disabling it
|
|
115
|
+
clears the current readout with one `Cursor` event carrying `undefined`, cancels
|
|
116
|
+
queued readings, and suppresses further cursor events. Enabling waits for a new
|
|
117
|
+
pointer movement. The last `cursorReading` remains available; marker controls and
|
|
118
|
+
events work independently.
|
|
119
|
+
|
|
97
120
|
`draw(selector | HTMLElement)` moves the existing SVG when called again. A missing
|
|
98
121
|
container throws. Call `chart.destroy()` on unmount; it removes the SVG, releases
|
|
99
122
|
event handlers, and cancels queued notifications. Repeated destruction is safe.
|
|
100
123
|
|
|
124
|
+
## Trace input formats
|
|
125
|
+
|
|
126
|
+
`addTrace()` and `updateTrace()` accept the same `TraceInput` union:
|
|
127
|
+
|
|
128
|
+
- `TraceSamples`: an array of objects with `frequencyHz` and `reflectionCoefficient`.
|
|
129
|
+
- `readonly TraceTuple[]`: `[frequencyHz, re, im]` tuples, including `as const` arrays.
|
|
130
|
+
- `Float64Array`: packed triples in the order `f, re, im, f, re, im, …`.
|
|
131
|
+
|
|
132
|
+
In every format, frequency is in **Hz** and `re`/`im` are the dimensionless
|
|
133
|
+
voltage reflection coefficient **Γ**, relative to the chart's reference impedance.
|
|
134
|
+
A single input must use one format throughout; mixed tuples and objects are rejected.
|
|
135
|
+
Typed-array views are supported; only values inside the supplied view are copied.
|
|
136
|
+
The packed length must be a positive multiple of three. All formats use the same
|
|
137
|
+
finite-value checks and retain input order, duplicate frequencies, and full sample precision.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { Smith, type TraceTuple } from 'smithkit';
|
|
141
|
+
|
|
142
|
+
const chart = new Smith();
|
|
143
|
+
chart.draw('#smith');
|
|
144
|
+
const samples: readonly TraceTuple[] = [
|
|
145
|
+
[1e9, 0.4, -0.4],
|
|
146
|
+
[1.5e9, 0, 0],
|
|
147
|
+
[2e9, 0.4, 0.4],
|
|
148
|
+
];
|
|
149
|
+
const traceId = chart.addTrace(samples, { name: 'S11', mode: 'line' });
|
|
150
|
+
|
|
151
|
+
// A later update may use a different format. Each triple is one sample.
|
|
152
|
+
chart.updateTrace(traceId, new Float64Array([1e9, 0.3, -0.3, 1.5e9, 0, 0, 2e9, 0.3, 0.3]));
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
For large datasets, fill the packed array directly to avoid creating intermediate
|
|
156
|
+
objects or tuples:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import { Smith } from 'smithkit';
|
|
160
|
+
|
|
161
|
+
const count = 100_000;
|
|
162
|
+
const samples = new Float64Array(count * 3);
|
|
163
|
+
for (let i = 0; i < count; i++) {
|
|
164
|
+
samples[3 * i] = 1e9 + i * 1e4;
|
|
165
|
+
samples[3 * i + 1] = 0.7 * Math.cos((i / count) * 10);
|
|
166
|
+
samples[3 * i + 2] = 0.7 * Math.sin((i / count) * 10);
|
|
167
|
+
}
|
|
168
|
+
const chart = new Smith();
|
|
169
|
+
chart.draw('#smith');
|
|
170
|
+
const traceId = chart.addTrace(samples, { mode: 'points' });
|
|
171
|
+
chart.addMarker(traceId, count - 1);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
All inputs are copied into owned packed storage (24 bytes per sample for the numeric
|
|
175
|
+
payload). Modifying the input after adding or updating a trace does not change the
|
|
176
|
+
chart. Marker readings and events keep their existing object shape. `Touchstone.parse()` returns object samples by default, or packed triples with
|
|
177
|
+
`output: 'packed'`. `RfCalculations.renormalizeSamples()` preserves object or packed
|
|
178
|
+
representation.
|
|
179
|
+
Invalid replacements leave data, markers, and rendering unchanged.
|
|
180
|
+
|
|
181
|
+
For more than 5,000 samples, point rendering groups overlapping points into screen
|
|
182
|
+
cells and skips offscreen points; markers still select from the full data. Lines
|
|
183
|
+
retain every sample, so very large SVG paths can remain expensive to render and export.
|
|
184
|
+
Sorted ascending frequencies accelerate frequency selection; unsorted inputs remain
|
|
185
|
+
supported without reordering. There is no automatic interpolation or data reduction.
|
|
186
|
+
|
|
187
|
+
## Constructor configuration
|
|
188
|
+
|
|
189
|
+
`new Smith(options?)` accepts a typed `SmithOptions` object. Every field is optional:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { Smith } from 'smithkit';
|
|
193
|
+
|
|
194
|
+
const chart = new Smith({
|
|
195
|
+
referenceImpedanceOhms: 75,
|
|
196
|
+
appearance: { theme: 'dark' },
|
|
197
|
+
interaction: { zoom: false },
|
|
198
|
+
peripheralScales: { visible: false },
|
|
199
|
+
grid: {
|
|
200
|
+
detail: 'basic',
|
|
201
|
+
labelsVisible: true,
|
|
202
|
+
style: { majorWidth: 1.5 },
|
|
203
|
+
layers: {
|
|
204
|
+
resistance: { style: { stroke: '#60a5fa' } },
|
|
205
|
+
reactance: { labelsVisible: false },
|
|
206
|
+
conductance: { visible: true, detail: 'standard' },
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
circles: {
|
|
210
|
+
q: { visible: true, values: [1, 2, 5] },
|
|
211
|
+
vswr: { visible: true, values: [2, 3], style: { stroke: '#fbbf24' } },
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
chart.draw('#smith');
|
|
215
|
+
|
|
216
|
+
// Update all four grids together, including hidden admittance layers.
|
|
217
|
+
chart.setGridDetail('standard');
|
|
218
|
+
// Individual overrides remain available.
|
|
219
|
+
chart.layers.reactance.setDetail('basic');
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Configuration is grouped by responsibility:
|
|
223
|
+
|
|
224
|
+
| Group | Purpose | Runtime API |
|
|
225
|
+
| ------------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
226
|
+
| `referenceImpedanceOhms` | Physical reference impedance | `renormalize()` |
|
|
227
|
+
| `appearance` | Theme, fonts, colors, marker/cursor styling | `setAppearance()` |
|
|
228
|
+
| `interaction` | `zoom` and `cursor` tracking switches | `setZoomEnabled()`, `setCursorEnabled()` |
|
|
229
|
+
| `grid` | Shared detail, labels, styles; `layers` overrides for resistance/reactance/conductance/susceptance | `setGridDetail()`, `layers.resistance` and the other grid controls |
|
|
230
|
+
| `circles` | Independent Q and VSWR values, visibility, styles | `layers.q`, `layers.vswr` |
|
|
231
|
+
| `peripheralScales` | Visibility of all peripheral rulers together | `peripheralScales.setVisible()` |
|
|
232
|
+
|
|
233
|
+
Defaults are 50 Ω, the light theme, zoom and cursor disabled, peripheral scales hidden,
|
|
234
|
+
and standard grids with labels. Resistance/reactance are visible;
|
|
235
|
+
conductance/susceptance and Q/VSWR circles are hidden. Q defaults to
|
|
236
|
+
`[0.5, 1, 2, 5, 10]`; VSWR defaults to `[1.2, 1.5, 2, 3, 5, 10]`.
|
|
237
|
+
|
|
238
|
+
Shared `grid` settings apply to all four grids; `grid.layers` overrides individual
|
|
239
|
+
fields afterward. Styles merge by property. Explicit layer styles override theme
|
|
240
|
+
colors and remain in effect when `setAppearance()` changes the theme.
|
|
241
|
+
Options and circle arrays are copied; changing the original object does not update
|
|
242
|
+
the chart. Use the existing chart/layer methods for later changes. Unknown constructor groups
|
|
243
|
+
or structural option names throw `TypeError`; omitted fields use defaults.
|
|
244
|
+
|
|
245
|
+
Export configuration belongs to `toSvg()`/`toPng()` calls, independently of chart
|
|
246
|
+
construction. `scaleReadout` requires `scales`; otherwise export throws/rejects with `TypeError`.
|
|
247
|
+
|
|
248
|
+
The constructor configures presentation and interaction. Add measurement data with
|
|
249
|
+
`addTrace()` and optional markers with `addMarker()`; no markers are created implicitly.
|
|
250
|
+
Radial parameter scales remain independently mounted `SmithScales` instances.
|
|
251
|
+
|
|
252
|
+
### Updating configuration
|
|
253
|
+
|
|
254
|
+
`chart.setOptions(options)` accepts the same `SmithOptions` type as the constructor:
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
chart.setOptions({
|
|
258
|
+
interaction: { zoom: true },
|
|
259
|
+
grid: {
|
|
260
|
+
detail: 'basic',
|
|
261
|
+
layers: { reactance: { labelsVisible: false } },
|
|
262
|
+
},
|
|
263
|
+
circles: { vswr: { visible: true, values: [2, 3] } },
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
This is a patch: omitted and `undefined` fields retain their current values;
|
|
268
|
+
`{}` groups do nothing. Shared grid settings apply to all four grids first, then
|
|
269
|
+
per-layer overrides in the same call. A later shared setting also replaces that
|
|
270
|
+
field on previously customized layers. Style fields merge; circle value lists
|
|
271
|
+
replace. `appearance`, when provided, replaces the preset/overrides exactly like
|
|
272
|
+
`setAppearance()` (it is not recursively merged with the previous appearance).
|
|
273
|
+
|
|
274
|
+
The complete patch is validated before application. Invalid settings or impossible
|
|
275
|
+
reference conversions leave the chart unchanged. `referenceImpedanceOhms` invokes
|
|
276
|
+
renormalization of existing traces and retains physical impedance and marker IDs.
|
|
277
|
+
Other configuration updates preserve measurements, markers, selection, and view.
|
|
278
|
+
Options are not retained; subsequent edits to the input object have no effect.
|
|
279
|
+
Individual setters remain available for focused changes.
|
|
280
|
+
|
|
101
281
|
### Keyboard and touch markers
|
|
102
282
|
|
|
103
283
|
Use Tab/Shift+Tab to focus a marker. Arrow keys move through samples in input order;
|
|
@@ -124,7 +304,7 @@ there. They survive renaming, hiding, updating samples, and removing other items
|
|
|
124
304
|
They are not persistent across chart instances or page reloads.
|
|
125
305
|
|
|
126
306
|
```ts
|
|
127
|
-
const markerA = chart.
|
|
307
|
+
const markerA = chart.addMarker(traceId)!; // First sample.
|
|
128
308
|
const markerB = chart.addMarker(traceId, 2)!; // Zero-based sample index.
|
|
129
309
|
|
|
130
310
|
chart.setTraceOptions(traceId, { name: 'Tuned antenna', visible: true });
|
|
@@ -141,7 +321,7 @@ chart.removeMarker(markerB);
|
|
|
141
321
|
|
|
142
322
|
| Method | Result / behavior |
|
|
143
323
|
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
144
|
-
| `addTrace(samples, options?)` | Returns a trace ID. Options: nonblank `name`, solid CSS `color`, and `visible`.
|
|
324
|
+
| `addTrace(samples, options?)` | Returns a trace ID, without creating markers. Options: nonblank `name`, solid CSS `color`, and `visible`. |
|
|
145
325
|
| `getTraces()` | Detached `TraceInfo` snapshots: ID, name, color, visibility, sample count, and marker metadata. |
|
|
146
326
|
| `setTraceOptions(id, options)` | Updates the supplied options only. Invalid options throw before any change. |
|
|
147
327
|
| `updateTrace(id, samples, options?)` | Replaces samples and preserves identity, appearance, and markers. Empty/invalid input throws without changing the trace. |
|
|
@@ -191,21 +371,41 @@ after destruction throw; trace/marker lookups return empty or missing results.
|
|
|
191
371
|
|
|
192
372
|
## Trace appearance
|
|
193
373
|
|
|
194
|
-
Pass `mode: 'points' | 'line' | 'both'`, `lineWidth`, and `
|
|
374
|
+
Pass `mode: 'points' | 'line' | 'both'`, `lineWidth`, `pointRadius`, and `lineTolerancePx` to
|
|
195
375
|
`addTrace` or `setTraceOptions`. Defaults are points, 2 px line width, and 2 px point radius. Both sizes are
|
|
196
376
|
CSS pixels and remain constant under chart zoom and container resize. Widths and radii must be positive and finite.
|
|
197
377
|
`getTraces()` includes the current style.
|
|
198
378
|
|
|
199
|
-
|
|
379
|
+
By default, lines connect all samples in input order, without smoothing or frequency sorting.
|
|
200
380
|
A line-only trace creates one SVG path and no sample circles, suitable for dense
|
|
201
381
|
sweeps. Points/both render every sample for traces up to 5,000 samples. Larger traces
|
|
202
382
|
render one representative per point-radius-sized display cell and skip points
|
|
203
383
|
outside the viewport; representatives are recalculated during zoom/pan.
|
|
204
384
|
This only simplifies the image: all original samples remain available to markers,
|
|
205
|
-
snapping, readouts, and comparisons.
|
|
385
|
+
snapping, readouts, and comparisons.
|
|
206
386
|
Styles do not change marker identity or layer ordering. Hidden traces retain their style after sample replacement.
|
|
207
387
|
The demo exposes the same controls per trace.
|
|
208
388
|
|
|
389
|
+
For dense lines, opt into `lineTolerancePx` (finite, non-negative; default `0` disables
|
|
390
|
+
simplification):
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
chart.setTraceOptions(traceId, { mode: 'line', lineTolerancePx: 0.5 });
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
The tolerance bounds additional geometric deviation in **CSS pixels**, accounting for
|
|
397
|
+
chart zoom and container size. It does not include SVG coordinate rounding or browser
|
|
398
|
+
antialiasing. Cached, nested geometry levels retain endpoints and input order; zooming
|
|
399
|
+
in selects finer geometry, while panning reuses the current level. The cache is rebuilt
|
|
400
|
+
when samples change, including reference-impedance renormalization. Markers, frequency
|
|
401
|
+
selection, RF calculations, and sample counts always use the full data. The option
|
|
402
|
+
applies to the line in `line` and `both` modes; point rendering is unchanged.
|
|
403
|
+
|
|
404
|
+
Preparing levels takes extra CPU and memory, and noisy traces may simplify very little.
|
|
405
|
+
This is an opt-in display optimization, not data compression. See the
|
|
406
|
+
[large-trace example](https://rosek86.github.io/smithkit/examples/large-trace/) to compare
|
|
407
|
+
full geometry with pixel tolerances and [local measurements](docs/performance.md).
|
|
408
|
+
|
|
209
409
|
## Events and readings
|
|
210
410
|
|
|
211
411
|
`onEvent(listener)` supports multiple independent subscriptions and returns an
|
|
@@ -240,8 +440,8 @@ queued `Marker` event and do not emit drag lifecycle events.
|
|
|
240
440
|
Cursor movement is suspended during marker dragging. Drag start/end events fire
|
|
241
441
|
synchronously; marker position notifications are queued and report the latest
|
|
242
442
|
snapshot at delivery. Before delivery, repeated updates to the same marker coalesce
|
|
243
|
-
into one notification; different markers have independent notifications.
|
|
244
|
-
queues an initial marker notification too. Removed markers cannot deliver queued
|
|
443
|
+
into one notification; different markers have independent notifications. `addMarker()`
|
|
444
|
+
queues an initial marker notification too; `addTrace()` does not. Removed markers cannot deliver queued
|
|
245
445
|
position events.
|
|
246
446
|
Trace metadata changes do not emit marker events; refresh metadata after mutations.
|
|
247
447
|
Destruction suppresses application callbacks.
|
|
@@ -368,7 +568,7 @@ const appearance: SmithAppearance = {
|
|
|
368
568
|
traceColors: ['#38bdf8', '#fb923c', '#a78bfa'],
|
|
369
569
|
},
|
|
370
570
|
};
|
|
371
|
-
const chart = new Smith(50, appearance);
|
|
571
|
+
const chart = new Smith({ referenceImpedanceOhms: 50, appearance });
|
|
372
572
|
const scales = new SmithScales(appearance);
|
|
373
573
|
chart.draw('#smith');
|
|
374
574
|
scales.draw('#scales');
|
|
@@ -437,12 +637,13 @@ layout raises it when needed to keep the font size at least 9 CSS pixels in the
|
|
|
437
637
|
default view. Partial updates retain other settings. Invalid numeric styles throw
|
|
438
638
|
before any property is changed.
|
|
439
639
|
|
|
440
|
-
|
|
640
|
+
Use `chart.setGridDetail('basic' | 'standard' | 'detailed')` for all four grid layers,
|
|
641
|
+
or `layer.setDetail(...)` to override one layer:
|
|
441
642
|
|
|
442
643
|
- **Basic:** complete circles and arcs for normalized values 0.2, 0.5, 1, 2, and 5,
|
|
443
644
|
with matching axis/rim labels and the zero label. Intended for small or static charts.
|
|
444
|
-
- **Standard
|
|
445
|
-
- **Detailed
|
|
645
|
+
- **Standard** (default): the full major grid and its labels, without minor lines.
|
|
646
|
+
- **Detailed:** the full major and minor grid.
|
|
446
647
|
|
|
447
648
|
Changing detail preserves layer visibility, styles, and the current view. Label
|
|
448
649
|
collision handling still applies at every level. Peripheral scales and Q/VSWR
|
|
@@ -455,7 +656,10 @@ whole-layer visibility changes and is included in SVG exports. Calling
|
|
|
455
656
|
layout; it does not show a hidden layer. The **Grid labels** checkbox in the demo’s **Chart settings** dialog controls all four grid layers together. Peripheral scale labels are unaffected.
|
|
456
657
|
|
|
457
658
|
`layers.q` and `layers.vswr` support `setVisible`,
|
|
458
|
-
`setStyle({ stroke?, strokeWidth? })`, `addValue`, and `removeValue`.
|
|
659
|
+
`setStyle({ stroke?, strokeWidth? })`, `setValues`, `addValue`, and `removeValue`.
|
|
660
|
+
`setValues([1, 2, 5])` replaces the entire list; `setValues([])` clears it.
|
|
661
|
+
Input arrays are copied, duplicate values are ignored, and invalid input leaves
|
|
662
|
+
the previous values unchanged.
|
|
459
663
|
Circle stroke widths are positive finite numbers in CSS pixels.
|
|
460
664
|
Q values must be positive and finite; VSWR values must be finite and at least 1.
|
|
461
665
|
Duplicate additions and removal of absent values have no effect.
|
|
@@ -515,7 +719,32 @@ assumes a matched line or attenuator terminated in an open or short: the reflect
|
|
|
515
719
|
wave traverses it twice. It does not measure insertion loss of an arbitrary load
|
|
516
720
|
from S11 alone. At \|Γ\| = 0.1 it reads 10 dB, while return loss reads 20 dB.
|
|
517
721
|
|
|
518
|
-
|
|
722
|
+
Peripheral rulers are hidden by default. Enable them with
|
|
723
|
+
`{ peripheralScales: { visible: true } }` or `chart.peripheralScales.setVisible(true)`.
|
|
724
|
+
Axis captions and numeric tick labels can be controlled independently, through the
|
|
725
|
+
constructor, `setOptions()`, or the peripheral scale controls:
|
|
726
|
+
|
|
727
|
+
```ts
|
|
728
|
+
import { Smith } from 'smithkit';
|
|
729
|
+
|
|
730
|
+
const chart = new Smith({
|
|
731
|
+
peripheralScales: { visible: true, captionsVisible: false, tickLabelsVisible: true },
|
|
732
|
+
});
|
|
733
|
+
chart.draw('#smith');
|
|
734
|
+
|
|
735
|
+
chart.setOptions({ peripheralScales: { captionsVisible: true } });
|
|
736
|
+
chart.peripheralScales.setTickLabelsVisible(false); // Captions and rulers remain visible.
|
|
737
|
+
chart.peripheralScales.setCaptionsVisible(false); // Rulers and indicators remain visible.
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
Both text options default to `true`; the entire group remains hidden by default.
|
|
741
|
+
When captions are hidden, numeric labels fill the sectors normally reserved for them.
|
|
742
|
+
Hiding/re-showing the rulers preserves both preferences. Text controls do not affect
|
|
743
|
+
ruler lines, ticks, indicators, grid labels, or the independent radial parameter scales.
|
|
744
|
+
SVG/PNG exports preserve the current text visibility. The demo exposes **Axis captions**
|
|
745
|
+
and **Tick values** checkboxes in **Chart settings**.
|
|
746
|
+
|
|
747
|
+
`chart.peripheralScales.update(Complex | null)` supplies or clears the indicators.
|
|
519
748
|
Its four rulers zoom with the chart: reflection phase, voltage transmission phase,
|
|
520
749
|
wavelengths toward generator, and wavelengths toward load. Wavelength rulers start
|
|
521
750
|
at the negative real axis, with 0.5 λ per revolution (generator clockwise, load
|
|
@@ -554,28 +783,81 @@ Import renormalization is enabled by a labeled checkbox. Disable it to reject
|
|
|
554
783
|
files whose reference differs from the chart. Complex reference impedances and
|
|
555
784
|
multiport renormalization are outside the supported scope.
|
|
556
785
|
|
|
557
|
-
## Touchstone import
|
|
786
|
+
## Touchstone import and export
|
|
787
|
+
|
|
788
|
+
`Touchstone.parse(text, options?)` returns `{ samples, referenceImpedanceOhms }`.
|
|
789
|
+
It reads Touchstone 1.x S-parameters, converts RI/MA/DB into Cartesian Γ and
|
|
790
|
+
frequencies into Hz, and throws an `Error` with a line number for invalid content.
|
|
791
|
+
Invalid parser options throw `TypeError`.
|
|
558
792
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
793
|
+
| Option | Default | Meaning |
|
|
794
|
+
| ----------- | ----------- | -------------------------------------------------------------------------------- |
|
|
795
|
+
| `ports` | `1` | Source port count: `1` for `.s1p`, `2` for `.s2p`. It is not inferred from text. |
|
|
796
|
+
| `parameter` | `'S11'` | Reflection parameter: `'S11'` or, with two ports, `'S22'`. |
|
|
797
|
+
| `output` | `'objects'` | Object samples or `'packed'` `Float64Array` containing f/re/im triples. |
|
|
562
798
|
|
|
563
799
|
```ts
|
|
564
800
|
import { Smith, Touchstone } from 'smithkit';
|
|
565
801
|
|
|
566
802
|
async function showMeasurement(file: File): Promise<Smith> {
|
|
567
|
-
const
|
|
568
|
-
const
|
|
803
|
+
const ports = /\.s2p$/i.test(file.name) ? 2 : 1;
|
|
804
|
+
const { samples, referenceImpedanceOhms } = Touchstone.parse(await file.text(), {
|
|
805
|
+
ports,
|
|
806
|
+
parameter: ports === 2 ? 'S22' : 'S11',
|
|
807
|
+
output: 'packed',
|
|
808
|
+
});
|
|
809
|
+
const chart = new Smith({ referenceImpedanceOhms });
|
|
569
810
|
chart.draw('#smith');
|
|
570
811
|
chart.addTrace(samples, { name: file.name });
|
|
571
812
|
return chart;
|
|
572
813
|
}
|
|
573
814
|
```
|
|
574
815
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
816
|
+
Packed parsing writes directly into growing typed storage, without creating an
|
|
817
|
+
object or coordinate array per sample. It scans lines incrementally within the
|
|
818
|
+
supplied string; this is not a streaming file API. The returned buffer has exact
|
|
819
|
+
length and is caller-owned. The default object result remains unchanged.
|
|
820
|
+
|
|
821
|
+
Omitted header options use GHz, S, MA, 50 Ω. The parser accepts comments, BOM,
|
|
822
|
+
LF/CRLF/CR line endings, decimal scientific notation, and continued records. Each
|
|
823
|
+
frequency record starts on a new line. Two-port records use S11, S21, S12, S22
|
|
824
|
+
order; all four parameters are validated even though only one reflection trace is
|
|
825
|
+
returned. Two-port frequencies must increase strictly. Three or more ports,
|
|
826
|
+
per-port/complex reference impedances, noise blocks and Touchstone 2.x keywords
|
|
827
|
+
are rejected. See the [IBIS Touchstone specification](https://www.ibis.org/touchstone_ver2.1/touchstone_ver2_1.pdf)
|
|
828
|
+
for the legacy 1.x data layout.
|
|
829
|
+
|
|
830
|
+
`Touchstone.stringify(samples, { referenceImpedanceOhms })` returns `.s1p` text
|
|
831
|
+
with a `# Hz S RI R …` header and a final newline. It accepts object samples,
|
|
832
|
+
tuples, or packed triples, writes numeric values without a precision limit, and
|
|
833
|
+
does not modify or renormalize the input. The reference defaults to 50 Ω; supply
|
|
834
|
+
the actual reference of your data. Empty/invalid samples, nonpositive/nonfinite
|
|
835
|
+
reference impedance, and duplicate or descending frequencies throw `RangeError`.
|
|
836
|
+
Samples are never silently sorted or discarded.
|
|
837
|
+
|
|
838
|
+
```ts
|
|
839
|
+
import { RfCalculations, Touchstone } from 'smithkit';
|
|
840
|
+
|
|
841
|
+
const sourceText = '# GHz S RI R 50\n1 0 0\n2 0.5 0';
|
|
842
|
+
const parsed = Touchstone.parse(sourceText, { output: 'packed' });
|
|
843
|
+
const samples = RfCalculations.renormalizeSamples(
|
|
844
|
+
parsed.samples,
|
|
845
|
+
parsed.referenceImpedanceOhms,
|
|
846
|
+
75,
|
|
847
|
+
);
|
|
848
|
+
const text = Touchstone.stringify(samples, { referenceImpedanceOhms: 75 });
|
|
849
|
+
// Save text as measurement.s1p in your application.
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
For an extracted S11/S22 trace, this is **one-port renormalization**: the other
|
|
853
|
+
port remains terminated in the original file reference. It is not renormalization
|
|
854
|
+
of the complete two-port network. Exporting S22 to `.s1p` represents that selected
|
|
855
|
+
port as the single port of the new file; transmission data is not exported.
|
|
856
|
+
|
|
857
|
+
The [Touchstone example](https://rosek86.github.io/smithkit/examples/touchstone/index.html)
|
|
858
|
+
shows parameter selection, packed import, renormalization and download. In the demo,
|
|
859
|
+
choose **Two-port reflection** before importing `.s2p`; the trace name includes the
|
|
860
|
+
selected parameter. Both `.s1p` and `.s2p` use packed import.
|
|
579
861
|
|
|
580
862
|
## PNG and report export
|
|
581
863
|
|
|
@@ -602,6 +884,11 @@ const scalePng = await scales.toPng({ width: 1200, background: 'transparent' });
|
|
|
602
884
|
- `background`: omit to keep component backgrounds, or pass a concrete CSS color
|
|
603
885
|
(for example `'#fff'`) or `'transparent'` to replace them. Chart colors stay as
|
|
604
886
|
configured; choose a suitable chart theme for your report background.
|
|
887
|
+
- `lineDetail` (chart only): `'full'` (default) includes every sample in each trace line;
|
|
888
|
+
`'view'` preserves the currently displayed line geometry, including simplification.
|
|
889
|
+
Both work for SVG and PNG without changing the live chart. Increasing export dimensions
|
|
890
|
+
scales the current-view error too; use `'full'` for reports requiring all samples.
|
|
891
|
+
This option does not change point culling, the viewport, markers, or scales.
|
|
605
892
|
- `legend` (chart only): append the names and colors of visible traces. Long names
|
|
606
893
|
wrap; hidden traces are omitted. Default: `false`.
|
|
607
894
|
- `markerLegend` (chart only): independently append marker descriptions below the chart/scales.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SmithOptions } from './options.js';
|
|
2
|
+
import type { CircleStyle, GridDetail, GridStyle } from './layers.js';
|
|
3
|
+
/** Shared validation for initial configuration, patches, and individual controls. */
|
|
4
|
+
export declare class OptionsValidation {
|
|
5
|
+
private constructor();
|
|
6
|
+
static object(value: unknown, name: string, keys?: readonly string[]): void;
|
|
7
|
+
static boolean(value: boolean, name: string): void;
|
|
8
|
+
static detail(value: GridDetail): void;
|
|
9
|
+
private static lengths;
|
|
10
|
+
private static strings;
|
|
11
|
+
static gridStyle(style: Partial<GridStyle>): void;
|
|
12
|
+
static circleStyle(style: Partial<CircleStyle>): void;
|
|
13
|
+
static circleValue(value: number, minimum: number): void;
|
|
14
|
+
static circleValues(values: readonly number[], minimum: number): void;
|
|
15
|
+
static chart(options: SmithOptions): void;
|
|
16
|
+
}
|