@ggterm/core 0.2.5 → 0.2.7
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 +11423 -0
- package/dist/cli.js +1265 -855
- 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 +3347 -2511
- 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/index.d.ts +2 -0
- package/dist/stats/index.d.ts.map +1 -1
- package/package.json +4 -3
- 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,472 +30,64 @@ 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() {
|
|
443
|
-
return {
|
|
444
|
-
panel: {
|
|
445
|
-
background: "",
|
|
446
|
-
border: "single",
|
|
447
|
-
grid: { major: "·", minor: null }
|
|
448
|
-
},
|
|
449
|
-
axis: {
|
|
450
|
-
text: { color: "" },
|
|
451
|
-
ticks: { char: "┼", length: 1 },
|
|
452
|
-
title: { color: "", bold: false }
|
|
453
|
-
},
|
|
454
|
-
legend: {
|
|
455
|
-
position: "right",
|
|
456
|
-
title: { bold: true }
|
|
457
|
-
},
|
|
458
|
-
title: {
|
|
459
|
-
align: "center",
|
|
460
|
-
bold: true
|
|
461
|
-
},
|
|
462
|
-
facet: {
|
|
463
|
-
strip: {
|
|
464
|
-
text: "#c8c8c8",
|
|
465
|
-
background: ""
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
function themeMinimal() {
|
|
471
|
-
return {
|
|
472
|
-
panel: {
|
|
473
|
-
background: "",
|
|
474
|
-
border: "none",
|
|
475
|
-
grid: { major: null, minor: null }
|
|
476
|
-
},
|
|
477
|
-
axis: {
|
|
478
|
-
text: { color: "" },
|
|
479
|
-
ticks: { char: "│", length: 1 },
|
|
480
|
-
title: { color: "", bold: false }
|
|
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() {
|
|
90
|
+
function themeDark() {
|
|
499
91
|
return {
|
|
500
92
|
panel: {
|
|
501
93
|
background: "#1e1e1e",
|
|
@@ -592,229 +184,658 @@ function coordCartesian(options = {}) {
|
|
|
592
184
|
}
|
|
593
185
|
};
|
|
594
186
|
}
|
|
595
|
-
function coordFlip() {
|
|
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];
|
|
445
|
+
}
|
|
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++;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
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];
|
|
468
|
+
}
|
|
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;
|
|
485
|
+
}
|
|
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;
|
|
495
|
+
}
|
|
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];
|
|
500
|
+
}
|
|
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;
|
|
515
|
+
}
|
|
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];
|
|
529
|
+
}
|
|
530
|
+
function getTransformFunctions(trans = "identity") {
|
|
531
|
+
switch (trans) {
|
|
532
|
+
case "log10":
|
|
533
|
+
return {
|
|
534
|
+
type: "log10",
|
|
535
|
+
transform: (v) => v > 0 ? Math.log10(v) : -Infinity,
|
|
536
|
+
invert: (v) => Math.pow(10, v)
|
|
537
|
+
};
|
|
538
|
+
case "sqrt":
|
|
539
|
+
return {
|
|
540
|
+
type: "sqrt",
|
|
541
|
+
transform: (v) => v >= 0 ? Math.sqrt(v) : 0,
|
|
542
|
+
invert: (v) => v * v
|
|
543
|
+
};
|
|
544
|
+
case "reverse":
|
|
545
|
+
return {
|
|
546
|
+
type: "reverse",
|
|
547
|
+
transform: (v) => -v,
|
|
548
|
+
invert: (v) => -v
|
|
549
|
+
};
|
|
550
|
+
default:
|
|
551
|
+
return {
|
|
552
|
+
type: "identity",
|
|
553
|
+
transform: (v) => v,
|
|
554
|
+
invert: (v) => v
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
}
|
|
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);
|
|
563
|
+
return {
|
|
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;
|
|
596
593
|
return {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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));
|
|
600
610
|
}
|
|
601
611
|
};
|
|
602
612
|
}
|
|
603
|
-
function
|
|
604
|
-
const theta = options.theta ?? "x";
|
|
613
|
+
function interpolateColor(color1, color2, t) {
|
|
605
614
|
return {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
return {
|
|
611
|
-
x: radius * Math.cos(angle),
|
|
612
|
-
y: radius * Math.sin(angle)
|
|
613
|
-
};
|
|
614
|
-
}
|
|
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
|
|
615
619
|
};
|
|
616
620
|
}
|
|
617
|
-
function
|
|
618
|
-
const ratio = options.ratio ?? 1;
|
|
621
|
+
function createResolvedDiscreteColorScale(domain, palette = CATEGORY_COLORS) {
|
|
619
622
|
return {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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];
|
|
627
632
|
}
|
|
628
633
|
};
|
|
629
634
|
}
|
|
630
|
-
function
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
function getTransform(type) {
|
|
634
|
-
switch (type) {
|
|
635
|
-
case "log10":
|
|
636
|
-
return (v) => v > 0 ? Math.log10(v) : -Infinity;
|
|
637
|
-
case "sqrt":
|
|
638
|
-
return (v) => v >= 0 ? Math.sqrt(v) : 0;
|
|
639
|
-
case "reverse":
|
|
640
|
-
return (v) => -v;
|
|
641
|
-
default:
|
|
642
|
-
return (v) => v;
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
function coordTrans(options = {}) {
|
|
646
|
-
const xTrans = getTransform(options.x ?? "identity");
|
|
647
|
-
const yTrans = getTransform(options.y ?? "identity");
|
|
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;
|
|
648
638
|
return {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
y: yTrans(y)
|
|
659
|
-
};
|
|
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);
|
|
660
648
|
}
|
|
661
649
|
};
|
|
662
650
|
}
|
|
663
|
-
function
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
return { x: y, y: x };
|
|
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" && isNaN(Number(value))) {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
671
658
|
}
|
|
672
|
-
}
|
|
659
|
+
}
|
|
660
|
+
return false;
|
|
673
661
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
var DEFAULT_BG = { r: 0, g: 0, b: 0, a: 0 };
|
|
678
|
-
function createEmptyCell() {
|
|
662
|
+
function createResolvedSizeScale(domain) {
|
|
663
|
+
const [min, max] = domain;
|
|
664
|
+
const span = max - min;
|
|
679
665
|
return {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
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);
|
|
675
|
+
}
|
|
683
676
|
};
|
|
684
677
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
this.clear();
|
|
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)];
|
|
695
687
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
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;
|
|
712
|
+
}
|
|
699
713
|
}
|
|
700
|
-
const
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
return createEmptyCell();
|
|
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;
|
|
718
|
+
}
|
|
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;
|
|
725
|
+
}
|
|
726
|
+
if (userXScale?.labels) {
|
|
727
|
+
x.labels = userXScale.labels;
|
|
715
728
|
}
|
|
716
|
-
return this.cells[Math.floor(y)][Math.floor(x)];
|
|
717
729
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
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;
|
|
724
748
|
}
|
|
725
|
-
this.cells.push(row);
|
|
726
749
|
}
|
|
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);
|
|
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;
|
|
734
754
|
}
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
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;
|
|
739
761
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
for (let i = 0;i < length; i++) {
|
|
743
|
-
this.drawChar(x, y + i, char, fg);
|
|
762
|
+
if (userYScale?.labels) {
|
|
763
|
+
y.labels = userYScale.labels;
|
|
744
764
|
}
|
|
745
765
|
}
|
|
746
|
-
|
|
747
|
-
|
|
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;
|
|
748
779
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
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;
|
|
753
797
|
}
|
|
754
798
|
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
this.drawVLine(x + width - 1, y + 1, height - 2, chars.v, fg);
|
|
766
|
-
}
|
|
767
|
-
toString() {
|
|
768
|
-
return this.cells.map((row) => row.map((cell) => cell.char).join("")).join(`
|
|
769
|
-
`);
|
|
770
|
-
}
|
|
771
|
-
toAnsiString() {
|
|
772
|
-
const lines = [];
|
|
773
|
-
for (const row of this.cells) {
|
|
774
|
-
let line = "";
|
|
775
|
-
let currentFg = null;
|
|
776
|
-
let currentBg = null;
|
|
777
|
-
for (const cell of row) {
|
|
778
|
-
const fgChanged = !currentFg || currentFg.r !== cell.fg.r || currentFg.g !== cell.fg.g || currentFg.b !== cell.fg.b;
|
|
779
|
-
const bgChanged = cell.bg.a > 0 && (!currentBg || currentBg.r !== cell.bg.r || currentBg.g !== cell.bg.g || currentBg.b !== cell.bg.b);
|
|
780
|
-
if (fgChanged) {
|
|
781
|
-
line += `\x1B[38;2;${cell.fg.r};${cell.fg.g};${cell.fg.b}m`;
|
|
782
|
-
currentFg = cell.fg;
|
|
783
|
-
}
|
|
784
|
-
if (bgChanged) {
|
|
785
|
-
line += `\x1B[48;2;${cell.bg.r};${cell.bg.g};${cell.bg.b}m`;
|
|
786
|
-
currentBg = cell.bg;
|
|
787
|
-
}
|
|
788
|
-
if (cell.bold)
|
|
789
|
-
line += "\x1B[1m";
|
|
790
|
-
if (cell.italic)
|
|
791
|
-
line += "\x1B[3m";
|
|
792
|
-
if (cell.underline)
|
|
793
|
-
line += "\x1B[4m";
|
|
794
|
-
line += cell.char;
|
|
795
|
-
if (cell.bold || cell.italic || cell.underline) {
|
|
796
|
-
line += "\x1B[22;23;24m";
|
|
797
|
-
if (currentFg) {
|
|
798
|
-
line += `\x1B[38;2;${currentFg.r};${currentFg.g};${currentFg.b}m`;
|
|
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;
|
|
@@ -1769,20 +1774,52 @@ function renderGeomTile(data, geom, aes, scales, canvas) {
|
|
|
1769
1774
|
const plotRight = Math.round(scales.x.range[1]);
|
|
1770
1775
|
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
1771
1776
|
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
1772
|
-
let
|
|
1773
|
-
let
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1777
|
+
let halfW;
|
|
1778
|
+
let halfH;
|
|
1779
|
+
const xIsDiscrete = scales.x.type === "discrete";
|
|
1780
|
+
const yIsDiscrete = scales.y.type === "discrete";
|
|
1781
|
+
if (xIsDiscrete) {
|
|
1782
|
+
const xDomain = scales.x.domain;
|
|
1783
|
+
const canvasWidth = Math.abs(scales.x.range[1] - scales.x.range[0]);
|
|
1784
|
+
halfW = Math.max(1, Math.floor(canvasWidth / (xDomain.length * 2)));
|
|
1785
|
+
} else {
|
|
1786
|
+
let tileWidth = data[0]?.width ?? geom.params.width;
|
|
1787
|
+
if (!tileWidth) {
|
|
1788
|
+
const xVals = [...new Set(data.map((r) => Number(r[aes.x])).filter((v) => !isNaN(v)))].sort((a, b) => a - b);
|
|
1789
|
+
if (xVals.length > 1) {
|
|
1790
|
+
tileWidth = xVals[1] - xVals[0];
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
tileWidth = tileWidth ?? 1;
|
|
1794
|
+
const sampleX = data.find((r) => r[aes.x] !== null && r[aes.x] !== undefined)?.[aes.x];
|
|
1795
|
+
if (sampleX !== undefined) {
|
|
1796
|
+
const cx = scales.x.map(sampleX);
|
|
1797
|
+
halfW = Math.max(1, Math.floor(Math.abs(scales.x.map(Number(sampleX) + tileWidth / 2) - cx)));
|
|
1798
|
+
} else {
|
|
1799
|
+
halfW = 1;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
if (yIsDiscrete) {
|
|
1803
|
+
const yDomain = scales.y.domain;
|
|
1804
|
+
const canvasHeight = Math.abs(scales.y.range[1] - scales.y.range[0]);
|
|
1805
|
+
halfH = Math.max(1, Math.floor(canvasHeight / (yDomain.length * 2)));
|
|
1806
|
+
} else {
|
|
1807
|
+
let tileHeight = data[0]?.height ?? geom.params.height;
|
|
1808
|
+
if (!tileHeight) {
|
|
1809
|
+
const yVals = [...new Set(data.map((r) => Number(r[aes.y])).filter((v) => !isNaN(v)))].sort((a, b) => a - b);
|
|
1810
|
+
if (yVals.length > 1) {
|
|
1811
|
+
tileHeight = yVals[1] - yVals[0];
|
|
1812
|
+
}
|
|
1779
1813
|
}
|
|
1780
|
-
|
|
1781
|
-
|
|
1814
|
+
tileHeight = tileHeight ?? 1;
|
|
1815
|
+
const sampleY = data.find((r) => r[aes.y] !== null && r[aes.y] !== undefined)?.[aes.y];
|
|
1816
|
+
if (sampleY !== undefined) {
|
|
1817
|
+
const cy = scales.y.map(sampleY);
|
|
1818
|
+
halfH = Math.max(1, Math.floor(Math.abs(scales.y.map(Number(sampleY) + tileHeight / 2) - cy)));
|
|
1819
|
+
} else {
|
|
1820
|
+
halfH = 1;
|
|
1782
1821
|
}
|
|
1783
1822
|
}
|
|
1784
|
-
tileWidth = tileWidth ?? 1;
|
|
1785
|
-
tileHeight = tileHeight ?? 1;
|
|
1786
1823
|
for (const row of data) {
|
|
1787
1824
|
const xVal = row[aes.x];
|
|
1788
1825
|
const yVal = row[aes.y];
|
|
@@ -1792,8 +1829,6 @@ function renderGeomTile(data, geom, aes, scales, canvas) {
|
|
|
1792
1829
|
}
|
|
1793
1830
|
const cx = Math.round(scales.x.map(xVal));
|
|
1794
1831
|
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
1832
|
let color;
|
|
1798
1833
|
if (scales.color && typeof fillVal === "number") {
|
|
1799
1834
|
color = scales.color.map(fillVal);
|
|
@@ -2173,6 +2208,7 @@ function renderGeom(data, geom, aes, scales, canvas, coordType) {
|
|
|
2173
2208
|
break;
|
|
2174
2209
|
case "tile":
|
|
2175
2210
|
case "raster":
|
|
2211
|
+
case "bin2d":
|
|
2176
2212
|
renderGeomTile(data, geom, aes, scales, canvas);
|
|
2177
2213
|
break;
|
|
2178
2214
|
case "contour":
|
|
@@ -2202,6 +2238,26 @@ function renderGeom(data, geom, aes, scales, canvas, coordType) {
|
|
|
2202
2238
|
break;
|
|
2203
2239
|
}
|
|
2204
2240
|
}
|
|
2241
|
+
var POINT_SHAPES, SIZE_CHARS;
|
|
2242
|
+
var init_render_geoms = __esm(() => {
|
|
2243
|
+
init_scales();
|
|
2244
|
+
POINT_SHAPES = {
|
|
2245
|
+
circle: "●",
|
|
2246
|
+
filled_circle: "●",
|
|
2247
|
+
open_circle: "○",
|
|
2248
|
+
square: "■",
|
|
2249
|
+
open_square: "□",
|
|
2250
|
+
diamond: "◆",
|
|
2251
|
+
open_diamond: "◇",
|
|
2252
|
+
triangle: "▲",
|
|
2253
|
+
open_triangle: "△",
|
|
2254
|
+
cross: "✕",
|
|
2255
|
+
plus: "+",
|
|
2256
|
+
star: "★",
|
|
2257
|
+
dot: "•"
|
|
2258
|
+
};
|
|
2259
|
+
SIZE_CHARS = ["·", "•", "●", "⬤"];
|
|
2260
|
+
});
|
|
2205
2261
|
|
|
2206
2262
|
// src/pipeline/render-axes.ts
|
|
2207
2263
|
function calculateTicks(domain, targetTicks = 5, transform, invert) {
|
|
@@ -2509,7 +2565,6 @@ function renderTitle(canvas, title, width, theme) {
|
|
|
2509
2565
|
}
|
|
2510
2566
|
canvas.drawString(x, 0, title, titleColor);
|
|
2511
2567
|
}
|
|
2512
|
-
var SIZE_SYMBOLS = ["·", "•", "●", "⬤"];
|
|
2513
2568
|
function renderMultiLegend(canvas, entries, x, y, theme, width) {
|
|
2514
2569
|
if (theme.legend.position === "none" || entries.length === 0)
|
|
2515
2570
|
return;
|
|
@@ -2637,6 +2692,10 @@ function formatContinuousLegendValue(value) {
|
|
|
2637
2692
|
}
|
|
2638
2693
|
return value.toFixed(1);
|
|
2639
2694
|
}
|
|
2695
|
+
var SIZE_SYMBOLS;
|
|
2696
|
+
var init_render_axes = __esm(() => {
|
|
2697
|
+
SIZE_SYMBOLS = ["·", "•", "●", "⬤"];
|
|
2698
|
+
});
|
|
2640
2699
|
|
|
2641
2700
|
// src/stats/bin.ts
|
|
2642
2701
|
function computeBins(data, field, params = {}) {
|
|
@@ -2748,6 +2807,248 @@ function stat_bin(params = {}) {
|
|
|
2748
2807
|
};
|
|
2749
2808
|
}
|
|
2750
2809
|
|
|
2810
|
+
// src/performance/binning.ts
|
|
2811
|
+
function computeDomain2(data, field) {
|
|
2812
|
+
let min = Infinity;
|
|
2813
|
+
let max = -Infinity;
|
|
2814
|
+
for (const d of data) {
|
|
2815
|
+
const v = d[field];
|
|
2816
|
+
if (typeof v === "number" && !isNaN(v)) {
|
|
2817
|
+
if (v < min)
|
|
2818
|
+
min = v;
|
|
2819
|
+
if (v > max)
|
|
2820
|
+
max = v;
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
if (min === Infinity)
|
|
2824
|
+
return [0, 1];
|
|
2825
|
+
if (min === max)
|
|
2826
|
+
return [min - 0.5, max + 0.5];
|
|
2827
|
+
return [min, max];
|
|
2828
|
+
}
|
|
2829
|
+
function aggregateValues(values, method) {
|
|
2830
|
+
if (values.length === 0)
|
|
2831
|
+
return 0;
|
|
2832
|
+
switch (method) {
|
|
2833
|
+
case "count":
|
|
2834
|
+
return values.length;
|
|
2835
|
+
case "sum":
|
|
2836
|
+
return values.reduce((a, b) => a + b, 0);
|
|
2837
|
+
case "mean":
|
|
2838
|
+
return values.reduce((a, b) => a + b, 0) / values.length;
|
|
2839
|
+
case "median":
|
|
2840
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
2841
|
+
const mid = Math.floor(sorted.length / 2);
|
|
2842
|
+
return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
2843
|
+
case "min":
|
|
2844
|
+
return Math.min(...values);
|
|
2845
|
+
case "max":
|
|
2846
|
+
return Math.max(...values);
|
|
2847
|
+
default:
|
|
2848
|
+
return values.length;
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
function rectbin(data, options) {
|
|
2852
|
+
const {
|
|
2853
|
+
xField,
|
|
2854
|
+
yField,
|
|
2855
|
+
xBins = 20,
|
|
2856
|
+
yBins = 20,
|
|
2857
|
+
aggregate = "count",
|
|
2858
|
+
valueField
|
|
2859
|
+
} = options;
|
|
2860
|
+
if (data.length === 0)
|
|
2861
|
+
return [];
|
|
2862
|
+
const xDomain = options.xDomain ?? computeDomain2(data, xField);
|
|
2863
|
+
const yDomain = options.yDomain ?? computeDomain2(data, yField);
|
|
2864
|
+
const xRange = xDomain[1] - xDomain[0];
|
|
2865
|
+
const yRange = yDomain[1] - yDomain[0];
|
|
2866
|
+
const binWidth = xRange / xBins;
|
|
2867
|
+
const binHeight = yRange / yBins;
|
|
2868
|
+
const bins = new Map;
|
|
2869
|
+
for (const point of data) {
|
|
2870
|
+
const x = point[xField];
|
|
2871
|
+
const y = point[yField];
|
|
2872
|
+
if (typeof x !== "number" || typeof y !== "number")
|
|
2873
|
+
continue;
|
|
2874
|
+
const bx = Math.min(xBins - 1, Math.max(0, Math.floor((x - xDomain[0]) / binWidth)));
|
|
2875
|
+
const by = Math.min(yBins - 1, Math.max(0, Math.floor((y - yDomain[0]) / binHeight)));
|
|
2876
|
+
const key = `${bx},${by}`;
|
|
2877
|
+
if (!bins.has(key)) {
|
|
2878
|
+
bins.set(key, { points: [], values: [] });
|
|
2879
|
+
}
|
|
2880
|
+
const bin = bins.get(key);
|
|
2881
|
+
bin.points.push(point);
|
|
2882
|
+
if (valueField && typeof point[valueField] === "number") {
|
|
2883
|
+
bin.values.push(point[valueField]);
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
const result = [];
|
|
2887
|
+
for (const [key, bin] of bins) {
|
|
2888
|
+
const [bx, by] = key.split(",").map(Number);
|
|
2889
|
+
const centerX = xDomain[0] + (bx + 0.5) * binWidth;
|
|
2890
|
+
const centerY = yDomain[0] + (by + 0.5) * binHeight;
|
|
2891
|
+
result.push({
|
|
2892
|
+
x: centerX,
|
|
2893
|
+
y: centerY,
|
|
2894
|
+
count: bin.points.length,
|
|
2895
|
+
value: aggregateValues(bin.values.length > 0 ? bin.values : [bin.points.length], aggregate),
|
|
2896
|
+
width: binWidth,
|
|
2897
|
+
height: binHeight,
|
|
2898
|
+
points: bin.points
|
|
2899
|
+
});
|
|
2900
|
+
}
|
|
2901
|
+
return result;
|
|
2902
|
+
}
|
|
2903
|
+
function hexbin(data, options) {
|
|
2904
|
+
const { xField, yField, aggregate = "count", valueField, radius = 10 } = options;
|
|
2905
|
+
if (data.length === 0)
|
|
2906
|
+
return [];
|
|
2907
|
+
const xDomain = options.xDomain ?? computeDomain2(data, xField);
|
|
2908
|
+
const yDomain = options.yDomain ?? computeDomain2(data, yField);
|
|
2909
|
+
const hexWidth = radius * 2;
|
|
2910
|
+
const hexHeight = radius * Math.sqrt(3);
|
|
2911
|
+
const bins = new Map;
|
|
2912
|
+
for (const point of data) {
|
|
2913
|
+
const x = point[xField];
|
|
2914
|
+
const y = point[yField];
|
|
2915
|
+
if (typeof x !== "number" || typeof y !== "number")
|
|
2916
|
+
continue;
|
|
2917
|
+
const col = Math.round((x - xDomain[0]) / (hexWidth * 0.75));
|
|
2918
|
+
const row = Math.round((y - yDomain[0]) / hexHeight - col % 2 * 0.5);
|
|
2919
|
+
const key = `${col},${row}`;
|
|
2920
|
+
if (!bins.has(key)) {
|
|
2921
|
+
bins.set(key, { points: [], values: [], col, row });
|
|
2922
|
+
}
|
|
2923
|
+
const bin = bins.get(key);
|
|
2924
|
+
bin.points.push(point);
|
|
2925
|
+
if (valueField && typeof point[valueField] === "number") {
|
|
2926
|
+
bin.values.push(point[valueField]);
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
function hexVertices(cx, cy, r) {
|
|
2930
|
+
const vertices = [];
|
|
2931
|
+
for (let i = 0;i < 6; i++) {
|
|
2932
|
+
const angle = Math.PI / 3 * i + Math.PI / 6;
|
|
2933
|
+
vertices.push({
|
|
2934
|
+
x: cx + r * Math.cos(angle),
|
|
2935
|
+
y: cy + r * Math.sin(angle)
|
|
2936
|
+
});
|
|
2937
|
+
}
|
|
2938
|
+
return vertices;
|
|
2939
|
+
}
|
|
2940
|
+
const result = [];
|
|
2941
|
+
for (const [, bin] of bins) {
|
|
2942
|
+
const centerX = xDomain[0] + bin.col * hexWidth * 0.75;
|
|
2943
|
+
const centerY = yDomain[0] + (bin.row + bin.col % 2 * 0.5) * hexHeight;
|
|
2944
|
+
result.push({
|
|
2945
|
+
x: centerX,
|
|
2946
|
+
y: centerY,
|
|
2947
|
+
count: bin.points.length,
|
|
2948
|
+
value: aggregateValues(bin.values.length > 0 ? bin.values : [bin.points.length], aggregate),
|
|
2949
|
+
width: hexWidth,
|
|
2950
|
+
height: hexHeight,
|
|
2951
|
+
points: bin.points,
|
|
2952
|
+
vertices: hexVertices(centerX, centerY, radius),
|
|
2953
|
+
col: bin.col,
|
|
2954
|
+
row: bin.row
|
|
2955
|
+
});
|
|
2956
|
+
}
|
|
2957
|
+
return result;
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2960
|
+
class Binner {
|
|
2961
|
+
options;
|
|
2962
|
+
type;
|
|
2963
|
+
hexRadius;
|
|
2964
|
+
constructor(options) {
|
|
2965
|
+
this.options = options;
|
|
2966
|
+
this.type = options.type ?? "rect";
|
|
2967
|
+
this.hexRadius = options.hexRadius ?? 10;
|
|
2968
|
+
}
|
|
2969
|
+
bin(data) {
|
|
2970
|
+
if (this.type === "hex") {
|
|
2971
|
+
return hexbin(data, { ...this.options, radius: this.hexRadius });
|
|
2972
|
+
}
|
|
2973
|
+
return rectbin(data, this.options);
|
|
2974
|
+
}
|
|
2975
|
+
toPlotData(data) {
|
|
2976
|
+
const bins = this.bin(data);
|
|
2977
|
+
const maxCount = Math.max(...bins.map((b) => b.count));
|
|
2978
|
+
const minSize = 1;
|
|
2979
|
+
const maxSize = 5;
|
|
2980
|
+
return bins.map((bin) => ({
|
|
2981
|
+
x: bin.x,
|
|
2982
|
+
y: bin.y,
|
|
2983
|
+
count: bin.count,
|
|
2984
|
+
value: bin.value,
|
|
2985
|
+
size: minSize + bin.count / maxCount * (maxSize - minSize)
|
|
2986
|
+
}));
|
|
2987
|
+
}
|
|
2988
|
+
getDensityColors(bins, colorScale) {
|
|
2989
|
+
const maxCount = Math.max(...bins.map((b) => b.count));
|
|
2990
|
+
const colors = new Map;
|
|
2991
|
+
for (const bin of bins) {
|
|
2992
|
+
const t = bin.count / maxCount;
|
|
2993
|
+
colors.set(bin, colorScale(t));
|
|
2994
|
+
}
|
|
2995
|
+
return colors;
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
function createBinner(options) {
|
|
2999
|
+
return new Binner(options);
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
// src/stats/bin2d.ts
|
|
3003
|
+
function computeBins2d(data, xField, yField, params = {}) {
|
|
3004
|
+
const {
|
|
3005
|
+
bins = 30,
|
|
3006
|
+
binsx,
|
|
3007
|
+
binsy,
|
|
3008
|
+
drop = true
|
|
3009
|
+
} = params;
|
|
3010
|
+
const xBins = binsx ?? bins;
|
|
3011
|
+
const yBins = binsy ?? bins;
|
|
3012
|
+
const binned = rectbin(data, {
|
|
3013
|
+
xField,
|
|
3014
|
+
yField,
|
|
3015
|
+
xBins,
|
|
3016
|
+
yBins,
|
|
3017
|
+
aggregate: "count"
|
|
3018
|
+
});
|
|
3019
|
+
const total = data.length;
|
|
3020
|
+
const results = binned.map((bin) => ({
|
|
3021
|
+
x: bin.x,
|
|
3022
|
+
y: bin.y,
|
|
3023
|
+
count: bin.count,
|
|
3024
|
+
density: total > 0 ? bin.count / total : 0,
|
|
3025
|
+
width: bin.width,
|
|
3026
|
+
height: bin.height
|
|
3027
|
+
}));
|
|
3028
|
+
if (drop) {
|
|
3029
|
+
return results.filter((r) => r.count > 0);
|
|
3030
|
+
}
|
|
3031
|
+
return results;
|
|
3032
|
+
}
|
|
3033
|
+
function stat_bin2d(params = {}) {
|
|
3034
|
+
return {
|
|
3035
|
+
type: "bin2d",
|
|
3036
|
+
compute(data, aes) {
|
|
3037
|
+
const bins = computeBins2d(data, aes.x, aes.y, params);
|
|
3038
|
+
return bins.map((bin) => ({
|
|
3039
|
+
x: bin.x,
|
|
3040
|
+
y: bin.y,
|
|
3041
|
+
count: bin.count,
|
|
3042
|
+
density: bin.density,
|
|
3043
|
+
fill: bin.count,
|
|
3044
|
+
width: bin.width,
|
|
3045
|
+
height: bin.height
|
|
3046
|
+
}));
|
|
3047
|
+
}
|
|
3048
|
+
};
|
|
3049
|
+
}
|
|
3050
|
+
var init_bin2d = () => {};
|
|
3051
|
+
|
|
2751
3052
|
// src/stats/boxplot.ts
|
|
2752
3053
|
function quantile(sorted, p) {
|
|
2753
3054
|
if (sorted.length === 0)
|
|
@@ -3163,17 +3464,6 @@ function stat_smooth(params = {}) {
|
|
|
3163
3464
|
}
|
|
3164
3465
|
|
|
3165
3466
|
// 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
3467
|
function sd(values) {
|
|
3178
3468
|
const n = values.length;
|
|
3179
3469
|
if (n < 2)
|
|
@@ -3305,6 +3595,20 @@ function stat_summary(params = {}) {
|
|
|
3305
3595
|
}
|
|
3306
3596
|
};
|
|
3307
3597
|
}
|
|
3598
|
+
var summaryFunctions;
|
|
3599
|
+
var init_summary = __esm(() => {
|
|
3600
|
+
summaryFunctions = {
|
|
3601
|
+
mean: (values) => values.reduce((a, b) => a + b, 0) / values.length,
|
|
3602
|
+
median: (values) => {
|
|
3603
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
3604
|
+
const mid = Math.floor(sorted.length / 2);
|
|
3605
|
+
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
3606
|
+
},
|
|
3607
|
+
min: (values) => Math.min(...values),
|
|
3608
|
+
max: (values) => Math.max(...values),
|
|
3609
|
+
sum: (values) => values.reduce((a, b) => a + b, 0)
|
|
3610
|
+
};
|
|
3611
|
+
});
|
|
3308
3612
|
|
|
3309
3613
|
// src/stats/qq.ts
|
|
3310
3614
|
function qnorm(p, mean = 0, sd2 = 1) {
|
|
@@ -3488,14 +3792,6 @@ function stat_qq_line(params = {}) {
|
|
|
3488
3792
|
}
|
|
3489
3793
|
|
|
3490
3794
|
// 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
3795
|
function as_labeller(labels) {
|
|
3500
3796
|
return (value) => labels[value] ?? value;
|
|
3501
3797
|
}
|
|
@@ -3688,6 +3984,11 @@ function calculateGridStripLayout(totalWidth, totalHeight, nrow, ncol, hasTitle,
|
|
|
3688
3984
|
rowStripWidth: rowStripWidth - 1
|
|
3689
3985
|
};
|
|
3690
3986
|
}
|
|
3987
|
+
var label_value = (value) => value, label_both = (value, variable) => variable ? `${variable}: ${value}` : value, label_parsed = (value) => value.replace(/_/g, " "), label_wrap = (width) => (value) => {
|
|
3988
|
+
if (value.length <= width)
|
|
3989
|
+
return value;
|
|
3990
|
+
return value.substring(0, width - 1) + "…";
|
|
3991
|
+
};
|
|
3691
3992
|
|
|
3692
3993
|
// src/pipeline/pipeline.ts
|
|
3693
3994
|
function calculateLayout(spec, options) {
|
|
@@ -3800,6 +4101,14 @@ function applyStatTransform(data, geom, aes) {
|
|
|
3800
4101
|
dparams: geom.params.dparams
|
|
3801
4102
|
});
|
|
3802
4103
|
return qqLineStat.compute(data, aes);
|
|
4104
|
+
} else if (geom.stat === "bin2d") {
|
|
4105
|
+
const bin2dStat = stat_bin2d({
|
|
4106
|
+
bins: geom.params.bins,
|
|
4107
|
+
binsx: geom.params.binsx,
|
|
4108
|
+
binsy: geom.params.binsy,
|
|
4109
|
+
drop: geom.params.drop
|
|
4110
|
+
});
|
|
4111
|
+
return bin2dStat.compute(data, aes);
|
|
3803
4112
|
}
|
|
3804
4113
|
return data;
|
|
3805
4114
|
}
|
|
@@ -3864,6 +4173,10 @@ function renderToCanvas(spec, options) {
|
|
|
3864
4173
|
scaleAes = { ...spec.aes, x: "x", y: "y" };
|
|
3865
4174
|
}
|
|
3866
4175
|
break;
|
|
4176
|
+
} else if (geom.stat === "bin2d") {
|
|
4177
|
+
scaleData = applyStatTransform(spec.data, geom, spec.aes);
|
|
4178
|
+
scaleAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
|
|
4179
|
+
break;
|
|
3867
4180
|
}
|
|
3868
4181
|
}
|
|
3869
4182
|
scaleData = applyCoordTransform(scaleData, scaleAes, spec.coord);
|
|
@@ -3898,6 +4211,8 @@ function renderToCanvas(spec, options) {
|
|
|
3898
4211
|
geomAes = { ...spec.aes, x: "x", y: "y" };
|
|
3899
4212
|
} else if (geom.stat === "qq_line") {
|
|
3900
4213
|
geomAes = { ...spec.aes, x: "x", y: "y", xend: "xend", yend: "yend" };
|
|
4214
|
+
} else if (geom.stat === "bin2d") {
|
|
4215
|
+
geomAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
|
|
3901
4216
|
}
|
|
3902
4217
|
geomData = applyCoordTransform(geomData, geomAes, spec.coord);
|
|
3903
4218
|
}
|
|
@@ -4148,8 +4463,14 @@ function renderPanel(canvas, panel, layout, spec, facet, sharedScales, nrow = 1,
|
|
|
4148
4463
|
renderPanelAxes(canvas, scales, plotArea, panel.row, panel.col, nrow, ncol, spec.theme);
|
|
4149
4464
|
for (const geom of spec.geoms) {
|
|
4150
4465
|
let geomData = applyStatTransform(panel.data, geom, spec.aes);
|
|
4151
|
-
|
|
4152
|
-
|
|
4466
|
+
let geomAes = spec.aes;
|
|
4467
|
+
if (geom.stat === "bin" || geom.stat === "boxplot" || geom.stat === "count" || geom.stat === "qq") {
|
|
4468
|
+
geomAes = { ...spec.aes, x: "x", y: "y" };
|
|
4469
|
+
} else if (geom.stat === "bin2d") {
|
|
4470
|
+
geomAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
|
|
4471
|
+
}
|
|
4472
|
+
geomData = applyCoordTransform(geomData, geomAes, spec.coord);
|
|
4473
|
+
renderGeom(geomData, geom, geomAes, scales, canvas, spec.coord.type);
|
|
4153
4474
|
}
|
|
4154
4475
|
}
|
|
4155
4476
|
function renderPanelAxes(canvas, scales, plotArea, row, col, nrow, _ncol, _theme) {
|
|
@@ -4197,9 +4518,22 @@ function renderToString(spec, options) {
|
|
|
4197
4518
|
}
|
|
4198
4519
|
return canvas.toAnsiString();
|
|
4199
4520
|
}
|
|
4521
|
+
var init_pipeline = __esm(() => {
|
|
4522
|
+
init_canvas();
|
|
4523
|
+
init_scales();
|
|
4524
|
+
init_render_geoms();
|
|
4525
|
+
init_render_axes();
|
|
4526
|
+
init_bin2d();
|
|
4527
|
+
init_summary();
|
|
4528
|
+
});
|
|
4200
4529
|
|
|
4201
4530
|
// src/pipeline/index.ts
|
|
4202
|
-
|
|
4531
|
+
var init_pipeline2 = __esm(() => {
|
|
4532
|
+
init_pipeline();
|
|
4533
|
+
init_scales();
|
|
4534
|
+
init_render_geoms();
|
|
4535
|
+
init_render_axes();
|
|
4536
|
+
});
|
|
4203
4537
|
|
|
4204
4538
|
// src/grammar.ts
|
|
4205
4539
|
class GGPlot {
|
|
@@ -4290,6 +4624,9 @@ class GGPlot {
|
|
|
4290
4624
|
function gg(data = []) {
|
|
4291
4625
|
return new GGPlot(data);
|
|
4292
4626
|
}
|
|
4627
|
+
var init_grammar = __esm(() => {
|
|
4628
|
+
init_pipeline2();
|
|
4629
|
+
});
|
|
4293
4630
|
|
|
4294
4631
|
// src/geoms/point.ts
|
|
4295
4632
|
function geom_point(options = {}) {
|
|
@@ -4305,6 +4642,7 @@ function geom_point(options = {}) {
|
|
|
4305
4642
|
}
|
|
4306
4643
|
};
|
|
4307
4644
|
}
|
|
4645
|
+
|
|
4308
4646
|
// src/geoms/line.ts
|
|
4309
4647
|
function geom_line(options = {}) {
|
|
4310
4648
|
return {
|
|
@@ -4343,6 +4681,7 @@ function geom_vline(options) {
|
|
|
4343
4681
|
}
|
|
4344
4682
|
};
|
|
4345
4683
|
}
|
|
4684
|
+
|
|
4346
4685
|
// src/geoms/path.ts
|
|
4347
4686
|
function geom_path(options = {}) {
|
|
4348
4687
|
return {
|
|
@@ -4359,6 +4698,7 @@ function geom_path(options = {}) {
|
|
|
4359
4698
|
}
|
|
4360
4699
|
};
|
|
4361
4700
|
}
|
|
4701
|
+
|
|
4362
4702
|
// src/geoms/bar.ts
|
|
4363
4703
|
function geom_bar(options = {}) {
|
|
4364
4704
|
return {
|
|
@@ -4376,6 +4716,7 @@ function geom_bar(options = {}) {
|
|
|
4376
4716
|
function geom_col(options = {}) {
|
|
4377
4717
|
return geom_bar({ ...options, stat: "identity" });
|
|
4378
4718
|
}
|
|
4719
|
+
|
|
4379
4720
|
// src/geoms/text.ts
|
|
4380
4721
|
function geom_text(options = {}) {
|
|
4381
4722
|
return {
|
|
@@ -4408,6 +4749,7 @@ function geom_label(options = {}) {
|
|
|
4408
4749
|
}
|
|
4409
4750
|
};
|
|
4410
4751
|
}
|
|
4752
|
+
|
|
4411
4753
|
// src/geoms/area.ts
|
|
4412
4754
|
function geom_area(options = {}) {
|
|
4413
4755
|
return {
|
|
@@ -4433,6 +4775,7 @@ function geom_ribbon(options = {}) {
|
|
|
4433
4775
|
}
|
|
4434
4776
|
};
|
|
4435
4777
|
}
|
|
4778
|
+
|
|
4436
4779
|
// src/geoms/histogram.ts
|
|
4437
4780
|
function geom_histogram(options = {}) {
|
|
4438
4781
|
return {
|
|
@@ -4464,6 +4807,7 @@ function geom_freqpoly(options = {}) {
|
|
|
4464
4807
|
}
|
|
4465
4808
|
};
|
|
4466
4809
|
}
|
|
4810
|
+
|
|
4467
4811
|
// src/geoms/boxplot.ts
|
|
4468
4812
|
function geom_boxplot(options = {}) {
|
|
4469
4813
|
return {
|
|
@@ -4480,6 +4824,7 @@ function geom_boxplot(options = {}) {
|
|
|
4480
4824
|
}
|
|
4481
4825
|
};
|
|
4482
4826
|
}
|
|
4827
|
+
|
|
4483
4828
|
// src/geoms/segment.ts
|
|
4484
4829
|
function geom_segment(options = {}) {
|
|
4485
4830
|
return {
|
|
@@ -4512,6 +4857,7 @@ function geom_curve(options = {}) {
|
|
|
4512
4857
|
}
|
|
4513
4858
|
};
|
|
4514
4859
|
}
|
|
4860
|
+
|
|
4515
4861
|
// src/geoms/smooth.ts
|
|
4516
4862
|
function geom_smooth(options = {}) {
|
|
4517
4863
|
return {
|
|
@@ -4531,6 +4877,7 @@ function geom_smooth(options = {}) {
|
|
|
4531
4877
|
}
|
|
4532
4878
|
};
|
|
4533
4879
|
}
|
|
4880
|
+
|
|
4534
4881
|
// src/geoms/step.ts
|
|
4535
4882
|
function geom_step(options = {}) {
|
|
4536
4883
|
return {
|
|
@@ -4546,6 +4893,7 @@ function geom_step(options = {}) {
|
|
|
4546
4893
|
}
|
|
4547
4894
|
};
|
|
4548
4895
|
}
|
|
4896
|
+
|
|
4549
4897
|
// src/geoms/rug.ts
|
|
4550
4898
|
function geom_rug(options = {}) {
|
|
4551
4899
|
return {
|
|
@@ -4561,6 +4909,7 @@ function geom_rug(options = {}) {
|
|
|
4561
4909
|
}
|
|
4562
4910
|
};
|
|
4563
4911
|
}
|
|
4912
|
+
|
|
4564
4913
|
// src/geoms/violin.ts
|
|
4565
4914
|
function geom_violin(options = {}) {
|
|
4566
4915
|
return {
|
|
@@ -4578,6 +4927,7 @@ function geom_violin(options = {}) {
|
|
|
4578
4927
|
}
|
|
4579
4928
|
};
|
|
4580
4929
|
}
|
|
4930
|
+
|
|
4581
4931
|
// src/geoms/tile.ts
|
|
4582
4932
|
function geom_tile(options = {}) {
|
|
4583
4933
|
return {
|
|
@@ -4596,6 +4946,22 @@ function geom_tile(options = {}) {
|
|
|
4596
4946
|
function geom_raster(options = {}) {
|
|
4597
4947
|
return geom_tile(options);
|
|
4598
4948
|
}
|
|
4949
|
+
|
|
4950
|
+
// src/geoms/bin2d.ts
|
|
4951
|
+
function geom_bin2d(options = {}) {
|
|
4952
|
+
return {
|
|
4953
|
+
type: "bin2d",
|
|
4954
|
+
stat: "bin2d",
|
|
4955
|
+
params: {
|
|
4956
|
+
bins: options.bins ?? 30,
|
|
4957
|
+
binsx: options.binsx,
|
|
4958
|
+
binsy: options.binsy,
|
|
4959
|
+
alpha: options.alpha ?? 1,
|
|
4960
|
+
drop: options.drop ?? true
|
|
4961
|
+
}
|
|
4962
|
+
};
|
|
4963
|
+
}
|
|
4964
|
+
|
|
4599
4965
|
// src/geoms/contour.ts
|
|
4600
4966
|
function geom_contour(options = {}) {
|
|
4601
4967
|
return {
|
|
@@ -4638,6 +5004,7 @@ function geom_density_2d(options = {}) {
|
|
|
4638
5004
|
}
|
|
4639
5005
|
};
|
|
4640
5006
|
}
|
|
5007
|
+
|
|
4641
5008
|
// src/geoms/errorbar.ts
|
|
4642
5009
|
function geom_errorbar(options = {}) {
|
|
4643
5010
|
return {
|
|
@@ -4704,6 +5071,7 @@ function geom_pointrange(options = {}) {
|
|
|
4704
5071
|
}
|
|
4705
5072
|
};
|
|
4706
5073
|
}
|
|
5074
|
+
|
|
4707
5075
|
// src/geoms/rect.ts
|
|
4708
5076
|
function geom_rect(options = {}) {
|
|
4709
5077
|
return {
|
|
@@ -4732,6 +5100,7 @@ function geom_abline(options = {}) {
|
|
|
4732
5100
|
}
|
|
4733
5101
|
};
|
|
4734
5102
|
}
|
|
5103
|
+
|
|
4735
5104
|
// src/geoms/qq.ts
|
|
4736
5105
|
function geom_qq(options = {}) {
|
|
4737
5106
|
return {
|
|
@@ -4760,6 +5129,10 @@ function geom_qq_line(options = {}) {
|
|
|
4760
5129
|
}
|
|
4761
5130
|
};
|
|
4762
5131
|
}
|
|
5132
|
+
|
|
5133
|
+
// src/geoms/index.ts
|
|
5134
|
+
var init_geoms = () => {};
|
|
5135
|
+
|
|
4763
5136
|
// src/scales/continuous.ts
|
|
4764
5137
|
function createContinuousScale(aesthetic, options = {}) {
|
|
4765
5138
|
const trans = options.trans ?? "identity";
|
|
@@ -4838,6 +5211,7 @@ function scale_y2_sqrt(options = {}) {
|
|
|
4838
5211
|
function scale_y2_reverse(options = {}) {
|
|
4839
5212
|
return createContinuousScale("y2", { ...options, trans: "reverse" });
|
|
4840
5213
|
}
|
|
5214
|
+
|
|
4841
5215
|
// src/scales/discrete.ts
|
|
4842
5216
|
function createDiscreteScale(aesthetic, options = {}) {
|
|
4843
5217
|
const valueToPosition = new Map;
|
|
@@ -4887,123 +5261,8 @@ function scale_x_discrete(options = {}) {
|
|
|
4887
5261
|
function scale_y_discrete(options = {}) {
|
|
4888
5262
|
return createDiscreteScale("y", options);
|
|
4889
5263
|
}
|
|
5264
|
+
|
|
4890
5265
|
// 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
5266
|
function hexToRgba(hex) {
|
|
5008
5267
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
5009
5268
|
if (!result)
|
|
@@ -5224,6 +5483,126 @@ function getAvailablePalettes() {
|
|
|
5224
5483
|
function getPaletteColors(name) {
|
|
5225
5484
|
return PALETTES[name];
|
|
5226
5485
|
}
|
|
5486
|
+
var PALETTES;
|
|
5487
|
+
var init_color = __esm(() => {
|
|
5488
|
+
PALETTES = {
|
|
5489
|
+
viridis: ["#440154", "#414487", "#2a788e", "#22a884", "#7ad151", "#fde725"],
|
|
5490
|
+
plasma: ["#0d0887", "#6a00a8", "#b12a90", "#e16462", "#fca636", "#f0f921"],
|
|
5491
|
+
inferno: ["#000004", "#420a68", "#932667", "#dd513a", "#fca50a", "#fcffa4"],
|
|
5492
|
+
magma: ["#000004", "#3b0f70", "#8c2981", "#de4968", "#fe9f6d", "#fcfdbf"],
|
|
5493
|
+
cividis: ["#002051", "#1d3f6e", "#52596a", "#7b7b78", "#a89f68", "#d9c84a", "#fdea45"],
|
|
5494
|
+
turbo: ["#30123b", "#4662d7", "#35aaf8", "#1ae4b6", "#72fe5e", "#c8ef34", "#faba39", "#f66b19", "#ca2a04"],
|
|
5495
|
+
Blues: ["#f7fbff", "#deebf7", "#c6dbef", "#9ecae1", "#6baed6", "#4292c6", "#2171b5", "#08519c", "#08306b"],
|
|
5496
|
+
Greens: ["#f7fcf5", "#e5f5e0", "#c7e9c0", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#006d2c", "#00441b"],
|
|
5497
|
+
Greys: ["#ffffff", "#f0f0f0", "#d9d9d9", "#bdbdbd", "#969696", "#737373", "#525252", "#252525", "#000000"],
|
|
5498
|
+
Oranges: ["#fff5eb", "#fee6ce", "#fdd0a2", "#fdae6b", "#fd8d3c", "#f16913", "#d94801", "#a63603", "#7f2704"],
|
|
5499
|
+
Purples: ["#fcfbfd", "#efedf5", "#dadaeb", "#bcbddc", "#9e9ac8", "#807dba", "#6a51a3", "#54278f", "#3f007d"],
|
|
5500
|
+
Reds: ["#fff5f0", "#fee0d2", "#fcbba1", "#fc9272", "#fb6a4a", "#ef3b2c", "#cb181d", "#a50f15", "#67000d"],
|
|
5501
|
+
BuGn: ["#f7fcfd", "#e5f5f9", "#ccece6", "#99d8c9", "#66c2a4", "#41ae76", "#238b45", "#006d2c", "#00441b"],
|
|
5502
|
+
BuPu: ["#f7fcfd", "#e0ecf4", "#bfd3e6", "#9ebcda", "#8c96c6", "#8c6bb1", "#88419d", "#810f7c", "#4d004b"],
|
|
5503
|
+
GnBu: ["#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5", "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081"],
|
|
5504
|
+
OrRd: ["#fff7ec", "#fee8c8", "#fdd49e", "#fdbb84", "#fc8d59", "#ef6548", "#d7301f", "#b30000", "#7f0000"],
|
|
5505
|
+
PuBu: ["#fff7fb", "#ece7f2", "#d0d1e6", "#a6bddb", "#74a9cf", "#3690c0", "#0570b0", "#045a8d", "#023858"],
|
|
5506
|
+
PuBuGn: ["#fff7fb", "#ece2f0", "#d0d1e6", "#a6bddb", "#67a9cf", "#3690c0", "#02818a", "#016c59", "#014636"],
|
|
5507
|
+
PuRd: ["#f7f4f9", "#e7e1ef", "#d4b9da", "#c994c7", "#df65b0", "#e7298a", "#ce1256", "#980043", "#67001f"],
|
|
5508
|
+
RdPu: ["#fff7f3", "#fde0dd", "#fcc5c0", "#fa9fb5", "#f768a1", "#dd3497", "#ae017e", "#7a0177", "#49006a"],
|
|
5509
|
+
YlGn: ["#ffffe5", "#f7fcb9", "#d9f0a3", "#addd8e", "#78c679", "#41ab5d", "#238b45", "#006837", "#004529"],
|
|
5510
|
+
YlGnBu: ["#ffffd9", "#edf8b1", "#c7e9b4", "#7fcdbb", "#41b6c4", "#1d91c0", "#225ea8", "#253494", "#081d58"],
|
|
5511
|
+
YlOrBr: ["#ffffe5", "#fff7bc", "#fee391", "#fec44f", "#fe9929", "#ec7014", "#cc4c02", "#993404", "#662506"],
|
|
5512
|
+
YlOrRd: ["#ffffcc", "#ffeda0", "#fed976", "#feb24c", "#fd8d3c", "#fc4e2a", "#e31a1c", "#bd0026", "#800026"],
|
|
5513
|
+
BrBG: ["#543005", "#8c510a", "#bf812d", "#dfc27d", "#f6e8c3", "#f5f5f5", "#c7eae5", "#80cdc1", "#35978f", "#01665e", "#003c30"],
|
|
5514
|
+
PiYG: ["#8e0152", "#c51b7d", "#de77ae", "#f1b6da", "#fde0ef", "#f7f7f7", "#e6f5d0", "#b8e186", "#7fbc41", "#4d9221", "#276419"],
|
|
5515
|
+
PRGn: ["#40004b", "#762a83", "#9970ab", "#c2a5cf", "#e7d4e8", "#f7f7f7", "#d9f0d3", "#a6dba0", "#5aae61", "#1b7837", "#00441b"],
|
|
5516
|
+
PuOr: ["#7f3b08", "#b35806", "#e08214", "#fdb863", "#fee0b6", "#f7f7f7", "#d8daeb", "#b2abd2", "#8073ac", "#542788", "#2d004b"],
|
|
5517
|
+
RdBu: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#f7f7f7", "#d1e5f0", "#92c5de", "#4393c3", "#2166ac", "#053061"],
|
|
5518
|
+
RdGy: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#ffffff", "#e0e0e0", "#bababa", "#878787", "#4d4d4d", "#1a1a1a"],
|
|
5519
|
+
RdYlBu: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee090", "#ffffbf", "#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"],
|
|
5520
|
+
RdYlGn: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#d9ef8b", "#a6d96a", "#66bd63", "#1a9850", "#006837"],
|
|
5521
|
+
Spectral: ["#9e0142", "#d53e4f", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#e6f598", "#abdda4", "#66c2a5", "#3288bd", "#5e4fa2"],
|
|
5522
|
+
category10: [
|
|
5523
|
+
"#1f77b4",
|
|
5524
|
+
"#ff7f0e",
|
|
5525
|
+
"#2ca02c",
|
|
5526
|
+
"#d62728",
|
|
5527
|
+
"#9467bd",
|
|
5528
|
+
"#8c564b",
|
|
5529
|
+
"#e377c2",
|
|
5530
|
+
"#7f7f7f",
|
|
5531
|
+
"#bcbd22",
|
|
5532
|
+
"#17becf"
|
|
5533
|
+
],
|
|
5534
|
+
category20: [
|
|
5535
|
+
"#1f77b4",
|
|
5536
|
+
"#aec7e8",
|
|
5537
|
+
"#ff7f0e",
|
|
5538
|
+
"#ffbb78",
|
|
5539
|
+
"#2ca02c",
|
|
5540
|
+
"#98df8a",
|
|
5541
|
+
"#d62728",
|
|
5542
|
+
"#ff9896",
|
|
5543
|
+
"#9467bd",
|
|
5544
|
+
"#c5b0d5",
|
|
5545
|
+
"#8c564b",
|
|
5546
|
+
"#c49c94",
|
|
5547
|
+
"#e377c2",
|
|
5548
|
+
"#f7b6d2",
|
|
5549
|
+
"#7f7f7f",
|
|
5550
|
+
"#c7c7c7",
|
|
5551
|
+
"#bcbd22",
|
|
5552
|
+
"#dbdb8d",
|
|
5553
|
+
"#17becf",
|
|
5554
|
+
"#9edae5"
|
|
5555
|
+
],
|
|
5556
|
+
Accent: ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17", "#666666"],
|
|
5557
|
+
Dark2: ["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"],
|
|
5558
|
+
Paired: ["#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e31a1c", "#fdbf6f", "#ff7f00", "#cab2d6", "#6a3d9a", "#ffff99", "#b15928"],
|
|
5559
|
+
Pastel1: ["#fbb4ae", "#b3cde3", "#ccebc5", "#decbe4", "#fed9a6", "#ffffcc", "#e5d8bd", "#fddaec", "#f2f2f2"],
|
|
5560
|
+
Pastel2: ["#b3e2cd", "#fdcdac", "#cbd5e8", "#f4cae4", "#e6f5c9", "#fff2ae", "#f1e2cc", "#cccccc"],
|
|
5561
|
+
Set1: ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", "#a65628", "#f781bf", "#999999"],
|
|
5562
|
+
Set2: ["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3"],
|
|
5563
|
+
Set3: ["#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f"],
|
|
5564
|
+
Tab10: [
|
|
5565
|
+
"#4e79a7",
|
|
5566
|
+
"#f28e2c",
|
|
5567
|
+
"#e15759",
|
|
5568
|
+
"#76b7b2",
|
|
5569
|
+
"#59a14f",
|
|
5570
|
+
"#edc949",
|
|
5571
|
+
"#af7aa1",
|
|
5572
|
+
"#ff9da7",
|
|
5573
|
+
"#9c755f",
|
|
5574
|
+
"#bab0ab"
|
|
5575
|
+
],
|
|
5576
|
+
Tab20: [
|
|
5577
|
+
"#4e79a7",
|
|
5578
|
+
"#a0cbe8",
|
|
5579
|
+
"#f28e2c",
|
|
5580
|
+
"#ffbe7d",
|
|
5581
|
+
"#59a14f",
|
|
5582
|
+
"#8cd17d",
|
|
5583
|
+
"#b6992d",
|
|
5584
|
+
"#f1ce63",
|
|
5585
|
+
"#499894",
|
|
5586
|
+
"#86bcb6",
|
|
5587
|
+
"#e15759",
|
|
5588
|
+
"#ff9d9a",
|
|
5589
|
+
"#79706e",
|
|
5590
|
+
"#bab0ac",
|
|
5591
|
+
"#d37295",
|
|
5592
|
+
"#fabfd2",
|
|
5593
|
+
"#b07aa1",
|
|
5594
|
+
"#d4a6c8",
|
|
5595
|
+
"#9d7660",
|
|
5596
|
+
"#d7b5a6"
|
|
5597
|
+
],
|
|
5598
|
+
thermal: ["#042333", "#2c3e50", "#0b5345", "#1e8449", "#f39c12", "#e74c3c", "#fadbd8"],
|
|
5599
|
+
haline: ["#2c3e50", "#1a5276", "#2980b9", "#5dade2", "#aed6f1", "#d5f5e3"],
|
|
5600
|
+
terrain: ["#333399", "#0099ff", "#00cc00", "#ffff00", "#ff9900", "#cc6600", "#996633", "#ffffff"],
|
|
5601
|
+
rainbow: ["#ff0000", "#ff8000", "#ffff00", "#80ff00", "#00ff00", "#00ff80", "#00ffff", "#0080ff", "#0000ff", "#8000ff"],
|
|
5602
|
+
cubehelix: ["#000000", "#1a1530", "#30304d", "#4d5366", "#6d826e", "#8ab17d", "#add38a", "#dae8a2", "#ffffff"]
|
|
5603
|
+
};
|
|
5604
|
+
});
|
|
5605
|
+
|
|
5227
5606
|
// src/scales/size.ts
|
|
5228
5607
|
function scale_size_continuous(options = {}) {
|
|
5229
5608
|
const range = options.range ?? [1, 6];
|
|
@@ -5292,45 +5671,8 @@ function scale_size_binned(options = {}) {
|
|
|
5292
5671
|
}
|
|
5293
5672
|
};
|
|
5294
5673
|
}
|
|
5674
|
+
|
|
5295
5675
|
// 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
5676
|
function scale_shape_discrete(options = {}) {
|
|
5335
5677
|
const shapes = options.values ?? DEFAULT_SHAPES;
|
|
5336
5678
|
return {
|
|
@@ -5389,6 +5731,48 @@ function scale_shape_ordinal(options = {}) {
|
|
|
5389
5731
|
}
|
|
5390
5732
|
};
|
|
5391
5733
|
}
|
|
5734
|
+
var DEFAULT_SHAPES, SHAPE_CHARS;
|
|
5735
|
+
var init_shape = __esm(() => {
|
|
5736
|
+
DEFAULT_SHAPES = [
|
|
5737
|
+
"circle",
|
|
5738
|
+
"square",
|
|
5739
|
+
"triangle",
|
|
5740
|
+
"diamond",
|
|
5741
|
+
"cross",
|
|
5742
|
+
"plus",
|
|
5743
|
+
"star",
|
|
5744
|
+
"open_circle",
|
|
5745
|
+
"open_square",
|
|
5746
|
+
"open_triangle",
|
|
5747
|
+
"open_diamond",
|
|
5748
|
+
"dot"
|
|
5749
|
+
];
|
|
5750
|
+
SHAPE_CHARS = {
|
|
5751
|
+
circle: "●",
|
|
5752
|
+
filled_circle: "●",
|
|
5753
|
+
open_circle: "○",
|
|
5754
|
+
square: "■",
|
|
5755
|
+
filled_square: "■",
|
|
5756
|
+
open_square: "□",
|
|
5757
|
+
triangle: "▲",
|
|
5758
|
+
filled_triangle: "▲",
|
|
5759
|
+
open_triangle: "△",
|
|
5760
|
+
triangle_down: "▼",
|
|
5761
|
+
diamond: "◆",
|
|
5762
|
+
filled_diamond: "◆",
|
|
5763
|
+
open_diamond: "◇",
|
|
5764
|
+
cross: "✕",
|
|
5765
|
+
plus: "+",
|
|
5766
|
+
star: "★",
|
|
5767
|
+
open_star: "☆",
|
|
5768
|
+
dot: "•",
|
|
5769
|
+
bullet: "•",
|
|
5770
|
+
asterisk: "*",
|
|
5771
|
+
hash: "#",
|
|
5772
|
+
at: "@"
|
|
5773
|
+
};
|
|
5774
|
+
});
|
|
5775
|
+
|
|
5392
5776
|
// src/scales/alpha.ts
|
|
5393
5777
|
function scale_alpha_continuous(options = {}) {
|
|
5394
5778
|
const range = options.range ?? [0.1, 1];
|
|
@@ -5485,17 +5869,8 @@ function scale_alpha_binned(options = {}) {
|
|
|
5485
5869
|
}
|
|
5486
5870
|
};
|
|
5487
5871
|
}
|
|
5872
|
+
|
|
5488
5873
|
// 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
5874
|
function parseDateTime(value) {
|
|
5500
5875
|
if (value === null || value === undefined)
|
|
5501
5876
|
return null;
|
|
@@ -5677,7 +6052,30 @@ function scale_y_duration(options = {}) {
|
|
|
5677
6052
|
scale.aesthetic = "y";
|
|
5678
6053
|
return scale;
|
|
5679
6054
|
}
|
|
6055
|
+
var TIME_INTERVALS;
|
|
6056
|
+
var init_datetime = __esm(() => {
|
|
6057
|
+
TIME_INTERVALS = [
|
|
6058
|
+
{ name: "millisecond", ms: 1 },
|
|
6059
|
+
{ name: "second", ms: 1000 },
|
|
6060
|
+
{ name: "minute", ms: 60 * 1000 },
|
|
6061
|
+
{ name: "hour", ms: 60 * 60 * 1000 },
|
|
6062
|
+
{ name: "day", ms: 24 * 60 * 60 * 1000 },
|
|
6063
|
+
{ name: "week", ms: 7 * 24 * 60 * 60 * 1000 },
|
|
6064
|
+
{ name: "month", ms: 30 * 24 * 60 * 60 * 1000 },
|
|
6065
|
+
{ name: "year", ms: 365 * 24 * 60 * 60 * 1000 }
|
|
6066
|
+
];
|
|
6067
|
+
});
|
|
6068
|
+
|
|
6069
|
+
// src/scales/index.ts
|
|
6070
|
+
var init_scales2 = __esm(() => {
|
|
6071
|
+
init_color();
|
|
6072
|
+
init_shape();
|
|
6073
|
+
init_datetime();
|
|
6074
|
+
});
|
|
6075
|
+
|
|
5680
6076
|
// src/repl/repl.ts
|
|
6077
|
+
import * as readline from "readline";
|
|
6078
|
+
|
|
5681
6079
|
class GGTermREPL {
|
|
5682
6080
|
rl = null;
|
|
5683
6081
|
state;
|
|
@@ -6312,7 +6710,19 @@ function startREPL(options) {
|
|
|
6312
6710
|
repl.start();
|
|
6313
6711
|
return repl;
|
|
6314
6712
|
}
|
|
6713
|
+
var init_repl = __esm(() => {
|
|
6714
|
+
init_grammar();
|
|
6715
|
+
init_geoms();
|
|
6716
|
+
init_scales2();
|
|
6717
|
+
});
|
|
6718
|
+
|
|
6719
|
+
// src/repl/index.ts
|
|
6720
|
+
var init_repl2 = __esm(() => {
|
|
6721
|
+
init_repl();
|
|
6722
|
+
});
|
|
6723
|
+
|
|
6315
6724
|
// src/cli.ts
|
|
6725
|
+
init_repl2();
|
|
6316
6726
|
import * as fs from "fs";
|
|
6317
6727
|
import * as path from "path";
|
|
6318
6728
|
var VERSION = "0.0.1";
|