@jbrowse/bandage-core 0.1.15 → 0.1.17

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/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
  }
@@ -2147,6 +2153,7 @@ var LAYOUT_MODES = [
2147
2153
  description: "x is reference bp, one row per stable rank. Needs rGFA tags or a reference path.",
2148
2154
  run: anchoredLayout,
2149
2155
  cutMargins: true,
2156
+ wholeWalks: false,
2150
2157
  available: hasBackbone,
2151
2158
  drawsLocally: hasBackbone
2152
2159
  },
@@ -2156,6 +2163,7 @@ var LAYOUT_MODES = [
2156
2163
  description: "x is reference bp, one row per contributing assembly. Needs rGFA tags or a reference path.",
2157
2164
  run: sampleRowLayout,
2158
2165
  cutMargins: true,
2166
+ wholeWalks: false,
2159
2167
  available: hasAlleles,
2160
2168
  drawsLocally: hasAlleles
2161
2169
  },
@@ -2165,6 +2173,7 @@ var LAYOUT_MODES = [
2165
2173
  description: "x is each walk's own bp: one bar per haplotype, sequence the reference also carries in blue and sequence it does not in purple, so a repeat expansion reads as bar length. Needs W or P lines.",
2166
2174
  run: walkRowLayout,
2167
2175
  cutMargins: false,
2176
+ wholeWalks: true,
2168
2177
  available: hasWalks,
2169
2178
  drawsLocally: hasWalks
2170
2179
  },
@@ -2174,6 +2183,7 @@ var LAYOUT_MODES = [
2174
2183
  description: "x is reference order, not bp: every node gets room, bubbles read as lenses. Needs rGFA tags or a reference path.",
2175
2184
  run: orderedLayout,
2176
2185
  cutMargins: false,
2186
+ wholeWalks: false,
2177
2187
  available: hasBackbone,
2178
2188
  drawsLocally: hasBackbone
2179
2189
  },
@@ -2183,6 +2193,7 @@ var LAYOUT_MODES = [
2183
2193
  description: "sequenceTubeMap: every path a coloured tube through boxed nodes, columns in node order and node widths log-scaled. Needs P or W lines.",
2184
2194
  run: tubeMapLayout,
2185
2195
  cutMargins: false,
2196
+ wholeWalks: false,
2186
2197
  available: hasTubeMapPaths,
2187
2198
  drawsLocally: hasTubeMapPaths
2188
2199
  },
@@ -2192,6 +2203,7 @@ var LAYOUT_MODES = [
2192
2203
  description: "The tube map with each column at the reference bp it covers, so the tubes line up with the tracks around them. Needs P or W lines and a reference path.",
2193
2204
  run: tubeMapReferenceLayout,
2194
2205
  cutMargins: true,
2206
+ wholeWalks: false,
2195
2207
  available: hasTubeMapBackbone,
2196
2208
  drawsLocally: hasTubeMapBackbone
2197
2209
  },
@@ -2201,6 +2213,7 @@ var LAYOUT_MODES = [
2201
2213
  description: "OGDF FMMM, via the external Bandage engine.",
2202
2214
  run: () => void 0,
2203
2215
  cutMargins: false,
2216
+ wholeWalks: false,
2204
2217
  available: () => true,
2205
2218
  drawsLocally: () => false
2206
2219
  }
@@ -2848,10 +2861,11 @@ var EDGE_DEFAULT_COLOR = packAbgr2(119, 119, 119, 217);
2848
2861
  var EDGE_PATH_FALLBACK_COLOR = packAbgr2(136, 136, 136, 217);
2849
2862
  var EDGE_DELETION_COLOR = packAbgr2(24, 24, 28, 240);
2850
2863
  var DELETION_THICKNESS_FACTOR = 2.2;
2864
+ var LIFT_BACKDROP_COLOR = packAbgr2(160, 160, 160, 255);
2851
2865
  var FADED_ALPHA = 0.18;
2852
2866
  var DELETION_DASH_PX = 11;
2853
2867
  var MIN_PATH_STRIPE_PX = 1.2;
2854
- var MIN_WALK_LANE_PX = 3;
2868
+ var MIN_WALK_LANE_PX = 4;
2855
2869
  var MIN_SCALE_FOR_OFFSET = 1e-6;
2856
2870
  var ARROW_LENGTH_BASE_PX = 7;
2857
2871
  var ARROW_LENGTH_PER_EDGE_PX = 3;
@@ -3438,13 +3452,13 @@ function buildGeometry(options) {
3438
3452
  if (viewportBounds && !isPolylineInBounds(segments, viewportBounds)) {
3439
3453
  continue;
3440
3454
  }
3441
- const own = getNodeColor(
3455
+ const faded = highlight !== void 0 && !highlight.nodeIds.has(nodeId);
3456
+ const own = faded ? LIFT_BACKDROP_COLOR : getNodeColor(
3442
3457
  node,
3443
3458
  nodeIndexMap.get(nodeId) ?? 0,
3444
3459
  colorScheme,
3445
3460
  colorRange
3446
3461
  );
3447
- const faded = highlight !== void 0 && !highlight.nodeIds.has(nodeId);
3448
3462
  const color = faded ? fadeAbgr(own, FADED_ALPHA) : own;
3449
3463
  const width = nodeWidthPx(node, contigThickness, nodeWidth2, depthNorm);
3450
3464
  const nodeThickness = width / 2;
@@ -4074,13 +4088,14 @@ var OVERHANG_PX = 5;
4074
4088
  function referenceStripBlocks(graph, {
4075
4089
  colorScheme,
4076
4090
  referenceRamp,
4077
- walkNodes
4091
+ walkNodes,
4092
+ walkColors
4078
4093
  }) {
4079
4094
  const range = { ...computeColorSchemeRange(graph), referenceRamp };
4080
4095
  const out = [];
4081
4096
  graph.nodes.forEach((node, index) => {
4082
4097
  if (isBackbone(node)) {
4083
- const own = getNodeColor(node, index, colorScheme, range);
4098
+ const own = walkNodes ? walkColors?.get(node.id) ?? LIFT_BACKDROP_COLOR : getNodeColor(node, index, colorScheme, range);
4084
4099
  out.push({
4085
4100
  node: node.id,
4086
4101
  bp0: node.stable.start,
@@ -5239,78 +5254,84 @@ var WALK_FIELDS = [
5239
5254
  {
5240
5255
  value: "progress",
5241
5256
  label: "Progress along the walk",
5242
- legend: "pale where the walk starts, deep where it ends"
5257
+ legend: "light where each walk starts, dark where it ends"
5243
5258
  },
5259
+ { value: "walk", label: "One colour for the walk", legend: "" },
5244
5260
  {
5245
5261
  value: "reference",
5246
5262
  label: "Reference position",
5247
5263
  legend: "along the reference left to right, charcoal off it"
5248
- },
5249
- {
5250
- value: "strand",
5251
- label: "Strand against the reference",
5252
- legend: "pale where the walk runs as the reference does, deep where reversed"
5253
- },
5254
- {
5255
- value: "visits",
5256
- label: "Visits",
5257
- legend: "pale where the walk passes once, deep four times or more"
5258
5264
  }
5259
5265
  ];
5260
5266
  var WALK_SCHEMES = [
5261
- { value: "rainbow", label: "Rainbow" },
5262
- { value: "blues", label: "Blues", hue: 215 },
5263
- { value: "reds", label: "Reds", hue: 0 },
5264
- { value: "greens", label: "Greens", hue: 130 },
5265
- { value: "oranges", label: "Oranges", hue: 30 },
5266
- { value: "purples", label: "Purples", hue: 280 },
5267
- { value: "greys", label: "Greys" }
5268
- ];
5269
- var DEFAULT_FAMILIES = [
5270
- "blues",
5271
- "reds",
5272
- "greens",
5273
- "oranges",
5274
- "purples"
5267
+ { value: "grey", label: "Grey to black", ends: ["#a3a3a3", "#151515"] },
5268
+ { value: "blue", label: "Cyan to navy", ends: ["#6ee0f0", "#0b2c7a"] },
5269
+ { value: "red", label: "Yellow to red", ends: ["#ffd24a", "#b3121b"] },
5270
+ { value: "purple", label: "Pink to plum", ends: ["#f5a3d8", "#5e1a6e"] },
5271
+ { value: "green", label: "Lime to forest", ends: ["#b6e36c", "#0b5d3b"] },
5272
+ { value: "rainbow", label: "Rainbow" }
5275
5273
  ];
5276
- function resolveEncoding(layer, reference, picked) {
5277
- return {
5278
- field: layer.color?.field ?? (reference ? "reference" : "progress"),
5279
- scheme: layer.color?.scheme ?? (reference ? "rainbow" : DEFAULT_FAMILIES[picked % DEFAULT_FAMILIES.length])
5280
- };
5274
+ var FAMILIES = ["blue", "red", "purple", "green"];
5275
+ var isField = (v) => WALK_FIELDS.some((f) => f.value === v);
5276
+ var isScheme = (v) => WALK_SCHEMES.some((s) => s.value === v);
5277
+ function resolveEncoding(layer, reference, picked, alone = true) {
5278
+ const { field: askedField, scheme: askedScheme } = layer.color ?? {};
5279
+ const field = isField(askedField) ? askedField : alone ? "progress" : "walk";
5280
+ const family = reference ? "grey" : FAMILIES[picked % FAMILIES.length];
5281
+ const scheme = isScheme(askedScheme) ? askedScheme === "rainbow" && field !== "reference" ? family : askedScheme : family;
5282
+ return { field, scheme };
5283
+ }
5284
+ var BASE_T = 0.5;
5285
+ var toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
5286
+ var toGamma = (c) => c <= 31308e-7 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;
5287
+ function oklab(hex) {
5288
+ const [r, g, b] = [1, 3, 5].map(
5289
+ (i) => toLinear(Number.parseInt(hex.slice(i, i + 2), 16) / 255)
5290
+ );
5291
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
5292
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
5293
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
5294
+ return [
5295
+ 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
5296
+ 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
5297
+ 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
5298
+ ];
5299
+ }
5300
+ function oklabToRgb([L, a, b]) {
5301
+ const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
5302
+ const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
5303
+ const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
5304
+ return [
5305
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
5306
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
5307
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
5308
+ ].map((c) => toGamma(Math.max(0, Math.min(1, c))) * 255);
5281
5309
  }
5282
- var PALE = 0.82;
5283
- var DEEP = 0.28;
5284
- function schemeHsl(scheme, t) {
5310
+ function schemeRgb(scheme, t) {
5285
5311
  const x = Math.max(0, Math.min(1, t));
5286
- if (scheme === "rainbow") {
5287
- return { h: x * REFERENCE_RAMP_MAX_HUE, s: 0.7, l: 0.5 };
5288
- }
5289
5312
  const family = WALK_SCHEMES.find((s) => s.value === scheme);
5290
- const l = PALE + (DEEP - PALE) * x;
5291
- return family && "hue" in family ? { h: family.hue, s: 0.75, l } : { h: 0, s: 0, l };
5313
+ if (!family || !("ends" in family)) {
5314
+ return hslToRgb(x * REFERENCE_RAMP_MAX_HUE, 0.7, 0.5).map((c) => c * 255);
5315
+ }
5316
+ const from = oklab(family.ends[0]);
5317
+ const to = oklab(family.ends[1]);
5318
+ return oklabToRgb(from.map((v, i) => v + (to[i] - v) * x));
5292
5319
  }
5293
5320
  function schemeCss(scheme, t) {
5294
- const { h, s, l } = schemeHsl(scheme, t);
5295
- return `hsl(${h}, ${s * 100}%, ${l * 100}%)`;
5321
+ const [r, g, b] = schemeRgb(scheme, t).map(Math.round);
5322
+ return `rgb(${r}, ${g}, ${b})`;
5296
5323
  }
5297
5324
  function schemeColor(scheme, t) {
5298
- const { h, s, l } = schemeHsl(scheme, t);
5299
- const [r, g, b] = hslToRgb(h, s, l);
5300
- return packAbgr3(
5301
- Math.round(r * 255),
5302
- Math.round(g * 255),
5303
- Math.round(b * 255),
5304
- 255
5305
- );
5325
+ const [r, g, b] = schemeRgb(scheme, t).map(Math.round);
5326
+ return packAbgr3(r, g, b, 255);
5327
+ }
5328
+ function encodedColor({ field, scheme }, t) {
5329
+ return field === "walk" ? schemeColor(scheme, BASE_T) : t === void 0 ? NO_VALUE_COLOR : schemeColor(scheme, t);
5306
5330
  }
5307
5331
  var NO_VALUE_COLOR = REFERENCE_RAMP_ALT_COLOR;
5308
- var STRAND_T = { same: 0.2, reversed: 0.95 };
5309
5332
  function encodingSwatchCss({ field, scheme }) {
5310
- if (field === "strand") {
5311
- const same = schemeCss(scheme, STRAND_T.same);
5312
- const reversed = schemeCss(scheme, STRAND_T.reversed);
5313
- return `linear-gradient(to right, ${same} 50%, ${reversed} 50%)`;
5333
+ if (field === "walk") {
5334
+ return schemeCss(scheme, BASE_T);
5314
5335
  }
5315
5336
  const stops = Array.from({ length: 7 }, (_, i) => {
5316
5337
  const t = i / 6;
@@ -5357,9 +5378,16 @@ function walkHighlight(graph, name) {
5357
5378
  before += length;
5358
5379
  }
5359
5380
  const reference = referenceOf(graph);
5381
+ const originName = pathOrigin(name).name;
5382
+ const origin = graph.anchorPaths?.find((a) => a.name === originName && a.length === bp) ?? graph.anchorPaths?.find((a) => a.name === originName);
5360
5383
  return {
5361
5384
  name,
5362
5385
  reference: reference === path,
5386
+ range: origin ? {
5387
+ contig: path.contig ?? panSNContig(origin.name),
5388
+ start: origin.start,
5389
+ end: origin.start + origin.length
5390
+ } : void 0,
5363
5391
  nodeIds: new Set(path.nodeIds),
5364
5392
  edgeIndexes,
5365
5393
  progress,
@@ -5368,37 +5396,39 @@ function walkHighlight(graph, name) {
5368
5396
  referenceBp: reference && reference !== path ? reference.nodeIds.reduce((sum, id) => sum + lengthOf(id), 0) : void 0
5369
5397
  };
5370
5398
  }
5371
- function laneColors(graph, walk, { field, scheme }, ramp) {
5372
- const colors = /* @__PURE__ */ new Map();
5399
+ function laneColors(graph, walk, encoding, ramp) {
5373
5400
  const byId = new Map(graph.nodes.map((n) => [n.id, n]));
5374
- const walkPath = pathOrigin(walk.name).name;
5375
- const reference = referenceOf(graph);
5376
- const referencePath = reference ? pathOrigin(reference.name).name : void 0;
5377
- const path = graph.paths.find((p) => p.name === walk.name);
5378
- const visits = /* @__PURE__ */ new Map();
5379
- for (const id of path.nodeIds) {
5380
- visits.set(id, (visits.get(id) ?? 0) + 1);
5381
- }
5382
- const strandOf = (segment, of) => graph.pathVisits?.get(segment)?.find((v) => v.path === of)?.strand;
5401
+ const colors = /* @__PURE__ */ new Map();
5383
5402
  for (const [id, progress] of walk.progress) {
5384
5403
  const node = byId.get(id);
5385
- let t;
5386
- if (field === "progress") {
5387
- t = progress;
5388
- } else if (field === "visits") {
5389
- t = (Math.min(visits.get(id) ?? 1, 4) - 1) / 3;
5390
- } else if (field === "reference") {
5391
- const mid = ramp?.midpoints.get(id);
5392
- t = ramp && mid !== void 0 && !(node?.stable && node.stable.rank > 0) ? (mid - ramp.start) / ramp.span : void 0;
5393
- } else if (node) {
5394
- const own = strandOf(node.name, walkPath);
5395
- const theirs = strandOf(node.name, referencePath);
5396
- t = own && theirs ? own === theirs ? STRAND_T.same : STRAND_T.reversed : void 0;
5397
- }
5398
- colors.set(id, t === void 0 ? NO_VALUE_COLOR : schemeColor(scheme, t));
5404
+ const mid = ramp?.midpoints.get(id);
5405
+ const t = encoding.field === "progress" ? progress : ramp && mid !== void 0 && !(node?.stable && node.stable.rank > 0) ? (mid - ramp.start) / ramp.span : void 0;
5406
+ colors.set(id, encodedColor(encoding, t));
5399
5407
  }
5400
5408
  return colors;
5401
5409
  }
5410
+ function reversedNodes(graph, walk) {
5411
+ const reference = referenceOf(graph);
5412
+ const reversed = /* @__PURE__ */ new Set();
5413
+ let bp = 0;
5414
+ if (!reference || walk.reference) {
5415
+ return { reversed, bp };
5416
+ }
5417
+ const walkPath = pathOrigin(walk.name).name;
5418
+ const referencePath = pathOrigin(reference.name).name;
5419
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
5420
+ for (const id of walk.progress.keys()) {
5421
+ const node = byId.get(id);
5422
+ const visits = node ? graph.pathVisits?.get(node.name) : void 0;
5423
+ const own = visits?.find((v) => v.path === walkPath)?.strand;
5424
+ const theirs = visits?.find((v) => v.path === referencePath)?.strand;
5425
+ if (own && theirs && own !== theirs) {
5426
+ reversed.add(id);
5427
+ bp += node.length;
5428
+ }
5429
+ }
5430
+ return { reversed, bp };
5431
+ }
5402
5432
  function walkLift(graph, layers, ramp) {
5403
5433
  const seen = /* @__PURE__ */ new Set();
5404
5434
  const lifted = layers.filter((layer) => !seen.has(layer.walk) && seen.add(layer.walk)).flatMap((layer) => {
@@ -5413,16 +5443,21 @@ function walkLift(graph, layers, ramp) {
5413
5443
  const encoding = resolveEncoding(
5414
5444
  layer,
5415
5445
  walk.reference,
5416
- walk.reference ? 0 : picked++
5446
+ walk.reference ? 0 : picked++,
5447
+ lifted.length === 1
5417
5448
  );
5449
+ const { reversed, bp } = reversedNodes(graph, walk);
5418
5450
  return {
5419
5451
  ...walk,
5420
5452
  encoding,
5421
- colors: laneColors(graph, walk, encoding, ramp)
5453
+ colors: laneColors(graph, walk, encoding, ramp),
5454
+ reversed,
5455
+ reversedBp: bp
5422
5456
  };
5423
5457
  });
5424
5458
  return {
5425
5459
  walks,
5460
+ referenceDomain: ramp ? { start: ramp.start, end: ramp.start + ramp.span } : void 0,
5426
5461
  nodeIds: new Set(walks.flatMap((w) => [...w.nodeIds])),
5427
5462
  edgeIndexes: new Set(walks.flatMap((w) => [...w.edgeIndexes])),
5428
5463
  names: new Set(walks.map((w) => w.name))
@@ -15,6 +15,7 @@ export interface LayoutMode {
15
15
  }, keepRows?: readonly string[]) => LayoutResult | undefined;
16
16
  available: (graph: Graph) => boolean;
17
17
  cutMargins: boolean;
18
+ wholeWalks: boolean;
18
19
  drawsLocally: (graph: Graph) => boolean;
19
20
  }
20
21
  export declare const LAYOUT_MODES: readonly [{
@@ -23,6 +24,7 @@ export declare const LAYOUT_MODES: readonly [{
23
24
  readonly description: "x is reference bp, one row per stable rank. Needs rGFA tags or a reference path.";
24
25
  readonly run: typeof anchoredLayout;
25
26
  readonly cutMargins: true;
27
+ readonly wholeWalks: false;
26
28
  readonly available: (graph: Graph) => boolean;
27
29
  readonly drawsLocally: (graph: Graph) => boolean;
28
30
  }, {
@@ -31,6 +33,7 @@ export declare const LAYOUT_MODES: readonly [{
31
33
  readonly description: "x is reference bp, one row per contributing assembly. Needs rGFA tags or a reference path.";
32
34
  readonly run: typeof sampleRowLayout;
33
35
  readonly cutMargins: true;
36
+ readonly wholeWalks: false;
34
37
  readonly available: (graph: Graph) => boolean;
35
38
  readonly drawsLocally: (graph: Graph) => boolean;
36
39
  }, {
@@ -39,6 +42,7 @@ export declare const LAYOUT_MODES: readonly [{
39
42
  readonly description: "x is each walk's own bp: one bar per haplotype, sequence the reference also carries in blue and sequence it does not in purple, so a repeat expansion reads as bar length. Needs W or P lines.";
40
43
  readonly run: typeof walkRowLayout;
41
44
  readonly cutMargins: false;
45
+ readonly wholeWalks: true;
42
46
  readonly available: (graph: Graph) => boolean;
43
47
  readonly drawsLocally: (graph: Graph) => boolean;
44
48
  }, {
@@ -47,6 +51,7 @@ export declare const LAYOUT_MODES: readonly [{
47
51
  readonly description: "x is reference order, not bp: every node gets room, bubbles read as lenses. Needs rGFA tags or a reference path.";
48
52
  readonly run: typeof orderedLayout;
49
53
  readonly cutMargins: false;
54
+ readonly wholeWalks: false;
50
55
  readonly available: (graph: Graph) => boolean;
51
56
  readonly drawsLocally: (graph: Graph) => boolean;
52
57
  }, {
@@ -55,6 +60,7 @@ export declare const LAYOUT_MODES: readonly [{
55
60
  readonly description: "sequenceTubeMap: every path a coloured tube through boxed nodes, columns in node order and node widths log-scaled. Needs P or W lines.";
56
61
  readonly run: typeof tubeMapLayout;
57
62
  readonly cutMargins: false;
63
+ readonly wholeWalks: false;
58
64
  readonly available: typeof hasTubeMapPaths;
59
65
  readonly drawsLocally: typeof hasTubeMapPaths;
60
66
  }, {
@@ -63,6 +69,7 @@ export declare const LAYOUT_MODES: readonly [{
63
69
  readonly description: "The tube map with each column at the reference bp it covers, so the tubes line up with the tracks around them. Needs P or W lines and a reference path.";
64
70
  readonly run: typeof tubeMapReferenceLayout;
65
71
  readonly cutMargins: true;
72
+ readonly wholeWalks: false;
66
73
  readonly available: (graph: Graph) => boolean;
67
74
  readonly drawsLocally: (graph: Graph) => boolean;
68
75
  }, {
@@ -71,6 +78,7 @@ export declare const LAYOUT_MODES: readonly [{
71
78
  readonly description: "OGDF FMMM, via the external Bandage engine.";
72
79
  readonly run: () => undefined;
73
80
  readonly cutMargins: false;
81
+ readonly wholeWalks: false;
74
82
  readonly available: () => true;
75
83
  readonly drawsLocally: () => false;
76
84
  }];
@@ -83,6 +91,7 @@ export declare function layoutModeByValue(value: string): {
83
91
  readonly description: "x is reference bp, one row per stable rank. Needs rGFA tags or a reference path.";
84
92
  readonly run: typeof anchoredLayout;
85
93
  readonly cutMargins: true;
94
+ readonly wholeWalks: false;
86
95
  readonly available: (graph: Graph) => boolean;
87
96
  readonly drawsLocally: (graph: Graph) => boolean;
88
97
  } | {
@@ -91,6 +100,7 @@ export declare function layoutModeByValue(value: string): {
91
100
  readonly description: "x is reference bp, one row per contributing assembly. Needs rGFA tags or a reference path.";
92
101
  readonly run: typeof sampleRowLayout;
93
102
  readonly cutMargins: true;
103
+ readonly wholeWalks: false;
94
104
  readonly available: (graph: Graph) => boolean;
95
105
  readonly drawsLocally: (graph: Graph) => boolean;
96
106
  } | {
@@ -99,6 +109,7 @@ export declare function layoutModeByValue(value: string): {
99
109
  readonly description: "x is each walk's own bp: one bar per haplotype, sequence the reference also carries in blue and sequence it does not in purple, so a repeat expansion reads as bar length. Needs W or P lines.";
100
110
  readonly run: typeof walkRowLayout;
101
111
  readonly cutMargins: false;
112
+ readonly wholeWalks: true;
102
113
  readonly available: (graph: Graph) => boolean;
103
114
  readonly drawsLocally: (graph: Graph) => boolean;
104
115
  } | {
@@ -107,6 +118,7 @@ export declare function layoutModeByValue(value: string): {
107
118
  readonly description: "x is reference order, not bp: every node gets room, bubbles read as lenses. Needs rGFA tags or a reference path.";
108
119
  readonly run: typeof orderedLayout;
109
120
  readonly cutMargins: false;
121
+ readonly wholeWalks: false;
110
122
  readonly available: (graph: Graph) => boolean;
111
123
  readonly drawsLocally: (graph: Graph) => boolean;
112
124
  } | {
@@ -115,6 +127,7 @@ export declare function layoutModeByValue(value: string): {
115
127
  readonly description: "sequenceTubeMap: every path a coloured tube through boxed nodes, columns in node order and node widths log-scaled. Needs P or W lines.";
116
128
  readonly run: typeof tubeMapLayout;
117
129
  readonly cutMargins: false;
130
+ readonly wholeWalks: false;
118
131
  readonly available: typeof hasTubeMapPaths;
119
132
  readonly drawsLocally: typeof hasTubeMapPaths;
120
133
  } | {
@@ -123,6 +136,7 @@ export declare function layoutModeByValue(value: string): {
123
136
  readonly description: "The tube map with each column at the reference bp it covers, so the tubes line up with the tracks around them. Needs P or W lines and a reference path.";
124
137
  readonly run: typeof tubeMapReferenceLayout;
125
138
  readonly cutMargins: true;
139
+ readonly wholeWalks: false;
126
140
  readonly available: (graph: Graph) => boolean;
127
141
  readonly drawsLocally: (graph: Graph) => boolean;
128
142
  } | {
@@ -131,6 +145,7 @@ export declare function layoutModeByValue(value: string): {
131
145
  readonly description: "OGDF FMMM, via the external Bandage engine.";
132
146
  readonly run: () => undefined;
133
147
  readonly cutMargins: false;
148
+ readonly wholeWalks: false;
134
149
  readonly available: () => true;
135
150
  readonly drawsLocally: () => false;
136
151
  };
@@ -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,40 @@
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
+ readonly legend: "light where each walk starts, dark where it ends";
5
+ }, {
6
+ readonly value: "walk";
7
+ readonly label: "One colour for the walk";
8
+ readonly legend: "";
5
9
  }, {
6
10
  readonly value: "reference";
7
11
  readonly label: "Reference position";
8
12
  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
13
  }];
18
14
  export type WalkField = (typeof WALK_FIELDS)[number]['value'];
19
15
  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;
16
+ readonly value: "grey";
17
+ readonly label: "Grey to black";
18
+ readonly ends: readonly ["#a3a3a3", "#151515"];
26
19
  }, {
27
- readonly value: "reds";
28
- readonly label: "Reds";
29
- readonly hue: 0;
20
+ readonly value: "blue";
21
+ readonly label: "Cyan to navy";
22
+ readonly ends: readonly ["#6ee0f0", "#0b2c7a"];
30
23
  }, {
31
- readonly value: "greens";
32
- readonly label: "Greens";
33
- readonly hue: 130;
24
+ readonly value: "red";
25
+ readonly label: "Yellow to red";
26
+ readonly ends: readonly ["#ffd24a", "#b3121b"];
34
27
  }, {
35
- readonly value: "oranges";
36
- readonly label: "Oranges";
37
- readonly hue: 30;
28
+ readonly value: "purple";
29
+ readonly label: "Pink to plum";
30
+ readonly ends: readonly ["#f5a3d8", "#5e1a6e"];
38
31
  }, {
39
- readonly value: "purples";
40
- readonly label: "Purples";
41
- readonly hue: 280;
32
+ readonly value: "green";
33
+ readonly label: "Lime to forest";
34
+ readonly ends: readonly ["#b6e36c", "#0b5d3b"];
42
35
  }, {
43
- readonly value: "greys";
44
- readonly label: "Greys";
36
+ readonly value: "rainbow";
37
+ readonly label: "Rainbow";
45
38
  }];
46
39
  export type WalkScheme = (typeof WALK_SCHEMES)[number]['value'];
47
40
  export interface WalkEncoding {
@@ -52,19 +45,12 @@ export interface WalkLayer {
52
45
  walk: string;
53
46
  color?: Partial<WalkEncoding>;
54
47
  }
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
- };
48
+ export declare function resolveEncoding(layer: WalkLayer, reference: boolean, picked: number, alone?: boolean): WalkEncoding;
49
+ export declare function schemeRgb(scheme: WalkScheme, t: number): number[];
61
50
  export declare function schemeCss(scheme: WalkScheme, t: number): string;
62
51
  export declare function schemeColor(scheme: WalkScheme, t: number): number;
52
+ export declare function encodedColor({ field, scheme }: WalkEncoding, t?: number): number;
63
53
  export declare const NO_VALUE_COLOR: number;
64
54
  export declare const NO_VALUE_CSS: string;
65
- export declare const STRAND_T: {
66
- same: number;
67
- reversed: number;
68
- };
69
55
  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";
56
+ export declare function fieldLegend(field: WalkField): "" | "light where each walk starts, dark where it ends" | "along the reference left to right, charcoal off it";
@@ -10,13 +10,24 @@ 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>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/bandage-core",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
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": {