@uwdata/mosaic-plot 0.11.0 → 0.12.1

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.
@@ -1,4 +1,4 @@
1
- import { dateBin } from '@uwdata/mosaic-sql';
1
+ import { ExprNode, add, dateBin, div, float64, floor, interval, mul, sub } from '@uwdata/mosaic-sql';
2
2
  import { Transform } from '../symbols.js';
3
3
  import { channelScale } from '../marks/util/channel-scale.js';
4
4
  import { bins } from './bin-step.js';
@@ -16,12 +16,12 @@ export function bin(field, options = {}) {
16
16
  const fn = (mark, channel) => {
17
17
  if (hasExtent(mark, channel)) {
18
18
  return {
19
- [`${channel}1`]: binField(mark, channel, field, options),
20
- [`${channel}2`]: binField(mark, channel, field, { ...options, offset: 1 })
19
+ [`${channel}1`]: binNode(mark, channel, field, options),
20
+ [`${channel}2`]: binNode(mark, channel, field, { ...options, offset: 1 })
21
21
  };
22
22
  } else {
23
23
  return {
24
- [channel]: binField(mark, channel, field, options)
24
+ [channel]: binNode(mark, channel, field, options)
25
25
  };
26
26
  }
27
27
  };
@@ -29,43 +29,54 @@ export function bin(field, options = {}) {
29
29
  return fn;
30
30
  }
31
31
 
32
- function binField(mark, channel, column, options) {
33
- return {
34
- column,
35
- label: column,
36
- get columns() { return [column]; },
37
- get basis() { return column; },
38
- get stats() { return { column, stats: ['min', 'max'] }; },
39
- toString() {
40
- const { type, min, max } = mark.channelField(channel);
41
- const { interval: i, steps, offset = 0 } = options;
42
- const interval = i ?? (
43
- type === 'date' || hasTimeScale(mark, channel) ? 'date' : 'number'
44
- );
45
-
46
- if (interval === 'number') {
47
- // perform number binning
48
- const { apply, sqlApply, sqlInvert } = channelScale(mark, channel);
49
- const b = bins(apply(min), apply(max), options);
50
- const col = sqlApply(column);
51
- const base = b.min === 0 ? col : `(${col} - ${b.min})`;
52
- const alpha = `${(b.max - b.min) / b.steps}::DOUBLE`;
53
- const off = offset ? `${offset} + ` : '';
54
- const expr = `${b.min} + ${alpha} * (${off}FLOOR(${base} / ${alpha}))`;
55
- return `${sqlInvert(expr)}`;
56
- } else {
57
- // perform date/time binning
58
- const { interval: unit, step = 1 } = interval === 'date'
59
- ? timeInterval(min, max, steps || 40)
60
- : options;
61
- const off = offset ? ` + INTERVAL ${offset * step} ${unit}` : '';
62
- return `(${dateBin(column, unit, step)}${off})`;
63
- }
64
- }
65
- };
32
+ function binNode(mark, channel, column, options) {
33
+ return new BinTransformNode(column, mark, channel, options);
66
34
  }
67
35
 
68
36
  function hasTimeScale(mark, channel) {
69
37
  const scale = mark.plot.getAttribute(`${channel}Scale`);
70
38
  return scale === 'utc' || scale === 'time';
71
39
  }
40
+
41
+ class BinTransformNode extends ExprNode {
42
+ constructor(column, mark, channel, options) {
43
+ super('COLUMN_REF');
44
+ this.column = column;
45
+ this.mark = mark;
46
+ this.channel = channel;
47
+ this.options = options;
48
+ }
49
+
50
+ get stats() {
51
+ return { column: this.column, stats: ['min', 'max'] };
52
+ }
53
+
54
+ toString() {
55
+ const { mark, channel, column, options } = this;
56
+ const { type, min, max } = mark.channelField(channel);
57
+ const { interval: i, steps, offset = 0 } = options;
58
+ const ival = i ?? (
59
+ type === 'date' || hasTimeScale(mark, channel) ? 'date' : 'number'
60
+ );
61
+
62
+ let result;
63
+ if (ival === 'number') {
64
+ // perform number binning
65
+ const { apply, sqlApply, sqlInvert } = channelScale(mark, channel);
66
+ const b = bins(apply(min), apply(max), options);
67
+ const col = sqlApply(column);
68
+ const alpha = float64((b.max - b.min) / b.steps);
69
+ const bin = floor(div(b.min === 0 ? col : sub(col, b.min), alpha));
70
+ const expr = add(b.min, mul(alpha, offset ? add(offset, bin) : bin));
71
+ result = sqlInvert(expr);
72
+ } else {
73
+ // perform date/time binning
74
+ const { interval: unit, step = 1 } = ival === 'date'
75
+ ? timeInterval(min, max, steps || 40)
76
+ : options;
77
+ const bin = dateBin(column, unit, step);
78
+ result = offset ? add(bin, interval(unit, offset * step)) : bin;
79
+ }
80
+ return `${result}`;
81
+ }
82
+ }
@@ -1,3 +0,0 @@
1
- export {
2
- bin
3
- } from './bin.js';