@jbrowse/bandage-core 7.1.0 → 7.2.0

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,3 +1,6 @@
1
+ import {
2
+ Canvas2DRenderer
3
+ } from "./chunk-CH3DLBUT.js";
1
4
  import {
2
5
  svgCanvas
3
6
  } from "./chunk-47DYCZOK.js";
@@ -11,9 +14,6 @@ import {
11
14
  walkRowsKeyTree,
12
15
  walkRowsTree
13
16
  } from "./chunk-UGD6ZMOF.js";
14
- import {
15
- Canvas2DRenderer
16
- } from "./chunk-CH3DLBUT.js";
17
17
  import {
18
18
  EXON_COLOR,
19
19
  exonOutlineTree,
@@ -24,10 +24,10 @@ import {
24
24
  } from "./chunk-BUBZ32IC.js";
25
25
  import {
26
26
  version
27
- } from "./chunk-MAPRJ2H2.js";
27
+ } from "./chunk-S73EYTZA.js";
28
28
  import {
29
29
  axisScaleOf
30
- } from "./chunk-AWCMVPVP.js";
30
+ } from "./chunk-Y7UR3MDE.js";
31
31
  import {
32
32
  facetLifts,
33
33
  walkLift
@@ -43,7 +43,7 @@ import {
43
43
  FIT_PADDING,
44
44
  drawingBounds,
45
45
  fitTransform
46
- } from "./chunk-6UFS3EWI.js";
46
+ } from "./chunk-EPWYRSHH.js";
47
47
  import {
48
48
  buildGeometry,
49
49
  computeReferenceRamp
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var version = "7.1.0";
2
+ var version = "7.2.0";
3
3
 
4
4
  export {
5
5
  version
@@ -1,21 +1,11 @@
1
+ import {
2
+ stressPlacement
3
+ } from "./chunk-LYJ4US66.js";
1
4
  import {
2
5
  isBackbone
3
6
  } from "./chunk-FYQWPEEY.js";
4
7
 
5
8
  // src/layout/stressEngine.ts
6
- var LAYOUT_ENGINES = [
7
- {
8
- value: "fmmm",
9
- label: "Bandage (FMMM)",
10
- description: "Bandage's force-directed layout: OGDF's fast multipole multilevel method, compiled to wasm."
11
- },
12
- {
13
- value: "stress",
14
- label: "Stress (experimental)",
15
- description: "Stress layout by stochastic gradient descent in plain JS: distances along the graph become distances on the page, so the reference reads straight and a repeat loop reads as a ring."
16
- }
17
- ];
18
- var LAYOUT_ENGINE_VALUES = LAYOUT_ENGINES.map((e) => e.value);
19
9
  var QUALITY = [
20
10
  { walks: 2, iterations: 15 },
21
11
  { walks: 4, iterations: 30 },
@@ -24,11 +14,12 @@ var QUALITY = [
24
14
  { walks: 16, iterations: 120 }
25
15
  ];
26
16
  var UNTANGLE_PASSES = 20;
27
- var UNTANGLE_RADIUS = 15;
17
+ var UNTANGLE_LINKS = 3;
28
18
  var UNTANGLE_PUSH = 0.3;
29
19
  var SMOOTH_PASSES = 2;
30
20
  var MAX_HOPS = 200;
31
21
  var EPS = 0.1;
22
+ var WARM = 0.5;
32
23
  function flipped(strand, name) {
33
24
  const own = name.at(-1);
34
25
  return (strand === "+" || strand === "-") && (own === "+" || own === "-") && strand !== own;
@@ -137,12 +128,36 @@ function chains(request) {
137
128
  off,
138
129
  nb,
139
130
  wt,
140
- n
131
+ n,
132
+ link
141
133
  };
142
134
  }
135
+ function components(c) {
136
+ const { n, off, nb } = c;
137
+ const comp = new Int32Array(n).fill(-1);
138
+ const members = [];
139
+ for (let s = 0; s < n; s++) {
140
+ if (comp[s] >= 0) {
141
+ continue;
142
+ }
143
+ const queue = [s];
144
+ comp[s] = members.length;
145
+ for (const u of queue) {
146
+ for (let e = off[u]; e < off[u + 1]; e++) {
147
+ const v = nb[e];
148
+ if (comp[v] < 0) {
149
+ comp[v] = members.length;
150
+ queue.push(v);
151
+ }
152
+ }
153
+ }
154
+ members.push(queue);
155
+ }
156
+ return { comp, members };
157
+ }
143
158
  function stressLayout(request, opts = {}) {
144
159
  const c = chains(request);
145
- const { n, off, nb, wt, seedX, seedY, backbone, first, count, per } = c;
160
+ const { n, off, nb, wt, seedX, seedY, backbone, first, count, per, link } = c;
146
161
  const o = request.options;
147
162
  const quality = QUALITY[Math.max(0, Math.min(4, num(opts.quality ?? o.quality, 2)))];
148
163
  const gap = num(opts.componentSeparation ?? o.componentSeparation, 15);
@@ -153,6 +168,7 @@ function stressLayout(request, opts = {}) {
153
168
  if (n === 0) {
154
169
  return { nodePositions };
155
170
  }
171
+ const { comp, members } = components(c);
156
172
  let dmin = Infinity;
157
173
  let total = 0;
158
174
  for (let e = 0; e < nb.length; e++) {
@@ -167,9 +183,13 @@ function stressLayout(request, opts = {}) {
167
183
  break;
168
184
  }
169
185
  }
186
+ const placed = anySeed ? stressPlacement(c) : void 0;
170
187
  const side = Math.sqrt(n) * 20;
171
188
  for (let i = 0; i < n; i++) {
172
- if (anySeed && !Number.isNaN(seedX[i])) {
189
+ if (placed && !Number.isNaN(placed.X[i])) {
190
+ X[i] = placed.X[i];
191
+ Y[i] = placed.Y[i];
192
+ } else if (anySeed && !Number.isNaN(seedX[i])) {
173
193
  X[i] = seedX[i] + rand() - 0.5;
174
194
  Y[i] = seedY[i] + rand() - 0.5;
175
195
  } else {
@@ -177,15 +197,18 @@ function stressLayout(request, opts = {}) {
177
197
  Y[i] = rand() * side;
178
198
  }
179
199
  }
180
- const refIdx = [];
181
- for (let i = 0; i < n; i++) {
182
- if (backbone[i] && !Number.isNaN(seedX[i])) {
183
- refIdx.push(i);
200
+ const refIdx = members.map(
201
+ (points) => Int32Array.from(
202
+ points.filter((i) => backbone[i] && !Number.isNaN(seedX[i])).sort((a, b) => seedX[a] - seedX[b])
203
+ )
204
+ );
205
+ const refX = refIdx.map((idx) => Float64Array.from(idx, (i) => seedX[i]));
206
+ let span = 0;
207
+ for (const xs of refX) {
208
+ if (xs.length) {
209
+ span = Math.max(span, xs[xs.length - 1] - xs[0]);
184
210
  }
185
211
  }
186
- refIdx.sort((a, b) => seedX[a] - seedX[b]);
187
- const refX = Float64Array.from(refIdx, (i) => seedX[i]);
188
- const span = refIdx.length ? refX[refX.length - 1] - refX[0] : 0;
189
212
  const dmax = Math.max(span, total / 4, dmin * 10);
190
213
  const etaMax = dmax * dmax;
191
214
  const etaMin = EPS * dmin * dmin;
@@ -209,6 +232,7 @@ function stressLayout(request, opts = {}) {
209
232
  X[j] = X[j] + rx;
210
233
  Y[j] = Y[j] + ry;
211
234
  };
235
+ let walked = 0;
212
236
  const walk = (i, length) => {
213
237
  let chain = c.chainOf[i];
214
238
  let idx = c.indexOf[i];
@@ -219,48 +243,57 @@ function stressLayout(request, opts = {}) {
219
243
  const step = per[chain];
220
244
  const toEnd = (dir > 0 ? points - 1 - idx : idx) * step;
221
245
  if (remaining <= toEnd) {
222
- return first[chain] + idx + dir * Math.round(remaining / step);
246
+ const steps = Math.round(remaining / step);
247
+ walked = length - remaining + steps * step;
248
+ return first[chain] + idx + dir * steps;
223
249
  }
224
250
  remaining -= toEnd;
225
251
  const out = c.links[chain][dir > 0 ? 1 : 0];
226
252
  if (out.length === 0) {
253
+ walked = length - remaining;
227
254
  return first[chain] + (dir > 0 ? points - 1 : 0);
228
255
  }
229
256
  const [next, enterSide] = out[Math.floor(rand() * out.length)];
230
- remaining -= num(o.edgeLength, 1);
257
+ remaining -= link;
231
258
  chain = next;
232
259
  dir = enterSide === 0 ? 1 : -1;
233
260
  idx = enterSide === 0 ? 0 : count[next] - 1;
234
261
  if (remaining <= 0) {
262
+ walked = length - remaining;
235
263
  return first[chain] + idx;
236
264
  }
237
265
  }
238
266
  return -1;
239
267
  };
240
- const refPartner = (i) => {
241
- const length = Math.exp(logMin + rand() * (logMax - logMin)) * (rand() < 0.5 ? -1 : 1);
242
- const target = seedX[i] + length;
268
+ const referenceTerm = (i, eta) => {
269
+ const idx = refIdx[comp[i]];
270
+ if (!backbone[i] || idx.length < 2 || Number.isNaN(seedX[i])) {
271
+ return;
272
+ }
273
+ const xs = refX[comp[i]];
274
+ const target = seedX[i] + Math.exp(logMin + rand() * (logMax - logMin)) * (rand() < 0.5 ? -1 : 1);
243
275
  let lo = 0;
244
- let hi = refX.length;
276
+ let hi = xs.length;
245
277
  while (lo < hi) {
246
278
  const mid = lo + hi >> 1;
247
- if (refX[mid] < target) {
279
+ if (xs[mid] < target) {
248
280
  lo = mid + 1;
249
281
  } else {
250
282
  hi = mid;
251
283
  }
252
284
  }
253
- return refIdx[Math.min(lo, refIdx.length - 1)];
254
- };
255
- const referenceTerm = (i, eta) => {
256
- if (!backbone[i] || refIdx.length < 2 || Number.isNaN(seedX[i])) {
285
+ const j = idx[Math.min(lo, idx.length - 1)];
286
+ const d = seedX[j] - seedX[i];
287
+ if (j === i || d === 0) {
257
288
  return;
258
289
  }
259
- const j = refPartner(i);
260
- const d = Math.abs(seedX[i] - seedX[j]);
261
- if (j !== i && d > 0) {
262
- move(i, j, d, eta);
290
+ let mu = eta / (d * d);
291
+ if (mu > 1) {
292
+ mu = 1;
263
293
  }
294
+ const r = mu * (X[j] - X[i] - d) / 2;
295
+ X[i] = X[i] + r;
296
+ X[j] = X[j] - r;
264
297
  };
265
298
  const adjacentTerms = (i, eta) => {
266
299
  for (let e = off[i]; e < off[i + 1]; e++) {
@@ -274,7 +307,8 @@ function stressLayout(request, opts = {}) {
274
307
  for (let i = 0; i < n; i++) {
275
308
  order[i] = i;
276
309
  }
277
- for (let t = 0; t < iterations; t++) {
310
+ const warm = anySeed ? Math.floor(WARM * iterations) : 0;
311
+ for (let t = warm; t < iterations; t++) {
278
312
  const eta = etaMax * Math.exp(-lambda * t);
279
313
  for (let k = n - 1; k > 0; k--) {
280
314
  const r = Math.floor(rand() * (k + 1));
@@ -288,15 +322,15 @@ function stressLayout(request, opts = {}) {
288
322
  for (let w = 0; w < walks; w++) {
289
323
  const length = Math.exp(logMin + rand() * (logMax - logMin));
290
324
  const j = walk(i, length);
291
- if (j >= 0 && j !== i) {
292
- move(i, j, length, eta);
325
+ if (j >= 0 && j !== i && walked > 0) {
326
+ move(i, j, walked, eta);
293
327
  }
294
328
  }
295
329
  referenceTerm(i, eta);
296
330
  }
297
331
  }
298
- const cell = UNTANGLE_RADIUS;
299
- const key = (x, y) => Math.floor(x / cell) * 73856093 ^ Math.floor(y / cell) * 19349663;
332
+ const radius = UNTANGLE_LINKS * link;
333
+ const key = (x, y) => Math.floor(x / radius) * 73856093 ^ Math.floor(y / radius) * 19349663;
300
334
  for (let u = 0; u < UNTANGLE_PASSES; u++) {
301
335
  const grid = /* @__PURE__ */ new Map();
302
336
  for (let i = 0; i < n; i++) {
@@ -309,8 +343,8 @@ function stressLayout(request, opts = {}) {
309
343
  }
310
344
  }
311
345
  for (let i = 0; i < n; i++) {
312
- const cx = Math.floor(X[i] / cell);
313
- const cy = Math.floor(Y[i] / cell);
346
+ const cx = Math.floor(X[i] / radius);
347
+ const cy = Math.floor(Y[i] / radius);
314
348
  for (let gx = cx - 1; gx <= cx + 1; gx++) {
315
349
  for (let gy = cy - 1; gy <= cy + 1; gy++) {
316
350
  const list = grid.get(gx * 73856093 ^ gy * 19349663);
@@ -334,18 +368,18 @@ function stressLayout(request, opts = {}) {
334
368
  const dx = X[i] - X[j];
335
369
  const dy = Y[i] - Y[j];
336
370
  const mag = Math.sqrt(dx * dx + dy * dy);
337
- if (mag >= UNTANGLE_RADIUS) {
371
+ if (mag >= radius) {
338
372
  continue;
339
373
  }
340
374
  let rx;
341
375
  let ry;
342
376
  if (mag > 1e-6) {
343
- const r = UNTANGLE_PUSH * (UNTANGLE_RADIUS - mag) / (2 * mag);
377
+ const r = UNTANGLE_PUSH * (radius - mag) / (2 * mag);
344
378
  rx = r * dx;
345
379
  ry = r * dy;
346
380
  } else {
347
- rx = UNTANGLE_PUSH * UNTANGLE_RADIUS * (rand() - 0.5);
348
- ry = UNTANGLE_PUSH * UNTANGLE_RADIUS * (rand() - 0.5);
381
+ rx = UNTANGLE_PUSH * radius * (rand() - 0.5);
382
+ ry = UNTANGLE_PUSH * radius * (rand() - 0.5);
349
383
  }
350
384
  X[i] = X[i] + rx;
351
385
  Y[i] = Y[i] + ry;
@@ -374,28 +408,9 @@ function stressLayout(request, opts = {}) {
374
408
  Y[a + i] = 0.5 * ys[i] + 0.25 * (ys[i - 1] + ys[i + 1]);
375
409
  }
376
410
  }
377
- let length = 0;
378
- let cx = 0;
379
- let cy = 0;
380
- for (let i = 0; i < m; i++) {
381
- cx += X[a + i];
382
- cy += Y[a + i];
383
- if (i > 0) {
384
- length += Math.hypot(
385
- X[a + i] - X[a + i - 1],
386
- Y[a + i] - Y[a + i - 1]
387
- );
388
- }
389
- }
390
- cx /= m;
391
- cy /= m;
392
- const scale = length > 0 ? per[k] * (m - 1) / length : 1;
393
- for (let i = 0; i < m; i++) {
394
- X[a + i] = cx + (X[a + i] - cx) * scale;
395
- Y[a + i] = cy + (Y[a + i] - cy) * scale;
396
- }
411
+ respace(X, Y, a, m, per[k]);
397
412
  }
398
- packComponents(c, X, Y, anySeed, gap);
413
+ packComponents(comp, members, X, Y, anySeed, gap);
399
414
  for (let k = 0; k < c.ids.length; k++) {
400
415
  const points = [];
401
416
  for (let i = 0; i < count[k]; i++) {
@@ -405,99 +420,110 @@ function stressLayout(request, opts = {}) {
405
420
  }
406
421
  return { nodePositions };
407
422
  }
408
- function packComponents(c, X, Y, anySeed, gap) {
409
- const { n, off, nb } = c;
410
- const comp = new Int32Array(n).fill(-1);
411
- let components = 0;
412
- for (let s = 0; s < n; s++) {
413
- if (comp[s] >= 0) {
414
- continue;
423
+ function respace(X, Y, a, m, per) {
424
+ const arc = new Float64Array(m);
425
+ for (let i = 1; i < m; i++) {
426
+ arc[i] = arc[i - 1] + Math.hypot(X[a + i] - X[a + i - 1], Y[a + i] - Y[a + i - 1]);
427
+ }
428
+ if (!arc[m - 1]) {
429
+ return;
430
+ }
431
+ const loss = per * (m - 1) - arc[m - 1];
432
+ if (loss > 0) {
433
+ extend(X, Y, a, a + 1, loss / 2);
434
+ extend(X, Y, a + m - 1, a + m - 2, loss / 2);
435
+ for (let i = 1; i < m; i++) {
436
+ arc[i] = arc[i - 1] + Math.hypot(X[a + i] - X[a + i - 1], Y[a + i] - Y[a + i - 1]);
415
437
  }
416
- const queue = [s];
417
- comp[s] = components;
418
- for (const u of queue) {
419
- for (let e = off[u]; e < off[u + 1]; e++) {
420
- const v = nb[e];
421
- if (comp[v] < 0) {
422
- comp[v] = components;
423
- queue.push(v);
424
- }
425
- }
438
+ }
439
+ const total = arc[m - 1];
440
+ const xs = X.slice(a, a + m);
441
+ const ys = Y.slice(a, a + m);
442
+ let seg = 1;
443
+ for (let i = 1; i + 1 < m; i++) {
444
+ const s = total * i / (m - 1);
445
+ while (seg < m - 1 && arc[seg] < s) {
446
+ seg++;
426
447
  }
427
- components++;
448
+ const span = arc[seg] - arc[seg - 1];
449
+ const t = span > 0 ? (s - arc[seg - 1]) / span : 0;
450
+ X[a + i] = xs[seg - 1] + (xs[seg] - xs[seg - 1]) * t;
451
+ Y[a + i] = ys[seg - 1] + (ys[seg] - ys[seg - 1]) * t;
428
452
  }
453
+ }
454
+ function extend(X, Y, end, next, by) {
455
+ const dx = X[end] - X[next];
456
+ const dy = Y[end] - Y[next];
457
+ const mag = Math.hypot(dx, dy);
458
+ if (mag > 0) {
459
+ X[end] = X[end] + dx / mag * by;
460
+ Y[end] = Y[end] + dy / mag * by;
461
+ }
462
+ }
463
+ function packComponents(comp, members, X, Y, anySeed, gap) {
429
464
  if (!anySeed) {
430
- for (let k = 0; k < components; k++) {
431
- rotateToPrincipalAxis(X, Y, comp, k);
465
+ for (const points of members) {
466
+ rotateToPrincipalAxis(X, Y, points);
432
467
  }
433
468
  }
434
- if (components < 2) {
469
+ if (members.length < 2) {
435
470
  return;
436
471
  }
437
- const minX = new Float64Array(components).fill(Infinity);
438
- const minY = new Float64Array(components).fill(Infinity);
439
- const maxY = new Float64Array(components).fill(-Infinity);
440
- for (let i = 0; i < n; i++) {
472
+ const minX = new Float64Array(members.length).fill(Infinity);
473
+ const minY = new Float64Array(members.length).fill(Infinity);
474
+ const maxY = new Float64Array(members.length).fill(-Infinity);
475
+ for (let i = 0; i < X.length; i++) {
441
476
  const k = comp[i];
442
477
  minX[k] = Math.min(minX[k], X[i]);
443
478
  minY[k] = Math.min(minY[k], Y[i]);
444
479
  maxY[k] = Math.max(maxY[k], Y[i]);
445
480
  }
446
- const shift = new Float64Array(components);
481
+ const shift = new Float64Array(members.length);
447
482
  let y = 0;
448
- for (let k = 0; k < components; k++) {
483
+ for (let k = 0; k < members.length; k++) {
449
484
  shift[k] = y - minY[k];
450
485
  y += maxY[k] - minY[k] + gap;
451
486
  }
452
- for (let i = 0; i < n; i++) {
487
+ for (let i = 0; i < X.length; i++) {
453
488
  const k = comp[i];
454
489
  X[i] = X[i] - minX[k];
455
490
  Y[i] = Y[i] + shift[k];
456
491
  }
457
492
  }
458
- function rotateToPrincipalAxis(X, Y, comp, k) {
459
- let m = 0;
493
+ function rotateToPrincipalAxis(X, Y, points) {
494
+ if (points.length < 3) {
495
+ return;
496
+ }
460
497
  let cx = 0;
461
498
  let cy = 0;
462
- for (let i = 0; i < X.length; i++) {
463
- if (comp[i] === k) {
464
- cx += X[i];
465
- cy += Y[i];
466
- m++;
467
- }
468
- }
469
- if (m < 3) {
470
- return;
499
+ for (const i of points) {
500
+ cx += X[i];
501
+ cy += Y[i];
471
502
  }
472
- cx /= m;
473
- cy /= m;
503
+ cx /= points.length;
504
+ cy /= points.length;
474
505
  let sxx = 0;
475
506
  let syy = 0;
476
507
  let sxy = 0;
477
- for (let i = 0; i < X.length; i++) {
478
- if (comp[i] === k) {
479
- const dx = X[i] - cx;
480
- const dy = Y[i] - cy;
481
- sxx += dx * dx;
482
- syy += dy * dy;
483
- sxy += dx * dy;
484
- }
508
+ for (const i of points) {
509
+ const dx = X[i] - cx;
510
+ const dy = Y[i] - cy;
511
+ sxx += dx * dx;
512
+ syy += dy * dy;
513
+ sxy += dx * dy;
485
514
  }
486
515
  const angle = -0.5 * Math.atan2(2 * sxy, sxx - syy);
487
516
  const cos = Math.cos(angle);
488
517
  const sin = Math.sin(angle);
489
- for (let i = 0; i < X.length; i++) {
490
- if (comp[i] === k) {
491
- const dx = X[i] - cx;
492
- const dy = Y[i] - cy;
493
- X[i] = cx + cos * dx - sin * dy;
494
- Y[i] = cy + sin * dx + cos * dy;
495
- }
518
+ for (const i of points) {
519
+ const dx = X[i] - cx;
520
+ const dy = Y[i] - cy;
521
+ X[i] = cx + cos * dx - sin * dy;
522
+ Y[i] = cy + sin * dx + cos * dy;
496
523
  }
497
524
  }
498
525
 
499
526
  export {
500
- LAYOUT_ENGINES,
501
- LAYOUT_ENGINE_VALUES,
527
+ chains,
502
528
  stressLayout
503
529
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clampZoom
3
- } from "./chunk-6UFS3EWI.js";
3
+ } from "./chunk-EPWYRSHH.js";
4
4
 
5
5
  // src/viewport.ts
6
6
  function axisScaleOf(scale, pixelRows) {
@@ -5,9 +5,12 @@ import {
5
5
  genesFromText
6
6
  } from "../chunks/chunk-BXEPA4KS.js";
7
7
  import {
8
+ LAYOUT_ENGINE_VALUES,
9
+ isLayoutEngineKind,
8
10
  layoutEngine
9
- } from "../chunks/chunk-L53SXJZI.js";
10
- import "../chunks/chunk-O4TGF4WS.js";
11
+ } from "../chunks/chunk-6EJIU6IA.js";
12
+ import "../chunks/chunk-UNOE2NDN.js";
13
+ import "../chunks/chunk-LYJ4US66.js";
11
14
  import {
12
15
  LAYOUT_MODES,
13
16
  layoutModeByValue
@@ -23,32 +26,31 @@ import "../chunks/chunk-C44YRP5F.js";
23
26
  import "../chunks/chunk-7XHHVYG7.js";
24
27
  import {
25
28
  figureSvg
26
- } from "../chunks/chunk-2WA4EY25.js";
29
+ } from "../chunks/chunk-QMJ4J5PT.js";
30
+ import "../chunks/chunk-CH3DLBUT.js";
31
+ import "../chunks/chunk-4BYTEJGW.js";
27
32
  import "../chunks/chunk-47DYCZOK.js";
28
33
  import "../chunks/chunk-KREASK3Z.js";
29
34
  import {
30
35
  genesOnRow,
31
36
  placeRowGenes
32
37
  } from "../chunks/chunk-UGD6ZMOF.js";
33
- import "../chunks/chunk-CH3DLBUT.js";
34
- import "../chunks/chunk-4BYTEJGW.js";
35
38
  import "../chunks/chunk-3S3YVOJ7.js";
36
39
  import "../chunks/chunk-BUBZ32IC.js";
37
- import "../chunks/chunk-MAPRJ2H2.js";
38
- import "../chunks/chunk-AWCMVPVP.js";
40
+ import "../chunks/chunk-S73EYTZA.js";
41
+ import "../chunks/chunk-Y7UR3MDE.js";
39
42
  import "../chunks/chunk-MH5IA57M.js";
40
43
  import "../chunks/chunk-TQ7VCGJR.js";
41
44
  import "../chunks/chunk-2LQ5BWT7.js";
42
45
  import {
43
46
  forceLayout,
44
47
  loadGraph
45
- } from "../chunks/chunk-6UFS3EWI.js";
48
+ } from "../chunks/chunk-EPWYRSHH.js";
46
49
  import "../chunks/chunk-PUG7LXDF.js";
47
50
  import "../chunks/chunk-IGVV37VI.js";
48
51
  import "../chunks/chunk-72N5DJHZ.js";
49
52
  import "../chunks/chunk-QYBZZI5H.js";
50
53
  import "../chunks/chunk-CDLPYR5O.js";
51
- import "../chunks/chunk-YZ5CCEDH.js";
52
54
  import "../chunks/chunk-VECR253P.js";
53
55
  import "../chunks/chunk-VST5SR4C.js";
54
56
  import "../chunks/chunk-UMNCCYBN.js";
@@ -57,6 +59,7 @@ import "../chunks/chunk-GJMC3PGM.js";
57
59
  import "../chunks/chunk-FP4H7SFT.js";
58
60
  import "../chunks/chunk-MLSWIMZO.js";
59
61
  import "../chunks/chunk-WFB5TXRA.js";
62
+ import "../chunks/chunk-JVLURPFW.js";
60
63
  import "../chunks/chunk-3JANT2SW.js";
61
64
  import {
62
65
  filterSamples,
@@ -202,8 +205,16 @@ function checkLayout(layout) {
202
205
  );
203
206
  }
204
207
  }
208
+ function checkEngine(engine) {
209
+ if (engine !== void 0 && !isLayoutEngineKind(engine)) {
210
+ throw new Error(
211
+ `no "${engine}" layout engine: one of ${LAYOUT_ENGINE_VALUES.join(", ")}`
212
+ );
213
+ }
214
+ }
205
215
  async function renderSpec(spec, base) {
206
216
  checkLayout(spec.layout);
217
+ checkEngine(spec.engine);
207
218
  const resolve = (location) => isUrl(location) ? location : path.resolve(base, location);
208
219
  let source;
209
220
  if (spec.gbz) {
package/dist/figure.js CHANGED
@@ -1,25 +1,24 @@
1
1
  import {
2
2
  figureSvg
3
- } from "./chunks/chunk-2WA4EY25.js";
3
+ } from "./chunks/chunk-QMJ4J5PT.js";
4
+ import "./chunks/chunk-CH3DLBUT.js";
5
+ import "./chunks/chunk-4BYTEJGW.js";
4
6
  import "./chunks/chunk-47DYCZOK.js";
5
7
  import "./chunks/chunk-KREASK3Z.js";
6
8
  import "./chunks/chunk-UGD6ZMOF.js";
7
- import "./chunks/chunk-CH3DLBUT.js";
8
- import "./chunks/chunk-4BYTEJGW.js";
9
9
  import "./chunks/chunk-3S3YVOJ7.js";
10
10
  import "./chunks/chunk-BUBZ32IC.js";
11
- import "./chunks/chunk-MAPRJ2H2.js";
12
- import "./chunks/chunk-AWCMVPVP.js";
11
+ import "./chunks/chunk-S73EYTZA.js";
12
+ import "./chunks/chunk-Y7UR3MDE.js";
13
13
  import "./chunks/chunk-MH5IA57M.js";
14
14
  import "./chunks/chunk-TQ7VCGJR.js";
15
15
  import "./chunks/chunk-2LQ5BWT7.js";
16
- import "./chunks/chunk-6UFS3EWI.js";
16
+ import "./chunks/chunk-EPWYRSHH.js";
17
17
  import "./chunks/chunk-PUG7LXDF.js";
18
18
  import "./chunks/chunk-IGVV37VI.js";
19
19
  import "./chunks/chunk-72N5DJHZ.js";
20
20
  import "./chunks/chunk-QYBZZI5H.js";
21
21
  import "./chunks/chunk-CDLPYR5O.js";
22
- import "./chunks/chunk-YZ5CCEDH.js";
23
22
  import "./chunks/chunk-VECR253P.js";
24
23
  import "./chunks/chunk-VST5SR4C.js";
25
24
  import "./chunks/chunk-UMNCCYBN.js";
@@ -28,6 +27,7 @@ import "./chunks/chunk-GJMC3PGM.js";
28
27
  import "./chunks/chunk-FP4H7SFT.js";
29
28
  import "./chunks/chunk-MLSWIMZO.js";
30
29
  import "./chunks/chunk-WFB5TXRA.js";
30
+ import "./chunks/chunk-JVLURPFW.js";
31
31
  import "./chunks/chunk-3JANT2SW.js";
32
32
  import "./chunks/chunk-SZNZ2T6D.js";
33
33
  import "./chunks/chunk-E7FWQQHP.js";