smithkit 0.4.0 → 0.6.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 +47 -774
- package/dist/lib/OptionsValidation.js +7 -3
- package/dist/lib/Smith.d.ts +7 -1
- package/dist/lib/Smith.js +17 -9
- package/dist/lib/grid/SmithGridLayer.js +3 -1
- package/dist/lib/index.d.ts +2 -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 +4 -0
- package/dist/lib/math/Complex.d.ts +1 -1
- package/dist/lib/math/Complex.js +2 -2
- package/dist/lib/measurements.d.ts +2 -0
- package/dist/lib/options.d.ts +4 -0
- package/dist/lib/rendering/SvgChartRenderer.d.ts +3 -3
- package/dist/lib/rendering/SvgChartRenderer.js +28 -3
- 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/scales/SmithScales.js +2 -2
- package/dist/lib/svg/LabelLayout.js +9 -2
- package/dist/lib/svg/SvgExporter.d.ts +1 -1
- package/dist/lib/svg/SvgExporter.js +4 -3
- package/dist/lib/svg/export.d.ts +2 -0
- package/dist/lib/traces/SmithData.d.ts +10 -4
- package/dist/lib/traces/SmithData.js +14 -4
- package/dist/lib/traces/SmithMarker.js +1 -0
- 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 +25 -6
package/README.md
CHANGED
|
@@ -3,27 +3,13 @@
|
|
|
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
|
-
[
|
|
6
|
+
[](https://rosek86.github.io/smithkit/)
|
|
7
|
+
|
|
8
|
+
[API documentation](https://rosek86.github.io/smithkit/api/) · [Try the interactive demo](https://rosek86.github.io/smithkit/) or browse the
|
|
7
9
|
[integration examples](https://rosek86.github.io/smithkit/examples/index.html):
|
|
8
|
-
static charts, marker controls, themes, report exports, and lifecycle cleanup.
|
|
10
|
+
static charts, marker controls, a 100,000-sample trace, themes, report exports, React/Angular components, and lifecycle cleanup.
|
|
9
11
|
Each example includes its TypeScript source.
|
|
10
12
|
|
|
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).
|
|
14
|
-
|
|
15
|
-
Upgrading from 0.2.x? Version 0.3.0 replaces `GridLayer.setMinorVisible()` with
|
|
16
|
-
`setDetail('basic' | 'standard' | 'detailed')`. Replace `false` with `'standard'`
|
|
17
|
-
and `true` with `'detailed'`; `'basic'` shows only the principal circles.
|
|
18
|
-
|
|
19
|
-
Upgrading from 0.1.x? Version 0.2.0 groups calculation, parsing, formatting, and
|
|
20
|
-
comparison functions into classes. See the [migration guide](https://github.com/rosek86/smithkit/blob/v0.2.0/docs/migration-0.2.md)
|
|
21
|
-
for the changed imports.
|
|
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
|
-
|
|
27
13
|
## Features
|
|
28
14
|
|
|
29
15
|
- Labeled resistance, reactance, conductance, and susceptance grids.
|
|
@@ -34,7 +20,7 @@ define the public contract and the compatibility scope intended for 1.0. During
|
|
|
34
20
|
- Physical impedance/admittance conversions and DOM-independent RF readings.
|
|
35
21
|
- Twelve parameter scales mounted independently of chart zoom.
|
|
36
22
|
- Four peripheral rulers for phase and electrical length.
|
|
37
|
-
-
|
|
23
|
+
- Touchstone 1.x `.s1p` / `.s2p` reflection import (RI/MA/DB), packed output, and `.s1p` export.
|
|
38
24
|
- Standalone SVG and configurable PNG export of the chart and radial scales.
|
|
39
25
|
- ESM modules and TypeScript declarations.
|
|
40
26
|
|
|
@@ -47,16 +33,25 @@ npm install smithkit
|
|
|
47
33
|
```
|
|
48
34
|
|
|
49
35
|
Browser applications need SVG, ES2022, and an ESM-compatible build tool.
|
|
36
|
+
The checked TypeScript minimum is 5.7.3. See the
|
|
37
|
+
[browser and framework compatibility](https://github.com/rosek86/smithkit/blob/main/docs/compatibility.md)
|
|
38
|
+
for tested environments and build targets.
|
|
50
39
|
No library stylesheet is required. To build the library from source, see
|
|
51
40
|
[Contributing](https://github.com/rosek86/smithkit/blob/main/CONTRIBUTING.md).
|
|
52
41
|
|
|
53
42
|
For a complete application using the installed package, see the
|
|
54
43
|
[standalone integration example](https://github.com/rosek86/smithkit/tree/main/examples/basic).
|
|
55
44
|
It demonstrates mounting, replacing samples, event subscriptions, resizing, and cleanup.
|
|
45
|
+
Copyable [React](https://rosek86.github.io/smithkit/examples/react/index.html) and
|
|
46
|
+
[Angular](https://rosek86.github.io/smithkit/examples/angular/index.html) components
|
|
47
|
+
cover the same lifecycle through framework props/inputs.
|
|
48
|
+
|
|
49
|
+
For upgrades from earlier versions, see the
|
|
50
|
+
[migration guide](https://github.com/rosek86/smithkit/blob/main/docs/migrations.md).
|
|
56
51
|
|
|
57
52
|
## Quick start
|
|
58
53
|
|
|
59
|
-
|
|
54
|
+
Mount a container with a non-zero size:
|
|
60
55
|
|
|
61
56
|
```html
|
|
62
57
|
<div id="smith" style="width: 100%; max-width: 700px; aspect-ratio: 1;"></div>
|
|
@@ -65,776 +60,54 @@ Give the container an explicit size and run the code after it is mounted:
|
|
|
65
60
|
```ts
|
|
66
61
|
import { Smith } from 'smithkit';
|
|
67
62
|
|
|
68
|
-
const chart = new Smith({ referenceImpedanceOhms: 50 });
|
|
63
|
+
const chart = new Smith({ referenceImpedanceOhms: 50 });
|
|
69
64
|
chart.draw('#smith');
|
|
70
65
|
const traceId = chart.addTrace(
|
|
71
66
|
[
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
],
|
|
76
|
-
{ name: 'Antenna', color: '#2563eb' },
|
|
77
|
-
);
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Each `TraceSample` contains `frequencyHz` and the dimensionless voltage reflection
|
|
81
|
-
coefficient Γ as `[real, imaginary]`. Samples are copied and validated; readonly tuples and arrays (`as const`) are accepted. Frequencies
|
|
82
|
-
must be finite and non-negative; both coordinates must be finite. A trace must
|
|
83
|
-
contain at least one sample.
|
|
84
|
-
|
|
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
|
|
88
|
-
and their focus indicators stay above grid labels and sample points. `chart.resetView()` restores the initial view, including peripheral rulers.
|
|
89
|
-
|
|
90
|
-
Construct `Smith` only in a browser, such as your framework's mount hook. Importing
|
|
91
|
-
the package and using its calculation or parsing methods does not require a DOM.
|
|
92
|
-
|
|
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:
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
import { Smith } from 'smithkit';
|
|
101
|
-
|
|
102
|
-
const chart = new Smith({ interaction: { zoom: true, cursor: true } });
|
|
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.
|
|
107
|
-
```
|
|
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
|
-
|
|
120
|
-
`draw(selector | HTMLElement)` moves the existing SVG when called again. A missing
|
|
121
|
-
container throws. Call `chart.destroy()` on unmount; it removes the SVG, releases
|
|
122
|
-
event handlers, and cancels queued notifications. Repeated destruction is safe.
|
|
123
|
-
|
|
124
|
-
## Constructor configuration
|
|
125
|
-
|
|
126
|
-
`new Smith(options?)` accepts a typed `SmithOptions` object. Every field is optional:
|
|
127
|
-
|
|
128
|
-
```ts
|
|
129
|
-
import { Smith } from 'smithkit';
|
|
130
|
-
|
|
131
|
-
const chart = new Smith({
|
|
132
|
-
referenceImpedanceOhms: 75,
|
|
133
|
-
appearance: { theme: 'dark' },
|
|
134
|
-
interaction: { zoom: false },
|
|
135
|
-
peripheralScales: { visible: false },
|
|
136
|
-
grid: {
|
|
137
|
-
detail: 'basic',
|
|
138
|
-
labelsVisible: true,
|
|
139
|
-
style: { majorWidth: 1.5 },
|
|
140
|
-
layers: {
|
|
141
|
-
resistance: { style: { stroke: '#60a5fa' } },
|
|
142
|
-
reactance: { labelsVisible: false },
|
|
143
|
-
conductance: { visible: true, detail: 'standard' },
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
circles: {
|
|
147
|
-
q: { visible: true, values: [1, 2, 5] },
|
|
148
|
-
vswr: { visible: true, values: [2, 3], style: { stroke: '#fbbf24' } },
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
chart.draw('#smith');
|
|
152
|
-
|
|
153
|
-
// Update all four grids together, including hidden admittance layers.
|
|
154
|
-
chart.setGridDetail('standard');
|
|
155
|
-
// Individual overrides remain available.
|
|
156
|
-
chart.layers.reactance.setDetail('basic');
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
Configuration is grouped by responsibility:
|
|
160
|
-
|
|
161
|
-
| Group | Purpose | Runtime API |
|
|
162
|
-
| ------------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
163
|
-
| `referenceImpedanceOhms` | Physical reference impedance | `renormalize()` |
|
|
164
|
-
| `appearance` | Theme, fonts, colors, marker/cursor styling | `setAppearance()` |
|
|
165
|
-
| `interaction` | `zoom` and `cursor` tracking switches | `setZoomEnabled()`, `setCursorEnabled()` |
|
|
166
|
-
| `grid` | Shared detail, labels, styles; `layers` overrides for resistance/reactance/conductance/susceptance | `setGridDetail()`, `layers.resistance` and the other grid controls |
|
|
167
|
-
| `circles` | Independent Q and VSWR values, visibility, styles | `layers.q`, `layers.vswr` |
|
|
168
|
-
| `peripheralScales` | Visibility of all peripheral rulers together | `peripheralScales.setVisible()` |
|
|
169
|
-
|
|
170
|
-
Defaults are 50 Ω, the light theme, zoom and cursor disabled, peripheral scales hidden,
|
|
171
|
-
and standard grids with labels. Resistance/reactance are visible;
|
|
172
|
-
conductance/susceptance and Q/VSWR circles are hidden. Q defaults to
|
|
173
|
-
`[0.5, 1, 2, 5, 10]`; VSWR defaults to `[1.2, 1.5, 2, 3, 5, 10]`.
|
|
174
|
-
|
|
175
|
-
Shared `grid` settings apply to all four grids; `grid.layers` overrides individual
|
|
176
|
-
fields afterward. Styles merge by property. Explicit layer styles override theme
|
|
177
|
-
colors and remain in effect when `setAppearance()` changes the theme.
|
|
178
|
-
Options and circle arrays are copied; changing the original object does not update
|
|
179
|
-
the chart. Use the existing chart/layer methods for later changes. Unknown constructor groups
|
|
180
|
-
or structural option names throw `TypeError`; omitted fields use defaults.
|
|
181
|
-
|
|
182
|
-
Export configuration belongs to `toSvg()`/`toPng()` calls, independently of chart
|
|
183
|
-
construction. `scaleReadout` requires `scales`; otherwise export throws/rejects with `TypeError`.
|
|
184
|
-
|
|
185
|
-
The constructor configures presentation and interaction. Add measurement data with
|
|
186
|
-
`addTrace()` and optional markers with `addMarker()`; no markers are created implicitly.
|
|
187
|
-
Radial parameter scales remain independently mounted `SmithScales` instances.
|
|
188
|
-
|
|
189
|
-
### Updating configuration
|
|
190
|
-
|
|
191
|
-
`chart.setOptions(options)` accepts the same `SmithOptions` type as the constructor:
|
|
192
|
-
|
|
193
|
-
```ts
|
|
194
|
-
chart.setOptions({
|
|
195
|
-
interaction: { zoom: true },
|
|
196
|
-
grid: {
|
|
197
|
-
detail: 'basic',
|
|
198
|
-
layers: { reactance: { labelsVisible: false } },
|
|
199
|
-
},
|
|
200
|
-
circles: { vswr: { visible: true, values: [2, 3] } },
|
|
201
|
-
});
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
This is a patch: omitted and `undefined` fields retain their current values;
|
|
205
|
-
`{}` groups do nothing. Shared grid settings apply to all four grids first, then
|
|
206
|
-
per-layer overrides in the same call. A later shared setting also replaces that
|
|
207
|
-
field on previously customized layers. Style fields merge; circle value lists
|
|
208
|
-
replace. `appearance`, when provided, replaces the preset/overrides exactly like
|
|
209
|
-
`setAppearance()` (it is not recursively merged with the previous appearance).
|
|
210
|
-
|
|
211
|
-
The complete patch is validated before application. Invalid settings or impossible
|
|
212
|
-
reference conversions leave the chart unchanged. `referenceImpedanceOhms` invokes
|
|
213
|
-
renormalization of existing traces and retains physical impedance and marker IDs.
|
|
214
|
-
Other configuration updates preserve measurements, markers, selection, and view.
|
|
215
|
-
Options are not retained; subsequent edits to the input object have no effect.
|
|
216
|
-
Individual setters remain available for focused changes.
|
|
217
|
-
|
|
218
|
-
### Keyboard and touch markers
|
|
219
|
-
|
|
220
|
-
Use Tab/Shift+Tab to focus a marker. Arrow keys move through samples in input order;
|
|
221
|
-
Right/Up advances and Left/Down goes back. Shift+Arrow or Page Up/Down moves ten
|
|
222
|
-
samples, and Home/End selects the first/last sample. Navigation clamps at the ends
|
|
223
|
-
and also works when chart zoom is disabled. A single-sample trace remains focusable
|
|
224
|
-
for reading, with its slider marked disabled.
|
|
225
|
-
|
|
226
|
-
A focused marker has a contrasting outline and exposes its trace name, marker
|
|
227
|
-
number, sample position, and frequency to assistive technology. Hidden traces are
|
|
228
|
-
excluded from keyboard focus. `chart.focusMarker(id)` allows a separate marker
|
|
229
|
-
selector to focus the matching chart control. The demo provides a **Focus on chart**
|
|
230
|
-
button beside its marker selector.
|
|
231
|
-
|
|
232
|
-
Markers have a 44 CSS px circular hit area and an 18 CSS px triangle, kept constant
|
|
233
|
-
through zoom and container resizing. A marker touch gesture does not pan the chart;
|
|
234
|
-
cancelling it releases the drag state. Touch target areas may overlap for nearby
|
|
235
|
-
markers; use keyboard focus or the demo selector to reach an obscured marker.
|
|
236
|
-
|
|
237
|
-
## Traces and markers
|
|
238
|
-
|
|
239
|
-
Trace and marker IDs are opaque strings, unique within a chart and never reused
|
|
240
|
-
there. They survive renaming, hiding, updating samples, and removing other items.
|
|
241
|
-
They are not persistent across chart instances or page reloads.
|
|
242
|
-
|
|
243
|
-
```ts
|
|
244
|
-
const markerA = chart.addMarker(traceId)!; // First sample.
|
|
245
|
-
const markerB = chart.addMarker(traceId, 2)!; // Zero-based sample index.
|
|
246
|
-
|
|
247
|
-
chart.setTraceOptions(traceId, { name: 'Tuned antenna', visible: true });
|
|
248
|
-
chart.setMarkerSample(markerB, 1);
|
|
249
|
-
console.log(chart.getMarker(markerB)?.frequencyHz); // 1.5e9
|
|
250
|
-
|
|
251
|
-
const difference = chart.compareMarkers(markerA, markerB);
|
|
252
|
-
console.log(difference?.frequencyDeltaHz); // B − A, in Hz.
|
|
253
|
-
console.log(difference?.impedanceDeltaOhms?.toVector());
|
|
254
|
-
console.log(difference?.phaseDeltaDegrees);
|
|
255
|
-
|
|
256
|
-
chart.removeMarker(markerB);
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
| Method | Result / behavior |
|
|
260
|
-
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
261
|
-
| `addTrace(samples, options?)` | Returns a trace ID, without creating markers. Options: nonblank `name`, solid CSS `color`, and `visible`. |
|
|
262
|
-
| `getTraces()` | Detached `TraceInfo` snapshots: ID, name, color, visibility, sample count, and marker metadata. |
|
|
263
|
-
| `setTraceOptions(id, options)` | Updates the supplied options only. Invalid options throw before any change. |
|
|
264
|
-
| `updateTrace(id, samples, options?)` | Replaces samples and preserves identity, appearance, and markers. Empty/invalid input throws without changing the trace. |
|
|
265
|
-
| `removeTrace(id)` | Removes the trace and its markers. |
|
|
266
|
-
| `clearTraces()` | Removes all traces and their markers. |
|
|
267
|
-
| `addMarker(traceId, sampleIndex = 0)` | Returns a marker ID, or `undefined` if the trace is missing. |
|
|
268
|
-
| `getMarker(id)` | Returns a `MarkerSnapshot`, or `undefined` if missing. |
|
|
269
|
-
| `focusMarker(id)` | Moves keyboard focus to a mounted, visible marker; returns `false` if missing or not focusable. |
|
|
270
|
-
| `setMarkerSample(id, sampleIndex)` | Selects an existing sample and queues a marker notification. |
|
|
271
|
-
| `removeMarker(id)` | Removes one marker without renumbering the remaining markers. |
|
|
272
|
-
| `compareMarkers(a, b)` | Returns B − A, or `undefined` if either marker is missing. |
|
|
273
|
-
| `referenceImpedanceOhms` | Read-only reference impedance. Must be positive and finite. |
|
|
274
|
-
|
|
275
|
-
Update/remove methods return a boolean: `false` means the ID was not found.
|
|
276
|
-
Sample indices must be zero-based integers within the trace; invalid indices throw
|
|
277
|
-
`RangeError`. Sample replacement follows the nearest measured frequency by default.
|
|
278
|
-
Pass `{ markerSelection: 'sample-index' }` to retain indices (clamped to the new last
|
|
279
|
-
sample if the trace shrinks), or `{ markerSelection: 'reflection' }` to select the
|
|
280
|
-
nearest Γ. Frequency and Γ ties select the earlier sample in input order, including
|
|
281
|
-
unsorted sweeps and duplicate frequencies. Selection uses the actual selected sample,
|
|
282
|
-
not a previous requested frequency. No interpolation is performed.
|
|
283
|
-
|
|
284
|
-
```ts
|
|
285
|
-
chart.updateTrace(
|
|
286
|
-
traceId,
|
|
287
|
-
[
|
|
288
|
-
{ frequencyHz: 1e9, reflectionCoefficient: [0.2, 0] },
|
|
289
|
-
{ frequencyHz: 2e9, reflectionCoefficient: [0.3, 0] },
|
|
67
|
+
[1e9, 0.5, -0.5],
|
|
68
|
+
[1.5e9, 0, 0],
|
|
69
|
+
[2e9, 0.5, 0.5],
|
|
290
70
|
],
|
|
291
|
-
{
|
|
71
|
+
{ name: 'Antenna', color: '#2563eb', mode: 'line' },
|
|
292
72
|
);
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
Invalid strategies throw `TypeError`; empty or invalid samples throw `RangeError`
|
|
296
|
-
before mutation. Unknown trace IDs return `false` without validating input.
|
|
297
|
-
Renormalization always preserves sample indices because it transforms the existing
|
|
298
|
-
sweep rather than replacing it.
|
|
299
73
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
and `frequencyHz`.
|
|
74
|
+
// Optional: enable interaction and add a marker explicitly.
|
|
75
|
+
chart.setOptions({ interaction: { zoom: true, cursor: true } });
|
|
76
|
+
chart.addMarker(traceId, 1);
|
|
304
77
|
|
|
305
|
-
|
|
306
|
-
comparisons. Hiding or deleting a dragged marker/trace ends the drag. Mutations
|
|
307
|
-
after destruction throw; trace/marker lookups return empty or missing results.
|
|
308
|
-
|
|
309
|
-
## Trace appearance
|
|
310
|
-
|
|
311
|
-
Pass `mode: 'points' | 'line' | 'both'`, `lineWidth`, and `pointRadius` to
|
|
312
|
-
`addTrace` or `setTraceOptions`. Defaults are points, 2 px line width, and 2 px point radius. Both sizes are
|
|
313
|
-
CSS pixels and remain constant under chart zoom and container resize. Widths and radii must be positive and finite.
|
|
314
|
-
`getTraces()` includes the current style.
|
|
315
|
-
|
|
316
|
-
Lines connect all samples in input order, without smoothing or frequency sorting.
|
|
317
|
-
A line-only trace creates one SVG path and no sample circles, suitable for dense
|
|
318
|
-
sweeps. Points/both render every sample for traces up to 5,000 samples. Larger traces
|
|
319
|
-
render one representative per point-radius-sized display cell and skip points
|
|
320
|
-
outside the viewport; representatives are recalculated during zoom/pan.
|
|
321
|
-
This only simplifies the image: all original samples remain available to markers,
|
|
322
|
-
snapping, readouts, and comparisons. Lines still connect every input sample.
|
|
323
|
-
Styles do not change marker identity or layer ordering. Hidden traces retain their style after sample replacement.
|
|
324
|
-
The demo exposes the same controls per trace.
|
|
325
|
-
|
|
326
|
-
## Events and readings
|
|
327
|
-
|
|
328
|
-
`onEvent(listener)` supports multiple independent subscriptions and returns an
|
|
329
|
-
unsubscribe function. `SmithEvent` is a discriminated union: checking `type`
|
|
330
|
-
narrows `data` without a cast or a property-presence test.
|
|
331
|
-
|
|
332
|
-
```ts
|
|
333
|
-
import { SmithEventType } from 'smithkit';
|
|
334
|
-
|
|
335
|
-
const unsubscribe = chart.onEvent((event) => {
|
|
336
|
-
if (event.type === SmithEventType.Cursor) {
|
|
337
|
-
// undefined when the pointer leaves or a marker drag starts.
|
|
338
|
-
console.log(event.data?.impedanceOhms?.toVector());
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
// Marker, MarkerSelect, MarkerDragStart, and MarkerDragEnd carry a MarkerSnapshot.
|
|
342
|
-
console.log(event.data.markerId, event.data.frequencyHz);
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
// On component unmount:
|
|
346
|
-
unsubscribe();
|
|
347
|
-
chart.destroy();
|
|
78
|
+
// On component unmount: chart.destroy();
|
|
348
79
|
```
|
|
349
80
|
|
|
350
|
-
|
|
351
|
-
`
|
|
352
|
-
`MarkerDragStart` (`'marker-drag-start'`), and `MarkerDragEnd` (`'marker-drag-end'`).
|
|
353
|
-
`MarkerSelect` fires synchronously when a marker receives focus or is engaged by
|
|
354
|
-
keyboard navigation or a pointer press. Use it to select the corresponding
|
|
355
|
-
readout; it does not indicate a position change. Keyboard changes use the normal
|
|
356
|
-
queued `Marker` event and do not emit drag lifecycle events.
|
|
357
|
-
Cursor movement is suspended during marker dragging. Drag start/end events fire
|
|
358
|
-
synchronously; marker position notifications are queued and report the latest
|
|
359
|
-
snapshot at delivery. Before delivery, repeated updates to the same marker coalesce
|
|
360
|
-
into one notification; different markers have independent notifications. `addMarker()`
|
|
361
|
-
queues an initial marker notification too; `addTrace()` does not. Removed markers cannot deliver queued
|
|
362
|
-
position events.
|
|
363
|
-
Trace metadata changes do not emit marker events; refresh metadata after mutations.
|
|
364
|
-
Destruction suppresses application callbacks.
|
|
365
|
-
|
|
366
|
-
`chart.cursorReading` returns the last cursor position. Cursor and marker readings
|
|
367
|
-
share `SmithReading`; `RfCalculations.readReflection(gamma, referenceImpedanceOhms = 50)` produces
|
|
368
|
-
the same reading without constructing a chart.
|
|
369
|
-
|
|
370
|
-
| Fields | Units / meaning |
|
|
371
|
-
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
|
|
372
|
-
| `reflectionCoefficient` | Complex, dimensionless voltage Γ. |
|
|
373
|
-
| `impedanceOhms`, `admittanceSiemens` | Physical complex Z in Ω and Y in S. Multiply Y by 1000 for mS display. |
|
|
374
|
-
| `phaseDegrees` | Phase of Γ in degrees; undefined at Γ = 0. |
|
|
375
|
-
| `vswr`, `q` | Dimensionless voltage standing-wave ratio and \|X/R\|. |
|
|
376
|
-
| `returnLossDb`, `reflectionLossDb` | dB. Reflection loss is also called mismatch loss. |
|
|
377
|
-
| `standingWaveRatioDb` | 20 log₁₀(VSWR), in dB. |
|
|
378
|
-
| `attenuationDb` | Half the return loss; interpretation described below. |
|
|
379
|
-
| `powerReflectionCoefficient`, `powerTransmissionCoefficient` | \|Γ\|² and 1 − \|Γ\|². |
|
|
380
|
-
| `voltageReflectionCoefficientMagnitude` | \|Γ\|. |
|
|
381
|
-
| `voltageTransmissionCoefficientMagnitude`, `currentTransmissionCoefficientMagnitude` | \|1 + Γ\| and \|1 − Γ\|, respectively. |
|
|
382
|
-
| `standingWavePeak`, `standingWaveLossCoefficient` | √VSWR and (1 + \|Γ\|²)/(1 − \|Γ\|²). |
|
|
383
|
-
|
|
384
|
-
Singular Z at Γ = +1 and Y at Γ = −1 are `undefined`. Q is undefined at an open
|
|
385
|
-
or short, and infinite for a nonzero purely reactive impedance. Finite points near
|
|
386
|
-
these limits retain finite readings within the supported numeric range. An exact
|
|
387
|
-
infinite scalar limit is preserved: perfect match gives infinite return loss;
|
|
388
|
-
\|Γ\| = 1 gives infinite VSWR and reflection loss.
|
|
389
|
-
|
|
390
|
-
For active loads (\|Γ\| > 1), VSWR, standing-wave quantities, reflection loss,
|
|
391
|
-
attenuation, and power transmission are `undefined`. Other quantities remain
|
|
392
|
-
available. Non-finite complex inputs or invalid reference impedances throw
|
|
393
|
-
`RangeError` in the public RF methods. Unrepresentable complex conversion
|
|
394
|
-
results are `undefined`.
|
|
395
|
-
|
|
396
|
-
## Selecting a marker by frequency
|
|
397
|
-
|
|
398
|
-
`chart.setMarkerFrequency(markerId, frequencyHz)` selects the nearest measured
|
|
399
|
-
frequency and returns `true`, or `false` if the marker does not exist. It accepts
|
|
400
|
-
finite, non-negative Hz values; other values throw `RangeError`. It works with
|
|
401
|
-
unsorted sweeps and duplicate frequencies. Equal-distance ties choose the earliest
|
|
402
|
-
sample in input order. Requests outside the sweep select the nearest endpoint.
|
|
403
|
-
No interpolation or sample reordering is performed.
|
|
404
|
-
|
|
405
|
-
Read `chart.getMarker(markerId).frequencyHz` for the actual selected frequency.
|
|
406
|
-
The same queued `Marker` event is emitted as for sample-index selection, and
|
|
407
|
-
comparisons update accordingly. The demo accepts MHz and shows the selected
|
|
408
|
-
measurement frequency; dragging and sample selection keep that field synchronized.
|
|
409
|
-
|
|
410
|
-
## Calculations without a chart
|
|
411
|
-
|
|
412
|
-
```ts
|
|
413
|
-
import { Complex, RfCalculations } from 'smithkit';
|
|
414
|
-
|
|
415
|
-
const gamma = RfCalculations.impedanceToReflection(Complex.from(75, 25), 50)!;
|
|
416
|
-
const reading = RfCalculations.readReflection(gamma, 50);
|
|
417
|
-
console.log(reading.impedanceOhms?.toVector()); // Approximately [75, 25].
|
|
418
|
-
console.log(reading.admittanceSiemens?.toVector());
|
|
419
|
-
```
|
|
81
|
+
Each tuple is `[frequencyHz, realGamma, imaginaryGamma]`. Object samples and
|
|
82
|
+
packed `Float64Array` triples are also supported. Inputs are validated and copied.
|
|
420
83
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
| `RfCalculations.impedanceToReflection(impedanceOhms, referenceImpedanceOhms = 50)` | Physical Z in Ω → Γ. |
|
|
425
|
-
| `RfCalculations.reflectionToAdmittance(gamma, referenceImpedanceOhms = 50)` | Γ → physical Y in S. |
|
|
426
|
-
| `RfCalculations.admittanceToReflection(admittanceSiemens, referenceImpedanceOhms = 50)` | Physical Y in S → Γ. |
|
|
427
|
-
| `RfCalculations.readReflection(gamma, referenceImpedanceOhms = 50)` | Complete `SmithReading`. |
|
|
428
|
-
| `MarkerMeasurements.compare(a, b)` | Compare readings without a chart. Each input needs `frequencyHz`, `reflectionCoefficient`, and `impedanceOhms`. |
|
|
84
|
+
By default, the chart shows a labeled standard impedance grid with zoom, cursor
|
|
85
|
+
tracking, and peripheral scales disabled. No markers are added automatically.
|
|
86
|
+
The constructor and `setOptions()` share the same grouped configuration schema.
|
|
429
87
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
179° → −179° gives +2°; an exact half turn gives −180°. Phase is undefined if
|
|
433
|
-
either Γ is zero or non-finite. Impedance differences are undefined if either Z
|
|
434
|
-
is singular or non-finite. Frequencies must be finite and non-negative. This is
|
|
435
|
-
a point comparison, not sweep phase unwrapping or group delay.
|
|
88
|
+
Create charts in the browser after mounting the host; call `destroy()` on unmount.
|
|
89
|
+
Calculation, formatting, and Touchstone classes also work without a DOM.
|
|
436
90
|
|
|
437
|
-
|
|
438
|
-
`mul`, `div`, `pow`) returns new values. The class also provides `abs`, `arg`
|
|
439
|
-
(radians), and static methods such as `Complex.conj`, `Complex.sqrt`,
|
|
440
|
-
`Complex.exp`, `Complex.log`, and trigonometric/hyperbolic functions and inverses. `toVector()` returns `[real, imaginary]`; `toString(dp)` formats
|
|
441
|
-
a Cartesian value. See the exported declarations for all operations.
|
|
91
|
+
## Documentation
|
|
442
92
|
|
|
443
|
-
The
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
`SmithFormatter.number` includes spacing so you can append a unit, e.g. `SmithFormatter.number(1e9) + 'Hz'`.
|
|
93
|
+
The [searchable API documentation](https://rosek86.github.io/smithkit/api/) combines
|
|
94
|
+
usage guides with generated reference pages for every public class, method, and type.
|
|
95
|
+
The hosted site follows `main`; consult the installed package's declarations when
|
|
96
|
+
using an older release.
|
|
448
97
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
Use `reading.impedanceOhms.im` for the reactance when impedance is defined.
|
|
464
|
-
Zero frequency, zero reactance, and unrepresentable results return `undefined`.
|
|
465
|
-
Non-finite reactance or negative/non-finite frequency throws `RangeError`.
|
|
466
|
-
This is a single-frequency equivalence, not a fitted circuit model.
|
|
467
|
-
|
|
468
|
-
## Appearance and themes
|
|
469
|
-
|
|
470
|
-
`Smith` and `SmithScales` accept the same appearance configuration. The default
|
|
471
|
-
is the light preset with a transparent background. The dark preset includes a
|
|
472
|
-
solid dark background so its labels remain readable when embedded or exported.
|
|
473
|
-
|
|
474
|
-
```ts
|
|
475
|
-
import { Smith, SmithScales } from 'smithkit';
|
|
476
|
-
import type { SmithAppearance } from 'smithkit';
|
|
477
|
-
|
|
478
|
-
const appearance: SmithAppearance = {
|
|
479
|
-
theme: 'dark',
|
|
480
|
-
overrides: {
|
|
481
|
-
fontFamily: 'Arial, sans-serif',
|
|
482
|
-
grid: { majorWidth: 1.2 },
|
|
483
|
-
cursor: { impedanceColor: '#fbbf24' },
|
|
484
|
-
marker: { focusColor: '#38bdf8' },
|
|
485
|
-
traceColors: ['#38bdf8', '#fb923c', '#a78bfa'],
|
|
486
|
-
},
|
|
487
|
-
};
|
|
488
|
-
const chart = new Smith({ referenceImpedanceOhms: 50, appearance });
|
|
489
|
-
const scales = new SmithScales(appearance);
|
|
490
|
-
chart.draw('#smith');
|
|
491
|
-
scales.draw('#scales');
|
|
492
|
-
|
|
493
|
-
// Update both independent components using the same configuration.
|
|
494
|
-
chart.setAppearance({ theme: 'light' });
|
|
495
|
-
scales.setAppearance({ theme: 'light' });
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
Each `setAppearance` call replaces the previous preset and overrides; omitted
|
|
499
|
-
settings return to the selected preset, or light when `theme` is omitted.
|
|
500
|
-
Nested overrides are partial. Appearance is scoped to each component and does not
|
|
501
|
-
change the surrounding application's CSS or other chart instances.
|
|
502
|
-
|
|
503
|
-
| Override | Settings |
|
|
504
|
-
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
505
|
-
| `background`, `fontFamily` | Component background and shared font family. |
|
|
506
|
-
| `grid` | `stroke`, `textColor`, `majorWidth`, `minorWidth`, `fontSize`. |
|
|
507
|
-
| `boundary` | `stroke`, `width` for the Smith chart boundary. |
|
|
508
|
-
| `circles` | `q`, `vswr` colors and shared `width`. |
|
|
509
|
-
| `scales` | `stroke`, `boundaryColor`, `textColor`, `valueColor`, `indicatorColor`, `indicatorOutline`; `fontSize` for radial ticks, `titleFontSize`, `valueFontSize`, and `peripheralFontSize`. |
|
|
510
|
-
| `cursor` | `pointColor`, `impedanceColor`, `admittanceColor`, `pointSize` (dot diameter), `lineWidth`. |
|
|
511
|
-
| `marker` | `outlineColor`, `textColor`, `focusColor`, `focusHaloColor`. Marker fill follows its trace color. |
|
|
512
|
-
| `traceColors` | Non-empty palette for automatically colored traces. |
|
|
513
|
-
|
|
514
|
-
Colors must be solid CSS colors accepted by the library's color parser, including
|
|
515
|
-
hex, RGB, HSL, named colors, and `transparent`; CSS variable references are not
|
|
516
|
-
accepted in the configuration. Numeric values must be positive and finite.
|
|
517
|
-
Line widths and cursor point size are CSS pixels. Font sizes are SVG chart/scale
|
|
518
|
-
units and follow the existing layout; grid labels retain their adaptive minimum
|
|
519
|
-
size. Marker geometry and the 44 px touch target stay unchanged.
|
|
520
|
-
|
|
521
|
-
Appearance updates retain zoom, samples, marker selection/focus, layer visibility,
|
|
522
|
-
and scale readings. They recolor existing and future automatically colored traces.
|
|
523
|
-
Explicit colors passed through trace options and explicit layer styles take
|
|
524
|
-
precedence and survive theme changes. Applying a new appearance does not reset
|
|
525
|
-
those individual overrides. Invalid appearance settings throw before making changes.
|
|
526
|
-
|
|
527
|
-
SVG exports resolve the appearance without requiring theme CSS. A configured
|
|
528
|
-
background is included in the exported image; `transparent` preserves transparency.
|
|
529
|
-
The **Theme** selector in the demo's **Chart settings** dialog updates both library components and the demo UI.
|
|
530
|
-
|
|
531
|
-
## Grid layers
|
|
532
|
-
|
|
533
|
-
Resistance and reactance are initially visible. Conductance, susceptance, Q,
|
|
534
|
-
and VSWR layers start hidden. All controls are under `chart.layers`:
|
|
535
|
-
|
|
536
|
-
```ts
|
|
537
|
-
chart.layers.resistance.setVisible(false);
|
|
538
|
-
chart.layers.reactance.setVisible(false);
|
|
539
|
-
chart.layers.conductance.setVisible(true);
|
|
540
|
-
chart.layers.susceptance.setVisible(true);
|
|
541
|
-
chart.layers.conductance.setDetail('standard');
|
|
542
|
-
chart.layers.conductance.setLabelsVisible(false);
|
|
543
|
-
chart.layers.susceptance.setLabelsVisible(false);
|
|
544
|
-
chart.layers.susceptance.setStyle({ stroke: '#64748b', textColor: '#2a7f62' });
|
|
545
|
-
chart.layers.vswr.addValue(4);
|
|
546
|
-
chart.layers.vswr.setVisible(true);
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
The four grid layers support `setVisible`, `setLabelsVisible`, `setDetail`, and
|
|
550
|
-
`setStyle(Partial<GridStyle>)`. Style fields: `stroke`, `majorWidth`, `minorWidth`,
|
|
551
|
-
`textColor`, `textFontFamily`, `textFontSize`. Widths are positive finite numbers
|
|
552
|
-
in CSS pixels. Font size is a positive finite base size in chart units; adaptive
|
|
553
|
-
layout raises it when needed to keep the font size at least 9 CSS pixels in the
|
|
554
|
-
default view. Partial updates retain other settings. Invalid numeric styles throw
|
|
555
|
-
before any property is changed.
|
|
556
|
-
|
|
557
|
-
Use `chart.setGridDetail('basic' | 'standard' | 'detailed')` for all four grid layers,
|
|
558
|
-
or `layer.setDetail(...)` to override one layer:
|
|
559
|
-
|
|
560
|
-
- **Basic:** complete circles and arcs for normalized values 0.2, 0.5, 1, 2, and 5,
|
|
561
|
-
with matching axis/rim labels and the zero label. Intended for small or static charts.
|
|
562
|
-
- **Standard** (default): the full major grid and its labels, without minor lines.
|
|
563
|
-
- **Detailed:** the full major and minor grid.
|
|
564
|
-
|
|
565
|
-
Changing detail preserves layer visibility, styles, and the current view. Label
|
|
566
|
-
collision handling still applies at every level. Peripheral scales and Q/VSWR
|
|
567
|
-
circles are independent. The demo's **Chart settings → Grid detail** selector updates all four grid layers.
|
|
568
|
-
|
|
569
|
-
Use `setLabelsVisible(false)` to hide a grid layer's labels while keeping its lines.
|
|
570
|
-
Labels default to visible. The setting persists through detail, style, theme, and
|
|
571
|
-
whole-layer visibility changes and is included in SVG exports. Calling
|
|
572
|
-
`setLabelsVisible(true)` restores labels allowed by the current detail and collision
|
|
573
|
-
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.
|
|
574
|
-
|
|
575
|
-
`layers.q` and `layers.vswr` support `setVisible`,
|
|
576
|
-
`setStyle({ stroke?, strokeWidth? })`, `setValues`, `addValue`, and `removeValue`.
|
|
577
|
-
`setValues([1, 2, 5])` replaces the entire list; `setValues([])` clears it.
|
|
578
|
-
Input arrays are copied, duplicate values are ignored, and invalid input leaves
|
|
579
|
-
the previous values unchanged.
|
|
580
|
-
Circle stroke widths are positive finite numbers in CSS pixels.
|
|
581
|
-
Q values must be positive and finite; VSWR values must be finite and at least 1.
|
|
582
|
-
Duplicate additions and removal of absent values have no effect.
|
|
583
|
-
|
|
584
|
-
Grid labels use normalized values; readings use physical units. Strokes default
|
|
585
|
-
to slate gray with 1 px major and 0.6 px minor lines. Stroke widths stay constant
|
|
586
|
-
under zoom. Layer controls do not expose drawing objects or SVG nodes.
|
|
587
|
-
|
|
588
|
-
Grid labels adapt automatically to the chart's rendered size,
|
|
589
|
-
including static charts with zoom disabled. The layout prioritizes key values,
|
|
590
|
-
hides labels that overlap or extend beyond the default view, and prioritizes zero
|
|
591
|
-
and the highest labeled axis value. It recalculates on resize and layer visibility
|
|
592
|
-
or style changes. Zoom and pan preserve the chosen labels and scale them smoothly
|
|
593
|
-
with the grid. This changes only labels; grid lines and ticks remain unchanged.
|
|
594
|
-
SVG exports preserve the current label layout.
|
|
595
|
-
|
|
596
|
-
For small static charts, hide minor grid lines and, when unnecessary, peripheral
|
|
597
|
-
scales using the controls above. Very small charts necessarily show fewer values;
|
|
598
|
-
use a larger container for detailed readings. Peripheral labels retain their full
|
|
599
|
-
wording and scale with the chart. Their rulers form two outlined bands: phase
|
|
600
|
-
(transmission/reflection) and electrical length (toward load/generator), with a
|
|
601
|
-
shared tick circle inside each band.
|
|
602
|
-
The independent `SmithScales` panel uses its own responsive layout.
|
|
603
|
-
|
|
604
|
-
## Parameter scales
|
|
605
|
-
|
|
606
|
-
Mount `SmithScales` independently so its twelve axes stay outside chart zoom:
|
|
607
|
-
|
|
608
|
-
```ts
|
|
609
|
-
import { SmithScales, SmithEventType } from 'smithkit';
|
|
610
|
-
|
|
611
|
-
const scales = new SmithScales();
|
|
612
|
-
scales.draw('#smith-scales'); // Provide a separate mounted container.
|
|
613
|
-
const stopScales = chart.onEvent((event) => {
|
|
614
|
-
if (event.type === SmithEventType.Cursor || event.type === SmithEventType.Marker) {
|
|
615
|
-
const gamma = event.data?.reflectionCoefficient ?? null;
|
|
616
|
-
scales.update(gamma);
|
|
617
|
-
chart.peripheralScales.update(gamma);
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
// On unmount: stopScales(); scales.destroy(); chart.destroy();
|
|
622
|
-
```
|
|
623
|
-
|
|
624
|
-
`update(Complex | null)` synchronizes indicators, values, tooltips, and accessible
|
|
625
|
-
labels. Null, non-finite, or active-load inputs hide indicators. `draw` accepts a
|
|
626
|
-
selector or `HTMLElement`; `destroy` is idempotent. Scales adapt to container width.
|
|
627
|
-
|
|
628
|
-
Labels follow the complete Smith chart terminology: **Reflection loss**,
|
|
629
|
-
**Power reflection coefficient**, **Power transmission coefficient**, and separate
|
|
630
|
-
**Voltage transmission coefficient** and **Current transmission coefficient**.
|
|
631
|
-
Ratios are dimensionless; loss/standing-wave dB axes are in dB. Transmission
|
|
632
|
-
indicators depend on Γ phase as well as magnitude.
|
|
633
|
-
|
|
634
|
-
Attenuation is −10 log₁₀\|Γ\|, half the return loss. Its one-way loss interpretation
|
|
635
|
-
assumes a matched line or attenuator terminated in an open or short: the reflected
|
|
636
|
-
wave traverses it twice. It does not measure insertion loss of an arbitrary load
|
|
637
|
-
from S11 alone. At \|Γ\| = 0.1 it reads 10 dB, while return loss reads 20 dB.
|
|
638
|
-
|
|
639
|
-
Peripheral rulers are hidden by default. Enable them with
|
|
640
|
-
`{ peripheralScales: { visible: true } }` or `chart.peripheralScales.setVisible(true)`.
|
|
641
|
-
`chart.peripheralScales` supports `setVisible(boolean)` and `update(Complex | null)`.
|
|
642
|
-
Its four rulers zoom with the chart: reflection phase, voltage transmission phase,
|
|
643
|
-
wavelengths toward generator, and wavelengths toward load. Wavelength rulers start
|
|
644
|
-
at the negative real axis, with 0.5 λ per revolution (generator clockwise, load
|
|
645
|
-
counterclockwise). These are electrical-length coordinates modulo 0.5 λ.
|
|
646
|
-
Reflection phase and wavelength coordinates are undefined at perfect match;
|
|
647
|
-
transmission phase is undefined at Γ = −1.
|
|
648
|
-
|
|
649
|
-
Scale conventions follow the [complete Smith chart reference](https://www.uiyinc.com/assets/The-Complete-Smith-Chart-Black-Magic-Design.jpg)
|
|
650
|
-
and [CERN's Smith chart introduction](https://arxiv.org/abs/1201.4068).
|
|
651
|
-
|
|
652
|
-
## Reference impedance and renormalization
|
|
653
|
-
|
|
654
|
-
`chart.renormalize(referenceImpedanceOhms)` changes the positive real reference
|
|
655
|
-
impedance and transforms every loaded Γ to preserve physical Z. Trace/marker IDs,
|
|
656
|
-
names, colors, visibility, frequencies, and selected sample indices are retained.
|
|
657
|
-
Results for all traces are validated before any change; a singular/unrepresentable
|
|
658
|
-
result rejects the operation without changing Z₀ or data. Active marker drags end,
|
|
659
|
-
cursor indicators are cleared, and marker readings are queued with the new values.
|
|
660
|
-
Changing to the current Z₀ has no effect. Mutations after destruction throw.
|
|
661
|
-
|
|
662
|
-
Two DOM-independent methods are available on `RfCalculations`:
|
|
663
|
-
|
|
664
|
-
- `RfCalculations.renormalizeReflection(gamma, fromOhms, toOhms)` returns the new complex Γ or
|
|
665
|
-
`undefined` for a singular/unrepresentable result. Exact open and short limits
|
|
666
|
-
remain Γ = +1 and −1. References must be positive, finite, real ohm values.
|
|
667
|
-
- `RfCalculations.renormalizeSamples(samples, fromOhms, toOhms)` returns a new sample array in
|
|
668
|
-
the same order, preserving frequencies. Invalid samples or a singular result
|
|
669
|
-
throw `RangeError`; the input is never modified.
|
|
670
|
-
|
|
671
|
-
For example, a matched 75 Ω load has Γ = 0 at 75 Ω and Γ = 0.2 at 50 Ω.
|
|
672
|
-
Renormalization changes Γ, VSWR, and loss readings; physical impedance stays 75 Ω.
|
|
673
|
-
Simply relabeling the same Γ with a new Z₀ would describe a different load.
|
|
674
|
-
|
|
675
|
-
The demo exposes chart Z₀ and explicitly renormalizes existing traces when applied.
|
|
676
|
-
Import renormalization is enabled by a labeled checkbox. Disable it to reject
|
|
677
|
-
files whose reference differs from the chart. Complex reference impedances and
|
|
678
|
-
multiport renormalization are outside the supported scope.
|
|
679
|
-
|
|
680
|
-
## Touchstone import
|
|
681
|
-
|
|
682
|
-
`Touchstone.parse(text)` returns `{ samples, referenceImpedanceOhms }`. It accepts
|
|
683
|
-
one-port Touchstone 1.x, converts RI/MA/DB into Cartesian Γ and all frequencies
|
|
684
|
-
into Hz, and throws for unsupported or invalid input.
|
|
685
|
-
|
|
686
|
-
```ts
|
|
687
|
-
import { Smith, Touchstone } from 'smithkit';
|
|
688
|
-
|
|
689
|
-
async function showMeasurement(file: File): Promise<Smith> {
|
|
690
|
-
const { samples, referenceImpedanceOhms } = Touchstone.parse(await file.text());
|
|
691
|
-
const chart = new Smith({ referenceImpedanceOhms });
|
|
692
|
-
chart.draw('#smith');
|
|
693
|
-
chart.addTrace(samples, { name: file.name });
|
|
694
|
-
return chart;
|
|
695
|
-
}
|
|
696
|
-
```
|
|
697
|
-
|
|
698
|
-
Omitted options use Touchstone defaults: GHz, S, MA, 50 Ω. For an existing chart,
|
|
699
|
-
use `RfCalculations.renormalizeSamples` when the file reference differs from
|
|
700
|
-
`chart.referenceImpedanceOhms`. The parser itself does not renormalize data.
|
|
701
|
-
Multiport data and Touchstone 2.x are not supported.
|
|
702
|
-
|
|
703
|
-
## PNG and report export
|
|
704
|
-
|
|
705
|
-
`chart.toPng(options?)` and `scales.toPng(options?)` return `Promise<Blob>` with MIME
|
|
706
|
-
type `image/png`. Call them in a browser after mounting the components at non-zero
|
|
707
|
-
sizes, as with SVG export. The current view, labels, colors, markers, and scale
|
|
708
|
-
readings are captured without modifying the live components.
|
|
709
|
-
|
|
710
|
-
```ts
|
|
711
|
-
import { SmithScales } from 'smithkit';
|
|
712
|
-
|
|
713
|
-
const scales = new SmithScales();
|
|
714
|
-
scales.draw('#scales');
|
|
715
|
-
const png = await chart.toPng({ width: 3200, background: 'white', legend: true });
|
|
716
|
-
// Use the Blob with your application's download, preview, or upload flow.
|
|
717
|
-
const report = await chart.toPng({ width: 2400, scales, legend: true });
|
|
718
|
-
const scalePng = await scales.toPng({ width: 1200, background: 'transparent' });
|
|
719
|
-
```
|
|
720
|
-
|
|
721
|
-
- `width` / `height`: output pixels. Omit both to use the snapshot's natural size;
|
|
722
|
-
specify one to preserve proportions. With both set, the complete image is
|
|
723
|
-
centered and fitted without distortion or cropping. Padding uses the chosen
|
|
724
|
-
background, or transparency when no background is specified.
|
|
725
|
-
- `background`: omit to keep component backgrounds, or pass a concrete CSS color
|
|
726
|
-
(for example `'#fff'`) or `'transparent'` to replace them. Chart colors stay as
|
|
727
|
-
configured; choose a suitable chart theme for your report background.
|
|
728
|
-
- `legend` (chart only): append the names and colors of visible traces. Long names
|
|
729
|
-
wrap; hidden traces are omitted. Default: `false`.
|
|
730
|
-
- `markerLegend` (chart only): independently append marker descriptions below the chart/scales.
|
|
731
|
-
Default: `false`. `true` includes every marker of visible traces, with trace name,
|
|
732
|
-
marker number, frequency, and impedance. Use an options object to select `markerIds`
|
|
733
|
-
and `fields` (`frequency`, `impedance`, `admittance`, `reflectionCoefficient`, `vswr`,
|
|
734
|
-
`returnLoss`). Fields use Hz with SI prefixes, Ω, mS, dimensionless Γ, VSWR ratios,
|
|
735
|
-
and dB respectively. Empty `markerIds` selects none; empty `fields` keeps only names
|
|
736
|
-
and marker numbers. Hidden traces are always omitted, duplicate selections appear
|
|
737
|
-
once, and unknown IDs/fields throw. Long descriptions wrap. Readings are captured at
|
|
738
|
-
export invocation, without moving markers or changing the live view.
|
|
739
|
-
- `scales` (chart only): a mounted `SmithScales` instance to place centered below the chart.
|
|
740
|
-
Its current responsive layout and readings are preserved. Use `scaleReadout` to
|
|
741
|
-
export a specific reading independently of the live view.
|
|
742
|
-
|
|
743
|
-
```ts
|
|
744
|
-
// Works with toSvg() as well. Trace and marker legends are independent.
|
|
745
|
-
const png = await chart.toPng({
|
|
746
|
-
legend: false,
|
|
747
|
-
markerLegend: {
|
|
748
|
-
fields: ['frequency', 'impedance', 'vswr'],
|
|
749
|
-
// Omit markerIds to include all markers of visible traces.
|
|
750
|
-
},
|
|
751
|
-
});
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
Dimensions must be positive integers, at most 8192 px per side and 32 megapixels
|
|
755
|
-
in total. Invalid options and unavailable/destroyed components reject the promise.
|
|
756
|
-
PNG export uses browser SVG decoding and Canvas 2D and releases temporary image URLs.
|
|
757
|
-
Fonts must be available to the browser; external font files are not embedded.
|
|
758
|
-
Export size increases resolution; it does not change the current label density.
|
|
759
|
-
|
|
760
|
-
The demo's **Export** dialog supports chart, scales, or a combined report,
|
|
761
|
-
custom dimensions/background, and independent trace and marker legends. **Include marker legend** reveals field and marker checkboxes; it is disabled for scales-only exports. The default output width is 3200 px. Choose PNG or SVG in the same dialog; both formats support these report options. The demo starts in dark mode. For exports containing parameter scales, **Scale readings** explicitly selects a marker or **None**, independently of the Cursor/Marker tab. Marker exports include the trace name, marker number, and frequency; cursor readings are not exported.
|
|
762
|
-
|
|
763
|
-
To export a specific scale reading without changing the live view, pass `readout` to
|
|
764
|
-
`scales.toSvg()` / `scales.toPng()`, or `scaleReadout` to a combined chart export:
|
|
765
|
-
|
|
766
|
-
```ts
|
|
767
|
-
import { Complex, SmithScales } from 'smithkit';
|
|
768
|
-
|
|
769
|
-
const scales = new SmithScales();
|
|
770
|
-
scales.draw('#scales');
|
|
771
|
-
const report = await chart.toPng({
|
|
772
|
-
scales,
|
|
773
|
-
scaleReadout: {
|
|
774
|
-
reflectionCoefficient: Complex.from(0.2, 0.3),
|
|
775
|
-
label: 'Antenna · Marker 1 · Frequency: 1 GHz',
|
|
776
|
-
},
|
|
777
|
-
});
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
Use `{ reflectionCoefficient: null }` for scales without readings. Omit the override to
|
|
781
|
-
preserve the current readings. Labels wrap to fit the exported scales.
|
|
782
|
-
|
|
783
|
-
## SVG export
|
|
784
|
-
|
|
785
|
-
`chart.toSvg(options?)` and `scales.toSvg(options?)` return SVG strings synchronously.
|
|
786
|
-
They accept the same `SmithImageExportOptions` / `ImageExportOptions` as PNG export,
|
|
787
|
-
including size, background, legend, and scales. Omitting options preserves the
|
|
788
|
-
original standalone SVG snapshot. Call them after `draw()`
|
|
789
|
-
while the component is mounted and has a non-zero rendered size; exporting before
|
|
790
|
-
mounting, from a `display: none` container, or after destruction throws an error.
|
|
791
|
-
|
|
792
|
-
```ts
|
|
793
|
-
const svg = chart.toSvg();
|
|
794
|
-
const blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });
|
|
795
|
-
const url = URL.createObjectURL(blob);
|
|
796
|
-
const link = document.createElement('a');
|
|
797
|
-
link.href = url;
|
|
798
|
-
link.download = 'smith-chart.svg';
|
|
799
|
-
document.body.appendChild(link);
|
|
800
|
-
link.click();
|
|
801
|
-
link.remove();
|
|
802
|
-
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
|
803
|
-
```
|
|
804
|
-
|
|
805
|
-
The chart export preserves the current zoom/pan, layer visibility, labels, traces,
|
|
806
|
-
markers, and visible indicators. It captures the rendered points, including dense
|
|
807
|
-
trace point reduction; it is an image export, not a measurement-data export.
|
|
808
|
-
The scale export combines all twelve axes into one SVG using their current layout
|
|
809
|
-
and displayed readings. To export a marker reading, call `scales.update()` with
|
|
810
|
-
that marker's reflection coefficient before `scales.toSvg()`.
|
|
811
|
-
|
|
812
|
-
Files have explicit pixel dimensions and preserve the configured component background
|
|
813
|
-
(transparent by default). Presentation
|
|
814
|
-
styles are inlined so the application's stylesheet is not required. Text remains
|
|
815
|
-
editable, and curved captions retain their internal path references. Font files
|
|
816
|
-
and surrounding HTML controls/backgrounds are not embedded. Downloading is the
|
|
817
|
-
consumer's responsibility; the library does not create files or modify live nodes.
|
|
818
|
-
In the demo, choose **Export → Format → SVG**, then select chart, scales, or the combined report.
|
|
98
|
+
| Topic | Guide |
|
|
99
|
+
| -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
100
|
+
| Mounting, resizing, cleanup | [Getting started](https://rosek86.github.io/smithkit/api/documents/Getting_started.html) |
|
|
101
|
+
| Constructor options, runtime patches, themes, layers | [Configuration](https://rosek86.github.io/smithkit/api/documents/Configuration.html) |
|
|
102
|
+
| Data formats, trace styling, markers, keyboard and touch | [Traces and markers](https://rosek86.github.io/smithkit/api/documents/Traces_and_markers.html) |
|
|
103
|
+
| Subscriptions, event timing, readouts and units | [Events and readings](https://rosek86.github.io/smithkit/api/documents/Events_and_readings.html) |
|
|
104
|
+
| Radial and peripheral scales | [Scales](https://rosek86.github.io/smithkit/api/documents/Scales.html) |
|
|
105
|
+
| Complex arithmetic, conversions and renormalization | [RF calculations](https://rosek86.github.io/smithkit/api/documents/RF_calculations.html) |
|
|
106
|
+
| S11/S22 import, packed parsing, one-port export | [Touchstone](https://rosek86.github.io/smithkit/api/documents/Touchstone.html) |
|
|
107
|
+
| SVG/PNG, dimensions, backgrounds, scales and legends | [Report export](https://rosek86.github.io/smithkit/api/documents/SVG_and_PNG_export.html) |
|
|
108
|
+
| React and Angular lifecycle integration | [Framework integration](https://rosek86.github.io/smithkit/api/documents/Framework_integration.html) |
|
|
819
109
|
|
|
820
110
|
## Development and license
|
|
821
111
|
|
|
822
112
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for development, testing, release, and demo
|
|
823
113
|
hosting instructions. Licensed under [MIT](LICENSE).
|
|
824
|
-
|
|
825
|
-
## Numerical limits
|
|
826
|
-
|
|
827
|
-
`Complex` uses JavaScript binary64 numbers. Multiplication and division scale
|
|
828
|
-
intermediate products to avoid premature overflow and underflow; logarithms,
|
|
829
|
-
square roots, and reciprocals also handle extreme finite components. Results still
|
|
830
|
-
round to binary64: unrepresentable magnitudes become infinity and tiny results
|
|
831
|
-
can underflow to signed zero. Division by zero and reciprocals at zero return
|
|
832
|
-
`[NaN, NaN]`. These operations reject non-finite operands with NaN components.
|
|
833
|
-
The principal logarithm of zero retains its `-Infinity` real limit, and signed
|
|
834
|
-
zeros select the side of square-root and logarithm branch cuts. `pow(z, 0)` is one,
|
|
835
|
-
including zero to the zeroth power; negative powers of zero are undefined.
|
|
836
|
-
|
|
837
|
-
RF helpers validate finite inputs and use `undefined` for unrepresentable complex
|
|
838
|
-
readings, including an overflowing impedance difference between markers. These
|
|
839
|
-
conventions do not imply arbitrary precision or numerical certification of every
|
|
840
|
-
transcendental operation.
|