@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.
- package/dist/chunks/chunk-6EJIU6IA.js +42 -0
- package/dist/chunks/{chunk-6UFS3EWI.js → chunk-EPWYRSHH.js} +1 -1
- package/dist/chunks/{chunk-YZ5CCEDH.js → chunk-JVLURPFW.js} +1 -0
- package/dist/chunks/chunk-LYJ4US66.js +664 -0
- package/dist/chunks/{chunk-2WA4EY25.js → chunk-QMJ4J5PT.js} +6 -6
- package/dist/chunks/{chunk-MAPRJ2H2.js → chunk-S73EYTZA.js} +1 -1
- package/dist/chunks/{chunk-O4TGF4WS.js → chunk-UNOE2NDN.js} +155 -129
- package/dist/chunks/{chunk-AWCMVPVP.js → chunk-Y7UR3MDE.js} +1 -1
- package/dist/cli/figure.js +20 -9
- package/dist/figure.js +7 -7
- package/dist/index.js +15 -14
- package/dist/layout/deletionRoutes.js +3 -1
- package/dist/layout/stressEngine.js +5 -5
- package/dist/layout/stressPlacement.js +7 -0
- package/dist/layoutEngines.js +10 -2
- package/dist/pipeline.js +2 -2
- package/dist/types/cli/figure.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/layout/deletionRoutes.d.ts +1 -0
- package/dist/types/layout/stressEngine.d.ts +19 -11
- package/dist/types/layout/stressPlacement.d.ts +5 -0
- package/dist/types/layoutEngines.d.ts +12 -0
- package/dist/types/pipeline.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/viewport.js +3 -3
- package/package.json +1 -1
- package/dist/chunks/chunk-L53SXJZI.js +0 -22
|
@@ -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-
|
|
27
|
+
} from "./chunk-S73EYTZA.js";
|
|
28
28
|
import {
|
|
29
29
|
axisScaleOf
|
|
30
|
-
} from "./chunk-
|
|
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-
|
|
46
|
+
} from "./chunk-EPWYRSHH.js";
|
|
47
47
|
import {
|
|
48
48
|
buildGeometry,
|
|
49
49
|
computeReferenceRamp
|
|
@@ -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
|
|
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 (
|
|
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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
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 -=
|
|
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
|
|
241
|
-
const
|
|
242
|
-
|
|
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 =
|
|
276
|
+
let hi = xs.length;
|
|
245
277
|
while (lo < hi) {
|
|
246
278
|
const mid = lo + hi >> 1;
|
|
247
|
-
if (
|
|
279
|
+
if (xs[mid] < target) {
|
|
248
280
|
lo = mid + 1;
|
|
249
281
|
} else {
|
|
250
282
|
hi = mid;
|
|
251
283
|
}
|
|
252
284
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
299
|
-
const key = (x, y) => Math.floor(x /
|
|
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] /
|
|
313
|
-
const cy = Math.floor(Y[i] /
|
|
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 >=
|
|
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 * (
|
|
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 *
|
|
348
|
-
ry = UNTANGLE_PUSH *
|
|
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
|
-
|
|
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(
|
|
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
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
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
|
-
|
|
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 (
|
|
431
|
-
rotateToPrincipalAxis(X, Y,
|
|
465
|
+
for (const points of members) {
|
|
466
|
+
rotateToPrincipalAxis(X, Y, points);
|
|
432
467
|
}
|
|
433
468
|
}
|
|
434
|
-
if (
|
|
469
|
+
if (members.length < 2) {
|
|
435
470
|
return;
|
|
436
471
|
}
|
|
437
|
-
const minX = new Float64Array(
|
|
438
|
-
const minY = new Float64Array(
|
|
439
|
-
const maxY = new Float64Array(
|
|
440
|
-
for (let i = 0; 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(
|
|
481
|
+
const shift = new Float64Array(members.length);
|
|
447
482
|
let y = 0;
|
|
448
|
-
for (let k = 0; 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 <
|
|
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,
|
|
459
|
-
|
|
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 (
|
|
463
|
-
|
|
464
|
-
|
|
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 /=
|
|
473
|
-
cy /=
|
|
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 (
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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 (
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
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
|
-
|
|
501
|
-
LAYOUT_ENGINE_VALUES,
|
|
527
|
+
chains,
|
|
502
528
|
stressLayout
|
|
503
529
|
};
|
package/dist/cli/figure.js
CHANGED
|
@@ -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-
|
|
10
|
-
import "../chunks/chunk-
|
|
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-
|
|
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-
|
|
38
|
-
import "../chunks/chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
12
|
-
import "./chunks/chunk-
|
|
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-
|
|
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";
|