@jbrowse/bandage-core 11.7.3 → 11.9.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.
Files changed (99) hide show
  1. package/README.md +59 -19
  2. package/dist/bubbles/bubbleHalos.js +6 -6
  3. package/dist/bubbles/classifyBubble.js +5 -5
  4. package/dist/bubbles/superbubbles.js +7 -7
  5. package/dist/chunks/{chunk-K4KVAMEF.js → chunk-2A6Z2DHF.js} +1 -1
  6. package/dist/chunks/{chunk-4SN7R4UF.js → chunk-2MXFG3W7.js} +1 -1
  7. package/dist/chunks/chunk-3BDQQTXY.js +568 -0
  8. package/dist/chunks/{chunk-QXBQDHKL.js → chunk-3BOREHCJ.js} +80 -38
  9. package/dist/chunks/{chunk-F4CDC72I.js → chunk-3DHGSHC3.js} +1 -1
  10. package/dist/chunks/{chunk-P276TWPM.js → chunk-3GORESBG.js} +1 -1
  11. package/dist/chunks/{chunk-4KOYS5WR.js → chunk-4BYGFDQB.js} +1 -1
  12. package/dist/chunks/{chunk-LH436HS2.js → chunk-4JDO7ZLN.js} +2 -2
  13. package/dist/chunks/{chunk-2US43KNG.js → chunk-7YSIP3O2.js} +2 -2
  14. package/dist/chunks/{chunk-VNF236GG.js → chunk-ARXDNQLF.js} +2 -2
  15. package/dist/chunks/{chunk-N73RA4DR.js → chunk-AURNOR27.js} +3 -3
  16. package/dist/chunks/{chunk-63XWYNID.js → chunk-BDS5VZYZ.js} +4 -4
  17. package/dist/chunks/{chunk-BXE3SBBN.js → chunk-C3KAPREU.js} +1 -1
  18. package/dist/chunks/{chunk-VXKL2ZLR.js → chunk-GDZQFELP.js} +259 -60
  19. package/dist/chunks/{chunk-2T3V6Z3M.js → chunk-GYJMPVOU.js} +1 -1
  20. package/dist/chunks/{chunk-BFUS3ENH.js → chunk-HEYIAMTC.js} +2 -2
  21. package/dist/chunks/{chunk-HMEAGAGC.js → chunk-HIN56TLA.js} +2 -2
  22. package/dist/chunks/{chunk-2VMKQKVO.js → chunk-HNNP5QUN.js} +1 -1
  23. package/dist/chunks/{chunk-W5YRBEWQ.js → chunk-I53QYITQ.js} +1 -1
  24. package/dist/chunks/{chunk-UTDMFVC7.js → chunk-I5CHAYDZ.js} +8 -8
  25. package/dist/chunks/{chunk-EPOPGV5G.js → chunk-IXLT3JJX.js} +1 -1
  26. package/dist/chunks/{chunk-SG7VQB4F.js → chunk-IZKM4NY7.js} +1 -1
  27. package/dist/chunks/{chunk-KMLATBNT.js → chunk-J7RNXBXA.js} +3 -3
  28. package/dist/chunks/{chunk-VACK24HF.js → chunk-JJV2GT2Z.js} +43 -9
  29. package/dist/chunks/{chunk-PKGPSTRW.js → chunk-JO2T77NW.js} +2 -2
  30. package/dist/chunks/{chunk-XKPXOIWD.js → chunk-JVT3XTKN.js} +3 -3
  31. package/dist/chunks/{chunk-SDI6BVG7.js → chunk-KKHXMJEE.js} +1 -1
  32. package/dist/chunks/{chunk-G7SG4XMK.js → chunk-LODKC7PJ.js} +7 -0
  33. package/dist/chunks/{chunk-AJQRKN3X.js → chunk-N3DCLT7M.js} +1 -1
  34. package/dist/chunks/{chunk-ZZZ6NVLW.js → chunk-NAYS472K.js} +1 -1
  35. package/dist/chunks/{chunk-AWJJSA7D.js → chunk-NWEVR2OQ.js} +1 -1
  36. package/dist/chunks/{chunk-33KUO34R.js → chunk-P2GJBFNA.js} +1 -1
  37. package/dist/chunks/{chunk-IHM43Y7B.js → chunk-RT4U3DH3.js} +1 -1
  38. package/dist/chunks/{chunk-XTCIKBWM.js → chunk-S6E3PMH7.js} +1 -1
  39. package/dist/chunks/{chunk-BLDUBB7X.js → chunk-SZYFZNCO.js} +2 -2
  40. package/dist/chunks/{chunk-T3MEG5D3.js → chunk-T2UNTWU5.js} +90 -21
  41. package/dist/chunks/{chunk-QJC63NFR.js → chunk-TQ26XEFL.js} +2 -2
  42. package/dist/chunks/{chunk-6RB5ZQ34.js → chunk-UEWIGD52.js} +51 -14
  43. package/dist/chunks/{chunk-SENPGW4O.js → chunk-VCUOYVLC.js} +1 -1
  44. package/dist/chunks/{chunk-CL6ELLVF.js → chunk-VNCHWWLG.js} +1 -1
  45. package/dist/chunks/{chunk-GD6RUZU5.js → chunk-VQ353UDK.js} +14 -8
  46. package/dist/chunks/{chunk-QLLKALSH.js → chunk-VTGQCLGI.js} +1 -1
  47. package/dist/chunks/{chunk-Z4HXW6ZH.js → chunk-ZWBQ4RRK.js} +24 -10
  48. package/dist/cli/figure.js +31 -30
  49. package/dist/cli/fold.js +6 -6
  50. package/dist/deletionEdges.js +2 -2
  51. package/dist/figure.js +27 -26
  52. package/dist/figureData.js +25 -24
  53. package/dist/figureScene.js +18 -17
  54. package/dist/figureSettings.js +6 -6
  55. package/dist/foldVariants.js +2 -2
  56. package/dist/genes/genePins.js +3 -3
  57. package/dist/graphLabels.js +4 -4
  58. package/dist/index.js +45 -44
  59. package/dist/labelLayout.js +8 -8
  60. package/dist/layout/forceCache.js +6 -6
  61. package/dist/layout/mergeRuns.js +2 -2
  62. package/dist/layout/orientToReference.js +2 -2
  63. package/dist/layout/tubeMapLayout.js +9 -9
  64. package/dist/layout/walkRowDraw.js +9 -8
  65. package/dist/layout/walkRowLayout.js +3 -3
  66. package/dist/layout/walkRowRuns.js +1 -1
  67. package/dist/layout/walkRows.js +2 -2
  68. package/dist/layout/walkStrip.js +13 -12
  69. package/dist/layoutModes.js +11 -11
  70. package/dist/pathColors.js +5 -5
  71. package/dist/pipeline.js +5 -5
  72. package/dist/referenceStrip.js +9 -8
  73. package/dist/renderer/GeometryBuilder.js +8 -7
  74. package/dist/renderer/walkLanes.js +46 -0
  75. package/dist/tubeMap/axis.js +5 -5
  76. package/dist/tubeMap/bundle.js +10 -10
  77. package/dist/tubeMap/coarsen.js +10 -10
  78. package/dist/tubeMap/deviations.js +11 -11
  79. package/dist/tubeMap/draw.js +5 -5
  80. package/dist/tubeMap/genes.js +6 -6
  81. package/dist/tubeMap/nodeColors.js +9 -8
  82. package/dist/tubeMap/reads.js +2 -2
  83. package/dist/types/figureData.d.ts +22 -0
  84. package/dist/types/renderer/types.d.ts +20 -0
  85. package/dist/types/renderer/walkLanes.d.ts +76 -0
  86. package/dist/types/util/geometry.d.ts +13 -1
  87. package/dist/types/version.d.ts +1 -1
  88. package/dist/types/walkEncoding.d.ts +9 -5
  89. package/dist/types/walkHighlight.d.ts +3 -0
  90. package/dist/util/SpatialIndex.js +4 -4
  91. package/dist/util/edgeCurves.js +3 -3
  92. package/dist/util/geometry.js +7 -1
  93. package/dist/util/hitDetection.js +5 -5
  94. package/dist/version.js +1 -1
  95. package/dist/viewport.js +6 -6
  96. package/dist/walkEncoding.js +13 -10
  97. package/dist/walkHighlight.js +10 -9
  98. package/dist/walkKey.js +5 -5
  99. package/package.json +1 -1
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-OPPVSPEF.js";
4
4
  import {
5
5
  orientToReference
6
- } from "./chunk-ZZZ6NVLW.js";
6
+ } from "./chunk-NAYS472K.js";
7
7
  import {
8
8
  seededNodes
9
9
  } from "./chunk-CKUVEHSS.js";
@@ -27,7 +27,7 @@ import {
27
27
  import {
28
28
  mergeRuns,
29
29
  splitRuns
30
- } from "./chunk-2VMKQKVO.js";
30
+ } from "./chunk-HNNP5QUN.js";
31
31
  import {
32
32
  spreadFor
33
33
  } from "./chunk-HKYXWZQS.js";
@@ -39,7 +39,7 @@ import {
39
39
  import {
40
40
  deletionDrawing,
41
41
  deletionEdges
42
- } from "./chunk-P276TWPM.js";
42
+ } from "./chunk-3GORESBG.js";
43
43
  import {
44
44
  anchorGraph
45
45
  } from "./chunk-3YBP46PB.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-5OJZV6YT.js";
4
4
  import {
5
5
  ownStrand
6
- } from "./chunk-VACK24HF.js";
6
+ } from "./chunk-JJV2GT2Z.js";
7
7
 
8
8
  // src/tubeMap/reads.ts
9
9
  function stepName(node, strand) {
@@ -13,6 +13,7 @@ import {
13
13
  } from "./chunk-BSOZW3FC.js";
14
14
  import {
15
15
  panSNContig,
16
+ panSNHaplotype,
16
17
  panSNSample
17
18
  } from "./chunk-2JL2JVZ2.js";
18
19
 
@@ -466,6 +467,12 @@ function walkRowRuns(source, region, o = {}) {
466
467
  meta: rowOf(pieces),
467
468
  row: i + 1
468
469
  }));
470
+ const metas = [referenceRow, ...rows.map((r) => r.meta)];
471
+ if (new Set(metas.map((m) => m.label)).size < metas.length) {
472
+ for (const meta of metas) {
473
+ meta.label = panSNHaplotype(meta.name) ?? meta.label;
474
+ }
475
+ }
469
476
  rows.sort(
470
477
  (a, b) => Number(b.meta.complete) - Number(a.meta.complete) || b.meta.bp - a.meta.bp || a.meta.label.localeCompare(b.meta.label)
471
478
  );
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var version = "11.7.3";
2
+ var version = "11.9.0";
3
3
 
4
4
  export {
5
5
  version
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ownStrand
3
- } from "./chunk-VACK24HF.js";
3
+ } from "./chunk-JJV2GT2Z.js";
4
4
  import {
5
5
  isBackbone
6
6
  } from "./chunk-RJWPJCIB.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-FX4RDMDN.js";
4
4
  import {
5
5
  formatBp
6
- } from "./chunk-N73RA4DR.js";
6
+ } from "./chunk-AURNOR27.js";
7
7
 
8
8
  // src/bubbles/classifyBubble.ts
9
9
  var REPEAT_GROWTH = 10;
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-HMXCN6PG.js";
4
4
  import {
5
5
  edgeCurvesOf
6
- } from "./chunk-P276TWPM.js";
6
+ } from "./chunk-3GORESBG.js";
7
7
 
8
8
  // src/util/edgeCurves.ts
9
9
  var cache = weakMemo();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  tubeSpan
3
- } from "./chunk-W5YRBEWQ.js";
3
+ } from "./chunk-I53QYITQ.js";
4
4
 
5
5
  // src/tubeMap/genes.ts
6
6
  function tubeMapGenes(byRefName, genes) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pathSteps
3
- } from "./chunk-63XWYNID.js";
3
+ } from "./chunk-BDS5VZYZ.js";
4
4
  import {
5
5
  pathOrigin
6
6
  } from "./chunk-3YBP46PB.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  bubbleSegmentIds,
3
3
  classifyBubble
4
- } from "./chunk-AWJJSA7D.js";
4
+ } from "./chunk-NWEVR2OQ.js";
5
5
  import {
6
6
  svgPath
7
- } from "./chunk-VACK24HF.js";
7
+ } from "./chunk-JJV2GT2Z.js";
8
8
  import {
9
9
  isBackbone
10
10
  } from "./chunk-RJWPJCIB.js";
@@ -3,25 +3,30 @@ import {
3
3
  } from "./chunk-CO6RGQAD.js";
4
4
  import {
5
5
  layoutModeByValue
6
- } from "./chunk-VNF236GG.js";
6
+ } from "./chunk-ARXDNQLF.js";
7
7
  import {
8
8
  parseRegion
9
9
  } from "./chunk-FNDNSDKW.js";
10
10
  import {
11
11
  genePins
12
- } from "./chunk-BFUS3ENH.js";
12
+ } from "./chunk-HEYIAMTC.js";
13
13
  import {
14
14
  version
15
- } from "./chunk-AJQRKN3X.js";
15
+ } from "./chunk-N3DCLT7M.js";
16
16
  import {
17
17
  axisScaleOf
18
- } from "./chunk-F4CDC72I.js";
18
+ } from "./chunk-3DHGSHC3.js";
19
19
  import {
20
20
  figureScene
21
- } from "./chunk-UTDMFVC7.js";
21
+ } from "./chunk-I5CHAYDZ.js";
22
22
  import {
23
23
  encodingStops
24
- } from "./chunk-6RB5ZQ34.js";
24
+ } from "./chunk-UEWIGD52.js";
25
+ import {
26
+ laneSlideAt,
27
+ passesKey,
28
+ threadsPasses
29
+ } from "./chunk-3BDQQTXY.js";
25
30
  import {
26
31
  abgrAlpha,
27
32
  abgrBlue,
@@ -30,13 +35,13 @@ import {
30
35
  } from "./chunk-G2FD7S3C.js";
31
36
  import {
32
37
  FIGURE_DEFAULTS
33
- } from "./chunk-4SN7R4UF.js";
38
+ } from "./chunk-2MXFG3W7.js";
34
39
  import {
35
40
  engineSettingsOf,
36
41
  fitTransform,
37
42
  forceLayout,
38
43
  loadGraph
39
- } from "./chunk-XKPXOIWD.js";
44
+ } from "./chunk-JVT3XTKN.js";
40
45
  import {
41
46
  referenceVisitStarts
42
47
  } from "./chunk-3YBP46PB.js";
@@ -86,15 +91,29 @@ function figureData(graph, layout, o = {}) {
86
91
  }
87
92
  const axis = axisScaleOf(fit.scale, pixelRows);
88
93
  const panels = [];
89
- const keys = columns(["panel", "walk", "note", "scale", "stops"]);
94
+ const keys = columns([
95
+ "panel",
96
+ "walk",
97
+ "name",
98
+ "color",
99
+ "note",
100
+ "scale",
101
+ "stops",
102
+ "field"
103
+ ]);
104
+ const threadKeys = columns(["panel", "note"]);
90
105
  const pushKey = (walk, panel) => {
91
106
  const key = keyText(walk);
107
+ const stops = encodingStops(walk.encoding).map((s) => cssHex(s.abgr));
92
108
  keys.push({
93
109
  panel,
94
110
  walk: labelOf(walk.name),
111
+ name: walk.name,
112
+ color: walk.encoding.field === "walk" ? stops[0] : "",
95
113
  note: key.note,
96
114
  scale: key.scale ?? "",
97
- stops: encodingStops(walk.encoding).map((s) => cssHex(s.abgr)).join(",")
115
+ stops: stops.join(","),
116
+ field: walk.encoding.field
98
117
  });
99
118
  return key;
100
119
  };
@@ -103,19 +122,30 @@ function figureData(graph, layout, o = {}) {
103
122
  for (const { panel } of ordered) {
104
123
  const walk = panel.walks[0];
105
124
  const name = labelOf(walk.name);
125
+ const firstKeyRow = keys.out.panel.length;
106
126
  const key = pushKey(walk, name);
107
127
  panels.push({
108
128
  highlight: panel,
109
129
  name,
110
130
  key: key.note,
111
- range: key.scale ?? ""
131
+ range: key.scale ?? "",
132
+ firstKeyRow
112
133
  });
113
134
  }
114
135
  } else {
115
136
  for (const walk of lift?.walks ?? []) {
116
137
  pushKey(walk, "");
117
138
  }
118
- panels.push({ highlight: lift, name: "", key: "", range: "" });
139
+ if (threadsPasses(lift?.walks ?? [])) {
140
+ threadKeys.push({ panel: "", note: passesKey(lift?.walks ?? []) });
141
+ }
142
+ panels.push({
143
+ highlight: lift,
144
+ name: "",
145
+ key: "",
146
+ range: "",
147
+ firstKeyRow: 0
148
+ });
119
149
  }
120
150
  const pins = columns(["gene", "x", "y", "covered", "bp"]);
121
151
  const exons = columns(["gene", "node", "stretch", "x", "y"]);
@@ -146,7 +176,12 @@ function figureData(graph, layout, o = {}) {
146
176
  "y",
147
177
  "color",
148
178
  "alpha",
149
- "width"
179
+ "width",
180
+ "walk",
181
+ "pass",
182
+ "nx",
183
+ "ny",
184
+ "offset"
150
185
  ]);
151
186
  const edges = columns([
152
187
  "panel",
@@ -163,7 +198,15 @@ function figureData(graph, layout, o = {}) {
163
198
  "color",
164
199
  "alpha",
165
200
  "width",
166
- "deletion"
201
+ "deletion",
202
+ "walk",
203
+ "pass",
204
+ "nx",
205
+ "ny",
206
+ "offset",
207
+ "nx1",
208
+ "ny1",
209
+ "offset1"
167
210
  ]);
168
211
  const arrows = columns([
169
212
  "panel",
@@ -176,12 +219,18 @@ function figureData(graph, layout, o = {}) {
176
219
  "color",
177
220
  "alpha"
178
221
  ]);
179
- for (const { highlight, name: panel } of panels) {
222
+ for (const { highlight, name: panel, firstKeyRow } of panels) {
180
223
  const batch = geometry(highlight, axis);
224
+ const keyRowOf = (walk) => walk === void 0 ? null : firstKeyRow + walk;
225
+ const screen = ({ normal, offsetX }) => ({
226
+ nx: normal.nx,
227
+ ny: normal.ny,
228
+ offset: offsetX * axis.scaleX
229
+ });
181
230
  for (const [node, run] of batch.nodeStrokeRuns) {
182
231
  for (let i = run.start; i < run.start + run.count; i++) {
183
232
  const s = batch.nodeStrokes[i];
184
- for (const p of s.points) {
233
+ s.points.forEach((p, k) => {
185
234
  nodes.push({
186
235
  panel,
187
236
  node,
@@ -190,15 +239,28 @@ function figureData(graph, layout, o = {}) {
190
239
  y: p.y,
191
240
  color: cssHex(s.color),
192
241
  alpha: alphaOf(s.color),
193
- width: s.thickness * 2
242
+ width: s.thickness * 2,
243
+ walk: keyRowOf(s.walk),
244
+ pass: s.pass ?? null,
245
+ nx: s.normals?.[k]?.nx ?? 0,
246
+ ny: s.normals?.[k]?.ny ?? 0,
247
+ offset: (s.offsetX ?? 0) * axis.scaleX
194
248
  });
195
- }
249
+ });
196
250
  }
197
251
  }
198
252
  for (const [edge, run] of batch.edgeCurveRuns) {
199
253
  for (let i = run.start; i < run.start + run.count; i++) {
200
254
  const b = batch.edgeCurves[i];
201
- for (const c of b.curves) {
255
+ const n = b.curves.length;
256
+ const start = b.normal && { normal: b.normal, offsetX: b.offsetX ?? 0 };
257
+ const finish = b.endNormal && {
258
+ normal: b.endNormal,
259
+ offsetX: b.endOffsetX ?? 0
260
+ };
261
+ const slideAlong = (along) => start && finish ? screen(laneSlideAt(start, finish, along)) : { nx: 0, ny: 0, offset: 0 };
262
+ b.curves.forEach((c, k) => {
263
+ const end = slideAlong((k + 1) / n);
202
264
  edges.push({
203
265
  panel,
204
266
  edge,
@@ -207,9 +269,15 @@ function figureData(graph, layout, o = {}) {
207
269
  color: cssHex(b.color),
208
270
  alpha: alphaOf(b.color),
209
271
  width: b.thickness * 2,
210
- deletion: drawnDeletions.bypassed.has(edge)
272
+ deletion: drawnDeletions.bypassed.has(edge),
273
+ walk: keyRowOf(b.walk),
274
+ pass: b.pass ?? null,
275
+ ...slideAlong(k / n),
276
+ nx1: end.nx,
277
+ ny1: end.ny,
278
+ offset1: end.offset
211
279
  });
212
- }
280
+ });
213
281
  }
214
282
  }
215
283
  for (const [edge, run] of batch.arrowRuns) {
@@ -253,6 +321,7 @@ function figureData(graph, layout, o = {}) {
253
321
  range: panels.map((p) => p.range)
254
322
  },
255
323
  keys: keys.out,
324
+ threadKeys: threadKeys.out,
256
325
  pins: pins.out,
257
326
  exons: exons.out,
258
327
  walkNames: [...new Set((graph.paths ?? []).map((p) => p.name))],
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  nodesUnderBox
3
- } from "./chunk-LH436HS2.js";
3
+ } from "./chunk-4JDO7ZLN.js";
4
4
  import {
5
5
  graphLabels,
6
6
  rowLabelBox
7
- } from "./chunk-N73RA4DR.js";
7
+ } from "./chunk-AURNOR27.js";
8
8
  import {
9
9
  LABEL_CHAR_PX,
10
10
  LABEL_PAD,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  REFERENCE_RAMP_ALT_COLOR,
3
3
  hslToRgb
4
- } from "./chunk-VXKL2ZLR.js";
4
+ } from "./chunk-GDZQFELP.js";
5
5
  import {
6
6
  packAbgr
7
7
  } from "./chunk-G2FD7S3C.js";
@@ -33,9 +33,40 @@ function resolveEncoding(layer, reference, picked, alone = true) {
33
33
  const field = isField(askedField) ? askedField : alone ? "progress" : "walk";
34
34
  const family = reference ? "grey" : FAMILIES[picked % FAMILIES.length];
35
35
  const scheme = isScheme(askedScheme) ? askedScheme === "rainbow" && field !== "reference" ? family : askedScheme : family;
36
- return { field, scheme };
36
+ const round = Math.floor(picked / FAMILIES.length) % SHADES.length;
37
+ return field === "walk" && scheme === family && round > 0 ? { field, scheme, shade: SHADES[round] } : alone || field === "walk" ? { field, scheme } : { field, scheme, darkest: TOGETHER_DARKEST };
37
38
  }
39
+ var TOGETHER_DARKEST = 0.55;
38
40
  var BASE_T = 0.5;
41
+ var SHADES = [BASE_T, 0.85, 0.2];
42
+ var STRETCH_GAP = 0.08;
43
+ var rampsOn = ({ field, scheme }) => field !== "walk" && scheme !== "rainbow";
44
+ function splitFamilies(encodings) {
45
+ const counts = /* @__PURE__ */ new Map();
46
+ for (const e of encodings) {
47
+ if (rampsOn(e)) {
48
+ counts.set(e.scheme, (counts.get(e.scheme) ?? 0) + 1);
49
+ }
50
+ }
51
+ const seen = /* @__PURE__ */ new Map();
52
+ return encodings.map((e) => {
53
+ const k = rampsOn(e) ? counts.get(e.scheme) : 1;
54
+ if (k < 2) {
55
+ return e;
56
+ }
57
+ const j = seen.get(e.scheme) ?? 0;
58
+ seen.set(e.scheme, j + 1);
59
+ const half = STRETCH_GAP / 2;
60
+ return {
61
+ ...e,
62
+ stretch: [
63
+ j / k + (j > 0 ? half : 0),
64
+ (j + 1) / k - (j < k - 1 ? half : 0)
65
+ ]
66
+ };
67
+ });
68
+ }
69
+ var along = ({ stretch }, t) => stretch ? stretch[0] + (stretch[1] - stretch[0]) * t : t;
39
70
  var toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
40
71
  var toGamma = (c) => c <= 31308e-7 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;
41
72
  function oklab(hex) {
@@ -72,7 +103,7 @@ function oklabEnds(scheme) {
72
103
  }
73
104
  return endsCache.get(scheme);
74
105
  }
75
- function schemeRgb(scheme, t) {
106
+ function schemeRgb(scheme, t, darkest = 0) {
76
107
  const x = Math.max(0, Math.min(1, t));
77
108
  const ends = oklabEnds(scheme);
78
109
  if (!ends) {
@@ -83,27 +114,32 @@ function schemeRgb(scheme, t) {
83
114
  ).map((c) => c * 255);
84
115
  }
85
116
  const [from, to] = ends;
86
- return oklabToRgb(from.map((v, i) => v + (to[i] - v) * x));
117
+ const light = from[0];
118
+ const dark = to[0];
119
+ const reach = dark < darkest && light > darkest ? (light - darkest) / (light - dark) : 1;
120
+ return oklabToRgb(from.map((v, i) => v + (to[i] - v) * x * reach));
87
121
  }
88
- function schemeCss(scheme, t) {
89
- const [r, g, b] = schemeRgb(scheme, t).map(Math.round);
122
+ function schemeCss(scheme, t, darkest) {
123
+ const [r, g, b] = schemeRgb(scheme, t, darkest).map(Math.round);
90
124
  return `rgb(${r}, ${g}, ${b})`;
91
125
  }
92
- function schemeColor(scheme, t) {
93
- const [r, g, b] = schemeRgb(scheme, t).map(Math.round);
126
+ function schemeColor(scheme, t, darkest) {
127
+ const [r, g, b] = schemeRgb(scheme, t, darkest).map(Math.round);
94
128
  return packAbgr(r, g, b, 255);
95
129
  }
96
- function encodedColor({ field, scheme }, t) {
97
- return field === "walk" ? schemeColor(scheme, BASE_T) : t === void 0 ? NO_VALUE_COLOR : schemeColor(scheme, t);
130
+ function encodedColor(encoding, t) {
131
+ const { field, scheme, darkest, shade = BASE_T } = encoding;
132
+ return field === "walk" ? schemeColor(scheme, shade) : t === void 0 ? NO_VALUE_COLOR : schemeColor(scheme, along(encoding, t), darkest);
98
133
  }
99
134
  var NO_VALUE_COLOR = REFERENCE_RAMP_ALT_COLOR;
100
- function encodingStops({ field, scheme }) {
135
+ function encodingStops(encoding) {
136
+ const { field, scheme, darkest, shade = BASE_T } = encoding;
101
137
  const stop = (offset, t) => ({
102
138
  offset,
103
- color: schemeCss(scheme, t),
104
- abgr: schemeColor(scheme, t)
139
+ color: schemeCss(scheme, t, darkest),
140
+ abgr: schemeColor(scheme, t, darkest)
105
141
  });
106
- return field === "walk" ? [stop(0, BASE_T)] : Array.from({ length: 7 }, (_, i) => stop(i / 6, i / 6));
142
+ return field === "walk" ? [stop(0, shade)] : Array.from({ length: 7 }, (_, i) => stop(i / 6, along(encoding, i / 6)));
107
143
  }
108
144
  function encodingSwatchCss(encoding) {
109
145
  const stops = encodingStops(encoding);
@@ -114,6 +150,7 @@ export {
114
150
  WALK_FIELDS,
115
151
  WALK_SCHEMES,
116
152
  resolveEncoding,
153
+ splitFamilies,
117
154
  schemeRgb,
118
155
  schemeCss,
119
156
  schemeColor,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  walkRows
3
- } from "./chunk-BXE3SBBN.js";
3
+ } from "./chunk-C3KAPREU.js";
4
4
  import {
5
5
  ROW_HEIGHT_PX
6
6
  } from "./chunk-CPMHA4W5.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pathSteps
3
- } from "./chunk-63XWYNID.js";
3
+ } from "./chunk-BDS5VZYZ.js";
4
4
  import {
5
5
  pathOrigin
6
6
  } from "./chunk-3YBP46PB.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  groupDigits
3
- } from "./chunk-N73RA4DR.js";
3
+ } from "./chunk-AURNOR27.js";
4
4
  import {
5
5
  pathOrigin
6
6
  } from "./chunk-3YBP46PB.js";
@@ -52,18 +52,24 @@ function pathLegend(paths, colors) {
52
52
  firstOf.set(path.name, i);
53
53
  }
54
54
  });
55
- const entries = [...firstOf].map(([name, i]) => ({ name, i }));
55
+ const entries = [...firstOf].map(([name2, i]) => ({ name: name2, i }));
56
56
  const named = entries.map((e) => labelTiers(e.name));
57
- const candidates = [0, 1, 2].flatMap((t) => [
58
- entries.map((_, k) => named[k][t]),
59
- entries.map((e, k) => offsetTiers(e.name, named[k])[t])
60
- ]);
57
+ const name = (t) => entries.map((_, k) => named[k][t]);
58
+ const offset = (t) => entries.map((e, k) => offsetTiers(e.name, named[k])[t]);
59
+ const candidates = [
60
+ name(0),
61
+ name(1),
62
+ offset(0),
63
+ name(2),
64
+ offset(1),
65
+ offset(2)
66
+ ];
61
67
  const distinct = candidates.find(
62
68
  (labels2) => new Set(labels2).size === entries.length
63
69
  );
64
70
  const labels = distinct ?? candidates.at(-1);
65
- return entries.map(({ name, i }, k) => ({
66
- name,
71
+ return entries.map(({ name: name2, i }, k) => ({
72
+ name: name2,
67
73
  label: labels[k],
68
74
  color: colors?.[i] ?? pathCssColor(i, paths.length)
69
75
  }));
@@ -2,7 +2,7 @@ import {
2
2
  LIFT_BACKDROP_CSS,
3
3
  computeColorSchemeRange,
4
4
  getNodeColor
5
- } from "./chunk-VXKL2ZLR.js";
5
+ } from "./chunk-GDZQFELP.js";
6
6
  import {
7
7
  abgrToCssRgba
8
8
  } from "./chunk-G2FD7S3C.js";
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  encodedColor,
3
- resolveEncoding
4
- } from "./chunk-6RB5ZQ34.js";
3
+ resolveEncoding,
4
+ splitFamilies
5
+ } from "./chunk-UEWIGD52.js";
5
6
  import {
6
7
  rampFraction
7
- } from "./chunk-VXKL2ZLR.js";
8
+ } from "./chunk-GDZQFELP.js";
8
9
  import {
9
10
  gapParts
10
11
  } from "./chunk-LG2UK4MB.js";
@@ -54,6 +55,8 @@ function highlightOf(graph, name, { byId, edgeAt }) {
54
55
  const nodeIds = /* @__PURE__ */ new Set();
55
56
  const edgeIndexes = /* @__PURE__ */ new Set();
56
57
  const progress = /* @__PURE__ */ new Map();
58
+ const passes = /* @__PURE__ */ new Map();
59
+ let mostPasses = 1;
57
60
  let before = 0;
58
61
  for (const piece of pieces) {
59
62
  if (range) {
@@ -61,6 +64,9 @@ function highlightOf(graph, name, { byId, edgeAt }) {
61
64
  }
62
65
  piece.nodeIds.forEach((id, i) => {
63
66
  nodeIds.add(id);
67
+ const passed = (passes.get(id) ?? 0) + 1;
68
+ passes.set(id, passed);
69
+ mostPasses = Math.max(mostPasses, passed);
64
70
  if (i > 0) {
65
71
  const a = piece.nodeIds[i - 1];
66
72
  const index = edgeAt.get(`${a}>${id}`) ?? edgeAt.get(`${id}>${a}`);
@@ -107,6 +113,9 @@ function highlightOf(graph, name, { byId, edgeAt }) {
107
113
  nodeIds,
108
114
  edgeIndexes,
109
115
  progress,
116
+ passes,
117
+ mostPasses,
118
+ route: pieces.map((piece) => piece.nodeIds),
110
119
  steps: pieces.reduce((sum, piece) => sum + piece.nodeIds.length, 0),
111
120
  bp,
112
121
  referenceBp: referenceSpan(),
@@ -159,13 +168,18 @@ function walkLift(graph, layers, ramp) {
159
168
  return void 0;
160
169
  }
161
170
  let picked = 0;
162
- const walks = lifted.map(({ walk, layer }) => {
163
- const encoding = resolveEncoding(
164
- layer,
165
- walk.reference,
166
- walk.reference ? 0 : picked++,
167
- lifted.length === 1
168
- );
171
+ const encodings = splitFamilies(
172
+ lifted.map(
173
+ ({ walk, layer }) => resolveEncoding(
174
+ layer,
175
+ walk.reference,
176
+ walk.reference ? 0 : picked++,
177
+ lifted.length === 1
178
+ )
179
+ )
180
+ );
181
+ const walks = lifted.map(({ walk }, i) => {
182
+ const encoding = encodings[i];
169
183
  const { reversed, bp } = reversedNodes(graph, index.byId, walk);
170
184
  return {
171
185
  ...walk,