@uwdata/vgplot 0.12.1 → 0.12.2

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/vgplot.js CHANGED
@@ -103,7 +103,7 @@ var require_search_bounds = __commonJS({
103
103
  }
104
104
  return -1;
105
105
  }
106
- function norm(a2, y4, c4, l, h2, f2) {
106
+ function norm2(a2, y4, c4, l, h2, f2) {
107
107
  if (typeof c4 === "function") {
108
108
  return f2(a2, y4, c4, l === void 0 ? 0 : l | 0, h2 === void 0 ? a2.length - 1 : h2 | 0);
109
109
  }
@@ -111,19 +111,19 @@ var require_search_bounds = __commonJS({
111
111
  }
112
112
  module.exports = {
113
113
  ge: function(a2, y4, c4, l, h2) {
114
- return norm(a2, y4, c4, l, h2, ge);
114
+ return norm2(a2, y4, c4, l, h2, ge);
115
115
  },
116
116
  gt: function(a2, y4, c4, l, h2) {
117
- return norm(a2, y4, c4, l, h2, gt2);
117
+ return norm2(a2, y4, c4, l, h2, gt2);
118
118
  },
119
119
  lt: function(a2, y4, c4, l, h2) {
120
- return norm(a2, y4, c4, l, h2, lt2);
120
+ return norm2(a2, y4, c4, l, h2, lt2);
121
121
  },
122
122
  le: function(a2, y4, c4, l, h2) {
123
- return norm(a2, y4, c4, l, h2, le);
123
+ return norm2(a2, y4, c4, l, h2, le);
124
124
  },
125
125
  eq: function(a2, y4, c4, l, h2) {
126
- return norm(a2, y4, c4, l, h2, eq2);
126
+ return norm2(a2, y4, c4, l, h2, eq2);
127
127
  }
128
128
  };
129
129
  }
@@ -563,14 +563,15 @@ var MosaicClient = class {
563
563
  }
564
564
  /**
565
565
  * Return an array of fields queried by this client.
566
- * @returns {object[]|null} The fields to retrieve info for.
566
+ * @returns {import('./types.js').FieldInfoRequest[] | null}
567
+ * The fields to retrieve info for.
567
568
  */
568
569
  fields() {
569
570
  return null;
570
571
  }
571
572
  /**
572
573
  * Called by the coordinator to set the field info for this client.
573
- * @param {*} info The field info result.
574
+ * @param {import('./types.js').FieldInfo[]} info The field info result.
574
575
  * @returns {this}
575
576
  */
576
577
  fieldInfo(info) {
@@ -3451,6 +3452,9 @@ var ColumnNameRefNode = class extends ColumnRefNode {
3451
3452
  };
3452
3453
 
3453
3454
  // ../sql/src/ast/column-param.js
3455
+ function isColumnParam(value) {
3456
+ return value instanceof ColumnParamNode;
3457
+ }
3454
3458
  var ColumnParamNode = class extends ColumnRefNode {
3455
3459
  /**
3456
3460
  * Instantiate a column param node.
@@ -5039,7 +5043,7 @@ function collectAggregates(root2) {
5039
5043
  function collectColumns(root2) {
5040
5044
  const cols = {};
5041
5045
  walk(root2, (node) => {
5042
- if (node.type === COLUMN_REF) {
5046
+ if (node.type === COLUMN_REF || node.type === COLUMN_PARAM) {
5043
5047
  cols[node] = node;
5044
5048
  }
5045
5049
  });
@@ -5170,21 +5174,21 @@ function bin2d(q2, xp, yp, aggs, xn, groupby) {
5170
5174
  }
5171
5175
 
5172
5176
  // ../sql/src/transforms/bin-linear-1d.js
5173
- function binLinear1d(query, x4, weight) {
5177
+ function binLinear1d(query, x4, weight = void 0, groupby = []) {
5174
5178
  const w = weight ? (x5) => mul(x5, weight) : (x5) => x5;
5175
5179
  const p0 = floor(x4);
5176
5180
  const p1 = add(p0, 1);
5177
5181
  return Query.from(Query.unionAll(
5178
5182
  query.clone().select({ i: int322(p0), w: w(sub(p1, x4)) }),
5179
5183
  query.clone().select({ i: int322(p1), w: w(sub(x4, p0)) })
5180
- )).select({ index: "i", density: sum("w") }).groupby("index").having(neq("density", 0));
5184
+ )).select({ index: "i", density: sum("w") }, groupby).groupby("index", groupby).having(neq("density", 0));
5181
5185
  }
5182
5186
 
5183
5187
  // ../sql/src/transforms/bin-linear-2d.js
5184
5188
  function identity(x4) {
5185
5189
  return x4;
5186
5190
  }
5187
- function binLinear2d(q2, xp, yp, weight, xn, groupby) {
5191
+ function binLinear2d(q2, xp, yp, weight, xn, groupby = []) {
5188
5192
  const w = weight ? (x4) => mul(x4, weight) : identity;
5189
5193
  const subq = (i, w2) => q2.clone().select({ xp, yp, i, w: w2 });
5190
5194
  const index2 = (x4, y4) => add(x4, mul(y4, xn));
@@ -5914,7 +5918,7 @@ var statMap = {
5914
5918
  [Min]: min,
5915
5919
  [Nulls]: (column3) => count().where(isNull(column3))
5916
5920
  };
5917
- function summarize(table3, column3, stats) {
5921
+ function summarize({ table: table3, column: column3, stats }) {
5918
5922
  return Query.from(table3).select(Array.from(stats, (s2) => ({ [s2]: statMap[s2](column3) })));
5919
5923
  }
5920
5924
  async function queryFieldInfo(mc, fields) {
@@ -5925,7 +5929,7 @@ async function queryFieldInfo(mc, fields) {
5925
5929
  }
5926
5930
  }
5927
5931
  async function getFieldInfo(mc, { table: table3, column: column3, stats }) {
5928
- const q2 = Query.from({ source: table3 }).select({ column: column3 }).groupby(column3.aggregate ? sql`ALL` : []);
5932
+ const q2 = Query.from({ source: table3 }).select({ column: column3 }).groupby(isNode(column3) && isAggregateExpression(column3) ? sql`ALL` : []);
5929
5933
  const [desc2] = Array.from(await mc.query(Query.describe(q2)));
5930
5934
  const info = {
5931
5935
  table: table3,
@@ -5934,16 +5938,16 @@ async function getFieldInfo(mc, { table: table3, column: column3, stats }) {
5934
5938
  type: jsType(desc2.column_type),
5935
5939
  nullable: desc2.null === "YES"
5936
5940
  };
5937
- if (!(stats?.length || stats?.size)) return info;
5941
+ if (!stats?.length) return info;
5938
5942
  const [result] = await mc.query(
5939
- summarize(table3, column3, stats),
5943
+ summarize({ table: table3, column: column3, stats }),
5940
5944
  { persist: true }
5941
5945
  );
5942
5946
  return Object.assign(info, result);
5943
5947
  }
5944
5948
  async function getTableInfo(mc, table3) {
5945
- const result = await mc.query(`DESCRIBE ${asTableRef(table3)}`);
5946
- return Array.from(result).map((desc2) => ({
5949
+ const result = Array.from(await mc.query(`DESCRIBE ${asTableRef(table3)}`));
5950
+ return result.map((desc2) => ({
5947
5951
  table: table3,
5948
5952
  column: desc2.column_name,
5949
5953
  sqlType: desc2.column_type,
@@ -6559,7 +6563,10 @@ var Coordinator = class {
6559
6563
  * or a SQL string.
6560
6564
  * @param {object} [options] An options object.
6561
6565
  * @param {'arrow' | 'json'} [options.type] The query result format type.
6562
- * @param {boolean} [options.cache=true] If true, cache the query result.
6566
+ * @param {boolean} [options.cache=true] If true, cache the query result
6567
+ * client-side within the QueryManager.
6568
+ * @param {boolean} [options.persist] If true, request the database
6569
+ * server to persist a cached query server-side.
6563
6570
  * @param {number} [options.priority] The query priority, defaults to
6564
6571
  * `Priority.Normal`.
6565
6572
  * @returns {QueryResult} A query result promise.
@@ -44195,7 +44202,9 @@ function isColor2(value) {
44195
44202
 
44196
44203
  // ../plot/src/marks/util/is-constant-option.js
44197
44204
  var constantOptions = /* @__PURE__ */ new Set([
44205
+ "offset",
44198
44206
  "order",
44207
+ "reverse",
44199
44208
  "sort",
44200
44209
  "label",
44201
44210
  "anchor",
@@ -44267,7 +44276,7 @@ var isFieldObject = (channel, field3) => {
44267
44276
  var fieldEntry = (channel, field3) => ({
44268
44277
  channel,
44269
44278
  field: field3,
44270
- as: isColumnRef(field3) ? field3.column : channel
44279
+ as: isColumnRef(field3) && !isColumnParam(field3) ? field3.column : channel
44271
44280
  });
44272
44281
  var valueEntry = (channel, value) => ({ channel, value });
44273
44282
  var isDataArray = (source) => Array.isArray(source);
@@ -44363,7 +44372,11 @@ var Mark2 = class extends MosaicClient {
44363
44372
  reqs[channel]?.forEach((s2) => entry.add(s2));
44364
44373
  }
44365
44374
  const table3 = this.sourceTable();
44366
- return Array.from(fields, ([c4, s2]) => ({ table: table3, column: c4, stats: s2 }));
44375
+ return Array.from(fields, ([c4, s2]) => ({
44376
+ table: table3,
44377
+ column: c4,
44378
+ stats: Array.from(s2)
44379
+ }));
44367
44380
  }
44368
44381
  fieldInfo(info) {
44369
44382
  const lookup = Object.fromEntries(info.map((x4) => [x4.column, x4]));
@@ -44561,13 +44574,33 @@ var ConnectedMark = class extends Mark2 {
44561
44574
  function array3(size, proto = []) {
44562
44575
  return new proto.constructor(size);
44563
44576
  }
44564
- function grid1d(size, index2, value) {
44565
- const G = array3(size, value);
44566
- const n = value.length;
44567
- for (let i = 0; i < n; ++i) {
44568
- G[index2[i]] = value[i];
44577
+ function grid1d(size, index2, value, columns, groupby) {
44578
+ const numRows = index2.length;
44579
+ const result = {};
44580
+ const cells = [];
44581
+ if (groupby?.length) {
44582
+ const group3 = new Int32Array(numRows);
44583
+ const gvalues = groupby.map((name2) => columns[name2]);
44584
+ const cellMap = {};
44585
+ for (let row = 0; row < numRows; ++row) {
44586
+ const key = gvalues.map((group4) => group4[row]);
44587
+ group3[row] = cellMap[key] ??= cells.push(key) - 1;
44588
+ }
44589
+ for (let i = 0; i < groupby.length; ++i) {
44590
+ result[groupby[i]] = cells.map((cell3) => cell3[i]);
44591
+ }
44592
+ const G = result._grid = cells.map(() => array3(size, value));
44593
+ for (let row = 0; row < numRows; ++row) {
44594
+ G[group3[row]][index2[row]] = value[row];
44595
+ }
44596
+ } else {
44597
+ cells.push([]);
44598
+ const [G] = result._grid = [array3(size, value)];
44599
+ for (let row = 0; row < numRows; ++row) {
44600
+ G[index2[row]] = value[row];
44601
+ }
44569
44602
  }
44570
- return G;
44603
+ return { numRows: cells.length, columns: result };
44571
44604
  }
44572
44605
  function grid2d(w, h2, index2, columns, aggregates, groupby, interpolate) {
44573
44606
  const numRows = index2.length;
@@ -45425,9 +45458,16 @@ function stripXY(mark2, filter3) {
45425
45458
  }
45426
45459
 
45427
45460
  // ../plot/src/marks/Density1DMark.js
45461
+ var GROUPBY = { fill: 1, stroke: 1, z: 1 };
45428
45462
  var Density1DMark = class extends Mark2 {
45429
45463
  constructor(type2, source, options) {
45430
- const { bins: bins2 = 1024, bandwidth = 20, ...channels } = options;
45464
+ const {
45465
+ bins: bins2 = 1024,
45466
+ bandwidth = 20,
45467
+ normalize: normalize4 = false,
45468
+ stack: stack2 = false,
45469
+ ...channels
45470
+ } = options;
45431
45471
  const dim = type2.endsWith("X") ? "y" : "x";
45432
45472
  super(type2, source, channels, dim === "x" ? xext : yext);
45433
45473
  this.dim = dim;
@@ -45436,7 +45476,13 @@ var Density1DMark = class extends Mark2 {
45436
45476
  });
45437
45477
  this.bandwidth = handleParam(bandwidth, (value) => {
45438
45478
  this.bandwidth = value;
45439
- return this.grid ? this.convolve().update() : null;
45479
+ return this.grids ? this.convolve().update() : null;
45480
+ });
45481
+ this.normalize = handleParam(normalize4, (value) => {
45482
+ return this.normalize = value, this.convolve().update();
45483
+ });
45484
+ this.stack = handleParam(stack2, (value) => {
45485
+ return this.stack = value, this.update();
45440
45486
  });
45441
45487
  }
45442
45488
  get filterStable() {
@@ -45451,42 +45497,67 @@ var Density1DMark = class extends Mark2 {
45451
45497
  const [x4, bx] = binExpr(this, dim, bins2, extent4);
45452
45498
  const q2 = markQuery(channels, this.sourceTable(), [dim]).where(filter3.concat(isBetween(bx, extent4)));
45453
45499
  const v3 = this.channelField("weight") ? "weight" : null;
45454
- return binLinear1d(q2, x4, v3);
45500
+ const g2 = this.groupby = channels.flatMap((c4) => {
45501
+ return GROUPBY[c4.channel] && c4.field ? c4.as : [];
45502
+ });
45503
+ return binLinear1d(q2, x4, v3, g2);
45455
45504
  }
45456
45505
  queryResult(data) {
45457
- const { columns: { index: index2, density: density3 } } = toDataColumns(data);
45458
- this.grid = grid1d(this.bins, index2, density3);
45506
+ const c4 = toDataColumns(data).columns;
45507
+ this.grids = grid1d(this.bins, c4.index, c4.density, c4, this.groupby);
45459
45508
  return this.convolve();
45460
45509
  }
45461
45510
  convolve() {
45462
- const { bins: bins2, bandwidth, dim, grid: grid2, plot: plot3, extent: [lo, hi] } = this;
45463
- const neg = grid2.some((v4) => v4 < 0);
45511
+ const {
45512
+ bins: bins2,
45513
+ bandwidth,
45514
+ normalize: normalize4,
45515
+ dim,
45516
+ grids,
45517
+ groupby,
45518
+ plot: plot3,
45519
+ extent: [lo, hi]
45520
+ } = this;
45521
+ const cols = grids.columns;
45522
+ const numGrids = grids.numRows;
45523
+ const b2 = this.channelField(dim).as;
45524
+ const v3 = dim === "x" ? "y" : "x";
45464
45525
  const size = dim === "x" ? plot3.innerWidth() : plot3.innerHeight();
45526
+ const neg = cols._grid.some((grid2) => grid2.some((v4) => v4 < 0));
45465
45527
  const config = dericheConfig(bandwidth * (bins2 - 1) / size, neg);
45466
- const result = dericheConv1d(config, grid2, bins2);
45467
- const v3 = dim === "x" ? "y" : "x";
45468
- const b2 = this.channelField(dim).as;
45469
45528
  const b0 = +lo;
45470
45529
  const delta = (hi - b0) / (bins2 - 1);
45471
- const scale3 = 1 / delta;
45472
- const _b2 = new Float64Array(bins2);
45473
- const _v2 = new Float64Array(bins2);
45474
- for (let i = 0; i < bins2; ++i) {
45475
- _b2[i] = b0 + i * delta;
45476
- _v2[i] = result[i] * scale3;
45477
- }
45478
- this.data = { numRows: bins2, columns: { [b2]: _b2, [v3]: _v2 } };
45530
+ const numRows = bins2 * numGrids;
45531
+ const _b2 = new Float64Array(numRows);
45532
+ const _v2 = new Float64Array(numRows);
45533
+ const _g2 = groupby.reduce((m2, name2) => (m2[name2] = Array(numRows), m2), {});
45534
+ for (let k3 = 0, g2 = 0; g2 < numGrids; ++g2) {
45535
+ groupby.forEach((name2) => _g2[name2].fill(cols[name2][g2], k3, k3 + bins2));
45536
+ const grid2 = cols._grid[g2];
45537
+ const result = dericheConv1d(config, grid2, bins2);
45538
+ const scale3 = 1 / norm(grid2, result, delta, normalize4);
45539
+ for (let i = 0; i < bins2; ++i, ++k3) {
45540
+ _b2[k3] = b0 + i * delta;
45541
+ _v2[k3] = result[i] * scale3;
45542
+ }
45543
+ }
45544
+ this.data = { numRows, columns: { [b2]: _b2, [v3]: _v2, ..._g2 } };
45479
45545
  return this;
45480
45546
  }
45481
45547
  plotSpecs() {
45482
- const { type: type2, data: { numRows: length4, columns }, channels, dim } = this;
45483
- const options = dim === "x" ? { y: columns.y } : { x: columns.x };
45548
+ const { type: type2, data: { numRows: length4, columns }, channels, dim, stack: stack2 } = this;
45549
+ const _2 = type2.startsWith("area") && !stack2 ? "2" : "";
45550
+ const options = dim === "x" ? { [`y${_2}`]: columns.y } : { [`x${_2}`]: columns.x };
45484
45551
  for (const c4 of channels) {
45485
45552
  options[c4.channel] = channelOption(c4, columns);
45486
45553
  }
45487
45554
  return [{ type: type2, data: { length: length4 }, options }];
45488
45555
  }
45489
45556
  };
45557
+ function norm(grid2, smoothed, delta, type2) {
45558
+ const value = type2 === true || type2 === "sum" ? sum2(grid2) : type2 === "max" ? max2(smoothed) : delta;
45559
+ return value || 1;
45560
+ }
45490
45561
 
45491
45562
  // ../plot/src/marks/Density2DMark.js
45492
45563
  var Density2DMark = class extends Grid2DMark {
@@ -47554,6 +47625,7 @@ var Menu = class extends MosaicClient {
47554
47625
  constructor({
47555
47626
  element,
47556
47627
  filterBy,
47628
+ as,
47557
47629
  from: from2,
47558
47630
  column: column3,
47559
47631
  label = column3,
@@ -47561,8 +47633,7 @@ var Menu = class extends MosaicClient {
47561
47633
  // TODO
47562
47634
  options,
47563
47635
  value,
47564
- field: field3 = column3,
47565
- as
47636
+ field: field3 = column3
47566
47637
  } = {}) {
47567
47638
  super(filterBy);
47568
47639
  this.from = from2;
@@ -47579,8 +47650,8 @@ var Menu = class extends MosaicClient {
47579
47650
  this.select = document.createElement("select");
47580
47651
  this.element.appendChild(this.select);
47581
47652
  if (options) {
47582
- this.data = options.map((value2) => isObject3(value2) ? value2 : { value: value2 });
47583
- this.selectedValue(value ?? "");
47653
+ this.data = options.map((opt) => isObject3(opt) ? opt : { value: opt });
47654
+ this.selectedValue(value === void 0 ? "" : value);
47584
47655
  this.update();
47585
47656
  }
47586
47657
  if (selection2) {
@@ -47654,7 +47725,7 @@ var Menu = class extends MosaicClient {
47654
47725
  }
47655
47726
  if (selection2) {
47656
47727
  const value = isSelection(selection2) ? selection2.valueFor(this) : selection2.value;
47657
- this.selectedValue(value ?? "");
47728
+ this.selectedValue(value === void 0 ? "" : value);
47658
47729
  }
47659
47730
  return this;
47660
47731
  }
@@ -48050,8 +48121,8 @@ var Table3 = class extends MosaicClient {
48050
48121
  coordinator().prefetch(query.clone().offset(offset2 + this.limit));
48051
48122
  }
48052
48123
  fields() {
48053
- const from2 = this.sourceTable();
48054
- return this.columns.map((name2) => column(name2, from2));
48124
+ const table3 = this.sourceTable();
48125
+ return this.columns.map((column3) => ({ column: column3, table: table3 }));
48055
48126
  }
48056
48127
  fieldInfo(info) {
48057
48128
  this.schema = info;