ggaction 0.0.23 → 0.0.24

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.
@@ -11,7 +11,7 @@ const MAX_CELLS = 1_000_000;
11
11
 
12
12
  const TRANSFORM_KEYS = Object.freeze([
13
13
  "type", "x", "y", "bins", "extent", "includeEmpty", "members", "as",
14
- "resolved"
14
+ "resolved", "assignment"
15
15
  ]);
16
16
  const AXIS_KEYS = Object.freeze(["x", "y"]);
17
17
  const FIELD_KEYS = Object.freeze(["x0", "x1", "y0", "y1", "count", "members"]);
@@ -180,6 +180,11 @@ export function validateBin2DTransform(transform) {
180
180
  }
181
181
  requireField(transform.x, "2D bin x field");
182
182
  requireField(transform.y, "2D bin y field");
183
+ if (transform.assignment !== undefined && transform.assignment !== "step") {
184
+ throw new TypeError(
185
+ 'Stored 2D bin assignment must be "step" or omitted.'
186
+ );
187
+ }
183
188
  validateBins(transform.bins);
184
189
  validateRequestedExtent(transform.extent);
185
190
  if (typeof transform.includeEmpty !== "boolean") {
@@ -201,10 +206,16 @@ export function normalizeBin2DTransform({
201
206
  y,
202
207
  bins,
203
208
  extent,
209
+ assignment = "edges",
204
210
  includeEmpty = false,
205
211
  members = false,
206
212
  as
207
213
  } = {}) {
214
+ if (assignment !== "edges" && assignment !== "step") {
215
+ throw new TypeError(
216
+ '2D bin assignment must be "edges" or "step".'
217
+ );
218
+ }
208
219
  const normalizedBins = normalizeBins(bins);
209
220
  const transform = {
210
221
  type: "bin2d",
@@ -214,7 +225,8 @@ export function normalizeBin2DTransform({
214
225
  extent: normalizeRequestedExtent(extent),
215
226
  includeEmpty,
216
227
  members,
217
- as: normalizeOutputFields(id, as, members)
228
+ as: normalizeOutputFields(id, as, members),
229
+ ...(assignment === "step" ? { assignment } : {})
218
230
  };
219
231
  validateBin2DTransform(transform);
220
232
  return cloneAndFreeze(transform);
@@ -266,6 +278,20 @@ function findBinIndex(value, edges) {
266
278
  return low;
267
279
  }
268
280
 
281
+ function findStepBinIndex(value, extent, count) {
282
+ if (count === 1 || value === extent[1]) return count - 1;
283
+ const [minimum, maximum] = extent;
284
+ const span = maximum - minimum;
285
+ const step = Number.isFinite(span)
286
+ ? span / count
287
+ : maximum / count - minimum / count;
288
+ const distance = value - minimum;
289
+ const position = Number.isFinite(distance)
290
+ ? distance / step
291
+ : value / step - minimum / step;
292
+ return Math.max(0, Math.min(count - 1, Math.floor(1e-14 + position)));
293
+ }
294
+
269
295
  export function deriveBin2DRows(rows, transform) {
270
296
  if (!Array.isArray(rows)) {
271
297
  throw new TypeError("2D bin source rows must be an array.");
@@ -304,8 +330,12 @@ export function deriveBin2DRows(rows, transform) {
304
330
  () => []
305
331
  );
306
332
  for (const item of eligible) {
307
- const xIndex = findBinIndex(item.row[transform.x], edges.x);
308
- const yIndex = findBinIndex(item.row[transform.y], edges.y);
333
+ const xIndex = transform.assignment === "step"
334
+ ? findStepBinIndex(item.row[transform.x], extent.x, transform.bins.x)
335
+ : findBinIndex(item.row[transform.x], edges.x);
336
+ const yIndex = transform.assignment === "step"
337
+ ? findStepBinIndex(item.row[transform.y], extent.y, transform.bins.y)
338
+ : findBinIndex(item.row[transform.y], edges.y);
309
339
  buckets[yIndex * transform.bins.x + xIndex].push(item.index);
310
340
  }
311
341
  const values = [];