@compstats/core 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/LICENSE +21 -0
  3. package/README.md +310 -0
  4. package/dist/3d.d.ts +33 -0
  5. package/dist/3d.d.ts.map +1 -0
  6. package/dist/3d.js +1984 -0
  7. package/dist/3d.js.map +22 -0
  8. package/dist/core/arith.d.ts +133 -0
  9. package/dist/core/arith.d.ts.map +1 -0
  10. package/dist/core/frame.d.ts +98 -0
  11. package/dist/core/frame.d.ts.map +1 -0
  12. package/dist/core/histogram.d.ts +68 -0
  13. package/dist/core/histogram.d.ts.map +1 -0
  14. package/dist/core/kde.d.ts +106 -0
  15. package/dist/core/kde.d.ts.map +1 -0
  16. package/dist/core/logit.d.ts +109 -0
  17. package/dist/core/logit.d.ts.map +1 -0
  18. package/dist/core/matrix.d.ts +135 -0
  19. package/dist/core/matrix.d.ts.map +1 -0
  20. package/dist/core/moderation.d.ts +127 -0
  21. package/dist/core/moderation.d.ts.map +1 -0
  22. package/dist/core/ols.d.ts +76 -0
  23. package/dist/core/ols.d.ts.map +1 -0
  24. package/dist/core/pca.d.ts +99 -0
  25. package/dist/core/pca.d.ts.map +1 -0
  26. package/dist/core/precision.d.ts +10 -0
  27. package/dist/core/precision.d.ts.map +1 -0
  28. package/dist/core/pretty.d.ts +51 -0
  29. package/dist/core/pretty.d.ts.map +1 -0
  30. package/dist/core/regression.d.ts +68 -0
  31. package/dist/core/regression.d.ts.map +1 -0
  32. package/dist/core/rng.d.ts +206 -0
  33. package/dist/core/rng.d.ts.map +1 -0
  34. package/dist/core/sampling.d.ts +157 -0
  35. package/dist/core/sampling.d.ts.map +1 -0
  36. package/dist/core/special.d.ts +92 -0
  37. package/dist/core/special.d.ts.map +1 -0
  38. package/dist/core/tdist.d.ts +53 -0
  39. package/dist/core/tdist.d.ts.map +1 -0
  40. package/dist/core/ttest.d.ts +146 -0
  41. package/dist/core/ttest.d.ts.map +1 -0
  42. package/dist/data/moderationData.d.ts +40 -0
  43. package/dist/data/moderationData.d.ts.map +1 -0
  44. package/dist/data/pcaDegenerate.d.ts +18 -0
  45. package/dist/data/pcaDegenerate.d.ts.map +1 -0
  46. package/dist/index.d.ts +66 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +4195 -0
  49. package/dist/index.js.map +47 -0
  50. package/dist/interactive/controls.d.ts +97 -0
  51. package/dist/interactive/controls.d.ts.map +1 -0
  52. package/dist/interactive/logit.d.ts +57 -0
  53. package/dist/interactive/logit.d.ts.map +1 -0
  54. package/dist/interactive/matrixInverse.d.ts +86 -0
  55. package/dist/interactive/matrixInverse.d.ts.map +1 -0
  56. package/dist/interactive/moderation3d.d.ts +103 -0
  57. package/dist/interactive/moderation3d.d.ts.map +1 -0
  58. package/dist/interactive/pca.d.ts +90 -0
  59. package/dist/interactive/pca.d.ts.map +1 -0
  60. package/dist/interactive/regression.d.ts +57 -0
  61. package/dist/interactive/regression.d.ts.map +1 -0
  62. package/dist/interactive/sampling.d.ts +78 -0
  63. package/dist/interactive/sampling.d.ts.map +1 -0
  64. package/dist/interactive/scatter3d.d.ts +124 -0
  65. package/dist/interactive/scatter3d.d.ts.map +1 -0
  66. package/dist/interactive/tTest.d.ts +69 -0
  67. package/dist/interactive/tTest.d.ts.map +1 -0
  68. package/dist/interactive/target.d.ts +132 -0
  69. package/dist/interactive/target.d.ts.map +1 -0
  70. package/dist/plot/axes.d.ts +128 -0
  71. package/dist/plot/axes.d.ts.map +1 -0
  72. package/dist/plot/draw.d.ts +46 -0
  73. package/dist/plot/draw.d.ts.map +1 -0
  74. package/dist/plot/format.d.ts +33 -0
  75. package/dist/plot/format.d.ts.map +1 -0
  76. package/dist/plot/logit.d.ts +68 -0
  77. package/dist/plot/logit.d.ts.map +1 -0
  78. package/dist/plot/matrixInverse.d.ts +62 -0
  79. package/dist/plot/matrixInverse.d.ts.map +1 -0
  80. package/dist/plot/moderation3d.d.ts +135 -0
  81. package/dist/plot/moderation3d.d.ts.map +1 -0
  82. package/dist/plot/pca.d.ts +79 -0
  83. package/dist/plot/pca.d.ts.map +1 -0
  84. package/dist/plot/plotly.d.ts +209 -0
  85. package/dist/plot/plotly.d.ts.map +1 -0
  86. package/dist/plot/regression.d.ts +52 -0
  87. package/dist/plot/regression.d.ts.map +1 -0
  88. package/dist/plot/sampleCi.d.ts +82 -0
  89. package/dist/plot/sampleCi.d.ts.map +1 -0
  90. package/dist/plot/sampling.d.ts +159 -0
  91. package/dist/plot/sampling.d.ts.map +1 -0
  92. package/dist/plot/scatter3d.d.ts +164 -0
  93. package/dist/plot/scatter3d.d.ts.map +1 -0
  94. package/dist/plot/tTest.d.ts +49 -0
  95. package/dist/plot/tTest.d.ts.map +1 -0
  96. package/dist/plot/target.d.ts +55 -0
  97. package/dist/plot/target.d.ts.map +1 -0
  98. package/package.json +71 -0
package/dist/3d.js ADDED
@@ -0,0 +1,1984 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined")
5
+ return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // src/plot/plotly.ts
10
+ function sameCamera(a, b) {
11
+ if (a === undefined || b === undefined) {
12
+ return a === b;
13
+ }
14
+ return sameVector(a.eye, b.eye) && sameVector(a.center, b.center) && sameVector(a.up, b.up);
15
+ }
16
+ function sameVector(a, b) {
17
+ if (a === undefined || b === undefined) {
18
+ return a === b;
19
+ }
20
+ return a.x === b.x && a.y === b.y && a.z === b.z;
21
+ }
22
+ var loading;
23
+ function loadPlotly() {
24
+ loading ??= import("plotly.js-dist-min").then((module) => {
25
+ const loaded = module.default ?? module;
26
+ return loaded;
27
+ });
28
+ return loading;
29
+ }
30
+ // src/core/frame.ts
31
+ function isNumericColumn(column) {
32
+ return column.length > 0 && column.every((value) => typeof value === "number");
33
+ }
34
+ function numericColumns(data) {
35
+ return Object.keys(data).filter((name) => isNumericColumn(data[name]));
36
+ }
37
+ function requireThreeNumericColumns(numeric, caller) {
38
+ if (numeric.length < 3) {
39
+ throw new RangeError(`${caller}() needs at least 3 numeric columns; got ${numeric.length}. ` + "Supply x/y/z explicitly or add numeric columns.");
40
+ }
41
+ }
42
+ function frameRows(data) {
43
+ const names = Object.keys(data);
44
+ const first = names[0];
45
+ if (first === undefined) {
46
+ return 0;
47
+ }
48
+ const rows = data[first].length;
49
+ const ragged = names.find((name) => data[name].length !== rows);
50
+ if (ragged !== undefined) {
51
+ throw new RangeError(`every column needs the same number of rows: "${first}" has ${rows} ` + `but "${ragged}" has ${data[ragged].length}`);
52
+ }
53
+ return rows;
54
+ }
55
+ function requireNumericColumn(data, name, role) {
56
+ const column = data[name];
57
+ if (column === undefined) {
58
+ throw new RangeError(`Column "${name}" (passed as \`${role}\`) is not in the data.`);
59
+ }
60
+ if (!isNumericColumn(column)) {
61
+ throw new RangeError(`Column "${name}" (passed as \`${role}\`) is not numeric; ` + "only numeric columns can carry the statistics.");
62
+ }
63
+ return column;
64
+ }
65
+
66
+ // src/plot/scatter3d.ts
67
+ var UIREVISION = "scatter3d";
68
+ var NUMERIC_COLORSCALE = "Viridis";
69
+ var CONFIG = { responsive: true };
70
+ var DEFAULT_SCATTER3D_STYLE = {
71
+ aspect: [1, 1, 1],
72
+ opacity: 0.8,
73
+ size: 5
74
+ };
75
+ function scatter3dSpec(data, options = {}) {
76
+ const {
77
+ aspect = DEFAULT_SCATTER3D_STYLE.aspect,
78
+ opacity = DEFAULT_SCATTER3D_STYLE.opacity,
79
+ size = DEFAULT_SCATTER3D_STYLE.size,
80
+ camera,
81
+ titles,
82
+ color
83
+ } = options;
84
+ validateScatter3dStyle(aspect, opacity, size);
85
+ frameRows(data);
86
+ const { axes, note } = chooseAxes(data, options);
87
+ const points = {
88
+ x: requireAxisColumn(data, axes.x, "x"),
89
+ y: requireAxisColumn(data, axes.y, "y"),
90
+ z: requireAxisColumn(data, axes.z, "z")
91
+ };
92
+ const colorColumn = color === undefined ? undefined : data[color];
93
+ if (color !== undefined && colorColumn === undefined) {
94
+ throw new RangeError(`Column "${color}" (passed as \`color\`) is not in the data.`);
95
+ }
96
+ const traces = buildTraces(points, { opacity, size }, colorColumn);
97
+ const shown = { x: axes.x, y: axes.y, z: axes.z, ...titles };
98
+ const layout = {
99
+ uirevision: UIREVISION,
100
+ scene: {
101
+ aspectmode: "manual",
102
+ aspectratio: {
103
+ x: aspect[0],
104
+ y: aspect[1],
105
+ z: aspect[2]
106
+ },
107
+ xaxis: { title: { text: shown.x } },
108
+ yaxis: { title: { text: shown.y } },
109
+ zaxis: { title: { text: shown.z } },
110
+ uirevision: UIREVISION,
111
+ ...camera === undefined ? {} : { camera }
112
+ }
113
+ };
114
+ return { traces, layout, note };
115
+ }
116
+ async function plotScatter3d(target, data, options = {}) {
117
+ const { plotly, ...specOptions } = options;
118
+ const spec = scatter3dSpec(data, specOptions);
119
+ const engine = plotly ?? await loadPlotly();
120
+ const element = await engine.react(target, spec.traces, spec.layout, CONFIG);
121
+ return { ...spec, element, plotly: engine };
122
+ }
123
+ function validateScatter3dStyle(aspect, opacity, size) {
124
+ if (aspect.length !== 3 || !aspect.every((value) => Number.isFinite(value))) {
125
+ throw new RangeError("`aspect` must be a numeric vector of length 3.");
126
+ }
127
+ if (aspect.some((value) => value <= 0)) {
128
+ throw new RangeError("`aspect` values must all be positive.");
129
+ }
130
+ if (!Number.isFinite(opacity) || opacity <= 0 || opacity > 1) {
131
+ throw new RangeError("`opacity` must be a single numeric in (0, 1].");
132
+ }
133
+ if (!Number.isFinite(size) || size <= 0) {
134
+ throw new RangeError("`size` must be a single positive numeric.");
135
+ }
136
+ }
137
+ function chooseAxes(data, options) {
138
+ const { x, y, z } = options;
139
+ if (x !== undefined && y !== undefined && z !== undefined) {
140
+ return { axes: { x, y, z }, note: null };
141
+ }
142
+ const numeric = numericColumns(data);
143
+ requireThreeNumericColumns(numeric, "plotScatter3d");
144
+ const chosen = numeric.slice(0, 3);
145
+ const skipped = numeric.slice(3);
146
+ const note = skipped.length === 0 ? null : `plotScatter3d(): using numeric columns ${chosen.join(", ")}; ` + `skipped ${skipped.join(", ")}. Pass x/y/z to choose explicitly.`;
147
+ return {
148
+ axes: { x: x ?? chosen[0], y: y ?? chosen[1], z: z ?? chosen[2] },
149
+ note
150
+ };
151
+ }
152
+ function requireAxisColumn(data, name, axis) {
153
+ const column = data[name];
154
+ if (column === undefined) {
155
+ throw new RangeError(`Column "${name}" (passed as \`${axis}\`) is not in the data.`);
156
+ }
157
+ if (!isNumericColumn(column)) {
158
+ throw new RangeError(`Column "${name}" (passed as \`${axis}\`) is ${describe(column)}; ` + "plotScatter3d() requires numeric columns on x/y/z. " + "Use `color` for categorical separation.");
159
+ }
160
+ return column;
161
+ }
162
+ function describe(column) {
163
+ const kinds = new Set(column.map((value) => typeof value));
164
+ if (kinds.size === 0) {
165
+ return "empty";
166
+ }
167
+ if (kinds.size > 1) {
168
+ return "mixed";
169
+ }
170
+ if (kinds.has("string")) {
171
+ return "text";
172
+ }
173
+ return kinds.has("boolean") ? "true or false" : "numbers";
174
+ }
175
+ function buildTraces(points, marker, color) {
176
+ if (color === undefined) {
177
+ return [{ type: "scatter3d", mode: "markers", ...points, marker }];
178
+ }
179
+ if (isNumericColumn(color)) {
180
+ return [
181
+ {
182
+ type: "scatter3d",
183
+ mode: "markers",
184
+ ...points,
185
+ marker: {
186
+ ...marker,
187
+ color,
188
+ colorscale: NUMERIC_COLORSCALE,
189
+ showscale: true
190
+ }
191
+ }
192
+ ];
193
+ }
194
+ const levels = [...new Set(color.map((value) => String(value)))];
195
+ return levels.map((level) => {
196
+ const rows = color.flatMap((value, row) => String(value) === level ? [row] : []);
197
+ return {
198
+ type: "scatter3d",
199
+ mode: "markers",
200
+ x: rows.map((row) => points.x[row]),
201
+ y: rows.map((row) => points.y[row]),
202
+ z: rows.map((row) => points.z[row]),
203
+ marker,
204
+ name: level,
205
+ showlegend: true
206
+ };
207
+ });
208
+ }
209
+ // src/interactive/controls.ts
210
+ function startingSliderValue(given, fallback, range) {
211
+ if (given === undefined) {
212
+ return fallback;
213
+ }
214
+ if (!Number.isFinite(given)) {
215
+ return range.min;
216
+ }
217
+ const clamped = Math.min(range.max, Math.max(range.min, given));
218
+ const decimals = decimalsOf(range.step);
219
+ const factor = 10 ** decimals;
220
+ const steps = Math.round((clamped - range.min) * factor / (range.step * factor));
221
+ const snapped = Number((range.min + steps * range.step).toFixed(decimals));
222
+ return Math.min(range.max, snapped);
223
+ }
224
+ function decimalsOf(step) {
225
+ return String(step).split(".")[1]?.length ?? 0;
226
+ }
227
+ function buildSlider(owner, name, label, range, value) {
228
+ const wrapper = owner.createElement("label");
229
+ wrapper.style.display = "block";
230
+ const caption = owner.createElement("span");
231
+ caption.textContent = `${label} `;
232
+ const readout = owner.createElement("output");
233
+ readout.textContent = String(value);
234
+ const input = owner.createElement("input");
235
+ input.type = "range";
236
+ input.name = name;
237
+ input.min = String(range.min);
238
+ input.max = String(range.max);
239
+ input.step = String(range.step);
240
+ input.value = String(value);
241
+ input.style.width = "100%";
242
+ wrapper.appendChild(caption);
243
+ wrapper.appendChild(readout);
244
+ wrapper.appendChild(input);
245
+ return { wrapper, input, readout };
246
+ }
247
+ function buildSelect(owner, name, label, choices, selected) {
248
+ const wrapper = owner.createElement("label");
249
+ wrapper.style.display = "block";
250
+ const caption = owner.createElement("span");
251
+ caption.textContent = `${label} `;
252
+ const input = owner.createElement("select");
253
+ input.name = name;
254
+ input.style.width = "100%";
255
+ for (const choice of choices) {
256
+ const option = owner.createElement("option");
257
+ option.value = String(choice);
258
+ option.textContent = String(choice);
259
+ input.appendChild(option);
260
+ }
261
+ input.value = String(selected);
262
+ wrapper.appendChild(caption);
263
+ wrapper.appendChild(input);
264
+ return { wrapper, input };
265
+ }
266
+ function buildNote(owner) {
267
+ const element = owner.createElement("p");
268
+ element.style.margin = "4px 0 0";
269
+ element.style.fontSize = "12px";
270
+ element.textContent = "";
271
+ element.hidden = true;
272
+ return {
273
+ element,
274
+ show(text) {
275
+ element.textContent = text ?? "";
276
+ element.hidden = text === null;
277
+ }
278
+ };
279
+ }
280
+
281
+ // src/plot/target.ts
282
+ function resolveTarget(target) {
283
+ if ("ctx" in target) {
284
+ return target;
285
+ }
286
+ const ctx = target.getContext("2d");
287
+ if (ctx === null) {
288
+ throw new Error("plot target: the canvas gave no 2D context. In tests, pass " + "{ ctx, width, height } instead of a canvas element.");
289
+ }
290
+ return { ctx, width: target.width, height: target.height };
291
+ }
292
+
293
+ // src/interactive/target.ts
294
+ function resolveInteractiveTarget(target) {
295
+ if ("surface" in target) {
296
+ return target;
297
+ }
298
+ return { surface: resolveTarget(target), element: target };
299
+ }
300
+ function eventPixel(element, surface, event) {
301
+ const rect = element.getBoundingClientRect();
302
+ const scaleX = rect.width === 0 ? 1 : surface.width / rect.width;
303
+ const scaleY = rect.height === 0 ? 1 : surface.height / rect.height;
304
+ return {
305
+ x: (event.clientX - rect.left) * scaleX,
306
+ y: (event.clientY - rect.top) * scaleY
307
+ };
308
+ }
309
+ var CONTROL_COLUMN_WIDTH = 140;
310
+ var FALLBACK_WIDTH = 640;
311
+ var FALLBACK_HEIGHT = 400;
312
+ function resolveControlTarget(target) {
313
+ if ("surface" in target) {
314
+ return {
315
+ surface: target.surface,
316
+ controls: target.controls,
317
+ release: () => {
318
+ return;
319
+ }
320
+ };
321
+ }
322
+ if (target.tagName === "CANVAS") {
323
+ throw new Error("interactive target: pass a container element to build the panel in, " + "not a canvas. A canvas has no room for the controls.");
324
+ }
325
+ const owner = target.ownerDocument;
326
+ const controls = owner.createElement("div");
327
+ controls.style.width = `${CONTROL_COLUMN_WIDTH}px`;
328
+ controls.style.flexShrink = "0";
329
+ controls.style.padding = "4px 6px";
330
+ controls.style.overflowY = "auto";
331
+ const width = target.clientWidth > CONTROL_COLUMN_WIDTH ? target.clientWidth - CONTROL_COLUMN_WIDTH : FALLBACK_WIDTH;
332
+ const height = target.clientHeight > 0 ? target.clientHeight : FALLBACK_HEIGHT;
333
+ const ratio = pixelRatio();
334
+ const canvas = owner.createElement("canvas");
335
+ canvas.width = Math.round(width * ratio);
336
+ canvas.height = Math.round(height * ratio);
337
+ canvas.style.width = `${width}px`;
338
+ canvas.style.height = `${height}px`;
339
+ canvas.style.minWidth = "0";
340
+ target.style.display = "flex";
341
+ target.appendChild(controls);
342
+ target.appendChild(canvas);
343
+ const remove = () => {
344
+ controls.remove();
345
+ canvas.remove();
346
+ };
347
+ const context = canvas.getContext("2d");
348
+ if (context === null) {
349
+ remove();
350
+ throw new Error("interactive target: the canvas gave no 2D context. In tests, pass " + "{ surface: { ctx, width, height }, controls } instead of a container.");
351
+ }
352
+ if (ratio !== 1) {
353
+ context.scale(ratio, ratio);
354
+ }
355
+ return { surface: { ctx: context, width, height }, controls, release: remove };
356
+ }
357
+ var FALLBACK_PLOT_HEIGHT = 480;
358
+ function resolvePlot3dTarget(target) {
359
+ if ("plot" in target) {
360
+ return {
361
+ plot: target.plot,
362
+ controls: target.controls,
363
+ release: () => {
364
+ return;
365
+ }
366
+ };
367
+ }
368
+ if (target.tagName === "CANVAS") {
369
+ throw new Error("interactive target: pass a container element to build the panel in, " + "not a canvas. Plotly draws into an element of its own.");
370
+ }
371
+ const owner = target.ownerDocument;
372
+ const controls = owner.createElement("div");
373
+ controls.style.display = "flex";
374
+ controls.style.flexWrap = "wrap";
375
+ controls.style.gap = "12px";
376
+ controls.style.padding = "8px";
377
+ controls.style.flexShrink = "0";
378
+ const plot = owner.createElement("div");
379
+ plot.style.flex = "1 1 auto";
380
+ plot.style.minHeight = target.clientHeight > 0 ? "0" : `${FALLBACK_PLOT_HEIGHT}px`;
381
+ target.style.display = "flex";
382
+ target.style.flexDirection = "column";
383
+ target.appendChild(controls);
384
+ target.appendChild(plot);
385
+ return {
386
+ plot,
387
+ controls,
388
+ release: () => {
389
+ controls.remove();
390
+ plot.remove();
391
+ }
392
+ };
393
+ }
394
+ function pixelRatio() {
395
+ const ratio = globalThis.devicePixelRatio;
396
+ return typeof ratio === "number" && ratio > 0 ? ratio : 1;
397
+ }
398
+
399
+ // src/interactive/scatter3d.ts
400
+ var NONE = "(none)";
401
+ var ASPECT_RANGE = { min: 0.1, max: 10, step: 0.1 };
402
+ var OPACITY_RANGE = { min: 0.05, max: 1, step: 0.05 };
403
+ var SIZE_RANGE = { min: 1, max: 20, step: 1 };
404
+ var ASPECT_SLIDERS = [
405
+ { name: "aspectX", label: "Aspect X" },
406
+ { name: "aspectY", label: "Aspect Y" },
407
+ { name: "aspectZ", label: "Aspect Z" }
408
+ ];
409
+ function interactiveScatter3d(target, data, options = {}) {
410
+ const {
411
+ plotly: givenEngine,
412
+ onDone,
413
+ x,
414
+ y,
415
+ z,
416
+ color,
417
+ aspect,
418
+ opacity,
419
+ size,
420
+ camera,
421
+ titles,
422
+ ...forwarded
423
+ } = options;
424
+ const style = {
425
+ aspect: aspect ?? DEFAULT_SCATTER3D_STYLE.aspect,
426
+ opacity: opacity ?? DEFAULT_SCATTER3D_STYLE.opacity,
427
+ size: size ?? DEFAULT_SCATTER3D_STYLE.size
428
+ };
429
+ validateScatter3dStyle(style.aspect, style.opacity, style.size);
430
+ const numeric = numericColumns(data);
431
+ requireThreeNumericColumns(numeric, "interactiveScatter3d");
432
+ for (const [axis, given] of [
433
+ ["x", x],
434
+ ["y", y],
435
+ ["z", z]
436
+ ]) {
437
+ if (given !== undefined && !numeric.includes(given)) {
438
+ throw new RangeError(`Initial \`${axis}\` ("${given}") is not a numeric column of ` + `\`data\`. Numeric columns: ${numeric.join(", ")}.`);
439
+ }
440
+ }
441
+ if (color !== undefined && data[color] === undefined) {
442
+ throw new RangeError(`Initial \`color\` ("${color}") is not in \`data\`.`);
443
+ }
444
+ const panel = resolvePlot3dTarget(target);
445
+ const owner = panel.controls.ownerDocument;
446
+ let values = {
447
+ x: x ?? numeric[0],
448
+ y: y ?? numeric[1],
449
+ z: z ?? numeric[2],
450
+ color,
451
+ aspect: style.aspect.map((value, axis) => startingSliderValue(value, DEFAULT_SCATTER3D_STYLE.aspect[axis], ASPECT_RANGE)),
452
+ opacity: startingSliderValue(style.opacity, DEFAULT_SCATTER3D_STYLE.opacity, OPACITY_RANGE),
453
+ size: startingSliderValue(style.size, DEFAULT_SCATTER3D_STYLE.size, SIZE_RANGE),
454
+ camera,
455
+ titles
456
+ };
457
+ let spec = null;
458
+ let engine = givenEngine;
459
+ let element = null;
460
+ let listening = false;
461
+ let destroyed = false;
462
+ let inFlight = null;
463
+ let queued = false;
464
+ const note = buildNote(owner);
465
+ async function renderOnce() {
466
+ const drawn = await plotScatter3d(panel.plot, data, {
467
+ ...forwarded,
468
+ ...values,
469
+ plotly: engine
470
+ });
471
+ if (destroyed) {
472
+ return;
473
+ }
474
+ engine = drawn.plotly;
475
+ element = drawn.element;
476
+ spec = { traces: drawn.traces, layout: drawn.layout, note: drawn.note };
477
+ note.show(drawn.note);
478
+ if (!listening) {
479
+ listening = true;
480
+ element.on("plotly_relayout", handleRelayout);
481
+ }
482
+ }
483
+ function requestRender() {
484
+ if (destroyed) {
485
+ return;
486
+ }
487
+ queued = true;
488
+ inFlight ??= start();
489
+ }
490
+ function start() {
491
+ const run = pump();
492
+ run.catch(() => {
493
+ return;
494
+ });
495
+ return run;
496
+ }
497
+ async function pump() {
498
+ try {
499
+ while (queued && !destroyed) {
500
+ queued = false;
501
+ await renderOnce();
502
+ }
503
+ } finally {
504
+ inFlight = null;
505
+ }
506
+ }
507
+ function handleRelayout(event) {
508
+ const moved = event["scene.camera"];
509
+ if (moved === undefined || destroyed || sameCamera(moved, values.camera)) {
510
+ return;
511
+ }
512
+ values = { ...values, camera: moved };
513
+ if (element !== null && engine !== undefined) {
514
+ engine.relayout(element, { "scene.camera": moved }).catch(() => {
515
+ return;
516
+ });
517
+ }
518
+ }
519
+ function handleChange(event) {
520
+ const input = event.target;
521
+ if (input.name === "color") {
522
+ values = {
523
+ ...values,
524
+ color: input.value === NONE ? undefined : input.value
525
+ };
526
+ } else {
527
+ values = { ...values, [input.name]: input.value };
528
+ }
529
+ requestRender();
530
+ }
531
+ function handleInput(event) {
532
+ const input = event.target;
533
+ const moved = Number(input.value);
534
+ const axis = ASPECT_SLIDERS.findIndex((slider) => slider.name === input.name);
535
+ if (axis >= 0) {
536
+ values = {
537
+ ...values,
538
+ aspect: values.aspect.map((was, index) => index === axis ? moved : was)
539
+ };
540
+ } else {
541
+ values = { ...values, [input.name]: moved };
542
+ }
543
+ const readout = readouts.get(input.name);
544
+ if (readout !== undefined) {
545
+ readout.textContent = input.value;
546
+ }
547
+ requestRender();
548
+ }
549
+ const built = [];
550
+ const selects = [];
551
+ const sliders = [];
552
+ const readouts = new Map;
553
+ for (const [axis, label] of [
554
+ ["x", "X"],
555
+ ["y", "Y"],
556
+ ["z", "Z"]
557
+ ]) {
558
+ const picker = buildSelect(owner, axis, label, numeric, values[axis]);
559
+ panel.controls.appendChild(picker.wrapper);
560
+ built.push(picker.wrapper);
561
+ selects.push(picker.input);
562
+ }
563
+ const colorPicker = buildSelect(owner, "color", "Color", [NONE, ...Object.keys(data)], values.color ?? NONE);
564
+ panel.controls.appendChild(colorPicker.wrapper);
565
+ built.push(colorPicker.wrapper);
566
+ selects.push(colorPicker.input);
567
+ for (const [axis, wanted] of ASPECT_SLIDERS.entries()) {
568
+ const control = buildSlider(owner, wanted.name, wanted.label, ASPECT_RANGE, values.aspect[axis]);
569
+ panel.controls.appendChild(control.wrapper);
570
+ built.push(control.wrapper);
571
+ sliders.push(control.input);
572
+ readouts.set(wanted.name, control.readout);
573
+ }
574
+ for (const [name, label, range, value] of [
575
+ ["opacity", "Opacity", OPACITY_RANGE, values.opacity],
576
+ ["size", "Size", SIZE_RANGE, values.size]
577
+ ]) {
578
+ const control = buildSlider(owner, name, label, range, value);
579
+ panel.controls.appendChild(control.wrapper);
580
+ built.push(control.wrapper);
581
+ sliders.push(control.input);
582
+ readouts.set(name, control.readout);
583
+ }
584
+ panel.controls.appendChild(note.element);
585
+ built.push(note.element);
586
+ for (const select of selects) {
587
+ select.addEventListener("change", handleChange);
588
+ }
589
+ for (const slider of sliders) {
590
+ slider.addEventListener("input", handleInput);
591
+ }
592
+ requestRender();
593
+ function currentValues() {
594
+ return { ...values, aspect: [...values.aspect] };
595
+ }
596
+ return {
597
+ getValues: currentValues,
598
+ getSpec: () => spec,
599
+ rendered: () => inFlight ?? Promise.resolve(),
600
+ done() {
601
+ onDone?.(currentValues());
602
+ },
603
+ destroy() {
604
+ if (destroyed) {
605
+ return;
606
+ }
607
+ destroyed = true;
608
+ for (const select of selects) {
609
+ select.removeEventListener("change", handleChange);
610
+ }
611
+ for (const slider of sliders) {
612
+ slider.removeEventListener("input", handleInput);
613
+ }
614
+ for (const node of built) {
615
+ node.remove();
616
+ }
617
+ if (element !== null) {
618
+ element.removeAllListeners("plotly_relayout");
619
+ engine?.purge(element);
620
+ }
621
+ panel.release();
622
+ }
623
+ };
624
+ }
625
+ // src/core/arith.ts
626
+ function sum(values) {
627
+ return values.reduce((total, value) => total + value, 0);
628
+ }
629
+ function mean(values) {
630
+ return sum(values) / values.length;
631
+ }
632
+ function extent(values) {
633
+ return values.reduce(([low, high], value) => [
634
+ value < low ? value : low,
635
+ value > high ? value : high
636
+ ], [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]);
637
+ }
638
+ function withoutNegativeZero(value) {
639
+ return value === 0 ? 0 : value;
640
+ }
641
+ function requireCount(value, name) {
642
+ if (!Number.isInteger(value) || value < 0) {
643
+ throw new RangeError(`${name} must be a non-negative integer, got ${value}`);
644
+ }
645
+ }
646
+ function zipWith(as, bs, combine) {
647
+ const length = Math.min(as.length, bs.length);
648
+ return as.slice(0, length).map((a, index) => combine(a, bs[index]));
649
+ }
650
+ function sd(values) {
651
+ if (values.length < 2) {
652
+ return Number.NaN;
653
+ }
654
+ const center = mean(values);
655
+ const squares = values.map((value) => (value - center) * (value - center));
656
+ return Math.sqrt(sum(squares) / (values.length - 1));
657
+ }
658
+ function meanAbsoluteDeviation(values) {
659
+ const center = mean(values);
660
+ return mean(values.map((value) => Math.abs(value - center)));
661
+ }
662
+ function fusedMultiplyAdd(a, b, c) {
663
+ const [product, productError] = twoProduct(a, b);
664
+ const [sum2, sumError] = twoSum(c, product);
665
+ const rounded = sum2 + (sumError + productError);
666
+ return Number.isFinite(rounded) ? rounded : a * b + c;
667
+ }
668
+ function split(value) {
669
+ const scaled = 134217729 * value;
670
+ const high = scaled - (scaled - value);
671
+ return [high, value - high];
672
+ }
673
+ function twoProduct(a, b) {
674
+ const product = a * b;
675
+ const [aHigh, aLow] = split(a);
676
+ const [bHigh, bLow] = split(b);
677
+ const error = aLow * bLow - (product - aHigh * bHigh - aLow * bHigh - aHigh * bLow);
678
+ return [product, error];
679
+ }
680
+ function twoSum(a, b) {
681
+ const sum2 = a + b;
682
+ const carried = sum2 - a;
683
+ return [sum2, a - (sum2 - carried) + (b - carried)];
684
+ }
685
+ function quantile(values, p) {
686
+ return quantiles(values, [p])[0];
687
+ }
688
+ function quantiles(values, probs) {
689
+ if (probs.some((p) => !(p >= 0 && p <= 1))) {
690
+ throw new RangeError(`every probability must be in [0, 1], got ${probs}`);
691
+ }
692
+ if (values.length === 0) {
693
+ return probs.map(() => Number.NaN);
694
+ }
695
+ const sorted = Float64Array.from(values).sort();
696
+ return probs.map((p) => type7(sorted, p));
697
+ }
698
+ function median(values) {
699
+ return quantile(values, 0.5);
700
+ }
701
+ function type7(sorted, p) {
702
+ const position = 1 + (sorted.length - 1) * p;
703
+ const below = Math.floor(position);
704
+ const above = Math.ceil(position);
705
+ const low = sorted[below - 1];
706
+ const high = sorted[above - 1];
707
+ if (position > below && high !== low) {
708
+ const h = position - below;
709
+ return (1 - h) * low + h * high;
710
+ }
711
+ return low;
712
+ }
713
+
714
+ // src/core/ols.ts
715
+ var DEFAULT_LEAST_SQUARES_TOLERANCE = 0.0000001;
716
+ function leastSquares(design, y, options = {}) {
717
+ const { weights, tolerance = DEFAULT_LEAST_SQUARES_TOLERANCE } = options;
718
+ const rows = design.length;
719
+ if (rows === 0) {
720
+ throw new RangeError("least squares needs at least one row");
721
+ }
722
+ const width = design[0].length;
723
+ if (design.some((row) => row.length !== width)) {
724
+ throw new RangeError("every design row needs the same number of columns");
725
+ }
726
+ if (y.length !== rows) {
727
+ throw new RangeError(`the response has ${y.length} values but the design has ${rows} rows`);
728
+ }
729
+ if (weights !== undefined) {
730
+ if (weights.length !== rows) {
731
+ throw new RangeError(`there are ${weights.length} weights but ${rows} rows`);
732
+ }
733
+ if (weights.some((weight) => !(weight >= 0))) {
734
+ throw new RangeError("weights cannot be negative or missing");
735
+ }
736
+ }
737
+ const scale = weights?.map((weight) => Math.sqrt(weight));
738
+ const scaled = (value, row) => scale === undefined ? value : value * scale[row];
739
+ const columns = Array.from({ length: width }, (_, column) => design.map((row, index) => scaled(row[column], index)));
740
+ const projected = y.map(scaled);
741
+ const { householders, pivot, rank } = decompose(columns, tolerance, rows);
742
+ applyHouseholders(columns, householders, projected, Math.min(rank, rows - 1));
743
+ const solved = backSubstitute(columns, projected, rank);
744
+ const coefficients = new Array(width).fill(null);
745
+ pivot.slice(0, rank).forEach((column, position) => {
746
+ coefficients[column] = solved[position];
747
+ });
748
+ const fitted = design.map((row) => sum(zipWith(row, coefficients, (value, coefficient) => coefficient === null ? 0 : value * coefficient)));
749
+ const residuals = zipWith(y, fitted, (value, fit) => value - fit);
750
+ return { coefficients, fitted, residuals, rank };
751
+ }
752
+ function decompose(columns, tolerance, rows) {
753
+ const width = columns.length;
754
+ const pivot = columns.map((_, column) => column);
755
+ const originalNorms = columns.map((column) => norm(column, 0) || 1);
756
+ const householders = new Array(width).fill(0);
757
+ let live = width;
758
+ for (let step = 0;step < Math.min(rows, width); step++) {
759
+ while (step < live && norm(columns[step], step) < originalNorms[step] * tolerance) {
760
+ cycleToEnd(columns, pivot, originalNorms, step);
761
+ live -= 1;
762
+ }
763
+ if (step === rows - 1) {
764
+ continue;
765
+ }
766
+ householders[step] = reflect(columns, step, rows);
767
+ }
768
+ return { householders, pivot, rank: Math.min(live, rows) };
769
+ }
770
+ function reflect(columns, step, rows) {
771
+ const column = columns[step];
772
+ const length = norm(column, step);
773
+ if (length === 0) {
774
+ return 0;
775
+ }
776
+ const pivotNorm = column[step] < 0 ? -length : length;
777
+ for (let row = step;row < rows; row++) {
778
+ column[row] = column[row] / pivotNorm;
779
+ }
780
+ const leading = 1 + column[step];
781
+ column[step] = leading;
782
+ for (let index = step + 1;index < columns.length; index++) {
783
+ const other = columns[index];
784
+ let inner = 0;
785
+ for (let row = step;row < rows; row++) {
786
+ inner += column[row] * other[row];
787
+ }
788
+ const factor = -inner / leading;
789
+ for (let row = step;row < rows; row++) {
790
+ other[row] = other[row] + factor * column[row];
791
+ }
792
+ }
793
+ column[step] = -pivotNorm;
794
+ return leading;
795
+ }
796
+ function applyHouseholders(columns, householders, response, count) {
797
+ const rows = response.length;
798
+ for (let step = 0;step < count; step++) {
799
+ const leading = householders[step];
800
+ if (leading === 0) {
801
+ continue;
802
+ }
803
+ const column = columns[step];
804
+ let inner = leading * response[step];
805
+ for (let row = step + 1;row < rows; row++) {
806
+ inner += column[row] * response[row];
807
+ }
808
+ const factor = -inner / leading;
809
+ response[step] = response[step] + factor * leading;
810
+ for (let row = step + 1;row < rows; row++) {
811
+ response[row] = response[row] + factor * column[row];
812
+ }
813
+ }
814
+ }
815
+ function backSubstitute(columns, response, rank) {
816
+ const solved = new Array(rank).fill(0);
817
+ for (let row = rank - 1;row >= 0; row--) {
818
+ let value = response[row];
819
+ for (let column = row + 1;column < rank; column++) {
820
+ value -= columns[column][row] * solved[column];
821
+ }
822
+ solved[row] = value / columns[row][row];
823
+ }
824
+ return solved;
825
+ }
826
+ function cycleToEnd(columns, pivot, originalNorms, step) {
827
+ moveToEnd(columns, step);
828
+ moveToEnd(pivot, step);
829
+ moveToEnd(originalNorms, step);
830
+ }
831
+ function moveToEnd(track, from) {
832
+ const [moved] = track.splice(from, 1);
833
+ track.push(moved);
834
+ }
835
+ function norm(column, from) {
836
+ return Math.hypot(...column.slice(from));
837
+ }
838
+
839
+ // src/core/moderation.ts
840
+ var GRID_STEPS = 15;
841
+ function moderationSurface(data, options) {
842
+ const { outcome, iv, mod, interaction = true, controls = [] } = options;
843
+ if (iv === mod) {
844
+ throw new RangeError(`\`iv\` and \`mod\` must name different columns, both name "${iv}"`);
845
+ }
846
+ const named = new Set([outcome, iv, mod]);
847
+ controls.forEach((control) => {
848
+ if (named.has(control)) {
849
+ throw new RangeError(`control "${control}" already names the outcome, the iv, the mod, ` + "or another control");
850
+ }
851
+ named.add(control);
852
+ });
853
+ const rows = frameRows(data);
854
+ const y = requireNumericColumn(data, outcome, "outcome");
855
+ const ivColumn = requireNumericColumn(data, iv, "iv");
856
+ const modColumn = requireNumericColumn(data, mod, "mod");
857
+ const controlColumns = controls.map((control) => requireNumericColumn(data, control, "controls"));
858
+ const modelColumns = [y, ivColumn, modColumn, ...controlColumns];
859
+ const completeRows = y.map((_, row) => row).filter((row) => modelColumns.every((column) => Number.isFinite(column[row])));
860
+ if (completeRows.length === 0) {
861
+ throw new RangeError("the model has no complete rows: every row is missing a value in " + "the outcome, the IV, the moderator, or a control");
862
+ }
863
+ const designColumns = [
864
+ { name: "(Intercept)", values: new Array(rows).fill(1) },
865
+ { name: iv, values: ivColumn },
866
+ { name: mod, values: modColumn },
867
+ ...controls.map((control, index) => ({
868
+ name: control,
869
+ values: controlColumns[index]
870
+ })),
871
+ ...interaction ? [
872
+ {
873
+ name: `${iv}:${mod}`,
874
+ values: zipWith(ivColumn, modColumn, (a, b) => a * b)
875
+ }
876
+ ] : []
877
+ ];
878
+ const design = completeRows.map((row) => designColumns.map((column) => column.values[row]));
879
+ const fit = leastSquares(design, completeRows.map((row) => y[row]));
880
+ const coefficients = designColumns.map((column, index) => ({
881
+ name: column.name,
882
+ value: fit.coefficients[index] ?? null
883
+ }));
884
+ const fitted = new Array(rows).fill(Number.NaN);
885
+ const residuals = new Array(rows).fill(Number.NaN);
886
+ completeRows.forEach((row, survivor) => {
887
+ fitted[row] = fit.fitted[survivor];
888
+ residuals[row] = fit.residuals[survivor];
889
+ });
890
+ const ivValues = rSeq(...extent(ivColumn), GRID_STEPS);
891
+ const modValues = rSeq(...extent(modColumn), GRID_STEPS);
892
+ const holds = Object.fromEntries(controls.map((control, index) => [
893
+ control,
894
+ mean(controlColumns[index].filter(Number.isFinite))
895
+ ]));
896
+ const weights = coefficients.map((term) => term.value ?? 0);
897
+ const predictions = modValues.flatMap((modValue) => ivValues.map((ivValue) => {
898
+ const gridRow = [
899
+ 1,
900
+ ivValue,
901
+ modValue,
902
+ ...controls.map((control) => holds[control]),
903
+ ...interaction ? [ivValue * modValue] : []
904
+ ];
905
+ return sum(zipWith(gridRow, weights, (value, weight) => value * weight));
906
+ }));
907
+ const [dataLow, dataHigh] = extent(y);
908
+ const [surfaceLow, surfaceHigh] = extent(predictions);
909
+ return {
910
+ coefficients,
911
+ fitted,
912
+ residuals,
913
+ ivValues,
914
+ modValues,
915
+ predictions,
916
+ zlim: [Math.min(dataLow, surfaceLow), Math.max(dataHigh, surfaceHigh)],
917
+ holds
918
+ };
919
+ }
920
+ function rSeq(from, to, length) {
921
+ if (from === to) {
922
+ return new Array(length).fill(from);
923
+ }
924
+ const by = (to - from) / (length - 1);
925
+ return Array.from({ length }, (_, index) => index === 0 ? from : index === length - 1 ? to : from + index * by);
926
+ }
927
+
928
+ // src/plot/moderation3d.ts
929
+ var DEFAULT_Z_ROT = 40;
930
+ var DEFAULT_X_ROT = -70;
931
+ var EYE_DISTANCE = 1.25 * Math.sqrt(3);
932
+ var UIREVISION2 = "moderation3d";
933
+ var CONFIG2 = { responsive: true };
934
+ function cameraFromRotations(zRot, xRot) {
935
+ if (!Number.isFinite(zRot) || !Number.isFinite(xRot)) {
936
+ throw new RangeError("`zRot` and `xRot` must be finite numbers.");
937
+ }
938
+ const azimuth = (-90 - zRot) * Math.PI / 180;
939
+ const elevation = (90 + xRot) * Math.PI / 180;
940
+ const eye = {
941
+ x: EYE_DISTANCE * Math.cos(elevation) * Math.cos(azimuth),
942
+ y: EYE_DISTANCE * Math.cos(elevation) * Math.sin(azimuth),
943
+ z: EYE_DISTANCE * Math.sin(elevation)
944
+ };
945
+ return { eye };
946
+ }
947
+ function moderation3dSpec(surface, model, view = {}) {
948
+ const { zRot = DEFAULT_Z_ROT, xRot = DEFAULT_X_ROT, zlim } = view;
949
+ const camera = cameraFromRotations(zRot, xRot);
950
+ if (zlim !== undefined) {
951
+ if (zlim.length !== 2 || !zlim.every((value) => Number.isFinite(value))) {
952
+ throw new RangeError("`zlim` must be two finite numbers.");
953
+ }
954
+ }
955
+ const range = zlim ?? [
956
+ surface.zlim[0],
957
+ surface.zlim[1]
958
+ ];
959
+ const steps = surface.ivValues.length;
960
+ const heights = surface.modValues.map((_, j) => surface.ivValues.map((__, i) => surface.predictions[j * steps + i]));
961
+ if (!surface.predictions.every(Number.isFinite)) {
962
+ throw new RangeError("the surface must have finite heights everywhere; " + "a prediction is NaN or infinite");
963
+ }
964
+ const trace = {
965
+ type: "surface",
966
+ x: surface.ivValues,
967
+ y: surface.modValues,
968
+ z: heights,
969
+ showscale: false
970
+ };
971
+ const layout = {
972
+ uirevision: UIREVISION2,
973
+ scene: {
974
+ xaxis: { title: { text: model.iv } },
975
+ yaxis: { title: { text: model.mod } },
976
+ zaxis: { title: { text: model.outcome }, range },
977
+ uirevision: UIREVISION2,
978
+ camera
979
+ }
980
+ };
981
+ return { traces: [trace], layout, note: describeHolds(model) };
982
+ }
983
+ async function plotModeration3d(target, data, options) {
984
+ const { plotly, zRot, xRot, zlim, ...model } = options;
985
+ const surface = moderationSurface(data, model);
986
+ const spec = moderation3dSpec(surface, model, { zRot, xRot, zlim });
987
+ const engine = plotly ?? await loadPlotly();
988
+ const element = await engine.react(target, spec.traces, spec.layout, CONFIG2);
989
+ return { ...spec, element, plotly: engine, surface };
990
+ }
991
+ function describeHolds(model) {
992
+ if ((model.controls ?? []).length === 0) {
993
+ return null;
994
+ }
995
+ return `Surface shows predicted ${model.outcome} over ${model.iv} and ` + `${model.mod}. Other predictors are held at their typical values.`;
996
+ }
997
+
998
+ // src/interactive/moderation3d.ts
999
+ var Z_ROT_RANGE = { min: 0, max: 360, step: 1 };
1000
+ var X_ROT_RANGE = { min: -90, max: -70, step: 1 };
1001
+ var DEFAULT_Z_ROT2 = 40;
1002
+ var DEFAULT_X_ROT2 = -70;
1003
+ var SLIDERS = [
1004
+ {
1005
+ name: "zRot",
1006
+ label: "Z rotation",
1007
+ range: Z_ROT_RANGE,
1008
+ fallback: DEFAULT_Z_ROT2
1009
+ },
1010
+ {
1011
+ name: "xRot",
1012
+ label: "X rotation",
1013
+ range: X_ROT_RANGE,
1014
+ fallback: DEFAULT_X_ROT2
1015
+ }
1016
+ ];
1017
+ function interactiveModeration3d(target, data, options) {
1018
+ const { plotly: givenEngine, onDone, zRot, xRot, ...model } = options;
1019
+ const panel = resolvePlot3dTarget(target);
1020
+ const owner = panel.controls.ownerDocument;
1021
+ let values = {
1022
+ ...model,
1023
+ zRot: startingSliderValue(zRot, DEFAULT_Z_ROT2, Z_ROT_RANGE),
1024
+ xRot: startingSliderValue(xRot, DEFAULT_X_ROT2, X_ROT_RANGE)
1025
+ };
1026
+ let spec = null;
1027
+ let surface = null;
1028
+ let engine = givenEngine;
1029
+ let element = null;
1030
+ let painted = null;
1031
+ let seenCamera;
1032
+ let listening = false;
1033
+ let destroyed = false;
1034
+ let inFlight = null;
1035
+ let queued = false;
1036
+ const note = buildNote(owner);
1037
+ async function renderOnce() {
1038
+ const wanted = { zRot: values.zRot, xRot: values.xRot };
1039
+ const drawn = await plotModeration3d(panel.plot, data, {
1040
+ ...values,
1041
+ plotly: engine
1042
+ });
1043
+ if (destroyed) {
1044
+ return;
1045
+ }
1046
+ engine = drawn.plotly;
1047
+ element = drawn.element;
1048
+ surface = drawn.surface;
1049
+ spec = { traces: drawn.traces, layout: drawn.layout, note: drawn.note };
1050
+ note.show(drawn.note);
1051
+ if (!listening) {
1052
+ listening = true;
1053
+ element.on("plotly_relayout", handleRelayout);
1054
+ }
1055
+ const moved = painted !== null && (painted.zRot !== wanted.zRot || painted.xRot !== wanted.xRot);
1056
+ painted = wanted;
1057
+ const camera = drawn.layout.scene.camera;
1058
+ if (moved && camera !== undefined) {
1059
+ seenCamera = camera;
1060
+ await drawn.plotly.relayout(element, { "scene.camera": camera });
1061
+ } else if (seenCamera !== undefined && !sameCamera(seenCamera, camera)) {
1062
+ await drawn.plotly.relayout(element, { "scene.camera": seenCamera });
1063
+ }
1064
+ }
1065
+ function handleRelayout(event) {
1066
+ const moved = event["scene.camera"];
1067
+ if (moved === undefined || destroyed || sameCamera(moved, seenCamera)) {
1068
+ return;
1069
+ }
1070
+ seenCamera = moved;
1071
+ if (element !== null && engine !== undefined) {
1072
+ engine.relayout(element, { "scene.camera": moved }).catch(() => {
1073
+ return;
1074
+ });
1075
+ }
1076
+ }
1077
+ function requestRender() {
1078
+ if (destroyed) {
1079
+ return;
1080
+ }
1081
+ queued = true;
1082
+ inFlight ??= start();
1083
+ }
1084
+ function start() {
1085
+ const run = pump();
1086
+ run.catch(() => {
1087
+ return;
1088
+ });
1089
+ return run;
1090
+ }
1091
+ async function pump() {
1092
+ try {
1093
+ while (queued && !destroyed) {
1094
+ queued = false;
1095
+ await renderOnce();
1096
+ }
1097
+ } finally {
1098
+ inFlight = null;
1099
+ }
1100
+ }
1101
+ function handleInput(event) {
1102
+ const input = event.target;
1103
+ values = { ...values, [input.name]: Number(input.value) };
1104
+ const readout = readouts.get(input.name);
1105
+ if (readout !== undefined) {
1106
+ readout.textContent = input.value;
1107
+ }
1108
+ requestRender();
1109
+ }
1110
+ const built = [];
1111
+ const inputs = [];
1112
+ const readouts = new Map;
1113
+ for (const slider of SLIDERS) {
1114
+ const control = buildSlider(owner, slider.name, slider.label, slider.range, values[slider.name]);
1115
+ panel.controls.appendChild(control.wrapper);
1116
+ built.push(control.wrapper);
1117
+ inputs.push(control.input);
1118
+ readouts.set(slider.name, control.readout);
1119
+ control.input.addEventListener("input", handleInput);
1120
+ }
1121
+ panel.controls.appendChild(note.element);
1122
+ built.push(note.element);
1123
+ requestRender();
1124
+ return {
1125
+ getValues: () => ({ ...values }),
1126
+ getSurface: () => surface,
1127
+ getSpec: () => spec,
1128
+ rendered: () => inFlight ?? Promise.resolve(),
1129
+ done() {
1130
+ onDone?.({ ...values });
1131
+ },
1132
+ destroy() {
1133
+ if (destroyed) {
1134
+ return;
1135
+ }
1136
+ destroyed = true;
1137
+ for (const input of inputs) {
1138
+ input.removeEventListener("input", handleInput);
1139
+ }
1140
+ for (const node of built) {
1141
+ node.remove();
1142
+ }
1143
+ if (element !== null) {
1144
+ element.removeAllListeners("plotly_relayout");
1145
+ engine?.purge(element);
1146
+ }
1147
+ panel.release();
1148
+ }
1149
+ };
1150
+ }
1151
+ // src/data/moderationData.ts
1152
+ var moderationData = {
1153
+ y: [
1154
+ -7.272897200071196,
1155
+ -1.8368504105536234,
1156
+ 2.4825030269210964,
1157
+ 6.0885502472158235,
1158
+ -2.7813932586215913,
1159
+ -1.404547743484975,
1160
+ -2.328370225641195,
1161
+ 0.24770227680217238,
1162
+ -1.0630104614416778,
1163
+ -2.0458910688111343,
1164
+ -5.134105295915988,
1165
+ 18.10246414109479,
1166
+ -3.4663420296290077,
1167
+ -1.0047522093312424,
1168
+ -0.8247466640897548,
1169
+ 0.011971257899126564,
1170
+ -2.4321918294924254,
1171
+ -14.110628278307653,
1172
+ -1.5077118301445713,
1173
+ -3.3519580636316557,
1174
+ 0.3422839785409655,
1175
+ -1.4420566151665186,
1176
+ -0.09954101599791107,
1177
+ -4.171757229061835,
1178
+ 5.638370200339164,
1179
+ -0.24209932633994577,
1180
+ -0.9294220298667977,
1181
+ -0.1430677581344491,
1182
+ -0.7519187319967391,
1183
+ -2.6149345603765624,
1184
+ 1.9162030995224288,
1185
+ 2.882308922335612,
1186
+ -4.1366719661768885,
1187
+ -1.5262757249783787,
1188
+ -0.13241561132928859,
1189
+ 1.0868995782488633,
1190
+ -5.43223982082246,
1191
+ -1.0526454319438507,
1192
+ -5.336080703693647,
1193
+ 0.8037058943922428,
1194
+ 0.6456670109243666,
1195
+ -0.580865310517441,
1196
+ 5.995820813731591,
1197
+ -3.748881331929856,
1198
+ 4.799106863920568,
1199
+ 3.917014743258661,
1200
+ -2.52057971625805,
1201
+ 1.0052100508228277,
1202
+ -1.2592451123609627,
1203
+ -1.4191054380364576,
1204
+ -2.7688068774363885,
1205
+ -1.1283556266006958,
1206
+ -5.015571911735988,
1207
+ 0.7443650892965741,
1208
+ 1.3457889732609731,
1209
+ -1.5775936354323048,
1210
+ 0.24940175331052905,
1211
+ 0.8453453656305834,
1212
+ 9.108639550485199,
1213
+ -1.089576439866974,
1214
+ -0.0548347508354996,
1215
+ 3.4396743692990768,
1216
+ 1.82777129315956,
1217
+ -9.08768179039613,
1218
+ -1.6403441299936004,
1219
+ 6.344112012159234,
1220
+ 3.0068415808329494,
1221
+ 1.0402916701960967,
1222
+ -10.792485667257104,
1223
+ 0.19774249672127087,
1224
+ -2.6230964327485333,
1225
+ -1.5340564759379902,
1226
+ 1.72657398132359,
1227
+ -4.472744132233102,
1228
+ 0.051358701883551766,
1229
+ 3.4112581498484817,
1230
+ 1.7155585583877218,
1231
+ -2.4096746494084527,
1232
+ -3.658089954388166,
1233
+ -4.219629941316109,
1234
+ 5.770611553647898,
1235
+ -4.03685548370302,
1236
+ -1.8534915424952012,
1237
+ -1.4551065653571458,
1238
+ -0.5733313061368043,
1239
+ 1.2587331393918402,
1240
+ -0.1807495531690153,
1241
+ -1.7541060455623132,
1242
+ -7.181673967259479,
1243
+ 2.268171576280935,
1244
+ -2.2618552849857134,
1245
+ -1.0033432551835315,
1246
+ -1.5998101004488254,
1247
+ 13.776336779706227,
1248
+ -1.360193467035638,
1249
+ 0.8437705359604352,
1250
+ 0.26923062515768637,
1251
+ -6.158720480354257,
1252
+ 0.2845594239106771,
1253
+ -3.7313390977173673,
1254
+ 2.209575611277963,
1255
+ 4.957315515246748,
1256
+ -1.1074416328100625,
1257
+ 6.773590899689121,
1258
+ -1.1622855609602678,
1259
+ -0.1468882418607233,
1260
+ -1.8138297100034615,
1261
+ -0.8822977247856844,
1262
+ -2.531058796320521,
1263
+ 0.9225068493015128,
1264
+ 1.0529999297345707,
1265
+ -1.0226841183124429,
1266
+ -0.6282619133683303,
1267
+ 0.047095104558446066,
1268
+ -2.1862971987559754,
1269
+ 1.9185432668727294,
1270
+ -1.4157898788687031,
1271
+ 3.8559400012867275,
1272
+ 4.8196910254616006,
1273
+ 1.1859049624611124,
1274
+ 2.1292032810255828,
1275
+ -2.580469493916582,
1276
+ 0.7806460650847441,
1277
+ -0.7717747448671646,
1278
+ 4.302323128742706,
1279
+ 1.1280497997890846,
1280
+ -3.3823450205179935,
1281
+ -2.8141768087650334,
1282
+ 1.9176969652481777,
1283
+ -1.8022438527307034,
1284
+ 0.5676992260859575,
1285
+ -1.1988798479187797,
1286
+ -0.8112714289530125,
1287
+ 3.0023694027723717,
1288
+ 6.313814189291469,
1289
+ -0.7209131724573175,
1290
+ -0.4934212971184535,
1291
+ -5.311645069538028,
1292
+ 1.5864321371634191,
1293
+ -1.3767448543412033,
1294
+ -0.32149297043332475,
1295
+ -2.7378068772633672,
1296
+ 0.44512957644982276,
1297
+ 1.014415590908376,
1298
+ -0.3398299559551271,
1299
+ 3.6424411700938926,
1300
+ -0.804849649687885,
1301
+ 0.26491344714041165,
1302
+ 1.0255159271802998,
1303
+ -3.4431481857611512,
1304
+ -1.261772843081508,
1305
+ 2.4072718264535986,
1306
+ 4.18584814419661,
1307
+ 0.8444989650012846,
1308
+ 0.6890664424805704,
1309
+ -4.930173029208773,
1310
+ 1.3181686730513686,
1311
+ -3.950474574106549,
1312
+ 0.6996653997568072,
1313
+ -7.733171334446728,
1314
+ 0.37966613312994063,
1315
+ 2.098048515776042,
1316
+ 0.5869676229216956,
1317
+ -0.09533520375390134,
1318
+ -1.3602473690753563,
1319
+ -1.8363341184552933,
1320
+ -5.327197109758741,
1321
+ -2.4667878836756927,
1322
+ -0.8477118043370667,
1323
+ 1.794347325600735,
1324
+ -1.1215052328640052,
1325
+ 0.9693808927847424,
1326
+ -8.852509568972764,
1327
+ -10.171192748327044,
1328
+ 5.515479360644947,
1329
+ 0.8133474344349123,
1330
+ 1.5442257490953633,
1331
+ -2.3028072866769134,
1332
+ 0.6898369821689965,
1333
+ 1.9915198521027817,
1334
+ 2.832247846170376,
1335
+ 0.34764862749885805,
1336
+ -0.5034271262990748,
1337
+ 1.1733004427545144,
1338
+ 0.18449984894824215,
1339
+ -1.9938893833160367,
1340
+ 0.8829064829548916,
1341
+ 0.6266797217305222,
1342
+ -3.9311936779928676,
1343
+ -4.693057322327316,
1344
+ 0.5942425542793619,
1345
+ -0.04091322810348444,
1346
+ 1.5529759191506414,
1347
+ 0.5255897517761228,
1348
+ -0.5181252414019946,
1349
+ 5.713823828860155,
1350
+ 0.8064569522257248,
1351
+ 2.7208395005315182,
1352
+ -1.9931388422548042,
1353
+ 2.0982441518090775
1354
+ ],
1355
+ x: [
1356
+ 2.741916894293337,
1357
+ -1.1293963427921776,
1358
+ 0.7262568226746783,
1359
+ 1.265725209922081,
1360
+ 0.8085366462819982,
1361
+ -0.21224903218296798,
1362
+ 3.023043994877878,
1363
+ -0.18931807682619511,
1364
+ 4.036847427754083,
1365
+ -0.125428198104842,
1366
+ 2.6097393084469704,
1367
+ 4.573290785402214,
1368
+ -2.7777214022246786,
1369
+ -0.5575775336347428,
1370
+ -0.266642672787316,
1371
+ 1.271900796140149,
1372
+ -0.5685058428321448,
1373
+ -5.312910841809552,
1374
+ -4.880933857151038,
1375
+ 2.640226691460384,
1376
+ -0.6132771881569492,
1377
+ -3.562616867960001,
1378
+ -0.3438347115192427,
1379
+ 2.429349398345198,
1380
+ 3.7903869225299305,
1381
+ -0.8609382632123992,
1382
+ -0.5145387655378593,
1383
+ -3.5263261703895603,
1384
+ 0.9201947096625428,
1385
+ -1.2799897519202386,
1386
+ 0.9109002464824387,
1387
+ 1.4096746744576383,
1388
+ 2.0702070439398446,
1389
+ -1.2178527508144228,
1390
+ 1.0099102465959404,
1391
+ -3.434017358146686,
1392
+ -1.5689180167589927,
1393
+ -1.7018151883530368,
1394
+ -4.828415299893265,
1395
+ 0.07224521378451125,
1396
+ 0.41199720040050775,
1397
+ -0.7221145970973324,
1398
+ 1.516326471399034,
1399
+ -1.4534096541531503,
1400
+ -2.736562088838589,
1401
+ 0.8656360517774341,
1402
+ -1.6227863523733432,
1403
+ 2.8882025234425055,
1404
+ -0.8628924052266909,
1405
+ 1.3112957668044132,
1406
+ 0.6438505304078931,
1407
+ -1.5676778817607508,
1408
+ 3.1514550395839547,
1409
+ 1.285798611434633,
1410
+ 0.17952129319921128,
1411
+ 0.5531014945829259,
1412
+ 1.3585776321105416,
1413
+ 0.17966577315816343,
1414
+ -5.98618016630587,
1415
+ 0.5697659070613188,
1416
+ -0.7344692854819507,
1417
+ 0.3704611297312187,
1418
+ 1.1636474547310138,
1419
+ 2.799473654585356,
1420
+ -1.45458411894893,
1421
+ 2.605085264088287,
1422
+ 0.6716962395041488,
1423
+ 2.0770121973952422,
1424
+ 1.8414571365812926,
1425
+ 1.4417563257337251,
1426
+ -2.08623787713571,
1427
+ -0.18037277322141337,
1428
+ 1.2470363239990871,
1429
+ -1.907046715544688,
1430
+ -1.0856576291477136,
1431
+ 1.1619929953633648,
1432
+ 1.536357475669182,
1433
+ 0.9275351770803344,
1434
+ -1.771552594819359,
1435
+ -2.199561797295711,
1436
+ 3.025414019609856,
1437
+ 0.5158428750640617,
1438
+ 0.17688045831917268,
1439
+ -0.24179307507817885,
1440
+ -2.3886577903210564,
1441
+ 1.2239937960807739,
1442
+ -0.4342796914930417,
1443
+ -0.3655134126638434,
1444
+ 1.8666926571423201,
1445
+ 1.643546221016498,
1446
+ 2.784232751868542,
1447
+ -0.9523478461093488,
1448
+ 1.3006971214526097,
1449
+ 2.7822209127800015,
1450
+ -2.2215777588957977,
1451
+ -1.7215851737556847,
1452
+ -2.26347736170754,
1453
+ -2.9184279990047917,
1454
+ 0.15996510648232234,
1455
+ 1.30640867929838,
1456
+ 2.4019307511969883,
1457
+ 2.0895021743354505,
1458
+ -2.006417293679696,
1459
+ 3.696963803345493,
1460
+ -1.3335468175156342,
1461
+ 0.21102762491213886,
1462
+ -0.8445117637377121,
1463
+ -0.24470034390994258,
1464
+ 0.37638606900299576,
1465
+ 0.23832191599401276,
1466
+ -0.050185101734805754,
1467
+ 0.2161454558840652,
1468
+ -0.9708704716933354,
1469
+ -1.0084342613758068,
1470
+ -3.322198159829624,
1471
+ -0.7646674537476362,
1472
+ -1.025300515755601,
1473
+ 5.403782000689595,
1474
+ -2.7242324623794376,
1475
+ 0.2745124371172138,
1476
+ -2.987250134632581,
1477
+ -2.940871482873593,
1478
+ 0.2494047723940136,
1479
+ -1.9932782697680742,
1480
+ -0.0036452286094163897,
1481
+ -0.8565177628516306,
1482
+ -1.2273432128989903,
1483
+ -4.049355690838215,
1484
+ -2.449495900719972,
1485
+ 0.3590328822358758,
1486
+ 1.1352411888470701,
1487
+ -0.9857547071069496,
1488
+ 0.00012576813070224816,
1489
+ 2.245779286759933,
1490
+ 2.87971148595238,
1491
+ -2.1942275368116433,
1492
+ -0.23463912050035363,
1493
+ 2.4029968018394023,
1494
+ -0.9394591611326017,
1495
+ -0.10493896987799263,
1496
+ -0.17221459647417905,
1497
+ -1.775358035812863,
1498
+ -0.8893680097694762,
1499
+ -0.05888975817647629,
1500
+ -0.8277376981158471,
1501
+ 2.2267720467364067,
1502
+ -0.9619856833079639,
1503
+ -0.8663380652014581,
1504
+ 1.3937251531042052,
1505
+ -2.1127368263418163,
1506
+ -0.08139695030242985,
1507
+ -3.1030896446951792,
1508
+ 2.334339098471364,
1509
+ -0.5472914027481613,
1510
+ -0.9356906493445072,
1511
+ -2.4765046559724295,
1512
+ -0.015524067554653256,
1513
+ -1.600564355903319,
1514
+ -1.066984659900873,
1515
+ 2.5753504911691776,
1516
+ -0.35105174048425475,
1517
+ -2.143564768301352,
1518
+ 0.3264137649347646,
1519
+ -0.7254768312558996,
1520
+ 1.1800270959746773,
1521
+ 2.864843855461979,
1522
+ -1.9853850222189862,
1523
+ 0.9093005951605652,
1524
+ 0.16979611735697459,
1525
+ 1.7911311645290895,
1526
+ -0.45955627789253306,
1527
+ 1.6732381369212268,
1528
+ -3.4901117226733867,
1529
+ 3.378917842626747,
1530
+ 1.729555957037156,
1531
+ -0.3015519777714956,
1532
+ -2.898014260278335,
1533
+ 1.2860174000839635,
1534
+ 0.9663877276295352,
1535
+ -0.012711252842777425,
1536
+ 0.30291178572484884,
1537
+ -1.1682179406996087,
1538
+ 0.7376134652604842,
1539
+ 0.5893086794390312,
1540
+ -0.5585187466851501,
1541
+ -2.672473309786308,
1542
+ 1.4014976368800685,
1543
+ 1.108393244548067,
1544
+ -1.67261318560283,
1545
+ -3.189176324012486,
1546
+ 0.40991716117526766,
1547
+ -0.6901759559457797,
1548
+ 0.5052234067289093,
1549
+ -2.5880049309691064,
1550
+ -1.918340888760726,
1551
+ 2.1715497073598016,
1552
+ 0.8075498094314278,
1553
+ 1.1729750734385955,
1554
+ 3.630456892307906,
1555
+ 0.2576428572047662
1556
+ ],
1557
+ z: [
1558
+ -4.001858475463022,
1559
+ 0.6675543948671404,
1560
+ 2.342650254717589,
1561
+ 4.119078484598608,
1562
+ -2.7537231964810425,
1563
+ -2.301711131254211,
1564
+ -1.4116427895202421,
1565
+ -2.108111564154383,
1566
+ -1.2914874462849828,
1567
+ -0.3707559353530068,
1568
+ -2.4024441014799702,
1569
+ 4.0739443339663,
1570
+ 0.2155494897710934,
1571
+ -0.16821620101116128,
1572
+ 0.9912392832091879,
1573
+ 0.07483037223593068,
1574
+ -0.2641760739118198,
1575
+ 2.9535748471041936,
1576
+ -0.43406042018420693,
1577
+ -2.5672044081844505,
1578
+ 0.7713357808868047,
1579
+ -0.7030257470581849,
1580
+ -1.0435921867125384,
1581
+ -2.1362624013743408,
1582
+ 0.856731806533385,
1583
+ -0.3480364688539898,
1584
+ 1.0313354572960587,
1585
+ -0.468730554611843,
1586
+ -1.3170068516435418,
1587
+ 2.500473208157433,
1588
+ -0.5435274302227936,
1589
+ 1.8959039917503921,
1590
+ -2.4031648602178755,
1591
+ -0.9322321927510044,
1592
+ -0.5387027903063599,
1593
+ -0.7819308162617215,
1594
+ 2.697414023983427,
1595
+ -0.04552940259682519,
1596
+ 0.4884517022069007,
1597
+ -1.8847434157278455,
1598
+ -1.4584345530191491,
1599
+ 1.9961378171096964,
1600
+ 2.5169633291911206,
1601
+ 2.497727377620192,
1602
+ -2.7612740990506603,
1603
+ 4.099921387272788,
1604
+ 2.0337456595990835,
1605
+ -0.053434928276515886,
1606
+ 1.407215557596521,
1607
+ -1.9427704583037273,
1608
+ -2.1923124831177145,
1609
+ 0.09810090187519412,
1610
+ -2.39699171311556,
1611
+ 0.380037997119496,
1612
+ 2.5954117992093324,
1613
+ -2.067747445929502,
1614
+ -1.4768815084261278,
1615
+ 0.0931278789017267,
1616
+ -2.0351922396522117,
1617
+ -0.7665679197725563,
1618
+ 1.745510823342797,
1619
+ 1.939090027940234,
1620
+ 0.7676933300541888,
1621
+ -3.703111326134929,
1622
+ -0.10799347365233136,
1623
+ 2.1295464286765675,
1624
+ 1.62639007482321,
1625
+ -0.38163294820856347,
1626
+ -5.399859617127405,
1627
+ 0.1219332776022331,
1628
+ 1.1475033949671558,
1629
+ 0.09160715945019773,
1630
+ 0.3148250803517509,
1631
+ 0.8631307457375416,
1632
+ -0.7930994721004244,
1633
+ 2.6199564515030986,
1634
+ 0.940786799747886,
1635
+ -2.4853405411492027,
1636
+ 2.763150912771066,
1637
+ 2.4089178740196484,
1638
+ 1.648147927363762,
1639
+ -3.3252588043711886,
1640
+ -1.1386126872109616,
1641
+ 1.2710276345790525,
1642
+ 0.08744401515571584,
1643
+ 0.6960246073226142,
1644
+ 4.91918709774083,
1645
+ -1.636760648799339,
1646
+ -4.226400229858274,
1647
+ 0.5473905448608293,
1648
+ -1.3751936824868236,
1649
+ 0.8920821059237314,
1650
+ -1.6247694475811947,
1651
+ 4.424110960670272,
1652
+ -0.24741194315485965,
1653
+ -0.9546710120601046,
1654
+ -0.3325229829732164,
1655
+ 1.7251267672528618,
1656
+ 0.19468097040563787,
1657
+ -3.2512334784225763,
1658
+ -0.00924153565291559,
1659
+ 1.5204843353241098,
1660
+ 0.07798182574512524,
1661
+ 1.4701442832288814,
1662
+ -0.2929452539977395,
1663
+ -0.11577467076256517,
1664
+ 0.9647389322090653,
1665
+ 1.9858872735514685,
1666
+ -2.4927909960640844,
1667
+ -0.06697504969121937,
1668
+ -0.1419243624999926,
1669
+ -1.517841307461901,
1670
+ -2.0687187218783056,
1671
+ -1.2614639079416392,
1672
+ 1.1736154400259904,
1673
+ -0.8326453123673038,
1674
+ -1.5697756190106404,
1675
+ 0.32683263897219417,
1676
+ -2.4734284702186993,
1677
+ 2.091747552473343,
1678
+ -0.9691908324374187,
1679
+ 0.37825762336133084,
1680
+ 0.1020126631499464,
1681
+ -0.0004813377728839536,
1682
+ 3.618764084885732,
1683
+ -1.6506559142198896,
1684
+ 2.2909409044559705,
1685
+ 0.06314637510648614,
1686
+ -1.6704116106134392,
1687
+ -0.13752729803302502,
1688
+ 1.4935433740249338,
1689
+ -0.8510374687892082,
1690
+ -1.5441644703869135,
1691
+ 0.30552821349578935,
1692
+ 1.977193690357598,
1693
+ -0.14691666934434808,
1694
+ -2.774053107119484,
1695
+ -2.6133518087507257,
1696
+ -1.5367906501558772,
1697
+ -1.0542162507489161,
1698
+ -0.04285413008324925,
1699
+ 1.3409961419925638,
1700
+ -0.869234077144813,
1701
+ -2.2277595666256937,
1702
+ 1.2142119897569996,
1703
+ 0.5509139374791826,
1704
+ 2.3146941388294735,
1705
+ -3.3649617189565113,
1706
+ 0.17463817778974872,
1707
+ 2.706723787885337,
1708
+ 1.4483476013667382,
1709
+ -1.665105651528423,
1710
+ 1.4650569735368288,
1711
+ -1.7438537399944254,
1712
+ -0.9067950224595854,
1713
+ 2.3750685572581554,
1714
+ -0.5802906235801585,
1715
+ 1.6570922899308729,
1716
+ -0.5824554175583375,
1717
+ -3.1527248094958122,
1718
+ -1.6976313938978438,
1719
+ -2.1770397239143895,
1720
+ -0.968581142234347,
1721
+ -0.6726224180191456,
1722
+ -0.3067157813232876,
1723
+ -0.4864944571496919,
1724
+ 3.784404083200223,
1725
+ -2.7719966745708398,
1726
+ -0.8296486014155607,
1727
+ 0.6981630562136623,
1728
+ 3.256884531630813,
1729
+ 0.17704379142723264,
1730
+ 2.478301416801126,
1731
+ -3.2891110715074134,
1732
+ 2.892713050756959,
1733
+ -1.3811203433303656,
1734
+ -0.5528621709077041,
1735
+ -2.2188375197988743,
1736
+ 0.26773863285890354,
1737
+ 3.570678103463104,
1738
+ 4.8443267105031795,
1739
+ -2.1536578042368233,
1740
+ 0.971882220806198,
1741
+ 2.7770434774885837,
1742
+ -0.3913136345690878,
1743
+ -0.43634959541242196,
1744
+ -0.6095559090928905,
1745
+ 1.195665448222886,
1746
+ 2.7948588216315193,
1747
+ 1.3752395224799268,
1748
+ 0.6403760285939373,
1749
+ -0.6037398515545216,
1750
+ 0.9966973711158991,
1751
+ -1.0990738358335126,
1752
+ -0.5585130072744854,
1753
+ 2.1930268862234645,
1754
+ 0.8840261763576225,
1755
+ 0.48203258805222476,
1756
+ -0.5112153107110367,
1757
+ 1.8620658029697648
1758
+ ],
1759
+ w: [
1760
+ -0.49696586637986573,
1761
+ 0.8446407716647866,
1762
+ 1.9753065872793472,
1763
+ 1.6711363440700464,
1764
+ -1.321043718091411,
1765
+ 3.1281389865836706,
1766
+ -3.245951870583094,
1767
+ 1.727792746957976,
1768
+ -1.0232055468724002,
1769
+ -3.8347300508908027,
1770
+ -3.731627697239897,
1771
+ 0.4903581268793773,
1772
+ 4.447068603816132,
1773
+ 0.5467521282889305,
1774
+ 2.261569589056565,
1775
+ 1.6773387481201982,
1776
+ -1.3092305557564106,
1777
+ 1.907921956958791,
1778
+ 0.7059029309786451,
1779
+ 0.4131985852992269,
1780
+ 2.002226468620497,
1781
+ 1.4949039832805529,
1782
+ -1.2531496734462773,
1783
+ 0.7904473718734281,
1784
+ -1.7843359080911552,
1785
+ 1.2616368201835455,
1786
+ -0.865410366569135,
1787
+ 0.9042772884370336,
1788
+ 0.7359980903926909,
1789
+ -0.5407749793238182,
1790
+ 0.9310252354259575,
1791
+ 1.1487124512539382,
1792
+ -0.4613999803148218,
1793
+ 2.3444850166049025,
1794
+ 2.7854054134662434,
1795
+ -1.3239825114191694,
1796
+ -1.5547384134500284,
1797
+ 1.0270771578175601,
1798
+ -1.8266244760825443,
1799
+ -0.8988476105006012,
1800
+ 1.6058653982072366,
1801
+ -1.1469537019622078,
1802
+ -3.8562503356966524,
1803
+ 1.3287816676442965,
1804
+ -3.205080447588506,
1805
+ -2.709200514907699,
1806
+ -6.0358653588357924,
1807
+ 1.6624756444601259,
1808
+ 0.502194177694688,
1809
+ 0.9245869318826591,
1810
+ 1.6895844464464735,
1811
+ -0.0839430486431242,
1812
+ -2.2111518114000552,
1813
+ 1.1275513046617478,
1814
+ 2.606729511639341,
1815
+ -3.0004418755893147,
1816
+ -1.2139784702380723,
1817
+ -0.5844901313131545,
1818
+ -2.579366686647206,
1819
+ 1.3882116975493977,
1820
+ -1.198363805794238,
1821
+ 2.5138132879432744,
1822
+ 0.10701602725472605,
1823
+ 1.456185035343705,
1824
+ 3.1221961364212145,
1825
+ 0.5312495071943797,
1826
+ 2.1534525184145346,
1827
+ 0.4213958633584909,
1828
+ -3.0233470516447363,
1829
+ 0.044804519827250026,
1830
+ 1.4362724120842063,
1831
+ 0.9789140356845396,
1832
+ -0.34777669175653925,
1833
+ -2.435398977336801,
1834
+ 1.292796737418924,
1835
+ -1.8329120566957797,
1836
+ -2.5036468848511326,
1837
+ 1.1898554368110026,
1838
+ -2.465621330379653,
1839
+ 0.48872882981227517,
1840
+ 0.005544370687190118,
1841
+ -2.65641937205113,
1842
+ 2.35939282366555,
1843
+ -1.1856099982978574,
1844
+ 2.399956632673344,
1845
+ -0.9500673592242697,
1846
+ -1.1501141923016327,
1847
+ -0.06245204921699806,
1848
+ -0.7161139919569112,
1849
+ -0.7132021552954626,
1850
+ -1.7553287668674522,
1851
+ -2.4257942503559256,
1852
+ 1.2265732373740676,
1853
+ -1.6124066829249548,
1854
+ -2.7529138598177902,
1855
+ -1.0156957983270942,
1856
+ -1.6018709734746754,
1857
+ -4.385571371340135,
1858
+ -0.5818742985353497,
1859
+ 0.3343482423210354,
1860
+ 0.5893847129713754,
1861
+ 0.7854825308414517,
1862
+ -2.0016874260016304,
1863
+ -0.6514542396468678,
1864
+ -2.016697610857685,
1865
+ -1.2708629640675322,
1866
+ -2.419681375974685,
1867
+ -2.2329276013053807,
1868
+ 1.2597623251518704,
1869
+ -0.5450431403572512,
1870
+ -0.5176823367573421,
1871
+ 3.459116359782987,
1872
+ -0.11678433081474329,
1873
+ -1.0741275692178371,
1874
+ 1.4945733923314797,
1875
+ -0.9745156707794659,
1876
+ 2.7458155629590104,
1877
+ -0.7553447212924415,
1878
+ -1.2323052282367883,
1879
+ -2.3362501021493713,
1880
+ 0.6572807171821716,
1881
+ 2.93302125488033,
1882
+ -0.7120190901778252,
1883
+ 0.5229352837548622,
1884
+ 0.6666577103514623,
1885
+ 2.8443864806190855,
1886
+ 1.3277532013323454,
1887
+ -2.147310311390621,
1888
+ -1.3938035493334802,
1889
+ -1.4922609138691223,
1890
+ 0.2831457442644387,
1891
+ -0.007894441461306145,
1892
+ 0.7358750021835311,
1893
+ -1.314685829394494,
1894
+ -0.7526933403221041,
1895
+ 1.4827201208501692,
1896
+ -0.19921351289694036,
1897
+ -1.3085797572141897,
1898
+ 1.942328748122542,
1899
+ 0.02699262313677293,
1900
+ -1.83306933404309,
1901
+ 3.4193771225232736,
1902
+ -2.3362019798933114,
1903
+ -3.562072520305047,
1904
+ -4.506264897136434,
1905
+ 1.3022519390933986,
1906
+ -1.0656652512055347,
1907
+ -0.5511187139445664,
1908
+ 0.5792539452580913,
1909
+ -0.9329681235815281,
1910
+ -3.216120349889375,
1911
+ -3.899567592083976,
1912
+ -0.6813998364619616,
1913
+ 0.3494510546626397,
1914
+ -4.555555121554458,
1915
+ 0.5810489618941678,
1916
+ 0.8446127149472286,
1917
+ 2.5894747264134295,
1918
+ 0.32942803714790875,
1919
+ 0.4099076816004704,
1920
+ 1.2092072534516118,
1921
+ -0.03828153833786284,
1922
+ -0.15942869475761728,
1923
+ 0.2319689288056091,
1924
+ 1.4883467280967757,
1925
+ -0.8625812070553853,
1926
+ -0.9990579038224688,
1927
+ -1.7303241535114227,
1928
+ -1.915514566543747,
1929
+ 0.6535999426772754,
1930
+ 3.09474445137035,
1931
+ -1.9377191377288612,
1932
+ -0.37688085251892567,
1933
+ -2.060002322911837,
1934
+ 1.816172883720992,
1935
+ -0.634763729416257,
1936
+ 0.35800793308084394,
1937
+ 0.6960563754583543,
1938
+ -2.1085580425488804,
1939
+ -0.2094885762214029,
1940
+ -0.45668523418905876,
1941
+ 1.3507111248550778,
1942
+ -2.4664893870126186,
1943
+ -2.3999230888455583,
1944
+ 1.5317331532322156,
1945
+ -1.1761957225659538,
1946
+ -1.3205916599511518,
1947
+ 0.22602704439468746,
1948
+ -0.6407975993720775,
1949
+ 3.7327629938775755,
1950
+ 0.5190629115355975,
1951
+ 0.32312014183613985,
1952
+ 1.8621498186707084,
1953
+ -0.11989349851924225,
1954
+ 0.09747940015490032,
1955
+ -2.1457508014679263,
1956
+ -4.585942860961345,
1957
+ -2.414413700128684,
1958
+ 0.22821885959438232,
1959
+ -2.066594158210754
1960
+ ]
1961
+ };
1962
+ export {
1963
+ validateScatter3dStyle,
1964
+ scatter3dSpec,
1965
+ resolvePlot3dTarget,
1966
+ requireThreeNumericColumns,
1967
+ requireNumericColumn,
1968
+ plotScatter3d,
1969
+ plotModeration3d,
1970
+ numericColumns,
1971
+ moderationSurface,
1972
+ moderationData,
1973
+ moderation3dSpec,
1974
+ loadPlotly,
1975
+ isNumericColumn,
1976
+ interactiveScatter3d,
1977
+ interactiveModeration3d,
1978
+ frameRows,
1979
+ cameraFromRotations,
1980
+ DEFAULT_SCATTER3D_STYLE
1981
+ };
1982
+
1983
+ //# debugId=167ACAEEE5BCC45664756E2164756E21
1984
+ //# sourceMappingURL=3d.js.map