@jbrowse/plugin-alignments 3.6.4 → 3.7.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 (243) hide show
  1. package/dist/AlignmentsFeatureDetail/stateModelFactory.d.ts +4 -4
  2. package/dist/CramAdapter/CramAdapter.js +1 -1
  3. package/dist/CramAdapter/CramSlightlyLazyFeature.js +8 -7
  4. package/dist/CramAdapter/{util.js → readFeaturesToCIGAR.js} +4 -5
  5. package/dist/CramAdapter/readFeaturesToMismatches.d.ts +5 -0
  6. package/dist/CramAdapter/readFeaturesToMismatches.js +106 -0
  7. package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +6 -2
  8. package/dist/LinearAlignmentsDisplay/model.js +3 -2
  9. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +17 -2
  10. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +2 -2
  11. package/dist/LinearPileupDisplay/components/GroupByDialog.js +4 -4
  12. package/dist/LinearPileupDisplay/components/SetModificationThresholdDialog.d.ts +10 -0
  13. package/dist/LinearPileupDisplay/components/SetModificationThresholdDialog.js +39 -0
  14. package/dist/LinearPileupDisplay/doAfterAttach.d.ts +1 -0
  15. package/dist/LinearPileupDisplay/doAfterAttach.js +3 -2
  16. package/dist/LinearPileupDisplay/model.d.ts +20 -2
  17. package/dist/LinearPileupDisplay/model.js +39 -4
  18. package/dist/LinearReadArcsDisplay/index.js +1 -1
  19. package/dist/LinearReadArcsDisplay/model.d.ts +23 -30
  20. package/dist/LinearReadArcsDisplay/model.js +5 -86
  21. package/dist/LinearReadCloudDisplay/components/ReactComponent.js +84 -2
  22. package/dist/LinearReadCloudDisplay/components/SetFeatureHeightDialog.d.ts +10 -0
  23. package/dist/LinearReadCloudDisplay/components/SetFeatureHeightDialog.js +26 -0
  24. package/dist/LinearReadCloudDisplay/configSchema.d.ts +7 -0
  25. package/dist/LinearReadCloudDisplay/configSchema.js +5 -0
  26. package/dist/LinearReadCloudDisplay/drawFeatsAbstract.js +13 -0
  27. package/dist/LinearReadCloudDisplay/drawFeatsCloud.js +24 -0
  28. package/dist/LinearReadCloudDisplay/drawFeatsCommon.d.ts +23 -0
  29. package/dist/LinearReadCloudDisplay/drawFeatsCommon.js +198 -0
  30. package/dist/LinearReadCloudDisplay/drawFeatsStack.d.ts +2 -0
  31. package/dist/LinearReadCloudDisplay/drawFeatsStack.js +36 -0
  32. package/dist/LinearReadCloudDisplay/index.js +1 -1
  33. package/dist/LinearReadCloudDisplay/model.d.ts +51 -31
  34. package/dist/LinearReadCloudDisplay/model.js +93 -78
  35. package/dist/LinearSNPCoverageDisplay/components/TooltipContents.d.ts +3 -0
  36. package/dist/LinearSNPCoverageDisplay/components/TooltipContents.js +148 -19
  37. package/dist/LinearSNPCoverageDisplay/model.js +14 -3
  38. package/dist/MismatchParser/cigarToMismatches.js +1 -0
  39. package/dist/ModificationParser/detectSimplexModifications.d.ts +4 -0
  40. package/dist/ModificationParser/detectSimplexModifications.js +20 -0
  41. package/dist/ModificationParser/getModPositions.d.ts +1 -1
  42. package/dist/ModificationParser/getModPositions.js +13 -16
  43. package/dist/PileupRPC/methods/GetVisibleModifications.d.ts +4 -1
  44. package/dist/PileupRPC/methods/GetVisibleModifications.js +16 -3
  45. package/dist/PileupRenderer/PileupRenderer.d.ts +6 -1
  46. package/dist/PileupRenderer/PileupRenderer.js +11 -14
  47. package/dist/PileupRenderer/components/PileupRendering.d.ts +8 -15
  48. package/dist/PileupRenderer/components/PileupRendering.js +18 -2
  49. package/dist/PileupRenderer/makeImageData.d.ts +5 -2
  50. package/dist/PileupRenderer/makeImageData.js +37 -6
  51. package/dist/PileupRenderer/{getAlignmentShapeColor.js → renderers/getAlignmentShapeColor.js} +2 -2
  52. package/{esm/PileupRenderer → dist/PileupRenderer/renderers}/renderAlignment.d.ts +6 -3
  53. package/dist/PileupRenderer/{renderAlignment.js → renderers/renderAlignment.js} +12 -3
  54. package/{esm/PileupRenderer → dist/PileupRenderer/renderers}/renderAlignmentShape.d.ts +2 -2
  55. package/dist/PileupRenderer/{renderAlignmentShape.js → renderers/renderAlignmentShape.js} +1 -1
  56. package/dist/PileupRenderer/{renderMethylation.d.ts → renderers/renderMethylation.d.ts} +2 -2
  57. package/dist/PileupRenderer/{renderMethylation.js → renderers/renderMethylation.js} +2 -2
  58. package/dist/PileupRenderer/{renderMismatches.d.ts → renderers/renderMismatches.d.ts} +6 -3
  59. package/dist/PileupRenderer/{renderMismatches.js → renderers/renderMismatches.js} +29 -5
  60. package/dist/PileupRenderer/{renderModifications.d.ts → renderers/renderModifications.d.ts} +6 -3
  61. package/dist/PileupRenderer/renderers/renderModifications.js +84 -0
  62. package/dist/PileupRenderer/{renderPerBaseLettering.d.ts → renderers/renderPerBaseLettering.d.ts} +1 -1
  63. package/dist/PileupRenderer/{renderPerBaseLettering.js → renderers/renderPerBaseLettering.js} +1 -1
  64. package/{esm/PileupRenderer → dist/PileupRenderer/renderers}/renderPerBaseQuality.d.ts +1 -1
  65. package/dist/PileupRenderer/{renderPerBaseQuality.js → renderers/renderPerBaseQuality.js} +1 -1
  66. package/dist/PileupRenderer/{renderSoftClipping.d.ts → renderers/renderSoftClipping.d.ts} +2 -2
  67. package/dist/PileupRenderer/{renderSoftClipping.js → renderers/renderSoftClipping.js} +2 -2
  68. package/dist/PileupRenderer/types.d.ts +6 -0
  69. package/dist/SNPCoverageAdapter/generateCoverageBins.js +5 -4
  70. package/dist/SNPCoverageAdapter/processModifications.js +14 -4
  71. package/dist/SNPCoverageRenderer/makeImage.js +44 -33
  72. package/dist/SNPCoverageRenderer/types.d.ts +1 -0
  73. package/dist/shared/LinearReadDisplayBaseMixin.d.ts +24 -0
  74. package/dist/shared/LinearReadDisplayBaseMixin.js +50 -0
  75. package/dist/shared/LinearReadDisplayWithLayoutMixin.d.ts +11 -0
  76. package/dist/shared/LinearReadDisplayWithLayoutMixin.js +24 -0
  77. package/dist/shared/LinearReadDisplayWithPairFiltersMixin.d.ts +11 -0
  78. package/dist/shared/LinearReadDisplayWithPairFiltersMixin.js +27 -0
  79. package/dist/shared/afterAttach.js +3 -2
  80. package/dist/shared/chainToSimpleFeature.d.ts +3 -0
  81. package/dist/shared/chainToSimpleFeature.js +43 -0
  82. package/dist/shared/chevron.d.ts +1 -0
  83. package/dist/shared/chevron.js +27 -0
  84. package/dist/shared/color.d.ts +43 -6
  85. package/dist/shared/color.js +101 -22
  86. package/dist/shared/components/BaseDisplayComponent.d.ts +12 -3
  87. package/dist/shared/components/BaseDisplayComponent.js +2 -2
  88. package/dist/shared/components/SetFeatureHeightDialog.d.ts +10 -0
  89. package/dist/shared/components/SetFeatureHeightDialog.js +26 -0
  90. package/dist/shared/components/SetMaxHeightDialog.d.ts +8 -0
  91. package/dist/shared/components/SetMaxHeightDialog.js +28 -0
  92. package/dist/shared/drawLongReadChains.d.ts +24 -0
  93. package/dist/shared/drawLongReadChains.js +104 -0
  94. package/dist/shared/drawPairChains.d.ts +24 -0
  95. package/dist/shared/drawPairChains.js +94 -0
  96. package/dist/shared/flatbushType.d.ts +12 -0
  97. package/dist/shared/flatbushType.js +2 -0
  98. package/dist/shared/getUniqueModifications.d.ts +4 -1
  99. package/dist/shared/menuItems.d.ts +23 -0
  100. package/dist/shared/menuItems.js +89 -0
  101. package/dist/shared/modificationData.d.ts +6 -0
  102. package/dist/shared/modificationData.js +22 -0
  103. package/dist/shared/primaryStrand.d.ts +3 -0
  104. package/dist/shared/primaryStrand.js +24 -0
  105. package/dist/shared/types.d.ts +2 -0
  106. package/dist/shared/util.d.ts +2 -0
  107. package/dist/shared/util.js +6 -1
  108. package/dist/util.d.ts +1 -6
  109. package/dist/util.js +4 -15
  110. package/esm/AlignmentsFeatureDetail/stateModelFactory.d.ts +4 -4
  111. package/esm/CramAdapter/CramAdapter.js +1 -1
  112. package/esm/CramAdapter/CramSlightlyLazyFeature.js +2 -1
  113. package/esm/CramAdapter/{util.js → readFeaturesToCIGAR.js} +4 -5
  114. package/esm/CramAdapter/readFeaturesToMismatches.d.ts +5 -0
  115. package/esm/CramAdapter/readFeaturesToMismatches.js +103 -0
  116. package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +6 -2
  117. package/esm/LinearAlignmentsDisplay/model.js +3 -2
  118. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +17 -2
  119. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +2 -2
  120. package/esm/LinearPileupDisplay/components/GroupByDialog.js +4 -4
  121. package/esm/LinearPileupDisplay/components/SetModificationThresholdDialog.d.ts +10 -0
  122. package/esm/LinearPileupDisplay/components/SetModificationThresholdDialog.js +37 -0
  123. package/esm/LinearPileupDisplay/doAfterAttach.d.ts +1 -0
  124. package/esm/LinearPileupDisplay/doAfterAttach.js +3 -2
  125. package/esm/LinearPileupDisplay/model.d.ts +20 -2
  126. package/esm/LinearPileupDisplay/model.js +39 -4
  127. package/esm/LinearReadArcsDisplay/index.js +1 -1
  128. package/esm/LinearReadArcsDisplay/model.d.ts +23 -30
  129. package/esm/LinearReadArcsDisplay/model.js +5 -83
  130. package/esm/LinearReadCloudDisplay/components/ReactComponent.js +86 -4
  131. package/esm/LinearReadCloudDisplay/components/SetFeatureHeightDialog.d.ts +10 -0
  132. package/esm/LinearReadCloudDisplay/components/SetFeatureHeightDialog.js +24 -0
  133. package/esm/LinearReadCloudDisplay/configSchema.d.ts +7 -0
  134. package/esm/LinearReadCloudDisplay/configSchema.js +5 -0
  135. package/esm/LinearReadCloudDisplay/drawFeatsAbstract.d.ts +2 -0
  136. package/esm/LinearReadCloudDisplay/drawFeatsAbstract.js +10 -0
  137. package/esm/LinearReadCloudDisplay/drawFeatsCloud.d.ts +2 -0
  138. package/esm/LinearReadCloudDisplay/drawFeatsCloud.js +21 -0
  139. package/esm/LinearReadCloudDisplay/drawFeatsCommon.d.ts +23 -0
  140. package/esm/LinearReadCloudDisplay/drawFeatsCommon.js +187 -0
  141. package/esm/LinearReadCloudDisplay/drawFeatsStack.d.ts +2 -0
  142. package/esm/LinearReadCloudDisplay/drawFeatsStack.js +30 -0
  143. package/esm/LinearReadCloudDisplay/index.js +1 -1
  144. package/esm/LinearReadCloudDisplay/model.d.ts +51 -31
  145. package/esm/LinearReadCloudDisplay/model.js +94 -76
  146. package/esm/LinearSNPCoverageDisplay/components/TooltipContents.d.ts +3 -0
  147. package/esm/LinearSNPCoverageDisplay/components/TooltipContents.js +149 -20
  148. package/esm/LinearSNPCoverageDisplay/model.js +14 -3
  149. package/esm/MismatchParser/cigarToMismatches.js +1 -0
  150. package/esm/ModificationParser/detectSimplexModifications.d.ts +4 -0
  151. package/esm/ModificationParser/detectSimplexModifications.js +17 -0
  152. package/esm/ModificationParser/getModPositions.d.ts +1 -1
  153. package/esm/ModificationParser/getModPositions.js +13 -16
  154. package/esm/PileupRPC/methods/GetVisibleModifications.d.ts +4 -1
  155. package/esm/PileupRPC/methods/GetVisibleModifications.js +16 -3
  156. package/esm/PileupRenderer/PileupRenderer.d.ts +6 -1
  157. package/esm/PileupRenderer/PileupRenderer.js +11 -14
  158. package/esm/PileupRenderer/components/PileupRendering.d.ts +8 -15
  159. package/esm/PileupRenderer/components/PileupRendering.js +16 -3
  160. package/esm/PileupRenderer/makeImageData.d.ts +5 -2
  161. package/esm/PileupRenderer/makeImageData.js +34 -6
  162. package/esm/PileupRenderer/{getAlignmentShapeColor.js → renderers/getAlignmentShapeColor.js} +2 -2
  163. package/{dist/PileupRenderer → esm/PileupRenderer/renderers}/renderAlignment.d.ts +6 -3
  164. package/esm/PileupRenderer/{renderAlignment.js → renderers/renderAlignment.js} +12 -3
  165. package/{dist/PileupRenderer → esm/PileupRenderer/renderers}/renderAlignmentShape.d.ts +2 -2
  166. package/esm/PileupRenderer/{renderAlignmentShape.js → renderers/renderAlignmentShape.js} +1 -1
  167. package/esm/PileupRenderer/{renderMethylation.d.ts → renderers/renderMethylation.d.ts} +2 -2
  168. package/esm/PileupRenderer/{renderMethylation.js → renderers/renderMethylation.js} +2 -2
  169. package/esm/PileupRenderer/{renderMismatches.d.ts → renderers/renderMismatches.d.ts} +6 -3
  170. package/esm/PileupRenderer/{renderMismatches.js → renderers/renderMismatches.js} +29 -5
  171. package/esm/PileupRenderer/{renderModifications.d.ts → renderers/renderModifications.d.ts} +6 -3
  172. package/esm/PileupRenderer/renderers/renderModifications.js +81 -0
  173. package/esm/PileupRenderer/{renderPerBaseLettering.d.ts → renderers/renderPerBaseLettering.d.ts} +1 -1
  174. package/esm/PileupRenderer/{renderPerBaseLettering.js → renderers/renderPerBaseLettering.js} +1 -1
  175. package/{dist/PileupRenderer → esm/PileupRenderer/renderers}/renderPerBaseQuality.d.ts +1 -1
  176. package/esm/PileupRenderer/{renderPerBaseQuality.js → renderers/renderPerBaseQuality.js} +1 -1
  177. package/esm/PileupRenderer/{renderSoftClipping.d.ts → renderers/renderSoftClipping.d.ts} +2 -2
  178. package/esm/PileupRenderer/{renderSoftClipping.js → renderers/renderSoftClipping.js} +2 -2
  179. package/esm/PileupRenderer/types.d.ts +6 -0
  180. package/esm/SNPCoverageAdapter/generateCoverageBins.js +5 -4
  181. package/esm/SNPCoverageAdapter/processModifications.js +14 -4
  182. package/esm/SNPCoverageRenderer/makeImage.js +44 -33
  183. package/esm/SNPCoverageRenderer/types.d.ts +1 -0
  184. package/esm/shared/LinearReadDisplayBaseMixin.d.ts +24 -0
  185. package/esm/shared/LinearReadDisplayBaseMixin.js +47 -0
  186. package/esm/shared/LinearReadDisplayWithLayoutMixin.d.ts +11 -0
  187. package/esm/shared/LinearReadDisplayWithLayoutMixin.js +21 -0
  188. package/esm/shared/LinearReadDisplayWithPairFiltersMixin.d.ts +11 -0
  189. package/esm/shared/LinearReadDisplayWithPairFiltersMixin.js +24 -0
  190. package/esm/shared/afterAttach.js +3 -2
  191. package/esm/shared/chainToSimpleFeature.d.ts +3 -0
  192. package/esm/shared/chainToSimpleFeature.js +40 -0
  193. package/esm/shared/chevron.d.ts +1 -0
  194. package/esm/shared/chevron.js +24 -0
  195. package/esm/shared/color.d.ts +43 -6
  196. package/esm/shared/color.js +96 -20
  197. package/esm/shared/components/BaseDisplayComponent.d.ts +12 -3
  198. package/esm/shared/components/BaseDisplayComponent.js +2 -2
  199. package/esm/shared/components/SetFeatureHeightDialog.d.ts +10 -0
  200. package/esm/shared/components/SetFeatureHeightDialog.js +24 -0
  201. package/esm/shared/components/SetMaxHeightDialog.d.ts +8 -0
  202. package/esm/shared/components/SetMaxHeightDialog.js +26 -0
  203. package/esm/shared/drawLongReadChains.d.ts +24 -0
  204. package/esm/shared/drawLongReadChains.js +101 -0
  205. package/esm/shared/drawPairChains.d.ts +24 -0
  206. package/esm/shared/drawPairChains.js +91 -0
  207. package/esm/shared/flatbushType.d.ts +12 -0
  208. package/esm/shared/flatbushType.js +1 -0
  209. package/esm/shared/getUniqueModifications.d.ts +4 -1
  210. package/esm/shared/menuItems.d.ts +23 -0
  211. package/esm/shared/menuItems.js +49 -0
  212. package/esm/shared/modificationData.d.ts +6 -0
  213. package/esm/shared/modificationData.js +18 -0
  214. package/esm/shared/primaryStrand.d.ts +3 -0
  215. package/esm/shared/primaryStrand.js +20 -0
  216. package/esm/shared/types.d.ts +2 -0
  217. package/esm/shared/util.d.ts +2 -0
  218. package/esm/shared/util.js +4 -0
  219. package/esm/util.d.ts +1 -6
  220. package/esm/util.js +2 -14
  221. package/package.json +6 -6
  222. package/dist/LinearReadCloudDisplay/drawFeats.js +0 -27
  223. package/dist/LinearReadCloudDisplay/drawLongReadChains.d.ts +0 -11
  224. package/dist/LinearReadCloudDisplay/drawLongReadChains.js +0 -64
  225. package/dist/LinearReadCloudDisplay/drawPairChains.d.ts +0 -17
  226. package/dist/LinearReadCloudDisplay/drawPairChains.js +0 -94
  227. package/dist/PileupRenderer/renderModifications.js +0 -44
  228. package/esm/LinearReadCloudDisplay/drawFeats.js +0 -24
  229. package/esm/LinearReadCloudDisplay/drawLongReadChains.d.ts +0 -11
  230. package/esm/LinearReadCloudDisplay/drawLongReadChains.js +0 -61
  231. package/esm/LinearReadCloudDisplay/drawPairChains.d.ts +0 -17
  232. package/esm/LinearReadCloudDisplay/drawPairChains.js +0 -90
  233. package/esm/PileupRenderer/renderModifications.js +0 -41
  234. /package/dist/CramAdapter/{util.d.ts → readFeaturesToCIGAR.d.ts} +0 -0
  235. /package/dist/LinearReadCloudDisplay/{drawFeats.d.ts → drawFeatsAbstract.d.ts} +0 -0
  236. /package/{esm/LinearReadCloudDisplay/drawFeats.d.ts → dist/LinearReadCloudDisplay/drawFeatsCloud.d.ts} +0 -0
  237. /package/dist/PileupRenderer/{getAlignmentShapeColor.d.ts → renderers/getAlignmentShapeColor.d.ts} +0 -0
  238. /package/dist/{LinearReadCloudDisplay/util.d.ts → shared/canvasUtils.d.ts} +0 -0
  239. /package/dist/{LinearReadCloudDisplay/util.js → shared/canvasUtils.js} +0 -0
  240. /package/esm/CramAdapter/{util.d.ts → readFeaturesToCIGAR.d.ts} +0 -0
  241. /package/esm/PileupRenderer/{getAlignmentShapeColor.d.ts → renderers/getAlignmentShapeColor.d.ts} +0 -0
  242. /package/esm/{LinearReadCloudDisplay/util.d.ts → shared/canvasUtils.d.ts} +0 -0
  243. /package/esm/{LinearReadCloudDisplay/util.js → shared/canvasUtils.js} +0 -0
@@ -0,0 +1,81 @@
1
+ import { bpSpanPx, max, sum } from '@jbrowse/core/util';
2
+ import { getNextRefPos } from '../../MismatchParser';
3
+ import { getModPositions } from '../../ModificationParser/getModPositions';
4
+ import { getModProbabilities } from '../../ModificationParser/getModProbabilities';
5
+ import { getMaxProbModAtEachPosition } from '../../shared/getMaximumModificationAtEachPosition';
6
+ import { getModificationName } from '../../shared/modificationData';
7
+ import { alphaColor } from '../../shared/util';
8
+ import { getTagAlt } from '../../util';
9
+ import { fillRect } from '../util';
10
+ export function renderModifications({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth, cigarOps, }) {
11
+ var _a, _b, _c, _d, _e;
12
+ const items = [];
13
+ const coords = [];
14
+ const { feature, topPx, heightPx } = feat;
15
+ const { colorBy, visibleModifications = {} } = renderArgs;
16
+ const seq = feature.get('seq');
17
+ if (!seq) {
18
+ return { coords, items };
19
+ }
20
+ const start = feature.get('start');
21
+ const isolatedModification = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.isolatedModification;
22
+ const twoColor = (_b = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _b === void 0 ? void 0 : _b.twoColor;
23
+ const modificationThreshold = (_d = (_c = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _c === void 0 ? void 0 : _c.threshold) !== null && _d !== void 0 ? _d : 10;
24
+ const thresholdFraction = modificationThreshold / 100;
25
+ const fstrand = feature.get('strand');
26
+ const mm = getTagAlt(feature, 'MM', 'Mm') || '';
27
+ const modifications = getModPositions(mm, seq, fstrand);
28
+ const probabilities = getModProbabilities(feature);
29
+ const modsByPosition = new Map();
30
+ let probIndex = 0;
31
+ for (const { type, base, strand, positions } of modifications) {
32
+ for (const { ref, idx } of getNextRefPos(cigarOps, positions)) {
33
+ const prob = (probabilities === null || probabilities === void 0 ? void 0 : probabilities[probIndex + (fstrand === -1 ? positions.length - 1 - idx : idx)]) || 0;
34
+ if (!modsByPosition.has(ref)) {
35
+ modsByPosition.set(ref, []);
36
+ }
37
+ modsByPosition.get(ref).push({ type, base, strand, prob });
38
+ }
39
+ probIndex += positions.length;
40
+ }
41
+ (_e = getMaxProbModAtEachPosition(feature, cigarOps)) === null || _e === void 0 ? void 0 : _e.forEach(({ allProbs, prob, type }, pos) => {
42
+ const r = start + pos;
43
+ const [leftPx, rightPx] = bpSpanPx(r, r + 1, region, bpPerPx);
44
+ const mod = visibleModifications[type];
45
+ if (!mod) {
46
+ console.warn(`${type} not known yet`);
47
+ return;
48
+ }
49
+ if (isolatedModification && mod.type !== isolatedModification) {
50
+ return;
51
+ }
52
+ if (prob < thresholdFraction) {
53
+ return;
54
+ }
55
+ const col = mod.color || 'black';
56
+ const s = 1 - sum(allProbs);
57
+ if (twoColor && s > max(allProbs)) {
58
+ const c = alphaColor('blue', s);
59
+ const w = rightPx - leftPx + 0.5;
60
+ fillRect(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
61
+ }
62
+ else {
63
+ const c = alphaColor(col, prob);
64
+ const w = rightPx - leftPx + 0.5;
65
+ fillRect(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
66
+ }
67
+ const modsAtPos = modsByPosition.get(pos) || [];
68
+ const strandInfo = modsAtPos
69
+ .map(m => `${m.base}${m.strand}${m.type} ${getModificationName(m.type)} (${(m.prob * 100).toFixed(1)}%)`)
70
+ .join('<br/>');
71
+ items.push({
72
+ type: 'modification',
73
+ seq: strandInfo || mod.base,
74
+ modType: type,
75
+ probability: prob,
76
+ });
77
+ coords.push(leftPx, topPx, rightPx, topPx + heightPx);
78
+ pos++;
79
+ });
80
+ return { coords, items };
81
+ }
@@ -1,4 +1,4 @@
1
- import type { LayoutFeature } from './util';
1
+ import type { LayoutFeature } from '../util';
2
2
  import type { Region } from '@jbrowse/core/util';
3
3
  export declare function renderPerBaseLettering({ ctx, feat, region, bpPerPx, colorMap, colorContrastMap, charWidth, charHeight, canvasWidth, cigarOps, }: {
4
4
  ctx: CanvasRenderingContext2D;
@@ -1,5 +1,5 @@
1
1
  import { bpSpanPx } from '@jbrowse/core/util';
2
- import { fillRect } from './util';
2
+ import { fillRect } from '../util';
3
3
  export function renderPerBaseLettering({ ctx, feat, region, bpPerPx, colorMap, colorContrastMap, charWidth, charHeight, canvasWidth, cigarOps, }) {
4
4
  const heightLim = charHeight - 2;
5
5
  const { feature, topPx, heightPx } = feat;
@@ -1,4 +1,4 @@
1
- import type { LayoutFeature } from './util';
1
+ import type { LayoutFeature } from '../util';
2
2
  import type { Region } from '@jbrowse/core/util';
3
3
  export declare function renderPerBaseQuality({ ctx, feat, region, bpPerPx, canvasWidth, cigarOps, }: {
4
4
  ctx: CanvasRenderingContext2D;
@@ -1,5 +1,5 @@
1
1
  import { bpSpanPx } from '@jbrowse/core/util';
2
- import { fillRect } from './util';
2
+ import { fillRect } from '../util';
3
3
  export function renderPerBaseQuality({ ctx, feat, region, bpPerPx, canvasWidth, cigarOps, }) {
4
4
  const { feature, topPx, heightPx } = feat;
5
5
  const qual = feature.get('qual') || '';
@@ -1,5 +1,5 @@
1
- import type { ProcessedRenderArgs } from './types';
2
- import type { LayoutFeature } from './util';
1
+ import type { ProcessedRenderArgs } from '../types';
2
+ import type { LayoutFeature } from '../util';
3
3
  import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
4
4
  import type { Theme } from '@mui/material';
5
5
  export declare function renderSoftClipping({ ctx, feat, renderArgs, config, theme, colorMap, canvasWidth, }: {
@@ -1,7 +1,7 @@
1
1
  import { readConfObject } from '@jbrowse/core/configuration';
2
2
  import { bpSpanPx } from '@jbrowse/core/util';
3
- import { fillRect, getCharWidthHeight } from './util';
4
- import { parseCigar } from '../MismatchParser';
3
+ import { parseCigar } from '../../MismatchParser';
4
+ import { fillRect, getCharWidthHeight } from '../util';
5
5
  export function renderSoftClipping({ ctx, feat, renderArgs, config, theme, colorMap, canvasWidth, }) {
6
6
  const { feature, topPx, heightPx } = feat;
7
7
  const { regions, bpPerPx } = renderArgs;
@@ -7,6 +7,12 @@ export interface LayoutFeature {
7
7
  topPx: number;
8
8
  feature: Feature;
9
9
  }
10
+ export interface FlatbushItem {
11
+ type: 'insertion' | 'deletion' | 'mismatch' | 'modification';
12
+ seq: string;
13
+ modType?: string;
14
+ probability?: number;
15
+ }
10
16
  export interface RenderArgsDeserialized extends BoxRenderArgsDeserialized {
11
17
  colorBy?: ColorBy;
12
18
  colorTagMap?: Record<string, string>;
@@ -10,6 +10,7 @@ export async function generateCoverageBins({ fetchSequence, features, region, op
10
10
  const bins = [];
11
11
  const start2 = Math.max(0, region.start - 1);
12
12
  const diff = region.start - start2;
13
+ let regionSequence;
13
14
  let start = performance.now();
14
15
  for (const feature of features) {
15
16
  if (performance.now() - start > 400) {
@@ -22,11 +23,11 @@ export async function generateCoverageBins({ fetchSequence, features, region, op
22
23
  region,
23
24
  });
24
25
  if ((colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'modifications') {
25
- const regionSequence = (await fetchSequence({
26
+ regionSequence !== null && regionSequence !== void 0 ? regionSequence : (regionSequence = (await fetchSequence({
26
27
  ...region,
27
28
  start: start2,
28
29
  end: region.end + 1,
29
- })) || '';
30
+ })) || '');
30
31
  processModifications({
31
32
  feature,
32
33
  colorBy,
@@ -36,11 +37,11 @@ export async function generateCoverageBins({ fetchSequence, features, region, op
36
37
  });
37
38
  }
38
39
  else if ((colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'methylation') {
39
- const regionSequence = (await fetchSequence({
40
+ regionSequence !== null && regionSequence !== void 0 ? regionSequence : (regionSequence = (await fetchSequence({
40
41
  ...region,
41
42
  start: start2,
42
43
  end: region.end + 1,
43
- })) || '';
44
+ })) || '');
44
45
  processReferenceCpGs({
45
46
  feature,
46
47
  bins,
@@ -1,17 +1,28 @@
1
1
  import { max, sum } from '@jbrowse/core/util';
2
2
  import { incWithProbabilities } from './util';
3
+ import { parseCigar } from '../MismatchParser';
3
4
  import { getMaxProbModAtEachPosition } from '../shared/getMaximumModificationAtEachPosition';
4
5
  export function processModifications({ feature, colorBy, region, bins, regionSequence, }) {
5
- var _a, _b, _c;
6
+ var _a, _b, _c, _d, _e;
6
7
  const fstart = feature.get('start');
7
8
  const fstrand = feature.get('strand');
8
9
  const fend = feature.get('end');
9
10
  const twoColor = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.twoColor;
10
11
  const isolatedModification = (_b = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _b === void 0 ? void 0 : _b.isolatedModification;
11
- (_c = getMaxProbModAtEachPosition(feature)) === null || _c === void 0 ? void 0 : _c.forEach(({ allProbs, prob, type }, pos) => {
12
+ const seq = feature.get('seq');
13
+ const modificationThreshold = (_d = (_c = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _c === void 0 ? void 0 : _c.threshold) !== null && _d !== void 0 ? _d : 10;
14
+ const thresholdFraction = modificationThreshold / 100;
15
+ if (!seq) {
16
+ return;
17
+ }
18
+ const cigarOps = parseCigar(feature.get('CIGAR'));
19
+ (_e = getMaxProbModAtEachPosition(feature, cigarOps)) === null || _e === void 0 ? void 0 : _e.forEach(({ allProbs, prob, type }, pos) => {
12
20
  if (isolatedModification && type !== isolatedModification) {
13
21
  return;
14
22
  }
23
+ if (prob < thresholdFraction) {
24
+ return;
25
+ }
15
26
  const epos = pos + fstart - region.start;
16
27
  if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
17
28
  if (bins[epos] === undefined) {
@@ -32,9 +43,9 @@ export function processModifications({ feature, colorBy, region, bins, regionSeq
32
43
  noncov: {},
33
44
  };
34
45
  }
35
- const s = 1 - sum(allProbs);
36
46
  const bin = bins[epos];
37
47
  bin.refbase = regionSequence[epos];
48
+ const s = 1 - sum(allProbs);
38
49
  if (twoColor && s > max(allProbs)) {
39
50
  incWithProbabilities(bin, fstrand, 'nonmods', `nonmod_${type}`, s);
40
51
  }
@@ -42,6 +53,5 @@ export function processModifications({ feature, colorBy, region, bins, regionSeq
42
53
  incWithProbabilities(bin, fstrand, 'mods', `mod_${type}`, prob);
43
54
  }
44
55
  }
45
- pos++;
46
56
  });
47
57
  }
@@ -13,9 +13,26 @@ const complementBase = {
13
13
  T: 'A',
14
14
  };
15
15
  const fudgeFactor = 0.6;
16
+ function calculateModificationCounts({ base, isSimplex, refbase, snps, ref, score0, }) {
17
+ var _a, _b, _c, _d;
18
+ if (base === 'N') {
19
+ return { modifiable: score0, detectable: score0 };
20
+ }
21
+ const cmp = complementBase[base];
22
+ const baseCount = (((_a = snps[base]) === null || _a === void 0 ? void 0 : _a.entryDepth) || 0) + (refbase === base ? ref.entryDepth : 0);
23
+ const complCount = (((_b = snps[cmp]) === null || _b === void 0 ? void 0 : _b.entryDepth) || 0) + (refbase === cmp ? ref.entryDepth : 0);
24
+ const modifiable = baseCount + complCount;
25
+ const detectable = isSimplex
26
+ ? (((_c = snps[base]) === null || _c === void 0 ? void 0 : _c['1']) || 0) +
27
+ (((_d = snps[cmp]) === null || _d === void 0 ? void 0 : _d['-1']) || 0) +
28
+ (refbase === base ? ref['1'] : 0) +
29
+ (refbase === cmp ? ref['-1'] : 0)
30
+ : modifiable;
31
+ return { modifiable, detectable };
32
+ }
16
33
  export async function makeImage(ctx, props) {
17
34
  var _a;
18
- const { features, regions, bpPerPx, colorBy, displayCrossHatches, visibleModifications = {}, scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks, stopToken, } = props;
35
+ const { features, regions, bpPerPx, colorBy, displayCrossHatches, visibleModifications = {}, simplexModifications = [], scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks, stopToken, } = props;
19
36
  const theme = createJBrowseTheme(configTheme);
20
37
  const region = regions[0];
21
38
  const width = (region.end - region.start) / bpPerPx;
@@ -67,8 +84,9 @@ export async function makeImage(ctx, props) {
67
84
  const drawingModifications = colorBy.type === 'modifications';
68
85
  const drawingMethylation = colorBy.type === 'methylation';
69
86
  const isolatedModification = (_a = colorBy.modifications) === null || _a === void 0 ? void 0 : _a.isolatedModification;
87
+ const simplexSet = new Set(simplexModifications);
70
88
  forEachWithStopTokenCheck(features.values(), stopToken, feature => {
71
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
89
+ var _a;
72
90
  if (feature.get('type') === 'skip') {
73
91
  return;
74
92
  }
@@ -80,9 +98,10 @@ export async function makeImage(ctx, props) {
80
98
  let curr = 0;
81
99
  const refbase = (_a = snpinfo.refbase) === null || _a === void 0 ? void 0 : _a.toUpperCase();
82
100
  const { nonmods, mods, snps, ref } = snpinfo;
83
- for (const m of Object.keys(nonmods).sort().reverse()) {
84
- const mod = visibleModifications[m.replace('nonmod_', '')] ||
85
- visibleModifications[m.replace('mod_', '')];
101
+ const nonmodKeys = Object.keys(nonmods).sort().reverse();
102
+ for (const m of nonmodKeys) {
103
+ const modKey = m.replace(/^(nonmod_|mod_)/, '');
104
+ const mod = visibleModifications[modKey];
86
105
  if (!mod) {
87
106
  console.warn(`${m} not known yet`);
88
107
  continue;
@@ -90,19 +109,14 @@ export async function makeImage(ctx, props) {
90
109
  if (isolatedModification && mod.type !== isolatedModification) {
91
110
  continue;
92
111
  }
93
- const cmp = complementBase[mod.base];
94
- const detectable = mod.base === 'N'
95
- ? score0
96
- : (((_b = snps[mod.base]) === null || _b === void 0 ? void 0 : _b.entryDepth) || 0) +
97
- (((_c = snps[cmp]) === null || _c === void 0 ? void 0 : _c.entryDepth) || 0) +
98
- (refbase === mod.base ? ref['1'] : 0) +
99
- (refbase === cmp ? ref['-1'] : 0);
100
- const modifiable = mod.base === 'N'
101
- ? score0
102
- : (((_d = snps[mod.base]) === null || _d === void 0 ? void 0 : _d.entryDepth) || 0) +
103
- (((_e = snps[cmp]) === null || _e === void 0 ? void 0 : _e.entryDepth) || 0) +
104
- (refbase === mod.base ? ref.entryDepth : 0) +
105
- (refbase === cmp ? ref.entryDepth : 0);
112
+ const { modifiable, detectable } = calculateModificationCounts({
113
+ base: mod.base,
114
+ isSimplex: simplexSet.has(mod.type),
115
+ refbase,
116
+ snps,
117
+ ref,
118
+ score0,
119
+ });
106
120
  const { entryDepth, avgProbability = 0 } = snpinfo.nonmods[m];
107
121
  const modFraction = (modifiable / score0) * (entryDepth / detectable);
108
122
  const nonModColor = 'blue';
@@ -113,8 +127,10 @@ export async function makeImage(ctx, props) {
113
127
  ctx.fillRect(Math.round(leftPx), bottom - (curr + modFraction * height), w, modFraction * height);
114
128
  curr += modFraction * height;
115
129
  }
116
- for (const m of Object.keys(mods).sort().reverse()) {
117
- const mod = visibleModifications[m.replace('mod_', '')];
130
+ const modKeys = Object.keys(mods).sort().reverse();
131
+ for (const m of modKeys) {
132
+ const modKey = m.replace('mod_', '');
133
+ const mod = visibleModifications[modKey];
118
134
  if (!mod) {
119
135
  console.warn(`${m} not known yet`);
120
136
  continue;
@@ -122,19 +138,14 @@ export async function makeImage(ctx, props) {
122
138
  if (isolatedModification && mod.type !== isolatedModification) {
123
139
  continue;
124
140
  }
125
- const cmp = complementBase[mod.base];
126
- const detectable = mod.base === 'N'
127
- ? score0
128
- : (((_f = snps[mod.base]) === null || _f === void 0 ? void 0 : _f.entryDepth) || 0) +
129
- (((_g = snps[cmp]) === null || _g === void 0 ? void 0 : _g.entryDepth) || 0) +
130
- (refbase === mod.base ? ref['1'] : 0) +
131
- (refbase === cmp ? ref['-1'] : 0);
132
- const modifiable = mod.base === 'N'
133
- ? score0
134
- : (((_h = snps[mod.base]) === null || _h === void 0 ? void 0 : _h.entryDepth) || 0) +
135
- (((_j = snps[cmp]) === null || _j === void 0 ? void 0 : _j.entryDepth) || 0) +
136
- (refbase === mod.base ? ref.entryDepth : 0) +
137
- (refbase === cmp ? ref.entryDepth : 0);
141
+ const { modifiable, detectable } = calculateModificationCounts({
142
+ base: mod.base,
143
+ isSimplex: simplexSet.has(mod.type),
144
+ refbase,
145
+ snps,
146
+ ref,
147
+ score0,
148
+ });
138
149
  const { entryDepth, avgProbability = 0 } = mods[m];
139
150
  const modFraction = (modifiable / score0) * (entryDepth / detectable);
140
151
  const baseColor = mod.color || 'black';
@@ -15,6 +15,7 @@ export interface RenderArgsDeserializedWithFeatures extends RenderArgsDeserializ
15
15
  };
16
16
  displayCrossHatches: boolean;
17
17
  visibleModifications?: Record<string, ModificationTypeWithColor>;
18
+ simplexModifications?: string[];
18
19
  statusCallback?: (arg: string) => void;
19
20
  colorBy: ColorBy;
20
21
  }
@@ -0,0 +1,24 @@
1
+ import type { ChainData } from './fetchChains';
2
+ import type { ColorBy, FilterBy } from './types';
3
+ export declare function LinearReadDisplayBaseMixin(): import("mobx-state-tree").IModelType<{
4
+ filterBySetting: import("mobx-state-tree").IType<FilterBy | undefined, FilterBy | undefined, FilterBy | undefined>;
5
+ colorBySetting: import("mobx-state-tree").IType<ColorBy | undefined, ColorBy | undefined, ColorBy | undefined>;
6
+ }, {
7
+ loading: boolean;
8
+ chainData: ChainData | undefined;
9
+ lastDrawnOffsetPx: number | undefined;
10
+ lastDrawnBpPerPx: number;
11
+ ref: HTMLCanvasElement | null;
12
+ } & {
13
+ setLastDrawnOffsetPx(n: number): void;
14
+ setLastDrawnBpPerPx(n: number): void;
15
+ setLoading(f: boolean): void;
16
+ setRef(ref: HTMLCanvasElement | null): void;
17
+ setColorScheme(colorBy: {
18
+ type: string;
19
+ }): void;
20
+ setChainData(args: ChainData): void;
21
+ setFilterBy(filter: FilterBy): void;
22
+ } & {
23
+ readonly drawn: boolean;
24
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -0,0 +1,47 @@
1
+ import { types } from 'mobx-state-tree';
2
+ export function LinearReadDisplayBaseMixin() {
3
+ return types
4
+ .model('LinearReadDisplayBaseMixin', {
5
+ filterBySetting: types.frozen(),
6
+ colorBySetting: types.frozen(),
7
+ })
8
+ .volatile(() => ({
9
+ loading: false,
10
+ chainData: undefined,
11
+ lastDrawnOffsetPx: undefined,
12
+ lastDrawnBpPerPx: 0,
13
+ ref: null,
14
+ }))
15
+ .actions(self => ({
16
+ setLastDrawnOffsetPx(n) {
17
+ self.lastDrawnOffsetPx = n;
18
+ },
19
+ setLastDrawnBpPerPx(n) {
20
+ self.lastDrawnBpPerPx = n;
21
+ },
22
+ setLoading(f) {
23
+ self.loading = f;
24
+ },
25
+ setRef(ref) {
26
+ self.ref = ref;
27
+ },
28
+ setColorScheme(colorBy) {
29
+ self.colorBySetting = {
30
+ ...colorBy,
31
+ };
32
+ },
33
+ setChainData(args) {
34
+ self.chainData = args;
35
+ },
36
+ setFilterBy(filter) {
37
+ self.filterBySetting = {
38
+ ...filter,
39
+ };
40
+ },
41
+ }))
42
+ .views(self => ({
43
+ get drawn() {
44
+ return self.lastDrawnOffsetPx !== undefined;
45
+ },
46
+ }));
47
+ }
@@ -0,0 +1,11 @@
1
+ import type { FlatbushEntry } from './flatbushType';
2
+ import type Flatbush from '@jbrowse/core/util/flatbush';
3
+ export declare function LinearReadDisplayWithLayoutMixin(): import("mobx-state-tree").IModelType<{}, {
4
+ featureLayout: Flatbush | undefined;
5
+ mouseoverRef: HTMLCanvasElement | null;
6
+ featuresForFlatbush: FlatbushEntry[];
7
+ } & {
8
+ setFeatureLayout(layout: Flatbush): void;
9
+ setMouseoverRef(ref: HTMLCanvasElement | null): void;
10
+ setFeaturesForFlatbush(features: FlatbushEntry[]): void;
11
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -0,0 +1,21 @@
1
+ import { types } from 'mobx-state-tree';
2
+ export function LinearReadDisplayWithLayoutMixin() {
3
+ return types
4
+ .model('LinearReadDisplayWithLayoutMixin', {})
5
+ .volatile(() => ({
6
+ featureLayout: undefined,
7
+ mouseoverRef: null,
8
+ featuresForFlatbush: [],
9
+ }))
10
+ .actions(self => ({
11
+ setFeatureLayout(layout) {
12
+ self.featureLayout = layout;
13
+ },
14
+ setMouseoverRef(ref) {
15
+ self.mouseoverRef = ref;
16
+ },
17
+ setFeaturesForFlatbush(features) {
18
+ self.featuresForFlatbush = features;
19
+ },
20
+ }));
21
+ }
@@ -0,0 +1,11 @@
1
+ export declare function LinearReadDisplayWithPairFiltersMixin(): import("mobx-state-tree").IModelType<{
2
+ drawSingletons: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
3
+ drawProperPairs: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
4
+ flipStrandLongReadChains: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
5
+ featureHeight: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
6
+ }, {
7
+ setDrawSingletons(f: boolean): void;
8
+ setDrawProperPairs(f: boolean): void;
9
+ setFlipStrandLongReadChains(f: boolean): void;
10
+ setFeatureHeight(n?: number): void;
11
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -0,0 +1,24 @@
1
+ import { types } from 'mobx-state-tree';
2
+ export function LinearReadDisplayWithPairFiltersMixin() {
3
+ return types
4
+ .model('LinearReadDisplayWithPairFiltersMixin', {
5
+ drawSingletons: true,
6
+ drawProperPairs: true,
7
+ flipStrandLongReadChains: true,
8
+ featureHeight: types.maybe(types.number),
9
+ })
10
+ .actions(self => ({
11
+ setDrawSingletons(f) {
12
+ self.drawSingletons = f;
13
+ },
14
+ setDrawProperPairs(f) {
15
+ self.drawProperPairs = f;
16
+ },
17
+ setFlipStrandLongReadChains(f) {
18
+ self.flipStrandLongReadChains = f;
19
+ },
20
+ setFeatureHeight(n) {
21
+ self.featureHeight = n;
22
+ },
23
+ }));
24
+ }
@@ -17,10 +17,11 @@ export function doAfterAttach(self, cb) {
17
17
  if (!self.chainData) {
18
18
  return;
19
19
  }
20
- ctx.clearRect(0, 0, canvas.width, self.height * 2);
20
+ const height = 'layoutHeight' in self ? self.layoutHeight || 1 : self.height;
21
21
  ctx.resetTransform();
22
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
22
23
  ctx.scale(2, 2);
23
- cb(self, ctx, canvas.width, self.height);
24
+ cb(self, ctx, canvas.width, height);
24
25
  self.setLastDrawnOffsetPx(view.offsetPx);
25
26
  self.setLastDrawnBpPerPx(view.bpPerPx);
26
27
  }
@@ -0,0 +1,3 @@
1
+ import { SimpleFeature } from '@jbrowse/core/util';
2
+ import type { ReducedFeature } from './fetchChains';
3
+ export declare function chainToSimpleFeature(chain: ReducedFeature[]): SimpleFeature;
@@ -0,0 +1,40 @@
1
+ import { SimpleFeature } from '@jbrowse/core/util';
2
+ export function chainToSimpleFeature(chain) {
3
+ if (chain.length === 0) {
4
+ throw new Error('Chain cannot be empty');
5
+ }
6
+ const firstFeat = chain[0];
7
+ return new SimpleFeature({
8
+ uniqueId: firstFeat.id,
9
+ id: firstFeat.id,
10
+ name: firstFeat.name,
11
+ refName: firstFeat.refName,
12
+ start: Math.min(...chain.map(f => f.start)),
13
+ end: Math.max(...chain.map(f => f.end)),
14
+ strand: firstFeat.strand,
15
+ flags: firstFeat.flags,
16
+ tlen: firstFeat.tlen,
17
+ pair_orientation: firstFeat.pair_orientation,
18
+ clipPos: firstFeat.clipPos,
19
+ ...(firstFeat.next_ref && { next_ref: firstFeat.next_ref }),
20
+ ...(firstFeat.next_pos !== undefined && { next_pos: firstFeat.next_pos }),
21
+ ...(firstFeat.SA && { SA: firstFeat.SA }),
22
+ subfeatures: chain.map((feat, idx) => ({
23
+ uniqueId: `${feat.id}_${idx}`,
24
+ id: `${feat.id}_${idx}`,
25
+ name: feat.name,
26
+ refName: feat.refName,
27
+ start: feat.start,
28
+ end: feat.end,
29
+ strand: feat.strand,
30
+ type: 'alignment_part',
31
+ flags: feat.flags,
32
+ tlen: feat.tlen,
33
+ pair_orientation: feat.pair_orientation,
34
+ clipPos: feat.clipPos,
35
+ ...(feat.next_ref && { next_ref: feat.next_ref }),
36
+ ...(feat.next_pos !== undefined && { next_pos: feat.next_pos }),
37
+ ...(feat.SA && { SA: feat.SA }),
38
+ })),
39
+ });
40
+ }
@@ -0,0 +1 @@
1
+ export declare function drawChevron(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, strand: number, color: string, chevronWidth: number, stroke?: string): void;
@@ -0,0 +1,24 @@
1
+ export function drawChevron(ctx, x, y, width, height, strand, color, chevronWidth, stroke) {
2
+ ctx.fillStyle = color;
3
+ ctx.beginPath();
4
+ if (strand === -1) {
5
+ ctx.moveTo(x - chevronWidth, y + height / 2);
6
+ ctx.lineTo(x, y + height);
7
+ ctx.lineTo(x + width, y + height);
8
+ ctx.lineTo(x + width, y);
9
+ ctx.lineTo(x, y);
10
+ }
11
+ else {
12
+ ctx.moveTo(x, y);
13
+ ctx.lineTo(x, y + height);
14
+ ctx.lineTo(x + width, y + height);
15
+ ctx.lineTo(x + width + chevronWidth, y + height / 2);
16
+ ctx.lineTo(x + width, y);
17
+ }
18
+ ctx.closePath();
19
+ ctx.fill();
20
+ if (stroke) {
21
+ ctx.strokeStyle = stroke;
22
+ ctx.stroke();
23
+ }
24
+ }