@jbrowse/bandage-core 0.1.16 → 0.1.18

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/README.md CHANGED
@@ -9,11 +9,13 @@ npm install @jbrowse/bandage-core
9
9
  ```
10
10
 
11
11
  - GFA and rGFA text in (`loadGraph`)
12
- - Layouts: Bandage's FMMM engine as WASM (`loadBandage`, `forceLayout`), variant
13
- map, ordered, anchored, sample rows, walk rows, tube map
12
+ - Layouts: Bandage's FMMM engine as WASM (`loadBandage`, `forceLayout`),
13
+ ordered, anchored, sample rows, walk rows, tube map
14
14
  - A Canvas2D renderer (`buildGeometry`, `Canvas2DRenderer`), hit testing and
15
15
  label placement
16
16
  - Bubbles, deletion edges, path colors, gbz-base windows cut to GFA
17
+ - Walks lifted out of the drawing (`walkLift`), one facet panel per walk
18
+ (`facetLifts`, `facetGrid`) and each walk's key in words (`walkKey`)
17
19
  - Which assembly a backbone lies on (`graphBackbone`, `backboneAssembly`,
18
20
  `assemblyWalk`), and the genes on it: `featuresOnBackbone` renames an
19
21
  assembly's genes onto the backbone's refNames, and `genePins` pins only those
package/dist/index.js CHANGED
@@ -979,9 +979,15 @@ function fittedTranslateY(bounds, usableHeight, yScale, padTop = FIT_PADDING) {
979
979
  const leftoverY = usableHeight - bounds.h * yScale;
980
980
  return padTop - bounds.minY * yScale + Math.max(0, leftoverY) / 2;
981
981
  }
982
- function fitTransform(bounds, paneWidth, paneHeight, pixelRows, { minScale = 0, padLeft = FIT_PADDING, padTop = FIT_PADDING } = {}) {
983
- const usableWidth = paneWidth - padLeft - FIT_PADDING;
984
- const usableHeight = paneHeight - padTop - FIT_PADDING;
982
+ function fitTransform(bounds, paneWidth, paneHeight, pixelRows, {
983
+ minScale = 0,
984
+ padLeft = FIT_PADDING,
985
+ padTop = FIT_PADDING,
986
+ padRight = FIT_PADDING,
987
+ padBottom = FIT_PADDING
988
+ } = {}) {
989
+ const usableWidth = paneWidth - padLeft - padRight;
990
+ const usableHeight = paneHeight - padTop - padBottom;
985
991
  if (usableWidth <= 0 || usableHeight <= 0 || !(bounds.w > 0 || !pixelRows && bounds.h > 0)) {
986
992
  return void 0;
987
993
  }
@@ -2855,10 +2861,11 @@ var EDGE_DEFAULT_COLOR = packAbgr2(119, 119, 119, 217);
2855
2861
  var EDGE_PATH_FALLBACK_COLOR = packAbgr2(136, 136, 136, 217);
2856
2862
  var EDGE_DELETION_COLOR = packAbgr2(24, 24, 28, 240);
2857
2863
  var DELETION_THICKNESS_FACTOR = 2.2;
2864
+ var LIFT_BACKDROP_COLOR = packAbgr2(160, 160, 160, 255);
2858
2865
  var FADED_ALPHA = 0.18;
2859
2866
  var DELETION_DASH_PX = 11;
2860
2867
  var MIN_PATH_STRIPE_PX = 1.2;
2861
- var MIN_WALK_LANE_PX = 3;
2868
+ var MIN_WALK_LANE_PX = 4;
2862
2869
  var MIN_SCALE_FOR_OFFSET = 1e-6;
2863
2870
  var ARROW_LENGTH_BASE_PX = 7;
2864
2871
  var ARROW_LENGTH_PER_EDGE_PX = 3;
@@ -3445,13 +3452,13 @@ function buildGeometry(options) {
3445
3452
  if (viewportBounds && !isPolylineInBounds(segments, viewportBounds)) {
3446
3453
  continue;
3447
3454
  }
3448
- const own = getNodeColor(
3455
+ const faded = highlight !== void 0 && !highlight.nodeIds.has(nodeId);
3456
+ const own = faded ? LIFT_BACKDROP_COLOR : getNodeColor(
3449
3457
  node,
3450
3458
  nodeIndexMap.get(nodeId) ?? 0,
3451
3459
  colorScheme,
3452
3460
  colorRange
3453
3461
  );
3454
- const faded = highlight !== void 0 && !highlight.nodeIds.has(nodeId);
3455
3462
  const color = faded ? fadeAbgr(own, FADED_ALPHA) : own;
3456
3463
  const width = nodeWidthPx(node, contigThickness, nodeWidth2, depthNorm);
3457
3464
  const nodeThickness = width / 2;
@@ -4081,13 +4088,14 @@ var OVERHANG_PX = 5;
4081
4088
  function referenceStripBlocks(graph, {
4082
4089
  colorScheme,
4083
4090
  referenceRamp,
4084
- walkNodes
4091
+ walkNodes,
4092
+ walkColors
4085
4093
  }) {
4086
4094
  const range = { ...computeColorSchemeRange(graph), referenceRamp };
4087
4095
  const out = [];
4088
4096
  graph.nodes.forEach((node, index) => {
4089
4097
  if (isBackbone(node)) {
4090
- const own = getNodeColor(node, index, colorScheme, range);
4098
+ const own = walkNodes ? walkColors?.get(node.id) ?? LIFT_BACKDROP_COLOR : getNodeColor(node, index, colorScheme, range);
4091
4099
  out.push({
4092
4100
  node: node.id,
4093
4101
  bp0: node.stable.start,
@@ -5243,81 +5251,79 @@ function drawTubeMapConnectors(ctx, connectors, bottom, {
5243
5251
  // src/walkEncoding.ts
5244
5252
  import { packAbgr as packAbgr3 } from "@jbrowse/core/util/colorBits";
5245
5253
  var WALK_FIELDS = [
5246
- {
5247
- value: "progress",
5248
- label: "Progress along the walk",
5249
- legend: "pale where the walk starts, deep where it ends"
5250
- },
5251
- {
5252
- value: "reference",
5253
- label: "Reference position",
5254
- legend: "along the reference left to right, charcoal off it"
5255
- },
5256
- {
5257
- value: "strand",
5258
- label: "Strand against the reference",
5259
- legend: "pale where the walk runs as the reference does, deep where reversed"
5260
- },
5261
- {
5262
- value: "visits",
5263
- label: "Visits",
5264
- legend: "pale where the walk passes once, deep four times or more"
5265
- }
5254
+ { value: "progress", label: "Progress along the walk" },
5255
+ { value: "walk", label: "One colour for the walk" },
5256
+ { value: "reference", label: "Reference position" }
5266
5257
  ];
5267
5258
  var WALK_SCHEMES = [
5268
- { value: "rainbow", label: "Rainbow" },
5269
- { value: "blues", label: "Blues", hue: 215 },
5270
- { value: "reds", label: "Reds", hue: 0 },
5271
- { value: "greens", label: "Greens", hue: 130 },
5272
- { value: "oranges", label: "Oranges", hue: 30 },
5273
- { value: "purples", label: "Purples", hue: 280 },
5274
- { value: "greys", label: "Greys" }
5275
- ];
5276
- var DEFAULT_FAMILIES = [
5277
- "blues",
5278
- "reds",
5279
- "greens",
5280
- "oranges",
5281
- "purples"
5259
+ { value: "grey", label: "Grey to black", ends: ["#a3a3a3", "#151515"] },
5260
+ { value: "blue", label: "Cyan to navy", ends: ["#6ee0f0", "#0b2c7a"] },
5261
+ { value: "red", label: "Yellow to red", ends: ["#ffd24a", "#b3121b"] },
5262
+ { value: "purple", label: "Pink to plum", ends: ["#f5a3d8", "#5e1a6e"] },
5263
+ { value: "green", label: "Lime to forest", ends: ["#b6e36c", "#0b5d3b"] },
5264
+ { value: "rainbow", label: "Rainbow" }
5282
5265
  ];
5283
- function resolveEncoding(layer, reference, picked) {
5284
- return {
5285
- field: layer.color?.field ?? (reference ? "reference" : "progress"),
5286
- scheme: layer.color?.scheme ?? (reference ? "rainbow" : DEFAULT_FAMILIES[picked % DEFAULT_FAMILIES.length])
5287
- };
5266
+ var FAMILIES = ["blue", "red", "purple", "green"];
5267
+ var isField = (v) => WALK_FIELDS.some((f) => f.value === v);
5268
+ var isScheme = (v) => WALK_SCHEMES.some((s) => s.value === v);
5269
+ function resolveEncoding(layer, reference, picked, alone = true) {
5270
+ const { field: askedField, scheme: askedScheme } = layer.color ?? {};
5271
+ const field = isField(askedField) ? askedField : alone ? "progress" : "walk";
5272
+ const family = reference ? "grey" : FAMILIES[picked % FAMILIES.length];
5273
+ const scheme = isScheme(askedScheme) ? askedScheme === "rainbow" && field !== "reference" ? family : askedScheme : family;
5274
+ return { field, scheme };
5275
+ }
5276
+ var BASE_T = 0.5;
5277
+ var toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
5278
+ var toGamma = (c) => c <= 31308e-7 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;
5279
+ function oklab(hex) {
5280
+ const [r, g, b] = [1, 3, 5].map(
5281
+ (i) => toLinear(Number.parseInt(hex.slice(i, i + 2), 16) / 255)
5282
+ );
5283
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
5284
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
5285
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
5286
+ return [
5287
+ 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
5288
+ 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
5289
+ 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
5290
+ ];
5288
5291
  }
5289
- var PALE = 0.82;
5290
- var DEEP = 0.28;
5291
- function schemeHsl(scheme, t) {
5292
+ function oklabToRgb([L, a, b]) {
5293
+ const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
5294
+ const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
5295
+ const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
5296
+ return [
5297
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
5298
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
5299
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
5300
+ ].map((c) => toGamma(Math.max(0, Math.min(1, c))) * 255);
5301
+ }
5302
+ function schemeRgb(scheme, t) {
5292
5303
  const x = Math.max(0, Math.min(1, t));
5293
- if (scheme === "rainbow") {
5294
- return { h: x * REFERENCE_RAMP_MAX_HUE, s: 0.7, l: 0.5 };
5295
- }
5296
5304
  const family = WALK_SCHEMES.find((s) => s.value === scheme);
5297
- const l = PALE + (DEEP - PALE) * x;
5298
- return family && "hue" in family ? { h: family.hue, s: 0.75, l } : { h: 0, s: 0, l };
5305
+ if (!family || !("ends" in family)) {
5306
+ return hslToRgb(x * REFERENCE_RAMP_MAX_HUE, 0.7, 0.5).map((c) => c * 255);
5307
+ }
5308
+ const from = oklab(family.ends[0]);
5309
+ const to = oklab(family.ends[1]);
5310
+ return oklabToRgb(from.map((v, i) => v + (to[i] - v) * x));
5299
5311
  }
5300
5312
  function schemeCss(scheme, t) {
5301
- const { h, s, l } = schemeHsl(scheme, t);
5302
- return `hsl(${h}, ${s * 100}%, ${l * 100}%)`;
5313
+ const [r, g, b] = schemeRgb(scheme, t).map(Math.round);
5314
+ return `rgb(${r}, ${g}, ${b})`;
5303
5315
  }
5304
5316
  function schemeColor(scheme, t) {
5305
- const { h, s, l } = schemeHsl(scheme, t);
5306
- const [r, g, b] = hslToRgb(h, s, l);
5307
- return packAbgr3(
5308
- Math.round(r * 255),
5309
- Math.round(g * 255),
5310
- Math.round(b * 255),
5311
- 255
5312
- );
5317
+ const [r, g, b] = schemeRgb(scheme, t).map(Math.round);
5318
+ return packAbgr3(r, g, b, 255);
5319
+ }
5320
+ function encodedColor({ field, scheme }, t) {
5321
+ return field === "walk" ? schemeColor(scheme, BASE_T) : t === void 0 ? NO_VALUE_COLOR : schemeColor(scheme, t);
5313
5322
  }
5314
5323
  var NO_VALUE_COLOR = REFERENCE_RAMP_ALT_COLOR;
5315
- var STRAND_T = { same: 0.2, reversed: 0.95 };
5316
5324
  function encodingSwatchCss({ field, scheme }) {
5317
- if (field === "strand") {
5318
- const same = schemeCss(scheme, STRAND_T.same);
5319
- const reversed = schemeCss(scheme, STRAND_T.reversed);
5320
- return `linear-gradient(to right, ${same} 50%, ${reversed} 50%)`;
5325
+ if (field === "walk") {
5326
+ return schemeCss(scheme, BASE_T);
5321
5327
  }
5322
5328
  const stops = Array.from({ length: 7 }, (_, i) => {
5323
5329
  const t = i / 6;
@@ -5325,9 +5331,6 @@ function encodingSwatchCss({ field, scheme }) {
5325
5331
  });
5326
5332
  return `linear-gradient(to right, ${stops.join(", ")})`;
5327
5333
  }
5328
- function fieldLegend(field) {
5329
- return WALK_FIELDS.find((f) => f.value === field).legend;
5330
- }
5331
5334
 
5332
5335
  // src/walkHighlight.ts
5333
5336
  function referenceOf(graph) {
@@ -5364,9 +5367,16 @@ function walkHighlight(graph, name) {
5364
5367
  before += length;
5365
5368
  }
5366
5369
  const reference = referenceOf(graph);
5370
+ const originName = pathOrigin(name).name;
5371
+ const origin = graph.anchorPaths?.find((a) => a.name === originName && a.length === bp) ?? graph.anchorPaths?.find((a) => a.name === originName);
5367
5372
  return {
5368
5373
  name,
5369
5374
  reference: reference === path,
5375
+ range: origin ? {
5376
+ contig: path.contig ?? panSNContig(origin.name),
5377
+ start: origin.start,
5378
+ end: origin.start + origin.length
5379
+ } : void 0,
5370
5380
  nodeIds: new Set(path.nodeIds),
5371
5381
  edgeIndexes,
5372
5382
  progress,
@@ -5375,37 +5385,39 @@ function walkHighlight(graph, name) {
5375
5385
  referenceBp: reference && reference !== path ? reference.nodeIds.reduce((sum, id) => sum + lengthOf(id), 0) : void 0
5376
5386
  };
5377
5387
  }
5378
- function laneColors(graph, walk, { field, scheme }, ramp) {
5379
- const colors = /* @__PURE__ */ new Map();
5388
+ function laneColors(graph, walk, encoding, ramp) {
5380
5389
  const byId = new Map(graph.nodes.map((n) => [n.id, n]));
5381
- const walkPath = pathOrigin(walk.name).name;
5382
- const reference = referenceOf(graph);
5383
- const referencePath = reference ? pathOrigin(reference.name).name : void 0;
5384
- const path = graph.paths.find((p) => p.name === walk.name);
5385
- const visits = /* @__PURE__ */ new Map();
5386
- for (const id of path.nodeIds) {
5387
- visits.set(id, (visits.get(id) ?? 0) + 1);
5388
- }
5389
- const strandOf = (segment, of) => graph.pathVisits?.get(segment)?.find((v) => v.path === of)?.strand;
5390
+ const colors = /* @__PURE__ */ new Map();
5390
5391
  for (const [id, progress] of walk.progress) {
5391
5392
  const node = byId.get(id);
5392
- let t;
5393
- if (field === "progress") {
5394
- t = progress;
5395
- } else if (field === "visits") {
5396
- t = (Math.min(visits.get(id) ?? 1, 4) - 1) / 3;
5397
- } else if (field === "reference") {
5398
- const mid = ramp?.midpoints.get(id);
5399
- t = ramp && mid !== void 0 && !(node?.stable && node.stable.rank > 0) ? (mid - ramp.start) / ramp.span : void 0;
5400
- } else if (node) {
5401
- const own = strandOf(node.name, walkPath);
5402
- const theirs = strandOf(node.name, referencePath);
5403
- t = own && theirs ? own === theirs ? STRAND_T.same : STRAND_T.reversed : void 0;
5404
- }
5405
- colors.set(id, t === void 0 ? NO_VALUE_COLOR : schemeColor(scheme, t));
5393
+ const mid = ramp?.midpoints.get(id);
5394
+ const t = encoding.field === "progress" ? progress : ramp && mid !== void 0 && !(node?.stable && node.stable.rank > 0) ? (mid - ramp.start) / ramp.span : void 0;
5395
+ colors.set(id, encodedColor(encoding, t));
5406
5396
  }
5407
5397
  return colors;
5408
5398
  }
5399
+ function reversedNodes(graph, walk) {
5400
+ const reference = referenceOf(graph);
5401
+ const reversed = /* @__PURE__ */ new Set();
5402
+ let bp = 0;
5403
+ if (!reference || walk.reference) {
5404
+ return { reversed, bp };
5405
+ }
5406
+ const walkPath = pathOrigin(walk.name).name;
5407
+ const referencePath = pathOrigin(reference.name).name;
5408
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
5409
+ for (const id of walk.progress.keys()) {
5410
+ const node = byId.get(id);
5411
+ const visits = node ? graph.pathVisits?.get(node.name) : void 0;
5412
+ const own = visits?.find((v) => v.path === walkPath)?.strand;
5413
+ const theirs = visits?.find((v) => v.path === referencePath)?.strand;
5414
+ if (own && theirs && own !== theirs) {
5415
+ reversed.add(id);
5416
+ bp += node.length;
5417
+ }
5418
+ }
5419
+ return { reversed, bp };
5420
+ }
5409
5421
  function walkLift(graph, layers, ramp) {
5410
5422
  const seen = /* @__PURE__ */ new Set();
5411
5423
  const lifted = layers.filter((layer) => !seen.has(layer.walk) && seen.add(layer.walk)).flatMap((layer) => {
@@ -5420,22 +5432,120 @@ function walkLift(graph, layers, ramp) {
5420
5432
  const encoding = resolveEncoding(
5421
5433
  layer,
5422
5434
  walk.reference,
5423
- walk.reference ? 0 : picked++
5435
+ walk.reference ? 0 : picked++,
5436
+ lifted.length === 1
5424
5437
  );
5438
+ const { reversed, bp } = reversedNodes(graph, walk);
5425
5439
  return {
5426
5440
  ...walk,
5427
5441
  encoding,
5428
- colors: laneColors(graph, walk, encoding, ramp)
5442
+ colors: laneColors(graph, walk, encoding, ramp),
5443
+ reversed,
5444
+ reversedBp: bp
5429
5445
  };
5430
5446
  });
5447
+ return liftOf(walks, ramp);
5448
+ }
5449
+ var FACET_COLOR = { field: "progress", scheme: "red" };
5450
+ function facetLifts(graph, lift, layers, ramp) {
5451
+ return lift.walks.map((walk) => {
5452
+ const stated = layers.find((l) => l.walk === walk.name)?.color;
5453
+ const encoding = resolveEncoding(
5454
+ { walk: walk.name, color: { ...FACET_COLOR, ...stated } },
5455
+ walk.reference,
5456
+ 0
5457
+ );
5458
+ return liftOf(
5459
+ [
5460
+ {
5461
+ ...walk,
5462
+ encoding,
5463
+ colors: laneColors(graph, walk, encoding, ramp)
5464
+ }
5465
+ ],
5466
+ ramp
5467
+ );
5468
+ });
5469
+ }
5470
+ function liftOf(walks, ramp) {
5431
5471
  return {
5432
5472
  walks,
5473
+ referenceDomain: ramp ? { start: ramp.start, end: ramp.start + ramp.span } : void 0,
5433
5474
  nodeIds: new Set(walks.flatMap((w) => [...w.nodeIds])),
5434
5475
  edgeIndexes: new Set(walks.flatMap((w) => [...w.edgeIndexes])),
5435
5476
  names: new Set(walks.map((w) => w.name))
5436
5477
  };
5437
5478
  }
5438
5479
 
5480
+ // src/walkKey.ts
5481
+ function rangeText(contig, start, end) {
5482
+ const s = Math.round(start);
5483
+ const e = Math.round(end);
5484
+ return `${contig ? `${contig}:` : ""}${s.toLocaleString()}-${e.toLocaleString()} (${formatBp(e - s)})`;
5485
+ }
5486
+ function walkKey(walk, reference) {
5487
+ const { field } = walk.encoding;
5488
+ const own = walk.range ? rangeText(walk.range.contig, walk.range.start, walk.range.end) : void 0;
5489
+ const scale = field === "progress" ? own : field === "reference" && reference ? rangeText(reference.name, reference.start, reference.end) : void 0;
5490
+ return {
5491
+ delta: walk.referenceBp === void 0 || walk.bp === walk.referenceBp ? "" : ` ${walk.bp > walk.referenceBp ? "+" : "\u2212"}${formatBp(Math.abs(walk.bp - walk.referenceBp))}`,
5492
+ reversed: walk.reversedBp > 0 ? `, ${formatBp(walk.reversedBp)} reversed` : "",
5493
+ shades: field !== "walk",
5494
+ scale,
5495
+ hover: scale === own ? void 0 : own
5496
+ };
5497
+ }
5498
+
5499
+ // src/facetGrid.ts
5500
+ var FACET_GAP_PX = 8;
5501
+ var FACET_TITLE_PX = 34;
5502
+ var FACET_PAD_PX = 12;
5503
+ var MIN_FACET_PANEL_PX = 60;
5504
+ function facetGrid({
5505
+ count,
5506
+ bounds,
5507
+ pixelRows,
5508
+ width,
5509
+ room,
5510
+ columns
5511
+ }) {
5512
+ function tile(across) {
5513
+ const rows = Math.ceil(count / across);
5514
+ const panelWidth = Math.floor(
5515
+ (width - (across - 1) * FACET_GAP_PX) / across
5516
+ );
5517
+ const panelRoom = (room - rows * FACET_TITLE_PX - (rows - 1) * FACET_GAP_PX) / rows;
5518
+ const fitX = (panelWidth - 2 * FACET_PAD_PX) / bounds.w;
5519
+ const fitY = bounds.h > 0 ? (panelRoom - 2 * FACET_PAD_PX) / bounds.h : Infinity;
5520
+ const scale = pixelRows ? fitX : Math.min(fitX, fitY);
5521
+ const drawn = pixelRows ? bounds.h : bounds.h * scale;
5522
+ const height = Math.floor(
5523
+ Math.max(
5524
+ MIN_FACET_PANEL_PX,
5525
+ Math.min(drawn + 2 * FACET_PAD_PX, panelRoom)
5526
+ )
5527
+ );
5528
+ return {
5529
+ columns: across,
5530
+ width: panelWidth,
5531
+ height,
5532
+ scale,
5533
+ total: rows * (height + FACET_TITLE_PX) + (rows - 1) * FACET_GAP_PX
5534
+ };
5535
+ }
5536
+ if (columns !== void 0) {
5537
+ return tile(Math.max(1, Math.min(count, Math.round(columns))));
5538
+ }
5539
+ let best = tile(1);
5540
+ for (let across = 2; across <= count; across++) {
5541
+ const grid = tile(across);
5542
+ if (grid.scale > best.scale) {
5543
+ best = grid;
5544
+ }
5545
+ }
5546
+ return best;
5547
+ }
5548
+
5439
5549
  // src/bubbles/bubbleLine.ts
5440
5550
  var SATURATED_PATH_COUNT = 2147483647;
5441
5551
 
@@ -6253,6 +6363,9 @@ export {
6253
6363
  BUBBLE_SPREADS,
6254
6364
  COLOR_SCHEMES,
6255
6365
  Canvas2DRenderer,
6366
+ FACET_GAP_PX,
6367
+ FACET_PAD_PX,
6368
+ FACET_TITLE_PX,
6256
6369
  FIT_PADDING,
6257
6370
  FORCE_LAYOUT_LABEL,
6258
6371
  HALO_FACTOR,
@@ -6292,8 +6405,9 @@ export {
6292
6405
  encodingSwatchCss,
6293
6406
  engineKey,
6294
6407
  engineRequest,
6408
+ facetGrid,
6409
+ facetLifts,
6295
6410
  featuresOnBackbone,
6296
- fieldLegend,
6297
6411
  findHoveredEdge,
6298
6412
  findHoveredNode,
6299
6413
  fitTransform,
@@ -6341,6 +6455,7 @@ export {
6341
6455
  tubeX,
6342
6456
  viewportOf,
6343
6457
  walkHighlight,
6458
+ walkKey,
6344
6459
  walkLift,
6345
6460
  walkRows,
6346
6461
  walkRowsExtent,
@@ -0,0 +1,21 @@
1
+ export declare const FACET_GAP_PX = 8;
2
+ export declare const FACET_TITLE_PX = 34;
3
+ export declare const FACET_PAD_PX = 12;
4
+ export interface FacetGrid {
5
+ columns: number;
6
+ width: number;
7
+ height: number;
8
+ scale: number;
9
+ total: number;
10
+ }
11
+ export declare function facetGrid({ count, bounds, pixelRows, width, room, columns, }: {
12
+ count: number;
13
+ bounds: {
14
+ w: number;
15
+ h: number;
16
+ };
17
+ pixelRows: boolean;
18
+ width: number;
19
+ room: number;
20
+ columns?: number;
21
+ }): FacetGrid;
@@ -32,9 +32,12 @@ export type { Connector, ReferenceNode } from './tubeMap/connectors.js';
32
32
  export type { TubeMapColumn, TubeMapDrawing } from './layout/tubeMapLayout.js';
33
33
  export { deletionEdges } from './deletionEdges.js';
34
34
  export type { DeletionEdge } from './deletionEdges.js';
35
- export { walkHighlight, walkLift } from './walkHighlight.js';
35
+ export { facetLifts, walkHighlight, walkLift } from './walkHighlight.js';
36
+ export { walkKey } from './walkKey.js';
37
+ export { FACET_GAP_PX, FACET_PAD_PX, FACET_TITLE_PX, facetGrid, } from './facetGrid.js';
38
+ export type { FacetGrid } from './facetGrid.js';
36
39
  export type { LiftedWalk, WalkLift } from './walkHighlight.js';
37
- export { WALK_FIELDS, WALK_SCHEMES, encodingSwatchCss, fieldLegend, resolveEncoding, schemeCss, } from './walkEncoding.js';
40
+ export { WALK_FIELDS, WALK_SCHEMES, encodingSwatchCss, resolveEncoding, schemeCss, } from './walkEncoding.js';
38
41
  export type { WalkEncoding, WalkField, WalkLayer, WalkScheme, } from './walkEncoding.js';
39
42
  export { pathColorsLegible, pathLegend } from './pathColors.js';
40
43
  export { bubblesFromGraph } from './bubbles/bubblesFromGraph.js';
@@ -60,10 +60,12 @@ export declare function fitTransform(bounds: {
60
60
  minY: number;
61
61
  w: number;
62
62
  h: number;
63
- }, paneWidth: number, paneHeight: number, pixelRows: boolean, { minScale, padLeft, padTop }?: {
63
+ }, paneWidth: number, paneHeight: number, pixelRows: boolean, { minScale, padLeft, padTop, padRight, padBottom, }?: {
64
64
  minScale?: number | undefined;
65
65
  padLeft?: number | undefined;
66
66
  padTop?: number | undefined;
67
+ padRight?: number | undefined;
68
+ padBottom?: number | undefined;
67
69
  }): {
68
70
  scale: number;
69
71
  translateX: number;
@@ -9,10 +9,11 @@ export interface StripBlock {
9
9
  bp1: number;
10
10
  color: string;
11
11
  }
12
- export declare function referenceStripBlocks(graph: Graph, { colorScheme, referenceRamp, walkNodes, }: {
12
+ export declare function referenceStripBlocks(graph: Graph, { colorScheme, referenceRamp, walkNodes, walkColors, }: {
13
13
  colorScheme: ResolvedColorScheme;
14
14
  referenceRamp?: ReferenceRamp;
15
15
  walkNodes?: ReadonlySet<string>;
16
+ walkColors?: ReadonlyMap<string, number>;
16
17
  }): StripBlock[];
17
18
  export interface BpFrame {
18
19
  scale: number;
@@ -4,6 +4,7 @@ import type { Graph, GraphNode, NodeSegment } from '../types.js';
4
4
  import type { WalkLift } from '../walkHighlight.js';
5
5
  import type { RenderBatch } from './types.js';
6
6
  import type { AxisScale, BezierCurve } from '../util/geometry.js';
7
+ export declare const LIFT_BACKDROP_COLOR: number;
7
8
  export declare const FADED_ALPHA = 0.18;
8
9
  export interface BuildOptions {
9
10
  nodePositions: Record<string, NodeSegment[]>;
@@ -1,47 +1,37 @@
1
1
  export declare const WALK_FIELDS: readonly [{
2
2
  readonly value: "progress";
3
3
  readonly label: "Progress along the walk";
4
- readonly legend: "pale where the walk starts, deep where it ends";
4
+ }, {
5
+ readonly value: "walk";
6
+ readonly label: "One colour for the walk";
5
7
  }, {
6
8
  readonly value: "reference";
7
9
  readonly label: "Reference position";
8
- readonly legend: "along the reference left to right, charcoal off it";
9
- }, {
10
- readonly value: "strand";
11
- readonly label: "Strand against the reference";
12
- readonly legend: "pale where the walk runs as the reference does, deep where reversed";
13
- }, {
14
- readonly value: "visits";
15
- readonly label: "Visits";
16
- readonly legend: "pale where the walk passes once, deep four times or more";
17
10
  }];
18
11
  export type WalkField = (typeof WALK_FIELDS)[number]['value'];
19
12
  export declare const WALK_SCHEMES: readonly [{
20
- readonly value: "rainbow";
21
- readonly label: "Rainbow";
22
- }, {
23
- readonly value: "blues";
24
- readonly label: "Blues";
25
- readonly hue: 215;
13
+ readonly value: "grey";
14
+ readonly label: "Grey to black";
15
+ readonly ends: readonly ["#a3a3a3", "#151515"];
26
16
  }, {
27
- readonly value: "reds";
28
- readonly label: "Reds";
29
- readonly hue: 0;
17
+ readonly value: "blue";
18
+ readonly label: "Cyan to navy";
19
+ readonly ends: readonly ["#6ee0f0", "#0b2c7a"];
30
20
  }, {
31
- readonly value: "greens";
32
- readonly label: "Greens";
33
- readonly hue: 130;
21
+ readonly value: "red";
22
+ readonly label: "Yellow to red";
23
+ readonly ends: readonly ["#ffd24a", "#b3121b"];
34
24
  }, {
35
- readonly value: "oranges";
36
- readonly label: "Oranges";
37
- readonly hue: 30;
25
+ readonly value: "purple";
26
+ readonly label: "Pink to plum";
27
+ readonly ends: readonly ["#f5a3d8", "#5e1a6e"];
38
28
  }, {
39
- readonly value: "purples";
40
- readonly label: "Purples";
41
- readonly hue: 280;
29
+ readonly value: "green";
30
+ readonly label: "Lime to forest";
31
+ readonly ends: readonly ["#b6e36c", "#0b5d3b"];
42
32
  }, {
43
- readonly value: "greys";
44
- readonly label: "Greys";
33
+ readonly value: "rainbow";
34
+ readonly label: "Rainbow";
45
35
  }];
46
36
  export type WalkScheme = (typeof WALK_SCHEMES)[number]['value'];
47
37
  export interface WalkEncoding {
@@ -52,19 +42,10 @@ export interface WalkLayer {
52
42
  walk: string;
53
43
  color?: Partial<WalkEncoding>;
54
44
  }
55
- export declare function resolveEncoding(layer: WalkLayer, reference: boolean, picked: number): WalkEncoding;
56
- export declare function schemeHsl(scheme: WalkScheme, t: number): {
57
- h: number;
58
- s: number;
59
- l: number;
60
- };
45
+ export declare function resolveEncoding(layer: WalkLayer, reference: boolean, picked: number, alone?: boolean): WalkEncoding;
46
+ export declare function schemeRgb(scheme: WalkScheme, t: number): number[];
61
47
  export declare function schemeCss(scheme: WalkScheme, t: number): string;
62
48
  export declare function schemeColor(scheme: WalkScheme, t: number): number;
49
+ export declare function encodedColor({ field, scheme }: WalkEncoding, t?: number): number;
63
50
  export declare const NO_VALUE_COLOR: number;
64
- export declare const NO_VALUE_CSS: string;
65
- export declare const STRAND_T: {
66
- same: number;
67
- reversed: number;
68
- };
69
51
  export declare function encodingSwatchCss({ field, scheme }: WalkEncoding): string;
70
- export declare function fieldLegend(field: WalkField): "pale where the walk starts, deep where it ends" | "along the reference left to right, charcoal off it" | "pale where the walk runs as the reference does, deep where reversed" | "pale where the walk passes once, deep four times or more";
@@ -10,16 +10,28 @@ export interface WalkHighlight {
10
10
  steps: number;
11
11
  bp: number;
12
12
  referenceBp?: number;
13
+ range?: {
14
+ contig: string;
15
+ start: number;
16
+ end: number;
17
+ };
13
18
  }
14
19
  export interface LiftedWalk extends WalkHighlight {
15
20
  encoding: WalkEncoding;
16
21
  colors: Map<string, number>;
22
+ reversed: Set<string>;
23
+ reversedBp: number;
17
24
  }
18
25
  export interface WalkLift {
19
26
  walks: LiftedWalk[];
27
+ referenceDomain?: {
28
+ start: number;
29
+ end: number;
30
+ };
20
31
  nodeIds: Set<string>;
21
32
  edgeIndexes: Set<number>;
22
33
  names: Set<string>;
23
34
  }
24
35
  export declare function walkHighlight(graph: Graph, name: string): WalkHighlight | undefined;
25
36
  export declare function walkLift(graph: Graph, layers: readonly WalkLayer[], ramp?: ReferenceRamp): WalkLift | undefined;
37
+ export declare function facetLifts(graph: Graph, lift: WalkLift, layers: readonly WalkLayer[], ramp?: ReferenceRamp): WalkLift[];
@@ -0,0 +1,12 @@
1
+ import type { LiftedWalk } from './walkHighlight.js';
2
+ export declare function walkKey(walk: LiftedWalk, reference?: {
3
+ name?: string;
4
+ start: number;
5
+ end: number;
6
+ }): {
7
+ delta: string;
8
+ reversed: string;
9
+ shades: boolean;
10
+ scale: string | undefined;
11
+ hover: string | undefined;
12
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/bandage-core",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Pangenome graph layout and drawing with no host: GFA in, the Bandage force-directed engine and reference-anchored layouts, a Canvas2D renderer, hit testing and labels out",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": {