@jbrowse/plugin-alignments 2.16.0 → 2.17.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 (221) hide show
  1. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +2 -3
  2. package/dist/AlignmentsFeatureDetail/Flags.js +2 -2
  3. package/dist/AlignmentsFeatureDetail/LinkedPairedAlignments.js +2 -2
  4. package/dist/AlignmentsFeatureDetail/SupplementaryAlignments.js +2 -2
  5. package/dist/AlignmentsFeatureDetail/getSAFeatures.js +2 -2
  6. package/dist/AlignmentsFeatureDetail/stateModelFactory.d.ts +1 -1
  7. package/dist/BamAdapter/BamAdapter.d.ts +3 -2
  8. package/dist/BamAdapter/BamAdapter.js +34 -11
  9. package/dist/BamAdapter/BamSlightlyLazyFeature.d.ts +3 -17
  10. package/dist/BamAdapter/BamSlightlyLazyFeature.js +42 -72
  11. package/dist/CramAdapter/CramAdapter.d.ts +4 -3
  12. package/dist/CramAdapter/CramAdapter.js +24 -7
  13. package/dist/CramAdapter/CramSlightlyLazyFeature.d.ts +21 -27
  14. package/dist/CramAdapter/CramSlightlyLazyFeature.js +74 -73
  15. package/dist/CramAdapter/util.d.ts +1 -10
  16. package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +1 -1
  17. package/dist/LinearAlignmentsDisplay/index.js +2 -2
  18. package/dist/LinearAlignmentsDisplay/{models/model.d.ts → model.d.ts} +6 -3
  19. package/dist/LinearAlignmentsDisplay/{models/model.js → model.js} +11 -7
  20. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +6 -27
  21. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +43 -21
  22. package/dist/LinearPileupDisplay/components/ColorByTagDialog.d.ts +5 -4
  23. package/dist/LinearPileupDisplay/components/ColorByTagDialog.js +3 -1
  24. package/dist/LinearPileupDisplay/components/GroupByDialog.js +8 -6
  25. package/dist/LinearPileupDisplay/components/SortByTagDialog.js +6 -4
  26. package/dist/LinearPileupDisplay/model.d.ts +41 -45
  27. package/dist/LinearPileupDisplay/model.js +118 -41
  28. package/dist/LinearReadArcsDisplay/components/ReactComponent.js +1 -1
  29. package/dist/LinearReadArcsDisplay/model.d.ts +22 -21
  30. package/dist/LinearReadArcsDisplay/model.js +13 -14
  31. package/dist/LinearReadCloudDisplay/components/ReactComponent.js +1 -1
  32. package/dist/LinearReadCloudDisplay/model.d.ts +14 -22
  33. package/dist/LinearReadCloudDisplay/model.js +12 -13
  34. package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +49 -19
  35. package/dist/LinearSNPCoverageDisplay/index.js +3 -2
  36. package/dist/LinearSNPCoverageDisplay/{models/model.d.ts → model.d.ts} +3 -13
  37. package/dist/LinearSNPCoverageDisplay/{models/model.js → model.js} +71 -45
  38. package/dist/MismatchParser/cigarToMismatches.d.ts +3 -0
  39. package/dist/MismatchParser/cigarToMismatches.js +94 -0
  40. package/dist/MismatchParser/getNextRefPos.d.ts +4 -0
  41. package/dist/MismatchParser/getNextRefPos.js +40 -0
  42. package/dist/MismatchParser/index.d.ts +4 -29
  43. package/dist/MismatchParser/index.js +10 -321
  44. package/dist/MismatchParser/mdToMismatches.d.ts +3 -0
  45. package/dist/MismatchParser/mdToMismatches.js +80 -0
  46. package/dist/ModificationParser/index.d.ts +19 -0
  47. package/dist/ModificationParser/index.js +144 -0
  48. package/dist/PileupRPC/methods/GetGlobalValueForTag.js +1 -2
  49. package/dist/PileupRPC/methods/GetReducedFeatures.d.ts +1 -1
  50. package/dist/PileupRPC/methods/GetReducedFeatures.js +19 -16
  51. package/dist/PileupRPC/methods/GetVisibleModifications.d.ts +2 -1
  52. package/dist/PileupRPC/methods/GetVisibleModifications.js +9 -6
  53. package/dist/PileupRenderer/PileupLayoutSession.d.ts +8 -7
  54. package/dist/PileupRenderer/PileupRenderer.d.ts +6 -14
  55. package/dist/PileupRenderer/PileupRenderer.js +7 -5
  56. package/dist/PileupRenderer/renderAlignment.js +17 -4
  57. package/dist/PileupRenderer/renderAlignmentShape.js +102 -21
  58. package/dist/PileupRenderer/renderMethylation.d.ts +2 -1
  59. package/dist/PileupRenderer/renderMethylation.js +17 -9
  60. package/dist/PileupRenderer/renderMismatches.js +19 -19
  61. package/dist/PileupRenderer/renderModifications.d.ts +3 -2
  62. package/dist/PileupRenderer/renderModifications.js +31 -34
  63. package/dist/PileupRenderer/renderPerBaseLettering.d.ts +2 -1
  64. package/dist/PileupRenderer/renderPerBaseLettering.js +1 -3
  65. package/dist/PileupRenderer/renderPerBaseQuality.d.ts +2 -1
  66. package/dist/PileupRenderer/renderPerBaseQuality.js +1 -3
  67. package/dist/PileupRenderer/renderSoftClipping.js +6 -6
  68. package/dist/PileupRenderer/sortUtil.d.ts +2 -7
  69. package/dist/PileupRenderer/sortUtil.js +13 -13
  70. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js +10 -5
  71. package/dist/SNPCoverageAdapter/generateCoverageBins.d.ts +13 -9
  72. package/dist/SNPCoverageAdapter/generateCoverageBins.js +269 -166
  73. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +2 -1
  74. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +171 -54
  75. package/dist/shared/color.d.ts +0 -10
  76. package/dist/shared/color.js +1 -7
  77. package/{esm/shared → dist/shared/components}/BaseDisplayComponent.d.ts +2 -2
  78. package/{esm/shared → dist/shared/components}/FilterByTagDialog.d.ts +3 -3
  79. package/dist/shared/{FilterByTagDialog.js → components/FilterByTagDialog.js} +5 -1
  80. package/dist/shared/fetchChains.js +1 -2
  81. package/dist/shared/getMaximumModificationAtEachPosition.d.ts +8 -0
  82. package/dist/shared/getMaximumModificationAtEachPosition.js +42 -0
  83. package/dist/shared/getUniqueModifications.d.ts +14 -0
  84. package/dist/shared/getUniqueModifications.js +16 -0
  85. package/dist/shared/getUniqueTags.d.ts +15 -0
  86. package/dist/shared/getUniqueTags.js +18 -0
  87. package/dist/shared/types.d.ts +94 -0
  88. package/dist/shared/util.d.ts +8 -0
  89. package/dist/shared/util.js +26 -0
  90. package/dist/util.d.ts +7 -4
  91. package/dist/util.js +30 -30
  92. package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +2 -3
  93. package/esm/AlignmentsFeatureDetail/Flags.js +1 -1
  94. package/esm/AlignmentsFeatureDetail/LinkedPairedAlignments.js +1 -1
  95. package/esm/AlignmentsFeatureDetail/SupplementaryAlignments.js +1 -1
  96. package/esm/AlignmentsFeatureDetail/getSAFeatures.js +2 -2
  97. package/esm/AlignmentsFeatureDetail/stateModelFactory.d.ts +1 -1
  98. package/esm/BamAdapter/BamAdapter.d.ts +3 -2
  99. package/esm/BamAdapter/BamAdapter.js +31 -8
  100. package/esm/BamAdapter/BamSlightlyLazyFeature.d.ts +3 -17
  101. package/esm/BamAdapter/BamSlightlyLazyFeature.js +43 -73
  102. package/esm/CramAdapter/CramAdapter.d.ts +4 -3
  103. package/esm/CramAdapter/CramAdapter.js +22 -5
  104. package/esm/CramAdapter/CramSlightlyLazyFeature.d.ts +21 -27
  105. package/esm/CramAdapter/CramSlightlyLazyFeature.js +74 -73
  106. package/esm/CramAdapter/util.d.ts +1 -10
  107. package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +1 -1
  108. package/esm/LinearAlignmentsDisplay/index.js +2 -2
  109. package/esm/LinearAlignmentsDisplay/{models/model.d.ts → model.d.ts} +6 -3
  110. package/esm/LinearAlignmentsDisplay/{models/model.js → model.js} +11 -7
  111. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +6 -27
  112. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +45 -23
  113. package/esm/LinearPileupDisplay/components/ColorByTagDialog.d.ts +5 -4
  114. package/esm/LinearPileupDisplay/components/ColorByTagDialog.js +3 -1
  115. package/esm/LinearPileupDisplay/components/GroupByDialog.js +8 -6
  116. package/esm/LinearPileupDisplay/components/SortByTagDialog.js +6 -4
  117. package/esm/LinearPileupDisplay/model.d.ts +41 -45
  118. package/esm/LinearPileupDisplay/model.js +119 -42
  119. package/esm/LinearReadArcsDisplay/components/ReactComponent.js +1 -1
  120. package/esm/LinearReadArcsDisplay/model.d.ts +22 -21
  121. package/esm/LinearReadArcsDisplay/model.js +14 -15
  122. package/esm/LinearReadCloudDisplay/components/ReactComponent.js +1 -1
  123. package/esm/LinearReadCloudDisplay/model.d.ts +14 -22
  124. package/esm/LinearReadCloudDisplay/model.js +13 -14
  125. package/esm/LinearSNPCoverageDisplay/components/Tooltip.js +49 -19
  126. package/esm/LinearSNPCoverageDisplay/index.js +3 -2
  127. package/esm/LinearSNPCoverageDisplay/{models/model.d.ts → model.d.ts} +3 -13
  128. package/esm/LinearSNPCoverageDisplay/{models/model.js → model.js} +72 -46
  129. package/esm/MismatchParser/cigarToMismatches.d.ts +3 -0
  130. package/esm/MismatchParser/cigarToMismatches.js +91 -0
  131. package/esm/MismatchParser/getNextRefPos.d.ts +4 -0
  132. package/esm/MismatchParser/getNextRefPos.js +37 -0
  133. package/esm/MismatchParser/index.d.ts +4 -29
  134. package/esm/MismatchParser/index.js +5 -311
  135. package/esm/MismatchParser/mdToMismatches.d.ts +3 -0
  136. package/esm/MismatchParser/mdToMismatches.js +77 -0
  137. package/esm/ModificationParser/index.d.ts +19 -0
  138. package/esm/ModificationParser/index.js +138 -0
  139. package/esm/PileupRPC/methods/GetGlobalValueForTag.js +1 -2
  140. package/esm/PileupRPC/methods/GetReducedFeatures.d.ts +1 -1
  141. package/esm/PileupRPC/methods/GetReducedFeatures.js +19 -16
  142. package/esm/PileupRPC/methods/GetVisibleModifications.d.ts +2 -1
  143. package/esm/PileupRPC/methods/GetVisibleModifications.js +9 -6
  144. package/esm/PileupRenderer/PileupLayoutSession.d.ts +8 -7
  145. package/esm/PileupRenderer/PileupRenderer.d.ts +6 -14
  146. package/esm/PileupRenderer/PileupRenderer.js +8 -6
  147. package/esm/PileupRenderer/renderAlignment.js +17 -4
  148. package/esm/PileupRenderer/renderAlignmentShape.js +102 -21
  149. package/esm/PileupRenderer/renderMethylation.d.ts +2 -1
  150. package/esm/PileupRenderer/renderMethylation.js +17 -9
  151. package/esm/PileupRenderer/renderMismatches.js +19 -19
  152. package/esm/PileupRenderer/renderModifications.d.ts +3 -2
  153. package/esm/PileupRenderer/renderModifications.js +30 -33
  154. package/esm/PileupRenderer/renderPerBaseLettering.d.ts +2 -1
  155. package/esm/PileupRenderer/renderPerBaseLettering.js +1 -3
  156. package/esm/PileupRenderer/renderPerBaseQuality.d.ts +2 -1
  157. package/esm/PileupRenderer/renderPerBaseQuality.js +1 -3
  158. package/esm/PileupRenderer/renderSoftClipping.js +6 -6
  159. package/esm/PileupRenderer/sortUtil.d.ts +2 -7
  160. package/esm/PileupRenderer/sortUtil.js +13 -13
  161. package/esm/SNPCoverageAdapter/SNPCoverageAdapter.js +10 -5
  162. package/esm/SNPCoverageAdapter/generateCoverageBins.d.ts +13 -9
  163. package/esm/SNPCoverageAdapter/generateCoverageBins.js +269 -166
  164. package/esm/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +2 -1
  165. package/esm/SNPCoverageRenderer/SNPCoverageRenderer.js +171 -54
  166. package/esm/shared/color.d.ts +0 -10
  167. package/esm/shared/color.js +0 -6
  168. package/{dist/shared → esm/shared/components}/BaseDisplayComponent.d.ts +2 -2
  169. package/{dist/shared → esm/shared/components}/FilterByTagDialog.d.ts +3 -3
  170. package/esm/shared/{FilterByTagDialog.js → components/FilterByTagDialog.js} +5 -1
  171. package/esm/shared/fetchChains.js +1 -2
  172. package/esm/shared/getMaximumModificationAtEachPosition.d.ts +8 -0
  173. package/esm/shared/getMaximumModificationAtEachPosition.js +39 -0
  174. package/esm/shared/getUniqueModifications.d.ts +14 -0
  175. package/esm/shared/getUniqueModifications.js +13 -0
  176. package/esm/shared/getUniqueTags.d.ts +15 -0
  177. package/esm/shared/getUniqueTags.js +15 -0
  178. package/esm/shared/types.d.ts +94 -0
  179. package/esm/shared/util.d.ts +8 -0
  180. package/esm/shared/util.js +23 -0
  181. package/esm/util.d.ts +7 -4
  182. package/esm/util.js +28 -27
  183. package/package.json +4 -4
  184. package/dist/LinearPileupDisplay/components/ColorByModificationsDialog.d.ts +0 -15
  185. package/dist/LinearPileupDisplay/components/ColorByModificationsDialog.js +0 -41
  186. package/dist/LinearPileupDisplay/components/ModificationsTable.d.ts +0 -4
  187. package/dist/LinearPileupDisplay/components/ModificationsTable.js +0 -28
  188. package/dist/SNPCoverageAdapter/util.d.ts +0 -25
  189. package/dist/shared/index.d.ts +0 -49
  190. package/dist/shared/index.js +0 -41
  191. package/esm/LinearPileupDisplay/components/ColorByModificationsDialog.d.ts +0 -15
  192. package/esm/LinearPileupDisplay/components/ColorByModificationsDialog.js +0 -36
  193. package/esm/LinearPileupDisplay/components/ModificationsTable.d.ts +0 -4
  194. package/esm/LinearPileupDisplay/components/ModificationsTable.js +0 -22
  195. package/esm/SNPCoverageAdapter/util.d.ts +0 -25
  196. package/esm/shared/index.d.ts +0 -49
  197. package/esm/shared/index.js +0 -36
  198. /package/dist/LinearAlignmentsDisplay/{models/alignmentsModel.d.ts → alignmentsModel.d.ts} +0 -0
  199. /package/dist/LinearAlignmentsDisplay/{models/alignmentsModel.js → alignmentsModel.js} +0 -0
  200. /package/dist/LinearAlignmentsDisplay/{models/configSchema.d.ts → configSchema.d.ts} +0 -0
  201. /package/dist/LinearAlignmentsDisplay/{models/configSchema.js → configSchema.js} +0 -0
  202. /package/dist/LinearAlignmentsDisplay/{models/util.d.ts → util.d.ts} +0 -0
  203. /package/dist/LinearAlignmentsDisplay/{models/util.js → util.js} +0 -0
  204. /package/dist/LinearSNPCoverageDisplay/{models/configSchema.d.ts → configSchema.d.ts} +0 -0
  205. /package/dist/LinearSNPCoverageDisplay/{models/configSchema.js → configSchema.js} +0 -0
  206. /package/dist/shared/{BaseDisplayComponent.js → components/BaseDisplayComponent.js} +0 -0
  207. /package/dist/shared/{renderSvg.d.ts → renderSvgUtil.d.ts} +0 -0
  208. /package/dist/shared/{renderSvg.js → renderSvgUtil.js} +0 -0
  209. /package/dist/{SNPCoverageAdapter/util.js → shared/types.js} +0 -0
  210. /package/esm/LinearAlignmentsDisplay/{models/alignmentsModel.d.ts → alignmentsModel.d.ts} +0 -0
  211. /package/esm/LinearAlignmentsDisplay/{models/alignmentsModel.js → alignmentsModel.js} +0 -0
  212. /package/esm/LinearAlignmentsDisplay/{models/configSchema.d.ts → configSchema.d.ts} +0 -0
  213. /package/esm/LinearAlignmentsDisplay/{models/configSchema.js → configSchema.js} +0 -0
  214. /package/esm/LinearAlignmentsDisplay/{models/util.d.ts → util.d.ts} +0 -0
  215. /package/esm/LinearAlignmentsDisplay/{models/util.js → util.js} +0 -0
  216. /package/esm/LinearSNPCoverageDisplay/{models/configSchema.d.ts → configSchema.d.ts} +0 -0
  217. /package/esm/LinearSNPCoverageDisplay/{models/configSchema.js → configSchema.js} +0 -0
  218. /package/esm/shared/{BaseDisplayComponent.js → components/BaseDisplayComponent.js} +0 -0
  219. /package/esm/shared/{renderSvg.d.ts → renderSvgUtil.d.ts} +0 -0
  220. /package/esm/shared/{renderSvg.js → renderSvgUtil.js} +0 -0
  221. /package/esm/{SNPCoverageAdapter/util.js → shared/types.js} +0 -0
@@ -1,6 +1,8 @@
1
- import { getTag, getTagAlt, shouldFetchReferenceSequence } from '../util';
2
- import { parseCigar, getNextRefPos, getModificationPositions, getMethBins, } from '../MismatchParser';
3
- import { doesIntersect2 } from '@jbrowse/core/util';
1
+ import { doesIntersect2, max, sum } from '@jbrowse/core/util';
2
+ // locals
3
+ import { parseCigar } from '../MismatchParser';
4
+ import { getMethBins } from '../ModificationParser';
5
+ import { getMaxProbModAtEachPosition } from '../shared/getMaximumModificationAtEachPosition';
4
6
  function mismatchLen(mismatch) {
5
7
  return !isInterbase(mismatch.type) ? mismatch.length : 1;
6
8
  }
@@ -11,192 +13,293 @@ function inc(bin, strand, type, field) {
11
13
  let thisBin = bin[type][field];
12
14
  if (thisBin === undefined) {
13
15
  thisBin = bin[type][field] = {
14
- total: 0,
16
+ entryDepth: 0,
17
+ probabilities: [],
15
18
  '-1': 0,
16
19
  '0': 0,
17
20
  '1': 0,
18
21
  };
19
22
  }
20
- thisBin.total++;
23
+ thisBin.entryDepth++;
21
24
  thisBin[strand]++;
22
25
  }
23
- export default async function generateCoverageBins(features, region, opts, fetchSequence) {
24
- var _a, _b, _c;
25
- const { colorBy } = opts;
26
- const extendedRegion = {
27
- ...region,
28
- start: Math.max(0, region.start - 1),
29
- end: region.end + 1,
30
- };
31
- const binMax = Math.ceil(extendedRegion.end - extendedRegion.start);
32
- const skipmap = {};
33
- const regionSequence = features.length && shouldFetchReferenceSequence((_a = opts.colorBy) === null || _a === void 0 ? void 0 : _a.type)
34
- ? await fetchSequence(region)
35
- : undefined;
36
- const bins = [];
37
- for (const feature of features) {
38
- const fstart = feature.get('start');
39
- const fend = feature.get('end');
40
- const fstrand = feature.get('strand');
41
- const mismatches = feature.get('mismatches') || [];
42
- for (let j = fstart; j < fend + 1; j++) {
43
- const i = j - region.start;
44
- if (i >= 0 && i < binMax) {
45
- if (bins[i] === undefined) {
46
- bins[i] = {
47
- total: 0,
48
- all: 0,
49
- ref: 0,
26
+ function processDepth({ feature, bins, region, regionSequence, }) {
27
+ const fstart = feature.get('start');
28
+ const fend = feature.get('end');
29
+ const fstrand = feature.get('strand');
30
+ const regionLength = region.end - region.start;
31
+ for (let j = fstart; j < fend + 1; j++) {
32
+ const i = j - region.start;
33
+ if (i >= 0 && i < regionLength) {
34
+ if (bins[i] === undefined) {
35
+ bins[i] = {
36
+ depth: 0,
37
+ readsCounted: 0,
38
+ refbase: regionSequence[i],
39
+ ref: {
40
+ probabilities: [],
41
+ entryDepth: 0,
50
42
  '-1': 0,
51
- '0': 0,
52
- '1': 0,
53
- lowqual: {},
54
- cov: {},
55
- delskips: {},
56
- noncov: {},
57
- };
58
- }
59
- if (j !== fend) {
60
- bins[i].total++;
61
- bins[i].all++;
62
- bins[i].ref++;
63
- bins[i][fstrand]++;
64
- }
43
+ 0: 0,
44
+ 1: 0,
45
+ },
46
+ snps: {},
47
+ mods: {},
48
+ nonmods: {},
49
+ delskips: {},
50
+ noncov: {},
51
+ };
52
+ }
53
+ if (j !== fend) {
54
+ bins[i].depth++;
55
+ bins[i].readsCounted++;
56
+ bins[i].ref.entryDepth++;
57
+ bins[i].ref[fstrand]++;
65
58
  }
66
59
  }
67
- if ((colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'modifications') {
68
- const seq = feature.get('seq');
69
- const mm = getTagAlt(feature, 'MM', 'Mm') || '';
70
- const ops = parseCigar(feature.get('CIGAR'));
71
- const fend = feature.get('end');
72
- if (seq) {
73
- const modifications = getModificationPositions(mm, seq, fstrand);
74
- for (const { type, positions } of modifications) {
75
- const mod = `mod_${type}`;
76
- for (const pos of getNextRefPos(ops, positions)) {
77
- const epos = pos + fstart - region.start;
78
- if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
79
- if (bins[epos] === undefined) {
80
- bins[epos] = {
81
- total: 0,
82
- all: 0,
83
- ref: 0,
84
- '-1': 0,
85
- '0': 0,
86
- '1': 0,
87
- lowqual: {},
88
- cov: {},
89
- delskips: {},
90
- noncov: {},
91
- };
92
- }
93
- const bin = bins[epos];
94
- inc(bin, fstrand, 'cov', mod);
95
- }
96
- }
60
+ }
61
+ }
62
+ function processSNPs({ feature, region, bins, skipmap, }) {
63
+ var _a;
64
+ const fstart = feature.get('start');
65
+ const fstrand = feature.get('strand');
66
+ const mismatches = (_a = feature.get('mismatches')) !== null && _a !== void 0 ? _a : [];
67
+ // normal SNP based coloring
68
+ for (const mismatch of mismatches) {
69
+ const mstart = fstart + mismatch.start;
70
+ const mlen = mismatchLen(mismatch);
71
+ const mend = mstart + mlen;
72
+ for (let j = mstart; j < mstart + mlen; j++) {
73
+ const epos = j - region.start;
74
+ if (epos >= 0 && epos < bins.length) {
75
+ const bin = bins[epos];
76
+ const { base, type } = mismatch;
77
+ const interbase = isInterbase(type);
78
+ if (type === 'deletion' || type === 'skip') {
79
+ inc(bin, fstrand, 'delskips', type);
80
+ bin.depth--;
81
+ }
82
+ else if (!interbase) {
83
+ inc(bin, fstrand, 'snps', base);
84
+ bin.ref.entryDepth--;
85
+ bin.ref[fstrand]--;
86
+ }
87
+ else {
88
+ inc(bin, fstrand, 'noncov', type);
97
89
  }
98
90
  }
99
91
  }
100
- if ((colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'methylation') {
101
- if (!regionSequence) {
102
- throw new Error('no region sequence detected, need sequenceAdapter configuration');
92
+ if (mismatch.type === 'skip') {
93
+ // for upper case XS and TS: reports the literal strand of the genomic
94
+ // transcript
95
+ const tags = feature.get('tags');
96
+ const xs = (tags === null || tags === void 0 ? void 0 : tags.XS) || (tags === null || tags === void 0 ? void 0 : tags.TS);
97
+ // for lower case ts from minimap2: genomic transcript flipped by read
98
+ // strand
99
+ const ts = tags === null || tags === void 0 ? void 0 : tags.ts;
100
+ const effectiveStrand = xs === '+'
101
+ ? 1
102
+ : xs === '-'
103
+ ? -1
104
+ : (ts === '+' ? 1 : xs === '-' ? -1 : 0) * fstrand;
105
+ const hash = `${mstart}_${mend}_${effectiveStrand}`;
106
+ if (skipmap[hash] === undefined) {
107
+ skipmap[hash] = {
108
+ feature: feature,
109
+ start: mstart,
110
+ end: mend,
111
+ strand: fstrand,
112
+ effectiveStrand,
113
+ score: 0,
114
+ };
103
115
  }
104
- const seq = feature.get('seq');
105
- if (!seq) {
106
- continue;
107
- }
108
- const { methBins, methProbs } = getMethBins(feature);
109
- const dels = mismatches.filter(f => f.type === 'deletion');
110
- // methylation based coloring takes into account both reference sequence
111
- // CpG detection and reads
112
- for (let i = 0; i < fend - fstart; i++) {
113
- const j = i + fstart;
114
- const l1 = (_b = regionSequence[j - region.start + 1]) === null || _b === void 0 ? void 0 : _b.toLowerCase();
115
- const l2 = (_c = regionSequence[j - region.start + 2]) === null || _c === void 0 ? void 0 : _c.toLowerCase();
116
- if (l1 === 'c' && l2 === 'g') {
117
- const bin0 = bins[j - region.start];
118
- const bin1 = bins[j - region.start + 1];
119
- const b0 = methBins[i];
120
- const b1 = methBins[i + 1];
121
- const p0 = methProbs[i];
122
- const p1 = methProbs[i + 1];
123
- // color
124
- if ((b0 && (p0 !== undefined ? p0 > 0.5 : true)) ||
125
- (b1 && (p1 !== undefined ? p1 > 0.5 : true))) {
126
- if (bin0) {
127
- inc(bin0, fstrand, 'cov', 'meth');
128
- bin0.ref--;
129
- bin0[fstrand]--;
130
- }
131
- if (bin1) {
132
- inc(bin1, fstrand, 'cov', 'meth');
133
- bin1.ref--;
134
- bin1[fstrand]--;
135
- }
116
+ skipmap[hash].score++;
117
+ }
118
+ }
119
+ }
120
+ function processReferenceCpGs({ feature, region, bins, regionSequence, }) {
121
+ var _a;
122
+ const fstart = feature.get('start');
123
+ const fend = feature.get('end');
124
+ const fstrand = feature.get('strand');
125
+ const seq = feature.get('seq');
126
+ const mismatches = (_a = feature.get('mismatches')) !== null && _a !== void 0 ? _a : [];
127
+ const r = regionSequence.toLowerCase();
128
+ if (seq) {
129
+ const cigarOps = parseCigar(feature.get('CIGAR'));
130
+ const { methBins, methProbs } = getMethBins(feature, cigarOps);
131
+ const dels = mismatches.filter(f => f.type === 'deletion');
132
+ // methylation based coloring takes into account both reference sequence
133
+ // CpG detection and reads
134
+ for (let i = 0; i < fend - fstart; i++) {
135
+ const j = i + fstart;
136
+ const l1 = r[j - region.start + 1];
137
+ const l2 = r[j - region.start + 2];
138
+ if (l1 === 'c' && l2 === 'g') {
139
+ const bin0 = bins[j - region.start];
140
+ const bin1 = bins[j - region.start + 1];
141
+ const b0 = methBins[i];
142
+ const b1 = methBins[i + 1];
143
+ const p0 = methProbs[i];
144
+ const p1 = methProbs[i + 1];
145
+ // color
146
+ if ((b0 && (p0 !== undefined ? p0 > 0.5 : true)) ||
147
+ (b1 && (p1 !== undefined ? p1 > 0.5 : true))) {
148
+ if (bin0) {
149
+ incWithProbabilities(bin0, fstrand, 'mods', 'cpg_meth', p0 || 0);
150
+ bin0.ref.entryDepth--;
151
+ bin0.ref[fstrand]--;
136
152
  }
137
- else {
138
- if (bin0) {
139
- if (!dels.some(d => doesIntersect2(j, j + 1, d.start + fstart, d.start + fstart + d.length))) {
140
- inc(bin0, fstrand, 'cov', 'unmeth');
141
- bin0.ref--;
142
- bin0[fstrand]--;
143
- }
153
+ if (bin1) {
154
+ incWithProbabilities(bin1, fstrand, 'mods', 'cpg_meth', p1 || 0);
155
+ bin1.ref.entryDepth--;
156
+ bin1.ref[fstrand]--;
157
+ }
158
+ }
159
+ else {
160
+ if (bin0) {
161
+ if (!dels.some(d => doesIntersect2(j, j + 1, d.start + fstart, d.start + fstart + d.length))) {
162
+ incWithProbabilities(bin0, fstrand, 'nonmods', 'cpg_unmeth', 1 - (p0 || 0));
163
+ bin0.ref.entryDepth--;
164
+ bin0.ref[fstrand]--;
144
165
  }
145
- if (bin1) {
146
- if (!dels.some(d => doesIntersect2(j + 1, j + 2, d.start + fstart, d.start + fstart + d.length))) {
147
- inc(bin1, fstrand, 'cov', 'unmeth');
148
- bin1.ref--;
149
- bin1[fstrand]--;
150
- }
166
+ }
167
+ if (bin1) {
168
+ if (!dels.some(d => doesIntersect2(j + 1, j + 2, d.start + fstart, d.start + fstart + d.length))) {
169
+ incWithProbabilities(bin1, fstrand, 'nonmods', 'cpg_unmeth', 1 - (p1 || 0));
170
+ bin1.ref.entryDepth--;
171
+ bin1.ref[fstrand]--;
151
172
  }
152
173
  }
153
174
  }
154
175
  }
155
176
  }
156
- // normal SNP based coloring
157
- const colorSNPs = (colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) !== 'modifications' && (colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) !== 'methylation';
158
- for (const mismatch of mismatches) {
159
- const mstart = fstart + mismatch.start;
160
- const mlen = mismatchLen(mismatch);
161
- const mend = mstart + mlen;
162
- for (let j = mstart; j < mstart + mlen; j++) {
163
- const epos = j - region.start;
164
- if (epos >= 0 && epos < bins.length) {
165
- const bin = bins[epos];
166
- const { base, type } = mismatch;
167
- const interbase = isInterbase(type);
168
- if (!interbase) {
169
- bin.ref--;
170
- bin[fstrand]--;
171
- }
172
- else {
173
- inc(bin, fstrand, 'noncov', type);
174
- }
175
- if (type === 'deletion' || type === 'skip') {
176
- inc(bin, fstrand, 'delskips', type);
177
- bin.total--;
178
- }
179
- else if (!interbase && colorSNPs) {
180
- inc(bin, fstrand, 'cov', base);
181
- bin.refbase = mismatch.altbase;
182
- }
183
- }
177
+ }
178
+ }
179
+ function processModification({ feature, colorBy, region, bins, regionSequence, }) {
180
+ var _a, _b, _c;
181
+ const fstart = feature.get('start');
182
+ const fstrand = feature.get('strand');
183
+ const fend = feature.get('end');
184
+ const twoColor = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.twoColor;
185
+ const isolatedModification = (_b = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _b === void 0 ? void 0 : _b.isolatedModification;
186
+ (_c = getMaxProbModAtEachPosition(feature)) === null || _c === void 0 ? void 0 : _c.forEach(({ type, prob, allProbs }, pos) => {
187
+ if (isolatedModification && type !== isolatedModification) {
188
+ return;
189
+ }
190
+ const epos = pos + fstart - region.start;
191
+ if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
192
+ if (bins[epos] === undefined) {
193
+ bins[epos] = {
194
+ depth: 0,
195
+ readsCounted: 0,
196
+ refbase: regionSequence[epos],
197
+ snps: {},
198
+ ref: {
199
+ probabilities: [],
200
+ entryDepth: 0,
201
+ '-1': 0,
202
+ 0: 0,
203
+ 1: 0,
204
+ },
205
+ mods: {},
206
+ nonmods: {},
207
+ delskips: {},
208
+ noncov: {},
209
+ };
184
210
  }
185
- if (mismatch.type === 'skip') {
186
- const hash = `${mstart}_${mend}_${fstrand}`;
187
- if (skipmap[hash] === undefined) {
188
- skipmap[hash] = {
189
- feature: feature,
190
- start: mstart,
191
- end: mend,
192
- strand: fstrand,
193
- xs: getTag(feature, 'XS') || getTag(feature, 'TS'),
194
- score: 0,
195
- };
196
- }
197
- skipmap[hash].score++;
211
+ const s = 1 - sum(allProbs);
212
+ const bin = bins[epos];
213
+ if (twoColor && s > max(allProbs)) {
214
+ incWithProbabilities(bin, fstrand, 'nonmods', `nonmod_${type}`, s);
215
+ }
216
+ else {
217
+ incWithProbabilities(bin, fstrand, 'mods', `mod_${type}`, prob);
198
218
  }
199
219
  }
220
+ });
221
+ }
222
+ function incWithProbabilities(bin, strand, type, field, probability) {
223
+ let thisBin = bin[type][field];
224
+ if (thisBin === undefined) {
225
+ thisBin = bin[type][field] = {
226
+ entryDepth: 0,
227
+ probabilities: [],
228
+ '-1': 0,
229
+ '0': 0,
230
+ '1': 0,
231
+ };
200
232
  }
201
- return { bins, skipmap };
233
+ thisBin.entryDepth++;
234
+ thisBin.probabilities.push(probability);
235
+ thisBin[strand]++;
236
+ }
237
+ export async function generateCoverageBins({ fetchSequence, features, region, opts, }) {
238
+ const { colorBy } = opts;
239
+ const skipmap = {};
240
+ const bins = [];
241
+ const start2 = Math.max(0, region.start - 1);
242
+ const diff = region.start - start2;
243
+ const regionSequence = (await fetchSequence({
244
+ ...region,
245
+ start: start2,
246
+ end: region.end + 1,
247
+ })) || '';
248
+ for (const feature of features) {
249
+ processDepth({
250
+ feature,
251
+ bins,
252
+ region,
253
+ regionSequence: regionSequence.slice(diff),
254
+ });
255
+ if ((colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'modifications') {
256
+ processModification({
257
+ feature,
258
+ colorBy,
259
+ bins,
260
+ region,
261
+ regionSequence: regionSequence.slice(diff),
262
+ });
263
+ }
264
+ else if ((colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'methylation') {
265
+ processReferenceCpGs({
266
+ feature,
267
+ bins,
268
+ region,
269
+ regionSequence,
270
+ });
271
+ }
272
+ processSNPs({ feature, skipmap, bins, region });
273
+ }
274
+ for (const bin of bins) {
275
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
276
+ if (bin) {
277
+ bin.mods = Object.fromEntries(Object.entries(bin.mods).map(([key, val]) => {
278
+ return [
279
+ key,
280
+ {
281
+ ...val,
282
+ avgProbability: val.probabilities.length
283
+ ? sum(val.probabilities) / val.probabilities.length
284
+ : undefined,
285
+ },
286
+ ];
287
+ }));
288
+ bin.nonmods = Object.fromEntries(Object.entries(bin.nonmods).map(([key, val]) => {
289
+ return [
290
+ key,
291
+ {
292
+ ...val,
293
+ avgProbability: val.probabilities.length
294
+ ? sum(val.probabilities) / val.probabilities.length
295
+ : undefined,
296
+ },
297
+ ];
298
+ }));
299
+ }
300
+ }
301
+ return {
302
+ bins,
303
+ skipmap,
304
+ };
202
305
  }
@@ -1,6 +1,7 @@
1
1
  import { Feature } from '@jbrowse/core/util';
2
2
  import { RenderArgsDeserialized as FeatureRenderArgsDeserialized } from '@jbrowse/core/pluggableElementTypes/renderers/FeatureRendererType';
3
3
  import { ScaleOpts, WiggleBaseRenderer } from '@jbrowse/plugin-wiggle';
4
+ import { ModificationTypeWithColor } from '../shared/types';
4
5
  export interface RenderArgsDeserialized extends FeatureRenderArgsDeserialized {
5
6
  bpPerPx: number;
6
7
  height: number;
@@ -13,7 +14,7 @@ export interface RenderArgsDeserializedWithFeatures extends RenderArgsDeserializ
13
14
  values: number[];
14
15
  };
15
16
  displayCrossHatches: boolean;
16
- modificationTagMap?: Record<string, string>;
17
+ visibleModifications?: Record<string, ModificationTypeWithColor>;
17
18
  }
18
19
  export default class SNPCoverageRenderer extends WiggleBaseRenderer {
19
20
  draw(ctx: CanvasRenderingContext2D, props: RenderArgsDeserializedWithFeatures): Promise<undefined>;