@ggterm/core 0.2.5 → 0.2.9
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/dist/canvas/canvas.d.ts.map +1 -1
- package/dist/cli-plot.d.ts +1 -1
- package/dist/cli-plot.js +11594 -0
- package/dist/cli.js +1468 -887
- package/dist/demo.d.ts +6 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/export/vega-lite.d.ts.map +1 -1
- package/dist/geoms/bin2d.d.ts +47 -0
- package/dist/geoms/bin2d.d.ts.map +1 -0
- package/dist/geoms/index.d.ts +1 -0
- package/dist/geoms/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2443 -1436
- package/dist/init.d.ts +8 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/pipeline/pipeline.d.ts.map +1 -1
- package/dist/pipeline/render-geoms.d.ts.map +1 -1
- package/dist/pipeline/scales.d.ts.map +1 -1
- package/dist/stats/bin2d.d.ts +34 -0
- package/dist/stats/bin2d.d.ts.map +1 -0
- package/dist/stats/density2d.d.ts +36 -0
- package/dist/stats/density2d.d.ts.map +1 -0
- package/dist/stats/index.d.ts +4 -0
- package/dist/stats/index.d.ts.map +1 -1
- package/package.json +5 -4
- package/dist/canvas/canvas.d.ts +0 -71
- package/dist/canvas/index.d.ts +0 -5
- package/dist/geoms/area.d.ts +0 -18
- package/dist/geoms/boxplot.d.ts +0 -25
- package/dist/geoms/line.d.ts +0 -31
- package/dist/geoms/segment.d.ts +0 -33
- package/dist/pipeline/pipeline.d.ts +0 -45
- package/dist/stats/bin.d.ts +0 -33
- package/dist/stats/boxplot.d.ts +0 -28
- package/dist/stats/smooth.d.ts +0 -33
- package/dist/stats/summary.d.ts +0 -32
- package/dist/themes/default.d.ts +0 -25
package/dist/cli.js
CHANGED
|
@@ -30,426 +30,74 @@ var __export = (target, all) => {
|
|
|
30
30
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
31
31
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
32
32
|
|
|
33
|
-
// src/
|
|
34
|
-
|
|
35
|
-
__export(exports_scales, {
|
|
36
|
-
niceDomain: () => niceDomain,
|
|
37
|
-
inferDiscreteDomain: () => inferDiscreteDomain,
|
|
38
|
-
inferContinuousDomain: () => inferContinuousDomain,
|
|
39
|
-
getTransformFunctions: () => getTransformFunctions,
|
|
40
|
-
expandDomain: () => expandDomain,
|
|
41
|
-
createResolvedSizeScale: () => createResolvedSizeScale,
|
|
42
|
-
createResolvedDiscreteScale: () => createResolvedDiscreteScale,
|
|
43
|
-
createResolvedDiscreteColorScale: () => createResolvedDiscreteColorScale,
|
|
44
|
-
createResolvedContinuousScale: () => createResolvedContinuousScale,
|
|
45
|
-
createResolvedContinuousColorScale: () => createResolvedContinuousColorScale,
|
|
46
|
-
buildScaleContext: () => buildScaleContext,
|
|
47
|
-
DEFAULT_POINT_COLOR: () => DEFAULT_POINT_COLOR
|
|
48
|
-
});
|
|
49
|
-
function inferContinuousDomain(data, field) {
|
|
50
|
-
let min = Infinity;
|
|
51
|
-
let max = -Infinity;
|
|
52
|
-
for (const row of data) {
|
|
53
|
-
const value = row[field];
|
|
54
|
-
if (typeof value === "number" && !isNaN(value)) {
|
|
55
|
-
if (value < min)
|
|
56
|
-
min = value;
|
|
57
|
-
if (value > max)
|
|
58
|
-
max = value;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (min === Infinity)
|
|
62
|
-
min = 0;
|
|
63
|
-
if (max === -Infinity)
|
|
64
|
-
max = 1;
|
|
65
|
-
if (min === max) {
|
|
66
|
-
min = min - 1;
|
|
67
|
-
max = max + 1;
|
|
68
|
-
}
|
|
69
|
-
return [min, max];
|
|
70
|
-
}
|
|
71
|
-
function inferDiscreteDomain(data, field, options = {}) {
|
|
72
|
-
const { limits, order = "alphabetical", reverse = false, exclude, drop = true } = options;
|
|
73
|
-
const seen = new Map;
|
|
74
|
-
let index = 0;
|
|
75
|
-
for (const row of data) {
|
|
76
|
-
const value = row[field];
|
|
77
|
-
if (value !== null && value !== undefined) {
|
|
78
|
-
const key = String(value);
|
|
79
|
-
if (!seen.has(key)) {
|
|
80
|
-
seen.set(key, { firstIndex: index, count: 1 });
|
|
81
|
-
} else {
|
|
82
|
-
seen.get(key).count++;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
index++;
|
|
86
|
-
}
|
|
87
|
-
let result;
|
|
88
|
-
if (limits) {
|
|
89
|
-
if (drop) {
|
|
90
|
-
result = limits.filter((v) => seen.has(v));
|
|
91
|
-
} else {
|
|
92
|
-
result = [...limits];
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
const values = Array.from(seen.keys());
|
|
96
|
-
switch (order) {
|
|
97
|
-
case "data":
|
|
98
|
-
result = values.sort((a, b) => seen.get(a).firstIndex - seen.get(b).firstIndex);
|
|
99
|
-
break;
|
|
100
|
-
case "frequency":
|
|
101
|
-
result = values.sort((a, b) => seen.get(b).count - seen.get(a).count);
|
|
102
|
-
break;
|
|
103
|
-
case "reverse":
|
|
104
|
-
result = values.sort().reverse();
|
|
105
|
-
break;
|
|
106
|
-
case "alphabetical":
|
|
107
|
-
default:
|
|
108
|
-
result = values.sort();
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (exclude && exclude.length > 0) {
|
|
113
|
-
const excludeSet = new Set(exclude);
|
|
114
|
-
result = result.filter((v) => !excludeSet.has(v));
|
|
115
|
-
}
|
|
116
|
-
if (reverse) {
|
|
117
|
-
result = result.reverse();
|
|
118
|
-
}
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
|
-
function expandDomain(domain, expand = 0.05) {
|
|
122
|
-
const range = domain[1] - domain[0];
|
|
123
|
-
const padding = range * expand;
|
|
124
|
-
return [domain[0] - padding, domain[1] + padding];
|
|
125
|
-
}
|
|
126
|
-
function niceStep(range, targetTicks = 5) {
|
|
127
|
-
const rawStep = range / Math.max(1, targetTicks - 1);
|
|
128
|
-
const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));
|
|
129
|
-
const normalized = rawStep / magnitude;
|
|
130
|
-
let nice;
|
|
131
|
-
if (normalized <= 1.5)
|
|
132
|
-
nice = 1;
|
|
133
|
-
else if (normalized <= 3)
|
|
134
|
-
nice = 2;
|
|
135
|
-
else if (normalized <= 7)
|
|
136
|
-
nice = 5;
|
|
137
|
-
else
|
|
138
|
-
nice = 10;
|
|
139
|
-
return nice * magnitude;
|
|
140
|
-
}
|
|
141
|
-
function niceDomain(domain, targetTicks = 5) {
|
|
142
|
-
const [min, max] = domain;
|
|
143
|
-
const range = max - min;
|
|
144
|
-
if (range === 0) {
|
|
145
|
-
if (min === 0)
|
|
146
|
-
return [-1, 1];
|
|
147
|
-
const magnitude = Math.pow(10, Math.floor(Math.log10(Math.abs(min))));
|
|
148
|
-
return [min - magnitude, min + magnitude];
|
|
149
|
-
}
|
|
150
|
-
const step = niceStep(range, targetTicks);
|
|
151
|
-
const niceMin = Math.floor(min / step) * step;
|
|
152
|
-
const niceMax = Math.ceil(max / step) * step;
|
|
153
|
-
return [niceMin, niceMax];
|
|
154
|
-
}
|
|
155
|
-
function getTransformFunctions(trans = "identity") {
|
|
156
|
-
switch (trans) {
|
|
157
|
-
case "log10":
|
|
158
|
-
return {
|
|
159
|
-
type: "log10",
|
|
160
|
-
transform: (v) => v > 0 ? Math.log10(v) : -Infinity,
|
|
161
|
-
invert: (v) => Math.pow(10, v)
|
|
162
|
-
};
|
|
163
|
-
case "sqrt":
|
|
164
|
-
return {
|
|
165
|
-
type: "sqrt",
|
|
166
|
-
transform: (v) => v >= 0 ? Math.sqrt(v) : 0,
|
|
167
|
-
invert: (v) => v * v
|
|
168
|
-
};
|
|
169
|
-
case "reverse":
|
|
170
|
-
return {
|
|
171
|
-
type: "reverse",
|
|
172
|
-
transform: (v) => -v,
|
|
173
|
-
invert: (v) => -v
|
|
174
|
-
};
|
|
175
|
-
default:
|
|
176
|
-
return {
|
|
177
|
-
type: "identity",
|
|
178
|
-
transform: (v) => v,
|
|
179
|
-
invert: (v) => v
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
function createResolvedContinuousScale(aesthetic, domain, range, trans = "identity") {
|
|
184
|
-
const [domainMin, domainMax] = domain;
|
|
185
|
-
const [rangeMin, rangeMax] = range;
|
|
186
|
-
const rangeSpan = rangeMax - rangeMin;
|
|
187
|
-
const { transform, invert } = getTransformFunctions(trans);
|
|
33
|
+
// src/themes/default.ts
|
|
34
|
+
function defaultTheme() {
|
|
188
35
|
return {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
trans,
|
|
194
|
-
transform,
|
|
195
|
-
invert,
|
|
196
|
-
normalize(value) {
|
|
197
|
-
const num = Number(value);
|
|
198
|
-
if (isNaN(num))
|
|
199
|
-
return 0;
|
|
200
|
-
const transformed = transform(num);
|
|
201
|
-
const transformedMin = transform(domainMin);
|
|
202
|
-
const transformedMax = transform(domainMax);
|
|
203
|
-
if (transformedMax === transformedMin)
|
|
204
|
-
return 0.5;
|
|
205
|
-
return (transformed - transformedMin) / (transformedMax - transformedMin);
|
|
36
|
+
panel: {
|
|
37
|
+
background: "",
|
|
38
|
+
border: "single",
|
|
39
|
+
grid: { major: "·", minor: null }
|
|
206
40
|
},
|
|
207
|
-
|
|
208
|
-
|
|
41
|
+
axis: {
|
|
42
|
+
text: { color: "" },
|
|
43
|
+
ticks: { char: "┼", length: 1 },
|
|
44
|
+
title: { color: "", bold: false }
|
|
209
45
|
},
|
|
210
|
-
|
|
211
|
-
|
|
46
|
+
legend: {
|
|
47
|
+
position: "right",
|
|
48
|
+
title: { bold: true }
|
|
49
|
+
},
|
|
50
|
+
title: {
|
|
51
|
+
align: "center",
|
|
52
|
+
bold: true
|
|
53
|
+
},
|
|
54
|
+
facet: {
|
|
55
|
+
strip: {
|
|
56
|
+
text: "#c8c8c8",
|
|
57
|
+
background: ""
|
|
58
|
+
}
|
|
212
59
|
}
|
|
213
60
|
};
|
|
214
61
|
}
|
|
215
|
-
function
|
|
216
|
-
const [rangeMin, rangeMax] = range;
|
|
217
|
-
const rangeSpan = rangeMax - rangeMin;
|
|
62
|
+
function themeMinimal() {
|
|
218
63
|
return {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
normalize(value) {
|
|
224
|
-
const str = String(value);
|
|
225
|
-
const index = domain.indexOf(str);
|
|
226
|
-
if (index < 0)
|
|
227
|
-
return 0;
|
|
228
|
-
return domain.length > 1 ? index / (domain.length - 1) : 0.5;
|
|
64
|
+
panel: {
|
|
65
|
+
background: "",
|
|
66
|
+
border: "none",
|
|
67
|
+
grid: { major: null, minor: null }
|
|
229
68
|
},
|
|
230
|
-
|
|
231
|
-
|
|
69
|
+
axis: {
|
|
70
|
+
text: { color: "" },
|
|
71
|
+
ticks: { char: "│", length: 1 },
|
|
72
|
+
title: { color: "", bold: false }
|
|
232
73
|
},
|
|
233
|
-
|
|
234
|
-
|
|
74
|
+
legend: {
|
|
75
|
+
position: "right",
|
|
76
|
+
title: { bold: false }
|
|
77
|
+
},
|
|
78
|
+
title: {
|
|
79
|
+
align: "left",
|
|
80
|
+
bold: false
|
|
81
|
+
},
|
|
82
|
+
facet: {
|
|
83
|
+
strip: {
|
|
84
|
+
text: "#999999",
|
|
85
|
+
background: ""
|
|
86
|
+
}
|
|
235
87
|
}
|
|
236
88
|
};
|
|
237
89
|
}
|
|
238
|
-
function
|
|
239
|
-
return {
|
|
240
|
-
r: Math.round(color1.r + (color2.r - color1.r) * t),
|
|
241
|
-
g: Math.round(color1.g + (color2.g - color1.g) * t),
|
|
242
|
-
b: Math.round(color1.b + (color2.b - color1.b) * t),
|
|
243
|
-
a: color1.a + (color2.a - color1.a) * t
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
function createResolvedDiscreteColorScale(domain, palette = CATEGORY_COLORS) {
|
|
247
|
-
return {
|
|
248
|
-
aesthetic: "color",
|
|
249
|
-
type: "discrete",
|
|
250
|
-
domain,
|
|
251
|
-
map(value) {
|
|
252
|
-
const str = String(value);
|
|
253
|
-
const index = domain.indexOf(str);
|
|
254
|
-
if (index < 0)
|
|
255
|
-
return palette[0];
|
|
256
|
-
return palette[index % palette.length];
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
function createResolvedContinuousColorScale(domain, lowColor = { r: 68, g: 1, b: 84, a: 1 }, highColor = { r: 253, g: 231, b: 37, a: 1 }) {
|
|
261
|
-
const [min, max] = domain;
|
|
262
|
-
const span = max - min;
|
|
263
|
-
return {
|
|
264
|
-
aesthetic: "color",
|
|
265
|
-
type: "continuous",
|
|
266
|
-
domain,
|
|
267
|
-
map(value) {
|
|
268
|
-
const num = Number(value);
|
|
269
|
-
if (isNaN(num))
|
|
270
|
-
return lowColor;
|
|
271
|
-
const t = Math.max(0, Math.min(1, (num - min) / span));
|
|
272
|
-
return interpolateColor(lowColor, highColor, t);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
function isCategoricalField(data, field) {
|
|
277
|
-
for (const row of data) {
|
|
278
|
-
const value = row[field];
|
|
279
|
-
if (value !== null && value !== undefined) {
|
|
280
|
-
if (typeof value === "string" && isNaN(Number(value))) {
|
|
281
|
-
return true;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return false;
|
|
286
|
-
}
|
|
287
|
-
function createResolvedSizeScale(domain) {
|
|
288
|
-
const [min, max] = domain;
|
|
289
|
-
const span = max - min;
|
|
290
|
-
return {
|
|
291
|
-
aesthetic: "size",
|
|
292
|
-
type: "continuous",
|
|
293
|
-
domain,
|
|
294
|
-
map(value) {
|
|
295
|
-
const num = Number(value);
|
|
296
|
-
if (isNaN(num))
|
|
297
|
-
return 1;
|
|
298
|
-
const t = Math.max(0, Math.min(1, (num - min) / span));
|
|
299
|
-
return Math.floor(t * 3.99);
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
function computeDomain(data, field, trans = "identity") {
|
|
304
|
-
const rawDomain = inferContinuousDomain(data, field);
|
|
305
|
-
if (trans === "log10") {
|
|
306
|
-
const [min, max] = rawDomain;
|
|
307
|
-
const safeMin = min > 0 ? min : 0.001;
|
|
308
|
-
const safeMax = max > 0 ? max : 1;
|
|
309
|
-
const minPow = Math.floor(Math.log10(safeMin));
|
|
310
|
-
const maxPow = Math.ceil(Math.log10(safeMax));
|
|
311
|
-
return [Math.pow(10, minPow), Math.pow(10, maxPow)];
|
|
312
|
-
}
|
|
313
|
-
return niceDomain(rawDomain);
|
|
314
|
-
}
|
|
315
|
-
function buildScaleContext(data, aes, plotArea, userScales = [], coordLimits) {
|
|
316
|
-
const userXScale = userScales.find((s) => s.aesthetic === "x");
|
|
317
|
-
const userYScale = userScales.find((s) => s.aesthetic === "y");
|
|
318
|
-
const userColorScale = userScales.find((s) => s.aesthetic === "color" || s.aesthetic === "fill");
|
|
319
|
-
const xIsCategorical = isCategoricalField(data, aes.x);
|
|
320
|
-
let x;
|
|
321
|
-
if (xIsCategorical) {
|
|
322
|
-
const xOrderOptions = {};
|
|
323
|
-
if (userXScale) {
|
|
324
|
-
if (userXScale.domain && Array.isArray(userXScale.domain)) {
|
|
325
|
-
xOrderOptions.limits = userXScale.domain;
|
|
326
|
-
}
|
|
327
|
-
const orderOpts = userXScale.orderOptions;
|
|
328
|
-
if (orderOpts) {
|
|
329
|
-
if (orderOpts.order)
|
|
330
|
-
xOrderOptions.order = orderOpts.order;
|
|
331
|
-
if (orderOpts.reverse)
|
|
332
|
-
xOrderOptions.reverse = orderOpts.reverse;
|
|
333
|
-
if (orderOpts.exclude)
|
|
334
|
-
xOrderOptions.exclude = orderOpts.exclude;
|
|
335
|
-
if (orderOpts.drop !== undefined)
|
|
336
|
-
xOrderOptions.drop = orderOpts.drop;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
const xDomain = inferDiscreteDomain(data, aes.x, xOrderOptions);
|
|
340
|
-
x = createResolvedDiscreteScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1]);
|
|
341
|
-
if (userXScale?.labels) {
|
|
342
|
-
x.labels = userXScale.labels;
|
|
343
|
-
}
|
|
344
|
-
} else {
|
|
345
|
-
const xTrans = userXScale?.trans ?? "identity";
|
|
346
|
-
const xDomain = coordLimits?.xlim ?? userXScale?.domain ?? computeDomain(data, aes.x, xTrans);
|
|
347
|
-
x = createResolvedContinuousScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1], xTrans);
|
|
348
|
-
if (userXScale?.breaks) {
|
|
349
|
-
x.breaks = userXScale.breaks;
|
|
350
|
-
}
|
|
351
|
-
if (userXScale?.labels) {
|
|
352
|
-
x.labels = userXScale.labels;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
const yTrans = userYScale?.trans ?? "identity";
|
|
356
|
-
const yDomain = coordLimits?.ylim ?? userYScale?.domain ?? computeDomain(data, aes.y, yTrans);
|
|
357
|
-
const y = createResolvedContinuousScale("y", yDomain, [plotArea.y + plotArea.height - 1, plotArea.y], yTrans);
|
|
358
|
-
if (userYScale?.breaks) {
|
|
359
|
-
y.breaks = userYScale.breaks;
|
|
360
|
-
}
|
|
361
|
-
if (userYScale?.labels) {
|
|
362
|
-
y.labels = userYScale.labels;
|
|
363
|
-
}
|
|
364
|
-
const context = { x, y };
|
|
365
|
-
if (aes.y2) {
|
|
366
|
-
const userY2Scale = userScales.find((s) => s.aesthetic === "y2");
|
|
367
|
-
const y2Trans = userY2Scale?.trans ?? "identity";
|
|
368
|
-
const y2Domain = userY2Scale?.domain ?? computeDomain(data, aes.y2, y2Trans);
|
|
369
|
-
const y2 = createResolvedContinuousScale("y2", y2Domain, [plotArea.y + plotArea.height - 1, plotArea.y], y2Trans);
|
|
370
|
-
if (userY2Scale?.breaks) {
|
|
371
|
-
y2.breaks = userY2Scale.breaks;
|
|
372
|
-
}
|
|
373
|
-
if (userY2Scale?.labels) {
|
|
374
|
-
y2.labels = userY2Scale.labels;
|
|
375
|
-
}
|
|
376
|
-
context.y2 = y2;
|
|
377
|
-
}
|
|
378
|
-
const colorAesField = aes.color || aes.fill;
|
|
379
|
-
if (colorAesField) {
|
|
380
|
-
const colorOrderOptions = {};
|
|
381
|
-
if (userColorScale) {
|
|
382
|
-
if (userColorScale.domain && Array.isArray(userColorScale.domain)) {
|
|
383
|
-
colorOrderOptions.limits = userColorScale.domain;
|
|
384
|
-
}
|
|
385
|
-
const orderOpts = userColorScale.orderOptions;
|
|
386
|
-
if (orderOpts) {
|
|
387
|
-
if (orderOpts.order)
|
|
388
|
-
colorOrderOptions.order = orderOpts.order;
|
|
389
|
-
if (orderOpts.reverse)
|
|
390
|
-
colorOrderOptions.reverse = orderOpts.reverse;
|
|
391
|
-
if (orderOpts.exclude)
|
|
392
|
-
colorOrderOptions.exclude = orderOpts.exclude;
|
|
393
|
-
if (orderOpts.drop !== undefined)
|
|
394
|
-
colorOrderOptions.drop = orderOpts.drop;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
const colorDomain = inferDiscreteDomain(data, colorAesField, colorOrderOptions);
|
|
398
|
-
if (userColorScale && userColorScale.map) {
|
|
399
|
-
context.color = {
|
|
400
|
-
aesthetic: userColorScale.aesthetic || "color",
|
|
401
|
-
type: userColorScale.type === "continuous" ? "continuous" : "discrete",
|
|
402
|
-
domain: userColorScale.type === "continuous" ? userColorScale.domain ?? inferContinuousDomain(data, colorAesField) : colorDomain,
|
|
403
|
-
map: (value) => {
|
|
404
|
-
const result = userColorScale.map(value);
|
|
405
|
-
if (typeof result === "object" && "r" in result) {
|
|
406
|
-
return result;
|
|
407
|
-
}
|
|
408
|
-
return { r: 128, g: 128, b: 128, a: 1 };
|
|
409
|
-
}
|
|
410
|
-
};
|
|
411
|
-
} else {
|
|
412
|
-
context.color = createResolvedDiscreteColorScale(colorDomain);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
if (aes.size) {
|
|
416
|
-
const sizeDomain = inferContinuousDomain(data, aes.size);
|
|
417
|
-
context.size = createResolvedSizeScale(sizeDomain);
|
|
418
|
-
}
|
|
419
|
-
return context;
|
|
420
|
-
}
|
|
421
|
-
var CATEGORY_COLORS, DEFAULT_POINT_COLOR;
|
|
422
|
-
var init_scales = __esm(() => {
|
|
423
|
-
CATEGORY_COLORS = [
|
|
424
|
-
{ r: 31, g: 119, b: 180, a: 1 },
|
|
425
|
-
{ r: 255, g: 127, b: 14, a: 1 },
|
|
426
|
-
{ r: 44, g: 160, b: 44, a: 1 },
|
|
427
|
-
{ r: 214, g: 39, b: 40, a: 1 },
|
|
428
|
-
{ r: 148, g: 103, b: 189, a: 1 },
|
|
429
|
-
{ r: 140, g: 86, b: 75, a: 1 },
|
|
430
|
-
{ r: 227, g: 119, b: 194, a: 1 },
|
|
431
|
-
{ r: 127, g: 127, b: 127, a: 1 },
|
|
432
|
-
{ r: 188, g: 189, b: 34, a: 1 },
|
|
433
|
-
{ r: 23, g: 190, b: 207, a: 1 }
|
|
434
|
-
];
|
|
435
|
-
DEFAULT_POINT_COLOR = { r: 79, g: 169, b: 238, a: 1 };
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
// src/repl/repl.ts
|
|
439
|
-
import * as readline from "readline";
|
|
440
|
-
|
|
441
|
-
// src/themes/default.ts
|
|
442
|
-
function defaultTheme() {
|
|
90
|
+
function themeDark() {
|
|
443
91
|
return {
|
|
444
92
|
panel: {
|
|
445
|
-
background: "",
|
|
446
|
-
border: "
|
|
93
|
+
background: "#1e1e1e",
|
|
94
|
+
border: "rounded",
|
|
447
95
|
grid: { major: "·", minor: null }
|
|
448
96
|
},
|
|
449
97
|
axis: {
|
|
450
|
-
text: { color: "" },
|
|
98
|
+
text: { color: "#ccc" },
|
|
451
99
|
ticks: { char: "┼", length: 1 },
|
|
452
|
-
title: { color: "", bold:
|
|
100
|
+
title: { color: "#fff", bold: true }
|
|
453
101
|
},
|
|
454
102
|
legend: {
|
|
455
103
|
position: "right",
|
|
@@ -461,51 +109,23 @@ function defaultTheme() {
|
|
|
461
109
|
},
|
|
462
110
|
facet: {
|
|
463
111
|
strip: {
|
|
464
|
-
text: "#
|
|
465
|
-
background: ""
|
|
112
|
+
text: "#ffffff",
|
|
113
|
+
background: "#333333"
|
|
466
114
|
}
|
|
467
115
|
}
|
|
468
116
|
};
|
|
469
117
|
}
|
|
470
|
-
function
|
|
118
|
+
function themeClassic() {
|
|
471
119
|
return {
|
|
472
120
|
panel: {
|
|
473
121
|
background: "",
|
|
474
|
-
border: "
|
|
122
|
+
border: "single",
|
|
475
123
|
grid: { major: null, minor: null }
|
|
476
124
|
},
|
|
477
125
|
axis: {
|
|
478
126
|
text: { color: "" },
|
|
479
|
-
ticks: { char: "
|
|
480
|
-
title: { color: "", bold:
|
|
481
|
-
},
|
|
482
|
-
legend: {
|
|
483
|
-
position: "right",
|
|
484
|
-
title: { bold: false }
|
|
485
|
-
},
|
|
486
|
-
title: {
|
|
487
|
-
align: "left",
|
|
488
|
-
bold: false
|
|
489
|
-
},
|
|
490
|
-
facet: {
|
|
491
|
-
strip: {
|
|
492
|
-
text: "#999999",
|
|
493
|
-
background: ""
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
function themeDark() {
|
|
499
|
-
return {
|
|
500
|
-
panel: {
|
|
501
|
-
background: "#1e1e1e",
|
|
502
|
-
border: "rounded",
|
|
503
|
-
grid: { major: "·", minor: null }
|
|
504
|
-
},
|
|
505
|
-
axis: {
|
|
506
|
-
text: { color: "#ccc" },
|
|
507
|
-
ticks: { char: "┼", length: 1 },
|
|
508
|
-
title: { color: "#fff", bold: true }
|
|
127
|
+
ticks: { char: "─", length: 1 },
|
|
128
|
+
title: { color: "", bold: true }
|
|
509
129
|
},
|
|
510
130
|
legend: {
|
|
511
131
|
position: "right",
|
|
@@ -517,304 +137,705 @@ function themeDark() {
|
|
|
517
137
|
},
|
|
518
138
|
facet: {
|
|
519
139
|
strip: {
|
|
520
|
-
text: "#
|
|
521
|
-
background: "
|
|
140
|
+
text: "#c8c8c8",
|
|
141
|
+
background: ""
|
|
522
142
|
}
|
|
523
143
|
}
|
|
524
144
|
};
|
|
525
145
|
}
|
|
526
|
-
function
|
|
146
|
+
function themeVoid() {
|
|
527
147
|
return {
|
|
528
148
|
panel: {
|
|
529
149
|
background: "",
|
|
530
|
-
border: "
|
|
150
|
+
border: "none",
|
|
531
151
|
grid: { major: null, minor: null }
|
|
532
152
|
},
|
|
533
153
|
axis: {
|
|
534
154
|
text: { color: "" },
|
|
535
|
-
ticks: { char: "
|
|
536
|
-
title: { color: "", bold:
|
|
155
|
+
ticks: { char: "", length: 0 },
|
|
156
|
+
title: { color: "", bold: false }
|
|
537
157
|
},
|
|
538
158
|
legend: {
|
|
539
|
-
position: "
|
|
540
|
-
title: { bold:
|
|
159
|
+
position: "none",
|
|
160
|
+
title: { bold: false }
|
|
541
161
|
},
|
|
542
162
|
title: {
|
|
543
|
-
align: "
|
|
544
|
-
bold:
|
|
163
|
+
align: "left",
|
|
164
|
+
bold: false
|
|
545
165
|
},
|
|
546
166
|
facet: {
|
|
547
167
|
strip: {
|
|
548
|
-
text: "#
|
|
168
|
+
text: "#888888",
|
|
549
169
|
background: ""
|
|
550
170
|
}
|
|
551
171
|
}
|
|
552
|
-
};
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// src/coords/cartesian.ts
|
|
176
|
+
function coordCartesian(options = {}) {
|
|
177
|
+
return {
|
|
178
|
+
type: "cartesian",
|
|
179
|
+
xlim: options.xlim,
|
|
180
|
+
ylim: options.ylim,
|
|
181
|
+
clip: options.clip ?? true,
|
|
182
|
+
transform(x, y) {
|
|
183
|
+
return { x, y };
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function coordFlip() {
|
|
188
|
+
return {
|
|
189
|
+
type: "flip",
|
|
190
|
+
transform(x, y) {
|
|
191
|
+
return { x: y, y: x };
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function coordPolar(options = {}) {
|
|
196
|
+
const theta = options.theta ?? "x";
|
|
197
|
+
return {
|
|
198
|
+
type: "polar",
|
|
199
|
+
transform(x, y) {
|
|
200
|
+
const angle = theta === "x" ? x : y;
|
|
201
|
+
const radius = theta === "x" ? y : x;
|
|
202
|
+
return {
|
|
203
|
+
x: radius * Math.cos(angle),
|
|
204
|
+
y: radius * Math.sin(angle)
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function coordFixed(options = {}) {
|
|
210
|
+
const ratio = options.ratio ?? 1;
|
|
211
|
+
return {
|
|
212
|
+
type: "fixed",
|
|
213
|
+
xlim: options.xlim,
|
|
214
|
+
ylim: options.ylim,
|
|
215
|
+
clip: options.clip ?? true,
|
|
216
|
+
ratio,
|
|
217
|
+
transform(x, y) {
|
|
218
|
+
return { x, y };
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function coordEqual(options = {}) {
|
|
223
|
+
return coordFixed({ ...options, ratio: 1 });
|
|
224
|
+
}
|
|
225
|
+
function getTransform(type) {
|
|
226
|
+
switch (type) {
|
|
227
|
+
case "log10":
|
|
228
|
+
return (v) => v > 0 ? Math.log10(v) : -Infinity;
|
|
229
|
+
case "sqrt":
|
|
230
|
+
return (v) => v >= 0 ? Math.sqrt(v) : 0;
|
|
231
|
+
case "reverse":
|
|
232
|
+
return (v) => -v;
|
|
233
|
+
default:
|
|
234
|
+
return (v) => v;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function coordTrans(options = {}) {
|
|
238
|
+
const xTrans = getTransform(options.x ?? "identity");
|
|
239
|
+
const yTrans = getTransform(options.y ?? "identity");
|
|
240
|
+
return {
|
|
241
|
+
type: "trans",
|
|
242
|
+
xlim: options.xlim,
|
|
243
|
+
ylim: options.ylim,
|
|
244
|
+
clip: options.clip ?? true,
|
|
245
|
+
xTransType: options.x ?? "identity",
|
|
246
|
+
yTransType: options.y ?? "identity",
|
|
247
|
+
transform(x, y) {
|
|
248
|
+
return {
|
|
249
|
+
x: xTrans(x),
|
|
250
|
+
y: yTrans(y)
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function coordFlipWithLimits(options = {}) {
|
|
256
|
+
return {
|
|
257
|
+
type: "flip",
|
|
258
|
+
xlim: options.xlim,
|
|
259
|
+
ylim: options.ylim,
|
|
260
|
+
clip: options.clip ?? true,
|
|
261
|
+
transform(x, y) {
|
|
262
|
+
return { x: y, y: x };
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/canvas/canvas.ts
|
|
268
|
+
function createEmptyCell() {
|
|
269
|
+
return {
|
|
270
|
+
char: " ",
|
|
271
|
+
fg: { ...DEFAULT_FG },
|
|
272
|
+
bg: { ...DEFAULT_BG }
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
class TerminalCanvas {
|
|
277
|
+
width;
|
|
278
|
+
height;
|
|
279
|
+
cells;
|
|
280
|
+
constructor(width, height) {
|
|
281
|
+
this.width = width;
|
|
282
|
+
this.height = height;
|
|
283
|
+
this.cells = [];
|
|
284
|
+
this.clear();
|
|
285
|
+
}
|
|
286
|
+
setCell(x, y, cell) {
|
|
287
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || x >= this.width || y < 0 || y >= this.height) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const ix = Math.floor(x);
|
|
291
|
+
const iy = Math.floor(y);
|
|
292
|
+
const existing = this.cells[iy][ix];
|
|
293
|
+
this.cells[iy][ix] = {
|
|
294
|
+
char: cell.char ?? existing.char,
|
|
295
|
+
fg: cell.fg ?? existing.fg,
|
|
296
|
+
bg: cell.bg ?? existing.bg,
|
|
297
|
+
bold: cell.bold ?? existing.bold,
|
|
298
|
+
italic: cell.italic ?? existing.italic,
|
|
299
|
+
underline: cell.underline ?? existing.underline
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
getCell(x, y) {
|
|
303
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || x >= this.width || y < 0 || y >= this.height) {
|
|
304
|
+
return createEmptyCell();
|
|
305
|
+
}
|
|
306
|
+
return this.cells[Math.floor(y)][Math.floor(x)];
|
|
307
|
+
}
|
|
308
|
+
clear() {
|
|
309
|
+
this.cells = [];
|
|
310
|
+
for (let y = 0;y < this.height; y++) {
|
|
311
|
+
const row = [];
|
|
312
|
+
for (let x = 0;x < this.width; x++) {
|
|
313
|
+
row.push(createEmptyCell());
|
|
314
|
+
}
|
|
315
|
+
this.cells.push(row);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
drawChar(x, y, char, fg) {
|
|
319
|
+
this.setCell(x, y, { char, fg });
|
|
320
|
+
}
|
|
321
|
+
drawString(x, y, str, fg) {
|
|
322
|
+
for (let i = 0;i < str.length; i++) {
|
|
323
|
+
this.drawChar(x + i, y, str[i], fg);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
drawHLine(x, y, length, char = "─", fg) {
|
|
327
|
+
for (let i = 0;i < length; i++) {
|
|
328
|
+
this.drawChar(x + i, y, char, fg);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
drawVLine(x, y, length, char = "│", fg) {
|
|
332
|
+
for (let i = 0;i < length; i++) {
|
|
333
|
+
this.drawChar(x, y + i, char, fg);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
drawPoint(x, y, fg, shape = "●") {
|
|
337
|
+
this.drawChar(x, y, shape, fg);
|
|
338
|
+
}
|
|
339
|
+
fillRect(x, y, width, height, char = " ", fg, bg) {
|
|
340
|
+
for (let dy = 0;dy < height; dy++) {
|
|
341
|
+
for (let dx = 0;dx < width; dx++) {
|
|
342
|
+
this.setCell(x + dx, y + dy, { char, fg, bg });
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
drawBox(x, y, width, height, style = "single", fg) {
|
|
347
|
+
const chars = style === "double" ? { tl: "╔", tr: "╗", bl: "╚", br: "╝", h: "═", v: "║" } : style === "rounded" ? { tl: "╭", tr: "╮", bl: "╰", br: "╯", h: "─", v: "│" } : { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│" };
|
|
348
|
+
this.drawChar(x, y, chars.tl, fg);
|
|
349
|
+
this.drawChar(x + width - 1, y, chars.tr, fg);
|
|
350
|
+
this.drawChar(x, y + height - 1, chars.bl, fg);
|
|
351
|
+
this.drawChar(x + width - 1, y + height - 1, chars.br, fg);
|
|
352
|
+
this.drawHLine(x + 1, y, width - 2, chars.h, fg);
|
|
353
|
+
this.drawHLine(x + 1, y + height - 1, width - 2, chars.h, fg);
|
|
354
|
+
this.drawVLine(x, y + 1, height - 2, chars.v, fg);
|
|
355
|
+
this.drawVLine(x + width - 1, y + 1, height - 2, chars.v, fg);
|
|
356
|
+
}
|
|
357
|
+
toString() {
|
|
358
|
+
return this.cells.map((row) => row.map((cell) => cell.char).join("")).join(`
|
|
359
|
+
`);
|
|
360
|
+
}
|
|
361
|
+
toAnsiString() {
|
|
362
|
+
const lines = [];
|
|
363
|
+
for (const row of this.cells) {
|
|
364
|
+
let line = "";
|
|
365
|
+
let currentFg = null;
|
|
366
|
+
let currentBg = null;
|
|
367
|
+
for (const cell of row) {
|
|
368
|
+
const fgChanged = !currentFg || currentFg.r !== cell.fg.r || currentFg.g !== cell.fg.g || currentFg.b !== cell.fg.b;
|
|
369
|
+
const bgChanged = cell.bg.a > 0 && (!currentBg || currentBg.r !== cell.bg.r || currentBg.g !== cell.bg.g || currentBg.b !== cell.bg.b);
|
|
370
|
+
if (fgChanged) {
|
|
371
|
+
line += `\x1B[38;2;${cell.fg.r};${cell.fg.g};${cell.fg.b}m`;
|
|
372
|
+
currentFg = cell.fg;
|
|
373
|
+
}
|
|
374
|
+
if (bgChanged) {
|
|
375
|
+
line += `\x1B[48;2;${cell.bg.r};${cell.bg.g};${cell.bg.b}m`;
|
|
376
|
+
currentBg = cell.bg;
|
|
377
|
+
}
|
|
378
|
+
if (cell.bold)
|
|
379
|
+
line += "\x1B[1m";
|
|
380
|
+
if (cell.italic)
|
|
381
|
+
line += "\x1B[3m";
|
|
382
|
+
if (cell.underline)
|
|
383
|
+
line += "\x1B[4m";
|
|
384
|
+
line += cell.char;
|
|
385
|
+
if (cell.bold || cell.italic || cell.underline) {
|
|
386
|
+
line += "\x1B[22;23;24m";
|
|
387
|
+
if (currentFg) {
|
|
388
|
+
line += `\x1B[38;2;${currentFg.r};${currentFg.g};${currentFg.b}m`;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
line += "\x1B[0m";
|
|
393
|
+
lines.push(line);
|
|
394
|
+
}
|
|
395
|
+
return lines.join(`
|
|
396
|
+
`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
function createCanvas(width, height) {
|
|
400
|
+
return new TerminalCanvas(width, height);
|
|
401
|
+
}
|
|
402
|
+
var DEFAULT_FG, DEFAULT_BG;
|
|
403
|
+
var init_canvas = __esm(() => {
|
|
404
|
+
DEFAULT_FG = { r: 255, g: 255, b: 255, a: 1 };
|
|
405
|
+
DEFAULT_BG = { r: 0, g: 0, b: 0, a: 0 };
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// src/pipeline/scales.ts
|
|
409
|
+
var exports_scales = {};
|
|
410
|
+
__export(exports_scales, {
|
|
411
|
+
niceDomain: () => niceDomain,
|
|
412
|
+
inferDiscreteDomain: () => inferDiscreteDomain,
|
|
413
|
+
inferContinuousDomain: () => inferContinuousDomain,
|
|
414
|
+
getTransformFunctions: () => getTransformFunctions,
|
|
415
|
+
expandDomain: () => expandDomain,
|
|
416
|
+
createResolvedSizeScale: () => createResolvedSizeScale,
|
|
417
|
+
createResolvedDiscreteScale: () => createResolvedDiscreteScale,
|
|
418
|
+
createResolvedDiscreteColorScale: () => createResolvedDiscreteColorScale,
|
|
419
|
+
createResolvedContinuousScale: () => createResolvedContinuousScale,
|
|
420
|
+
createResolvedContinuousColorScale: () => createResolvedContinuousColorScale,
|
|
421
|
+
buildScaleContext: () => buildScaleContext,
|
|
422
|
+
DEFAULT_POINT_COLOR: () => DEFAULT_POINT_COLOR
|
|
423
|
+
});
|
|
424
|
+
function inferContinuousDomain(data, field) {
|
|
425
|
+
let min = Infinity;
|
|
426
|
+
let max = -Infinity;
|
|
427
|
+
for (const row of data) {
|
|
428
|
+
const value = row[field];
|
|
429
|
+
if (typeof value === "number" && !isNaN(value)) {
|
|
430
|
+
if (value < min)
|
|
431
|
+
min = value;
|
|
432
|
+
if (value > max)
|
|
433
|
+
max = value;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (min === Infinity)
|
|
437
|
+
min = 0;
|
|
438
|
+
if (max === -Infinity)
|
|
439
|
+
max = 1;
|
|
440
|
+
if (min === max) {
|
|
441
|
+
min = min - 1;
|
|
442
|
+
max = max + 1;
|
|
443
|
+
}
|
|
444
|
+
return [min, max];
|
|
553
445
|
}
|
|
554
|
-
function
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
legend: {
|
|
567
|
-
position: "none",
|
|
568
|
-
title: { bold: false }
|
|
569
|
-
},
|
|
570
|
-
title: {
|
|
571
|
-
align: "left",
|
|
572
|
-
bold: false
|
|
573
|
-
},
|
|
574
|
-
facet: {
|
|
575
|
-
strip: {
|
|
576
|
-
text: "#888888",
|
|
577
|
-
background: ""
|
|
446
|
+
function inferDiscreteDomain(data, field, options = {}) {
|
|
447
|
+
const { limits, order = "alphabetical", reverse = false, exclude, drop = true } = options;
|
|
448
|
+
const seen = new Map;
|
|
449
|
+
let index = 0;
|
|
450
|
+
for (const row of data) {
|
|
451
|
+
const value = row[field];
|
|
452
|
+
if (value !== null && value !== undefined) {
|
|
453
|
+
const key = String(value);
|
|
454
|
+
if (!seen.has(key)) {
|
|
455
|
+
seen.set(key, { firstIndex: index, count: 1 });
|
|
456
|
+
} else {
|
|
457
|
+
seen.get(key).count++;
|
|
578
458
|
}
|
|
579
459
|
}
|
|
580
|
-
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
ylim: options.ylim,
|
|
589
|
-
clip: options.clip ?? true,
|
|
590
|
-
transform(x, y) {
|
|
591
|
-
return { x, y };
|
|
460
|
+
index++;
|
|
461
|
+
}
|
|
462
|
+
let result;
|
|
463
|
+
if (limits) {
|
|
464
|
+
if (drop) {
|
|
465
|
+
result = limits.filter((v) => seen.has(v));
|
|
466
|
+
} else {
|
|
467
|
+
result = [...limits];
|
|
592
468
|
}
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
469
|
+
} else {
|
|
470
|
+
const values = Array.from(seen.keys());
|
|
471
|
+
switch (order) {
|
|
472
|
+
case "data":
|
|
473
|
+
result = values.sort((a, b) => seen.get(a).firstIndex - seen.get(b).firstIndex);
|
|
474
|
+
break;
|
|
475
|
+
case "frequency":
|
|
476
|
+
result = values.sort((a, b) => seen.get(b).count - seen.get(a).count);
|
|
477
|
+
break;
|
|
478
|
+
case "reverse":
|
|
479
|
+
result = values.sort().reverse();
|
|
480
|
+
break;
|
|
481
|
+
case "alphabetical":
|
|
482
|
+
default:
|
|
483
|
+
result = values.sort();
|
|
484
|
+
break;
|
|
600
485
|
}
|
|
601
|
-
}
|
|
486
|
+
}
|
|
487
|
+
if (exclude && exclude.length > 0) {
|
|
488
|
+
const excludeSet = new Set(exclude);
|
|
489
|
+
result = result.filter((v) => !excludeSet.has(v));
|
|
490
|
+
}
|
|
491
|
+
if (reverse) {
|
|
492
|
+
result = result.reverse();
|
|
493
|
+
}
|
|
494
|
+
return result;
|
|
602
495
|
}
|
|
603
|
-
function
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
transform(x, y) {
|
|
608
|
-
const angle = theta === "x" ? x : y;
|
|
609
|
-
const radius = theta === "x" ? y : x;
|
|
610
|
-
return {
|
|
611
|
-
x: radius * Math.cos(angle),
|
|
612
|
-
y: radius * Math.sin(angle)
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
};
|
|
496
|
+
function expandDomain(domain, expand = 0.05) {
|
|
497
|
+
const range = domain[1] - domain[0];
|
|
498
|
+
const padding = range * expand;
|
|
499
|
+
return [domain[0] - padding, domain[1] + padding];
|
|
616
500
|
}
|
|
617
|
-
function
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
501
|
+
function niceStep(range, targetTicks = 5) {
|
|
502
|
+
const rawStep = range / Math.max(1, targetTicks - 1);
|
|
503
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));
|
|
504
|
+
const normalized = rawStep / magnitude;
|
|
505
|
+
let nice;
|
|
506
|
+
if (normalized <= 1.5)
|
|
507
|
+
nice = 1;
|
|
508
|
+
else if (normalized <= 3)
|
|
509
|
+
nice = 2;
|
|
510
|
+
else if (normalized <= 7)
|
|
511
|
+
nice = 5;
|
|
512
|
+
else
|
|
513
|
+
nice = 10;
|
|
514
|
+
return nice * magnitude;
|
|
629
515
|
}
|
|
630
|
-
function
|
|
631
|
-
|
|
516
|
+
function niceDomain(domain, targetTicks = 5) {
|
|
517
|
+
const [min, max] = domain;
|
|
518
|
+
const range = max - min;
|
|
519
|
+
if (range === 0) {
|
|
520
|
+
if (min === 0)
|
|
521
|
+
return [-1, 1];
|
|
522
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(Math.abs(min))));
|
|
523
|
+
return [min - magnitude, min + magnitude];
|
|
524
|
+
}
|
|
525
|
+
const step = niceStep(range, targetTicks);
|
|
526
|
+
const niceMin = Math.floor(min / step) * step;
|
|
527
|
+
const niceMax = Math.ceil(max / step) * step;
|
|
528
|
+
return [niceMin, niceMax];
|
|
632
529
|
}
|
|
633
|
-
function
|
|
634
|
-
switch (
|
|
530
|
+
function getTransformFunctions(trans = "identity") {
|
|
531
|
+
switch (trans) {
|
|
635
532
|
case "log10":
|
|
636
|
-
return
|
|
533
|
+
return {
|
|
534
|
+
type: "log10",
|
|
535
|
+
transform: (v) => v > 0 ? Math.log10(v) : -Infinity,
|
|
536
|
+
invert: (v) => Math.pow(10, v)
|
|
537
|
+
};
|
|
637
538
|
case "sqrt":
|
|
638
|
-
return
|
|
539
|
+
return {
|
|
540
|
+
type: "sqrt",
|
|
541
|
+
transform: (v) => v >= 0 ? Math.sqrt(v) : 0,
|
|
542
|
+
invert: (v) => v * v
|
|
543
|
+
};
|
|
639
544
|
case "reverse":
|
|
640
|
-
return
|
|
545
|
+
return {
|
|
546
|
+
type: "reverse",
|
|
547
|
+
transform: (v) => -v,
|
|
548
|
+
invert: (v) => -v
|
|
549
|
+
};
|
|
641
550
|
default:
|
|
642
|
-
return
|
|
551
|
+
return {
|
|
552
|
+
type: "identity",
|
|
553
|
+
transform: (v) => v,
|
|
554
|
+
invert: (v) => v
|
|
555
|
+
};
|
|
643
556
|
}
|
|
644
557
|
}
|
|
645
|
-
function
|
|
646
|
-
const
|
|
647
|
-
const
|
|
558
|
+
function createResolvedContinuousScale(aesthetic, domain, range, trans = "identity") {
|
|
559
|
+
const [domainMin, domainMax] = domain;
|
|
560
|
+
const [rangeMin, rangeMax] = range;
|
|
561
|
+
const rangeSpan = rangeMax - rangeMin;
|
|
562
|
+
const { transform, invert } = getTransformFunctions(trans);
|
|
648
563
|
return {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
564
|
+
aesthetic,
|
|
565
|
+
type: "continuous",
|
|
566
|
+
domain,
|
|
567
|
+
range,
|
|
568
|
+
trans,
|
|
569
|
+
transform,
|
|
570
|
+
invert,
|
|
571
|
+
normalize(value) {
|
|
572
|
+
const num = Number(value);
|
|
573
|
+
if (isNaN(num))
|
|
574
|
+
return 0;
|
|
575
|
+
const transformed = transform(num);
|
|
576
|
+
const transformedMin = transform(domainMin);
|
|
577
|
+
const transformedMax = transform(domainMax);
|
|
578
|
+
if (transformedMax === transformedMin)
|
|
579
|
+
return 0.5;
|
|
580
|
+
return (transformed - transformedMin) / (transformedMax - transformedMin);
|
|
581
|
+
},
|
|
582
|
+
toCanvas(normalized) {
|
|
583
|
+
return rangeMin + normalized * rangeSpan;
|
|
584
|
+
},
|
|
585
|
+
map(value) {
|
|
586
|
+
return this.toCanvas(this.normalize(value));
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
function createResolvedDiscreteScale(aesthetic, domain, range) {
|
|
591
|
+
const [rangeMin, rangeMax] = range;
|
|
592
|
+
const rangeSpan = rangeMax - rangeMin;
|
|
593
|
+
return {
|
|
594
|
+
aesthetic,
|
|
595
|
+
type: "discrete",
|
|
596
|
+
domain,
|
|
597
|
+
range,
|
|
598
|
+
normalize(value) {
|
|
599
|
+
const str = String(value);
|
|
600
|
+
const index = domain.indexOf(str);
|
|
601
|
+
if (index < 0)
|
|
602
|
+
return 0;
|
|
603
|
+
return domain.length > 1 ? index / (domain.length - 1) : 0.5;
|
|
604
|
+
},
|
|
605
|
+
toCanvas(normalized) {
|
|
606
|
+
return rangeMin + normalized * rangeSpan;
|
|
607
|
+
},
|
|
608
|
+
map(value) {
|
|
609
|
+
return this.toCanvas(this.normalize(value));
|
|
660
610
|
}
|
|
661
611
|
};
|
|
662
612
|
}
|
|
663
|
-
function
|
|
613
|
+
function interpolateColor(color1, color2, t) {
|
|
664
614
|
return {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
615
|
+
r: Math.round(color1.r + (color2.r - color1.r) * t),
|
|
616
|
+
g: Math.round(color1.g + (color2.g - color1.g) * t),
|
|
617
|
+
b: Math.round(color1.b + (color2.b - color1.b) * t),
|
|
618
|
+
a: color1.a + (color2.a - color1.a) * t
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
function createResolvedDiscreteColorScale(domain, palette = CATEGORY_COLORS) {
|
|
622
|
+
return {
|
|
623
|
+
aesthetic: "color",
|
|
624
|
+
type: "discrete",
|
|
625
|
+
domain,
|
|
626
|
+
map(value) {
|
|
627
|
+
const str = String(value);
|
|
628
|
+
const index = domain.indexOf(str);
|
|
629
|
+
if (index < 0)
|
|
630
|
+
return palette[0];
|
|
631
|
+
return palette[index % palette.length];
|
|
671
632
|
}
|
|
672
633
|
};
|
|
673
634
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
var DEFAULT_BG = { r: 0, g: 0, b: 0, a: 0 };
|
|
678
|
-
function createEmptyCell() {
|
|
635
|
+
function createResolvedContinuousColorScale(domain, lowColor = { r: 68, g: 1, b: 84, a: 1 }, highColor = { r: 253, g: 231, b: 37, a: 1 }) {
|
|
636
|
+
const [min, max] = domain;
|
|
637
|
+
const span = max - min;
|
|
679
638
|
return {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
639
|
+
aesthetic: "color",
|
|
640
|
+
type: "continuous",
|
|
641
|
+
domain,
|
|
642
|
+
map(value) {
|
|
643
|
+
const num = Number(value);
|
|
644
|
+
if (isNaN(num))
|
|
645
|
+
return lowColor;
|
|
646
|
+
const t = Math.max(0, Math.min(1, (num - min) / span));
|
|
647
|
+
return interpolateColor(lowColor, highColor, t);
|
|
648
|
+
}
|
|
683
649
|
};
|
|
684
650
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
this.height = height;
|
|
693
|
-
this.cells = [];
|
|
694
|
-
this.clear();
|
|
695
|
-
}
|
|
696
|
-
setCell(x, y, cell) {
|
|
697
|
-
if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
|
|
698
|
-
return;
|
|
651
|
+
function isCategoricalField(data, field) {
|
|
652
|
+
for (const row of data) {
|
|
653
|
+
const value = row[field];
|
|
654
|
+
if (value !== null && value !== undefined) {
|
|
655
|
+
if (typeof value === "string") {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
699
658
|
}
|
|
700
|
-
const ix = Math.floor(x);
|
|
701
|
-
const iy = Math.floor(y);
|
|
702
|
-
const existing = this.cells[iy][ix];
|
|
703
|
-
this.cells[iy][ix] = {
|
|
704
|
-
char: cell.char ?? existing.char,
|
|
705
|
-
fg: cell.fg ?? existing.fg,
|
|
706
|
-
bg: cell.bg ?? existing.bg,
|
|
707
|
-
bold: cell.bold ?? existing.bold,
|
|
708
|
-
italic: cell.italic ?? existing.italic,
|
|
709
|
-
underline: cell.underline ?? existing.underline
|
|
710
|
-
};
|
|
711
659
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
function createResolvedSizeScale(domain) {
|
|
663
|
+
const [min, max] = domain;
|
|
664
|
+
const span = max - min;
|
|
665
|
+
return {
|
|
666
|
+
aesthetic: "size",
|
|
667
|
+
type: "continuous",
|
|
668
|
+
domain,
|
|
669
|
+
map(value) {
|
|
670
|
+
const num = Number(value);
|
|
671
|
+
if (isNaN(num))
|
|
672
|
+
return 1;
|
|
673
|
+
const t = Math.max(0, Math.min(1, (num - min) / span));
|
|
674
|
+
return Math.floor(t * 3.99);
|
|
715
675
|
}
|
|
716
|
-
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
function computeDomain(data, field, trans = "identity") {
|
|
679
|
+
const rawDomain = inferContinuousDomain(data, field);
|
|
680
|
+
if (trans === "log10") {
|
|
681
|
+
const [min, max] = rawDomain;
|
|
682
|
+
const safeMin = min > 0 ? min : 0.001;
|
|
683
|
+
const safeMax = max > 0 ? max : 1;
|
|
684
|
+
const minPow = Math.floor(Math.log10(safeMin));
|
|
685
|
+
const maxPow = Math.ceil(Math.log10(safeMax));
|
|
686
|
+
return [Math.pow(10, minPow), Math.pow(10, maxPow)];
|
|
717
687
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
688
|
+
return niceDomain(rawDomain);
|
|
689
|
+
}
|
|
690
|
+
function buildScaleContext(data, aes, plotArea, userScales = [], coordLimits) {
|
|
691
|
+
const userXScale = userScales.find((s) => s.aesthetic === "x");
|
|
692
|
+
const userYScale = userScales.find((s) => s.aesthetic === "y");
|
|
693
|
+
const userColorScale = userScales.find((s) => s.aesthetic === "color" || s.aesthetic === "fill");
|
|
694
|
+
const xIsCategorical = isCategoricalField(data, aes.x);
|
|
695
|
+
let x;
|
|
696
|
+
if (xIsCategorical) {
|
|
697
|
+
const xOrderOptions = {};
|
|
698
|
+
if (userXScale) {
|
|
699
|
+
if (userXScale.domain && Array.isArray(userXScale.domain)) {
|
|
700
|
+
xOrderOptions.limits = userXScale.domain;
|
|
701
|
+
}
|
|
702
|
+
const orderOpts = userXScale.orderOptions;
|
|
703
|
+
if (orderOpts) {
|
|
704
|
+
if (orderOpts.order)
|
|
705
|
+
xOrderOptions.order = orderOpts.order;
|
|
706
|
+
if (orderOpts.reverse)
|
|
707
|
+
xOrderOptions.reverse = orderOpts.reverse;
|
|
708
|
+
if (orderOpts.exclude)
|
|
709
|
+
xOrderOptions.exclude = orderOpts.exclude;
|
|
710
|
+
if (orderOpts.drop !== undefined)
|
|
711
|
+
xOrderOptions.drop = orderOpts.drop;
|
|
724
712
|
}
|
|
725
|
-
this.cells.push(row);
|
|
726
713
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
drawString(x, y, str, fg) {
|
|
732
|
-
for (let i = 0;i < str.length; i++) {
|
|
733
|
-
this.drawChar(x + i, y, str[i], fg);
|
|
714
|
+
const xDomain = inferDiscreteDomain(data, aes.x, xOrderOptions);
|
|
715
|
+
x = createResolvedDiscreteScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1]);
|
|
716
|
+
if (userXScale?.labels) {
|
|
717
|
+
x.labels = userXScale.labels;
|
|
734
718
|
}
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
719
|
+
} else {
|
|
720
|
+
const xTrans = userXScale?.trans ?? "identity";
|
|
721
|
+
const xDomain = coordLimits?.xlim ?? userXScale?.domain ?? computeDomain(data, aes.x, xTrans);
|
|
722
|
+
x = createResolvedContinuousScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1], xTrans);
|
|
723
|
+
if (userXScale?.breaks) {
|
|
724
|
+
x.breaks = userXScale.breaks;
|
|
739
725
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
for (let i = 0;i < length; i++) {
|
|
743
|
-
this.drawChar(x, y + i, char, fg);
|
|
726
|
+
if (userXScale?.labels) {
|
|
727
|
+
x.labels = userXScale.labels;
|
|
744
728
|
}
|
|
745
729
|
}
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
730
|
+
const yIsCategorical = isCategoricalField(data, aes.y);
|
|
731
|
+
let y;
|
|
732
|
+
if (yIsCategorical) {
|
|
733
|
+
const yOrderOptions = {};
|
|
734
|
+
if (userYScale) {
|
|
735
|
+
if (userYScale.domain && Array.isArray(userYScale.domain)) {
|
|
736
|
+
yOrderOptions.limits = userYScale.domain;
|
|
737
|
+
}
|
|
738
|
+
const orderOpts = userYScale.orderOptions;
|
|
739
|
+
if (orderOpts) {
|
|
740
|
+
if (orderOpts.order)
|
|
741
|
+
yOrderOptions.order = orderOpts.order;
|
|
742
|
+
if (orderOpts.reverse)
|
|
743
|
+
yOrderOptions.reverse = orderOpts.reverse;
|
|
744
|
+
if (orderOpts.exclude)
|
|
745
|
+
yOrderOptions.exclude = orderOpts.exclude;
|
|
746
|
+
if (orderOpts.drop !== undefined)
|
|
747
|
+
yOrderOptions.drop = orderOpts.drop;
|
|
753
748
|
}
|
|
754
749
|
}
|
|
750
|
+
const yDomain = inferDiscreteDomain(data, aes.y, yOrderOptions);
|
|
751
|
+
y = createResolvedDiscreteScale("y", yDomain, [plotArea.y + plotArea.height - 1, plotArea.y]);
|
|
752
|
+
if (userYScale?.labels) {
|
|
753
|
+
y.labels = userYScale.labels;
|
|
754
|
+
}
|
|
755
|
+
} else {
|
|
756
|
+
const yTrans = userYScale?.trans ?? "identity";
|
|
757
|
+
const yDomain = coordLimits?.ylim ?? userYScale?.domain ?? computeDomain(data, aes.y, yTrans);
|
|
758
|
+
y = createResolvedContinuousScale("y", yDomain, [plotArea.y + plotArea.height - 1, plotArea.y], yTrans);
|
|
759
|
+
if (userYScale?.breaks) {
|
|
760
|
+
y.breaks = userYScale.breaks;
|
|
761
|
+
}
|
|
762
|
+
if (userYScale?.labels) {
|
|
763
|
+
y.labels = userYScale.labels;
|
|
764
|
+
}
|
|
755
765
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
`);
|
|
766
|
+
const context = { x, y };
|
|
767
|
+
if (aes.y2) {
|
|
768
|
+
const userY2Scale = userScales.find((s) => s.aesthetic === "y2");
|
|
769
|
+
const y2Trans = userY2Scale?.trans ?? "identity";
|
|
770
|
+
const y2Domain = userY2Scale?.domain ?? computeDomain(data, aes.y2, y2Trans);
|
|
771
|
+
const y2 = createResolvedContinuousScale("y2", y2Domain, [plotArea.y + plotArea.height - 1, plotArea.y], y2Trans);
|
|
772
|
+
if (userY2Scale?.breaks) {
|
|
773
|
+
y2.breaks = userY2Scale.breaks;
|
|
774
|
+
}
|
|
775
|
+
if (userY2Scale?.labels) {
|
|
776
|
+
y2.labels = userY2Scale.labels;
|
|
777
|
+
}
|
|
778
|
+
context.y2 = y2;
|
|
770
779
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
if (
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if (
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
780
|
+
const colorAesField = aes.color || aes.fill;
|
|
781
|
+
if (colorAesField) {
|
|
782
|
+
const colorOrderOptions = {};
|
|
783
|
+
if (userColorScale) {
|
|
784
|
+
if (userColorScale.domain && Array.isArray(userColorScale.domain)) {
|
|
785
|
+
colorOrderOptions.limits = userColorScale.domain;
|
|
786
|
+
}
|
|
787
|
+
const orderOpts = userColorScale.orderOptions;
|
|
788
|
+
if (orderOpts) {
|
|
789
|
+
if (orderOpts.order)
|
|
790
|
+
colorOrderOptions.order = orderOpts.order;
|
|
791
|
+
if (orderOpts.reverse)
|
|
792
|
+
colorOrderOptions.reverse = orderOpts.reverse;
|
|
793
|
+
if (orderOpts.exclude)
|
|
794
|
+
colorOrderOptions.exclude = orderOpts.exclude;
|
|
795
|
+
if (orderOpts.drop !== undefined)
|
|
796
|
+
colorOrderOptions.drop = orderOpts.drop;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
const colorDomain = inferDiscreteDomain(data, colorAesField, colorOrderOptions);
|
|
800
|
+
if (userColorScale && userColorScale.map) {
|
|
801
|
+
context.color = {
|
|
802
|
+
aesthetic: userColorScale.aesthetic || "color",
|
|
803
|
+
type: userColorScale.type === "continuous" ? "continuous" : "discrete",
|
|
804
|
+
domain: userColorScale.type === "continuous" ? userColorScale.domain ?? inferContinuousDomain(data, colorAesField) : colorDomain,
|
|
805
|
+
map: (value) => {
|
|
806
|
+
const result = userColorScale.map(value);
|
|
807
|
+
if (typeof result === "object" && "r" in result) {
|
|
808
|
+
return result;
|
|
799
809
|
}
|
|
810
|
+
return { r: 128, g: 128, b: 128, a: 1 };
|
|
800
811
|
}
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
|
|
812
|
+
};
|
|
813
|
+
} else {
|
|
814
|
+
context.color = createResolvedDiscreteColorScale(colorDomain);
|
|
804
815
|
}
|
|
805
|
-
return lines.join(`
|
|
806
|
-
`);
|
|
807
816
|
}
|
|
817
|
+
if (aes.size) {
|
|
818
|
+
const sizeDomain = inferContinuousDomain(data, aes.size);
|
|
819
|
+
context.size = createResolvedSizeScale(sizeDomain);
|
|
820
|
+
}
|
|
821
|
+
return context;
|
|
808
822
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
823
|
+
var CATEGORY_COLORS, DEFAULT_POINT_COLOR;
|
|
824
|
+
var init_scales = __esm(() => {
|
|
825
|
+
CATEGORY_COLORS = [
|
|
826
|
+
{ r: 31, g: 119, b: 180, a: 1 },
|
|
827
|
+
{ r: 255, g: 127, b: 14, a: 1 },
|
|
828
|
+
{ r: 44, g: 160, b: 44, a: 1 },
|
|
829
|
+
{ r: 214, g: 39, b: 40, a: 1 },
|
|
830
|
+
{ r: 148, g: 103, b: 189, a: 1 },
|
|
831
|
+
{ r: 140, g: 86, b: 75, a: 1 },
|
|
832
|
+
{ r: 227, g: 119, b: 194, a: 1 },
|
|
833
|
+
{ r: 127, g: 127, b: 127, a: 1 },
|
|
834
|
+
{ r: 188, g: 189, b: 34, a: 1 },
|
|
835
|
+
{ r: 23, g: 190, b: 207, a: 1 }
|
|
836
|
+
];
|
|
837
|
+
DEFAULT_POINT_COLOR = { r: 79, g: 169, b: 238, a: 1 };
|
|
838
|
+
});
|
|
818
839
|
|
|
819
840
|
// src/positions/index.ts
|
|
820
841
|
function position_identity() {
|
|
@@ -1016,22 +1037,6 @@ function getPositionType(position) {
|
|
|
1016
1037
|
}
|
|
1017
1038
|
|
|
1018
1039
|
// src/pipeline/render-geoms.ts
|
|
1019
|
-
var POINT_SHAPES = {
|
|
1020
|
-
circle: "●",
|
|
1021
|
-
filled_circle: "●",
|
|
1022
|
-
open_circle: "○",
|
|
1023
|
-
square: "■",
|
|
1024
|
-
open_square: "□",
|
|
1025
|
-
diamond: "◆",
|
|
1026
|
-
open_diamond: "◇",
|
|
1027
|
-
triangle: "▲",
|
|
1028
|
-
open_triangle: "△",
|
|
1029
|
-
cross: "✕",
|
|
1030
|
-
plus: "+",
|
|
1031
|
-
star: "★",
|
|
1032
|
-
dot: "•"
|
|
1033
|
-
};
|
|
1034
|
-
var SIZE_CHARS = ["·", "•", "●", "⬤"];
|
|
1035
1040
|
function getPointShape(shape) {
|
|
1036
1041
|
if (!shape)
|
|
1037
1042
|
return POINT_SHAPES.circle;
|
|
@@ -1044,6 +1049,44 @@ function getPointColor(row, aes, colorScale) {
|
|
|
1044
1049
|
}
|
|
1045
1050
|
return DEFAULT_POINT_COLOR;
|
|
1046
1051
|
}
|
|
1052
|
+
function parseColorToRgba(color, fallback = { r: 128, g: 128, b: 128, a: 1 }) {
|
|
1053
|
+
if (!color)
|
|
1054
|
+
return fallback;
|
|
1055
|
+
if (typeof color === "object" && color !== null && "r" in color) {
|
|
1056
|
+
return color;
|
|
1057
|
+
}
|
|
1058
|
+
if (typeof color === "string") {
|
|
1059
|
+
if (color.startsWith("#")) {
|
|
1060
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
|
|
1061
|
+
if (result) {
|
|
1062
|
+
return {
|
|
1063
|
+
r: parseInt(result[1], 16),
|
|
1064
|
+
g: parseInt(result[2], 16),
|
|
1065
|
+
b: parseInt(result[3], 16),
|
|
1066
|
+
a: 1
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
const namedColors = {
|
|
1071
|
+
red: { r: 255, g: 0, b: 0, a: 1 },
|
|
1072
|
+
blue: { r: 0, g: 0, b: 255, a: 1 },
|
|
1073
|
+
green: { r: 0, g: 128, b: 0, a: 1 },
|
|
1074
|
+
black: { r: 0, g: 0, b: 0, a: 1 },
|
|
1075
|
+
white: { r: 255, g: 255, b: 255, a: 1 },
|
|
1076
|
+
gray: { r: 128, g: 128, b: 128, a: 1 },
|
|
1077
|
+
grey: { r: 128, g: 128, b: 128, a: 1 },
|
|
1078
|
+
yellow: { r: 255, g: 255, b: 0, a: 1 },
|
|
1079
|
+
orange: { r: 255, g: 165, b: 0, a: 1 },
|
|
1080
|
+
purple: { r: 128, g: 0, b: 128, a: 1 },
|
|
1081
|
+
cyan: { r: 0, g: 255, b: 255, a: 1 },
|
|
1082
|
+
magenta: { r: 255, g: 0, b: 255, a: 1 }
|
|
1083
|
+
};
|
|
1084
|
+
const named = namedColors[color.toLowerCase()];
|
|
1085
|
+
if (named)
|
|
1086
|
+
return named;
|
|
1087
|
+
}
|
|
1088
|
+
return fallback;
|
|
1089
|
+
}
|
|
1047
1090
|
function renderGeomPoint(data, geom, aes, scales, canvas) {
|
|
1048
1091
|
const defaultShape = getPointShape(geom.params.shape);
|
|
1049
1092
|
const positionType = getPositionType(geom.position);
|
|
@@ -1442,7 +1485,7 @@ function renderGeomHLine(_data, geom, _aes, scales, canvas) {
|
|
|
1442
1485
|
if (yintercept === undefined)
|
|
1443
1486
|
return;
|
|
1444
1487
|
const cy = Math.round(scales.y.map(yintercept));
|
|
1445
|
-
const color = geom.params.color
|
|
1488
|
+
const color = parseColorToRgba(geom.params.color);
|
|
1446
1489
|
const startX = Math.round(scales.x.range[0]);
|
|
1447
1490
|
const endX = Math.round(scales.x.range[1]);
|
|
1448
1491
|
canvas.drawHLine(startX, cy, endX - startX + 1, "─", color);
|
|
@@ -1452,7 +1495,7 @@ function renderGeomVLine(_data, geom, _aes, scales, canvas) {
|
|
|
1452
1495
|
if (xintercept === undefined)
|
|
1453
1496
|
return;
|
|
1454
1497
|
const cx = Math.round(scales.x.map(xintercept));
|
|
1455
|
-
const color = geom.params.color
|
|
1498
|
+
const color = parseColorToRgba(geom.params.color);
|
|
1456
1499
|
const startY = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
1457
1500
|
const endY = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
1458
1501
|
canvas.drawVLine(cx, startY, endY - startY + 1, "│", color);
|
|
@@ -1769,20 +1812,52 @@ function renderGeomTile(data, geom, aes, scales, canvas) {
|
|
|
1769
1812
|
const plotRight = Math.round(scales.x.range[1]);
|
|
1770
1813
|
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
1771
1814
|
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
1772
|
-
let
|
|
1773
|
-
let
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1815
|
+
let halfW;
|
|
1816
|
+
let halfH;
|
|
1817
|
+
const xIsDiscrete = scales.x.type === "discrete";
|
|
1818
|
+
const yIsDiscrete = scales.y.type === "discrete";
|
|
1819
|
+
if (xIsDiscrete) {
|
|
1820
|
+
const xDomain = scales.x.domain;
|
|
1821
|
+
const canvasWidth = Math.abs(scales.x.range[1] - scales.x.range[0]);
|
|
1822
|
+
halfW = Math.max(1, Math.floor(canvasWidth / (xDomain.length * 2)));
|
|
1823
|
+
} else {
|
|
1824
|
+
let tileWidth = data[0]?.width ?? geom.params.width;
|
|
1825
|
+
if (!tileWidth) {
|
|
1826
|
+
const xVals = [...new Set(data.map((r) => Number(r[aes.x])).filter((v) => !isNaN(v)))].sort((a, b) => a - b);
|
|
1827
|
+
if (xVals.length > 1) {
|
|
1828
|
+
tileWidth = xVals[1] - xVals[0];
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
tileWidth = tileWidth ?? 1;
|
|
1832
|
+
const sampleX = data.find((r) => r[aes.x] !== null && r[aes.x] !== undefined)?.[aes.x];
|
|
1833
|
+
if (sampleX !== undefined) {
|
|
1834
|
+
const cx = scales.x.map(sampleX);
|
|
1835
|
+
halfW = Math.max(1, Math.floor(Math.abs(scales.x.map(Number(sampleX) + tileWidth / 2) - cx)));
|
|
1836
|
+
} else {
|
|
1837
|
+
halfW = 1;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
if (yIsDiscrete) {
|
|
1841
|
+
const yDomain = scales.y.domain;
|
|
1842
|
+
const canvasHeight = Math.abs(scales.y.range[1] - scales.y.range[0]);
|
|
1843
|
+
halfH = Math.max(1, Math.floor(canvasHeight / (yDomain.length * 2)));
|
|
1844
|
+
} else {
|
|
1845
|
+
let tileHeight = data[0]?.height ?? geom.params.height;
|
|
1846
|
+
if (!tileHeight) {
|
|
1847
|
+
const yVals = [...new Set(data.map((r) => Number(r[aes.y])).filter((v) => !isNaN(v)))].sort((a, b) => a - b);
|
|
1848
|
+
if (yVals.length > 1) {
|
|
1849
|
+
tileHeight = yVals[1] - yVals[0];
|
|
1850
|
+
}
|
|
1779
1851
|
}
|
|
1780
|
-
|
|
1781
|
-
|
|
1852
|
+
tileHeight = tileHeight ?? 1;
|
|
1853
|
+
const sampleY = data.find((r) => r[aes.y] !== null && r[aes.y] !== undefined)?.[aes.y];
|
|
1854
|
+
if (sampleY !== undefined) {
|
|
1855
|
+
const cy = scales.y.map(sampleY);
|
|
1856
|
+
halfH = Math.max(1, Math.floor(Math.abs(scales.y.map(Number(sampleY) + tileHeight / 2) - cy)));
|
|
1857
|
+
} else {
|
|
1858
|
+
halfH = 1;
|
|
1782
1859
|
}
|
|
1783
1860
|
}
|
|
1784
|
-
tileWidth = tileWidth ?? 1;
|
|
1785
|
-
tileHeight = tileHeight ?? 1;
|
|
1786
1861
|
for (const row of data) {
|
|
1787
1862
|
const xVal = row[aes.x];
|
|
1788
1863
|
const yVal = row[aes.y];
|
|
@@ -1792,8 +1867,6 @@ function renderGeomTile(data, geom, aes, scales, canvas) {
|
|
|
1792
1867
|
}
|
|
1793
1868
|
const cx = Math.round(scales.x.map(xVal));
|
|
1794
1869
|
const cy = Math.round(scales.y.map(yVal));
|
|
1795
|
-
const halfW = Math.max(1, Math.floor(Math.abs(scales.x.map(Number(xVal) + tileWidth / 2) - cx)));
|
|
1796
|
-
const halfH = Math.max(1, Math.floor(Math.abs(scales.y.map(Number(yVal) + tileHeight / 2) - cy)));
|
|
1797
1870
|
let color;
|
|
1798
1871
|
if (scales.color && typeof fillVal === "number") {
|
|
1799
1872
|
color = scales.color.map(fillVal);
|
|
@@ -1981,7 +2054,7 @@ function renderGeomAbline(_data, geom, _aes, scales, canvas) {
|
|
|
1981
2054
|
const intercept = geom.params.intercept ?? 0;
|
|
1982
2055
|
const linetype = geom.params.linetype ?? "solid";
|
|
1983
2056
|
const lineChar = linetype === "dotted" ? "·" : linetype === "dashed" ? "╌" : "─";
|
|
1984
|
-
const color = geom.params.color
|
|
2057
|
+
const color = parseColorToRgba(geom.params.color);
|
|
1985
2058
|
const plotLeft = Math.round(scales.x.range[0]);
|
|
1986
2059
|
const plotRight = Math.round(scales.x.range[1]);
|
|
1987
2060
|
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
@@ -2173,6 +2246,7 @@ function renderGeom(data, geom, aes, scales, canvas, coordType) {
|
|
|
2173
2246
|
break;
|
|
2174
2247
|
case "tile":
|
|
2175
2248
|
case "raster":
|
|
2249
|
+
case "bin2d":
|
|
2176
2250
|
renderGeomTile(data, geom, aes, scales, canvas);
|
|
2177
2251
|
break;
|
|
2178
2252
|
case "contour":
|
|
@@ -2202,6 +2276,26 @@ function renderGeom(data, geom, aes, scales, canvas, coordType) {
|
|
|
2202
2276
|
break;
|
|
2203
2277
|
}
|
|
2204
2278
|
}
|
|
2279
|
+
var POINT_SHAPES, SIZE_CHARS;
|
|
2280
|
+
var init_render_geoms = __esm(() => {
|
|
2281
|
+
init_scales();
|
|
2282
|
+
POINT_SHAPES = {
|
|
2283
|
+
circle: "●",
|
|
2284
|
+
filled_circle: "●",
|
|
2285
|
+
open_circle: "○",
|
|
2286
|
+
square: "■",
|
|
2287
|
+
open_square: "□",
|
|
2288
|
+
diamond: "◆",
|
|
2289
|
+
open_diamond: "◇",
|
|
2290
|
+
triangle: "▲",
|
|
2291
|
+
open_triangle: "△",
|
|
2292
|
+
cross: "✕",
|
|
2293
|
+
plus: "+",
|
|
2294
|
+
star: "★",
|
|
2295
|
+
dot: "•"
|
|
2296
|
+
};
|
|
2297
|
+
SIZE_CHARS = ["·", "•", "●", "⬤"];
|
|
2298
|
+
});
|
|
2205
2299
|
|
|
2206
2300
|
// src/pipeline/render-axes.ts
|
|
2207
2301
|
function calculateTicks(domain, targetTicks = 5, transform, invert) {
|
|
@@ -2509,7 +2603,6 @@ function renderTitle(canvas, title, width, theme) {
|
|
|
2509
2603
|
}
|
|
2510
2604
|
canvas.drawString(x, 0, title, titleColor);
|
|
2511
2605
|
}
|
|
2512
|
-
var SIZE_SYMBOLS = ["·", "•", "●", "⬤"];
|
|
2513
2606
|
function renderMultiLegend(canvas, entries, x, y, theme, width) {
|
|
2514
2607
|
if (theme.legend.position === "none" || entries.length === 0)
|
|
2515
2608
|
return;
|
|
@@ -2637,6 +2730,10 @@ function formatContinuousLegendValue(value) {
|
|
|
2637
2730
|
}
|
|
2638
2731
|
return value.toFixed(1);
|
|
2639
2732
|
}
|
|
2733
|
+
var SIZE_SYMBOLS;
|
|
2734
|
+
var init_render_axes = __esm(() => {
|
|
2735
|
+
SIZE_SYMBOLS = ["·", "•", "●", "⬤"];
|
|
2736
|
+
});
|
|
2640
2737
|
|
|
2641
2738
|
// src/stats/bin.ts
|
|
2642
2739
|
function computeBins(data, field, params = {}) {
|
|
@@ -2748,6 +2845,248 @@ function stat_bin(params = {}) {
|
|
|
2748
2845
|
};
|
|
2749
2846
|
}
|
|
2750
2847
|
|
|
2848
|
+
// src/performance/binning.ts
|
|
2849
|
+
function computeDomain2(data, field) {
|
|
2850
|
+
let min = Infinity;
|
|
2851
|
+
let max = -Infinity;
|
|
2852
|
+
for (const d of data) {
|
|
2853
|
+
const v = d[field];
|
|
2854
|
+
if (typeof v === "number" && !isNaN(v)) {
|
|
2855
|
+
if (v < min)
|
|
2856
|
+
min = v;
|
|
2857
|
+
if (v > max)
|
|
2858
|
+
max = v;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
if (min === Infinity)
|
|
2862
|
+
return [0, 1];
|
|
2863
|
+
if (min === max)
|
|
2864
|
+
return [min - 0.5, max + 0.5];
|
|
2865
|
+
return [min, max];
|
|
2866
|
+
}
|
|
2867
|
+
function aggregateValues(values, method) {
|
|
2868
|
+
if (values.length === 0)
|
|
2869
|
+
return 0;
|
|
2870
|
+
switch (method) {
|
|
2871
|
+
case "count":
|
|
2872
|
+
return values.length;
|
|
2873
|
+
case "sum":
|
|
2874
|
+
return values.reduce((a, b) => a + b, 0);
|
|
2875
|
+
case "mean":
|
|
2876
|
+
return values.reduce((a, b) => a + b, 0) / values.length;
|
|
2877
|
+
case "median":
|
|
2878
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
2879
|
+
const mid = Math.floor(sorted.length / 2);
|
|
2880
|
+
return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
2881
|
+
case "min":
|
|
2882
|
+
return Math.min(...values);
|
|
2883
|
+
case "max":
|
|
2884
|
+
return Math.max(...values);
|
|
2885
|
+
default:
|
|
2886
|
+
return values.length;
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
function rectbin(data, options) {
|
|
2890
|
+
const {
|
|
2891
|
+
xField,
|
|
2892
|
+
yField,
|
|
2893
|
+
xBins = 20,
|
|
2894
|
+
yBins = 20,
|
|
2895
|
+
aggregate = "count",
|
|
2896
|
+
valueField
|
|
2897
|
+
} = options;
|
|
2898
|
+
if (data.length === 0)
|
|
2899
|
+
return [];
|
|
2900
|
+
const xDomain = options.xDomain ?? computeDomain2(data, xField);
|
|
2901
|
+
const yDomain = options.yDomain ?? computeDomain2(data, yField);
|
|
2902
|
+
const xRange = xDomain[1] - xDomain[0];
|
|
2903
|
+
const yRange = yDomain[1] - yDomain[0];
|
|
2904
|
+
const binWidth = xRange / xBins;
|
|
2905
|
+
const binHeight = yRange / yBins;
|
|
2906
|
+
const bins = new Map;
|
|
2907
|
+
for (const point of data) {
|
|
2908
|
+
const x = point[xField];
|
|
2909
|
+
const y = point[yField];
|
|
2910
|
+
if (typeof x !== "number" || typeof y !== "number")
|
|
2911
|
+
continue;
|
|
2912
|
+
const bx = Math.min(xBins - 1, Math.max(0, Math.floor((x - xDomain[0]) / binWidth)));
|
|
2913
|
+
const by = Math.min(yBins - 1, Math.max(0, Math.floor((y - yDomain[0]) / binHeight)));
|
|
2914
|
+
const key = `${bx},${by}`;
|
|
2915
|
+
if (!bins.has(key)) {
|
|
2916
|
+
bins.set(key, { points: [], values: [] });
|
|
2917
|
+
}
|
|
2918
|
+
const bin = bins.get(key);
|
|
2919
|
+
bin.points.push(point);
|
|
2920
|
+
if (valueField && typeof point[valueField] === "number") {
|
|
2921
|
+
bin.values.push(point[valueField]);
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
const result = [];
|
|
2925
|
+
for (const [key, bin] of bins) {
|
|
2926
|
+
const [bx, by] = key.split(",").map(Number);
|
|
2927
|
+
const centerX = xDomain[0] + (bx + 0.5) * binWidth;
|
|
2928
|
+
const centerY = yDomain[0] + (by + 0.5) * binHeight;
|
|
2929
|
+
result.push({
|
|
2930
|
+
x: centerX,
|
|
2931
|
+
y: centerY,
|
|
2932
|
+
count: bin.points.length,
|
|
2933
|
+
value: aggregateValues(bin.values.length > 0 ? bin.values : [bin.points.length], aggregate),
|
|
2934
|
+
width: binWidth,
|
|
2935
|
+
height: binHeight,
|
|
2936
|
+
points: bin.points
|
|
2937
|
+
});
|
|
2938
|
+
}
|
|
2939
|
+
return result;
|
|
2940
|
+
}
|
|
2941
|
+
function hexbin(data, options) {
|
|
2942
|
+
const { xField, yField, aggregate = "count", valueField, radius = 10 } = options;
|
|
2943
|
+
if (data.length === 0)
|
|
2944
|
+
return [];
|
|
2945
|
+
const xDomain = options.xDomain ?? computeDomain2(data, xField);
|
|
2946
|
+
const yDomain = options.yDomain ?? computeDomain2(data, yField);
|
|
2947
|
+
const hexWidth = radius * 2;
|
|
2948
|
+
const hexHeight = radius * Math.sqrt(3);
|
|
2949
|
+
const bins = new Map;
|
|
2950
|
+
for (const point of data) {
|
|
2951
|
+
const x = point[xField];
|
|
2952
|
+
const y = point[yField];
|
|
2953
|
+
if (typeof x !== "number" || typeof y !== "number")
|
|
2954
|
+
continue;
|
|
2955
|
+
const col = Math.round((x - xDomain[0]) / (hexWidth * 0.75));
|
|
2956
|
+
const row = Math.round((y - yDomain[0]) / hexHeight - col % 2 * 0.5);
|
|
2957
|
+
const key = `${col},${row}`;
|
|
2958
|
+
if (!bins.has(key)) {
|
|
2959
|
+
bins.set(key, { points: [], values: [], col, row });
|
|
2960
|
+
}
|
|
2961
|
+
const bin = bins.get(key);
|
|
2962
|
+
bin.points.push(point);
|
|
2963
|
+
if (valueField && typeof point[valueField] === "number") {
|
|
2964
|
+
bin.values.push(point[valueField]);
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
function hexVertices(cx, cy, r) {
|
|
2968
|
+
const vertices = [];
|
|
2969
|
+
for (let i = 0;i < 6; i++) {
|
|
2970
|
+
const angle = Math.PI / 3 * i + Math.PI / 6;
|
|
2971
|
+
vertices.push({
|
|
2972
|
+
x: cx + r * Math.cos(angle),
|
|
2973
|
+
y: cy + r * Math.sin(angle)
|
|
2974
|
+
});
|
|
2975
|
+
}
|
|
2976
|
+
return vertices;
|
|
2977
|
+
}
|
|
2978
|
+
const result = [];
|
|
2979
|
+
for (const [, bin] of bins) {
|
|
2980
|
+
const centerX = xDomain[0] + bin.col * hexWidth * 0.75;
|
|
2981
|
+
const centerY = yDomain[0] + (bin.row + bin.col % 2 * 0.5) * hexHeight;
|
|
2982
|
+
result.push({
|
|
2983
|
+
x: centerX,
|
|
2984
|
+
y: centerY,
|
|
2985
|
+
count: bin.points.length,
|
|
2986
|
+
value: aggregateValues(bin.values.length > 0 ? bin.values : [bin.points.length], aggregate),
|
|
2987
|
+
width: hexWidth,
|
|
2988
|
+
height: hexHeight,
|
|
2989
|
+
points: bin.points,
|
|
2990
|
+
vertices: hexVertices(centerX, centerY, radius),
|
|
2991
|
+
col: bin.col,
|
|
2992
|
+
row: bin.row
|
|
2993
|
+
});
|
|
2994
|
+
}
|
|
2995
|
+
return result;
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
class Binner {
|
|
2999
|
+
options;
|
|
3000
|
+
type;
|
|
3001
|
+
hexRadius;
|
|
3002
|
+
constructor(options) {
|
|
3003
|
+
this.options = options;
|
|
3004
|
+
this.type = options.type ?? "rect";
|
|
3005
|
+
this.hexRadius = options.hexRadius ?? 10;
|
|
3006
|
+
}
|
|
3007
|
+
bin(data) {
|
|
3008
|
+
if (this.type === "hex") {
|
|
3009
|
+
return hexbin(data, { ...this.options, radius: this.hexRadius });
|
|
3010
|
+
}
|
|
3011
|
+
return rectbin(data, this.options);
|
|
3012
|
+
}
|
|
3013
|
+
toPlotData(data) {
|
|
3014
|
+
const bins = this.bin(data);
|
|
3015
|
+
const maxCount = Math.max(...bins.map((b) => b.count));
|
|
3016
|
+
const minSize = 1;
|
|
3017
|
+
const maxSize = 5;
|
|
3018
|
+
return bins.map((bin) => ({
|
|
3019
|
+
x: bin.x,
|
|
3020
|
+
y: bin.y,
|
|
3021
|
+
count: bin.count,
|
|
3022
|
+
value: bin.value,
|
|
3023
|
+
size: minSize + bin.count / maxCount * (maxSize - minSize)
|
|
3024
|
+
}));
|
|
3025
|
+
}
|
|
3026
|
+
getDensityColors(bins, colorScale) {
|
|
3027
|
+
const maxCount = Math.max(...bins.map((b) => b.count));
|
|
3028
|
+
const colors = new Map;
|
|
3029
|
+
for (const bin of bins) {
|
|
3030
|
+
const t = bin.count / maxCount;
|
|
3031
|
+
colors.set(bin, colorScale(t));
|
|
3032
|
+
}
|
|
3033
|
+
return colors;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
function createBinner(options) {
|
|
3037
|
+
return new Binner(options);
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
// src/stats/bin2d.ts
|
|
3041
|
+
function computeBins2d(data, xField, yField, params = {}) {
|
|
3042
|
+
const {
|
|
3043
|
+
bins = 30,
|
|
3044
|
+
binsx,
|
|
3045
|
+
binsy,
|
|
3046
|
+
drop = true
|
|
3047
|
+
} = params;
|
|
3048
|
+
const xBins = binsx ?? bins;
|
|
3049
|
+
const yBins = binsy ?? bins;
|
|
3050
|
+
const binned = rectbin(data, {
|
|
3051
|
+
xField,
|
|
3052
|
+
yField,
|
|
3053
|
+
xBins,
|
|
3054
|
+
yBins,
|
|
3055
|
+
aggregate: "count"
|
|
3056
|
+
});
|
|
3057
|
+
const total = data.length;
|
|
3058
|
+
const results = binned.map((bin) => ({
|
|
3059
|
+
x: bin.x,
|
|
3060
|
+
y: bin.y,
|
|
3061
|
+
count: bin.count,
|
|
3062
|
+
density: total > 0 ? bin.count / total : 0,
|
|
3063
|
+
width: bin.width,
|
|
3064
|
+
height: bin.height
|
|
3065
|
+
}));
|
|
3066
|
+
if (drop) {
|
|
3067
|
+
return results.filter((r) => r.count > 0);
|
|
3068
|
+
}
|
|
3069
|
+
return results;
|
|
3070
|
+
}
|
|
3071
|
+
function stat_bin2d(params = {}) {
|
|
3072
|
+
return {
|
|
3073
|
+
type: "bin2d",
|
|
3074
|
+
compute(data, aes) {
|
|
3075
|
+
const bins = computeBins2d(data, aes.x, aes.y, params);
|
|
3076
|
+
return bins.map((bin) => ({
|
|
3077
|
+
x: bin.x,
|
|
3078
|
+
y: bin.y,
|
|
3079
|
+
count: bin.count,
|
|
3080
|
+
density: bin.density,
|
|
3081
|
+
fill: bin.count,
|
|
3082
|
+
width: bin.width,
|
|
3083
|
+
height: bin.height
|
|
3084
|
+
}));
|
|
3085
|
+
}
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
3088
|
+
var init_bin2d = () => {};
|
|
3089
|
+
|
|
2751
3090
|
// src/stats/boxplot.ts
|
|
2752
3091
|
function quantile(sorted, p) {
|
|
2753
3092
|
if (sorted.length === 0)
|
|
@@ -3163,17 +3502,6 @@ function stat_smooth(params = {}) {
|
|
|
3163
3502
|
}
|
|
3164
3503
|
|
|
3165
3504
|
// src/stats/summary.ts
|
|
3166
|
-
var summaryFunctions = {
|
|
3167
|
-
mean: (values) => values.reduce((a, b) => a + b, 0) / values.length,
|
|
3168
|
-
median: (values) => {
|
|
3169
|
-
const sorted = [...values].sort((a, b) => a - b);
|
|
3170
|
-
const mid = Math.floor(sorted.length / 2);
|
|
3171
|
-
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
3172
|
-
},
|
|
3173
|
-
min: (values) => Math.min(...values),
|
|
3174
|
-
max: (values) => Math.max(...values),
|
|
3175
|
-
sum: (values) => values.reduce((a, b) => a + b, 0)
|
|
3176
|
-
};
|
|
3177
3505
|
function sd(values) {
|
|
3178
3506
|
const n = values.length;
|
|
3179
3507
|
if (n < 2)
|
|
@@ -3305,6 +3633,20 @@ function stat_summary(params = {}) {
|
|
|
3305
3633
|
}
|
|
3306
3634
|
};
|
|
3307
3635
|
}
|
|
3636
|
+
var summaryFunctions;
|
|
3637
|
+
var init_summary = __esm(() => {
|
|
3638
|
+
summaryFunctions = {
|
|
3639
|
+
mean: (values) => values.reduce((a, b) => a + b, 0) / values.length,
|
|
3640
|
+
median: (values) => {
|
|
3641
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
3642
|
+
const mid = Math.floor(sorted.length / 2);
|
|
3643
|
+
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
3644
|
+
},
|
|
3645
|
+
min: (values) => Math.min(...values),
|
|
3646
|
+
max: (values) => Math.max(...values),
|
|
3647
|
+
sum: (values) => values.reduce((a, b) => a + b, 0)
|
|
3648
|
+
};
|
|
3649
|
+
});
|
|
3308
3650
|
|
|
3309
3651
|
// src/stats/qq.ts
|
|
3310
3652
|
function qnorm(p, mean = 0, sd2 = 1) {
|
|
@@ -3487,15 +3829,125 @@ function stat_qq_line(params = {}) {
|
|
|
3487
3829
|
};
|
|
3488
3830
|
}
|
|
3489
3831
|
|
|
3832
|
+
// src/stats/density2d.ts
|
|
3833
|
+
function gaussian2d(dx, dy, hx, hy) {
|
|
3834
|
+
const ux = dx / hx;
|
|
3835
|
+
const uy = dy / hy;
|
|
3836
|
+
return Math.exp(-0.5 * (ux * ux + uy * uy)) / (2 * Math.PI * hx * hy);
|
|
3837
|
+
}
|
|
3838
|
+
function scottBandwidth2d(values) {
|
|
3839
|
+
const n = values.length;
|
|
3840
|
+
if (n < 2)
|
|
3841
|
+
return 1;
|
|
3842
|
+
const mean = values.reduce((a, b) => a + b, 0) / n;
|
|
3843
|
+
const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / (n - 1);
|
|
3844
|
+
const std = Math.sqrt(variance);
|
|
3845
|
+
return std * Math.pow(n, -1 / 6);
|
|
3846
|
+
}
|
|
3847
|
+
function computeDensity2d(data, xField, yField, params = {}) {
|
|
3848
|
+
const points = [];
|
|
3849
|
+
const xValues = [];
|
|
3850
|
+
const yValues = [];
|
|
3851
|
+
for (const row of data) {
|
|
3852
|
+
const xVal = row[xField];
|
|
3853
|
+
const yVal = row[yField];
|
|
3854
|
+
if (xVal === null || xVal === undefined || yVal === null || yVal === undefined)
|
|
3855
|
+
continue;
|
|
3856
|
+
const x = Number(xVal);
|
|
3857
|
+
const y = Number(yVal);
|
|
3858
|
+
if (isNaN(x) || isNaN(y))
|
|
3859
|
+
continue;
|
|
3860
|
+
points.push({ x, y });
|
|
3861
|
+
xValues.push(x);
|
|
3862
|
+
yValues.push(y);
|
|
3863
|
+
}
|
|
3864
|
+
if (points.length < 3) {
|
|
3865
|
+
return [];
|
|
3866
|
+
}
|
|
3867
|
+
const n = params.n ?? 50;
|
|
3868
|
+
const nx = params.nx ?? n;
|
|
3869
|
+
const ny = params.ny ?? n;
|
|
3870
|
+
const adjust = params.adjust ?? 1;
|
|
3871
|
+
let hx, hy;
|
|
3872
|
+
if (Array.isArray(params.h)) {
|
|
3873
|
+
hx = params.h[0] * adjust;
|
|
3874
|
+
hy = params.h[1] * adjust;
|
|
3875
|
+
} else if (params.h !== undefined) {
|
|
3876
|
+
hx = params.h * adjust;
|
|
3877
|
+
hy = params.h * adjust;
|
|
3878
|
+
} else {
|
|
3879
|
+
hx = scottBandwidth2d(xValues) * adjust;
|
|
3880
|
+
hy = scottBandwidth2d(yValues) * adjust;
|
|
3881
|
+
}
|
|
3882
|
+
if (hx <= 0)
|
|
3883
|
+
hx = 1;
|
|
3884
|
+
if (hy <= 0)
|
|
3885
|
+
hy = 1;
|
|
3886
|
+
const xMin = Math.min(...xValues);
|
|
3887
|
+
const xMax = Math.max(...xValues);
|
|
3888
|
+
const yMin = Math.min(...yValues);
|
|
3889
|
+
const yMax = Math.max(...yValues);
|
|
3890
|
+
const xPad = 3 * hx;
|
|
3891
|
+
const yPad = 3 * hy;
|
|
3892
|
+
const gridXMin = xMin - xPad;
|
|
3893
|
+
const gridXMax = xMax + xPad;
|
|
3894
|
+
const gridYMin = yMin - yPad;
|
|
3895
|
+
const gridYMax = yMax + yPad;
|
|
3896
|
+
const xStep = (gridXMax - gridXMin) / (nx - 1);
|
|
3897
|
+
const yStep = (gridYMax - gridYMin) / (ny - 1);
|
|
3898
|
+
const results = [];
|
|
3899
|
+
const nPoints = points.length;
|
|
3900
|
+
for (let i = 0;i < nx; i++) {
|
|
3901
|
+
const gx = gridXMin + i * xStep;
|
|
3902
|
+
for (let j = 0;j < ny; j++) {
|
|
3903
|
+
const gy = gridYMin + j * yStep;
|
|
3904
|
+
let density = 0;
|
|
3905
|
+
for (const pt of points) {
|
|
3906
|
+
density += gaussian2d(gx - pt.x, gy - pt.y, hx, hy);
|
|
3907
|
+
}
|
|
3908
|
+
density /= nPoints;
|
|
3909
|
+
results.push({
|
|
3910
|
+
x: gx,
|
|
3911
|
+
y: gy,
|
|
3912
|
+
z: density,
|
|
3913
|
+
density,
|
|
3914
|
+
level: density
|
|
3915
|
+
});
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
return results;
|
|
3919
|
+
}
|
|
3920
|
+
function stat_density_2d(params = {}) {
|
|
3921
|
+
return {
|
|
3922
|
+
type: "density_2d",
|
|
3923
|
+
compute(data, aes) {
|
|
3924
|
+
if (aes.color) {
|
|
3925
|
+
const groups = new Map;
|
|
3926
|
+
for (const row of data) {
|
|
3927
|
+
const group = String(row[aes.color] ?? "default");
|
|
3928
|
+
if (!groups.has(group)) {
|
|
3929
|
+
groups.set(group, []);
|
|
3930
|
+
}
|
|
3931
|
+
groups.get(group).push(row);
|
|
3932
|
+
}
|
|
3933
|
+
const result = [];
|
|
3934
|
+
for (const [group, groupData] of groups) {
|
|
3935
|
+
const density = computeDensity2d(groupData, aes.x, aes.y, params);
|
|
3936
|
+
for (const d of density) {
|
|
3937
|
+
result.push({
|
|
3938
|
+
...d,
|
|
3939
|
+
[aes.color]: group
|
|
3940
|
+
});
|
|
3941
|
+
}
|
|
3942
|
+
}
|
|
3943
|
+
return result;
|
|
3944
|
+
}
|
|
3945
|
+
return computeDensity2d(data, aes.x, aes.y, params);
|
|
3946
|
+
}
|
|
3947
|
+
};
|
|
3948
|
+
}
|
|
3949
|
+
|
|
3490
3950
|
// src/facets/index.ts
|
|
3491
|
-
var label_value = (value) => value;
|
|
3492
|
-
var label_both = (value, variable) => variable ? `${variable}: ${value}` : value;
|
|
3493
|
-
var label_parsed = (value) => value.replace(/_/g, " ");
|
|
3494
|
-
var label_wrap = (width) => (value) => {
|
|
3495
|
-
if (value.length <= width)
|
|
3496
|
-
return value;
|
|
3497
|
-
return value.substring(0, width - 1) + "…";
|
|
3498
|
-
};
|
|
3499
3951
|
function as_labeller(labels) {
|
|
3500
3952
|
return (value) => labels[value] ?? value;
|
|
3501
3953
|
}
|
|
@@ -3688,6 +4140,11 @@ function calculateGridStripLayout(totalWidth, totalHeight, nrow, ncol, hasTitle,
|
|
|
3688
4140
|
rowStripWidth: rowStripWidth - 1
|
|
3689
4141
|
};
|
|
3690
4142
|
}
|
|
4143
|
+
var label_value = (value) => value, label_both = (value, variable) => variable ? `${variable}: ${value}` : value, label_parsed = (value) => value.replace(/_/g, " "), label_wrap = (width) => (value) => {
|
|
4144
|
+
if (value.length <= width)
|
|
4145
|
+
return value;
|
|
4146
|
+
return value.substring(0, width - 1) + "…";
|
|
4147
|
+
};
|
|
3691
4148
|
|
|
3692
4149
|
// src/pipeline/pipeline.ts
|
|
3693
4150
|
function calculateLayout(spec, options) {
|
|
@@ -3800,6 +4257,23 @@ function applyStatTransform(data, geom, aes) {
|
|
|
3800
4257
|
dparams: geom.params.dparams
|
|
3801
4258
|
});
|
|
3802
4259
|
return qqLineStat.compute(data, aes);
|
|
4260
|
+
} else if (geom.stat === "bin2d") {
|
|
4261
|
+
const bin2dStat = stat_bin2d({
|
|
4262
|
+
bins: geom.params.bins,
|
|
4263
|
+
binsx: geom.params.binsx,
|
|
4264
|
+
binsy: geom.params.binsy,
|
|
4265
|
+
drop: geom.params.drop
|
|
4266
|
+
});
|
|
4267
|
+
return bin2dStat.compute(data, aes);
|
|
4268
|
+
} else if (geom.stat === "density_2d") {
|
|
4269
|
+
const density2dStat = stat_density_2d({
|
|
4270
|
+
h: geom.params.bandwidth,
|
|
4271
|
+
n: geom.params.n,
|
|
4272
|
+
nx: geom.params.nx,
|
|
4273
|
+
ny: geom.params.ny,
|
|
4274
|
+
adjust: geom.params.adjust
|
|
4275
|
+
});
|
|
4276
|
+
return density2dStat.compute(data, aes);
|
|
3803
4277
|
}
|
|
3804
4278
|
return data;
|
|
3805
4279
|
}
|
|
@@ -3864,6 +4338,14 @@ function renderToCanvas(spec, options) {
|
|
|
3864
4338
|
scaleAes = { ...spec.aes, x: "x", y: "y" };
|
|
3865
4339
|
}
|
|
3866
4340
|
break;
|
|
4341
|
+
} else if (geom.stat === "bin2d") {
|
|
4342
|
+
scaleData = applyStatTransform(spec.data, geom, spec.aes);
|
|
4343
|
+
scaleAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
|
|
4344
|
+
break;
|
|
4345
|
+
} else if (geom.stat === "density_2d") {
|
|
4346
|
+
scaleData = applyStatTransform(spec.data, geom, spec.aes);
|
|
4347
|
+
scaleAes = { ...spec.aes, x: "x", y: "y" };
|
|
4348
|
+
break;
|
|
3867
4349
|
}
|
|
3868
4350
|
}
|
|
3869
4351
|
scaleData = applyCoordTransform(scaleData, scaleAes, spec.coord);
|
|
@@ -3898,6 +4380,10 @@ function renderToCanvas(spec, options) {
|
|
|
3898
4380
|
geomAes = { ...spec.aes, x: "x", y: "y" };
|
|
3899
4381
|
} else if (geom.stat === "qq_line") {
|
|
3900
4382
|
geomAes = { ...spec.aes, x: "x", y: "y", xend: "xend", yend: "yend" };
|
|
4383
|
+
} else if (geom.stat === "bin2d") {
|
|
4384
|
+
geomAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
|
|
4385
|
+
} else if (geom.stat === "density_2d") {
|
|
4386
|
+
geomAes = { ...spec.aes, x: "x", y: "y" };
|
|
3901
4387
|
}
|
|
3902
4388
|
geomData = applyCoordTransform(geomData, geomAes, spec.coord);
|
|
3903
4389
|
}
|
|
@@ -4148,8 +4634,14 @@ function renderPanel(canvas, panel, layout, spec, facet, sharedScales, nrow = 1,
|
|
|
4148
4634
|
renderPanelAxes(canvas, scales, plotArea, panel.row, panel.col, nrow, ncol, spec.theme);
|
|
4149
4635
|
for (const geom of spec.geoms) {
|
|
4150
4636
|
let geomData = applyStatTransform(panel.data, geom, spec.aes);
|
|
4151
|
-
|
|
4152
|
-
|
|
4637
|
+
let geomAes = spec.aes;
|
|
4638
|
+
if (geom.stat === "bin" || geom.stat === "boxplot" || geom.stat === "count" || geom.stat === "qq") {
|
|
4639
|
+
geomAes = { ...spec.aes, x: "x", y: "y" };
|
|
4640
|
+
} else if (geom.stat === "bin2d") {
|
|
4641
|
+
geomAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
|
|
4642
|
+
}
|
|
4643
|
+
geomData = applyCoordTransform(geomData, geomAes, spec.coord);
|
|
4644
|
+
renderGeom(geomData, geom, geomAes, scales, canvas, spec.coord.type);
|
|
4153
4645
|
}
|
|
4154
4646
|
}
|
|
4155
4647
|
function renderPanelAxes(canvas, scales, plotArea, row, col, nrow, _ncol, _theme) {
|
|
@@ -4197,9 +4689,22 @@ function renderToString(spec, options) {
|
|
|
4197
4689
|
}
|
|
4198
4690
|
return canvas.toAnsiString();
|
|
4199
4691
|
}
|
|
4692
|
+
var init_pipeline = __esm(() => {
|
|
4693
|
+
init_canvas();
|
|
4694
|
+
init_scales();
|
|
4695
|
+
init_render_geoms();
|
|
4696
|
+
init_render_axes();
|
|
4697
|
+
init_bin2d();
|
|
4698
|
+
init_summary();
|
|
4699
|
+
});
|
|
4200
4700
|
|
|
4201
4701
|
// src/pipeline/index.ts
|
|
4202
|
-
|
|
4702
|
+
var init_pipeline2 = __esm(() => {
|
|
4703
|
+
init_pipeline();
|
|
4704
|
+
init_scales();
|
|
4705
|
+
init_render_geoms();
|
|
4706
|
+
init_render_axes();
|
|
4707
|
+
});
|
|
4203
4708
|
|
|
4204
4709
|
// src/grammar.ts
|
|
4205
4710
|
class GGPlot {
|
|
@@ -4290,6 +4795,9 @@ class GGPlot {
|
|
|
4290
4795
|
function gg(data = []) {
|
|
4291
4796
|
return new GGPlot(data);
|
|
4292
4797
|
}
|
|
4798
|
+
var init_grammar = __esm(() => {
|
|
4799
|
+
init_pipeline2();
|
|
4800
|
+
});
|
|
4293
4801
|
|
|
4294
4802
|
// src/geoms/point.ts
|
|
4295
4803
|
function geom_point(options = {}) {
|
|
@@ -4305,6 +4813,7 @@ function geom_point(options = {}) {
|
|
|
4305
4813
|
}
|
|
4306
4814
|
};
|
|
4307
4815
|
}
|
|
4816
|
+
|
|
4308
4817
|
// src/geoms/line.ts
|
|
4309
4818
|
function geom_line(options = {}) {
|
|
4310
4819
|
return {
|
|
@@ -4343,6 +4852,7 @@ function geom_vline(options) {
|
|
|
4343
4852
|
}
|
|
4344
4853
|
};
|
|
4345
4854
|
}
|
|
4855
|
+
|
|
4346
4856
|
// src/geoms/path.ts
|
|
4347
4857
|
function geom_path(options = {}) {
|
|
4348
4858
|
return {
|
|
@@ -4359,6 +4869,7 @@ function geom_path(options = {}) {
|
|
|
4359
4869
|
}
|
|
4360
4870
|
};
|
|
4361
4871
|
}
|
|
4872
|
+
|
|
4362
4873
|
// src/geoms/bar.ts
|
|
4363
4874
|
function geom_bar(options = {}) {
|
|
4364
4875
|
return {
|
|
@@ -4376,6 +4887,7 @@ function geom_bar(options = {}) {
|
|
|
4376
4887
|
function geom_col(options = {}) {
|
|
4377
4888
|
return geom_bar({ ...options, stat: "identity" });
|
|
4378
4889
|
}
|
|
4890
|
+
|
|
4379
4891
|
// src/geoms/text.ts
|
|
4380
4892
|
function geom_text(options = {}) {
|
|
4381
4893
|
return {
|
|
@@ -4408,6 +4920,7 @@ function geom_label(options = {}) {
|
|
|
4408
4920
|
}
|
|
4409
4921
|
};
|
|
4410
4922
|
}
|
|
4923
|
+
|
|
4411
4924
|
// src/geoms/area.ts
|
|
4412
4925
|
function geom_area(options = {}) {
|
|
4413
4926
|
return {
|
|
@@ -4433,6 +4946,7 @@ function geom_ribbon(options = {}) {
|
|
|
4433
4946
|
}
|
|
4434
4947
|
};
|
|
4435
4948
|
}
|
|
4949
|
+
|
|
4436
4950
|
// src/geoms/histogram.ts
|
|
4437
4951
|
function geom_histogram(options = {}) {
|
|
4438
4952
|
return {
|
|
@@ -4464,6 +4978,7 @@ function geom_freqpoly(options = {}) {
|
|
|
4464
4978
|
}
|
|
4465
4979
|
};
|
|
4466
4980
|
}
|
|
4981
|
+
|
|
4467
4982
|
// src/geoms/boxplot.ts
|
|
4468
4983
|
function geom_boxplot(options = {}) {
|
|
4469
4984
|
return {
|
|
@@ -4480,6 +4995,7 @@ function geom_boxplot(options = {}) {
|
|
|
4480
4995
|
}
|
|
4481
4996
|
};
|
|
4482
4997
|
}
|
|
4998
|
+
|
|
4483
4999
|
// src/geoms/segment.ts
|
|
4484
5000
|
function geom_segment(options = {}) {
|
|
4485
5001
|
return {
|
|
@@ -4512,6 +5028,7 @@ function geom_curve(options = {}) {
|
|
|
4512
5028
|
}
|
|
4513
5029
|
};
|
|
4514
5030
|
}
|
|
5031
|
+
|
|
4515
5032
|
// src/geoms/smooth.ts
|
|
4516
5033
|
function geom_smooth(options = {}) {
|
|
4517
5034
|
return {
|
|
@@ -4531,6 +5048,7 @@ function geom_smooth(options = {}) {
|
|
|
4531
5048
|
}
|
|
4532
5049
|
};
|
|
4533
5050
|
}
|
|
5051
|
+
|
|
4534
5052
|
// src/geoms/step.ts
|
|
4535
5053
|
function geom_step(options = {}) {
|
|
4536
5054
|
return {
|
|
@@ -4546,6 +5064,7 @@ function geom_step(options = {}) {
|
|
|
4546
5064
|
}
|
|
4547
5065
|
};
|
|
4548
5066
|
}
|
|
5067
|
+
|
|
4549
5068
|
// src/geoms/rug.ts
|
|
4550
5069
|
function geom_rug(options = {}) {
|
|
4551
5070
|
return {
|
|
@@ -4561,6 +5080,7 @@ function geom_rug(options = {}) {
|
|
|
4561
5080
|
}
|
|
4562
5081
|
};
|
|
4563
5082
|
}
|
|
5083
|
+
|
|
4564
5084
|
// src/geoms/violin.ts
|
|
4565
5085
|
function geom_violin(options = {}) {
|
|
4566
5086
|
return {
|
|
@@ -4578,6 +5098,7 @@ function geom_violin(options = {}) {
|
|
|
4578
5098
|
}
|
|
4579
5099
|
};
|
|
4580
5100
|
}
|
|
5101
|
+
|
|
4581
5102
|
// src/geoms/tile.ts
|
|
4582
5103
|
function geom_tile(options = {}) {
|
|
4583
5104
|
return {
|
|
@@ -4596,6 +5117,22 @@ function geom_tile(options = {}) {
|
|
|
4596
5117
|
function geom_raster(options = {}) {
|
|
4597
5118
|
return geom_tile(options);
|
|
4598
5119
|
}
|
|
5120
|
+
|
|
5121
|
+
// src/geoms/bin2d.ts
|
|
5122
|
+
function geom_bin2d(options = {}) {
|
|
5123
|
+
return {
|
|
5124
|
+
type: "bin2d",
|
|
5125
|
+
stat: "bin2d",
|
|
5126
|
+
params: {
|
|
5127
|
+
bins: options.bins ?? 30,
|
|
5128
|
+
binsx: options.binsx,
|
|
5129
|
+
binsy: options.binsy,
|
|
5130
|
+
alpha: options.alpha ?? 1,
|
|
5131
|
+
drop: options.drop ?? true
|
|
5132
|
+
}
|
|
5133
|
+
};
|
|
5134
|
+
}
|
|
5135
|
+
|
|
4599
5136
|
// src/geoms/contour.ts
|
|
4600
5137
|
function geom_contour(options = {}) {
|
|
4601
5138
|
return {
|
|
@@ -4638,6 +5175,7 @@ function geom_density_2d(options = {}) {
|
|
|
4638
5175
|
}
|
|
4639
5176
|
};
|
|
4640
5177
|
}
|
|
5178
|
+
|
|
4641
5179
|
// src/geoms/errorbar.ts
|
|
4642
5180
|
function geom_errorbar(options = {}) {
|
|
4643
5181
|
return {
|
|
@@ -4704,6 +5242,7 @@ function geom_pointrange(options = {}) {
|
|
|
4704
5242
|
}
|
|
4705
5243
|
};
|
|
4706
5244
|
}
|
|
5245
|
+
|
|
4707
5246
|
// src/geoms/rect.ts
|
|
4708
5247
|
function geom_rect(options = {}) {
|
|
4709
5248
|
return {
|
|
@@ -4732,6 +5271,7 @@ function geom_abline(options = {}) {
|
|
|
4732
5271
|
}
|
|
4733
5272
|
};
|
|
4734
5273
|
}
|
|
5274
|
+
|
|
4735
5275
|
// src/geoms/qq.ts
|
|
4736
5276
|
function geom_qq(options = {}) {
|
|
4737
5277
|
return {
|
|
@@ -4760,6 +5300,10 @@ function geom_qq_line(options = {}) {
|
|
|
4760
5300
|
}
|
|
4761
5301
|
};
|
|
4762
5302
|
}
|
|
5303
|
+
|
|
5304
|
+
// src/geoms/index.ts
|
|
5305
|
+
var init_geoms = () => {};
|
|
5306
|
+
|
|
4763
5307
|
// src/scales/continuous.ts
|
|
4764
5308
|
function createContinuousScale(aesthetic, options = {}) {
|
|
4765
5309
|
const trans = options.trans ?? "identity";
|
|
@@ -4838,6 +5382,7 @@ function scale_y2_sqrt(options = {}) {
|
|
|
4838
5382
|
function scale_y2_reverse(options = {}) {
|
|
4839
5383
|
return createContinuousScale("y2", { ...options, trans: "reverse" });
|
|
4840
5384
|
}
|
|
5385
|
+
|
|
4841
5386
|
// src/scales/discrete.ts
|
|
4842
5387
|
function createDiscreteScale(aesthetic, options = {}) {
|
|
4843
5388
|
const valueToPosition = new Map;
|
|
@@ -4887,123 +5432,8 @@ function scale_x_discrete(options = {}) {
|
|
|
4887
5432
|
function scale_y_discrete(options = {}) {
|
|
4888
5433
|
return createDiscreteScale("y", options);
|
|
4889
5434
|
}
|
|
5435
|
+
|
|
4890
5436
|
// src/scales/color.ts
|
|
4891
|
-
var PALETTES = {
|
|
4892
|
-
viridis: ["#440154", "#414487", "#2a788e", "#22a884", "#7ad151", "#fde725"],
|
|
4893
|
-
plasma: ["#0d0887", "#6a00a8", "#b12a90", "#e16462", "#fca636", "#f0f921"],
|
|
4894
|
-
inferno: ["#000004", "#420a68", "#932667", "#dd513a", "#fca50a", "#fcffa4"],
|
|
4895
|
-
magma: ["#000004", "#3b0f70", "#8c2981", "#de4968", "#fe9f6d", "#fcfdbf"],
|
|
4896
|
-
cividis: ["#002051", "#1d3f6e", "#52596a", "#7b7b78", "#a89f68", "#d9c84a", "#fdea45"],
|
|
4897
|
-
turbo: ["#30123b", "#4662d7", "#35aaf8", "#1ae4b6", "#72fe5e", "#c8ef34", "#faba39", "#f66b19", "#ca2a04"],
|
|
4898
|
-
Blues: ["#f7fbff", "#deebf7", "#c6dbef", "#9ecae1", "#6baed6", "#4292c6", "#2171b5", "#08519c", "#08306b"],
|
|
4899
|
-
Greens: ["#f7fcf5", "#e5f5e0", "#c7e9c0", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#006d2c", "#00441b"],
|
|
4900
|
-
Greys: ["#ffffff", "#f0f0f0", "#d9d9d9", "#bdbdbd", "#969696", "#737373", "#525252", "#252525", "#000000"],
|
|
4901
|
-
Oranges: ["#fff5eb", "#fee6ce", "#fdd0a2", "#fdae6b", "#fd8d3c", "#f16913", "#d94801", "#a63603", "#7f2704"],
|
|
4902
|
-
Purples: ["#fcfbfd", "#efedf5", "#dadaeb", "#bcbddc", "#9e9ac8", "#807dba", "#6a51a3", "#54278f", "#3f007d"],
|
|
4903
|
-
Reds: ["#fff5f0", "#fee0d2", "#fcbba1", "#fc9272", "#fb6a4a", "#ef3b2c", "#cb181d", "#a50f15", "#67000d"],
|
|
4904
|
-
BuGn: ["#f7fcfd", "#e5f5f9", "#ccece6", "#99d8c9", "#66c2a4", "#41ae76", "#238b45", "#006d2c", "#00441b"],
|
|
4905
|
-
BuPu: ["#f7fcfd", "#e0ecf4", "#bfd3e6", "#9ebcda", "#8c96c6", "#8c6bb1", "#88419d", "#810f7c", "#4d004b"],
|
|
4906
|
-
GnBu: ["#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5", "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081"],
|
|
4907
|
-
OrRd: ["#fff7ec", "#fee8c8", "#fdd49e", "#fdbb84", "#fc8d59", "#ef6548", "#d7301f", "#b30000", "#7f0000"],
|
|
4908
|
-
PuBu: ["#fff7fb", "#ece7f2", "#d0d1e6", "#a6bddb", "#74a9cf", "#3690c0", "#0570b0", "#045a8d", "#023858"],
|
|
4909
|
-
PuBuGn: ["#fff7fb", "#ece2f0", "#d0d1e6", "#a6bddb", "#67a9cf", "#3690c0", "#02818a", "#016c59", "#014636"],
|
|
4910
|
-
PuRd: ["#f7f4f9", "#e7e1ef", "#d4b9da", "#c994c7", "#df65b0", "#e7298a", "#ce1256", "#980043", "#67001f"],
|
|
4911
|
-
RdPu: ["#fff7f3", "#fde0dd", "#fcc5c0", "#fa9fb5", "#f768a1", "#dd3497", "#ae017e", "#7a0177", "#49006a"],
|
|
4912
|
-
YlGn: ["#ffffe5", "#f7fcb9", "#d9f0a3", "#addd8e", "#78c679", "#41ab5d", "#238b45", "#006837", "#004529"],
|
|
4913
|
-
YlGnBu: ["#ffffd9", "#edf8b1", "#c7e9b4", "#7fcdbb", "#41b6c4", "#1d91c0", "#225ea8", "#253494", "#081d58"],
|
|
4914
|
-
YlOrBr: ["#ffffe5", "#fff7bc", "#fee391", "#fec44f", "#fe9929", "#ec7014", "#cc4c02", "#993404", "#662506"],
|
|
4915
|
-
YlOrRd: ["#ffffcc", "#ffeda0", "#fed976", "#feb24c", "#fd8d3c", "#fc4e2a", "#e31a1c", "#bd0026", "#800026"],
|
|
4916
|
-
BrBG: ["#543005", "#8c510a", "#bf812d", "#dfc27d", "#f6e8c3", "#f5f5f5", "#c7eae5", "#80cdc1", "#35978f", "#01665e", "#003c30"],
|
|
4917
|
-
PiYG: ["#8e0152", "#c51b7d", "#de77ae", "#f1b6da", "#fde0ef", "#f7f7f7", "#e6f5d0", "#b8e186", "#7fbc41", "#4d9221", "#276419"],
|
|
4918
|
-
PRGn: ["#40004b", "#762a83", "#9970ab", "#c2a5cf", "#e7d4e8", "#f7f7f7", "#d9f0d3", "#a6dba0", "#5aae61", "#1b7837", "#00441b"],
|
|
4919
|
-
PuOr: ["#7f3b08", "#b35806", "#e08214", "#fdb863", "#fee0b6", "#f7f7f7", "#d8daeb", "#b2abd2", "#8073ac", "#542788", "#2d004b"],
|
|
4920
|
-
RdBu: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#f7f7f7", "#d1e5f0", "#92c5de", "#4393c3", "#2166ac", "#053061"],
|
|
4921
|
-
RdGy: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#ffffff", "#e0e0e0", "#bababa", "#878787", "#4d4d4d", "#1a1a1a"],
|
|
4922
|
-
RdYlBu: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee090", "#ffffbf", "#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"],
|
|
4923
|
-
RdYlGn: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#d9ef8b", "#a6d96a", "#66bd63", "#1a9850", "#006837"],
|
|
4924
|
-
Spectral: ["#9e0142", "#d53e4f", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#e6f598", "#abdda4", "#66c2a5", "#3288bd", "#5e4fa2"],
|
|
4925
|
-
category10: [
|
|
4926
|
-
"#1f77b4",
|
|
4927
|
-
"#ff7f0e",
|
|
4928
|
-
"#2ca02c",
|
|
4929
|
-
"#d62728",
|
|
4930
|
-
"#9467bd",
|
|
4931
|
-
"#8c564b",
|
|
4932
|
-
"#e377c2",
|
|
4933
|
-
"#7f7f7f",
|
|
4934
|
-
"#bcbd22",
|
|
4935
|
-
"#17becf"
|
|
4936
|
-
],
|
|
4937
|
-
category20: [
|
|
4938
|
-
"#1f77b4",
|
|
4939
|
-
"#aec7e8",
|
|
4940
|
-
"#ff7f0e",
|
|
4941
|
-
"#ffbb78",
|
|
4942
|
-
"#2ca02c",
|
|
4943
|
-
"#98df8a",
|
|
4944
|
-
"#d62728",
|
|
4945
|
-
"#ff9896",
|
|
4946
|
-
"#9467bd",
|
|
4947
|
-
"#c5b0d5",
|
|
4948
|
-
"#8c564b",
|
|
4949
|
-
"#c49c94",
|
|
4950
|
-
"#e377c2",
|
|
4951
|
-
"#f7b6d2",
|
|
4952
|
-
"#7f7f7f",
|
|
4953
|
-
"#c7c7c7",
|
|
4954
|
-
"#bcbd22",
|
|
4955
|
-
"#dbdb8d",
|
|
4956
|
-
"#17becf",
|
|
4957
|
-
"#9edae5"
|
|
4958
|
-
],
|
|
4959
|
-
Accent: ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17", "#666666"],
|
|
4960
|
-
Dark2: ["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"],
|
|
4961
|
-
Paired: ["#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e31a1c", "#fdbf6f", "#ff7f00", "#cab2d6", "#6a3d9a", "#ffff99", "#b15928"],
|
|
4962
|
-
Pastel1: ["#fbb4ae", "#b3cde3", "#ccebc5", "#decbe4", "#fed9a6", "#ffffcc", "#e5d8bd", "#fddaec", "#f2f2f2"],
|
|
4963
|
-
Pastel2: ["#b3e2cd", "#fdcdac", "#cbd5e8", "#f4cae4", "#e6f5c9", "#fff2ae", "#f1e2cc", "#cccccc"],
|
|
4964
|
-
Set1: ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", "#a65628", "#f781bf", "#999999"],
|
|
4965
|
-
Set2: ["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3"],
|
|
4966
|
-
Set3: ["#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f"],
|
|
4967
|
-
Tab10: [
|
|
4968
|
-
"#4e79a7",
|
|
4969
|
-
"#f28e2c",
|
|
4970
|
-
"#e15759",
|
|
4971
|
-
"#76b7b2",
|
|
4972
|
-
"#59a14f",
|
|
4973
|
-
"#edc949",
|
|
4974
|
-
"#af7aa1",
|
|
4975
|
-
"#ff9da7",
|
|
4976
|
-
"#9c755f",
|
|
4977
|
-
"#bab0ab"
|
|
4978
|
-
],
|
|
4979
|
-
Tab20: [
|
|
4980
|
-
"#4e79a7",
|
|
4981
|
-
"#a0cbe8",
|
|
4982
|
-
"#f28e2c",
|
|
4983
|
-
"#ffbe7d",
|
|
4984
|
-
"#59a14f",
|
|
4985
|
-
"#8cd17d",
|
|
4986
|
-
"#b6992d",
|
|
4987
|
-
"#f1ce63",
|
|
4988
|
-
"#499894",
|
|
4989
|
-
"#86bcb6",
|
|
4990
|
-
"#e15759",
|
|
4991
|
-
"#ff9d9a",
|
|
4992
|
-
"#79706e",
|
|
4993
|
-
"#bab0ac",
|
|
4994
|
-
"#d37295",
|
|
4995
|
-
"#fabfd2",
|
|
4996
|
-
"#b07aa1",
|
|
4997
|
-
"#d4a6c8",
|
|
4998
|
-
"#9d7660",
|
|
4999
|
-
"#d7b5a6"
|
|
5000
|
-
],
|
|
5001
|
-
thermal: ["#042333", "#2c3e50", "#0b5345", "#1e8449", "#f39c12", "#e74c3c", "#fadbd8"],
|
|
5002
|
-
haline: ["#2c3e50", "#1a5276", "#2980b9", "#5dade2", "#aed6f1", "#d5f5e3"],
|
|
5003
|
-
terrain: ["#333399", "#0099ff", "#00cc00", "#ffff00", "#ff9900", "#cc6600", "#996633", "#ffffff"],
|
|
5004
|
-
rainbow: ["#ff0000", "#ff8000", "#ffff00", "#80ff00", "#00ff00", "#00ff80", "#00ffff", "#0080ff", "#0000ff", "#8000ff"],
|
|
5005
|
-
cubehelix: ["#000000", "#1a1530", "#30304d", "#4d5366", "#6d826e", "#8ab17d", "#add38a", "#dae8a2", "#ffffff"]
|
|
5006
|
-
};
|
|
5007
5437
|
function hexToRgba(hex) {
|
|
5008
5438
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
5009
5439
|
if (!result)
|
|
@@ -5224,6 +5654,126 @@ function getAvailablePalettes() {
|
|
|
5224
5654
|
function getPaletteColors(name) {
|
|
5225
5655
|
return PALETTES[name];
|
|
5226
5656
|
}
|
|
5657
|
+
var PALETTES;
|
|
5658
|
+
var init_color = __esm(() => {
|
|
5659
|
+
PALETTES = {
|
|
5660
|
+
viridis: ["#440154", "#414487", "#2a788e", "#22a884", "#7ad151", "#fde725"],
|
|
5661
|
+
plasma: ["#0d0887", "#6a00a8", "#b12a90", "#e16462", "#fca636", "#f0f921"],
|
|
5662
|
+
inferno: ["#000004", "#420a68", "#932667", "#dd513a", "#fca50a", "#fcffa4"],
|
|
5663
|
+
magma: ["#000004", "#3b0f70", "#8c2981", "#de4968", "#fe9f6d", "#fcfdbf"],
|
|
5664
|
+
cividis: ["#002051", "#1d3f6e", "#52596a", "#7b7b78", "#a89f68", "#d9c84a", "#fdea45"],
|
|
5665
|
+
turbo: ["#30123b", "#4662d7", "#35aaf8", "#1ae4b6", "#72fe5e", "#c8ef34", "#faba39", "#f66b19", "#ca2a04"],
|
|
5666
|
+
Blues: ["#f7fbff", "#deebf7", "#c6dbef", "#9ecae1", "#6baed6", "#4292c6", "#2171b5", "#08519c", "#08306b"],
|
|
5667
|
+
Greens: ["#f7fcf5", "#e5f5e0", "#c7e9c0", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#006d2c", "#00441b"],
|
|
5668
|
+
Greys: ["#ffffff", "#f0f0f0", "#d9d9d9", "#bdbdbd", "#969696", "#737373", "#525252", "#252525", "#000000"],
|
|
5669
|
+
Oranges: ["#fff5eb", "#fee6ce", "#fdd0a2", "#fdae6b", "#fd8d3c", "#f16913", "#d94801", "#a63603", "#7f2704"],
|
|
5670
|
+
Purples: ["#fcfbfd", "#efedf5", "#dadaeb", "#bcbddc", "#9e9ac8", "#807dba", "#6a51a3", "#54278f", "#3f007d"],
|
|
5671
|
+
Reds: ["#fff5f0", "#fee0d2", "#fcbba1", "#fc9272", "#fb6a4a", "#ef3b2c", "#cb181d", "#a50f15", "#67000d"],
|
|
5672
|
+
BuGn: ["#f7fcfd", "#e5f5f9", "#ccece6", "#99d8c9", "#66c2a4", "#41ae76", "#238b45", "#006d2c", "#00441b"],
|
|
5673
|
+
BuPu: ["#f7fcfd", "#e0ecf4", "#bfd3e6", "#9ebcda", "#8c96c6", "#8c6bb1", "#88419d", "#810f7c", "#4d004b"],
|
|
5674
|
+
GnBu: ["#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5", "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081"],
|
|
5675
|
+
OrRd: ["#fff7ec", "#fee8c8", "#fdd49e", "#fdbb84", "#fc8d59", "#ef6548", "#d7301f", "#b30000", "#7f0000"],
|
|
5676
|
+
PuBu: ["#fff7fb", "#ece7f2", "#d0d1e6", "#a6bddb", "#74a9cf", "#3690c0", "#0570b0", "#045a8d", "#023858"],
|
|
5677
|
+
PuBuGn: ["#fff7fb", "#ece2f0", "#d0d1e6", "#a6bddb", "#67a9cf", "#3690c0", "#02818a", "#016c59", "#014636"],
|
|
5678
|
+
PuRd: ["#f7f4f9", "#e7e1ef", "#d4b9da", "#c994c7", "#df65b0", "#e7298a", "#ce1256", "#980043", "#67001f"],
|
|
5679
|
+
RdPu: ["#fff7f3", "#fde0dd", "#fcc5c0", "#fa9fb5", "#f768a1", "#dd3497", "#ae017e", "#7a0177", "#49006a"],
|
|
5680
|
+
YlGn: ["#ffffe5", "#f7fcb9", "#d9f0a3", "#addd8e", "#78c679", "#41ab5d", "#238b45", "#006837", "#004529"],
|
|
5681
|
+
YlGnBu: ["#ffffd9", "#edf8b1", "#c7e9b4", "#7fcdbb", "#41b6c4", "#1d91c0", "#225ea8", "#253494", "#081d58"],
|
|
5682
|
+
YlOrBr: ["#ffffe5", "#fff7bc", "#fee391", "#fec44f", "#fe9929", "#ec7014", "#cc4c02", "#993404", "#662506"],
|
|
5683
|
+
YlOrRd: ["#ffffcc", "#ffeda0", "#fed976", "#feb24c", "#fd8d3c", "#fc4e2a", "#e31a1c", "#bd0026", "#800026"],
|
|
5684
|
+
BrBG: ["#543005", "#8c510a", "#bf812d", "#dfc27d", "#f6e8c3", "#f5f5f5", "#c7eae5", "#80cdc1", "#35978f", "#01665e", "#003c30"],
|
|
5685
|
+
PiYG: ["#8e0152", "#c51b7d", "#de77ae", "#f1b6da", "#fde0ef", "#f7f7f7", "#e6f5d0", "#b8e186", "#7fbc41", "#4d9221", "#276419"],
|
|
5686
|
+
PRGn: ["#40004b", "#762a83", "#9970ab", "#c2a5cf", "#e7d4e8", "#f7f7f7", "#d9f0d3", "#a6dba0", "#5aae61", "#1b7837", "#00441b"],
|
|
5687
|
+
PuOr: ["#7f3b08", "#b35806", "#e08214", "#fdb863", "#fee0b6", "#f7f7f7", "#d8daeb", "#b2abd2", "#8073ac", "#542788", "#2d004b"],
|
|
5688
|
+
RdBu: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#f7f7f7", "#d1e5f0", "#92c5de", "#4393c3", "#2166ac", "#053061"],
|
|
5689
|
+
RdGy: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#ffffff", "#e0e0e0", "#bababa", "#878787", "#4d4d4d", "#1a1a1a"],
|
|
5690
|
+
RdYlBu: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee090", "#ffffbf", "#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"],
|
|
5691
|
+
RdYlGn: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#d9ef8b", "#a6d96a", "#66bd63", "#1a9850", "#006837"],
|
|
5692
|
+
Spectral: ["#9e0142", "#d53e4f", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#e6f598", "#abdda4", "#66c2a5", "#3288bd", "#5e4fa2"],
|
|
5693
|
+
category10: [
|
|
5694
|
+
"#1f77b4",
|
|
5695
|
+
"#ff7f0e",
|
|
5696
|
+
"#2ca02c",
|
|
5697
|
+
"#d62728",
|
|
5698
|
+
"#9467bd",
|
|
5699
|
+
"#8c564b",
|
|
5700
|
+
"#e377c2",
|
|
5701
|
+
"#7f7f7f",
|
|
5702
|
+
"#bcbd22",
|
|
5703
|
+
"#17becf"
|
|
5704
|
+
],
|
|
5705
|
+
category20: [
|
|
5706
|
+
"#1f77b4",
|
|
5707
|
+
"#aec7e8",
|
|
5708
|
+
"#ff7f0e",
|
|
5709
|
+
"#ffbb78",
|
|
5710
|
+
"#2ca02c",
|
|
5711
|
+
"#98df8a",
|
|
5712
|
+
"#d62728",
|
|
5713
|
+
"#ff9896",
|
|
5714
|
+
"#9467bd",
|
|
5715
|
+
"#c5b0d5",
|
|
5716
|
+
"#8c564b",
|
|
5717
|
+
"#c49c94",
|
|
5718
|
+
"#e377c2",
|
|
5719
|
+
"#f7b6d2",
|
|
5720
|
+
"#7f7f7f",
|
|
5721
|
+
"#c7c7c7",
|
|
5722
|
+
"#bcbd22",
|
|
5723
|
+
"#dbdb8d",
|
|
5724
|
+
"#17becf",
|
|
5725
|
+
"#9edae5"
|
|
5726
|
+
],
|
|
5727
|
+
Accent: ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17", "#666666"],
|
|
5728
|
+
Dark2: ["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"],
|
|
5729
|
+
Paired: ["#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e31a1c", "#fdbf6f", "#ff7f00", "#cab2d6", "#6a3d9a", "#ffff99", "#b15928"],
|
|
5730
|
+
Pastel1: ["#fbb4ae", "#b3cde3", "#ccebc5", "#decbe4", "#fed9a6", "#ffffcc", "#e5d8bd", "#fddaec", "#f2f2f2"],
|
|
5731
|
+
Pastel2: ["#b3e2cd", "#fdcdac", "#cbd5e8", "#f4cae4", "#e6f5c9", "#fff2ae", "#f1e2cc", "#cccccc"],
|
|
5732
|
+
Set1: ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", "#a65628", "#f781bf", "#999999"],
|
|
5733
|
+
Set2: ["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3"],
|
|
5734
|
+
Set3: ["#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f"],
|
|
5735
|
+
Tab10: [
|
|
5736
|
+
"#4e79a7",
|
|
5737
|
+
"#f28e2c",
|
|
5738
|
+
"#e15759",
|
|
5739
|
+
"#76b7b2",
|
|
5740
|
+
"#59a14f",
|
|
5741
|
+
"#edc949",
|
|
5742
|
+
"#af7aa1",
|
|
5743
|
+
"#ff9da7",
|
|
5744
|
+
"#9c755f",
|
|
5745
|
+
"#bab0ab"
|
|
5746
|
+
],
|
|
5747
|
+
Tab20: [
|
|
5748
|
+
"#4e79a7",
|
|
5749
|
+
"#a0cbe8",
|
|
5750
|
+
"#f28e2c",
|
|
5751
|
+
"#ffbe7d",
|
|
5752
|
+
"#59a14f",
|
|
5753
|
+
"#8cd17d",
|
|
5754
|
+
"#b6992d",
|
|
5755
|
+
"#f1ce63",
|
|
5756
|
+
"#499894",
|
|
5757
|
+
"#86bcb6",
|
|
5758
|
+
"#e15759",
|
|
5759
|
+
"#ff9d9a",
|
|
5760
|
+
"#79706e",
|
|
5761
|
+
"#bab0ac",
|
|
5762
|
+
"#d37295",
|
|
5763
|
+
"#fabfd2",
|
|
5764
|
+
"#b07aa1",
|
|
5765
|
+
"#d4a6c8",
|
|
5766
|
+
"#9d7660",
|
|
5767
|
+
"#d7b5a6"
|
|
5768
|
+
],
|
|
5769
|
+
thermal: ["#042333", "#2c3e50", "#0b5345", "#1e8449", "#f39c12", "#e74c3c", "#fadbd8"],
|
|
5770
|
+
haline: ["#2c3e50", "#1a5276", "#2980b9", "#5dade2", "#aed6f1", "#d5f5e3"],
|
|
5771
|
+
terrain: ["#333399", "#0099ff", "#00cc00", "#ffff00", "#ff9900", "#cc6600", "#996633", "#ffffff"],
|
|
5772
|
+
rainbow: ["#ff0000", "#ff8000", "#ffff00", "#80ff00", "#00ff00", "#00ff80", "#00ffff", "#0080ff", "#0000ff", "#8000ff"],
|
|
5773
|
+
cubehelix: ["#000000", "#1a1530", "#30304d", "#4d5366", "#6d826e", "#8ab17d", "#add38a", "#dae8a2", "#ffffff"]
|
|
5774
|
+
};
|
|
5775
|
+
});
|
|
5776
|
+
|
|
5227
5777
|
// src/scales/size.ts
|
|
5228
5778
|
function scale_size_continuous(options = {}) {
|
|
5229
5779
|
const range = options.range ?? [1, 6];
|
|
@@ -5292,45 +5842,8 @@ function scale_size_binned(options = {}) {
|
|
|
5292
5842
|
}
|
|
5293
5843
|
};
|
|
5294
5844
|
}
|
|
5845
|
+
|
|
5295
5846
|
// src/scales/shape.ts
|
|
5296
|
-
var DEFAULT_SHAPES = [
|
|
5297
|
-
"circle",
|
|
5298
|
-
"square",
|
|
5299
|
-
"triangle",
|
|
5300
|
-
"diamond",
|
|
5301
|
-
"cross",
|
|
5302
|
-
"plus",
|
|
5303
|
-
"star",
|
|
5304
|
-
"open_circle",
|
|
5305
|
-
"open_square",
|
|
5306
|
-
"open_triangle",
|
|
5307
|
-
"open_diamond",
|
|
5308
|
-
"dot"
|
|
5309
|
-
];
|
|
5310
|
-
var SHAPE_CHARS = {
|
|
5311
|
-
circle: "●",
|
|
5312
|
-
filled_circle: "●",
|
|
5313
|
-
open_circle: "○",
|
|
5314
|
-
square: "■",
|
|
5315
|
-
filled_square: "■",
|
|
5316
|
-
open_square: "□",
|
|
5317
|
-
triangle: "▲",
|
|
5318
|
-
filled_triangle: "▲",
|
|
5319
|
-
open_triangle: "△",
|
|
5320
|
-
triangle_down: "▼",
|
|
5321
|
-
diamond: "◆",
|
|
5322
|
-
filled_diamond: "◆",
|
|
5323
|
-
open_diamond: "◇",
|
|
5324
|
-
cross: "✕",
|
|
5325
|
-
plus: "+",
|
|
5326
|
-
star: "★",
|
|
5327
|
-
open_star: "☆",
|
|
5328
|
-
dot: "•",
|
|
5329
|
-
bullet: "•",
|
|
5330
|
-
asterisk: "*",
|
|
5331
|
-
hash: "#",
|
|
5332
|
-
at: "@"
|
|
5333
|
-
};
|
|
5334
5847
|
function scale_shape_discrete(options = {}) {
|
|
5335
5848
|
const shapes = options.values ?? DEFAULT_SHAPES;
|
|
5336
5849
|
return {
|
|
@@ -5389,6 +5902,48 @@ function scale_shape_ordinal(options = {}) {
|
|
|
5389
5902
|
}
|
|
5390
5903
|
};
|
|
5391
5904
|
}
|
|
5905
|
+
var DEFAULT_SHAPES, SHAPE_CHARS;
|
|
5906
|
+
var init_shape = __esm(() => {
|
|
5907
|
+
DEFAULT_SHAPES = [
|
|
5908
|
+
"circle",
|
|
5909
|
+
"square",
|
|
5910
|
+
"triangle",
|
|
5911
|
+
"diamond",
|
|
5912
|
+
"cross",
|
|
5913
|
+
"plus",
|
|
5914
|
+
"star",
|
|
5915
|
+
"open_circle",
|
|
5916
|
+
"open_square",
|
|
5917
|
+
"open_triangle",
|
|
5918
|
+
"open_diamond",
|
|
5919
|
+
"dot"
|
|
5920
|
+
];
|
|
5921
|
+
SHAPE_CHARS = {
|
|
5922
|
+
circle: "●",
|
|
5923
|
+
filled_circle: "●",
|
|
5924
|
+
open_circle: "○",
|
|
5925
|
+
square: "■",
|
|
5926
|
+
filled_square: "■",
|
|
5927
|
+
open_square: "□",
|
|
5928
|
+
triangle: "▲",
|
|
5929
|
+
filled_triangle: "▲",
|
|
5930
|
+
open_triangle: "△",
|
|
5931
|
+
triangle_down: "▼",
|
|
5932
|
+
diamond: "◆",
|
|
5933
|
+
filled_diamond: "◆",
|
|
5934
|
+
open_diamond: "◇",
|
|
5935
|
+
cross: "✕",
|
|
5936
|
+
plus: "+",
|
|
5937
|
+
star: "★",
|
|
5938
|
+
open_star: "☆",
|
|
5939
|
+
dot: "•",
|
|
5940
|
+
bullet: "•",
|
|
5941
|
+
asterisk: "*",
|
|
5942
|
+
hash: "#",
|
|
5943
|
+
at: "@"
|
|
5944
|
+
};
|
|
5945
|
+
});
|
|
5946
|
+
|
|
5392
5947
|
// src/scales/alpha.ts
|
|
5393
5948
|
function scale_alpha_continuous(options = {}) {
|
|
5394
5949
|
const range = options.range ?? [0.1, 1];
|
|
@@ -5485,17 +6040,8 @@ function scale_alpha_binned(options = {}) {
|
|
|
5485
6040
|
}
|
|
5486
6041
|
};
|
|
5487
6042
|
}
|
|
6043
|
+
|
|
5488
6044
|
// src/scales/datetime.ts
|
|
5489
|
-
var TIME_INTERVALS = [
|
|
5490
|
-
{ name: "millisecond", ms: 1 },
|
|
5491
|
-
{ name: "second", ms: 1000 },
|
|
5492
|
-
{ name: "minute", ms: 60 * 1000 },
|
|
5493
|
-
{ name: "hour", ms: 60 * 60 * 1000 },
|
|
5494
|
-
{ name: "day", ms: 24 * 60 * 60 * 1000 },
|
|
5495
|
-
{ name: "week", ms: 7 * 24 * 60 * 60 * 1000 },
|
|
5496
|
-
{ name: "month", ms: 30 * 24 * 60 * 60 * 1000 },
|
|
5497
|
-
{ name: "year", ms: 365 * 24 * 60 * 60 * 1000 }
|
|
5498
|
-
];
|
|
5499
6045
|
function parseDateTime(value) {
|
|
5500
6046
|
if (value === null || value === undefined)
|
|
5501
6047
|
return null;
|
|
@@ -5677,7 +6223,30 @@ function scale_y_duration(options = {}) {
|
|
|
5677
6223
|
scale.aesthetic = "y";
|
|
5678
6224
|
return scale;
|
|
5679
6225
|
}
|
|
6226
|
+
var TIME_INTERVALS;
|
|
6227
|
+
var init_datetime = __esm(() => {
|
|
6228
|
+
TIME_INTERVALS = [
|
|
6229
|
+
{ name: "millisecond", ms: 1 },
|
|
6230
|
+
{ name: "second", ms: 1000 },
|
|
6231
|
+
{ name: "minute", ms: 60 * 1000 },
|
|
6232
|
+
{ name: "hour", ms: 60 * 60 * 1000 },
|
|
6233
|
+
{ name: "day", ms: 24 * 60 * 60 * 1000 },
|
|
6234
|
+
{ name: "week", ms: 7 * 24 * 60 * 60 * 1000 },
|
|
6235
|
+
{ name: "month", ms: 30 * 24 * 60 * 60 * 1000 },
|
|
6236
|
+
{ name: "year", ms: 365 * 24 * 60 * 60 * 1000 }
|
|
6237
|
+
];
|
|
6238
|
+
});
|
|
6239
|
+
|
|
6240
|
+
// src/scales/index.ts
|
|
6241
|
+
var init_scales2 = __esm(() => {
|
|
6242
|
+
init_color();
|
|
6243
|
+
init_shape();
|
|
6244
|
+
init_datetime();
|
|
6245
|
+
});
|
|
6246
|
+
|
|
5680
6247
|
// src/repl/repl.ts
|
|
6248
|
+
import * as readline from "readline";
|
|
6249
|
+
|
|
5681
6250
|
class GGTermREPL {
|
|
5682
6251
|
rl = null;
|
|
5683
6252
|
state;
|
|
@@ -6312,7 +6881,19 @@ function startREPL(options) {
|
|
|
6312
6881
|
repl.start();
|
|
6313
6882
|
return repl;
|
|
6314
6883
|
}
|
|
6884
|
+
var init_repl = __esm(() => {
|
|
6885
|
+
init_grammar();
|
|
6886
|
+
init_geoms();
|
|
6887
|
+
init_scales2();
|
|
6888
|
+
});
|
|
6889
|
+
|
|
6890
|
+
// src/repl/index.ts
|
|
6891
|
+
var init_repl2 = __esm(() => {
|
|
6892
|
+
init_repl();
|
|
6893
|
+
});
|
|
6894
|
+
|
|
6315
6895
|
// src/cli.ts
|
|
6896
|
+
init_repl2();
|
|
6316
6897
|
import * as fs from "fs";
|
|
6317
6898
|
import * as path from "path";
|
|
6318
6899
|
var VERSION = "0.0.1";
|